You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+176Lines changed: 176 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -73,3 +73,179 @@ A Julia interface to the SQLite library and support for operations on DataFrames
73
73
*`drop(db::SQLiteDB,table::String)`
74
74
75
75
`drop` is pretty self-explanatory. It's really just a convenience wrapper around `query` to execute a DROP TABLE command, while also calling "VACUUM" to clean out freed memory from the database.
Register a function `func` (which takes `nargs` number of arguments) with the SQLite database connection `db`. If the keyword argument `name` is given the function is registered with that name, otherwise it is registered with the name of `func`. If the function is stochastic (e.g. uses a random number) `isdeterm` should be set to `false`, see SQLite's [function creation documentation](http://sqlite.org/c3ref/create_function.html) for more information.
80
+
81
+
*`@scalarfunc function`
82
+
`@scalarfunc name function`
83
+
84
+
Define a function which can then be passed to `registerfunc`. In the first usage the function name is infered from the function definition, in the second it is explicitly given as the first parameter. The second form is only recommended when it's use is absolutely necessary, see below.
85
+
86
+
*`sr"..."`
87
+
88
+
This string literal is used to escape all special characters in the string, useful for using regex in a query.
89
+
90
+
*`sqlreturn(contex, val)`
91
+
92
+
This function should never be called explicitly. Instead it is exported so that it can be overloaded when necessary, see below.
93
+
94
+
#### User Defined Functions
95
+
96
+
##### SQLite Regular Expressions
97
+
98
+
SQLite provides syntax for calling the [`regexp` function](http://sqlite.org/lang_expr.html#regexp) from inside `WHERE` clauses. Unfortunately, however, SQLite does not provide a default implementation of the `regexp` function so SQLite.jl creates one automatically when you open a database. The function can be called in the following ways (examples using the [Chinook Database](http://chinookdatabase.codeplex.com/))
99
+
100
+
```julia
101
+
julia>using SQLite
102
+
103
+
julia> db =SQLiteDB("Chinook_Sqlite.sqlite")
104
+
105
+
julia># using SQLite's in-built syntax
106
+
107
+
julia>query(db, "SELECT FirstName, LastName FROM Employee WHERE LastName REGEXP 'e(?=a)'")
108
+
1x2 ResultSet
109
+
| Row |"FirstName"|"LastName"|
110
+
|-----|-------------|------------|
111
+
|1|"Jane"|"Peacock"|
112
+
113
+
julia># explicitly calling the regexp() function
114
+
115
+
julia>query(db, "SELECT * FROM Genre WHERE regexp('e[trs]', Name)")
116
+
6x2 ResultSet
117
+
| Row |"GenreId"|"Name"|
118
+
|-----|-----------|----------------------|
119
+
|1|3|"Metal"|
120
+
|2|4|"Alternative & Punk"|
121
+
|3|6|"Blues"|
122
+
|4|13|"Heavy Metal"|
123
+
|5|23|"Alternative"|
124
+
|6|25|"Opera"|
125
+
126
+
julia># you can even do strange things like this if you really want
127
+
128
+
julia>query(db, "SELECT * FROM Genre ORDER BY GenreId LIMIT 2")
129
+
2x2 ResultSet
130
+
| Row |"GenreId"|"Name"|
131
+
|-----|-----------|--------|
132
+
|1|1|"Rock"|
133
+
|2|2|"Jazz"|
134
+
135
+
julia>query(db, "INSERT INTO Genre VALUES (regexp('^word', 'this is a string'), 'My Genre')")
136
+
1x1 ResultSet
137
+
| Row |"Rows Affected"|
138
+
|-----|-----------------|
139
+
|1|0|
140
+
141
+
julia>query(db, "SELECT * FROM Genre ORDER BY GenreId LIMIT 2")
142
+
2x2 ResultSet
143
+
| Row |"GenreId"|"Name"|
144
+
|-----|-----------|------------|
145
+
|1|0|"My Genre"|
146
+
|2|1|"Rock"|
147
+
```
148
+
149
+
Due to the heavy use of escape characters you may run into problems where julia parses out some backslashes in your query, for example `"\y"` simlpy becomes `"y"`. For example the following two queries are identical
150
+
151
+
```julia
152
+
julia>query(db, "SELECT * FROM MediaType WHERE Name REGEXP '-\d'")
153
+
1x1 ResultSet
154
+
| Row |"Rows Affected"|
155
+
|-----|-----------------|
156
+
|1|0|
157
+
158
+
julia>query(db, "SELECT * FROM MediaType WHERE Name REGEXP '-d'")
159
+
1x1 ResultSet
160
+
| Row |"Rows Affected"|
161
+
|-----|-----------------|
162
+
|1|0|
163
+
```
164
+
165
+
This can be avoided in two ways. You can either escape each backslash yourself or you can use the sr"..." string literal that SQLite.jl exports. The previous query can then successfully be run like so
166
+
167
+
```julia
168
+
julia># manually escaping backslashes
169
+
170
+
julia>query(db, "SELECT * FROM MediaType WHERE Name REGEXP '-\\d'")
The sr"..." currently escapes all special characters in a string but it may be changed in the future to escape only characters which are part of a regex.
186
+
187
+
##### Custom Scalar Functions
188
+
189
+
SQLite.jl also provides a way that you can implement your own [Scalar Functions](https://www.sqlite.org/lang_corefunc.html) (though [Aggregate Functions](https://www.sqlite.org/lang_aggfunc.html) are not currently supported). This is done using the `registerfunc` function and `@scalarfunc` macro.
190
+
191
+
`@scalarfunc` takes an optional function name and a function and defines a new function which can be passed to `registerfunc`. It can be used with block function syntax
julia>@scalarfunc mult5 anotherirrelevantname(x) =5* x
212
+
mult5 (generic function with 1 method)
213
+
```
214
+
215
+
and previously defined functions (note that name inference does not work with this method)
216
+
217
+
```julia
218
+
julia>@scalarfunc sin sin
219
+
sin (generic function with 1 method)
220
+
221
+
julia>@scalarfunc subtract -
222
+
subtract (generic function with 1 method)
223
+
```
224
+
225
+
The function that is defined can then be passed to `registerfunc`. `registerfunc` takes three arguments; the database to which the function should be registered, the number of arguments that the function takes and the function itself. The function is registered to the database connection rather than the database itself so must be registered each time the database opens. Your function can not take more than 127 arguments unless it takes a variable number of arguments, if it does take a variable number of arguments then you must pass -1 as the second argument to `registerfunc`.
226
+
227
+
The `@scalarfunc` macro uses the `sqlreturn` function to return your function's return value to SQLite. By default, `sqlreturn` maps the returned value to a [native SQLite type](http://sqlite.org/c3ref/result_blob.html) or, failing that, serializes the julia value and stores it as a `BLOB`. To change this behaviour simply define a new method for `sqlreturn` which then calls a previously defined method for `sqlreturn`. Methods which map to native SQLite types are
228
+
229
+
```julia
230
+
sqlreturn(context, ::NullType)
231
+
sqlreturn(context, val::Int32)
232
+
sqlreturn(context, val::Int64)
233
+
sqlreturn(context, val::Float64)
234
+
sqlreturn(context, val::UTF16String)
235
+
sqlreturn(context, val::String)
236
+
sqlreturn(context, val::Any)
237
+
```
238
+
239
+
As an example, say you would like `BigInt`s to be stored as `TEXT` rather than a `BLOB`. You would simply need to define the following method
Another example is the `sqlreturn` used by the `regexp` function. For `regexp` to work correctly it must return it must return an `Int` (more specifically a `0` or `1`) but `ismatch` (used by `regexp`) returns a `Bool`. For this reason the following method was defined
0 commit comments