knjrbfw 0.0.110 → 0.0.111

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +2 -2
  4. data/VERSION +1 -1
  5. data/knjrbfw.gemspec +8 -36
  6. data/lib/knj/autoload.rb +1 -2
  7. data/lib/knj/gtk2_window.rb +7 -7
  8. data/lib/knj/unix_proc.rb +35 -35
  9. metadata +33 -62
  10. data/lib/knj/db.rb +0 -1
  11. data/lib/knj/knjdb/dbtime.rb +0 -35
  12. data/lib/knj/knjdb/drivers/mysql/knjdb_mysql.rb +0 -604
  13. data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_columns.rb +0 -155
  14. data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_indexes.rb +0 -69
  15. data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_sqlspecs.rb +0 -5
  16. data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_tables.rb +0 -443
  17. data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3.rb +0 -184
  18. data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_columns.rb +0 -177
  19. data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_indexes.rb +0 -29
  20. data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_sqlspecs.rb +0 -5
  21. data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_tables.rb +0 -449
  22. data/lib/knj/knjdb/dump.rb +0 -122
  23. data/lib/knj/knjdb/idquery.rb +0 -109
  24. data/lib/knj/knjdb/libknjdb.rb +0 -797
  25. data/lib/knj/knjdb/libknjdb_java_sqlite3.rb +0 -83
  26. data/lib/knj/knjdb/libknjdb_row.rb +0 -153
  27. data/lib/knj/knjdb/libknjdb_sqlite3_ironruby.rb +0 -69
  28. data/lib/knj/knjdb/query_buffer.rb +0 -87
  29. data/lib/knj/knjdb/revision.rb +0 -342
  30. data/lib/knj/knjdb/sqlspecs.rb +0 -5
  31. data/lib/knj/objects.rb +0 -957
  32. data/lib/knj/process.rb +0 -480
  33. data/lib/knj/process_meta.rb +0 -569
  34. data/spec/db_spec.rb +0 -282
  35. data/spec/db_spec_encoding_test_file.txt +0 -1
  36. data/spec/objects_spec.rb +0 -394
  37. data/spec/process_meta_spec.rb +0 -172
  38. data/spec/process_spec.rb +0 -115
@@ -1,122 +0,0 @@
1
- #This class can be used to make SQL-dumps of databases, tables or however you want it.
2
- class Knj::Db::Dump
3
- #Constructor.
4
- #===Examples
5
- # dump = Knj::Db::Dump.new(:db => db)
6
- def initialize(args)
7
- @args = args
8
- @debug = @args[:debug]
9
- end
10
-
11
- #Method used to update the status.
12
- def update_status
13
- return nil if !@on_status
14
- rows_count = Knj::Locales.number_out(@rows_count, 0)
15
- rows_count_total = Knj::Locales.number_out(@rows_count_total, 0)
16
- percent = (@rows_count.to_f / @rows_count_total.to_f) * 100
17
- percent_text = Knj::Locales.number_out(percent, 1)
18
- @on_status.call(:text => "Dumping table: '#{@table_obj.name}' (#{rows_count}/#{rows_count_total} - #{percent_text}%).")
19
- end
20
-
21
- #Dumps all tables into the given IO.
22
- def dump(io)
23
- print "Going through tables.\n" if @debug
24
- @rows_count = 0
25
-
26
- if @args[:tables]
27
- tables = @args[:tables]
28
- else
29
- tables = @args[:db].tables.list.values
30
- end
31
-
32
- if @on_status
33
- @on_status.call(:text => "Preparing.")
34
-
35
- @rows_count_total = 0
36
- tables.each do |table_obj|
37
- @rows_count_total += table_obj.rows_count
38
- end
39
- end
40
-
41
- tables.each do |table_obj|
42
- table_obj = @args[:db].tables[table_obj] if table_obj.is_a?(String) or table_obj.is_a?(Symbol)
43
- next if table_obj.native?
44
-
45
- #Figure out keys.
46
- @keys = []
47
- table_obj.columns do |col|
48
- @keys << col.name
49
- end
50
-
51
- @table_obj = table_obj
52
- self.update_status
53
- print "Dumping table: '#{table_obj.name}'.\n" if @debug
54
- self.dump_table(io, table_obj)
55
- end
56
- end
57
-
58
- #A block can be executed when a new status occurs.
59
- def on_status(&block)
60
- @on_status = block
61
- end
62
-
63
- #Dumps the given table into the given IO.
64
- def dump_table(io, table_obj)
65
- #Get SQL for creating table and add it to IO.
66
- sqls = @args[:db].tables.create(table_obj.name, table_obj.data, :return_sql => true)
67
- sqls.each do |sql|
68
- io.write("#{sql};\n")
69
- end
70
-
71
-
72
- #Try to find a primary column in the table.
73
- prim_col = nil
74
- table_obj.columns do |col|
75
- if col.primarykey?
76
- prim_col = col
77
- break
78
- end
79
- end
80
-
81
-
82
- #Set up rows and way to fill rows.
83
- rows = []
84
- block_data = proc do |row|
85
- rows << row
86
- @rows_count += 1
87
-
88
- if rows.length >= 1000
89
- self.update_status
90
- self.dump_insert_multi(io, table_obj, rows)
91
- end
92
- end
93
-
94
-
95
- #If a primary column is found then use IDQuery. Otherwise use cloned unbuffered query.
96
- args = {:idquery => prim_col.name.to_sym} if prim_col
97
-
98
-
99
- #Clone the connecting with array-results and execute query.
100
- @args[:db].clone_conn(:result => "array") do |db|
101
- db.select(table_obj.name, nil, args, &block_data)
102
- end
103
-
104
-
105
- #Dump the last rows if any.
106
- self.dump_insert_multi(io, table_obj, rows) if !rows.empty?
107
- end
108
-
109
- #Dumps the given rows from the given table into the given IO.
110
- def dump_insert_multi(io, table_obj, rows)
111
- print "Inserting #{rows.length} into #{table_obj.name}.\n" if @debug
112
- sqls = @args[:db].insert_multi(table_obj.name, rows, :return_sql => true, :keys => @keys)
113
- sqls.each do |sql|
114
- io.write("#{sql};\n")
115
- end
116
-
117
- rows.clear
118
-
119
- #Ensure garbage collection or we might start using A LOT of memory.
120
- GC.start
121
- end
122
- end
@@ -1,109 +0,0 @@
1
- #This class takes a lot of IDs and runs a query against them.
2
- class Knj::Db::Idquery
3
- #An array containing all the IDs that will be looked up.
4
- attr_reader :ids
5
-
6
- #Constructor.
7
- #===Examples
8
- # idq = Knj::Db::Idquery(:db => db, :table => :users)
9
- # idq.ids + [1, 5, 9]
10
- # idq.each do |user|
11
- # print "Name: #{user[:name]}\n"
12
- # end
13
- def initialize(args, &block)
14
- @args = args
15
- @ids = []
16
- @debug = @args[:debug]
17
-
18
- if @args[:query]
19
- @args[:db].q(@args[:query]) do |data|
20
- @args[:col] = data.keys.first if !@args[:col]
21
-
22
- if data.is_a?(Array)
23
- @ids << data.first
24
- else
25
- @ids << data[@args[:col]]
26
- end
27
- end
28
- end
29
-
30
- @args[:col] = :id if !@args[:col]
31
- @args[:size] = 200 if !@args[:size]
32
-
33
- if block
34
- raise "No query was given but a block was." if !@args[:query]
35
- self.each(&block)
36
- end
37
- end
38
-
39
- #Fetches results.
40
- #===Examples
41
- # data = idq.fetch #=> Hash
42
- def fetch
43
- return nil if !@args
44
-
45
- if @res
46
- data = @res.fetch if @res
47
- @res = nil if !data
48
- return data if data
49
- end
50
-
51
- @res = new_res if !@res
52
- if !@res
53
- destroy
54
- return nil
55
- end
56
-
57
- data = @res.fetch
58
- if !data
59
- destroy
60
- return nil
61
- end
62
-
63
- return data
64
- end
65
-
66
- #Yields a block for every result.
67
- #===Examples
68
- # idq.each do |data|
69
- # print "Name: #{data[:name]}\n"
70
- # end
71
- def each
72
- while data = self.fetch
73
- yield(data)
74
- end
75
- end
76
-
77
- private
78
-
79
- #Spawns a new database-result to read from.
80
- def new_res
81
- table_esc = "`#{@args[:db].esc_table(@args[:table])}`"
82
- col_esc = "`#{@args[:db].esc_col(@args[:col])}`"
83
- ids = @ids.shift(@args[:size])
84
-
85
- if ids.empty?
86
- destroy
87
- return nil
88
- end
89
-
90
- ids_sql = Knj::ArrayExt.join(
91
- :arr => ids,
92
- :callback => proc{|val| @args[:db].esc(val)},
93
- :sep => ",",
94
- :surr => "'"
95
- )
96
-
97
- query_str = "SELECT * FROM #{table_esc} WHERE #{table_esc}.#{col_esc} IN (#{ids_sql})"
98
- print "Query: #{query_str}\n" if @debug
99
-
100
- return @args[:db].q(query_str)
101
- end
102
-
103
- #Removes all variables on the object. This is done when no more results are available.
104
- def destroy
105
- @args = nil
106
- @ids = nil
107
- @debug = nil
108
- end
109
- end
@@ -1,797 +0,0 @@
1
- Knj.gem_require([:wref, :datet])
2
-
3
- #A wrapper of several possible database-types.
4
- #
5
- #===Examples
6
- # db = Knj::Db.new(:type => "mysql", :subtype => "mysql2", :db => "mysql", :user => "user", :pass => "password")
7
- # mysql_table = db.tables['mysql']
8
- # name = mysql_table.name
9
- # cols = mysql_table.columns
10
- #
11
- # db = Knj::Db.new(:type => "sqlite3", :path => "some_db.sqlite3")
12
- #
13
- # db.q("SELECT * FROM users") do |data|
14
- # print data[:name]
15
- # end
16
- class Knj::Db
17
- #Autoloader for subclasses..
18
- def self.const_missing(name)
19
- require "#{$knjpath}knjdb/#{name.to_s.downcase}.rb"
20
- raise "Still not defined: '#{name}'." if !Knj::Db.const_defined?(name)
21
- return Knj::Db.const_get(name)
22
- end
23
-
24
- attr_reader :sep_col, :sep_table, :sep_val, :opts, :conn, :conns, :int_types
25
-
26
- def initialize(opts)
27
- require "#{$knjpath}threadhandler"
28
-
29
- self.setOpts(opts) if opts != nil
30
-
31
- @int_types = ["int", "bigint", "tinyint", "smallint", "mediumint"]
32
-
33
- if !@opts[:threadsafe]
34
- require "monitor"
35
- @mutex = Monitor.new
36
- end
37
-
38
- @debug = @opts[:debug]
39
-
40
- self.conn_exec do |driver|
41
- @sep_table = driver.sep_table
42
- @sep_col = driver.sep_col
43
- @sep_val = driver.sep_val
44
- @esc_driver = driver
45
- end
46
- end
47
-
48
- def args
49
- return @opts
50
- end
51
-
52
- def setOpts(arr_opts)
53
- @opts = {}
54
- arr_opts.each do |key, val|
55
- @opts[key.to_sym] = val
56
- end
57
-
58
- if RUBY_PLATFORM == "java"
59
- @opts[:subtype] = "java"
60
- elsif @opts[:type] == "sqlite3" and RUBY_PLATFORM.index("mswin32") != nil
61
- @opts[:subtype] = "ironruby"
62
- end
63
-
64
- self.connect
65
- end
66
-
67
- #Actually connects to the database. This is useually done automatically.
68
- def connect
69
- if @opts[:threadsafe]
70
- @conns = Knj::Threadhandler.new
71
-
72
- @conns.on_spawn_new do
73
- self.spawn
74
- end
75
-
76
- @conns.on_inactive do |data|
77
- data[:obj].close
78
- end
79
-
80
- @conns.on_activate do |data|
81
- data[:obj].reconnect
82
- end
83
- else
84
- @conn = self.spawn
85
- end
86
- end
87
-
88
- #Spawns a new driver (useally done automatically).
89
- #===Examples
90
- # driver_instance = db.spawn
91
- def spawn
92
- raise "No type given (#{@opts.keys.join(",")})." if !@opts[:type]
93
-
94
- fpaths = [
95
- "drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}.rb",
96
- "libknjdb_#{@opts[:type]}.rb"
97
- ]
98
- fpaths.each do |fpath|
99
- rpath = "#{File.dirname(__FILE__)}/#{fpath}"
100
-
101
- if (!@opts.key?(:require) or @opts[:require]) and File.exists?(rpath)
102
- require rpath
103
- break
104
- end
105
- end
106
-
107
- return Kernel.const_get("KnjDB_#{@opts[:type]}").new(self)
108
- end
109
-
110
- #Registers a driver to the current thread.
111
- def get_and_register_thread
112
- raise "KnjDB-object is not in threadding mode." if !@conns
113
-
114
- thread_cur = Thread.current
115
- tid = self.__id__
116
- thread_cur[:knjdb] = {} if !thread_cur[:knjdb]
117
-
118
- if thread_cur[:knjdb][tid]
119
- #An object has already been spawned - free that first to avoid endless "used" objects.
120
- self.free_thread
121
- end
122
-
123
- thread_cur[:knjdb][tid] = @conns.get_and_lock if !thread_cur[:knjdb][tid]
124
-
125
- #If block given then be ensure to free thread after yielding.
126
- if block_given?
127
- begin
128
- yield
129
- ensure
130
- self.free_thread
131
- end
132
- end
133
- end
134
-
135
- #Frees the current driver from the current thread.
136
- def free_thread
137
- thread_cur = Thread.current
138
- tid = self.__id__
139
-
140
- if thread_cur[:knjdb] and thread_cur[:knjdb].key?(tid)
141
- db = thread_cur[:knjdb][tid]
142
- thread_cur[:knjdb].delete(tid)
143
- @conns.free(db) if @conns
144
- end
145
- end
146
-
147
- #Clean up various memory-stuff if possible.
148
- def clean
149
- if @conns
150
- @conns.objects.each do |data|
151
- data[:object].clean if data[:object].respond_to?("clean")
152
- end
153
- elsif @conn
154
- @conn.clean if @conn.respond_to?("clean")
155
- end
156
- end
157
-
158
- #The all driver-database-connections.
159
- def close
160
- @conn.close if @conn
161
- @conns.destroy if @conns
162
-
163
- @conn = nil
164
- @conns = nil
165
- end
166
-
167
- #Clones the current database-connection with possible extra arguments.
168
- def clone_conn(args = {})
169
- conn = Knj::Db.new(@opts.clone.merge(args))
170
-
171
- if block_given?
172
- begin
173
- yield(conn)
174
- ensure
175
- conn.close
176
- end
177
-
178
- return nil
179
- else
180
- return conn
181
- end
182
- end
183
-
184
- #Copies the content of the current database to another instance of Knj::Db.
185
- def copy_to(db, args = {})
186
- data["tables"].each do |table|
187
- table_args = nil
188
- table_args = args["tables"][table["name"].to_s] if args and args["tables"] and args["tables"][table["name"].to_s]
189
- next if table_args and table_args["skip"]
190
- table.delete("indexes") if table.key?("indexes") and args["skip_indexes"]
191
- db.tables.create(table["name"], table)
192
-
193
- limit_from = 0
194
- limit_incr = 1000
195
-
196
- loop do
197
- ins_arr = []
198
- q_rows = self.select(table["name"], {}, {"limit_from" => limit_from, "limit_to" => limit_incr})
199
- while d_rows = q_rows.fetch
200
- col_args = nil
201
-
202
- if table_args and table_args["columns"]
203
- d_rows.each do |col_name, col_data|
204
- col_args = table_args["columns"][col_name.to_s] if table_args and table_args["columns"]
205
- d_rows[col_name] = "" if col_args and col_args["empty"]
206
- end
207
- end
208
-
209
- ins_arr << d_rows
210
- end
211
-
212
- break if ins_arr.empty?
213
-
214
- db.insert_multi(table["name"], ins_arr)
215
- limit_from += limit_incr
216
- end
217
- end
218
- end
219
-
220
- #Returns the data of this database in a hash.
221
- #===Examples
222
- # data = db.data
223
- # tables_hash = data['tables']
224
- def data
225
- tables_ret = []
226
- tables.list.each do |name, table|
227
- tables_ret << table.data
228
- end
229
-
230
- return {
231
- "tables" => tables_ret
232
- }
233
- end
234
-
235
- #Simply inserts data into a table.
236
- #
237
- #===Examples
238
- # db.insert(:users, {:name => "John", :lastname => "Doe"})
239
- # id = db.insert(:users, {:name => "John", :lastname => "Doe"}, :return_id => true)
240
- # sql = db.insert(:users, {:name => "John", :lastname => "Doe"}, :return_sql => true) #=> "INSERT INTO `users` (`name`, `lastname`) VALUES ('John', 'Doe')"
241
- def insert(tablename, arr_insert, args = nil)
242
- sql = "INSERT INTO #{@sep_table}#{tablename}#{@sep_table}"
243
-
244
- if !arr_insert or arr_insert.empty?
245
- #This is the correct syntax for inserting a blank row in MySQL.
246
- if @opts[:type].to_s == "mysql"
247
- sql << " VALUES ()"
248
- elsif @opts[:type].to_s == "sqlite3"
249
- sql << " DEFAULT VALUES"
250
- else
251
- raise "Unknown database-type: '#{@opts[:type]}'."
252
- end
253
- else
254
- sql << " ("
255
-
256
- first = true
257
- arr_insert.each do |key, value|
258
- if first
259
- first = false
260
- else
261
- sql << ", "
262
- end
263
-
264
- sql << "#{@sep_col}#{key}#{@sep_col}"
265
- end
266
-
267
- sql << ") VALUES ("
268
-
269
- first = true
270
- arr_insert.each do |key, value|
271
- if first
272
- first = false
273
- else
274
- sql << ", "
275
- end
276
-
277
- sql << self.sqlval(value)
278
- end
279
-
280
- sql << ")"
281
- end
282
-
283
- return sql if args and args[:return_sql]
284
-
285
- self.conn_exec do |driver|
286
- driver.query(sql)
287
- return driver.lastID if args and args[:return_id]
288
- return nil
289
- end
290
- end
291
-
292
- #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.
293
- def sqlval(val)
294
- return @conn.sqlval(val) if @conn.respond_to?(:sqlval)
295
-
296
- if val.is_a?(Fixnum) or val.is_a?(Integer)
297
- return val.to_s
298
- elsif val == nil
299
- return "NULL"
300
- elsif val.is_a?(Date)
301
- return "#{@sep_val}#{Datet.in(val).dbstr(:time => false)}#{@sep_val}"
302
- elsif val.is_a?(Time) or val.is_a?(DateTime)
303
- return "#{@sep_val}#{Datet.in(val).dbstr}#{@sep_val}"
304
- else
305
- return "#{@sep_val}#{self.escape(val)}#{@sep_val}"
306
- end
307
- end
308
-
309
- #Simply and optimal insert multiple rows into a table in a single query. Uses the drivers functionality if supported or inserts each row manually.
310
- #
311
- #===Examples
312
- # db.insert_multi(:users, [
313
- # {:name => "John", :lastname => "Doe"},
314
- # {:name => "Kasper", :lastname => "Johansen"}
315
- # ])
316
- def insert_multi(tablename, arr_hashes, args = nil)
317
- return false if arr_hashes.empty?
318
-
319
- if @esc_driver.respond_to?(:insert_multi)
320
- if args and args[:return_sql]
321
- return [@esc_driver.insert_multi(tablename, arr_hashes, args)]
322
- end
323
-
324
- self.conn_exec do |driver|
325
- return driver.insert_multi(tablename, arr_hashes, args)
326
- end
327
- else
328
- ret = [] if args and (args[:return_id] or args[:return_sql])
329
- arr_hashes.each do |hash|
330
- if ret
331
- ret << self.insert(tablename, hash, args)
332
- else
333
- self.insert(tablename, hash, args)
334
- end
335
- end
336
-
337
- if ret
338
- return ret
339
- else
340
- return nil
341
- end
342
- end
343
- end
344
-
345
- #Simple updates rows.
346
- #
347
- #===Examples
348
- # db.update(:users, {:name => "John"}, {:lastname => "Doe"})
349
- def update(tablename, arr_update, arr_terms = {}, args = nil)
350
- raise "'arr_update' was not a hash." if !arr_update.is_a?(Hash)
351
- return false if arr_update.empty?
352
-
353
- sql = ""
354
- sql << "UPDATE #{@sep_col}#{tablename}#{@sep_col} SET "
355
-
356
- first = true
357
- arr_update.each do |key, value|
358
- if first
359
- first = false
360
- else
361
- sql << ", "
362
- end
363
-
364
- #Convert dates to valid dbstr.
365
- value = self.date_out(value) if value.is_a?(Datet) or value.is_a?(Time)
366
-
367
- sql << "#{@sep_col}#{key}#{@sep_col} = "
368
- sql << "#{@sep_val}#{@esc_driver.escape(value)}#{@sep_val}"
369
- end
370
-
371
- if arr_terms and arr_terms.length > 0
372
- sql << " WHERE #{self.makeWhere(arr_terms)}"
373
- end
374
-
375
- return sql if args and args[:return_sql]
376
-
377
- self.conn_exec do |driver|
378
- driver.query(sql)
379
- end
380
- end
381
-
382
- #Checks if a given selector exists. If it does, updates it to match data. If not inserts the row.
383
- def upsert(table, selector, data)
384
- row = self.select(table, selector, "limit" => 1).fetch
385
-
386
- if row
387
- self.update(table, data, row)
388
- else
389
- self.insert(table, selector.merge(data))
390
- end
391
- end
392
-
393
- #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.
394
- def select(tablename, arr_terms = nil, args = nil, &block)
395
- #Set up vars.
396
- sql = ""
397
- args_q = nil
398
- select_sql = "*"
399
-
400
- #Give 'cloned_ubuf' argument to 'q'-method.
401
- if args and args[:cloned_ubuf]
402
- args_q = {:cloned_ubuf => true}
403
- end
404
-
405
- #Set up IDQuery-stuff if that is given in arguments.
406
- if args and args[:idquery]
407
- if args[:idquery] == true
408
- select_sql = "`id`"
409
- col = :id
410
- else
411
- select_sql = "`#{self.esc_col(args[:idquery])}`"
412
- col = args[:idquery]
413
- end
414
- end
415
-
416
- sql = "SELECT #{select_sql} FROM #{@sep_table}#{tablename}#{@sep_table}"
417
-
418
- if arr_terms != nil and !arr_terms.empty?
419
- sql << " WHERE #{self.makeWhere(arr_terms)}"
420
- end
421
-
422
- if args != nil
423
- if args["orderby"]
424
- sql << " ORDER BY #{args["orderby"]}"
425
- end
426
-
427
- if args["limit"]
428
- sql << " LIMIT #{args["limit"]}"
429
- end
430
-
431
- if args["limit_from"] and args["limit_to"]
432
- raise "'limit_from' was not numeric: '#{args["limit_from"]}'." if !(Float(args["limit_from"]) rescue false)
433
- raise "'limit_to' was not numeric: '#{args["limit_to"]}'." if !(Float(args["limit_to"]) rescue false)
434
- sql << " LIMIT #{args["limit_from"]}, #{args["limit_to"]}"
435
- end
436
- end
437
-
438
- #Do IDQuery if given in arguments.
439
- if args and args[:idquery]
440
- res = Knj::Db::Idquery.new(:db => self, :table => tablename, :query => sql, :col => col, &block)
441
- else
442
- res = self.q(sql, args_q, &block)
443
- end
444
-
445
- #Return result if a block wasnt given.
446
- if block
447
- return nil
448
- else
449
- return res
450
- end
451
- end
452
-
453
- #Returns a single row from a database.
454
- #
455
- #===Examples
456
- # row = db.single(:users, {:lastname => "Doe"})
457
- def single(tablename, arr_terms = nil, args = {})
458
- args["limit"] = 1
459
-
460
- #Experienced very weird memory leak if this was not done by block. Maybe bug in Ruby 1.9.2? - knj
461
- self.select(tablename, arr_terms, args) do |data|
462
- return data
463
- end
464
-
465
- return false
466
- end
467
-
468
- alias :selectsingle :single
469
-
470
- #Deletes rows from the database.
471
- #
472
- #===Examples
473
- # db.delete(:users, {:lastname => "Doe"})
474
- def delete(tablename, arr_terms, args = nil)
475
- sql = "DELETE FROM #{@sep_table}#{tablename}#{@sep_table}"
476
-
477
- if arr_terms != nil and !arr_terms.empty?
478
- sql << " WHERE #{self.makeWhere(arr_terms)}"
479
- end
480
-
481
- return sql if args and args[:return_sql]
482
-
483
- self.conn_exec do |driver|
484
- driver.query(sql)
485
- end
486
-
487
- return nil
488
- end
489
-
490
- #Internally used to generate SQL.
491
- #
492
- #===Examples
493
- # sql = db.makeWhere({:lastname => "Doe"}, driver_obj)
494
- def makeWhere(arr_terms, driver = nil)
495
- sql = ""
496
-
497
- first = true
498
- arr_terms.each do |key, value|
499
- if first
500
- first = false
501
- else
502
- sql << " AND "
503
- end
504
-
505
- if value.is_a?(Array)
506
- raise "Array for column '#{key}' was empty." if value.empty?
507
- sql << "#{@sep_col}#{key}#{@sep_col} IN (#{Knj::ArrayExt.join(:arr => value, :sep => ",", :surr => "'", :callback => proc{|ele| self.esc(ele)})})"
508
- elsif value.is_a?(Hash)
509
- raise "Dont know how to handle hash."
510
- else
511
- sql << "#{@sep_col}#{key}#{@sep_col} = #{@sep_val}#{@esc_driver.escape(value)}#{@sep_val}"
512
- end
513
- end
514
-
515
- return sql
516
- end
517
-
518
- #Returns a driver-object based on the current thread and free driver-objects.
519
- #
520
- #===Examples
521
- # db.conn_exec do |driver|
522
- # str = driver.escape('something̈́')
523
- # end
524
- def conn_exec
525
- if tcur = Thread.current and tcur[:knjdb]
526
- tid = self.__id__
527
-
528
- if tcur[:knjdb].key?(tid)
529
- yield(tcur[:knjdb][tid])
530
- return nil
531
- end
532
- end
533
-
534
- if @conns
535
- conn = @conns.get_and_lock
536
-
537
- begin
538
- yield(conn)
539
- return nil
540
- ensure
541
- @conns.free(conn)
542
- end
543
- elsif @conn
544
- @mutex.synchronize do
545
- yield(@conn)
546
- return nil
547
- end
548
- end
549
-
550
- raise "Could not figure out how to find a driver to use?"
551
- end
552
-
553
- #Executes a query and returns the result.
554
- #
555
- #===Examples
556
- # res = db.query('SELECT * FROM users')
557
- # while data = res.fetch
558
- # print data[:name]
559
- # end
560
- def query(string)
561
- if @debug
562
- print "SQL: #{string}\n"
563
-
564
- if @debug.is_a?(Fixnum) and @debug >= 2
565
- print caller.join("\n")
566
- print "\n"
567
- end
568
- end
569
-
570
- self.conn_exec do |driver|
571
- return driver.query(string)
572
- end
573
- end
574
-
575
- #Execute an ubuffered query and returns the result.
576
- #
577
- #===Examples
578
- # db.query_ubuf('SELECT * FROM users') do |data|
579
- # print data[:name]
580
- # end
581
- def query_ubuf(string, &block)
582
- ret = nil
583
-
584
- self.conn_exec do |driver|
585
- ret = driver.query_ubuf(string, &block)
586
- end
587
-
588
- if block
589
- ret.each(&block)
590
- return nil
591
- end
592
-
593
- return ret
594
- end
595
-
596
- #Clones the connection, executes the given block and closes the connection again.
597
- #
598
- #===Examples
599
- # db.cloned_conn do |conn|
600
- # conn.q('SELCET * FROM users') do |data|
601
- # print data[:name]
602
- # end
603
- # end
604
- def cloned_conn(args = nil, &block)
605
- clone_conn_args = {
606
- :threadsafe => false
607
- }
608
-
609
- clone_conn_args.merge!(args[:clone_args]) if args and args[:clone_args]
610
- dbconn = self.clone_conn(clone_conn_args)
611
-
612
- begin
613
- yield(dbconn)
614
- ensure
615
- dbconn.close
616
- end
617
- end
618
-
619
- #Executes a query and returns the result. If a block is given the result is iterated over that block instead and it returns nil.
620
- #
621
- #===Examples
622
- # db.q('SELECT * FROM users') do |data|
623
- # print data[:name]
624
- # end
625
- def q(str, args = nil, &block)
626
- #If the query should be executed in a new connection unbuffered.
627
- if args
628
- if args[:cloned_ubuf]
629
- raise "No block given." if !block
630
-
631
- self.cloned_conn(:clone_args => args[:clone_args]) do |cloned_conn|
632
- ret = cloned_conn.query_ubuf(str)
633
- ret.each(&block)
634
- end
635
-
636
- return nil
637
- else
638
- raise "Invalid arguments given: '#{args}'."
639
- end
640
- end
641
-
642
- ret = self.query(str)
643
-
644
- if block
645
- ret.each(&block)
646
- return nil
647
- end
648
-
649
- return ret
650
- end
651
-
652
- #Yields a query-buffer and flushes at the end of the block given.
653
- def q_buffer(&block)
654
- Knj::Db::Query_buffer.new(:db => self, &block)
655
- return nil
656
- end
657
-
658
- #Returns the last inserted ID.
659
- #
660
- #===Examples
661
- # id = db.last_id
662
- def lastID
663
- self.conn_exec do |driver|
664
- return driver.lastID
665
- end
666
- end
667
-
668
- alias :last_id :lastID
669
-
670
- #Escapes a string to be safe-to-use in a query-string.
671
- #
672
- #===Examples
673
- # db.q("INSERT INTO users (name) VALUES ('#{db.esc('John')}')")
674
- def escape(string)
675
- return @esc_driver.escape(string)
676
- end
677
-
678
- alias :esc :escape
679
-
680
- #Escapes the given string to be used as a column.
681
- def esc_col(str)
682
- return @esc_driver.esc_col(str)
683
- end
684
-
685
- #Escapes the given string to be used as a table.
686
- def esc_table(str)
687
- return @esc_driver.esc_table(str)
688
- end
689
-
690
- #Returns a string which can be used in SQL with the current driver.
691
- #===Examples
692
- # str = db.date_out(Time.now) #=> "2012-05-20 22:06:09"
693
- def date_out(date_obj = Datet.new, args = {})
694
- if @esc_driver.respond_to?(:date_out)
695
- return @esc_driver.date_out(date_obj, args)
696
- end
697
-
698
- return Datet.in(date_obj).dbstr(args)
699
- end
700
-
701
- #Takes a valid date-db-string and converts it into a Datet.
702
- #===Examples
703
- # db.date_in('2012-05-20 22:06:09') #=> 2012-05-20 22:06:09 +0200
704
- def date_in(date_obj)
705
- if @esc_driver.respond_to?(:date_in)
706
- return @esc_driver.date_in(date_obj)
707
- end
708
-
709
- return Datet.in(date_obj)
710
- end
711
-
712
- #Returns the table-module and spawns it if it isnt already spawned.
713
- def tables
714
- if !@tables
715
- require "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}_tables" if (!@opts.key?(:require) or @opts[:require])
716
- @tables = Kernel.const_get("KnjDB_#{@opts[:type]}".to_sym).const_get(:Tables).new(
717
- :db => self
718
- )
719
- end
720
-
721
- return @tables
722
- end
723
-
724
- #Returns the columns-module and spawns it if it isnt already spawned.
725
- def cols
726
- if !@cols
727
- require "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}_columns" if (!@opts.key?(:require) or @opts[:require])
728
- @cols = Kernel.const_get("KnjDB_#{@opts[:type]}".to_sym).const_get(:Columns).new(
729
- :db => self
730
- )
731
- end
732
-
733
- return @cols
734
- end
735
-
736
- #Returns the index-module and spawns it if it isnt already spawned.
737
- def indexes
738
- if !@indexes
739
- require "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}_indexes" if (!@opts.key?(:require) or @opts[:require])
740
- @indexes = Kernel.const_get("KnjDB_#{@opts[:type]}".to_sym).const_get(:Indexes).new(
741
- :db => self
742
- )
743
- end
744
-
745
- return @indexes
746
- end
747
-
748
- #Returns the SQLSpec-module and spawns it if it isnt already spawned.
749
- def sqlspecs
750
- if !@sqlspecs
751
- require "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}_sqlspecs" if (!@opts.key?(:require) or @opts[:require])
752
- @sqlspecs = Kernel.const_get("KnjDB_#{@opts[:type]}".to_sym).const_get(:Sqlspecs).new(
753
- :db => self
754
- )
755
- end
756
-
757
- return @sqlspecs
758
- end
759
-
760
- #Beings a transaction and commits when the block ends.
761
- #
762
- #===Examples
763
- # db.transaction do |db|
764
- # db.insert(:users, {:name => "John"})
765
- # db.insert(:users, {:name => "Kasper"})
766
- # end
767
- def transaction(&block)
768
- self.conn_exec do |driver|
769
- driver.transaction(&block)
770
- end
771
- end
772
-
773
- #Optimizes all tables in the database.
774
- def optimize(args = nil)
775
- STDOUT.puts "Beginning optimization of database." if @debug or (args and args[:debug])
776
- self.tables.list do |table|
777
- STDOUT.puts "Optimizing table: '#{table.name}'." if @debug or (args and args[:debug])
778
- table.optimize
779
- end
780
-
781
- return nil
782
- end
783
-
784
- #Proxies the method to the driver.
785
- #
786
- #===Examples
787
- # db.method_on_driver
788
- def method_missing(method_name, *args)
789
- self.conn_exec do |driver|
790
- if driver.respond_to?(method_name.to_sym)
791
- return driver.send(method_name, *args)
792
- end
793
- end
794
-
795
- raise "Method not found: #{method_name}"
796
- end
797
- end