baza 0.0.19 → 0.0.20
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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +157 -0
- data/Gemfile +11 -9
- data/Gemfile.lock +41 -9
- data/README.md +1 -1
- data/Rakefile +19 -16
- data/VERSION +1 -1
- data/baza.gemspec +31 -7
- data/config/best_project_practice_rubocop.yml +2 -0
- data/config/best_project_practice_rubocop_todo.yml +157 -0
- data/lib/baza/base_sql_driver.rb +79 -20
- data/lib/baza/cloner.rb +2 -2
- data/lib/baza/column.rb +6 -0
- data/lib/baza/database.rb +33 -0
- data/lib/baza/database_model.rb +26 -0
- data/lib/baza/database_model_functionality.rb +10 -0
- data/lib/baza/database_model_name.rb +16 -0
- data/lib/baza/db.rb +210 -413
- data/lib/baza/dbtime.rb +20 -20
- data/lib/baza/driver.rb +3 -3
- data/lib/baza/drivers/active_record/columns.rb +1 -1
- data/lib/baza/drivers/active_record/indexes.rb +1 -1
- data/lib/baza/drivers/active_record/result.rb +3 -5
- data/lib/baza/drivers/active_record/tables.rb +2 -2
- data/lib/baza/drivers/active_record.rb +30 -16
- data/lib/baza/drivers/mysql/column.rb +51 -48
- data/lib/baza/drivers/mysql/columns.rb +8 -8
- data/lib/baza/drivers/mysql/database.rb +28 -0
- data/lib/baza/drivers/mysql/databases.rb +35 -0
- data/lib/baza/drivers/mysql/index.rb +32 -22
- data/lib/baza/drivers/mysql/result.rb +24 -24
- data/lib/baza/drivers/mysql/sqlspecs.rb +1 -1
- data/lib/baza/drivers/mysql/table.rb +80 -91
- data/lib/baza/drivers/mysql/tables.rb +30 -32
- data/lib/baza/drivers/mysql/unbuffered_result.rb +5 -5
- data/lib/baza/drivers/mysql.rb +127 -220
- data/lib/baza/drivers/mysql2/database.rb +2 -0
- data/lib/baza/drivers/mysql2/databases.rb +2 -0
- data/lib/baza/drivers/mysql2/result.rb +3 -5
- data/lib/baza/drivers/mysql2.rb +21 -106
- data/lib/baza/drivers/mysql_java/database.rb +2 -0
- data/lib/baza/drivers/mysql_java/databases.rb +2 -0
- data/lib/baza/drivers/mysql_java.rb +16 -12
- data/lib/baza/drivers/sqlite3/column.rb +33 -33
- data/lib/baza/drivers/sqlite3/columns.rb +6 -6
- data/lib/baza/drivers/sqlite3/database.rb +2 -0
- data/lib/baza/drivers/sqlite3/databases.rb +25 -0
- data/lib/baza/drivers/sqlite3/index.rb +20 -6
- data/lib/baza/drivers/sqlite3/result.rb +16 -17
- data/lib/baza/drivers/sqlite3/sqlspecs.rb +1 -1
- data/lib/baza/drivers/sqlite3/table.rb +99 -100
- data/lib/baza/drivers/sqlite3/tables.rb +30 -23
- data/lib/baza/drivers/sqlite3/unbuffered_result.rb +2 -2
- data/lib/baza/drivers/sqlite3.rb +27 -14
- data/lib/baza/drivers/sqlite3_java/database.rb +2 -0
- data/lib/baza/drivers/sqlite3_java/unbuffered_result.rb +2 -2
- data/lib/baza/drivers/sqlite3_java.rb +12 -10
- data/lib/baza/drivers/sqlite3_rhodes.rb +9 -7
- data/lib/baza/dump.rb +55 -55
- data/lib/baza/errors.rb +5 -0
- data/lib/baza/idquery.rb +25 -25
- data/lib/baza/index.rb +6 -0
- data/lib/baza/jdbc_driver.rb +6 -8
- data/lib/baza/jdbc_result.rb +1 -1
- data/lib/baza/model.rb +299 -309
- data/lib/baza/model_custom.rb +74 -72
- data/lib/baza/model_handler.rb +244 -255
- data/lib/baza/model_handler_sqlhelper.rb +122 -132
- data/lib/baza/mysql_base_driver.rb +112 -0
- data/lib/baza/query_buffer.rb +23 -23
- data/lib/baza/result_base.rb +2 -2
- data/lib/baza/revision.rb +67 -67
- data/lib/baza/row.rb +82 -84
- data/lib/baza/sqlspecs.rb +1 -1
- data/lib/baza/table.rb +31 -0
- data/lib/baza.rb +43 -10
- data/shippable.yml +1 -0
- data/spec/cloner_spec.rb +4 -4
- data/spec/drivers/active_record_mysql2_spec.rb +3 -3
- data/spec/drivers/active_record_mysql_spec.rb +2 -2
- data/spec/drivers/active_record_sqlite3_spec.rb +2 -2
- data/spec/drivers/mysql2_spec.rb +1 -0
- data/spec/drivers/mysql_spec.rb +1 -0
- data/spec/drivers/sqlite3_spec.rb +4 -5
- data/spec/info_active_record_example.rb +4 -6
- data/spec/info_active_record_mysql.rb +6 -7
- data/spec/info_active_record_mysql2.rb +2 -4
- data/spec/info_active_record_mysql2_shippable.rb +2 -4
- data/spec/info_active_record_mysql_shippable.rb +2 -4
- data/spec/info_active_record_sqlite3.rb +5 -6
- data/spec/info_mysql2_example.rb +1 -1
- data/spec/info_mysql2_shippable.rb +1 -1
- data/spec/info_mysql_example.rb +1 -1
- data/spec/info_mysql_shippable.rb +1 -1
- data/spec/info_sqlite3.rb +4 -3
- data/spec/model_handler_spec.rb +102 -115
- data/spec/spec_helper.rb +5 -5
- data/spec/support/driver_collection.rb +98 -95
- data/spec/support/driver_columns_collection.rb +18 -22
- data/spec/support/driver_databases_collection.rb +29 -0
- data/spec/support/driver_indexes_collection.rb +7 -6
- data/spec/support/driver_tables_collection.rb +38 -26
- metadata +49 -3
data/lib/baza/db.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#A wrapper of several possible database-types.
|
1
|
+
# A wrapper of several possible database-types.
|
2
2
|
#
|
3
3
|
#===Examples
|
4
4
|
# db = Baza::Db.new(type: :mysql2, db: "mysql", user: "user", pass: "password")
|
@@ -12,9 +12,9 @@
|
|
12
12
|
# print data[:name]
|
13
13
|
# end
|
14
14
|
class Baza::Db
|
15
|
-
attr_reader :sep_col, :sep_table, :sep_val, :opts, :
|
15
|
+
attr_reader :sep_col, :sep_table, :sep_val, :opts, :driver, :int_types
|
16
16
|
|
17
|
-
#Returns an array containing hashes of information about each registered driver.
|
17
|
+
# Returns an array containing hashes of information about each registered driver.
|
18
18
|
def self.drivers
|
19
19
|
path = "#{File.dirname(__FILE__)}/drivers"
|
20
20
|
drivers = []
|
@@ -34,10 +34,10 @@ class Baza::Db
|
|
34
34
|
}
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
drivers
|
38
38
|
end
|
39
39
|
|
40
|
-
#Tries to create a database-object based on the given object which could be a SQLite3 object or a MySQL 2 object (or other supported).
|
40
|
+
# Tries to create a database-object based on the given object which could be a SQLite3 object or a MySQL 2 object (or other supported).
|
41
41
|
def self.from_object(args)
|
42
42
|
args = {object: args} unless args.is_a?(Hash)
|
43
43
|
raise "No :object was given." unless args[:object]
|
@@ -47,14 +47,13 @@ class Baza::Db
|
|
47
47
|
next unless const.respond_to?(:from_object)
|
48
48
|
|
49
49
|
obj = const.from_object(args)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
50
|
+
next unless obj.is_a?(Hash) && obj[:type] == :success
|
51
|
+
if obj[:args]
|
52
|
+
new_args = obj[:args]
|
53
|
+
new_args = new_args.merge(args[:new_args]) if args[:new_args]
|
54
|
+
return Baza::Db.new(new_args)
|
55
|
+
else
|
56
|
+
raise "Didnt know what to do."
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
@@ -62,35 +61,28 @@ class Baza::Db
|
|
62
61
|
end
|
63
62
|
|
64
63
|
def initialize(opts)
|
65
|
-
@
|
66
|
-
|
64
|
+
@driver = opts.delete(:driver) if opts[:driver]
|
65
|
+
Baza.load_driver(opts.fetch(:type))
|
66
|
+
self.opts = opts unless opts.nil?
|
67
67
|
@int_types = [:int, :bigint, :tinyint, :smallint, :mediumint]
|
68
68
|
|
69
|
-
unless @opts[:threadsafe]
|
70
|
-
require 'monitor'
|
71
|
-
@mutex = Monitor.new
|
72
|
-
end
|
73
|
-
|
74
69
|
@debug = @opts[:debug]
|
70
|
+
@driver = spawn
|
71
|
+
@sep_table = @driver.sep_table
|
72
|
+
@sep_col = @driver.sep_col
|
73
|
+
@sep_val = @driver.sep_val
|
75
74
|
|
76
|
-
|
77
|
-
@sep_table = driver.sep_table
|
78
|
-
@sep_col = driver.sep_col
|
79
|
-
@sep_val = driver.sep_val
|
80
|
-
@esc_driver = driver
|
81
|
-
end
|
75
|
+
return unless block_given?
|
82
76
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
close
|
88
|
-
end
|
77
|
+
begin
|
78
|
+
yield self
|
79
|
+
ensure
|
80
|
+
close
|
89
81
|
end
|
90
82
|
end
|
91
83
|
|
92
84
|
def args
|
93
|
-
|
85
|
+
@opts
|
94
86
|
end
|
95
87
|
|
96
88
|
def opts=(arr_opts)
|
@@ -99,111 +91,63 @@ class Baza::Db
|
|
99
91
|
@opts[key.to_sym] = val
|
100
92
|
end
|
101
93
|
|
102
|
-
if RUBY_PLATFORM ==
|
94
|
+
if RUBY_PLATFORM == "java"
|
103
95
|
@opts[:type] = :sqlite3_java if @opts[:type] == :sqlite3
|
104
96
|
@opts[:type] = :mysql_java if @opts[:type] == :mysql || @opts[:type] == :mysql2
|
105
97
|
end
|
106
98
|
|
107
99
|
@type_cc = StringCases.snake_to_camel(@opts[:type])
|
108
|
-
self.connect
|
109
|
-
end
|
110
|
-
|
111
|
-
#Actually connects to the database. This is useually done automatically.
|
112
|
-
def connect
|
113
|
-
if @opts[:threadsafe]
|
114
|
-
require "#{$knjpath}threadhandler"
|
115
|
-
@conns = Knj::Threadhandler.new
|
116
|
-
|
117
|
-
@conns.on_spawn_new do
|
118
|
-
self.spawn
|
119
|
-
end
|
120
|
-
|
121
|
-
@conns.on_inactive do |data|
|
122
|
-
data[:obj].close
|
123
|
-
end
|
124
|
-
|
125
|
-
@conns.on_activate do |data|
|
126
|
-
data[:obj].reconnect
|
127
|
-
end
|
128
|
-
else
|
129
|
-
@conn = self.spawn
|
130
|
-
end
|
131
100
|
end
|
132
101
|
|
133
|
-
#Spawns a new driver (useally done automatically).
|
102
|
+
# Spawns a new driver (useally done automatically).
|
134
103
|
#===Examples
|
135
104
|
# driver_instance = db.spawn
|
136
105
|
def spawn
|
137
106
|
raise "No type given (#{@opts.keys.join(",")})." unless @opts[:type]
|
138
107
|
rpath = "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}.rb"
|
139
|
-
require rpath if File.
|
140
|
-
|
108
|
+
require rpath if File.exist?(rpath)
|
109
|
+
Baza::Driver.const_get(@type_cc).new(self)
|
141
110
|
end
|
142
111
|
|
143
|
-
#Registers a driver to the current thread.
|
112
|
+
# Registers a driver to the current thread.
|
144
113
|
def get_and_register_thread
|
145
114
|
raise "Baza-object is not in threadding mode" unless @conns
|
146
115
|
|
147
116
|
thread_cur = Thread.current
|
148
|
-
tid =
|
149
|
-
thread_cur[:baza] = {}
|
117
|
+
tid = __id__
|
118
|
+
thread_cur[:baza] = {} unless thread_cur[:baza]
|
150
119
|
|
151
120
|
if thread_cur[:baza][tid]
|
152
|
-
#An object has already been spawned - free that first to avoid endless "used" objects.
|
153
|
-
|
121
|
+
# An object has already been spawned - free that first to avoid endless "used" objects.
|
122
|
+
free_thread
|
154
123
|
end
|
155
124
|
|
156
125
|
thread_cur[:baza][tid] = @conns.get_and_lock unless thread_cur[:baza][tid]
|
157
126
|
|
158
|
-
#If block given then be ensure to free thread after yielding.
|
159
|
-
|
160
|
-
begin
|
161
|
-
yield
|
162
|
-
ensure
|
163
|
-
self.free_thread
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
#Frees the current driver from the current thread.
|
169
|
-
def free_thread
|
170
|
-
thread_cur = Thread.current
|
171
|
-
tid = self.__id__
|
127
|
+
# If block given then be ensure to free thread after yielding.
|
128
|
+
return unless block_given?
|
172
129
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
#Clean up various memory-stuff if possible.
|
181
|
-
def clean
|
182
|
-
if @conns
|
183
|
-
@conns.objects.each do |data|
|
184
|
-
data[:object].clean if data[:object].respond_to?("clean")
|
185
|
-
end
|
186
|
-
elsif @conn
|
187
|
-
@conn.clean if @conn.respond_to?("clean")
|
130
|
+
begin
|
131
|
+
yield
|
132
|
+
ensure
|
133
|
+
free_thread
|
188
134
|
end
|
189
135
|
end
|
190
136
|
|
191
|
-
#The all driver-database-connections.
|
137
|
+
# The all driver-database-connections.
|
192
138
|
def close
|
193
|
-
@
|
194
|
-
@
|
195
|
-
|
196
|
-
@conn = nil
|
197
|
-
@conns = nil
|
198
|
-
|
139
|
+
@driver.close if @driver
|
140
|
+
@driver = nil
|
199
141
|
@closed = true
|
200
142
|
end
|
201
143
|
|
144
|
+
# rubocop:disable Style/TrivialAccessors
|
202
145
|
def closed?
|
146
|
+
# rubocop:enable Style/TrivialAccessors
|
203
147
|
@closed
|
204
148
|
end
|
205
149
|
|
206
|
-
#Clones the current database-connection with possible extra arguments.
|
150
|
+
# Clones the current database-connection with possible extra arguments.
|
207
151
|
def clone_conn(args = {})
|
208
152
|
conn = Baza::Db.new(opts = @opts.clone.merge(args))
|
209
153
|
|
@@ -221,14 +165,14 @@ class Baza::Db
|
|
221
165
|
end
|
222
166
|
|
223
167
|
COPY_TO_ALLOWED_ARGS = [:tables, :debug]
|
224
|
-
#Copies the content of the current database to another instance of Baza::Db.
|
168
|
+
# Copies the content of the current database to another instance of Baza::Db.
|
225
169
|
def copy_to(db, args = {})
|
226
170
|
debug = args[:debug]
|
227
|
-
raise "No tables given."
|
171
|
+
raise "No tables given." unless data[:tables]
|
228
172
|
|
229
173
|
data[:tables].each do |table|
|
230
174
|
table_args = nil
|
231
|
-
table_args = args[:tables][table[:name
|
175
|
+
table_args = args[:tables][table[:name]] if args && args[:tables] && args[:tables][table[:name].to_sym]
|
232
176
|
next if table_args && table_args[:skip]
|
233
177
|
table.delete(:indexes) if table.key?(:indexes) && args[:skip_indexes]
|
234
178
|
|
@@ -242,12 +186,12 @@ class Baza::Db
|
|
242
186
|
loop do
|
243
187
|
puts "Copying rows (#{limit_from}, #{limit_incr})." if debug
|
244
188
|
ins_arr = []
|
245
|
-
|
189
|
+
select(table_name, {}, limit_from: limit_from, limit_to: limit_incr) do |d_rows|
|
246
190
|
col_args = nil
|
247
191
|
|
248
192
|
if table_args && table_args[:columns]
|
249
|
-
d_rows.each do |col_name,
|
250
|
-
col_args = table_args[:columns][col_name
|
193
|
+
d_rows.each do |col_name, _col_data|
|
194
|
+
col_args = table_args[:columns][col_name] if table_args && table_args[:columns]
|
251
195
|
d_rows[col_name] = "" if col_args && col_args[:empty]
|
252
196
|
end
|
253
197
|
end
|
@@ -264,89 +208,28 @@ class Baza::Db
|
|
264
208
|
end
|
265
209
|
end
|
266
210
|
|
267
|
-
#Returns the data of this database in a hash.
|
211
|
+
# Returns the data of this database in a hash.
|
268
212
|
#===Examples
|
269
213
|
# data = db.data
|
270
214
|
# tables_hash = data['tables']
|
271
215
|
def data
|
272
216
|
tables_ret = []
|
273
|
-
tables.list
|
217
|
+
tables.list do |table|
|
274
218
|
tables_ret << table.data
|
275
219
|
end
|
276
220
|
|
277
|
-
|
278
|
-
tables: tables_ret
|
279
|
-
}
|
221
|
+
{tables: tables_ret}
|
280
222
|
end
|
281
223
|
|
282
|
-
|
283
|
-
|
284
|
-
#===Examples
|
285
|
-
# db.insert(:users, name: "John", lastname: "Doe")
|
286
|
-
# id = db.insert(:users, {name: "John", lastname: "Doe"}, return_id: true)
|
287
|
-
# sql = db.insert(:users, {name: "John", lastname: "Doe"}, return_sql: true) #=> "INSERT INTO `users` (`name`, `lastname`) VALUES ('John', 'Doe')"
|
288
|
-
def insert(tablename, arr_insert, args = nil)
|
289
|
-
sql = "INSERT INTO #{@sep_table}#{self.esc_table(tablename)}#{@sep_table}"
|
290
|
-
|
291
|
-
if !arr_insert || arr_insert.empty?
|
292
|
-
# This is the correct syntax for inserting a blank row in MySQL.
|
293
|
-
if @opts[:type].to_s.include?("mysql")
|
294
|
-
sql << " VALUES ()"
|
295
|
-
elsif @opts[:type].to_s.include?("sqlite3")
|
296
|
-
sql << " DEFAULT VALUES"
|
297
|
-
else
|
298
|
-
raise "Unknown database-type: '#{@opts[:type]}'."
|
299
|
-
end
|
300
|
-
else
|
301
|
-
sql << " ("
|
302
|
-
|
303
|
-
first = true
|
304
|
-
arr_insert.each do |key, value|
|
305
|
-
if first
|
306
|
-
first = false
|
307
|
-
else
|
308
|
-
sql << ", "
|
309
|
-
end
|
310
|
-
|
311
|
-
sql << "#{@sep_col}#{self.esc_col(key)}#{@sep_col}"
|
312
|
-
end
|
313
|
-
|
314
|
-
sql << ") VALUES ("
|
315
|
-
|
316
|
-
first = true
|
317
|
-
arr_insert.each do |key, value|
|
318
|
-
if first
|
319
|
-
first = false
|
320
|
-
else
|
321
|
-
sql << ", "
|
322
|
-
end
|
323
|
-
|
324
|
-
sql << self.sqlval(value)
|
325
|
-
end
|
326
|
-
|
327
|
-
sql << ")"
|
328
|
-
end
|
329
|
-
|
330
|
-
return sql if args && args[:return_sql]
|
331
|
-
|
332
|
-
conn_exec do |driver|
|
333
|
-
begin
|
334
|
-
driver.query(sql)
|
335
|
-
rescue => e
|
336
|
-
self.add_sql_to_error(e, sql) if @opts[:sql_to_error]
|
337
|
-
raise e
|
338
|
-
end
|
339
|
-
|
340
|
-
return driver.last_id if args && args[:return_id]
|
341
|
-
return nil
|
342
|
-
end
|
224
|
+
def insert(table_name, data, args = nil)
|
225
|
+
@driver.insert(table_name, data, args)
|
343
226
|
end
|
344
227
|
|
345
228
|
def add_sql_to_error(error, sql)
|
346
229
|
error.message << " (SQL: #{sql})"
|
347
230
|
end
|
348
231
|
|
349
|
-
#Returns the correct SQL-value for the given value. If it is a number, then just the raw number as a string will be returned. nil's will be NULL and strings will have quotes and will be escaped.
|
232
|
+
# Returns the correct SQL-value for the given value. If it is a number, then just the raw number as a string will be returned. nil's will be NULL and strings will have quotes and will be escaped.
|
350
233
|
def sqlval(val)
|
351
234
|
return @conn.sqlval(val) if @conn.respond_to?(:sqlval)
|
352
235
|
|
@@ -359,11 +242,11 @@ class Baza::Db
|
|
359
242
|
elsif val.is_a?(Time) || val.is_a?(DateTime)
|
360
243
|
return "#{@sep_val}#{Datet.in(val).dbstr}#{@sep_val}"
|
361
244
|
else
|
362
|
-
return "#{@sep_val}#{
|
245
|
+
return "#{@sep_val}#{escape(val)}#{@sep_val}"
|
363
246
|
end
|
364
247
|
end
|
365
248
|
|
366
|
-
#Simply and optimal insert multiple rows into a table in a single query. Uses the drivers functionality if supported or inserts each row manually.
|
249
|
+
# Simply and optimal insert multiple rows into a table in a single query. Uses the drivers functionality if supported or inserts each row manually.
|
367
250
|
#
|
368
251
|
#===Examples
|
369
252
|
# db.insert_multi(:users, [
|
@@ -373,9 +256,9 @@ class Baza::Db
|
|
373
256
|
def insert_multi(tablename, arr_hashes, args = nil)
|
374
257
|
return false if arr_hashes.empty?
|
375
258
|
|
376
|
-
if @
|
259
|
+
if @driver.respond_to?(:insert_multi)
|
377
260
|
if args && args[:return_sql]
|
378
|
-
res =
|
261
|
+
res = @driver.insert_multi(tablename, arr_hashes, args)
|
379
262
|
if res.is_a?(String)
|
380
263
|
return [res]
|
381
264
|
elsif res.is_a?(Array)
|
@@ -385,13 +268,11 @@ class Baza::Db
|
|
385
268
|
end
|
386
269
|
end
|
387
270
|
|
388
|
-
|
389
|
-
return driver.insert_multi(tablename, arr_hashes, args)
|
390
|
-
end
|
271
|
+
@driver.insert_multi(tablename, arr_hashes, args)
|
391
272
|
else
|
392
273
|
transaction do
|
393
274
|
arr_hashes.each do |hash|
|
394
|
-
|
275
|
+
insert(tablename, hash, args)
|
395
276
|
end
|
396
277
|
end
|
397
278
|
|
@@ -399,12 +280,12 @@ class Baza::Db
|
|
399
280
|
end
|
400
281
|
end
|
401
282
|
|
402
|
-
#Simple updates rows.
|
283
|
+
# Simple updates rows.
|
403
284
|
#
|
404
285
|
#===Examples
|
405
286
|
# db.update(:users, {name: "John"}, {lastname: "Doe"})
|
406
287
|
def update(tablename, hash_update, arr_terms = {}, args = nil)
|
407
|
-
raise "'hash_update' was not a hash: '#{hash_update.class.name}'."
|
288
|
+
raise "'hash_update' was not a hash: '#{hash_update.class.name}'." unless hash_update.is_a?(Hash)
|
408
289
|
return false if hash_update.empty?
|
409
290
|
|
410
291
|
sql = ""
|
@@ -418,27 +299,23 @@ class Baza::Db
|
|
418
299
|
sql << ", "
|
419
300
|
end
|
420
301
|
|
421
|
-
#Convert dates to valid dbstr.
|
422
|
-
value =
|
302
|
+
# Convert dates to valid dbstr.
|
303
|
+
value = date_out(value) if value.is_a?(Datet) || value.is_a?(Time)
|
423
304
|
|
424
|
-
sql << "#{@sep_col}#{
|
425
|
-
sql <<
|
305
|
+
sql << "#{@sep_col}#{escape_column(key)}#{@sep_col} = "
|
306
|
+
sql << sqlval(value)
|
426
307
|
end
|
427
308
|
|
428
|
-
if arr_terms && arr_terms.length > 0
|
429
|
-
sql << " WHERE #{self.makeWhere(arr_terms)}"
|
430
|
-
end
|
309
|
+
sql << " WHERE #{makeWhere(arr_terms)}" if arr_terms && arr_terms.length > 0
|
431
310
|
|
432
311
|
return sql if args && args[:return_sql]
|
433
312
|
|
434
|
-
|
435
|
-
driver.query(sql)
|
436
|
-
end
|
313
|
+
query(sql)
|
437
314
|
end
|
438
315
|
|
439
|
-
#Checks if a given terms exists. If it does, updates it to match data. If not inserts the row.
|
316
|
+
# Checks if a given terms exists. If it does, updates it to match data. If not inserts the row.
|
440
317
|
def upsert(table, data, terms, args = nil)
|
441
|
-
row =
|
318
|
+
row = single(table, terms)
|
442
319
|
|
443
320
|
if args && args[:buffer]
|
444
321
|
obj = args[:buffer]
|
@@ -454,59 +331,68 @@ class Baza::Db
|
|
454
331
|
end
|
455
332
|
|
456
333
|
SELECT_ARGS_ALLOWED_KEYS = [:limit, :limit_from, :limit_to]
|
457
|
-
#Makes a select from the given arguments: table-name, where-terms and other arguments as limits and orders. Also takes a block to avoid raping of memory.
|
334
|
+
# Makes a select from the given arguments: table-name, where-terms and other arguments as limits and orders. Also takes a block to avoid raping of memory.
|
458
335
|
def select(tablename, arr_terms = nil, args = nil, &block)
|
459
|
-
#Set up vars.
|
336
|
+
# Set up vars.
|
460
337
|
sql = ""
|
461
338
|
args_q = nil
|
462
339
|
select_sql = "*"
|
463
340
|
|
464
|
-
#Give 'cloned_ubuf' argument to 'q'-method.
|
465
|
-
if args && args[:cloned_ubuf]
|
466
|
-
args_q = {cloned_ubuf: true}
|
467
|
-
end
|
341
|
+
# Give 'cloned_ubuf' argument to 'q'-method.
|
342
|
+
args_q = {cloned_ubuf: true} if args && args[:cloned_ubuf]
|
468
343
|
|
469
|
-
#Set up IDQuery-stuff if that is given in arguments.
|
344
|
+
# Set up IDQuery-stuff if that is given in arguments.
|
470
345
|
if args && args[:idquery]
|
471
346
|
if args[:idquery] == true
|
472
347
|
select_sql = "`id`"
|
473
348
|
col = :id
|
474
349
|
else
|
475
|
-
select_sql = "`#{
|
350
|
+
select_sql = "`#{escape_column(args[:idquery])}`"
|
476
351
|
col = args[:idquery]
|
477
352
|
end
|
478
353
|
end
|
479
354
|
|
480
|
-
sql = "SELECT #{select_sql} FROM
|
355
|
+
sql = "SELECT #{select_sql} FROM"
|
481
356
|
|
482
|
-
if
|
483
|
-
sql << "
|
357
|
+
if tablename.is_a?(Array)
|
358
|
+
sql << " #{@sep_table}#{tablename.first}#{@sep_table}.#{@sep_table}#{tablename.last}#{@sep_table}"
|
359
|
+
else
|
360
|
+
sql << " #{@sep_table}#{tablename}#{@sep_table}"
|
484
361
|
end
|
485
362
|
|
486
|
-
if
|
487
|
-
|
488
|
-
|
489
|
-
end
|
363
|
+
if !arr_terms.nil? && !arr_terms.empty?
|
364
|
+
sql << " WHERE #{makeWhere(arr_terms)}"
|
365
|
+
end
|
490
366
|
|
491
|
-
|
492
|
-
|
493
|
-
|
367
|
+
unless args.nil?
|
368
|
+
sql << " ORDER BY #{args[:orderby]}" if args[:orderby]
|
369
|
+
sql << " LIMIT #{args[:limit]}" if args[:limit]
|
494
370
|
|
495
371
|
if args[:limit_from] && args[:limit_to]
|
496
|
-
|
497
|
-
|
372
|
+
begin
|
373
|
+
Float(args[:limit_from])
|
374
|
+
rescue
|
375
|
+
raise "'limit_from' was not numeric: '#{args[:limit_from]}'."
|
376
|
+
end
|
377
|
+
|
378
|
+
begin
|
379
|
+
Float(args[:limit_to])
|
380
|
+
rescue
|
381
|
+
raise "'limit_to' was not numeric: '#{args[:limit_to]}'."
|
382
|
+
end
|
383
|
+
|
498
384
|
sql << " LIMIT #{args[:limit_from]}, #{args[:limit_to]}"
|
499
385
|
end
|
500
386
|
end
|
501
387
|
|
502
|
-
#Do IDQuery if given in arguments.
|
388
|
+
# Do IDQuery if given in arguments.
|
503
389
|
if args && args[:idquery]
|
504
390
|
res = Baza::Idquery.new(db: self, table: tablename, query: sql, col: col, &block)
|
505
391
|
else
|
506
392
|
res = q(sql, args_q, &block)
|
507
393
|
end
|
508
394
|
|
509
|
-
#Return result if a block wasnt given.
|
395
|
+
# Return result if a block wasnt given.
|
510
396
|
if block
|
511
397
|
return nil
|
512
398
|
else
|
@@ -515,55 +401,52 @@ class Baza::Db
|
|
515
401
|
end
|
516
402
|
|
517
403
|
def count(tablename, arr_terms = nil)
|
518
|
-
#Set up vars.
|
404
|
+
# Set up vars.
|
519
405
|
sql = ""
|
520
406
|
args_q = nil
|
521
407
|
|
522
408
|
sql = "SELECT COUNT(*) AS count FROM #{@sep_table}#{tablename}#{@sep_table}"
|
523
409
|
|
524
|
-
if arr_terms
|
525
|
-
sql << " WHERE #{
|
410
|
+
if !arr_terms.nil? && !arr_terms.empty?
|
411
|
+
sql << " WHERE #{makeWhere(arr_terms)}"
|
526
412
|
end
|
527
413
|
|
528
|
-
|
414
|
+
q(sql).fetch.fetch(:count).to_i
|
529
415
|
end
|
530
416
|
|
531
|
-
#Returns a single row from a database.
|
417
|
+
# Returns a single row from a database.
|
532
418
|
#
|
533
419
|
#===Examples
|
534
420
|
# row = db.single(:users, lastname: "Doe")
|
535
421
|
def single(tablename, terms = nil, args = {})
|
536
|
-
|
537
|
-
|
422
|
+
# Experienced very weird memory leak if this was not done by block. Maybe bug in Ruby 1.9.2? - knj
|
423
|
+
select(tablename, terms, args.merge(limit: 1)).fetch
|
538
424
|
end
|
539
425
|
|
540
|
-
|
426
|
+
alias_method :selectsingle, :single
|
541
427
|
|
542
|
-
#Deletes rows from the database.
|
428
|
+
# Deletes rows from the database.
|
543
429
|
#
|
544
430
|
#===Examples
|
545
431
|
# db.delete(:users, {lastname: "Doe"})
|
546
432
|
def delete(tablename, arr_terms, args = nil)
|
547
433
|
sql = "DELETE FROM #{@sep_table}#{tablename}#{@sep_table}"
|
548
434
|
|
549
|
-
if arr_terms
|
550
|
-
sql << " WHERE #{
|
435
|
+
if !arr_terms.nil? && !arr_terms.empty?
|
436
|
+
sql << " WHERE #{makeWhere(arr_terms)}"
|
551
437
|
end
|
552
438
|
|
553
439
|
return sql if args && args[:return_sql]
|
554
440
|
|
555
|
-
|
556
|
-
|
557
|
-
end
|
558
|
-
|
559
|
-
return nil
|
441
|
+
query(sql)
|
442
|
+
nil
|
560
443
|
end
|
561
444
|
|
562
|
-
#Internally used to generate SQL.
|
445
|
+
# Internally used to generate SQL.
|
563
446
|
#
|
564
447
|
#===Examples
|
565
448
|
# sql = db.makeWhere({lastname: "Doe"}, driver_obj)
|
566
|
-
def makeWhere(arr_terms,
|
449
|
+
def makeWhere(arr_terms, _driver = nil)
|
567
450
|
sql = ""
|
568
451
|
|
569
452
|
first = true
|
@@ -576,63 +459,26 @@ class Baza::Db
|
|
576
459
|
|
577
460
|
if value.is_a?(Array)
|
578
461
|
raise "Array for column '#{key}' was empty." if value.empty?
|
579
|
-
values = value.map { |v| "'#{escape(v)}'" }.join(
|
462
|
+
values = value.map { |v| "'#{escape(v)}'" }.join(",")
|
580
463
|
sql << "#{@sep_col}#{key}#{@sep_col} IN (#{values})"
|
581
464
|
elsif value.is_a?(Hash)
|
582
465
|
raise "Dont know how to handle hash."
|
583
466
|
else
|
584
|
-
sql << "#{@sep_col}#{key}#{@sep_col} = #{
|
585
|
-
end
|
586
|
-
end
|
587
|
-
|
588
|
-
return sql
|
589
|
-
end
|
590
|
-
|
591
|
-
#Returns a driver-object based on the current thread and free driver-objects.
|
592
|
-
#
|
593
|
-
#===Examples
|
594
|
-
# db.conn_exec do |driver|
|
595
|
-
# str = driver.escape('something̈́')
|
596
|
-
# end
|
597
|
-
def conn_exec
|
598
|
-
raise "Call to closed database" if @closed
|
599
|
-
|
600
|
-
if tcur = Thread.current && Thread.current[:baza]
|
601
|
-
tid = self.__id__
|
602
|
-
|
603
|
-
if tcur[:baza].key?(tid)
|
604
|
-
yield(tcur[:baza][tid])
|
605
|
-
return nil
|
467
|
+
sql << "#{@sep_col}#{key}#{@sep_col} = #{sqlval(value)}"
|
606
468
|
end
|
607
469
|
end
|
608
470
|
|
609
|
-
|
610
|
-
conn = @conns.get_and_lock
|
611
|
-
|
612
|
-
begin
|
613
|
-
yield(conn)
|
614
|
-
return nil
|
615
|
-
ensure
|
616
|
-
@conns.free(conn)
|
617
|
-
end
|
618
|
-
elsif @conn
|
619
|
-
@mutex.synchronize do
|
620
|
-
yield(@conn)
|
621
|
-
return nil
|
622
|
-
end
|
623
|
-
end
|
624
|
-
|
625
|
-
raise "Could not figure out which driver to use?"
|
471
|
+
sql
|
626
472
|
end
|
627
473
|
|
628
|
-
#Executes a query and returns the result.
|
474
|
+
# Executes a query and returns the result.
|
629
475
|
#
|
630
476
|
#===Examples
|
631
477
|
# res = db.query('SELECT * FROM users')
|
632
478
|
# while data = res.fetch
|
633
479
|
# print data[:name]
|
634
480
|
# end
|
635
|
-
def query(string)
|
481
|
+
def query(string, args = nil, &block)
|
636
482
|
if @debug
|
637
483
|
print "SQL: #{string}\n"
|
638
484
|
|
@@ -642,38 +488,49 @@ class Baza::Db
|
|
642
488
|
end
|
643
489
|
end
|
644
490
|
|
645
|
-
|
646
|
-
|
647
|
-
|
491
|
+
# If the query should be executed in a new connection unbuffered.
|
492
|
+
if args && args[:cloned_ubuf]
|
493
|
+
raise "No block given." unless block
|
494
|
+
|
495
|
+
cloned_conn(clone_args: args[:clone_args]) do |cloned_conn|
|
496
|
+
return cloned_conn.query_ubuf(string, args, &block)
|
648
497
|
end
|
649
|
-
|
650
|
-
|
651
|
-
raise e
|
498
|
+
|
499
|
+
return nil
|
652
500
|
end
|
501
|
+
|
502
|
+
return query_ubuf(string, args, &block) if args && args[:type] == :unbuffered
|
503
|
+
|
504
|
+
ret = @driver.query(string)
|
505
|
+
|
506
|
+
if block && ret
|
507
|
+
ret.each(&block)
|
508
|
+
return nil
|
509
|
+
end
|
510
|
+
|
511
|
+
ret
|
653
512
|
end
|
654
513
|
|
655
|
-
|
514
|
+
alias q query
|
515
|
+
|
516
|
+
# Execute an ubuffered query and returns the result.
|
656
517
|
#
|
657
518
|
#===Examples
|
658
519
|
# db.query_ubuf('SELECT * FROM users') do |data|
|
659
520
|
# print data[:name]
|
660
521
|
# end
|
661
|
-
def query_ubuf(string, &block)
|
662
|
-
ret =
|
663
|
-
|
664
|
-
conn_exec do |driver|
|
665
|
-
ret = driver.query_ubuf(string, &block)
|
666
|
-
end
|
522
|
+
def query_ubuf(string, args = nil, &block)
|
523
|
+
ret = @driver.query_ubuf(string)
|
667
524
|
|
668
525
|
if block
|
669
526
|
ret.each(&block)
|
670
527
|
return nil
|
671
528
|
end
|
672
529
|
|
673
|
-
|
530
|
+
ret
|
674
531
|
end
|
675
532
|
|
676
|
-
#Clones the connection, executes the given block and closes the connection again.
|
533
|
+
# Clones the connection, executes the given block and closes the connection again.
|
677
534
|
#
|
678
535
|
#===Examples
|
679
536
|
# db.cloned_conn do |conn|
|
@@ -681,13 +538,9 @@ class Baza::Db
|
|
681
538
|
# print data[:name]
|
682
539
|
# end
|
683
540
|
# end
|
684
|
-
def cloned_conn(args = nil, &
|
685
|
-
clone_conn_args = {
|
686
|
-
|
687
|
-
}
|
688
|
-
|
689
|
-
clone_conn_args.merge!(args[:clone_args]) if args && args[:clone_args]
|
690
|
-
dbconn = self.clone_conn(clone_conn_args)
|
541
|
+
def cloned_conn(args = nil, &_block)
|
542
|
+
clone_conn_args = args[:clone_args] || {}
|
543
|
+
dbconn = clone_conn(clone_conn_args)
|
691
544
|
|
692
545
|
begin
|
693
546
|
yield(dbconn)
|
@@ -696,142 +549,103 @@ class Baza::Db
|
|
696
549
|
end
|
697
550
|
end
|
698
551
|
|
699
|
-
#
|
700
|
-
#
|
701
|
-
#===Examples
|
702
|
-
# db.q('SELECT * FROM users') do |data|
|
703
|
-
# print data[:name]
|
704
|
-
# end
|
705
|
-
def q(sql, args = nil, &block)
|
706
|
-
#If the query should be executed in a new connection unbuffered.
|
707
|
-
if args && args[:cloned_ubuf]
|
708
|
-
raise "No block given." unless block
|
709
|
-
|
710
|
-
self.cloned_conn(clone_args: args[:clone_args]) do |cloned_conn|
|
711
|
-
ret = cloned_conn.query_ubuf(sql)
|
712
|
-
ret.each(&block)
|
713
|
-
end
|
714
|
-
|
715
|
-
return nil
|
716
|
-
end
|
717
|
-
|
718
|
-
if args && args[:type] == :unbuffered
|
719
|
-
ret = self.query_ubuf(sql)
|
720
|
-
else
|
721
|
-
ret = self.query(sql)
|
722
|
-
end
|
723
|
-
|
724
|
-
if block
|
725
|
-
ret.each(&block)
|
726
|
-
return nil
|
727
|
-
end
|
728
|
-
|
729
|
-
return ret
|
730
|
-
end
|
731
|
-
|
732
|
-
#Yields a query-buffer and flushes at the end of the block given.
|
552
|
+
# Yields a query-buffer and flushes at the end of the block given.
|
733
553
|
def q_buffer(args = {}, &block)
|
734
554
|
Baza::QueryBuffer.new(args.merge(db: self), &block)
|
735
|
-
|
555
|
+
nil
|
736
556
|
end
|
737
557
|
|
738
|
-
#Returns the last inserted ID.
|
558
|
+
# Returns the last inserted ID.
|
739
559
|
#
|
740
560
|
#===Examples
|
741
561
|
# id = db.last_id
|
742
562
|
def last_id
|
743
|
-
|
744
|
-
return driver.last_id
|
745
|
-
end
|
563
|
+
@driver.last_id
|
746
564
|
end
|
747
565
|
|
748
|
-
#Escapes a string to be safe-to-use in a query-string.
|
566
|
+
# Escapes a string to be safe-to-use in a query-string.
|
749
567
|
#
|
750
568
|
#===Examples
|
751
569
|
# db.q("INSERT INTO users (name) VALUES ('#{db.esc('John')}')")
|
752
570
|
def escape(string)
|
753
|
-
|
571
|
+
@driver.escape(string)
|
754
572
|
end
|
755
573
|
|
756
|
-
|
574
|
+
alias_method :esc, :escape
|
757
575
|
|
758
|
-
#Escapes the given string to be used as a column.
|
759
|
-
def
|
760
|
-
|
576
|
+
# Escapes the given string to be used as a column.
|
577
|
+
def escape_column(str)
|
578
|
+
@driver.escape_column(str)
|
761
579
|
end
|
762
580
|
|
763
|
-
#Escapes the given string to be used as a table.
|
764
|
-
def
|
765
|
-
|
581
|
+
# Escapes the given string to be used as a table.
|
582
|
+
def escape_table(str)
|
583
|
+
@driver.escape_table(str)
|
766
584
|
end
|
767
585
|
|
768
|
-
|
586
|
+
def escape_database(str)
|
587
|
+
@driver.escape_database(str)
|
588
|
+
end
|
589
|
+
|
590
|
+
# Returns a string which can be used in SQL with the current driver.
|
769
591
|
#===Examples
|
770
592
|
# str = db.date_out(Time.now) #=> "2012-05-20 22:06:09"
|
771
593
|
def date_out(date_obj = Datet.new, args = {})
|
772
|
-
if @
|
773
|
-
|
774
|
-
end
|
775
|
-
|
776
|
-
return Datet.in(date_obj).dbstr(args)
|
594
|
+
return @driver.date_out(date_obj, args) if @driver.respond_to?(:date_out)
|
595
|
+
Datet.in(date_obj).dbstr(args)
|
777
596
|
end
|
778
597
|
|
779
|
-
#Takes a valid date-db-string and converts it into a Datet.
|
598
|
+
# Takes a valid date-db-string and converts it into a Datet.
|
780
599
|
#===Examples
|
781
600
|
# db.date_in('2012-05-20 22:06:09') #=> 2012-05-20 22:06:09 +0200
|
782
601
|
def date_in(date_obj)
|
783
|
-
if @
|
784
|
-
return @esc_driver.date_in(date_obj)
|
785
|
-
end
|
602
|
+
return @driver.date_in(date_obj) if @driver.respond_to?(:date_in)
|
786
603
|
|
787
|
-
|
604
|
+
Datet.in(date_obj)
|
788
605
|
end
|
789
606
|
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
db: self
|
795
|
-
)
|
796
|
-
end
|
607
|
+
def databases
|
608
|
+
require_relative "drivers/#{@opts.fetch(:type)}/databases"
|
609
|
+
@databases ||= Baza::Driver.const_get(@type_cc).const_get(:Databases).new(db: self)
|
610
|
+
end
|
797
611
|
|
798
|
-
|
612
|
+
# Returns the table-module and spawns it if it isnt already spawned.
|
613
|
+
def tables
|
614
|
+
@tables ||= Baza::Driver.const_get(@type_cc).const_get(:Tables).new(db: self)
|
799
615
|
end
|
800
616
|
|
801
|
-
#Returns the columns-module and spawns it if it isnt already spawned.
|
617
|
+
# Returns the columns-module and spawns it if it isnt already spawned.
|
802
618
|
def cols
|
803
|
-
|
804
|
-
@cols = Baza::Driver.const_get(@type_cc).const_get(:Columns).new(
|
805
|
-
db: self
|
806
|
-
)
|
807
|
-
end
|
808
|
-
|
809
|
-
return @cols
|
619
|
+
@cols || Baza::Driver.const_get(@type_cc).const_get(:Columns).new(db: self)
|
810
620
|
end
|
811
621
|
|
812
|
-
#Returns the index-module and spawns it if it isnt already spawned.
|
622
|
+
# Returns the index-module and spawns it if it isnt already spawned.
|
813
623
|
def indexes
|
814
|
-
|
815
|
-
@indexes = Baza::Driver.const_get(@type_cc).const_get(:Indexes).new(
|
816
|
-
db: self
|
817
|
-
)
|
818
|
-
end
|
819
|
-
|
820
|
-
return @indexes
|
624
|
+
@indexes ||= Baza::Driver.const_get(@type_cc).const_get(:Indexes).new(db: self)
|
821
625
|
end
|
822
626
|
|
823
|
-
#Returns the SQLSpec-module and spawns it if it isnt already spawned.
|
627
|
+
# Returns the SQLSpec-module and spawns it if it isnt already spawned.
|
824
628
|
def sqlspecs
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
629
|
+
@sqlspecs ||= Baza::Driver.const_get(@type_cc).const_get(:Sqlspecs).new(db: self)
|
630
|
+
end
|
631
|
+
|
632
|
+
def supports_multiple_databases?
|
633
|
+
if @driver.respond_to?(:supports_multiple_databases?)
|
634
|
+
@driver.supports_multiple_databases?
|
635
|
+
else
|
636
|
+
false
|
829
637
|
end
|
638
|
+
end
|
830
639
|
|
831
|
-
|
640
|
+
def supports_type_translation?
|
641
|
+
if @driver.respond_to?(:supports_type_translation?)
|
642
|
+
@driver.supports_multiple_databases?
|
643
|
+
else
|
644
|
+
false
|
645
|
+
end
|
832
646
|
end
|
833
647
|
|
834
|
-
#Beings a transaction and commits when the block ends.
|
648
|
+
# Beings a transaction and commits when the block ends.
|
835
649
|
#
|
836
650
|
#===Examples
|
837
651
|
# db.transaction do |db|
|
@@ -839,14 +653,11 @@ class Baza::Db
|
|
839
653
|
# db.insert(:users, name: "Kasper")
|
840
654
|
# end
|
841
655
|
def transaction(&block)
|
842
|
-
|
843
|
-
|
844
|
-
end
|
845
|
-
|
846
|
-
return nil
|
656
|
+
@driver.transaction(&block)
|
657
|
+
nil
|
847
658
|
end
|
848
659
|
|
849
|
-
#Optimizes all tables in the database.
|
660
|
+
# Optimizes all tables in the database.
|
850
661
|
def optimize(args = nil)
|
851
662
|
STDOUT.puts "Beginning optimization of database." if @debug || (args && args[:debug])
|
852
663
|
tables.list do |table|
|
@@ -854,25 +665,11 @@ class Baza::Db
|
|
854
665
|
table.optimize
|
855
666
|
end
|
856
667
|
|
857
|
-
|
858
|
-
end
|
859
|
-
|
860
|
-
#Proxies the method to the driver.
|
861
|
-
#
|
862
|
-
#===Examples
|
863
|
-
# db.method_on_driver
|
864
|
-
def method_missing(method_name, *args)
|
865
|
-
conn_exec do |driver|
|
866
|
-
if driver.respond_to?(method_name.to_sym)
|
867
|
-
return driver.send(method_name, *args)
|
868
|
-
end
|
869
|
-
end
|
870
|
-
|
871
|
-
raise "Method not found: '#{method_name}'."
|
668
|
+
nil
|
872
669
|
end
|
873
670
|
|
874
671
|
def to_s
|
875
|
-
"#<Baza::Db driver
|
672
|
+
"#<Baza::Db driver=\"#{@opts[:type]}\">"
|
876
673
|
end
|
877
674
|
|
878
675
|
def inspect
|