baza 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/README.rdoc +106 -1
- data/VERSION +1 -1
- data/baza.gemspec +103 -0
- data/include/db.rb +108 -29
- data/include/drivers/mysql/mysql.rb +52 -47
- data/include/drivers/mysql/mysql_columns.rb +48 -41
- data/include/drivers/mysql/mysql_indexes.rb +2 -2
- data/include/drivers/mysql/mysql_tables.rb +91 -59
- data/include/drivers/sqlite3/sqlite3.rb +66 -45
- data/include/drivers/sqlite3/sqlite3_columns.rb +41 -39
- data/include/drivers/sqlite3/sqlite3_indexes.rb +2 -2
- data/include/drivers/sqlite3/sqlite3_tables.rb +86 -54
- data/include/dump.rb +5 -2
- data/include/revision.rb +130 -90
- data/spec/baza_spec.rb +312 -263
- data/spec/info_mysql_example.rb +6 -0
- data/spec/info_sqlite3.rb +20 -0
- metadata +22 -3
@@ -2,6 +2,22 @@ class Baza::Driver::Mysql
|
|
2
2
|
attr_reader :knjdb, :conn, :conns, :sep_table, :sep_col, :sep_val
|
3
3
|
attr_accessor :tables, :cols, :indexes
|
4
4
|
|
5
|
+
#Helper to enable automatic registering of database using Baza::Db.from_object
|
6
|
+
def self.from_object(args)
|
7
|
+
if args[:object].class.name == "Mysql2::Client"
|
8
|
+
return {
|
9
|
+
:type => :success,
|
10
|
+
:args => {
|
11
|
+
:type => :mysql,
|
12
|
+
:subtype => :mysql2,
|
13
|
+
:conn => args[:object]
|
14
|
+
}
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
return nil
|
19
|
+
end
|
20
|
+
|
5
21
|
def initialize(knjdb_ob)
|
6
22
|
@knjdb = knjdb_ob
|
7
23
|
@opts = @knjdb.opts
|
@@ -26,7 +42,7 @@ class Baza::Driver::Mysql
|
|
26
42
|
|
27
43
|
@java_rs_data = {}
|
28
44
|
@subtype = @knjdb.opts[:subtype]
|
29
|
-
@subtype =
|
45
|
+
@subtype = :mysql if @subtype.to_s.empty?
|
30
46
|
self.reconnect
|
31
47
|
end
|
32
48
|
|
@@ -49,9 +65,9 @@ class Baza::Driver::Mysql
|
|
49
65
|
def reconnect
|
50
66
|
@mutex.synchronize do
|
51
67
|
case @subtype
|
52
|
-
when
|
68
|
+
when :mysql
|
53
69
|
@conn = Mysql.real_connect(@knjdb.opts[:host], @knjdb.opts[:user], @knjdb.opts[:pass], @knjdb.opts[:db], @port)
|
54
|
-
when
|
70
|
+
when :mysql2
|
55
71
|
require "rubygems"
|
56
72
|
require "mysql2"
|
57
73
|
|
@@ -79,7 +95,11 @@ class Baza::Driver::Mysql
|
|
79
95
|
tries = 0
|
80
96
|
begin
|
81
97
|
tries += 1
|
82
|
-
@conn
|
98
|
+
if @knjdb.opts[:conn]
|
99
|
+
@conn = @knjdb.opts[:conn]
|
100
|
+
else
|
101
|
+
@conn = Mysql2::Client.new(args)
|
102
|
+
end
|
83
103
|
rescue => e
|
84
104
|
if tries <= 3
|
85
105
|
if e.message == "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)"
|
@@ -90,7 +110,7 @@ class Baza::Driver::Mysql
|
|
90
110
|
|
91
111
|
raise e
|
92
112
|
end
|
93
|
-
when
|
113
|
+
when :java
|
94
114
|
if !@jdbc_loaded
|
95
115
|
require "java"
|
96
116
|
require "/usr/share/java/mysql-connector-java.jar" if File.exists?("/usr/share/java/mysql-connector-java.jar")
|
@@ -101,7 +121,7 @@ class Baza::Driver::Mysql
|
|
101
121
|
@conn = java.sql::DriverManager.getConnection("jdbc:mysql://#{@knjdb.opts[:host]}:#{@port}/#{@knjdb.opts[:db]}?user=#{@knjdb.opts[:user]}&password=#{@knjdb.opts[:pass]}&populateInsertRowWithDefaultValues=true&zeroDateTimeBehavior=round&characterEncoding=#{@encoding}&holdResultsOpenOverStatementClose=true")
|
102
122
|
self.query("SET SQL_MODE = ''")
|
103
123
|
else
|
104
|
-
raise "Unknown subtype: #{@subtype}"
|
124
|
+
raise "Unknown subtype: #{@subtype} (#{@subtype.class.name})"
|
105
125
|
end
|
106
126
|
|
107
127
|
self.query("SET NAMES '#{self.esc(@encoding)}'") if @encoding
|
@@ -118,11 +138,11 @@ class Baza::Driver::Mysql
|
|
118
138
|
tries += 1
|
119
139
|
@mutex.synchronize do
|
120
140
|
case @subtype
|
121
|
-
when
|
122
|
-
return Baza::Driver::
|
123
|
-
when
|
124
|
-
return Baza::Driver::
|
125
|
-
when
|
141
|
+
when :mysql
|
142
|
+
return Baza::Driver::Mysql::Result.new(self, @conn.query(str))
|
143
|
+
when :mysql2
|
144
|
+
return Baza::Driver::Mysql::ResultMySQL2.new(@conn.query(str, @query_args))
|
145
|
+
when :java
|
126
146
|
stmt = conn.create_statement
|
127
147
|
|
128
148
|
if str.match(/^\s*(delete|update|create|drop|insert\s+into|alter)\s+/i)
|
@@ -138,7 +158,7 @@ class Baza::Driver::Mysql
|
|
138
158
|
|
139
159
|
begin
|
140
160
|
res = stmt.execute_query(str)
|
141
|
-
ret =
|
161
|
+
ret = Baza::Driver::Mysql::ResultJava.new(@knjdb, @opts, res)
|
142
162
|
id = ret.__id__
|
143
163
|
|
144
164
|
#If ID is being reused we have to free the result.
|
@@ -180,12 +200,12 @@ class Baza::Driver::Mysql
|
|
180
200
|
def query_ubuf(str)
|
181
201
|
@mutex.synchronize do
|
182
202
|
case @subtype
|
183
|
-
when
|
203
|
+
when :mysql
|
184
204
|
@conn.query_with_result = false
|
185
|
-
return Baza::Driver::
|
186
|
-
when
|
187
|
-
return Baza::Driver::
|
188
|
-
when
|
205
|
+
return Baza::Driver::Mysql::ResultUnbuffered.new(@conn, @opts, @conn.query(str))
|
206
|
+
when :mysql2
|
207
|
+
return Baza::Driver::Mysql::ResultMySQL2.new(@conn.query(str, @query_args.merge(:stream => true)))
|
208
|
+
when :java
|
189
209
|
if str.match(/^\s*(delete|update|create|drop|insert\s+into)\s+/i)
|
190
210
|
stmt = @conn.createStatement
|
191
211
|
|
@@ -202,7 +222,7 @@ class Baza::Driver::Mysql
|
|
202
222
|
|
203
223
|
begin
|
204
224
|
res = stmt.executeQuery(str)
|
205
|
-
ret =
|
225
|
+
ret = Baza::Driver::Mysql::ResultJava.new(@knjdb, @opts, res)
|
206
226
|
|
207
227
|
#Save reference to result and statement, so we can close them when they are garbage collected.
|
208
228
|
@java_rs_data[ret.__id__] = {:res => res, :stmt => stmt}
|
@@ -224,11 +244,11 @@ class Baza::Driver::Mysql
|
|
224
244
|
#Escapes a string to be safe to use in a query.
|
225
245
|
def escape_alternative(string)
|
226
246
|
case @subtype
|
227
|
-
when
|
247
|
+
when :mysql
|
228
248
|
return @conn.escape_string(string.to_s)
|
229
|
-
when
|
249
|
+
when :mysql2
|
230
250
|
return @conn.escape(string.to_s)
|
231
|
-
when
|
251
|
+
when :java
|
232
252
|
return self.escape(string)
|
233
253
|
else
|
234
254
|
raise "Unknown subtype: '#{@subtype}'."
|
@@ -261,15 +281,15 @@ class Baza::Driver::Mysql
|
|
261
281
|
#Returns the last inserted ID for the connection.
|
262
282
|
def lastID
|
263
283
|
case @subtype
|
264
|
-
when
|
284
|
+
when :mysql
|
265
285
|
@mutex.synchronize do
|
266
286
|
return @conn.insert_id.to_i
|
267
287
|
end
|
268
|
-
when
|
288
|
+
when :mysql2
|
269
289
|
@mutex.synchronize do
|
270
290
|
return @conn.last_id.to_i
|
271
291
|
end
|
272
|
-
when
|
292
|
+
when :java
|
273
293
|
data = self.query("SELECT LAST_INSERT_ID() AS id").fetch
|
274
294
|
return data[:id].to_i if data.key?(:id)
|
275
295
|
raise "Could not figure out last inserted ID."
|
@@ -384,7 +404,7 @@ class Baza::Driver::Mysql
|
|
384
404
|
end
|
385
405
|
|
386
406
|
#This class controls the results for the normal MySQL-driver.
|
387
|
-
class Baza::Driver::
|
407
|
+
class Baza::Driver::Mysql::Result
|
388
408
|
#Constructor. This should not be called manually.
|
389
409
|
def initialize(driver, result)
|
390
410
|
@driver = driver
|
@@ -393,28 +413,14 @@ class Baza::Driver::Mysql_result
|
|
393
413
|
|
394
414
|
if @result
|
395
415
|
@keys = []
|
396
|
-
|
397
|
-
keys.each do |key|
|
416
|
+
@result.fetch_fields.each do |key|
|
398
417
|
@keys << key.name.to_sym
|
399
418
|
end
|
400
419
|
end
|
401
420
|
end
|
402
421
|
|
403
|
-
#Returns a single result.
|
404
|
-
def fetch
|
405
|
-
return self.fetch_hash_symbols if @driver.knjdb.opts[:return_keys] == "symbols"
|
406
|
-
return self.fetch_hash_strings
|
407
|
-
end
|
408
|
-
|
409
|
-
#Returns a single result as a hash with strings as keys.
|
410
|
-
def fetch_hash_strings
|
411
|
-
@mutex.synchronize do
|
412
|
-
return @result.fetch_hash
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
422
|
#Returns a single result as a hash with symbols as keys.
|
417
|
-
def
|
423
|
+
def fetch
|
418
424
|
fetched = nil
|
419
425
|
@mutex.synchronize do
|
420
426
|
fetched = @result.fetch_row
|
@@ -434,14 +440,14 @@ class Baza::Driver::Mysql_result
|
|
434
440
|
|
435
441
|
#Loops over every result yielding it.
|
436
442
|
def each
|
437
|
-
while data = self.
|
443
|
+
while data = self.fetch
|
438
444
|
yield(data)
|
439
445
|
end
|
440
446
|
end
|
441
447
|
end
|
442
448
|
|
443
449
|
#This class controls the unbuffered result for the normal MySQL-driver.
|
444
|
-
class Baza::Driver::
|
450
|
+
class Baza::Driver::Mysql::ResultUnbuffered
|
445
451
|
#Constructor. This should not be called manually.
|
446
452
|
def initialize(conn, opts, result)
|
447
453
|
@conn = conn
|
@@ -514,7 +520,7 @@ class Baza::Driver::Mysql_unbuffered_result
|
|
514
520
|
end
|
515
521
|
|
516
522
|
#This class controls the result for the MySQL2 driver.
|
517
|
-
class Baza::Driver::
|
523
|
+
class Baza::Driver::Mysql::ResultMySQL2
|
518
524
|
#Constructor. This should not be called manually.
|
519
525
|
def initialize(result)
|
520
526
|
@result = result
|
@@ -534,15 +540,14 @@ class Baza::Driver::Mysql2_result
|
|
534
540
|
#Loops over every single result yielding it.
|
535
541
|
def each
|
536
542
|
@result.each do |res|
|
537
|
-
#This sometimes happens when streaming results...
|
538
|
-
next if !res
|
543
|
+
next if !res #This sometimes happens when streaming results...
|
539
544
|
yield(res)
|
540
545
|
end
|
541
546
|
end
|
542
547
|
end
|
543
548
|
|
544
549
|
#This class controls the result for the Java-MySQL-driver.
|
545
|
-
class
|
550
|
+
class Baza::Driver::Mysql::ResultJava
|
546
551
|
#Constructor. This should not be called manually.
|
547
552
|
def initialize(knjdb, opts, result)
|
548
553
|
@knjdb = knjdb
|
@@ -6,27 +6,33 @@ class Baza::Driver::Mysql::Columns
|
|
6
6
|
end
|
7
7
|
|
8
8
|
#Returns the SQL for this column.
|
9
|
+
DATA_SQL_ALLOWED_KEYS = [:type, :maxlength, :name, :primarykey, :autoincr, :default, :comment, :after, :first, :storage, :null]
|
9
10
|
def data_sql(data)
|
10
|
-
|
11
|
+
data.each do |key, val|
|
12
|
+
raise "Invalid key: '#{key}' (#{key.class.name})." if !DATA_SQL_ALLOWED_KEYS.include?(key)
|
13
|
+
end
|
14
|
+
|
15
|
+
raise "No type given." if !data[:type]
|
16
|
+
type = data[:type].to_sym
|
11
17
|
|
12
|
-
data[
|
18
|
+
data[:maxlength] = 255 if type == :varchar and !data.key?(:maxlength)
|
13
19
|
|
14
|
-
sql = "`#{data[
|
15
|
-
sql << "(#{data[
|
16
|
-
sql << " PRIMARY KEY" if data[
|
17
|
-
sql << " AUTO_INCREMENT" if data[
|
18
|
-
sql << " NOT NULL" if !data[
|
20
|
+
sql = "`#{data[:name]}` #{type}"
|
21
|
+
sql << "(#{data[:maxlength]})" if data[:maxlength]
|
22
|
+
sql << " PRIMARY KEY" if data[:primarykey]
|
23
|
+
sql << " AUTO_INCREMENT" if data[:autoincr]
|
24
|
+
sql << " NOT NULL" if !data[:null]
|
19
25
|
|
20
|
-
if data.key?(
|
21
|
-
sql << " DEFAULT #{data[
|
22
|
-
elsif data.key?(
|
23
|
-
sql << " DEFAULT '#{@args[:db].escape(data[
|
26
|
+
if data.key?(:default_func)
|
27
|
+
sql << " DEFAULT #{data[:default_func]}"
|
28
|
+
elsif data.key?(:default) and data[:default] != false
|
29
|
+
sql << " DEFAULT '#{@args[:db].escape(data[:default])}'"
|
24
30
|
end
|
25
31
|
|
26
|
-
sql << " COMMENT '#{@args[:db].escape(data[
|
27
|
-
sql << " AFTER `#{@args[:db].esc_col(data[
|
28
|
-
sql << " FIRST" if data[
|
29
|
-
sql << " STORAGE #{data[
|
32
|
+
sql << " COMMENT '#{@args[:db].escape(data[:comment])}'" if data.key?(:comment)
|
33
|
+
sql << " AFTER `#{@args[:db].esc_col(data[:after])}`" if data[:after] and !data[:first]
|
34
|
+
sql << " FIRST" if data[:first]
|
35
|
+
sql << " STORAGE #{data[:storage].to_s.upcase}" if data[:storage]
|
30
36
|
|
31
37
|
return sql
|
32
38
|
end
|
@@ -34,21 +40,18 @@ end
|
|
34
40
|
|
35
41
|
#This class handels every MySQL-column, that can be returned from a table-object.
|
36
42
|
class Baza::Driver::Mysql::Columns::Column
|
37
|
-
attr_reader :args
|
43
|
+
attr_reader :args, :name
|
38
44
|
|
39
45
|
#Constructor. Should not be called manually.
|
40
46
|
def initialize(args)
|
41
47
|
@args = args
|
48
|
+
@name = @args[:data][:Field].to_sym
|
49
|
+
@db = @args[:db]
|
42
50
|
end
|
43
51
|
|
44
52
|
#Used to validate in Knj::Wrap_map.
|
45
53
|
def __object_unique_id__
|
46
|
-
return @
|
47
|
-
end
|
48
|
-
|
49
|
-
#Returns the name of the column.
|
50
|
-
def name
|
51
|
-
return @args[:data][:Field]
|
54
|
+
return @name
|
52
55
|
end
|
53
56
|
|
54
57
|
#Returns the table-object that this column belongs to.
|
@@ -59,13 +62,13 @@ class Baza::Driver::Mysql::Columns::Column
|
|
59
62
|
#Returns all data of the column in the knjdb-format.
|
60
63
|
def data
|
61
64
|
return {
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
:type => self.type,
|
66
|
+
:name => self.name,
|
67
|
+
:null => self.null?,
|
68
|
+
:maxlength => self.maxlength,
|
69
|
+
:default => self.default,
|
70
|
+
:primarykey => self.primarykey?,
|
71
|
+
:autoincr => self.autoincr?
|
69
72
|
}
|
70
73
|
end
|
71
74
|
|
@@ -86,7 +89,7 @@ class Baza::Driver::Mysql::Columns::Column
|
|
86
89
|
@type = match[1].to_sym
|
87
90
|
end
|
88
91
|
|
89
|
-
raise "Still not type from: '#{@args[:data][:Type]}'." if @type.to_s.strip.
|
92
|
+
raise "Still not type from: '#{@args[:data][:Type]}'." if @type.to_s.strip.empty?
|
90
93
|
end
|
91
94
|
|
92
95
|
return @type
|
@@ -107,8 +110,8 @@ class Baza::Driver::Mysql::Columns::Column
|
|
107
110
|
|
108
111
|
#Returns the default value for the column.
|
109
112
|
def default
|
110
|
-
return false if (self.type ==
|
111
|
-
return false if (self.type ==
|
113
|
+
return false if (self.type == :datetime or self.type == :date) and @args[:data][:Default].to_s.strip.length <= 0
|
114
|
+
return false if (self.type == :int or self.type == :bigint) and @args[:data][:Default].to_s.strip.length <= 0
|
112
115
|
return false if !@args[:data][:Default]
|
113
116
|
return @args[:data][:Default]
|
114
117
|
end
|
@@ -121,7 +124,7 @@ class Baza::Driver::Mysql::Columns::Column
|
|
121
124
|
|
122
125
|
#Returns true if the column is auto-increasing. Otherwise false.
|
123
126
|
def autoincr?
|
124
|
-
return true if @args[:data][:Extra].
|
127
|
+
return true if @args[:data][:Extra].include?("auto_increment")
|
125
128
|
return false
|
126
129
|
end
|
127
130
|
|
@@ -132,7 +135,8 @@ class Baza::Driver::Mysql::Columns::Column
|
|
132
135
|
|
133
136
|
#Drops the column from the table.
|
134
137
|
def drop
|
135
|
-
@args[:db].query("ALTER TABLE `#{@args[:table_name]}` DROP COLUMN `#{self.name}`")
|
138
|
+
@args[:db].query("ALTER TABLE `#{@db.esc_table(@args[:table_name])}` DROP COLUMN `#{@db.esc_col(self.name)}`")
|
139
|
+
table = self.table.remove_column_from_list(self)
|
136
140
|
return nil
|
137
141
|
end
|
138
142
|
|
@@ -142,14 +146,17 @@ class Baza::Driver::Mysql::Columns::Column
|
|
142
146
|
table_escape = "`#{@args[:db].esc_table(self.table.name)}`"
|
143
147
|
newdata = data.clone
|
144
148
|
|
145
|
-
newdata[
|
146
|
-
newdata[
|
147
|
-
newdata[
|
148
|
-
newdata[
|
149
|
-
newdata[
|
150
|
-
newdata.delete(
|
149
|
+
newdata[:name] = self.name if !newdata.key?(:name)
|
150
|
+
newdata[:type] = self.type if !newdata.key?(:type)
|
151
|
+
newdata[:maxlength] = self.maxlength if !newdata.key?(:maxlength) and self.maxlength
|
152
|
+
newdata[:null] = self.null? if !newdata.key?(:null)
|
153
|
+
newdata[:default] = self.default if !newdata.key?(:default) and self.default
|
154
|
+
newdata.delete(:primarykey) if newdata.key?(:primarykey)
|
155
|
+
|
156
|
+
drop_add = true if self.name.to_s != newdata[:name].to_s
|
151
157
|
|
152
|
-
|
158
|
+
self.table.__send__(:remove_column_from_list, self) if drop_add
|
153
159
|
@args[:db].query("ALTER TABLE #{table_escape} CHANGE #{col_escaped} #{@args[:db].cols.data_sql(newdata)}")
|
160
|
+
self.table.__send__(:add_column_to_list, self) if drop_add
|
154
161
|
end
|
155
162
|
end
|