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
@@ -1,47 +1,57 @@
1
1
  #This class handels SQLite3-specific behaviour.
2
2
  class Baza::Driver::Sqlite3
3
+ autoload :Table, "#{File.dirname(__FILE__)}/sqlite3_table"
4
+ autoload :Tables, "#{File.dirname(__FILE__)}/sqlite3_tables"
5
+ autoload :Column, "#{File.dirname(__FILE__)}/sqlite3_column"
6
+ autoload :Columns, "#{File.dirname(__FILE__)}/sqlite3_columns"
7
+ autoload :Index, "#{File.dirname(__FILE__)}/sqlite3_index"
8
+ autoload :Indexes, "#{File.dirname(__FILE__)}/sqlite3_indexes"
9
+ autoload :Result, "#{File.dirname(__FILE__)}/sqlite3_result"
10
+ autoload :ResultJava, "#{File.dirname(__FILE__)}/sqlite3_result_java"
11
+ autoload :Sqlspecs, "#{File.dirname(__FILE__)}/sqlite3_sqlspecs"
12
+
3
13
  attr_reader :baza, :conn, :sep_table, :sep_col, :sep_val, :symbolize
4
14
  attr_accessor :tables, :cols, :indexes
5
-
15
+
6
16
  #Helper to enable automatic registering of database using Baza::Db.from_object
7
17
  def self.from_object(args)
8
18
  if args[:object].class.name == "SQLite3::Database"
9
19
  return {
10
- :type => :success,
11
- :args => {
12
- :type => :sqlite3,
13
- :conn => args[:object]
20
+ type: :success,
21
+ args: {
22
+ type: :sqlite3,
23
+ conn: args[:object]
14
24
  }
15
25
  }
16
26
  end
17
-
27
+
18
28
  return nil
19
29
  end
20
-
30
+
21
31
  #Constructor. This should not be called manually.
22
32
  def initialize(baza_db_obj)
23
33
  @sep_table = "`"
24
34
  @sep_col = "`"
25
35
  @sep_val = "'"
26
-
36
+
27
37
  @baza_db = baza_db_obj
28
38
  @path = @baza_db.opts[:path] if @baza_db.opts[:path]
29
39
  @path = @baza_db.opts["path"] if @baza_db.opts["path"]
30
-
31
- @baza_db.opts[:subtype] = "java" if !@baza_db.opts.key?(:subtype) and RUBY_ENGINE == "jruby"
32
-
40
+
41
+ @baza_db.opts[:subtype] = "java" if !@baza_db.opts.key?(:subtype) && RUBY_ENGINE == "jruby"
42
+
33
43
  if @baza_db.opts[:conn]
34
44
  @conn = @baza_db.opts[:conn]
35
45
  else
36
46
  raise "No path was given." if !@path
37
-
47
+
38
48
  if @baza_db.opts[:subtype] == "java"
39
49
  if @baza_db.opts[:sqlite_driver]
40
50
  require @baza_db.opts[:sqlite_driver]
41
51
  else
42
52
  require "#{File.dirname(__FILE__)}/../../../jruby/sqlitejdbc-v056.jar"
43
53
  end
44
-
54
+
45
55
  require "java"
46
56
  import "org.sqlite.JDBC"
47
57
  @conn = java.sql.DriverManager::getConnection("jdbc:sqlite:#{@baza_db.opts[:path]}")
@@ -55,7 +65,7 @@ class Baza::Driver::Sqlite3
55
65
  end
56
66
  end
57
67
  end
58
-
68
+
59
69
  #Executes a query against the driver.
60
70
  def query(string)
61
71
  if @baza_db.opts[:subtype] == :rhodes
@@ -74,132 +84,56 @@ class Baza::Driver::Sqlite3
74
84
  return Baza::Driver::Sqlite3::Result.new(self, @conn.execute(string))
75
85
  end
76
86
  end
77
-
87
+
78
88
  #SQLite3 driver doesnt support unbuffered queries??
79
89
  alias query_ubuf query
80
-
90
+
81
91
  #Escapes a string to be safe to used in a query.
82
92
  def escape(string)
83
93
  #This code is taken directly from the documentation so we dont have to rely on the SQLite3::Database class. This way it can also be used with JRuby and IronRuby...
84
94
  #http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html
85
95
  return string.to_s.gsub(/'/, "''")
86
96
  end
87
-
97
+
88
98
  #Escapes a string to be used as a column.
89
99
  def esc_col(string)
90
100
  string = string.to_s
91
101
  raise "Invalid column-string: #{string}" if string.index(@sep_col) != nil
92
102
  return string
93
103
  end
94
-
104
+
95
105
  alias :esc_table :esc_col
96
106
  alias :esc :escape
97
-
107
+
98
108
  #Returns the last inserted ID.
99
- def lastID
109
+ def last_id
100
110
  return @conn.last_insert_row_id if @conn.respond_to?(:last_insert_row_id)
101
- return self.query("SELECT last_insert_rowid() AS id").fetch[:id].to_i
111
+ return query("SELECT last_insert_rowid() AS id").fetch[:id].to_i
102
112
  end
103
-
113
+
104
114
  #Closes the connection to the database.
105
115
  def close
106
116
  @conn.close
107
117
  end
108
-
118
+
109
119
  #Starts a transaction, yields the database and commits.
110
120
  def transaction
111
121
  @conn.transaction do
112
122
  yield(@baza_db)
113
123
  end
114
124
  end
115
-
125
+
116
126
  def insert_multi(tablename, arr_hashes, args = nil)
117
- sql = [] if args and args[:return_sql]
118
-
127
+ sql = [] if args && args[:return_sql]
128
+
119
129
  @baza_db.transaction do
120
130
  arr_hashes.each do |hash|
121
131
  res = @baza_db.insert(tablename, hash, args)
122
- sql << res if args and args[:return_sql]
132
+ sql << res if args && args[:return_sql]
123
133
  end
124
134
  end
125
-
126
- return sql if args and args[:return_sql]
127
- return nil
128
- end
129
- end
130
135
 
131
- #This class handels results when running in JRuby.
132
- class Baza::Driver::Sqlite3::ResultJava
133
- def initialize(driver, rs)
134
- @index = 0
135
- retkeys = driver.knjdb.opts[:return_keys]
136
-
137
- if rs
138
- metadata = rs.getMetaData
139
- columns_count = metadata.getColumnCount
140
-
141
- @rows = []
142
- while rs.next
143
- row_data = {}
144
- for i in (1..columns_count)
145
- col_name = metadata.getColumnName(i).to_sym
146
- row_data[col_name] = rs.getString(i)
147
- end
148
-
149
- @rows << row_data
150
- end
151
- end
152
- end
153
-
154
- #Returns a single result.
155
- def fetch
156
- return false if !@rows
157
- ret = @rows[@index]
158
- return false if !ret
159
- @index += 1
160
- return ret
161
- end
162
-
163
- #Loops over every result and yields them.
164
- def each
165
- while data = self.fetch
166
- yield(data)
167
- end
136
+ return sql if args && args[:return_sql]
137
+ return nil
168
138
  end
169
139
  end
170
-
171
- #This class handels the result when running MRI (or others).
172
- class Baza::Driver::Sqlite3::Result
173
- #Constructor. This should not be called manually.
174
- def initialize(driver, result_array)
175
- @result_array = result_array
176
- @index = 0
177
- end
178
-
179
- #Returns a single result.
180
- def fetch
181
- result_hash = @result_array[@index]
182
- return false if !result_hash
183
- @index += 1
184
-
185
- ret = {}
186
- result_hash.each do |key, val|
187
- if (Float(key) rescue false)
188
- #do nothing.
189
- elsif !key.is_a?(Symbol)
190
- ret[key.to_sym] = val
191
- else
192
- ret[key] = val
193
- end
194
- end
195
-
196
- return ret
197
- end
198
-
199
- #Loops over every result yielding them.
200
- def each
201
- while data = self.fetch
202
- yield(data)
203
- end
204
- end
205
- end
@@ -0,0 +1,146 @@
1
+ #This class handels all the SQLite3-columns.
2
+ class Baza::Driver::Sqlite3::Column
3
+ attr_reader :args
4
+
5
+ #Constructor. This should not be called manually.
6
+ def initialize(args)
7
+ @args = args
8
+ @db = @args[:db]
9
+ end
10
+
11
+ #Returns the name of the column.
12
+ def name
13
+ return @args[:data][:name].to_sym
14
+ end
15
+
16
+ def table_name
17
+ @args[:table_name]
18
+ end
19
+
20
+ #Returns the columns table-object.
21
+ def table
22
+ return @db.tables[table_name]
23
+ end
24
+
25
+ #Returns the data of the column as a hash in knjdb-format.
26
+ def data
27
+ return {
28
+ type: type,
29
+ name: name,
30
+ null: null?,
31
+ maxlength: maxlength,
32
+ default: default,
33
+ primarykey: primarykey?,
34
+ autoincr: autoincr?
35
+ }
36
+ end
37
+
38
+ #Returns the type of the column.
39
+ def type
40
+ if !@type
41
+ if match = @args[:data][:type].match(/^([A-z]+)$/)
42
+ @maxlength = false
43
+ type = match[0].to_sym
44
+ elsif match = @args[:data][:type].match(/^decimal\((\d+),(\d+)\)$/)
45
+ @maxlength = "#{match[1]},#{match[2]}"
46
+ type = :decimal
47
+ elsif match = @args[:data][:type].match(/^enum\((.+)\)$/)
48
+ @maxlength = match[1]
49
+ type = :enum
50
+ elsif match = @args[:data][:type].match(/^(.+)\((\d+)\)$/)
51
+ @maxlength = match[2]
52
+ type = match[1].to_sym
53
+ elsif @args[:data].key?(:type) and @args[:data][:type].to_s == ""
54
+ #A type can actually be empty in SQLite... Wtf?
55
+ return @args[:data][:type]
56
+ end
57
+
58
+ if type == :integer
59
+ @type = :int
60
+ else
61
+ @type = type
62
+ end
63
+
64
+ raise "Still not type? (#{@args[:data]})" if @type.to_s.strip.empty?
65
+ end
66
+
67
+ return @type
68
+ end
69
+
70
+ #Returns true if the column allows null. Otherwise false.
71
+ def null?
72
+ return false if @args[:data][:notnull].to_i == 1
73
+ return true
74
+ end
75
+
76
+ #Returns the maxlength of the column.
77
+ def maxlength
78
+ self.type if !@maxlength
79
+ return @maxlength if @maxlength
80
+ return false
81
+ end
82
+
83
+ #Returns the default value of the column.
84
+ def default
85
+ def_val = @args[:data][:dflt_value]
86
+
87
+ if def_val && match = def_val.match(/\A'(.*)'\Z/)
88
+ return match[1]
89
+ end
90
+
91
+ return false if @args[:data][:dflt_value].to_s.empty?
92
+ return def_val
93
+ end
94
+
95
+ #Returns true if the column is the primary key.
96
+ def primarykey?
97
+ return false if @args[:data][:pk].to_i == 0
98
+ return true
99
+ end
100
+
101
+ #Returns true if the column is auto-increasing.
102
+ def autoincr?
103
+ return true if @args[:data][:pk].to_i == 1 && @args[:data][:type].to_sym == :integer
104
+ return false
105
+ end
106
+
107
+ #Drops the column from the table.
108
+ def drop
109
+ table.copy(drops: name)
110
+ end
111
+
112
+ def reload
113
+ @db.q("PRAGMA table_info(`#{@db.esc_table(table_name)}`)") do |data|
114
+ next unless data[:name] == @args[:data][:name]
115
+ @args[:data] = data
116
+ @type = nil
117
+ return
118
+ end
119
+
120
+ raise "Could not find data for column: #{table_name}.#{name}"
121
+ end
122
+
123
+ #Changes data on the column. Like the name, type, maxlength or whatever.
124
+ def change(data)
125
+ newdata = data.clone
126
+
127
+ newdata[:name] = name unless newdata.key?(:name)
128
+ newdata[:type] = type unless newdata.key?(:type)
129
+ newdata[:maxlength] = maxlength unless newdata.key?(:maxlength) && maxlength
130
+ newdata[:null] = null? unless newdata.key?(:null)
131
+ newdata[:default] = default unless newdata.key?(:default)
132
+ newdata[:primarykey] = primarykey? unless newdata.key?(:primarykey)
133
+
134
+ @type = nil
135
+ @maxlength = nil
136
+
137
+ new_table = table.copy(
138
+ alter_columns: {
139
+ name.to_sym => newdata
140
+ }
141
+ )
142
+
143
+ @args[:data][:name] = newdata[:name].to_s
144
+ reload
145
+ end
146
+ end
@@ -1,179 +1,47 @@
1
1
  #This class handels the SQLite3-specific behaviour for columns.
2
2
  class Baza::Driver::Sqlite3::Columns
3
3
  attr_reader :db
4
-
4
+
5
5
  #Constructor. This should not be called manually.
6
6
  def initialize(args)
7
7
  @args = args
8
8
  end
9
-
9
+
10
10
  DATA_SQL_ALLOWED_KEYS = [:name, :type, :maxlength, :autoincr, :primarykey, :null, :default, :default_func, :renames, :after, :renames]
11
11
  #Returns SQL for a knjdb-compatible hash.
12
12
  def data_sql(data)
13
13
  data.each do |key, val|
14
14
  raise "Invalid key: '#{key}' (#{key.class.name})." unless DATA_SQL_ALLOWED_KEYS.include?(key)
15
15
  end
16
-
17
- raise "No type given." if !data[:type]
16
+
17
+ raise "No type given." unless data[:type]
18
18
  type = data[:type].to_sym
19
-
19
+
20
20
  if type == :enum
21
21
  type = :varchar
22
22
  data.delete(:maxlength)
23
23
  end
24
-
25
- data[:maxlength] = 255 if type == :varchar and !data.key?(:maxlength)
26
- data[:maxlength] = 11 if type == :int and !data.key?(:maxlength) and !data[:autoincr] and !data[:primarykey]
27
- type = :integer if @args[:db].int_types.index(type) and (data[:autoincr] or data[:primarykey])
28
-
24
+
25
+ data[:maxlength] = 255 if type == :varchar && !data.key?(:maxlength)
26
+ data[:maxlength] = 11 if type == :int && !data.key?(:maxlength) && !data[:autoincr] && !data[:primarykey]
27
+ type = :integer if @args[:db].int_types.index(type) && (data[:autoincr] || data[:primarykey])
28
+
29
29
  sql = "`#{data[:name]}` #{type}"
30
- sql << "(#{data[:maxlength]})" if data[:maxlength] and !data[:autoincr]
30
+ sql << "(#{data[:maxlength]})" if data[:maxlength] && !data[:autoincr]
31
31
  sql << " PRIMARY KEY" if data[:primarykey]
32
32
  sql << " AUTOINCREMENT" if data[:autoincr]
33
-
34
- if !data[:null] and data.key?(:null)
33
+
34
+ if !data[:null] && data.key?(:null)
35
35
  sql << " NOT NULL"
36
- data[:default] = 0 if type == :int if !data.key?(:default) or !data[:default]
36
+ data[:default] = 0 if type == :int if !data.key?(:default) || !data[:default]
37
37
  end
38
-
38
+
39
39
  if data.key?(:default_func)
40
40
  sql << " DEFAULT #{data[:default_func]}"
41
- elsif data.key?(:default) and data[:default] != false
41
+ elsif data.key?(:default) && data[:default] != false
42
42
  sql << " DEFAULT '#{@args[:db].escape(data[:default])}'"
43
43
  end
44
-
44
+
45
45
  return sql
46
46
  end
47
47
  end
48
-
49
- #This class handels all the SQLite3-columns.
50
- class Baza::Driver::Sqlite3::Columns::Column
51
- attr_reader :args
52
-
53
- #Constructor. This should not be called manually.
54
- def initialize(args)
55
- @args = args
56
- @db = @args[:db]
57
- end
58
-
59
- #Returns the name of the column.
60
- def name
61
- return @args[:data][:name]
62
- end
63
-
64
- #Returns the columns table-object.
65
- def table
66
- return @db.tables[@args[:table_name]]
67
- end
68
-
69
- #Returns the data of the column as a hash in knjdb-format.
70
- def data
71
- return {
72
- :type => self.type,
73
- :name => self.name,
74
- :null => self.null?,
75
- :maxlength => self.maxlength,
76
- :default => self.default,
77
- :primarykey => self.primarykey?,
78
- :autoincr => self.autoincr?
79
- }
80
- end
81
-
82
- #Returns the type of the column.
83
- def type
84
- if !@type
85
- if match = @args[:data][:type].match(/^([A-z]+)$/)
86
- @maxlength = false
87
- type = match[0].to_sym
88
- elsif match = @args[:data][:type].match(/^decimal\((\d+),(\d+)\)$/)
89
- @maxlength = "#{match[1]},#{match[2]}"
90
- type = :decimal
91
- elsif match = @args[:data][:type].match(/^enum\((.+)\)$/)
92
- @maxlength = match[1]
93
- type = :enum
94
- elsif match = @args[:data][:type].match(/^(.+)\((\d+)\)$/)
95
- @maxlength = match[2]
96
- type = match[1].to_sym
97
- elsif @args[:data].key?(:type) and @args[:data][:type].to_s == ""
98
- #A type can actually be empty in SQLite... Wtf?
99
- return @args[:data][:type]
100
- end
101
-
102
- if type == :integer
103
- @type = :int
104
- else
105
- @type = type
106
- end
107
-
108
- raise "Still not type? (#{@args[:data]})" if @type.to_s.strip.length <= 0
109
- end
110
-
111
- return @type
112
- end
113
-
114
- #Returns true if the column allows null. Otherwise false.
115
- def null?
116
- return false if @args[:data][:notnull].to_i == 1
117
- return true
118
- end
119
-
120
- #Returns the maxlength of the column.
121
- def maxlength
122
- self.type if !@maxlength
123
- return @maxlength if @maxlength
124
- return false
125
- end
126
-
127
- #Returns the default value of the column.
128
- def default
129
- def_val = @args[:data][:dflt_value]
130
- if def_val.to_s.slice(0..0) == "'"
131
- def_val = def_val.to_s.slice(0)
132
- end
133
-
134
- if def_val.to_s.slice(-1..-1) == "'"
135
- def_val = def_val.to_s.slice(0, def_val.length - 1)
136
- end
137
-
138
- return false if @args[:data][:dflt_value].to_s.empty?
139
- return def_val
140
- end
141
-
142
- #Returns true if the column is the primary key.
143
- def primarykey?
144
- return false if @args[:data][:pk].to_i == 0
145
- return true
146
- end
147
-
148
- #Returns true if the column is auto-increasing.
149
- def autoincr?
150
- return true if @args[:data][:pk].to_i == 1 and @args[:data][:type].to_sym == :integer
151
- return false
152
- end
153
-
154
- #Drops the column from the table.
155
- def drop
156
- self.table.copy(:drops => self.name)
157
- end
158
-
159
- #Changes data on the column. Like the name, type, maxlength or whatever.
160
- def change(data)
161
- newdata = data.clone
162
-
163
- newdata[:name] = self.name if !newdata.key?(:name)
164
- newdata[:type] = self.type if !newdata.key?(:type)
165
- newdata[:maxlength] = self.maxlength if !newdata.key?(:maxlength) and self.maxlength
166
- newdata[:null] = self.null? if !newdata.key?(:null)
167
- newdata[:default] = self.default if !newdata.key?(:default)
168
- newdata[:primarykey] = self.primarykey? if !newdata.key?(:primarykey)
169
-
170
- @type = nil
171
- @maxlength = nil
172
-
173
- new_table = self.table.copy(
174
- :alter_columns => {
175
- self.name.to_sym => newdata
176
- }
177
- )
178
- end
179
- end
@@ -0,0 +1,55 @@
1
+ class Baza::Driver::Sqlite3::Index
2
+ attr_reader :args, :columns
3
+
4
+ def initialize(args)
5
+ @args = args
6
+ @columns = []
7
+ @db = args[:db]
8
+ end
9
+
10
+ def name
11
+ return @args[:data][:name]
12
+ end
13
+
14
+ def table_name
15
+ return @args[:table_name]
16
+ end
17
+
18
+ def table
19
+ return @db.tables[table_name]
20
+ end
21
+
22
+ def drop
23
+ @db.query("DROP INDEX `#{name}`")
24
+ end
25
+
26
+ def rename newname
27
+ newname = newname.to_sym
28
+
29
+ create_args = data
30
+ create_args[:name] = newname
31
+
32
+ drop
33
+ table.create_indexes([create_args])
34
+ @args[:data][:name] = newname
35
+ end
36
+
37
+ def data
38
+ return {
39
+ name: name,
40
+ columns: @columns
41
+ }
42
+ end
43
+
44
+ def column_names
45
+ @columns
46
+ end
47
+
48
+ def to_s
49
+ "#<Baza::Driver::Sqlite3::Index name: \"#{name}\", columns: #{@columns}>"
50
+ end
51
+
52
+ def inspect
53
+ to_s
54
+ end
55
+ end
@@ -3,55 +3,3 @@ class Baza::Driver::Sqlite3::Indexes
3
3
  @args = args
4
4
  end
5
5
  end
6
-
7
- class Baza::Driver::Sqlite3::Indexes::Index
8
- attr_reader :args, :columns
9
-
10
- def initialize(args)
11
- @args = args
12
- @columns = []
13
- @db = args[:db]
14
- end
15
-
16
- def name
17
- return @args[:data][:name]
18
- end
19
-
20
- def table_name
21
- return @args[:table_name]
22
- end
23
-
24
- def table
25
- return @db.tables[table_name]
26
- end
27
-
28
- def drop
29
- @db.query("DROP INDEX `#{name}`")
30
- end
31
-
32
- def rename newname
33
- newname = newname.to_sym
34
-
35
- create_args = data
36
- create_args[:name] = newname
37
-
38
- drop
39
- table.create_indexes([create_args])
40
- @args[:data][:name] = newname
41
- end
42
-
43
- def data
44
- return {
45
- name: name,
46
- columns: @columns
47
- }
48
- end
49
-
50
- def column_names
51
- @columns
52
- end
53
-
54
- def to_s
55
- "#<Baza::Driver::Sqlite3::Index name: \"#{name}\", columns: #{@columns}>"
56
- end
57
- end