Skip to content

Commit 6c75f59

Browse files
committed
Improved README
1 parent 15c73df commit 6c75f59

File tree

1 file changed

+45
-12
lines changed

1 file changed

+45
-12
lines changed

README.md

+45-12
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
11
# SqlStrings
22

3-
This package provides the `@sql_cmd` macro to allow SQL query strings to be
4-
constructed by normal-looking string interpolation but without danger of SQL
5-
injection attacks.
3+
SqlStrings.jl provides the `@sql_cmd` macro to allow SQL query strings to be
4+
constructed by normal-looking string interpolation but without risking SQL
5+
formatting errors or SQL injection attacks on your application. For example,
6+
the code
7+
8+
```julia
9+
query = "INSERT INTO Students VALUES ('$name', $age, '$class')"
10+
runquery(connection, query);
11+
```
12+
13+
is vulerable to the canonical SQL injection attack:
614

715
[![Little Bobby Tables](https://imgs.xkcd.com/comics/exploits_of_a_mom.png)](https://xkcd.com/327)
816

9-
`@sql_cmd` is quite simple — it understands only the basic rules of SQL
10-
quoting and Julia string interpolation, but does no other parsing of the source
11-
text. In this sense it is quite similar to `Base.Cmd` - it keeps any literal
12-
SQL text you write as-is and captures the Julia-level string interpolations
13-
in a safe way.
17+
Here's how to make this safe using SqlStrings.jl:
18+
19+
```julia
20+
query = sql`INSERT INTO Students VALUES ($name, $age, $class)`
21+
runquery(connection, query);
22+
```
23+
24+
In addition to making the above code safe, it allows the Julia types of
25+
interpolated parameters to be preserved and passed to the database driver
26+
library which can then marshal them correctly into types it understands. This
27+
provides more control than using string interpolation which is for human
28+
readability rather than data transfer.
1429

15-
## Simple usage
30+
# Simple usage
1631

1732
To use with a given database backend, you'll need a small amount of integration
1833
code. In the examples below we'll use with LibPQ.jl and a `runquery()` function
1934
(hopefully integration will be automatic in future).
2035

2136
```julia
37+
using SqlStrings
2238
import LibPQ
2339

2440
runquery(conn, sql::SqlStrings.Sql)
@@ -52,7 +68,9 @@ julia> runquery(conn, sql`SELECT * FROM foo`) |> DataFrame
5268
2 │ foo@example.com 2
5369
```
5470

55-
## Howto: Inserting values from a Julia array into a row
71+
# Howtos
72+
73+
## Inserting values from a Julia collection into a row
5674

5775
In some circumstances it can be useful to use splatting syntax to interpolate a
5876
Julia collection into a comma-separated list of values. Generally simple scalar
@@ -64,7 +82,7 @@ email_and_id = ("bar@example.com", 3)
6482
runquery(conn, sql`INSERT INTO foo VALUES ($(email_and_id...))`)
6583
```
6684

67-
## Howto: Using the `in` operator with a Julia collection
85+
## Using the `in` operator with a Julia collection
6886

6987
There's two ways to do this. First, using `in` and splatting syntax
7088

@@ -92,7 +110,7 @@ julia> ids = [1,2]
92110
2 │ foo@example.com 2
93111
```
94112

95-
## Howto: Building up a query from fragments
113+
## Building up a query from fragments
96114

97115
On occasion you might want to dynamically build up a complicated query from
98116
fragments of SQL source text. To do this, the result of `@sql_cmd` can be
@@ -118,3 +136,18 @@ A word of warning that constructing SQL logic with Julia-level logic can make
118136
the code quite hard to understand. It can be worth considering writing one
119137
larger SQL query which does more of the logic on the SQL side.
120138

139+
# Design
140+
141+
`SqlStrings` is a minimal approach to integrating SQL with Julia code in a safe
142+
way — it understands only the basic rules of SQL quoting and Julia string
143+
interpolation, but does no other parsing of the source text. This allows tight
144+
integration with your database of choice by being unopinionated about its
145+
source language and any SQL language extensions it may have.
146+
147+
I've chosen backticks for `@sql_cmd` rather than a normal string macro because
148+
* It's important to have syntax highlighting, and it seems editors disable
149+
syntax highlighting of interpolations within normal string macros.
150+
* `@sql_cmd` is very conceptually similar to the builtin backticks and
151+
`Base.Cmd`: it's a lightweight layer which deals only with preserving the
152+
structure of tokens in the source text.
153+

0 commit comments

Comments
 (0)