baza 0.0.20 → 0.0.21

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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +84 -0
  3. data/.rubocop_todo.yml +17 -135
  4. data/.travis.yml +21 -0
  5. data/Gemfile +10 -7
  6. data/Gemfile.lock +39 -44
  7. data/README.md +61 -3
  8. data/VERSION +1 -1
  9. data/baza.gemspec +146 -98
  10. data/config/best_project_practice_rubocop.yml +8 -0
  11. data/config/best_project_practice_rubocop_todo.yml +6 -0
  12. data/lib/baza.rb +8 -12
  13. data/lib/baza/base_sql_driver.rb +198 -52
  14. data/lib/baza/cloner.rb +1 -0
  15. data/lib/baza/column.rb +26 -0
  16. data/lib/baza/database.rb +19 -3
  17. data/lib/baza/db.rb +69 -271
  18. data/lib/baza/driver.rb +1 -6
  19. data/lib/baza/{drivers → driver}/active_record.rb +65 -21
  20. data/lib/baza/{drivers → driver}/active_record/columns.rb +0 -0
  21. data/lib/baza/driver/active_record/commands.rb +10 -0
  22. data/lib/baza/driver/active_record/databases.rb +10 -0
  23. data/lib/baza/{drivers → driver}/active_record/indexes.rb +0 -0
  24. data/lib/baza/{drivers → driver}/active_record/result.rb +3 -1
  25. data/lib/baza/{drivers → driver}/active_record/tables.rb +0 -0
  26. data/lib/baza/driver/active_record/users.rb +12 -0
  27. data/lib/baza/{drivers → driver}/mysql.rb +9 -26
  28. data/lib/baza/{drivers → driver}/mysql/column.rb +14 -35
  29. data/lib/baza/{drivers → driver}/mysql/columns.rb +9 -12
  30. data/lib/baza/driver/mysql/commands.rb +39 -0
  31. data/lib/baza/driver/mysql/database.rb +64 -0
  32. data/lib/baza/driver/mysql/databases.rb +63 -0
  33. data/lib/baza/{drivers → driver}/mysql/index.rb +0 -0
  34. data/lib/baza/{drivers → driver}/mysql/indexes.rb +0 -0
  35. data/lib/baza/{drivers → driver}/mysql/result.rb +15 -7
  36. data/lib/baza/{drivers → driver}/mysql/sqlspecs.rb +0 -0
  37. data/lib/baza/{drivers → driver}/mysql/table.rb +27 -43
  38. data/lib/baza/{drivers → driver}/mysql/tables.rb +5 -34
  39. data/lib/baza/{drivers → driver}/mysql/unbuffered_result.rb +8 -2
  40. data/lib/baza/driver/mysql/user.rb +22 -0
  41. data/lib/baza/driver/mysql/users.rb +39 -0
  42. data/lib/baza/{drivers → driver}/mysql2.rb +19 -49
  43. data/lib/baza/{drivers → driver}/mysql2/column.rb +0 -0
  44. data/lib/baza/{drivers → driver}/mysql2/columns.rb +0 -0
  45. data/lib/baza/driver/mysql2/commands.rb +2 -0
  46. data/lib/baza/{drivers → driver}/mysql2/database.rb +0 -0
  47. data/lib/baza/{drivers → driver}/mysql2/databases.rb +0 -0
  48. data/lib/baza/{drivers → driver}/mysql2/index.rb +0 -0
  49. data/lib/baza/{drivers → driver}/mysql2/indexes.rb +0 -0
  50. data/lib/baza/{drivers → driver}/mysql2/result.rb +3 -1
  51. data/lib/baza/{drivers → driver}/mysql2/table.rb +0 -0
  52. data/lib/baza/{drivers → driver}/mysql2/tables.rb +0 -0
  53. data/lib/baza/driver/mysql2/user.rb +2 -0
  54. data/lib/baza/driver/mysql2/users.rb +2 -0
  55. data/lib/baza/{drivers → driver}/mysql_java.rb +60 -38
  56. data/lib/baza/{drivers → driver}/mysql_java/column.rb +0 -0
  57. data/lib/baza/{drivers → driver}/mysql_java/columns.rb +0 -0
  58. data/lib/baza/driver/mysql_java/commands.rb +2 -0
  59. data/lib/baza/driver/mysql_java/database.rb +2 -0
  60. data/lib/baza/driver/mysql_java/databases.rb +2 -0
  61. data/lib/baza/{drivers → driver}/mysql_java/index.rb +0 -0
  62. data/lib/baza/{drivers → driver}/mysql_java/indexes.rb +0 -0
  63. data/lib/baza/{drivers → driver}/mysql_java/table.rb +0 -0
  64. data/lib/baza/{drivers → driver}/mysql_java/tables.rb +0 -0
  65. data/lib/baza/driver/mysql_java/user.rb +2 -0
  66. data/lib/baza/driver/mysql_java/users.rb +2 -0
  67. data/lib/baza/driver/pg.rb +80 -0
  68. data/lib/baza/driver/pg/column.rb +125 -0
  69. data/lib/baza/driver/pg/columns.rb +37 -0
  70. data/lib/baza/driver/pg/commands.rb +35 -0
  71. data/lib/baza/driver/pg/create_index_sql_creator.rb +51 -0
  72. data/lib/baza/driver/pg/database.rb +89 -0
  73. data/lib/baza/driver/pg/databases.rb +79 -0
  74. data/lib/baza/driver/pg/index.rb +35 -0
  75. data/lib/baza/driver/pg/indexes.rb +5 -0
  76. data/lib/baza/driver/pg/result.rb +139 -0
  77. data/lib/baza/driver/pg/table.rb +184 -0
  78. data/lib/baza/driver/pg/tables.rb +45 -0
  79. data/lib/baza/{drivers → driver}/sqlite3.rb +6 -24
  80. data/lib/baza/{drivers → driver}/sqlite3/column.rb +22 -24
  81. data/lib/baza/{drivers → driver}/sqlite3/columns.rb +6 -6
  82. data/lib/baza/driver/sqlite3/commands.rb +28 -0
  83. data/lib/baza/{drivers → driver}/sqlite3/database.rb +0 -0
  84. data/lib/baza/{drivers → driver}/sqlite3/databases.rb +0 -1
  85. data/lib/baza/{drivers → driver}/sqlite3/index.rb +0 -0
  86. data/lib/baza/{drivers → driver}/sqlite3/indexes.rb +0 -0
  87. data/lib/baza/{drivers → driver}/sqlite3/result.rb +14 -6
  88. data/lib/baza/{drivers → driver}/sqlite3/sqlspecs.rb +0 -0
  89. data/lib/baza/{drivers → driver}/sqlite3/table.rb +25 -16
  90. data/lib/baza/{drivers → driver}/sqlite3/tables.rb +5 -6
  91. data/lib/baza/{drivers → driver}/sqlite3/unbuffered_result.rb +8 -2
  92. data/lib/baza/{drivers → driver}/sqlite3_java.rb +13 -23
  93. data/lib/baza/{drivers → driver}/sqlite3_java/column.rb +0 -0
  94. data/lib/baza/{drivers → driver}/sqlite3_java/columns.rb +0 -0
  95. data/lib/baza/driver/sqlite3_java/commands.rb +2 -0
  96. data/lib/baza/{drivers → driver}/sqlite3_java/database.rb +0 -0
  97. data/lib/baza/{drivers → driver}/sqlite3_java/index.rb +0 -0
  98. data/lib/baza/{drivers → driver}/sqlite3_java/indexes.rb +0 -0
  99. data/lib/baza/{drivers → driver}/sqlite3_java/table.rb +0 -0
  100. data/lib/baza/{drivers → driver}/sqlite3_java/tables.rb +0 -0
  101. data/lib/baza/{drivers → driver}/sqlite3_java/unbuffered_result.rb +14 -9
  102. data/lib/baza/{drivers → driver}/sqlite3_rhodes.rb +6 -24
  103. data/lib/baza/errors.rb +2 -0
  104. data/lib/baza/idquery.rb +15 -8
  105. data/lib/baza/index.rb +7 -0
  106. data/lib/baza/jdbc_driver.rb +4 -16
  107. data/lib/baza/jdbc_result.rb +20 -12
  108. data/lib/baza/mysql_base_driver.rb +7 -7
  109. data/lib/baza/query_buffer.rb +20 -19
  110. data/lib/baza/row.rb +16 -16
  111. data/lib/baza/sql_queries.rb +3 -0
  112. data/lib/baza/sql_queries/generic_insert.rb +81 -0
  113. data/lib/baza/sql_queries/generic_update.rb +31 -0
  114. data/lib/baza/sql_queries/mysql_upsert.rb +52 -0
  115. data/lib/baza/sql_queries/mysql_upsert_duplicate_key.rb +57 -0
  116. data/lib/baza/sql_queries/non_atomic_upsert.rb +25 -0
  117. data/lib/baza/sql_queries/postgres_upsert_duplicate_key.rb +118 -0
  118. data/lib/baza/sql_queries/select.rb +170 -0
  119. data/lib/baza/sql_queries/sqlite_upsert_duplicate_key.rb +99 -0
  120. data/lib/baza/table.rb +35 -8
  121. data/spec/active_record/models/user.rb +3 -0
  122. data/spec/{cloner_spec.rb → baza/cloner_spec.rb} +0 -0
  123. data/spec/drivers/active_record_mysql2_spec.rb +5 -3
  124. data/spec/drivers/active_record_mysql_spec.rb +2 -1
  125. data/spec/drivers/active_record_pg_spec.rb +20 -0
  126. data/spec/drivers/active_record_sqlite3_spec.rb +2 -1
  127. data/spec/drivers/mysql2_spec.rb +1 -1
  128. data/spec/drivers/mysql_spec.rb +10 -10
  129. data/spec/drivers/pg_spec.rb +18 -0
  130. data/spec/drivers/sqlite3_spec.rb +7 -8
  131. data/spec/info_active_record_example.rb +1 -1
  132. data/spec/{info_active_record_mysql2.rb → info_active_record_mysql2_example.rb} +3 -2
  133. data/spec/info_active_record_mysql2_travis.rb +35 -0
  134. data/spec/{info_active_record_mysql.rb → info_active_record_mysql_example.rb} +5 -4
  135. data/spec/info_active_record_mysql_travis.rb +36 -0
  136. data/spec/info_active_record_pg_example.rb +36 -0
  137. data/spec/info_active_record_pg_travis.rb +34 -0
  138. data/spec/info_active_record_sqlite3.rb +1 -1
  139. data/spec/info_mysql2_example.rb +1 -3
  140. data/spec/{info_mysql2_shippable.rb → info_mysql2_travis.rb} +2 -4
  141. data/spec/info_mysql_example.rb +1 -3
  142. data/spec/{info_mysql_shippable.rb → info_mysql_travis.rb} +2 -4
  143. data/spec/info_pg_example.rb +22 -0
  144. data/spec/info_pg_travis.rb +20 -0
  145. data/spec/info_sqlite3.rb +1 -3
  146. data/spec/spec_helper.rb +1 -1
  147. data/spec/support/driver_active_record_collection.rb +62 -0
  148. data/spec/support/driver_collection.rb +136 -121
  149. data/spec/support/driver_columns_collection.rb +19 -10
  150. data/spec/support/driver_databases_collection.rb +23 -1
  151. data/spec/support/driver_indexes_collection.rb +2 -2
  152. data/spec/support/driver_tables_collection.rb +24 -4
  153. data/spec/support/driver_users_collection.rb +53 -0
  154. metadata +185 -104
  155. data/lib/baza/drivers/mysql/database.rb +0 -28
  156. data/lib/baza/drivers/mysql/databases.rb +0 -35
  157. data/lib/baza/drivers/mysql_java/database.rb +0 -2
  158. data/lib/baza/drivers/mysql_java/databases.rb +0 -2
  159. data/lib/baza/model.rb +0 -875
  160. data/lib/baza/model_custom.rb +0 -155
  161. data/lib/baza/model_handler.rb +0 -910
  162. data/lib/baza/model_handler_sqlhelper.rb +0 -484
  163. data/lib/baza/revision.rb +0 -383
  164. data/shippable.yml +0 -17
  165. data/spec/info_active_record_mysql2_shippable.rb +0 -34
  166. data/spec/info_active_record_mysql_shippable.rb +0 -34
  167. data/spec/model_handler_spec.rb +0 -431
@@ -1,5 +1,11 @@
1
1
 
2
2
 
3
+
4
+
5
+
6
+
7
+
8
+
3
9
  # This configuration was generated by
4
10
  # `rubocop --auto-gen-config`
5
11
  # on 2015-12-20 21:21:20 +0100 using RuboCop version 0.35.1.
@@ -1,16 +1,12 @@
1
1
  require "array_enumerator"
2
- require "wref"
2
+ require "auto_autoloader"
3
3
  require "datet"
4
+ require "simple_delegate"
4
5
  require "string-cases"
6
+ require "wref"
5
7
 
6
8
  class Baza
7
- # Autoloader for subclasses.
8
- def self.const_missing(name)
9
- file_name = name.to_s.gsub(/(.)([A-Z])/, '\1_\2').downcase
10
- require "#{File.dirname(__FILE__)}/baza/#{file_name}.rb"
11
- raise "Still not defined: '#{name}'." unless Baza.const_defined?(name)
12
- Baza.const_get(name)
13
- end
9
+ AutoAutoloader.autoload_sub_classes(self, __FILE__)
14
10
 
15
11
  class << self
16
12
  attr_writer :default_db
@@ -37,7 +33,7 @@ class Baza
37
33
 
38
34
  def self.drivers
39
35
  Enumerator.new do |yielder|
40
- Dir.foreach("#{File.dirname(__FILE__)}/baza/drivers") do |file|
36
+ Dir.foreach("#{File.dirname(__FILE__)}/baza/driver") do |file|
41
37
  if (match = file.match(/\A(.+?)\.rb\Z/))
42
38
  load_driver(match[1])
43
39
 
@@ -53,11 +49,11 @@ class Baza
53
49
  end
54
50
 
55
51
  def self.load_driver(name)
56
- require_relative "baza/drivers/#{name}"
52
+ require_relative "baza/driver/#{name}"
57
53
 
58
- loads = %w(databases database tables table columns column indexes index result)
54
+ loads = %w(databases database tables table columns column indexes index result commands)
59
55
  loads.each do |load|
60
- file_path = "#{File.dirname(__FILE__)}/baza/drivers/#{name}/#{load}"
56
+ file_path = "#{File.dirname(__FILE__)}/baza/driver/#{name}/#{load}"
61
57
  require_relative file_path if File.exist?(file_path)
62
58
  end
63
59
  end
@@ -1,16 +1,18 @@
1
1
  class Baza::BaseSqlDriver
2
- attr_reader :baza, :conn, :sep_table, :sep_col, :sep_val
2
+ attr_reader :db, :conn, :sep_database, :sep_table, :sep_col, :sep_val, :sep_index
3
3
  attr_accessor :tables, :cols, :indexes
4
4
 
5
5
  def self.from_object(_args)
6
6
  end
7
7
 
8
- def initialize(baza)
9
- @baza = baza
8
+ def initialize(db)
9
+ @db = db
10
10
 
11
+ @sep_database = "`"
11
12
  @sep_table = "`"
12
13
  @sep_col = "`"
13
14
  @sep_val = "'"
15
+ @sep_index = "`"
14
16
  end
15
17
 
16
18
  def escape(string)
@@ -25,26 +27,43 @@ class Baza::BaseSqlDriver
25
27
  end
26
28
  end
27
29
 
28
- alias_method :esc, :escape
29
- alias_method :escape_alternative, :escape
30
+ alias esc escape
31
+ alias escape_alternative escape
30
32
 
31
33
  # Escapes a string to be used as a column.
32
34
  def escape_column(string)
33
35
  string = string.to_s
34
- raise "Invalid column-string: #{string}" unless string.index(@sep_col).nil?
36
+ raise "Invalid column-string: #{string}" if string.include?(@sep_col)
37
+ string
38
+ end
39
+
40
+ def escape_table(string)
41
+ string = string.to_s
42
+ raise "Invalid table-string: #{string}" if string.include?(@sep_table)
43
+ string
44
+ end
45
+
46
+ def escape_database(string)
47
+ string = string.to_s
48
+ raise "Invalid database-string: #{string}" if string.include?(@sep_database)
49
+ string
50
+ end
51
+
52
+ def escape_index(string)
53
+ string = string.to_s
54
+ raise "Invalid index-string: #{string}" if string.include?(@sep_index)
35
55
  string
36
56
  end
37
- alias escape_table escape_column
38
- alias escape_database escape_column
39
57
 
40
58
  def transaction
41
- @baza.q("BEGIN TRANSACTION")
59
+ @db.q("BEGIN TRANSACTION")
42
60
 
43
61
  begin
44
- yield @baza
45
- @baza.q("COMMIT")
46
- rescue => e
47
- @baza.q("ROLLBACK")
62
+ yield @db
63
+ @db.q("COMMIT")
64
+ rescue
65
+ @db.q("ROLLBACK")
66
+ raise
48
67
  end
49
68
  end
50
69
 
@@ -54,70 +73,197 @@ class Baza::BaseSqlDriver
54
73
  # db.insert(:users, name: "John", lastname: "Doe")
55
74
  # id = db.insert(:users, {name: "John", lastname: "Doe"}, return_id: true)
56
75
  # sql = db.insert(:users, {name: "John", lastname: "Doe"}, return_sql: true) #=> "INSERT INTO `users` (`name`, `lastname`) VALUES ('John', 'Doe')"
57
- def insert(tablename, arr_insert, args = nil)
58
- sql = "INSERT INTO #{@sep_table}#{escape_table(tablename)}#{@sep_table}"
59
-
60
- if !arr_insert || arr_insert.empty?
61
- # This is the correct syntax for inserting a blank row in MySQL.
62
- if @baza.opts.fetch(:type).to_s.include?("mysql")
63
- sql << " VALUES ()"
64
- elsif @baza.opts.fetch(:type).to_s.include?("sqlite3")
65
- sql << " DEFAULT VALUES"
76
+ def insert(table_name, data, args = {})
77
+ Baza::SqlQueries::GenericInsert.new({
78
+ db: @db,
79
+ table_name: table_name,
80
+ data: data
81
+ }.merge(args)).execute
82
+ end
83
+
84
+ def insert_multi(tablename, arr_hashes, args = {})
85
+ sql = [] if args && args[:return_sql]
86
+
87
+ @db.transaction do
88
+ arr_hashes.each do |hash|
89
+ res = @db.insert(tablename, hash, args)
90
+ sql << res if args && args[:return_sql]
91
+ end
92
+ end
93
+
94
+ return sql if args && args[:return_sql]
95
+ nil
96
+ end
97
+
98
+ def supports_multiple_databases?
99
+ false
100
+ end
101
+
102
+ SELECT_ARGS_ALLOWED_KEYS = [:limit, :limit_from, :limit_to].freeze
103
+ # 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.
104
+ def select(tablename, arr_terms = nil, args = nil, &block)
105
+ # Set up vars.
106
+ sql = ""
107
+ args_q = nil
108
+ select_sql = "*"
109
+
110
+ # Give 'cloned_ubuf' argument to 'q'-method.
111
+ args_q = {cloned_ubuf: true} if args && args[:cloned_ubuf]
112
+
113
+ # Set up IDQuery-stuff if that is given in arguments.
114
+ if args && args[:idquery]
115
+ if args.fetch(:idquery) == true
116
+ select_sql = "#{sep_col}id#{sep_col}"
117
+ col = :id
66
118
  else
67
- raise "Unknown database-type: '#{@baza.opts.fetch(:type)}'."
119
+ select_sql = "#{sep_col}#{escape_column(args.fetch(:idquery))}#{sep_col}"
120
+ col = args.fetch(:idquery)
68
121
  end
122
+ end
123
+
124
+ sql = "SELECT #{select_sql} FROM"
125
+
126
+ if tablename.is_a?(Array)
127
+ sql << " #{@sep_table}#{tablename.first}#{@sep_table}.#{@sep_table}#{tablename.last}#{@sep_table}"
69
128
  else
70
- sql << " ("
129
+ sql << " #{@sep_table}#{tablename}#{@sep_table}"
130
+ end
71
131
 
72
- first = true
73
- arr_insert.each_key do |key|
74
- if first
75
- first = false
132
+ if !arr_terms.nil? && !arr_terms.empty?
133
+ sql << " WHERE #{sql_make_where(arr_terms)}"
134
+ end
135
+
136
+ unless args.nil?
137
+ if args[:orderby]
138
+ sql << " ORDER BY"
139
+
140
+ if args.fetch(:orderby).is_a?(Array)
141
+ first = true
142
+ args.fetch(:orderby).each do |order_by|
143
+ sql << "," unless first
144
+ first = false if first
145
+ sql << " #{sep_col}#{escape_column(order_by)}#{sep_col}"
146
+ end
76
147
  else
77
- sql << ", "
148
+ sql << " #{sep_col}#{escape_column(args.fetch(:orderby))}#{sep_col}"
78
149
  end
79
-
80
- sql << "#{@baza.sep_col}#{@baza.escape_column(key)}#{@baza.sep_col}"
81
150
  end
82
151
 
83
- sql << ") VALUES ("
152
+ sql << " LIMIT #{args[:limit]}" if args[:limit]
84
153
 
85
- first = true
86
- arr_insert.each_value do |value|
87
- if first
88
- first = false
89
- else
90
- sql << ", "
154
+ if args[:limit_from] && args[:limit_to]
155
+ begin
156
+ Float(args[:limit_from])
157
+ rescue
158
+ raise "'limit_from' was not numeric: '#{args.fetch(:limit_from)}'."
159
+ end
160
+
161
+ begin
162
+ Float(args[:limit_to])
163
+ rescue
164
+ raise "'limit_to' was not numeric: '#{args[:limit_to]}'."
91
165
  end
92
166
 
93
- sql << @baza.sqlval(value)
167
+ sql << " LIMIT #{args.fetch(:limit_from)}, #{args.fetch(:limit_to)}"
94
168
  end
169
+ end
170
+
171
+ # Do IDQuery if given in arguments.
172
+ if args && args[:idquery]
173
+ res = Baza::Idquery.new(db: @db, table: tablename, query: sql, col: col, &block)
174
+ else
175
+ res = @db.q(sql, args_q, &block)
176
+ end
177
+
178
+ # Return result if a block wasnt given.
179
+ if block
180
+ return nil
181
+ else
182
+ return res
183
+ end
184
+ end
185
+
186
+ def count(tablename, arr_terms = nil)
187
+ sql = "SELECT COUNT(*) AS count FROM #{@sep_table}#{tablename}#{@sep_table}"
95
188
 
96
- sql << ")"
189
+ if !arr_terms.nil? && !arr_terms.empty?
190
+ sql << " WHERE #{sql_make_where(arr_terms)}"
191
+ end
192
+
193
+ query(sql).fetch.fetch(:count).to_i
194
+ end
195
+
196
+ # Returns a single row from a database.
197
+ #
198
+ #===Examples
199
+ # row = db.single(:users, lastname: "Doe")
200
+ def single(tablename, terms = nil, args = {})
201
+ # Experienced very weird memory leak if this was not done by block. Maybe bug in Ruby 1.9.2? - knj
202
+ select(tablename, terms, args.merge(limit: 1)).fetch
203
+ end
204
+
205
+ # Deletes rows from the database.
206
+ #
207
+ #===Examples
208
+ # db.delete(:users, {lastname: "Doe"})
209
+ def delete(tablename, arr_terms, args = nil)
210
+ sql = "DELETE FROM #{@sep_table}#{tablename}#{@sep_table}"
211
+
212
+ if !arr_terms.nil? && !arr_terms.empty?
213
+ sql << " WHERE #{sql_make_where(arr_terms)}"
97
214
  end
98
215
 
99
216
  return sql if args && args[:return_sql]
100
217
 
101
- @baza.query(sql)
102
- return @baza.last_id if args && args[:return_id]
218
+ query(sql)
103
219
  nil
104
220
  end
105
221
 
106
- def insert_multi(tablename, arr_hashes, args = nil)
107
- sql = [] if args && args[:return_sql]
222
+ # Internally used to generate SQL.
223
+ #
224
+ #===Examples
225
+ # sql = db.sql_make_where({lastname: "Doe"}, driver_obj)
226
+ def sql_make_where(arr_terms, _driver = nil)
227
+ sql = ""
108
228
 
109
- @baza.transaction do
110
- arr_hashes.each do |hash|
111
- res = @baza.insert(tablename, hash, args)
112
- sql << res if args && args[:return_sql]
229
+ first = true
230
+ arr_terms.each do |key, value|
231
+ if first
232
+ first = false
233
+ else
234
+ sql << " AND "
235
+ end
236
+
237
+ if value.is_a?(Array)
238
+ raise "Array for column '#{key}' was empty." if value.empty?
239
+ values = value.map { |v| "'#{escape(v)}'" }.join(",")
240
+ sql << "#{@sep_col}#{key}#{@sep_col} IN (#{values})"
241
+ elsif value.is_a?(Hash)
242
+ raise "Dont know how to handle hash."
243
+ else
244
+ sql << "#{@sep_col}#{key}#{@sep_col} = #{sqlval(value)}"
113
245
  end
114
246
  end
115
247
 
116
- return sql if args && args[:return_sql]
117
- nil
248
+ sql
118
249
  end
119
250
 
120
- def supports_multiple_databases?
121
- false
251
+ # Returns the correct SQL-value for the given value.
252
+ # If it is a number, then just the raw number as a string will be returned.
253
+ # nil's will be NULL and strings will have quotes and will be escaped.
254
+ def sqlval(val)
255
+ return @conn.sqlval(val) if @conn.respond_to?(:sqlval)
256
+
257
+ if val.is_a?(Fixnum) || val.is_a?(Integer)
258
+ val.to_s
259
+ elsif val == nil
260
+ "NULL"
261
+ elsif val.is_a?(Date)
262
+ "#{@sep_val}#{Datet.in(val).dbstr(time: false)}#{@sep_val}"
263
+ elsif val.is_a?(Time) || val.is_a?(DateTime) || val.is_a?(Datet)
264
+ "#{@sep_val}#{Datet.in(val).dbstr}#{@sep_val}"
265
+ else
266
+ "#{@sep_val}#{escape(val)}#{@sep_val}"
267
+ end
122
268
  end
123
269
  end
@@ -17,6 +17,7 @@ class Baza::Cloner
17
17
  Baza::Db.new(db_args)
18
18
  elsif connection.class.name.include?("MysqlAdapter")
19
19
  connection = connection.instance_variable_get(:@connection)
20
+ connection = connection.instance_variable_get(:@connection) if RUBY_PLATFORM == "java"
20
21
 
21
22
  db_args = {
22
23
  type: :mysql,
@@ -12,4 +12,30 @@ class Baza::Column
12
12
  def to_param
13
13
  name
14
14
  end
15
+
16
+ def table
17
+ @db.tables[table_name]
18
+ end
19
+
20
+ def after
21
+ last = nil
22
+ table.columns.each do |column|
23
+ break if column.name == name
24
+ last = column.name
25
+ end
26
+
27
+ last
28
+ end
29
+
30
+ def data
31
+ {
32
+ type: type,
33
+ name: name,
34
+ null: null?,
35
+ maxlength: maxlength,
36
+ default: default,
37
+ primarykey: primarykey?,
38
+ autoincr: autoincr?
39
+ }
40
+ end
15
41
  end
@@ -11,16 +11,28 @@ class Baza::Database
11
11
  @name_was = @name
12
12
  end
13
13
 
14
- def tables
14
+ def tables(args = {})
15
+ list_args = {database: name}
16
+ list_args[:name] = args.fetch(:name) if args[:name]
17
+
15
18
  ArrayEnumerator.new do |yielder|
16
- @db.tables.list(database: name) do |table|
19
+ @db.tables.list(list_args) do |table|
17
20
  yielder << table
18
21
  end
19
22
  end
20
23
  end
21
24
 
22
25
  def table(name)
23
- @db.tables[name]
26
+ table = tables(name: name).first
27
+ raise Baza::Errors::TableNotFound unless table
28
+ table
29
+ end
30
+
31
+ def table_exists?(name)
32
+ table(name)
33
+ true
34
+ rescue Baza::Errors::TableNotFound
35
+ false
24
36
  end
25
37
 
26
38
  def save!
@@ -30,4 +42,8 @@ class Baza::Database
30
42
  def to_param
31
43
  name
32
44
  end
45
+
46
+ def use(&blk)
47
+ @db.databases.with_database(name, &blk)
48
+ end
33
49
  end
@@ -12,11 +12,17 @@
12
12
  # print data[:name]
13
13
  # end
14
14
  class Baza::Db
15
- attr_reader :sep_col, :sep_table, :sep_val, :opts, :driver, :int_types
15
+ include SimpleDelegate
16
+
17
+ delegate :last_id, :upsert, :upsert_duplicate_key, to: :commands
18
+ delegate :current_database, :current_database_name, :with_database, to: :databases
19
+ delegate :close, :count, :delete, :esc, :escape, :escape_column, :escape_table, :escape_database, :escape_index, :insert, :select, :single, :sqlval, :sql_make_where, to: :driver
20
+
21
+ attr_reader :sep_database, :sep_col, :sep_table, :sep_val, :sep_index, :opts, :driver, :int_types
16
22
 
17
23
  # Returns an array containing hashes of information about each registered driver.
18
24
  def self.drivers
19
- path = "#{File.dirname(__FILE__)}/drivers"
25
+ path = "#{File.dirname(__FILE__)}/driver"
20
26
  drivers = []
21
27
 
22
28
  Dir.foreach(path) do |file|
@@ -68,8 +74,10 @@ class Baza::Db
68
74
 
69
75
  @debug = @opts[:debug]
70
76
  @driver = spawn
77
+ @sep_database = @driver.sep_database
71
78
  @sep_table = @driver.sep_table
72
79
  @sep_col = @driver.sep_col
80
+ @sep_index = @driver.sep_index
73
81
  @sep_val = @driver.sep_val
74
82
 
75
83
  return unless block_given?
@@ -104,13 +112,13 @@ class Baza::Db
104
112
  # driver_instance = db.spawn
105
113
  def spawn
106
114
  raise "No type given (#{@opts.keys.join(",")})." unless @opts[:type]
107
- rpath = "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}.rb"
115
+ rpath = "#{File.dirname(__FILE__)}/driver/#{@opts.fetch(:type)}.rb"
108
116
  require rpath if File.exist?(rpath)
109
117
  Baza::Driver.const_get(@type_cc).new(self)
110
118
  end
111
119
 
112
120
  # Registers a driver to the current thread.
113
- def get_and_register_thread
121
+ def register_thread
114
122
  raise "Baza-object is not in threadding mode" unless @conns
115
123
 
116
124
  thread_cur = Thread.current
@@ -141,15 +149,13 @@ class Baza::Db
141
149
  @closed = true
142
150
  end
143
151
 
144
- # rubocop:disable Style/TrivialAccessors
145
152
  def closed?
146
- # rubocop:enable Style/TrivialAccessors
147
153
  @closed
148
154
  end
149
155
 
150
156
  # Clones the current database-connection with possible extra arguments.
151
157
  def clone_conn(args = {})
152
- conn = Baza::Db.new(opts = @opts.clone.merge(args))
158
+ conn = Baza::Db.new(@opts.merge(args))
153
159
 
154
160
  if block_given?
155
161
  begin
@@ -164,7 +170,7 @@ class Baza::Db
164
170
  end
165
171
  end
166
172
 
167
- COPY_TO_ALLOWED_ARGS = [:tables, :debug]
173
+ COPY_TO_ALLOWED_ARGS = [:tables, :debug].freeze
168
174
  # Copies the content of the current database to another instance of Baza::Db.
169
175
  def copy_to(db, args = {})
170
176
  debug = args[:debug]
@@ -221,31 +227,10 @@ class Baza::Db
221
227
  {tables: tables_ret}
222
228
  end
223
229
 
224
- def insert(table_name, data, args = nil)
225
- @driver.insert(table_name, data, args)
226
- end
227
-
228
230
  def add_sql_to_error(error, sql)
229
231
  error.message << " (SQL: #{sql})"
230
232
  end
231
233
 
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.
233
- def sqlval(val)
234
- return @conn.sqlval(val) if @conn.respond_to?(:sqlval)
235
-
236
- if val.is_a?(Fixnum) || val.is_a?(Integer)
237
- return val.to_s
238
- elsif val == nil
239
- return "NULL"
240
- elsif val.is_a?(Date)
241
- return "#{@sep_val}#{Datet.in(val).dbstr(time: false)}#{@sep_val}"
242
- elsif val.is_a?(Time) || val.is_a?(DateTime)
243
- return "#{@sep_val}#{Datet.in(val).dbstr}#{@sep_val}"
244
- else
245
- return "#{@sep_val}#{escape(val)}#{@sep_val}"
246
- end
247
- end
248
-
249
234
  # Simply and optimal insert multiple rows into a table in a single query. Uses the drivers functionality if supported or inserts each row manually.
250
235
  #
251
236
  #===Examples
@@ -253,7 +238,7 @@ class Baza::Db
253
238
  # {name: "John", lastname: "Doe"},
254
239
  # {name: "Kasper", lastname: "Johansen"}
255
240
  # ])
256
- def insert_multi(tablename, arr_hashes, args = nil)
241
+ def insert_multi(tablename, arr_hashes, args = {})
257
242
  return false if arr_hashes.empty?
258
243
 
259
244
  if @driver.respond_to?(:insert_multi)
@@ -284,191 +269,24 @@ class Baza::Db
284
269
  #
285
270
  #===Examples
286
271
  # db.update(:users, {name: "John"}, {lastname: "Doe"})
287
- def update(tablename, hash_update, arr_terms = {}, args = nil)
288
- raise "'hash_update' was not a hash: '#{hash_update.class.name}'." unless hash_update.is_a?(Hash)
289
- return false if hash_update.empty?
290
-
291
- sql = ""
292
- sql << "UPDATE #{@sep_col}#{tablename}#{@sep_col} SET "
293
-
294
- first = true
295
- hash_update.each do |key, value|
296
- if first
297
- first = false
298
- else
299
- sql << ", "
300
- end
301
-
302
- # Convert dates to valid dbstr.
303
- value = date_out(value) if value.is_a?(Datet) || value.is_a?(Time)
304
-
305
- sql << "#{@sep_col}#{escape_column(key)}#{@sep_col} = "
306
- sql << sqlval(value)
307
- end
308
-
309
- sql << " WHERE #{makeWhere(arr_terms)}" if arr_terms && arr_terms.length > 0
310
-
311
- return sql if args && args[:return_sql]
312
-
313
- query(sql)
314
- end
315
-
316
- # Checks if a given terms exists. If it does, updates it to match data. If not inserts the row.
317
- def upsert(table, data, terms, args = nil)
318
- row = single(table, terms)
319
-
320
- if args && args[:buffer]
321
- obj = args[:buffer]
322
- else
323
- obj = self
324
- end
325
-
326
- if row
327
- obj.update(table, data, terms)
328
- else
329
- obj.insert(table, terms.merge(data))
330
- end
331
- end
332
-
333
- SELECT_ARGS_ALLOWED_KEYS = [:limit, :limit_from, :limit_to]
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.
335
- def select(tablename, arr_terms = nil, args = nil, &block)
336
- # Set up vars.
337
- sql = ""
338
- args_q = nil
339
- select_sql = "*"
340
-
341
- # Give 'cloned_ubuf' argument to 'q'-method.
342
- args_q = {cloned_ubuf: true} if args && args[:cloned_ubuf]
343
-
344
- # Set up IDQuery-stuff if that is given in arguments.
345
- if args && args[:idquery]
346
- if args[:idquery] == true
347
- select_sql = "`id`"
348
- col = :id
349
- else
350
- select_sql = "`#{escape_column(args[:idquery])}`"
351
- col = args[:idquery]
352
- end
353
- end
354
-
355
- sql = "SELECT #{select_sql} FROM"
356
-
357
- if tablename.is_a?(Array)
358
- sql << " #{@sep_table}#{tablename.first}#{@sep_table}.#{@sep_table}#{tablename.last}#{@sep_table}"
272
+ def update(table_name, data, terms = {}, args = {})
273
+ command = Baza::SqlQueries::GenericUpdate.new(
274
+ db: self,
275
+ table_name: table_name,
276
+ data: data,
277
+ terms: terms,
278
+ buffer: args[:buffer]
279
+ )
280
+
281
+ if args[:return_sql]
282
+ command.to_sql
359
283
  else
360
- sql << " #{@sep_table}#{tablename}#{@sep_table}"
361
- end
362
-
363
- if !arr_terms.nil? && !arr_terms.empty?
364
- sql << " WHERE #{makeWhere(arr_terms)}"
365
- end
366
-
367
- unless args.nil?
368
- sql << " ORDER BY #{args[:orderby]}" if args[:orderby]
369
- sql << " LIMIT #{args[:limit]}" if args[:limit]
370
-
371
- if args[:limit_from] && args[:limit_to]
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
-
384
- sql << " LIMIT #{args[:limit_from]}, #{args[:limit_to]}"
385
- end
386
- end
387
-
388
- # Do IDQuery if given in arguments.
389
- if args && args[:idquery]
390
- res = Baza::Idquery.new(db: self, table: tablename, query: sql, col: col, &block)
391
- else
392
- res = q(sql, args_q, &block)
393
- end
394
-
395
- # Return result if a block wasnt given.
396
- if block
397
- return nil
398
- else
399
- return res
284
+ command.execute
400
285
  end
401
286
  end
402
287
 
403
- def count(tablename, arr_terms = nil)
404
- # Set up vars.
405
- sql = ""
406
- args_q = nil
407
-
408
- sql = "SELECT COUNT(*) AS count FROM #{@sep_table}#{tablename}#{@sep_table}"
409
-
410
- if !arr_terms.nil? && !arr_terms.empty?
411
- sql << " WHERE #{makeWhere(arr_terms)}"
412
- end
413
-
414
- q(sql).fetch.fetch(:count).to_i
415
- end
416
-
417
- # Returns a single row from a database.
418
- #
419
- #===Examples
420
- # row = db.single(:users, lastname: "Doe")
421
- def single(tablename, terms = nil, args = {})
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
424
- end
425
-
426
- alias_method :selectsingle, :single
427
-
428
- # Deletes rows from the database.
429
- #
430
- #===Examples
431
- # db.delete(:users, {lastname: "Doe"})
432
- def delete(tablename, arr_terms, args = nil)
433
- sql = "DELETE FROM #{@sep_table}#{tablename}#{@sep_table}"
434
-
435
- if !arr_terms.nil? && !arr_terms.empty?
436
- sql << " WHERE #{makeWhere(arr_terms)}"
437
- end
438
-
439
- return sql if args && args[:return_sql]
440
-
441
- query(sql)
442
- nil
443
- end
444
-
445
- # Internally used to generate SQL.
446
- #
447
- #===Examples
448
- # sql = db.makeWhere({lastname: "Doe"}, driver_obj)
449
- def makeWhere(arr_terms, _driver = nil)
450
- sql = ""
451
-
452
- first = true
453
- arr_terms.each do |key, value|
454
- if first
455
- first = false
456
- else
457
- sql << " AND "
458
- end
459
-
460
- if value.is_a?(Array)
461
- raise "Array for column '#{key}' was empty." if value.empty?
462
- values = value.map { |v| "'#{escape(v)}'" }.join(",")
463
- sql << "#{@sep_col}#{key}#{@sep_col} IN (#{values})"
464
- elsif value.is_a?(Hash)
465
- raise "Dont know how to handle hash."
466
- else
467
- sql << "#{@sep_col}#{key}#{@sep_col} = #{sqlval(value)}"
468
- end
469
- end
470
-
471
- sql
288
+ def in_transaction?
289
+ @in_transaction
472
290
  end
473
291
 
474
292
  # Executes a query and returns the result.
@@ -519,7 +337,7 @@ class Baza::Db
519
337
  # db.query_ubuf('SELECT * FROM users') do |data|
520
338
  # print data[:name]
521
339
  # end
522
- def query_ubuf(string, args = nil, &block)
340
+ def query_ubuf(string, _args = nil, &block)
523
341
  ret = @driver.query_ubuf(string)
524
342
 
525
343
  if block
@@ -555,38 +373,6 @@ class Baza::Db
555
373
  nil
556
374
  end
557
375
 
558
- # Returns the last inserted ID.
559
- #
560
- #===Examples
561
- # id = db.last_id
562
- def last_id
563
- @driver.last_id
564
- end
565
-
566
- # Escapes a string to be safe-to-use in a query-string.
567
- #
568
- #===Examples
569
- # db.q("INSERT INTO users (name) VALUES ('#{db.esc('John')}')")
570
- def escape(string)
571
- @driver.escape(string)
572
- end
573
-
574
- alias_method :esc, :escape
575
-
576
- # Escapes the given string to be used as a column.
577
- def escape_column(str)
578
- @driver.escape_column(str)
579
- end
580
-
581
- # Escapes the given string to be used as a table.
582
- def escape_table(str)
583
- @driver.escape_table(str)
584
- end
585
-
586
- def escape_database(str)
587
- @driver.escape_database(str)
588
- end
589
-
590
376
  # Returns a string which can be used in SQL with the current driver.
591
377
  #===Examples
592
378
  # str = db.date_out(Time.now) #=> "2012-05-20 22:06:09"
@@ -600,33 +386,23 @@ class Baza::Db
600
386
  # db.date_in('2012-05-20 22:06:09') #=> 2012-05-20 22:06:09 +0200
601
387
  def date_in(date_obj)
602
388
  return @driver.date_in(date_obj) if @driver.respond_to?(:date_in)
603
-
604
389
  Datet.in(date_obj)
605
390
  end
606
391
 
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
611
-
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)
615
- end
616
-
617
- # Returns the columns-module and spawns it if it isnt already spawned.
618
- def cols
619
- @cols || Baza::Driver.const_get(@type_cc).const_get(:Columns).new(db: self)
620
- end
621
-
622
- # Returns the index-module and spawns it if it isnt already spawned.
623
- def indexes
624
- @indexes ||= Baza::Driver.const_get(@type_cc).const_get(:Indexes).new(db: self)
625
- end
392
+ # Defines all the driver methods: tables, columns and so on
393
+ DRIVER_PARTS = [:databases, :tables, :commands, :columns, :indexes, :users, :sqlspecs].freeze
394
+ DRIVER_PARTS.each do |driver_part|
395
+ define_method(driver_part) do
396
+ if instance_variable_defined?(:"@#{driver_part}")
397
+ instance_variable_get(:"@#{driver_part}")
398
+ else
399
+ require_relative "driver/#{@opts.fetch(:type)}/#{driver_part}"
626
400
 
627
- # Returns the SQLSpec-module and spawns it if it isnt already spawned.
628
- def sqlspecs
629
- @sqlspecs ||= Baza::Driver.const_get(@type_cc).const_get(:Sqlspecs).new(db: self)
401
+ instance = Baza::Driver.const_get(@type_cc).const_get(StringCases.snake_to_camel(driver_part)).new(db: self)
402
+ instance_variable_set(:"@#{driver_part}", instance)
403
+ instance
404
+ end
405
+ end
630
406
  end
631
407
 
632
408
  def supports_multiple_databases?
@@ -653,8 +429,14 @@ class Baza::Db
653
429
  # db.insert(:users, name: "Kasper")
654
430
  # end
655
431
  def transaction(&block)
656
- @driver.transaction(&block)
657
- nil
432
+ @in_transaction = true
433
+ begin
434
+ @driver.transaction(&block)
435
+ ensure
436
+ @in_transaction = false
437
+ end
438
+
439
+ self
658
440
  end
659
441
 
660
442
  # Optimizes all tables in the database.
@@ -665,14 +447,30 @@ class Baza::Db
665
447
  table.optimize
666
448
  end
667
449
 
668
- nil
450
+ self
669
451
  end
670
452
 
671
453
  def to_s
672
- "#<Baza::Db driver=\"#{@opts[:type]}\">"
454
+ "#<Baza::Db driver=\"#{@opts.fetch(:type)}\">"
673
455
  end
674
456
 
675
457
  def inspect
676
458
  to_s
677
459
  end
460
+
461
+ def new_query
462
+ Baza::SqlQueries::Select.new(db: self)
463
+ end
464
+
465
+ def sqlite?
466
+ @sqlite ||= @driver.class.name.downcase.include?("sqlite")
467
+ end
468
+
469
+ def mysql?
470
+ @mysql ||= @driver.class.name.downcase.include?("mysql")
471
+ end
472
+
473
+ def postgres?
474
+ @postgres ||= @driver.class.name.downcase.include?("pg")
475
+ end
678
476
  end