baza 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +55 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/include/db.rb +784 -0
- data/include/dbtime.rb +35 -0
- data/include/drivers/.DS_Store +0 -0
- data/include/drivers/mysql/mysql.rb +604 -0
- data/include/drivers/mysql/mysql_columns.rb +155 -0
- data/include/drivers/mysql/mysql_indexes.rb +69 -0
- data/include/drivers/mysql/mysql_sqlspecs.rb +5 -0
- data/include/drivers/mysql/mysql_tables.rb +443 -0
- data/include/drivers/sqlite3/libknjdb_java_sqlite3.rb +83 -0
- data/include/drivers/sqlite3/libknjdb_sqlite3_ironruby.rb +69 -0
- data/include/drivers/sqlite3/sqlite3.rb +184 -0
- data/include/drivers/sqlite3/sqlite3_columns.rb +177 -0
- data/include/drivers/sqlite3/sqlite3_indexes.rb +29 -0
- data/include/drivers/sqlite3/sqlite3_sqlspecs.rb +5 -0
- data/include/drivers/sqlite3/sqlite3_tables.rb +449 -0
- data/include/dump.rb +122 -0
- data/include/idquery.rb +109 -0
- data/include/model.rb +873 -0
- data/include/model_custom.rb +153 -0
- data/include/model_handler.rb +957 -0
- data/include/model_handler_sqlhelper.rb +499 -0
- data/include/query_buffer.rb +87 -0
- data/include/revision.rb +342 -0
- data/include/row.rb +153 -0
- data/include/sqlspecs.rb +5 -0
- data/lib/baza.rb +8 -0
- data/spec/baza_spec.rb +286 -0
- data/spec/db_spec_encoding_test_file.txt +1 -0
- data/spec/spec_helper.rb +12 -0
- metadata +215 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
class Baza::Driver::Sqlite3::Indexes
|
2
|
+
def initialize(args)
|
3
|
+
@args = args
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class Baza::Driver::Sqlite3::Indexes::Index
|
8
|
+
attr_reader :columns
|
9
|
+
|
10
|
+
def initialize(args)
|
11
|
+
@args = args
|
12
|
+
@columns = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
return @args[:data][:name]
|
17
|
+
end
|
18
|
+
|
19
|
+
def drop
|
20
|
+
@args[:db].query("DROP INDEX `#{self.name}`")
|
21
|
+
end
|
22
|
+
|
23
|
+
def data
|
24
|
+
return {
|
25
|
+
"name" => name,
|
26
|
+
"columns" => @columns
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,449 @@
|
|
1
|
+
class Baza::Driver::Sqlite3::Tables
|
2
|
+
attr_reader :db, :driver
|
3
|
+
|
4
|
+
def initialize(args)
|
5
|
+
@args = args
|
6
|
+
@db = @args[:db]
|
7
|
+
|
8
|
+
@list_mutex = Mutex.new
|
9
|
+
@list = Wref_map.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](table_name)
|
13
|
+
table_name = table_name.to_s
|
14
|
+
|
15
|
+
begin
|
16
|
+
ret = @list[table_name]
|
17
|
+
return ret
|
18
|
+
rescue Wref::Recycled
|
19
|
+
#ignore.
|
20
|
+
end
|
21
|
+
|
22
|
+
self.list do |table_obj|
|
23
|
+
return table_obj if table_obj.name.to_s == table_name.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
raise Errno::ENOENT, "Table was not found: #{table_name}."
|
27
|
+
end
|
28
|
+
|
29
|
+
def list
|
30
|
+
ret = {} unless block_given?
|
31
|
+
|
32
|
+
@list_mutex.synchronize do
|
33
|
+
q_tables = @db.select("sqlite_master", {"type" => "table"}, {"orderby" => "name"}) do |d_tables|
|
34
|
+
next if d_tables[:name] == "sqlite_sequence"
|
35
|
+
|
36
|
+
obj = @list.get!(d_tables[:name])
|
37
|
+
|
38
|
+
if !obj
|
39
|
+
obj = Baza::Driver::Sqlite3::Tables::Table.new(
|
40
|
+
:db => @db,
|
41
|
+
:data => d_tables
|
42
|
+
)
|
43
|
+
@list[d_tables[:name]] = obj
|
44
|
+
end
|
45
|
+
|
46
|
+
if block_given?
|
47
|
+
yield(obj)
|
48
|
+
else
|
49
|
+
ret[d_tables[:name]] = obj
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if block_given?
|
55
|
+
return nil
|
56
|
+
else
|
57
|
+
return ret
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def create(name, data, args = nil)
|
62
|
+
sql = "CREATE TABLE `#{name}` ("
|
63
|
+
|
64
|
+
first = true
|
65
|
+
data["columns"].each do |col_data|
|
66
|
+
sql << ", " if !first
|
67
|
+
first = false if first
|
68
|
+
sql << @db.cols.data_sql(col_data)
|
69
|
+
end
|
70
|
+
|
71
|
+
sql << ")"
|
72
|
+
|
73
|
+
if args and args[:return_sql]
|
74
|
+
ret = [sql]
|
75
|
+
else
|
76
|
+
@db.query(sql)
|
77
|
+
end
|
78
|
+
|
79
|
+
if data.key?("indexes") and data["indexes"]
|
80
|
+
table_obj = self[name]
|
81
|
+
|
82
|
+
if args and args[:return_sql]
|
83
|
+
ret += table_obj.create_indexes(data["indexes"], :return_sql => true)
|
84
|
+
else
|
85
|
+
table_obj.create_indexes(data["indexes"])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
if args and args[:return_sql]
|
90
|
+
return ret
|
91
|
+
else
|
92
|
+
return nil
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class Baza::Driver::Sqlite3::Tables::Table
|
98
|
+
def initialize(args)
|
99
|
+
@db = args[:db]
|
100
|
+
@data = args[:data]
|
101
|
+
|
102
|
+
@list = Wref_map.new
|
103
|
+
@indexes_list = Wref_map.new
|
104
|
+
end
|
105
|
+
|
106
|
+
def name
|
107
|
+
return @data[:name]
|
108
|
+
end
|
109
|
+
|
110
|
+
def type
|
111
|
+
return @data[:type]
|
112
|
+
end
|
113
|
+
|
114
|
+
def maxlength
|
115
|
+
return @data[:maxlength]
|
116
|
+
end
|
117
|
+
|
118
|
+
def reload
|
119
|
+
@data = @db.select("sqlite_master", {"type" => "table", "name" => self.name}, {"orderby" => "name"}).fetch
|
120
|
+
end
|
121
|
+
|
122
|
+
def rows_count
|
123
|
+
data = @db.q("SELECT COUNT(*) AS count FROM `#{self.name}`").fetch
|
124
|
+
return data[:count].to_i
|
125
|
+
end
|
126
|
+
|
127
|
+
#Drops the table from the database.
|
128
|
+
def drop
|
129
|
+
raise "Cant drop native table: '#{self.name}'." if self.native?
|
130
|
+
@db.query("DROP TABLE `#{self.name}`")
|
131
|
+
end
|
132
|
+
|
133
|
+
#Returns true if the table is safe to drop.
|
134
|
+
def native?
|
135
|
+
return true if self.name.to_s == "sqlite_sequence"
|
136
|
+
return false
|
137
|
+
end
|
138
|
+
|
139
|
+
def optimize
|
140
|
+
raise "stub!"
|
141
|
+
end
|
142
|
+
|
143
|
+
def rename(newname)
|
144
|
+
self.clone(newname)
|
145
|
+
self.drop
|
146
|
+
end
|
147
|
+
|
148
|
+
def truncate
|
149
|
+
@db.query("DELETE FROM `#{self.name}` WHERE 1=1")
|
150
|
+
return nil
|
151
|
+
end
|
152
|
+
|
153
|
+
def table
|
154
|
+
return @db.tables[@table_name]
|
155
|
+
end
|
156
|
+
|
157
|
+
def column(name)
|
158
|
+
list = self.columns
|
159
|
+
return list[name] if list[name]
|
160
|
+
raise Errno::ENOENT.new("Column not found: #{name}.")
|
161
|
+
end
|
162
|
+
|
163
|
+
def columns
|
164
|
+
@db.cols
|
165
|
+
ret = {}
|
166
|
+
|
167
|
+
@db.q("PRAGMA table_info(`#{@db.esc_table(self.name)}`)") do |d_cols|
|
168
|
+
obj = @list.get!(d_cols[:name])
|
169
|
+
|
170
|
+
if !obj
|
171
|
+
obj = Baza::Driver::Sqlite3::Columns::Column.new(
|
172
|
+
:table_name => self.name,
|
173
|
+
:db => @db,
|
174
|
+
:data => d_cols
|
175
|
+
)
|
176
|
+
@list[d_cols[:name]] = obj
|
177
|
+
end
|
178
|
+
|
179
|
+
if block_given?
|
180
|
+
yield(obj)
|
181
|
+
else
|
182
|
+
ret[d_cols[:name]] = obj
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
if block_given?
|
187
|
+
return nil
|
188
|
+
else
|
189
|
+
return ret
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def create_columns(col_arr)
|
194
|
+
col_arr.each do |col_data|
|
195
|
+
#if col_data.key?("after")
|
196
|
+
# self.create_column_programmatic(col_data)
|
197
|
+
#else
|
198
|
+
@db.query("ALTER TABLE `#{self.name}` ADD COLUMN #{@db.cols.data_sql(col_data)};")
|
199
|
+
#end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def create_column_programmatic(col_data)
|
204
|
+
temp_name = "temptable_#{Time.now.to_f.to_s.hash}"
|
205
|
+
cloned_tabled = self.clone(temp_name)
|
206
|
+
cols_cur = self.columns
|
207
|
+
@db.query("DROP TABLE `#{self.name}`")
|
208
|
+
|
209
|
+
sql = "CREATE TABLE `#{self.name}` ("
|
210
|
+
first = true
|
211
|
+
cols_cur.each do |name, col|
|
212
|
+
sql << ", " if !first
|
213
|
+
first = false if first
|
214
|
+
sql << @db.cols.data_sql(col.data)
|
215
|
+
|
216
|
+
if col_data["after"] and col_data["after"] == name
|
217
|
+
sql << ", #{@db.cols.data_sql(col_data)}"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
sql << ");"
|
221
|
+
@db.query(sql)
|
222
|
+
|
223
|
+
sql = "INSERT INTO `#{self.name}` SELECT "
|
224
|
+
first = true
|
225
|
+
cols_cur.each do |name, col|
|
226
|
+
sql << ", " if !first
|
227
|
+
first = false if first
|
228
|
+
|
229
|
+
sql << "`#{name}`"
|
230
|
+
|
231
|
+
if col_data["after"] and col_data["after"] == name
|
232
|
+
sql << ", ''"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
sql << " FROM `#{temp_name}`"
|
236
|
+
@db.query(sql)
|
237
|
+
@db.query("DROP TABLE `#{temp_name}`")
|
238
|
+
end
|
239
|
+
|
240
|
+
def clone(newname)
|
241
|
+
raise "Invalid name." if newname.to_s.strip.length <= 0
|
242
|
+
cols_cur = self.columns
|
243
|
+
|
244
|
+
sql = "CREATE TABLE `#{newname}` ("
|
245
|
+
first = true
|
246
|
+
cols_cur.each do |name, col|
|
247
|
+
sql << ", " if !first
|
248
|
+
first = false if first
|
249
|
+
sql << @db.cols.data_sql(col.data)
|
250
|
+
end
|
251
|
+
|
252
|
+
sql << ");"
|
253
|
+
@db.query(sql)
|
254
|
+
|
255
|
+
sql = "INSERT INTO `#{newname}` SELECT * FROM `#{self.name}`"
|
256
|
+
@db.query(sql)
|
257
|
+
return @db.tables[newname]
|
258
|
+
end
|
259
|
+
|
260
|
+
def copy(args = {})
|
261
|
+
temp_name = "temptable_#{Time.now.to_f.to_s.hash}"
|
262
|
+
cloned_tabled = self.clone(temp_name)
|
263
|
+
cols_cur = self.columns
|
264
|
+
@db.query("DROP TABLE `#{self.name}`")
|
265
|
+
|
266
|
+
sql = "CREATE TABLE `#{self.name}` ("
|
267
|
+
first = true
|
268
|
+
cols_cur.each do |name, col|
|
269
|
+
next if args["drops"] and args["drops"].index(name) != nil
|
270
|
+
|
271
|
+
sql << ", " if !first
|
272
|
+
first = false if first
|
273
|
+
|
274
|
+
if args.key?("alter_columns") and args["alter_columns"][name.to_s]
|
275
|
+
sql << @db.cols.data_sql(args["alter_columns"][name.to_s])
|
276
|
+
else
|
277
|
+
sql << @db.cols.data_sql(col.data)
|
278
|
+
end
|
279
|
+
|
280
|
+
if args["new"]
|
281
|
+
args["new"].each do |col_data|
|
282
|
+
if col_data["after"] and col_data["after"] == name
|
283
|
+
sql << ", #{@db.cols.data_sql(col_data)}"
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
sql << ");"
|
289
|
+
@db.query(sql)
|
290
|
+
|
291
|
+
sql = "INSERT INTO `#{self.name}` SELECT "
|
292
|
+
first = true
|
293
|
+
cols_cur.each do |name, col|
|
294
|
+
next if args["drops"] and args["drops"].index(name) != nil
|
295
|
+
|
296
|
+
sql << ", " if !first
|
297
|
+
first = false if first
|
298
|
+
|
299
|
+
sql << "`#{name}`"
|
300
|
+
|
301
|
+
if args["news"]
|
302
|
+
args["news"].each do |col_data|
|
303
|
+
if col_data["after"] and col_data["after"] == name
|
304
|
+
sql << ", ''"
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
sql << " FROM `#{temp_name}`"
|
311
|
+
@db.query(sql)
|
312
|
+
@db.query("DROP TABLE `#{temp_name}`")
|
313
|
+
end
|
314
|
+
|
315
|
+
def index(name)
|
316
|
+
name = name.to_s
|
317
|
+
|
318
|
+
begin
|
319
|
+
return @indexes_list[name]
|
320
|
+
rescue Wref::Recycled
|
321
|
+
if @db.opts[:index_append_table_name]
|
322
|
+
tryname = "#{self.name}__#{name}"
|
323
|
+
|
324
|
+
begin
|
325
|
+
return @indexes_list[tryname]
|
326
|
+
rescue Wref::Recycled
|
327
|
+
#ignore.
|
328
|
+
end
|
329
|
+
else
|
330
|
+
#ignore
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
self.indexes do |index|
|
335
|
+
return index if index.name.to_s == name
|
336
|
+
end
|
337
|
+
|
338
|
+
raise Errno::ENOENT.new("Index not found: #{name}.")
|
339
|
+
end
|
340
|
+
|
341
|
+
def indexes
|
342
|
+
@db.indexes
|
343
|
+
ret = {} unless block_given?
|
344
|
+
|
345
|
+
@db.q("PRAGMA index_list(`#{@db.esc_table(self.name)}`)") do |d_indexes|
|
346
|
+
next if d_indexes[:Key_name] == "PRIMARY"
|
347
|
+
|
348
|
+
obj = @indexes_list.get!(d_indexes[:name])
|
349
|
+
|
350
|
+
if !obj
|
351
|
+
if @db.opts[:index_append_table_name]
|
352
|
+
match_name = d_indexes[:name].match(/__(.+)$/)
|
353
|
+
|
354
|
+
if match_name
|
355
|
+
name = match_name[1]
|
356
|
+
else
|
357
|
+
name = d_indexes[:name]
|
358
|
+
end
|
359
|
+
else
|
360
|
+
name = d_indexes[:name]
|
361
|
+
end
|
362
|
+
|
363
|
+
obj = Baza::Driver::Sqlite3::Indexes::Index.new(
|
364
|
+
:table_name => self.name,
|
365
|
+
:db => @db,
|
366
|
+
:data => d_indexes
|
367
|
+
)
|
368
|
+
obj.columns << name
|
369
|
+
@indexes_list[d_indexes[:name]] = obj
|
370
|
+
end
|
371
|
+
|
372
|
+
if block_given?
|
373
|
+
yield(obj)
|
374
|
+
else
|
375
|
+
ret[d_indexes[:name]] = obj
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
if block_given?
|
380
|
+
return nil
|
381
|
+
else
|
382
|
+
return ret
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
def create_indexes(index_arr, args = nil)
|
387
|
+
if args and args[:return_sql]
|
388
|
+
ret = []
|
389
|
+
end
|
390
|
+
|
391
|
+
index_arr.each do |index_data|
|
392
|
+
if index_data.is_a?(String)
|
393
|
+
index_data = {"name" => index_data, "columns" => [index_data]}
|
394
|
+
end
|
395
|
+
|
396
|
+
raise "No name was given." if !index_data.key?("name") or index_data["name"].strip.length <= 0
|
397
|
+
raise "No columns was given on index #{index_data["name"]}." if index_data["columns"].empty?
|
398
|
+
|
399
|
+
name = index_data["name"]
|
400
|
+
name = "#{self.name}__#{name}" if @db.opts[:index_append_table_name]
|
401
|
+
|
402
|
+
sql = "CREATE INDEX '#{@db.esc_col(name)}' ON `#{@db.esc_table(self.name)}` ("
|
403
|
+
|
404
|
+
first = true
|
405
|
+
index_data["columns"].each do |col_name|
|
406
|
+
sql << ", " if !first
|
407
|
+
first = false if first
|
408
|
+
|
409
|
+
sql << "`#{@db.esc_col(col_name)}`"
|
410
|
+
end
|
411
|
+
|
412
|
+
sql << ")"
|
413
|
+
|
414
|
+
if args and args[:return_sql]
|
415
|
+
ret << sql
|
416
|
+
else
|
417
|
+
@db.query(sql)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
if args and args[:return_sql]
|
422
|
+
return ret
|
423
|
+
else
|
424
|
+
return nil
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
def data
|
429
|
+
ret = {
|
430
|
+
"name" => name,
|
431
|
+
"columns" => [],
|
432
|
+
"indexes" => []
|
433
|
+
}
|
434
|
+
|
435
|
+
columns.each do |name, column|
|
436
|
+
ret["columns"] << column.data
|
437
|
+
end
|
438
|
+
|
439
|
+
indexes.each do |name, index|
|
440
|
+
ret["indexes"] << index.data if name != "PRIMARY"
|
441
|
+
end
|
442
|
+
|
443
|
+
return ret
|
444
|
+
end
|
445
|
+
|
446
|
+
def insert(data)
|
447
|
+
@db.insert(self.name, data)
|
448
|
+
end
|
449
|
+
end
|