1
1
VERSION >= v " 0.4.0-dev+6521" && __precompile__ (true )
2
2
module SQLite
3
3
4
- using CSV, DataStreams, DataFrames, NullableArrays , WeakRefStrings
4
+ using DataStreams, DataFrames, WeakRefStrings
5
5
6
- export Data
6
+ export Data, DataFrame
7
7
8
8
if ! isdefined (Core, :String )
9
9
typealias String UTF8String
@@ -23,7 +23,7 @@ include("consts.jl")
23
23
include (" api.jl" )
24
24
25
25
immutable NullType end
26
- " custom NULL value for interacting with the SQLite database"
26
+ # custom NULL value for interacting with the SQLite database
27
27
const NULL = NullType ()
28
28
show (io:: IO ,:: NullType ) = print (io," #NULL" )
29
29
@@ -34,7 +34,14 @@ sqliteopen(file::UTF16String,handle) = sqlite3_open16(file,handle)
34
34
sqliteerror () = throw (SQLiteException (unsafe_string (sqlite3_errmsg ())))
35
35
sqliteerror (db) = throw (SQLiteException (unsafe_string (sqlite3_errmsg (db. handle))))
36
36
37
- " represents an SQLite database, either backed by an on-disk file or in-memory"
37
+ """
38
+ represents an SQLite database, either backed by an on-disk file or in-memory
39
+
40
+ Constructors:
41
+
42
+ * `SQLite.DB()` => in-memory SQLite database
43
+ * `SQLite.DB(file)` => file-based SQLite database
44
+ """
38
45
type DB
39
46
file:: String
40
47
handle:: Ptr{Void}
@@ -54,7 +61,6 @@ type DB
54
61
end
55
62
end
56
63
end
57
- " `SQLite.DB()` creates an in-memory SQLite database"
58
64
DB () = DB (" :memory:" )
59
65
60
66
function _close (db:: DB )
@@ -92,15 +98,28 @@ sqliteprepare(db,sql,stmt,null) = @CHECK db sqlite3_prepare_v2(db.handle,sql,stm
92
98
include (" UDF.jl" )
93
99
export @sr_str , @register , register
94
100
95
- " bind a row (`values`) to nameless parameters by index"
101
+ """
102
+ `SQLite.bind!(stmt::SQLite.Stmt, values)`
103
+
104
+ bind `values` to parameters in a prepared SQL statement. Values can be:
105
+
106
+ * `Vector`; where each element will be bound to an SQL parameter by index order
107
+ * `Dict`; where dict values will be bound to named SQL parameters by the dict key
108
+
109
+ Additional methods exist for working individual SQL parameters:
110
+
111
+ * `SQLite.bind!(stmt, name, val)`: bind a single value to a named SQL parameter
112
+ * `SQLite.bind!(stmt, index, val)`: bind a single value to a SQL parameter by index number
113
+ """
114
+ function bind! end
115
+
96
116
function bind! (stmt:: Stmt , values:: Vector )
97
117
nparams = sqlite3_bind_parameter_count (stmt. handle)
98
118
@assert nparams == length (values) " you must provide values for all placeholders"
99
119
for i in 1 : nparams
100
120
@inbounds bind! (stmt, i, values[i])
101
121
end
102
122
end
103
- " bind a row (`Dict(:key => value)`) to named parameters"
104
123
function bind! {V} (stmt:: Stmt , values:: Dict{Symbol, V} )
105
124
nparams = sqlite3_bind_parameter_count (stmt. handle)
106
125
@assert nparams == length (values) " you must provide values for all placeholders"
@@ -113,7 +132,6 @@ function bind!{V}(stmt::Stmt, values::Dict{Symbol, V})
113
132
end
114
133
end
115
134
# Binding parameters to SQL statements
116
- " bind `val` to the named parameter `name`"
117
135
function bind! (stmt:: Stmt ,name:: AbstractString ,val)
118
136
i:: Int = sqlite3_bind_parameter_index (stmt. handle,name)
119
137
if i == 0
@@ -135,10 +153,10 @@ function bind!(stmt::Stmt,i::Int,val::WeakRefString{UInt32})
135
153
end
136
154
# We may want to track the new ByteVec type proposed at https://github.com/JuliaLang/julia/pull/8964
137
155
# as the "official" bytes type instead of Vector{UInt8}
138
- " bind a byte vector as an SQLite BLOB"
139
156
bind! (stmt:: Stmt ,i:: Int ,val:: Vector{UInt8} ) = (sqlite3_bind_blob (stmt. handle,i,val); return nothing )
140
157
# Fallback is BLOB and defaults to serializing the julia value
141
- " internal wrapper type to, in-effect, mark something which has been serialized"
158
+
159
+ # internal wrapper type to, in-effect, mark something which has been serialized
142
160
immutable Serialization
143
161
object
144
162
end
@@ -152,7 +170,7 @@ function sqlserialize(x)
152
170
serialize (t,s)
153
171
return takebuf_array (t)
154
172
end
155
- " fallback method to bind arbitrary julia `val` to the parameter at index `i` (object is serialized)"
173
+ # fallback method to bind arbitrary julia `val` to the parameter at index `i` (object is serialized)
156
174
bind! (stmt:: Stmt ,i:: Int ,val) = bind! (stmt,i,sqlserialize (val))
157
175
158
176
# magic bytes that indicate that a value is in fact a serialized julia value, instead of just a byte vector
171
189
# int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
172
190
# int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
173
191
174
- " Execute a prepared SQLite statement"
192
+ """
193
+ `SQLite.execute!(stmt::SQLite.Stmt)` => `Void`
194
+ `SQLite.execute!(db::DB, sql::String)` => `Void`
195
+
196
+ Execute a prepared SQLite statement, not checking for or returning any results.
197
+ """
198
+ function execute! end
199
+
175
200
function execute! (stmt:: Stmt )
176
201
r = sqlite3_step (stmt. handle)
177
202
if r == SQLITE_DONE
@@ -181,27 +206,39 @@ function execute!(stmt::Stmt)
181
206
end
182
207
return r
183
208
end
184
- " Prepare and execute an SQLite statement"
185
209
function execute! (db:: DB ,sql:: AbstractString )
186
210
stmt = Stmt (db,sql)
187
211
return execute! (stmt)
188
212
end
189
213
190
- " Escape SQLite identifiers (e.g. column, table or index names). Can be either
214
+ """
215
+ `SQLite.esc_id(x::Union{String,Vector{String}})`
216
+
217
+ Escape SQLite identifiers (e.g. column, table or index names). Can be either
191
218
a string, or a vector of strings (note does not check for null characters).
192
- A vector of identifiers will be separated by commas."
219
+ A vector of identifiers will be separated by commas.
220
+ """
221
+ function esc_id end
222
+
193
223
esc_id (x:: AbstractString ) = " \" " * replace (x," \" " ," \"\" " )* " \" "
194
224
esc_id {S<:AbstractString} (X:: AbstractVector{S} ) = join (map (esc_id,X),' ,' )
195
225
196
226
197
227
# Transaction-based commands
198
228
"""
199
- Begin a transaction in the spedified `mode`, default = "DEFERRED".
229
+ `SQLite.transaction(db, mode="DEFERRED")`
230
+ `SQLite.transaction(func, db)`
231
+
232
+ Begin a transaction in the specified `mode`, default = "DEFERRED".
200
233
201
234
If `mode` is one of "", "DEFERRED", "IMMEDIATE" or "EXCLUSIVE" then a
202
235
transaction of that (or the default) type is started. Otherwise a savepoint
203
236
is created whose name is `mode` converted to AbstractString.
237
+
238
+ In the second method, `func` is executed within a transaction (the transaction being committed upon successful execution)
204
239
"""
240
+ function transaction end
241
+
205
242
function transaction (db, mode= " DEFERRED" )
206
243
execute! (db," PRAGMA temp_store=MEMORY;" )
207
244
if uppercase (mode) in [" " , " DEFERRED" , " IMMEDIATE" , " EXCLUSIVE" ]
@@ -210,7 +247,6 @@ function transaction(db, mode="DEFERRED")
210
247
execute! (db, " SAVEPOINT $(mode) ;" )
211
248
end
212
249
end
213
- " Execute the function `f` within a transaction."
214
250
function transaction (f:: Function , db)
215
251
# generate a random name for the savepoint
216
252
name = string (" SQLITE" ,randstring (10 ))
@@ -228,17 +264,33 @@ function transaction(f::Function, db)
228
264
end
229
265
end
230
266
231
- " commit a transaction or named savepoint"
267
+ """
268
+ `SQLite.commit(db)`
269
+ `SQLite.commit(db, name)`
270
+
271
+ commit a transaction or named savepoint
272
+ """
273
+ function commit end
274
+
232
275
commit (db) = execute! (db, " COMMIT TRANSACTION;" )
233
- " commit a transaction or named savepoint"
234
276
commit (db, name) = execute! (db, " RELEASE SAVEPOINT $(name) ;" )
235
277
236
- " rollback transaction or named savepoint"
278
+ """
279
+ `SQLite.rollback(db)`
280
+ `SQLite.rollback(db, name)`
281
+
282
+ rollback transaction or named savepoint
283
+ """
284
+ function rollback end
285
+
237
286
rollback (db) = execute! (db, " ROLLBACK TRANSACTION;" )
238
- " rollback transaction or named savepoint"
239
287
rollback (db, name) = execute! (db, " ROLLBACK TRANSACTION TO SAVEPOINT $(name) ;" )
240
288
241
- " drop the SQLite table `table` from the database `db`; `ifexists=true` will prevent an error being thrown if `table` doesn't exist"
289
+ """
290
+ `SQLite.drop!(db, table; ifexists::Bool=true)`
291
+
292
+ drop the SQLite table `table` from the database `db`; `ifexists=true` will prevent an error being thrown if `table` doesn't exist
293
+ """
242
294
function drop! (db:: DB , table:: AbstractString ; ifexists:: Bool = false )
243
295
exists = ifexists ? " IF EXISTS" : " "
244
296
transaction (db) do
@@ -248,7 +300,11 @@ function drop!(db::DB, table::AbstractString; ifexists::Bool=false)
248
300
return
249
301
end
250
302
251
- " drop the SQLite index `index` from the database `db`; `ifexists=true` will not return an error if `index` doesn't exist"
303
+ """
304
+ `SQLite.dropindex!(db, index; ifexists::Bool=true)`
305
+
306
+ drop the SQLite index `index` from the database `db`; `ifexists=true` will not return an error if `index` doesn't exist
307
+ """
252
308
function dropindex! (db:: DB ,index:: AbstractString ;ifexists:: Bool = false )
253
309
exists = ifexists ? " IF EXISTS" : " "
254
310
transaction (db) do
@@ -258,6 +314,8 @@ function dropindex!(db::DB,index::AbstractString;ifexists::Bool=false)
258
314
end
259
315
260
316
"""
317
+ `SQLite.createindex!(db, table, index, cols; unique::Bool=true, ifnotexists::Bool=false)`
318
+
261
319
create the SQLite index `index` on the table `table` using `cols`, which may be a single column or vector of columns.
262
320
`unique` specifies whether the index will be unique or not.
263
321
`ifnotexists=true` will not throw an error if the index already exists
@@ -273,11 +331,15 @@ function createindex!{S<:AbstractString}(db::DB,table::AbstractString,index::Abs
273
331
return
274
332
end
275
333
276
- " removes duplicate rows from `table` based on the values in `cols` which is an array of column names"
334
+ """
335
+ `SQLite.removeduplicates!(db, table, cols::Vector)`
336
+
337
+ removes duplicate rows from `table` based on the values in `cols` which is an array of column names
338
+ """
277
339
function removeduplicates! {T <: AbstractString} (db,table:: AbstractString ,cols:: AbstractArray{T} )
278
340
colsstr = " "
279
341
for c in cols
280
- colsstr = colsstr* esc_id (c)* " ,"
342
+ colsstr = colsstr * esc_id (c) * " ,"
281
343
end
282
344
colsstr = chop (colsstr)
283
345
transaction (db) do
@@ -287,19 +349,7 @@ function removeduplicates!{T <: AbstractString}(db,table::AbstractString,cols::A
287
349
return
288
350
end
289
351
290
- function removeduplicates! (db,table:: AbstractString ,cols:: AbstractString )
291
- warn (" This method is deprecated, please provide the column names as an array of column names rather than a single string." )
292
- transaction (db) do
293
- execute! (db," DELETE FROM $(esc_id (table)) WHERE _ROWID_ NOT IN (SELECT max(_ROWID_) from $(esc_id (table)) GROUP BY $(esc_id (cols)) );" )
294
- end
295
- execute! (db," ANALYZE $table " )
296
- return
297
- end
298
-
299
-
300
- """
301
- `SQLite.Source` implementes the `DataStreams` framework for interacting with SQLite databases
302
- """
352
+ " `SQLite.Source` implements the `Source` interface in the `DataStreams` framework"
303
353
type Source <: Data.Source
304
354
schema:: Data.Schema
305
355
stmt:: Stmt
0 commit comments