baza 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +58 -13
  3. data/VERSION +1 -1
  4. data/baza.gemspec +15 -3
  5. data/include/db.rb +871 -865
  6. data/include/drivers/mysql/mysql.rb +104 -297
  7. data/include/drivers/mysql/mysql_column.rb +133 -0
  8. data/include/drivers/mysql/mysql_columns.rb +4 -127
  9. data/include/drivers/mysql/mysql_index.rb +76 -0
  10. data/include/drivers/mysql/mysql_indexes.rb +0 -73
  11. data/include/drivers/mysql/mysql_result.rb +42 -0
  12. data/include/drivers/mysql/mysql_result_java.rb +61 -0
  13. data/include/drivers/mysql/mysql_result_mysql2.rb +26 -0
  14. data/include/drivers/mysql/mysql_result_unbuffered.rb +72 -0
  15. data/include/drivers/mysql/mysql_sqlspecs.rb +1 -1
  16. data/include/drivers/mysql/mysql_table.rb +361 -0
  17. data/include/drivers/mysql/mysql_tables.rb +23 -381
  18. data/include/drivers/sqlite3/libknjdb_java_sqlite3.rb +17 -22
  19. data/include/drivers/sqlite3/libknjdb_sqlite3_ironruby.rb +13 -13
  20. data/include/drivers/sqlite3/sqlite3.rb +39 -105
  21. data/include/drivers/sqlite3/sqlite3_column.rb +146 -0
  22. data/include/drivers/sqlite3/sqlite3_columns.rb +17 -149
  23. data/include/drivers/sqlite3/sqlite3_index.rb +55 -0
  24. data/include/drivers/sqlite3/sqlite3_indexes.rb +0 -52
  25. data/include/drivers/sqlite3/sqlite3_result.rb +35 -0
  26. data/include/drivers/sqlite3/sqlite3_result_java.rb +39 -0
  27. data/include/drivers/sqlite3/sqlite3_table.rb +399 -0
  28. data/include/drivers/sqlite3/sqlite3_tables.rb +7 -403
  29. data/include/idquery.rb +19 -19
  30. data/include/model.rb +139 -139
  31. data/include/model_handler_sqlhelper.rb +74 -74
  32. data/spec/support/driver_columns_collection.rb +17 -0
  33. metadata +14 -2
@@ -0,0 +1,133 @@
1
+ #This class handels every MySQL-column, that can be returned from a table-object.
2
+ class Baza::Driver::Mysql::Column
3
+ attr_reader :args, :name
4
+
5
+ #Constructor. Should not be called manually.
6
+ def initialize(args)
7
+ @args = args
8
+ @name = @args[:data][:Field].to_sym
9
+ @db = @args[:db]
10
+ end
11
+
12
+ #Used to validate in Knj::Wrap_map.
13
+ def __object_unique_id__
14
+ return @name
15
+ end
16
+
17
+ def table_name
18
+ @args[:table_name]
19
+ end
20
+
21
+ #Returns the table-object that this column belongs to.
22
+ def table
23
+ return @db.tables[table_name]
24
+ end
25
+
26
+ #Returns all data of the column in the knjdb-format.
27
+ def data
28
+ return {
29
+ type: type,
30
+ name: name,
31
+ null: null?,
32
+ maxlength: maxlength,
33
+ default: default,
34
+ primarykey: primarykey?,
35
+ autoincr: autoincr?
36
+ }
37
+ end
38
+
39
+ def reload
40
+ @args[:data] = @db.query("SHOW FULL COLUMNS FROM `#{@db.esc_table(table_name)}` WHERE `Field` = '#{@db.esc(name)}'").fetch
41
+ @type = nil
42
+ end
43
+
44
+ #Returns the type of the column (integer, varchar etc.).
45
+ def type
46
+ if !@type
47
+ if match = @args[:data][:Type].match(/^([A-z]+)$/)
48
+ @maxlength = false
49
+ @type = match[0].to_sym
50
+ elsif match = @args[:data][:Type].match(/^decimal\((\d+),(\d+)\)$/)
51
+ @maxlength = "#{match[1]},#{match[2]}"
52
+ @type = :decimal
53
+ elsif match = @args[:data][:Type].match(/^enum\((.+)\)$/)
54
+ @maxlength = match[1]
55
+ @type = :enum
56
+ elsif match = @args[:data][:Type].match(/^(.+)\((\d+)\)/)
57
+ @maxlength = match[2].to_i
58
+ @type = match[1].to_sym
59
+ end
60
+
61
+ raise "Still not type from: '#{@args[:data][:Type]}'." if @type.to_s.strip.empty?
62
+ end
63
+
64
+ return @type
65
+ end
66
+
67
+ #Return true if the columns allows null. Otherwise false.
68
+ def null?
69
+ return false if @args[:data][:Null] == "NO"
70
+ return true
71
+ end
72
+
73
+ #Returns the maxlength.
74
+ def maxlength
75
+ self.type unless @maxlength
76
+ return @maxlength if @maxlength
77
+ return false
78
+ end
79
+
80
+ #Returns the default value for the column.
81
+ def default
82
+ return false if (self.type == :datetime || self.type == :date) && @args[:data][:Default].to_s.strip.empty?
83
+ return false if (self.type == :int || self.type == :bigint) && @args[:data][:Default].to_s.strip.empty?
84
+ return false if !@args[:data][:Default]
85
+ return @args[:data][:Default]
86
+ end
87
+
88
+ #Returns true if the column is the primary key. Otherwise false.
89
+ def primarykey?
90
+ return true if @args[:data][:Key] == "PRI"
91
+ return false
92
+ end
93
+
94
+ #Returns true if the column is auto-increasing. Otherwise false.
95
+ def autoincr?
96
+ return true if @args[:data][:Extra].include?("auto_increment")
97
+ return false
98
+ end
99
+
100
+ #Returns the comment for the column.
101
+ def comment
102
+ return @args[:data][:Comment]
103
+ end
104
+
105
+ #Drops the column from the table.
106
+ def drop
107
+ @args[:db].query("ALTER TABLE `#{@db.esc_table(@args[:table_name])}` DROP COLUMN `#{@db.esc_col(self.name)}`")
108
+ table.__send__(:remove_column_from_list, self)
109
+ return nil
110
+ end
111
+
112
+ #Changes the column properties by the given hash.
113
+ def change(data)
114
+ col_escaped = "`#{@db.esc_col(name)}`"
115
+ table_escape = "`#{@db.esc_table(table_name)}`"
116
+ newdata = data.clone
117
+
118
+ newdata[:name] = name unless newdata.key?(:name)
119
+ newdata[:type] = type unless newdata.key?(:type)
120
+ newdata[:maxlength] = maxlength if !newdata.key?(:maxlength) && maxlength
121
+ newdata[:null] = null? unless newdata.key?(:null)
122
+ newdata[:default] = self.default if !newdata.key?(:default) && default
123
+ newdata.delete(:primarykey) if newdata.key?(:primarykey)
124
+
125
+ drop_add = true if name.to_s != newdata[:name].to_s
126
+
127
+ table.__send__(:remove_column_from_list, self) if drop_add
128
+ @db.query("ALTER TABLE #{table_escape} CHANGE #{col_escaped} #{@args[:db].cols.data_sql(newdata)}")
129
+ @name = newdata[:name].to_sym
130
+ reload
131
+ table.__send__(:add_column_to_list, self) if drop_add
132
+ end
133
+ end
@@ -12,10 +12,10 @@ class Baza::Driver::Mysql::Columns
12
12
  raise "Invalid key: '#{key}' (#{key.class.name})." if !DATA_SQL_ALLOWED_KEYS.include?(key)
13
13
  end
14
14
 
15
- raise "No type given." if !data[:type]
15
+ raise "No type given." unless data[:type]
16
16
  type = data[:type].to_sym
17
17
 
18
- data[:maxlength] = 255 if type == :varchar and !data.key?(:maxlength)
18
+ data[:maxlength] = 255 if type == :varchar && !data.key?(:maxlength)
19
19
 
20
20
  sql = "`#{data[:name]}` #{type}"
21
21
  sql << "(#{data[:maxlength]})" if data[:maxlength]
@@ -25,138 +25,15 @@ class Baza::Driver::Mysql::Columns
25
25
 
26
26
  if data.key?(:default_func)
27
27
  sql << " DEFAULT #{data[:default_func]}"
28
- elsif data.key?(:default) and data[:default] != false
28
+ elsif data.key?(:default) && data[:default] != false
29
29
  sql << " DEFAULT '#{@args[:db].escape(data[:default])}'"
30
30
  end
31
31
 
32
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]
33
+ sql << " AFTER `#{@args[:db].esc_col(data[:after])}`" if data[:after] && !data[:first]
34
34
  sql << " FIRST" if data[:first]
35
35
  sql << " STORAGE #{data[:storage].to_s.upcase}" if data[:storage]
36
36
 
37
37
  return sql
38
38
  end
39
39
  end
40
-
41
- #This class handels every MySQL-column, that can be returned from a table-object.
42
- class Baza::Driver::Mysql::Columns::Column
43
- attr_reader :args, :name
44
-
45
- #Constructor. Should not be called manually.
46
- def initialize(args)
47
- @args = args
48
- @name = @args[:data][:Field].to_sym
49
- @db = @args[:db]
50
- end
51
-
52
- #Used to validate in Knj::Wrap_map.
53
- def __object_unique_id__
54
- return @name
55
- end
56
-
57
- #Returns the table-object that this column belongs to.
58
- def table
59
- return @args[:db].tables[@args[:table_name]]
60
- end
61
-
62
- #Returns all data of the column in the knjdb-format.
63
- def data
64
- return {
65
- type: type,
66
- name: name,
67
- null: null?,
68
- maxlength: maxlength,
69
- default: default,
70
- primarykey: primarykey?,
71
- autoincr: autoincr?
72
- }
73
- end
74
-
75
- #Returns the type of the column (integer, varchar etc.).
76
- def type
77
- if !@type
78
- if match = @args[:data][:Type].match(/^([A-z]+)$/)
79
- @maxlength = false
80
- @type = match[0].to_sym
81
- elsif match = @args[:data][:Type].match(/^decimal\((\d+),(\d+)\)$/)
82
- @maxlength = "#{match[1]},#{match[2]}"
83
- @type = :decimal
84
- elsif match = @args[:data][:Type].match(/^enum\((.+)\)$/)
85
- @maxlength = match[1]
86
- @type = :enum
87
- elsif match = @args[:data][:Type].match(/^(.+)\((\d+)\)/)
88
- @maxlength = match[2].to_i
89
- @type = match[1].to_sym
90
- end
91
-
92
- raise "Still not type from: '#{@args[:data][:Type]}'." if @type.to_s.strip.empty?
93
- end
94
-
95
- return @type
96
- end
97
-
98
- #Return true if the columns allows null. Otherwise false.
99
- def null?
100
- return false if @args[:data][:Null] == "NO"
101
- return true
102
- end
103
-
104
- #Returns the maxlength.
105
- def maxlength
106
- self.type if !@maxlength
107
- return @maxlength if @maxlength
108
- return false
109
- end
110
-
111
- #Returns the default value for the column.
112
- def default
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
115
- return false if !@args[:data][:Default]
116
- return @args[:data][:Default]
117
- end
118
-
119
- #Returns true if the column is the primary key. Otherwise false.
120
- def primarykey?
121
- return true if @args[:data][:Key] == "PRI"
122
- return false
123
- end
124
-
125
- #Returns true if the column is auto-increasing. Otherwise false.
126
- def autoincr?
127
- return true if @args[:data][:Extra].include?("auto_increment")
128
- return false
129
- end
130
-
131
- #Returns the comment for the column.
132
- def comment
133
- return @args[:data][:Comment]
134
- end
135
-
136
- #Drops the column from the table.
137
- def drop
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)
140
- return nil
141
- end
142
-
143
- #Changes the column properties by the given hash.
144
- def change(data)
145
- col_escaped = "`#{@args[:db].esc_col(self.name)}`"
146
- table_escape = "`#{@args[:db].esc_table(self.table.name)}`"
147
- newdata = data.clone
148
-
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
157
-
158
- self.table.__send__(:remove_column_from_list, self) if drop_add
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
161
- end
162
- end
@@ -0,0 +1,76 @@
1
+ class Baza::Driver::Mysql::Index
2
+ attr_reader :args, :columns
3
+
4
+ def initialize(args)
5
+ @args = args
6
+ @columns = []
7
+ end
8
+
9
+ #Used to validate in Knj::Wrap_map.
10
+ def __object_unique_id__
11
+ return @args[:data][:Key_name]
12
+ end
13
+
14
+ def name
15
+ return @args[:data][:Key_name]
16
+ end
17
+
18
+ def table
19
+ return @args[:db].tables[@args[:table_name]]
20
+ end
21
+
22
+ def drop
23
+ sql = "DROP INDEX `#{self.name}` ON `#{self.table.name}`"
24
+
25
+ begin
26
+ @args[:db].query(sql)
27
+ rescue => e
28
+ #The index has already been dropped - ignore.
29
+ if e.message.index("check that column/key exists") != nil
30
+ #ignore.
31
+ else
32
+ raise e
33
+ end
34
+ end
35
+ end
36
+
37
+ def rename newname
38
+ newname = newname.to_sym
39
+ create_args = data
40
+ create_args[:name] = newname
41
+
42
+ drop
43
+ table.create_indexes([create_args])
44
+ @args[:data][:Key_name] = newname
45
+ end
46
+
47
+ def data
48
+ return {
49
+ name: name,
50
+ columns: @columns
51
+ }
52
+ end
53
+
54
+ #Returns true if the index is a unique-index.
55
+ def unique?
56
+ if @args[:data][:Index_type] == "UNIQUE"
57
+ return true
58
+ else
59
+ return false
60
+ end
61
+ end
62
+
63
+ #Returns true if the index is a primary-index.
64
+ def primary?
65
+ return true if @args[:data][:Key_name] == "PRIMARY"
66
+ return false
67
+ end
68
+
69
+ def to_s
70
+ return "#<Baza::Driver::Mysql::Index name: \"#{name}\", columns: #{@columns}, primary: #{primary?}, unique: #{unique?}>"
71
+ end
72
+
73
+ def inspect
74
+ to_s
75
+ end
76
+ end
@@ -3,76 +3,3 @@ class Baza::Driver::Mysql::Indexes
3
3
  @args = args
4
4
  end
5
5
  end
6
-
7
- class Baza::Driver::Mysql::Indexes::Index
8
- attr_reader :args, :columns
9
-
10
- def initialize(args)
11
- @args = args
12
- @columns = []
13
- end
14
-
15
- #Used to validate in Knj::Wrap_map.
16
- def __object_unique_id__
17
- return @args[:data][:Key_name]
18
- end
19
-
20
- def name
21
- return @args[:data][:Key_name]
22
- end
23
-
24
- def table
25
- return @args[:db].tables[@args[:table_name]]
26
- end
27
-
28
- def drop
29
- sql = "DROP INDEX `#{self.name}` ON `#{self.table.name}`"
30
-
31
- begin
32
- @args[:db].query(sql)
33
- rescue => e
34
- #The index has already been dropped - ignore.
35
- if e.message.index("check that column/key exists") != nil
36
- #ignore.
37
- else
38
- raise e
39
- end
40
- end
41
- end
42
-
43
- def rename newname
44
- newname = newname.to_sym
45
- create_args = data
46
- create_args[:name] = newname
47
-
48
- drop
49
- table.create_indexes([create_args])
50
- @args[:data][:Key_name] = newname
51
- end
52
-
53
- def data
54
- return {
55
- name: name,
56
- columns: @columns
57
- }
58
- end
59
-
60
- #Returns true if the index is a unique-index.
61
- def unique?
62
- if @args[:data][:Index_type] == "UNIQUE"
63
- return true
64
- else
65
- return false
66
- end
67
- end
68
-
69
- #Returns true if the index is a primary-index.
70
- def primary?
71
- return true if @args[:data][:Key_name] == "PRIMARY"
72
- return false
73
- end
74
-
75
- def to_s
76
- return "#<Baza::Driver::Mysql::Index name: \"#{name}\", columns: #{@columns}, primary: #{primary?}, unique: #{unique?}>"
77
- end
78
- end
@@ -0,0 +1,42 @@
1
+ #This class controls the results for the normal MySQL-driver.
2
+ class Baza::Driver::Mysql::Result
3
+ #Constructor. This should not be called manually.
4
+ def initialize(driver, result)
5
+ @driver = driver
6
+ @result = result
7
+ @mutex = Mutex.new
8
+
9
+ if @result
10
+ @keys = []
11
+ @result.fetch_fields.each do |key|
12
+ @keys << key.name.to_sym
13
+ end
14
+ end
15
+ end
16
+
17
+ #Returns a single result as a hash with symbols as keys.
18
+ def fetch
19
+ fetched = nil
20
+ @mutex.synchronize do
21
+ fetched = @result.fetch_row
22
+ end
23
+
24
+ return false unless fetched
25
+
26
+ ret = {}
27
+ count = 0
28
+ @keys.each do |key|
29
+ ret[key] = fetched[count]
30
+ count += 1
31
+ end
32
+
33
+ return ret
34
+ end
35
+
36
+ #Loops over every result yielding it.
37
+ def each
38
+ while data = self.fetch
39
+ yield(data)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,61 @@
1
+ #This class controls the result for the Java-MySQL-driver.
2
+ class Baza::Driver::Mysql::ResultJava
3
+ #Constructor. This should not be called manually.
4
+ def initialize(knjdb, opts, result)
5
+ @baza_db = knjdb
6
+ @result = result
7
+
8
+ if !opts.key?(:result) || opts[:result] == "hash"
9
+ @as_hash = true
10
+ elsif opts[:result] == "array"
11
+ @as_hash = false
12
+ else
13
+ raise "Unknown type of result: '#{opts[:result]}'."
14
+ end
15
+ end
16
+
17
+ #Reads meta-data about the query like keys and count.
18
+ def read_meta
19
+ @result.before_first
20
+ meta = @result.meta_data
21
+ @count = meta.column_count
22
+
23
+ @keys = []
24
+ 1.upto(@count) do |count|
25
+ @keys << meta.column_label(count).to_sym
26
+ end
27
+ end
28
+
29
+ def fetch
30
+ return false unless @result
31
+ self.read_meta unless @keys
32
+ status = @result.next
33
+
34
+ unless status
35
+ @result = nil
36
+ @keys = nil
37
+ @count = nil
38
+ return false
39
+ end
40
+
41
+ if @as_hash
42
+ ret = {}
43
+ 1.upto(@count) do |count|
44
+ ret[@keys[count - 1]] = @result.object(count)
45
+ end
46
+ else
47
+ ret = []
48
+ 1.upto(@count) do |count|
49
+ ret << @result.object(count)
50
+ end
51
+ end
52
+
53
+ return ret
54
+ end
55
+
56
+ def each
57
+ while data = self.fetch
58
+ yield(data)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,26 @@
1
+ #This class controls the result for the MySQL2 driver.
2
+ class Baza::Driver::Mysql::ResultMysql2
3
+ #Constructor. This should not be called manually.
4
+ def initialize(result)
5
+ @result = result
6
+ end
7
+
8
+ #Returns a single result.
9
+ def fetch
10
+ @enum = @result.to_enum if !@enum
11
+
12
+ begin
13
+ return @enum.next
14
+ rescue StopIteration
15
+ return false
16
+ end
17
+ end
18
+
19
+ #Loops over every single result yielding it.
20
+ def each
21
+ @result.each do |res|
22
+ next unless res #This sometimes happens when streaming results...
23
+ yield(res)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,72 @@
1
+ #This class controls the unbuffered result for the normal MySQL-driver.
2
+ class Baza::Driver::Mysql::ResultUnbuffered
3
+ #Constructor. This should not be called manually.
4
+ def initialize(conn, opts, result)
5
+ @conn = conn
6
+ @result = result
7
+
8
+ if !opts.key?(:result) || opts[:result] == "hash"
9
+ @as_hash = true
10
+ elsif opts[:result] == "array"
11
+ @as_hash = false
12
+ else
13
+ raise "Unknown type of result: '#{opts[:result]}'."
14
+ end
15
+ end
16
+
17
+ #Lods the keys for the object.
18
+ def load_keys
19
+ @keys = []
20
+ keys = @res.fetch_fields
21
+ keys.each do |key|
22
+ @keys << key.name.to_sym
23
+ end
24
+ end
25
+
26
+ #Returns a single result.
27
+ def fetch
28
+ if @enum
29
+ begin
30
+ ret = @enum.next
31
+ rescue StopIteration
32
+ @enum = nil
33
+ @res = nil
34
+ end
35
+ end
36
+
37
+ if !ret && !@res && !@enum
38
+ begin
39
+ @res = @conn.use_result
40
+ @enum = @res.to_enum
41
+ ret = @enum.next
42
+ rescue Mysql::Error
43
+ #Reset it to run non-unbuffered again and then return false.
44
+ @conn.query_with_result = true
45
+ return false
46
+ rescue StopIteration
47
+ sleep 0.1
48
+ retry
49
+ end
50
+ end
51
+
52
+ if !@as_hash
53
+ return ret
54
+ else
55
+ self.load_keys if !@keys
56
+
57
+ ret_h = {}
58
+ @keys.each_index do |key_no|
59
+ ret_h[@keys[key_no]] = ret[key_no]
60
+ end
61
+
62
+ return ret_h
63
+ end
64
+ end
65
+
66
+ #Loops over every single result yielding it.
67
+ def each
68
+ while data = self.fetch
69
+ yield(data)
70
+ end
71
+ end
72
+ end
@@ -2,4 +2,4 @@ class Baza::Driver::Mysql::Sqlspecs < Baza::Sqlspecs
2
2
  def strftime(val, colstr)
3
3
  return "DATE_FORMAT(#{colstr}, '#{val}')"
4
4
  end
5
- end
5
+ end