1
1
__precompile__ (true )
2
2
module SQLite
3
3
4
- using DataStreams, DataFrames , WeakRefStrings, LegacyStrings, Compat
4
+ using Nulls, DataStreams , WeakRefStrings, LegacyStrings, DataFrames
5
5
import LegacyStrings: UTF16String
6
6
7
7
export Data, DataFrame
8
8
9
- type SQLiteException <: Exception
9
+ struct SQLiteException <: Exception
10
10
msg:: AbstractString
11
11
end
12
12
13
13
include (" consts.jl" )
14
14
include (" api.jl" )
15
15
16
- immutable NullType end
17
- # custom NULL value for interacting with the SQLite database
18
- const NULL = NullType ()
19
- show (io:: IO ,:: NullType ) = print (io," #NULL" )
20
-
21
16
# TODO : Support sqlite3_open_v2
22
17
# Normal constructor from filename
23
- sqliteopen (file,handle) = sqlite3_open (file,handle)
24
- sqliteopen (file:: UTF16String ,handle) = sqlite3_open16 (file,handle)
18
+ sqliteopen (file, handle) = sqlite3_open (file, handle)
19
+ sqliteopen (file:: UTF16String , handle) = sqlite3_open16 (file, handle)
25
20
sqliteerror () = throw (SQLiteException (unsafe_string (sqlite3_errmsg ())))
26
21
sqliteerror (db) = throw (SQLiteException (unsafe_string (sqlite3_errmsg (db. handle))))
27
22
@@ -33,7 +28,7 @@ Constructors:
33
28
* `SQLite.DB()` => in-memory SQLite database
34
29
* `SQLite.DB(file)` => file-based SQLite database
35
30
"""
36
- type DB
31
+ mutable struct DB
37
32
file:: String
38
33
handle:: Ptr{Void}
39
34
changes:: Int
@@ -59,19 +54,19 @@ function _close(db::DB)
59
54
return
60
55
end
61
56
62
- Base. show (io:: IO , db:: SQLite.DB ) = print (io, string (" SQLite.DB(" ,db. file == " :memory:" ? " in-memory" : " \" $(db. file) \" " ," )" ))
57
+ Base. show (io:: IO , db:: SQLite.DB ) = print (io, string (" SQLite.DB(" , db. file == " :memory:" ? " in-memory" : " \" $(db. file) \" " , " )" ))
63
58
64
59
"""
65
60
`SQLite.Stmt(db::DB, sql::AbstractString)` creates and prepares an SQLite statement
66
61
"""
67
- type Stmt
62
+ mutable struct Stmt
68
63
db:: DB
69
64
handle:: Ptr{Void}
70
65
71
66
function Stmt (db:: DB ,sql:: AbstractString )
72
67
handle = Ref {Ptr{Void}} ()
73
- sqliteprepare (db,sql,handle,Ref {Ptr{Void}} ())
74
- stmt = new (db,handle[])
68
+ sqliteprepare (db, sql, handle, Ref {Ptr{Void}} ())
69
+ stmt = new (db, handle[])
75
70
finalizer (stmt, _close)
76
71
return stmt
77
72
end
@@ -83,7 +78,7 @@ function _close(stmt::Stmt)
83
78
return
84
79
end
85
80
86
- sqliteprepare (db,sql,stmt,null) = @CHECK db sqlite3_prepare_v2 (db. handle,sql,stmt,null)
81
+ sqliteprepare (db, sql, stmt, null) = @CHECK db sqlite3_prepare_v2 (db. handle, sql, stmt, null)
87
82
88
83
include (" UDF.jl" )
89
84
export @sr_str , @register , register
@@ -127,7 +122,7 @@ function bind!(stmt::Stmt, values::Vector)
127
122
@inbounds bind! (stmt, i, values[i])
128
123
end
129
124
end
130
- function bind! {V} (stmt:: Stmt , values:: Dict{Symbol, V} )
125
+ function bind! (stmt:: Stmt , values:: Dict{Symbol, V} ) where {V}
131
126
nparams = sqlite3_bind_parameter_count (stmt. handle)
132
127
@assert nparams == length (values) " you must provide values for all placeholders"
133
128
for i in 1 : nparams
@@ -139,56 +134,58 @@ function bind!{V}(stmt::Stmt, values::Dict{Symbol, V})
139
134
end
140
135
end
141
136
# Binding parameters to SQL statements
142
- function bind! (stmt:: Stmt ,name:: AbstractString ,val)
143
- i:: Int = sqlite3_bind_parameter_index (stmt. handle,name)
137
+ function bind! (stmt:: Stmt ,name:: AbstractString , val)
138
+ i:: Int = sqlite3_bind_parameter_index (stmt. handle, name)
144
139
if i == 0
145
140
throw (SQLiteException (" SQL parameter $name not found in $stmt " ))
146
141
end
147
- return bind! (stmt,i, val)
142
+ return bind! (stmt, i, val)
148
143
end
149
- bind! (stmt:: Stmt ,i:: Int ,val:: AbstractFloat ) = (sqlite3_bind_double (stmt. handle,i ,Float64 (val)); return nothing )
150
- bind! (stmt:: Stmt ,i:: Int ,val:: Int32 ) = (sqlite3_bind_int (stmt. handle,i ,val); return nothing )
151
- bind! (stmt:: Stmt ,i:: Int ,val:: Int64 ) = (sqlite3_bind_int64 (stmt. handle,i ,val); return nothing )
152
- bind! (stmt:: Stmt ,i:: Int ,val:: NullType ) = (sqlite3_bind_null (stmt. handle,i ); return nothing )
153
- bind! (stmt:: Stmt ,i:: Int ,val:: AbstractString ) = (sqlite3_bind_text (stmt. handle,i ,val); return nothing )
154
- bind! (stmt:: Stmt ,i:: Int ,val:: WeakRefString{UInt8} ) = (sqlite3_bind_text (stmt. handle,i, val. ptr,val. len); return nothing )
155
- bind! (stmt:: Stmt ,i:: Int ,val:: WeakRefString{UInt16} ) = (sqlite3_bind_text16 (stmt. handle,i, val. ptr,val. len* 2 ); return nothing )
156
- bind! (stmt:: Stmt ,i:: Int ,val:: UTF16String ) = (sqlite3_bind_text16 (stmt. handle,i, val); return nothing )
157
- function bind! (stmt:: Stmt ,i:: Int ,val:: WeakRefString{UInt32} )
144
+ bind! (stmt:: Stmt , i:: Int , val:: AbstractFloat ) = (sqlite3_bind_double (stmt. handle, i ,Float64 (val)); return nothing )
145
+ bind! (stmt:: Stmt , i:: Int , val:: Int32 ) = (sqlite3_bind_int (stmt. handle, i ,val); return nothing )
146
+ bind! (stmt:: Stmt , i:: Int , val:: Int64 ) = (sqlite3_bind_int64 (stmt. handle, i ,val); return nothing )
147
+ bind! (stmt:: Stmt , i:: Int , val:: Null ) = (sqlite3_bind_null (stmt. handle, i ); return nothing )
148
+ bind! (stmt:: Stmt , i:: Int , val:: AbstractString ) = (sqlite3_bind_text (stmt. handle, i ,val); return nothing )
149
+ bind! (stmt:: Stmt , i:: Int , val:: WeakRefString{UInt8} ) = (sqlite3_bind_text (stmt. handle, i, val. ptr, val. len); return nothing )
150
+ bind! (stmt:: Stmt , i:: Int , val:: WeakRefString{UInt16} ) = (sqlite3_bind_text16 (stmt. handle, i, val. ptr, val. len* 2 ); return nothing )
151
+ bind! (stmt:: Stmt , i:: Int , val:: UTF16String ) = (sqlite3_bind_text16 (stmt. handle, i, val); return nothing )
152
+ function bind! (stmt:: Stmt , i:: Int , val:: WeakRefString{UInt32} )
158
153
A = UTF32String (pointer_to_array (val. ptr, val. len+ 1 , false ))
159
- return bind! (stmt, i, convert (String,A))
154
+ return bind! (stmt, i, convert (String, A))
160
155
end
161
- # We may want to track the new ByteVec type proposed at https://github.com/JuliaLang/julia/pull/8964
162
- # as the "official" bytes type instead of Vector{UInt8}
163
- bind! (stmt:: Stmt ,i:: Int ,val:: Vector{UInt8} ) = (sqlite3_bind_blob (stmt. handle,i, val); return nothing )
156
+ # We may want to track the new ByteVec mutable struct proposed at https://github.com/JuliaLang/julia/pull/8964
157
+ # as the "official" bytes mutable struct instead of Vector{UInt8}
158
+ bind! (stmt:: Stmt , i:: Int , val:: Vector{UInt8} ) = (sqlite3_bind_blob (stmt. handle, i, val); return nothing )
164
159
# Fallback is BLOB and defaults to serializing the julia value
165
160
166
- # internal wrapper type to, in-effect, mark something which has been serialized
167
- immutable Serialization
161
+ # internal wrapper mutable struct to, in-effect, mark something which has been serialized
162
+ struct Serialization
168
163
object
169
164
end
170
165
166
+ const GLOBAL_BUF = IOBuffer ()
171
167
function sqlserialize (x)
172
- t = IOBuffer ( )
168
+ seekstart (GLOBAL_BUF )
173
169
# deserialize will sometimes return a random object when called on an array
174
- # which has not been previously serialized, we can use this type to check
170
+ # which has not been previously serialized, we can use this mutable struct to check
175
171
# that the array has been serialized
176
172
s = Serialization (x)
177
- serialize (t, s)
178
- return take! (t )
173
+ serialize (GLOBAL_BUF, s)
174
+ return take! (GLOBAL_BUF )
179
175
end
180
176
# fallback method to bind arbitrary julia `val` to the parameter at index `i` (object is serialized)
181
- bind! (stmt:: Stmt ,i:: Int ,val) = bind! (stmt,i, sqlserialize (val))
177
+ bind! (stmt:: Stmt , i:: Int , val) = bind! (stmt, i, sqlserialize (val))
182
178
183
- immutable SerializeError <: Exception
179
+ struct SerializeError <: Exception
184
180
msg:: String
185
181
end
186
182
187
183
# magic bytes that indicate that a value is in fact a serialized julia value, instead of just a byte vector
188
- const SERIALIZATION = UInt8[0x11 ,0x01 ,0x02 ,0x0d ,0x53 ,0x65 ,0x72 ,0x69 ,0x61 ,0x6c ,0x69 ,0x7a ,0x61 ,0x74 ,0x69 ,0x6f ,0x6e ,0x23 ]
184
+ # const SERIALIZATION = UInt8[0x11,0x01,0x02,0x0d,0x53,0x65,0x72,0x69,0x61,0x6c,0x69,0x7a,0x61,0x74,0x69,0x6f,0x6e,0x23]
185
+ const SERIALIZATION = UInt8[0x34 ,0x10 ,0x01 ,0x0d ,0x53 ,0x65 ,0x72 ,0x69 ,0x61 ,0x6c ,0x69 ,0x7a ,0x61 ,0x74 ,0x69 ,0x6f ,0x6e ,0x1f ]
189
186
function sqldeserialize (r)
190
- ret = ccall (:memcmp , Int32, (Ptr{UInt8},Ptr{UInt8}, UInt),
191
- SERIALIZATION, r, min (18 ,length (r)))
187
+ ret = ccall (:memcmp , Int32, (Ptr{UInt8}, Ptr{UInt8}, UInt),
188
+ SERIALIZATION, r, min (18 , length (r)))
192
189
if ret == 0
193
190
try
194
191
v = deserialize (IOBuffer (r))
@@ -223,8 +220,8 @@ function execute!(stmt::Stmt)
223
220
end
224
221
return r
225
222
end
226
- function execute! (db:: DB ,sql:: AbstractString )
227
- stmt = Stmt (db,sql)
223
+ function execute! (db:: DB , sql:: AbstractString )
224
+ stmt = Stmt (db, sql)
228
225
return execute! (stmt)
229
226
end
230
227
@@ -237,8 +234,8 @@ A vector of identifiers will be separated by commas.
237
234
"""
238
235
function esc_id end
239
236
240
- esc_id (x:: AbstractString ) = " \" " * replace (x," \" " ," \"\" " )* " \" "
241
- esc_id {S<:AbstractString} (X:: AbstractVector{S} ) = join (map (esc_id,X),' ,' )
237
+ esc_id (x:: AbstractString ) = " \" " * replace (x," \" " ," \"\" " ) * " \" "
238
+ esc_id (X:: AbstractVector{S} ) where {S <: AbstractString } = join (map (esc_id, X), ' ,' )
242
239
243
240
244
241
# Transaction-based commands
@@ -251,15 +248,15 @@ esc_id{S<:AbstractString}(X::AbstractVector{S}) = join(map(esc_id,X),',')
251
248
Begin a transaction in the specified `mode`, default = "DEFERRED".
252
249
253
250
If `mode` is one of "", "DEFERRED", "IMMEDIATE" or "EXCLUSIVE" then a
254
- transaction of that (or the default) type is started. Otherwise a savepoint
251
+ transaction of that (or the default) mutable struct is started. Otherwise a savepoint
255
252
is created whose name is `mode` converted to AbstractString.
256
253
257
254
In the second method, `func` is executed within a transaction (the transaction being committed upon successful execution)
258
255
"""
259
256
function transaction end
260
257
261
258
function transaction (db, mode= " DEFERRED" )
262
- execute! (db," PRAGMA temp_store=MEMORY;" )
259
+ execute! (db, " PRAGMA temp_store=MEMORY;" )
263
260
if uppercase (mode) in [" " , " DEFERRED" , " IMMEDIATE" , " EXCLUSIVE" ]
264
261
execute! (db, " BEGIN $(mode) TRANSACTION;" )
265
262
else
@@ -317,9 +314,9 @@ drop the SQLite table `table` from the database `db`; `ifexists=true` will preve
317
314
function drop! (db:: DB , table:: AbstractString ; ifexists:: Bool = false )
318
315
exists = ifexists ? " IF EXISTS" : " "
319
316
transaction (db) do
320
- execute! (db," DROP TABLE $exists $(esc_id (table)) " )
317
+ execute! (db, " DROP TABLE $exists $(esc_id (table)) " )
321
318
end
322
- execute! (db," VACUUM" )
319
+ execute! (db, " VACUUM" )
323
320
return
324
321
end
325
322
@@ -328,10 +325,10 @@ end
328
325
329
326
drop the SQLite index `index` from the database `db`; `ifexists=true` will not return an error if `index` doesn't exist
330
327
"""
331
- function dropindex! (db:: DB ,index:: AbstractString ;ifexists:: Bool = false )
328
+ function dropindex! (db:: DB , index:: AbstractString ; ifexists:: Bool = false )
332
329
exists = ifexists ? " IF EXISTS" : " "
333
330
transaction (db) do
334
- execute! (db," DROP INDEX $exists $(esc_id (index)) " )
331
+ execute! (db, " DROP INDEX $exists $(esc_id (index)) " )
335
332
end
336
333
return
337
334
end
@@ -343,14 +340,14 @@ create the SQLite index `index` on the table `table` using `cols`, which may be
343
340
`unique` specifies whether the index will be unique or not.
344
341
`ifnotexists=true` will not throw an error if the index already exists
345
342
"""
346
- function createindex! {S<:AbstractString} (db:: DB ,table:: AbstractString ,index:: AbstractString ,cols:: Union{S,AbstractVector{S}}
347
- ; unique:: Bool = true ,ifnotexists:: Bool = false )
343
+ function createindex! (db:: DB , table:: AbstractString , index:: AbstractString , cols:: Union{S, AbstractVector{S}} ;
344
+ unique:: Bool = true , ifnotexists:: Bool = false ) where {S <: AbstractString }
348
345
u = unique ? " UNIQUE" : " "
349
346
exists = ifnotexists ? " IF NOT EXISTS" : " "
350
347
transaction (db) do
351
- execute! (db," CREATE $u INDEX $exists $(esc_id (index)) ON $(esc_id (table)) ($(esc_id (cols)) )" )
348
+ execute! (db, " CREATE $u INDEX $exists $(esc_id (index)) ON $(esc_id (table)) ($(esc_id (cols)) )" )
352
349
end
353
- execute! (db," ANALYZE $index " )
350
+ execute! (db, " ANALYZE $index " )
354
351
return
355
352
end
356
353
@@ -359,32 +356,33 @@ end
359
356
360
357
removes duplicate rows from `table` based on the values in `cols` which is an array of column names
361
358
"""
362
- function removeduplicates! {T <: AbstractString} (db,table:: AbstractString ,cols:: AbstractArray{T} )
359
+ function removeduplicates! (db, table:: AbstractString , cols:: AbstractArray{T} ) where {T <: AbstractString }
363
360
colsstr = " "
364
361
for c in cols
365
362
colsstr = colsstr * esc_id (c) * " ,"
366
363
end
367
364
colsstr = chop (colsstr)
368
365
transaction (db) do
369
- execute! (db," DELETE FROM $(esc_id (table)) WHERE _ROWID_ NOT IN (SELECT max(_ROWID_) from $(esc_id (table)) GROUP BY $(colsstr) );" )
366
+ execute! (db, " DELETE FROM $(esc_id (table)) WHERE _ROWID_ NOT IN (SELECT max(_ROWID_) from $(esc_id (table)) GROUP BY $(colsstr) );" )
370
367
end
371
- execute! (db," ANALYZE $table " )
368
+ execute! (db, " ANALYZE $table " )
372
369
return
373
370
end
374
371
375
372
" `SQLite.Source` implements the `Source` interface in the `DataStreams` framework"
376
- type Source <: Data.Source
373
+ mutable struct Source <: Data.Source
377
374
schema:: Data.Schema
378
375
stmt:: Stmt
379
376
status:: Cint
380
377
end
381
378
382
379
" SQLite.Sink implements the `Sink` interface in the `DataStreams` framework"
383
- type Sink <: Data.Sink
380
+ mutable struct Sink <: Data.Sink
384
381
db:: DB
385
382
tablename:: String
386
383
stmt:: Stmt
387
384
transaction:: String
385
+ cols:: Int
388
386
end
389
387
390
388
include (" Source.jl" )
0 commit comments