Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update DB Readme #602

Merged
merged 2 commits into from
May 26, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions docs/database/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,15 @@ To execute sql statements you can use `Database#exec`
db.exec "create table contacts (name varchar(30), age int)"
```

To avoid [SQL injection](https://owasp.org/www-community/attacks/SQL_Injection) values can be provided as query parameters.
The syntax for using query parameters depends on the database driver because they are typically just passed through to the database. MySQL uses `?` for parameter expansion and assignment is based on argument order. PostgreSQL uses `$n` where `n` is the ordinal number of the argument (starting with 1).

```crystal
# MySQL
db.exec "insert into contacts values (?, ?)", "John", 30
# Postgres
db.exec "insert into contacts values ($1, $2)", "Sarah", 33
db.exec "insert into contacts (name, age) values ('abc', 30)"
```

Values can be provided as query parameters, see below.

## Query

To perform a query and get the result set use `Database#query`, arguments can be used as in `Database#exec`.
To perform a query and get the result set use `Database#query`.

`Database#query` returns a `ResultSet` that needs to be closed. As in `Database#open`, if called with a block, the `ResultSet` will be closed implicitly.

Expand All @@ -91,6 +87,28 @@ db.query "select name, age from contacts order by age desc" do |rs|
end
```

Values can be provided as query parameters, see below.

## Query Parameters

To avoid [SQL injection](https://owasp.org/www-community/attacks/SQL_Injection) values can be provided as query parameters.
The syntax for using query parameters depends on the database driver because they are typically just passed through to the database. MySQL uses `?` for parameter expansion and assignment is based on argument order. PostgreSQL uses `$n` where `n` is the ordinal number of the argument (starting with 1).

```crystal
# MySQL
db.exec "insert into contacts values (?, ?)", "John", 30
# Postgres
db.exec "insert into contacts values ($1, $2)", "Sarah", 33
# Queries:
db.query("select name from contacts where age = ?", 33) do |rs|
rs.each do
# ... perform for each row in the ResultSet
end
end
```

## Reading Query Results

When reading values from the database there is no type information during compile time that crystal can use. You will need to call `rs.read(T)` with the type `T` you expect to get from the database.

```crystal
Expand All @@ -105,7 +123,7 @@ db.query "select name, age from contacts order by age desc" do |rs|
end
```

There are many convenient query methods built on top of `#query`.
There are many convenient query methods built on top of `#query` to make this easier.

You can read multiple columns at once:

Expand All @@ -125,4 +143,5 @@ Or read a scalar value without dealing explicitly with the ResultSet:
max_age = db.scalar "select max(age) from contacts"
```

There are many other helper methods to query with types, query column names with types, etc.
All available methods to perform statements in a database are defined in `DB::QueryMethods`.