baza 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +9 -11
  3. data/Gemfile.lock +76 -50
  4. data/README.md +3 -2
  5. data/VERSION +1 -1
  6. data/baza.gemspec +107 -54
  7. data/lib/baza.rb +1 -1
  8. data/lib/baza/base_sql_driver.rb +64 -0
  9. data/lib/baza/cloner.rb +31 -0
  10. data/{include → lib/baza}/column.rb +0 -0
  11. data/{include → lib/baza}/db.rb +61 -49
  12. data/{include → lib/baza}/dbtime.rb +0 -0
  13. data/{include → lib/baza}/driver.rb +1 -1
  14. data/lib/baza/drivers/active_record.rb +107 -0
  15. data/lib/baza/drivers/active_record/columns.rb +10 -0
  16. data/lib/baza/drivers/active_record/indexes.rb +10 -0
  17. data/lib/baza/drivers/active_record/result.rb +23 -0
  18. data/lib/baza/drivers/active_record/tables.rb +12 -0
  19. data/lib/baza/drivers/mysql.rb +220 -0
  20. data/{include/drivers/mysql/mysql_column.rb → lib/baza/drivers/mysql/column.rb} +0 -0
  21. data/{include/drivers/mysql/mysql_columns.rb → lib/baza/drivers/mysql/columns.rb} +0 -0
  22. data/{include/drivers/mysql/mysql_index.rb → lib/baza/drivers/mysql/index.rb} +0 -0
  23. data/{include/drivers/mysql/mysql_indexes.rb → lib/baza/drivers/mysql/indexes.rb} +0 -0
  24. data/lib/baza/drivers/mysql/result.rb +81 -0
  25. data/{include/drivers/mysql/mysql_sqlspecs.rb → lib/baza/drivers/mysql/sqlspecs.rb} +0 -0
  26. data/{include/drivers/mysql/mysql_table.rb → lib/baza/drivers/mysql/table.rb} +2 -2
  27. data/{include/drivers/mysql/mysql_tables.rb → lib/baza/drivers/mysql/tables.rb} +0 -1
  28. data/{include/drivers/mysql/mysql_result_unbuffered.rb → lib/baza/drivers/mysql/unbuffered_result.rb} +19 -23
  29. data/lib/baza/drivers/mysql2.rb +259 -0
  30. data/lib/baza/drivers/mysql2/column.rb +2 -0
  31. data/lib/baza/drivers/mysql2/columns.rb +2 -0
  32. data/lib/baza/drivers/mysql2/index.rb +2 -0
  33. data/lib/baza/drivers/mysql2/indexes.rb +2 -0
  34. data/lib/baza/drivers/mysql2/result.rb +26 -0
  35. data/lib/baza/drivers/mysql2/table.rb +2 -0
  36. data/lib/baza/drivers/mysql2/tables.rb +2 -0
  37. data/lib/baza/drivers/mysql_java.rb +178 -0
  38. data/lib/baza/drivers/mysql_java/column.rb +2 -0
  39. data/lib/baza/drivers/mysql_java/columns.rb +2 -0
  40. data/lib/baza/drivers/mysql_java/index.rb +2 -0
  41. data/lib/baza/drivers/mysql_java/indexes.rb +2 -0
  42. data/lib/baza/drivers/mysql_java/table.rb +2 -0
  43. data/lib/baza/drivers/mysql_java/tables.rb +2 -0
  44. data/lib/baza/drivers/sqlite3.rb +81 -0
  45. data/{include/drivers/sqlite3/sqlite3_column.rb → lib/baza/drivers/sqlite3/column.rb} +0 -0
  46. data/{include/drivers/sqlite3/sqlite3_columns.rb → lib/baza/drivers/sqlite3/columns.rb} +0 -0
  47. data/{include/drivers/sqlite3/sqlite3_index.rb → lib/baza/drivers/sqlite3/index.rb} +0 -0
  48. data/{include/drivers/sqlite3/sqlite3_indexes.rb → lib/baza/drivers/sqlite3/indexes.rb} +0 -0
  49. data/lib/baza/drivers/sqlite3/result.rb +64 -0
  50. data/{include/drivers/sqlite3/sqlite3_sqlspecs.rb → lib/baza/drivers/sqlite3/sqlspecs.rb} +1 -1
  51. data/{include/drivers/sqlite3/sqlite3_table.rb → lib/baza/drivers/sqlite3/table.rb} +0 -0
  52. data/{include/drivers/sqlite3/sqlite3_tables.rb → lib/baza/drivers/sqlite3/tables.rb} +0 -0
  53. data/lib/baza/drivers/sqlite3/unbuffered_result.rb +33 -0
  54. data/lib/baza/drivers/sqlite3_java.rb +75 -0
  55. data/lib/baza/drivers/sqlite3_java/column.rb +2 -0
  56. data/lib/baza/drivers/sqlite3_java/columns.rb +2 -0
  57. data/lib/baza/drivers/sqlite3_java/index.rb +2 -0
  58. data/lib/baza/drivers/sqlite3_java/indexes.rb +2 -0
  59. data/lib/baza/drivers/sqlite3_java/table.rb +2 -0
  60. data/lib/baza/drivers/sqlite3_java/tables.rb +2 -0
  61. data/lib/baza/drivers/sqlite3_java/unbuffered_result.rb +33 -0
  62. data/lib/baza/drivers/sqlite3_rhodes.rb +78 -0
  63. data/{include → lib/baza}/dump.rb +0 -0
  64. data/{include → lib/baza}/errors.rb +0 -0
  65. data/{include → lib/baza}/idquery.rb +0 -0
  66. data/{include → lib/baza}/index.rb +0 -0
  67. data/lib/baza/jdbc_driver.rb +102 -0
  68. data/lib/baza/jdbc_result.rb +125 -0
  69. data/{include → lib/baza}/model.rb +2 -2
  70. data/{include → lib/baza}/model_custom.rb +0 -0
  71. data/{include → lib/baza}/model_handler.rb +1 -1
  72. data/{include → lib/baza}/model_handler_sqlhelper.rb +0 -0
  73. data/{include → lib/baza}/query_buffer.rb +2 -2
  74. data/lib/baza/result_base.rb +25 -0
  75. data/{include → lib/baza}/revision.rb +1 -1
  76. data/{include → lib/baza}/row.rb +0 -0
  77. data/{include → lib/baza}/sqlspecs.rb +0 -0
  78. data/{include → lib/baza}/table.rb +0 -0
  79. data/shippable.yml +3 -1
  80. data/spec/cloner_spec.rb +10 -0
  81. data/spec/drivers/active_record_mysql2_spec.rb +18 -0
  82. data/spec/drivers/active_record_mysql_spec.rb +16 -0
  83. data/spec/drivers/active_record_sqlite3_spec.rb +16 -0
  84. data/spec/drivers/mysql2_spec.rb +16 -0
  85. data/spec/{include/drivers → drivers}/mysql_spec.rb +9 -1
  86. data/spec/{include/drivers → drivers}/sqlite3_spec.rb +8 -0
  87. data/spec/info_active_record_mysql.rb +37 -0
  88. data/spec/info_active_record_mysql2.rb +37 -0
  89. data/spec/info_active_record_mysql2_shippable.rb +36 -0
  90. data/spec/info_active_record_mysql_shippable.rb +36 -0
  91. data/spec/info_active_record_sqlite3.rb +37 -0
  92. data/spec/info_mysql2_example.rb +23 -0
  93. data/spec/info_mysql2_shippable.rb +22 -0
  94. data/spec/info_mysql_example.rb +3 -4
  95. data/spec/info_mysql_shippable.rb +7 -17
  96. data/spec/info_sqlite3.rb +5 -4
  97. data/spec/model_handler_spec.rb +137 -105
  98. data/spec/spec_helper.rb +8 -0
  99. data/spec/support/driver_collection.rb +124 -34
  100. data/spec/support/driver_columns_collection.rb +0 -7
  101. data/spec/support/driver_indexes_collection.rb +4 -11
  102. data/spec/support/driver_tables_collection.rb +0 -7
  103. metadata +160 -52
  104. data/include/cloner.rb +0 -18
  105. data/include/drivers/active_record/active_record.rb +0 -159
  106. data/include/drivers/mysql/mysql.rb +0 -443
  107. data/include/drivers/mysql/mysql_result.rb +0 -42
  108. data/include/drivers/mysql/mysql_result_java.rb +0 -61
  109. data/include/drivers/mysql/mysql_result_mysql2.rb +0 -26
  110. data/include/drivers/sqlite3/sqlite3.rb +0 -159
  111. data/include/drivers/sqlite3/sqlite3_result.rb +0 -35
  112. data/include/drivers/sqlite3/sqlite3_result_java.rb +0 -39
  113. data/spec/include/cloner_spec.rb +0 -10
  114. data/spec/include/drivers/active_record_spec.rb +0 -8
  115. data/spec/info_active_record.rb +0 -49
  116. data/spec/info_active_record_shippable.rb +0 -47
@@ -0,0 +1,259 @@
1
+ class Baza::Driver::Mysql2 < Baza::BaseSqlDriver
2
+ path = "#{File.dirname(__FILE__)}/mysql2"
3
+
4
+ autoload :Table, "#{path}/table"
5
+ autoload :Tables, "#{path}/tables"
6
+ autoload :Column, "#{path}/column"
7
+ autoload :Columns, "#{path}/columns"
8
+ autoload :Index, "#{path}/index"
9
+ autoload :Indexes, "#{path}/indexes"
10
+ autoload :Result, "#{path}/result"
11
+ autoload :UnbufferedResult, "#{path}/unbuffered_result"
12
+ autoload :Sqlspecs, "#{path}/sqlspecs"
13
+
14
+ attr_reader :conn, :conns
15
+
16
+ #Helper to enable automatic registering of database using Baza::Db.from_object
17
+ def self.from_object(args)
18
+ if args[:object].class.name == "Mysql2::Client"
19
+ return {
20
+ type: :success,
21
+ args: {
22
+ type: :mysql2,
23
+ conn: args[:object],
24
+ query_args: {
25
+ symbolize_keys: true
26
+ }
27
+ }
28
+ }
29
+ end
30
+
31
+ return nil
32
+ end
33
+
34
+ def initialize(baza)
35
+ super
36
+
37
+ @opts = @baza.opts
38
+
39
+ require "monitor"
40
+ @mutex = Monitor.new
41
+
42
+ if @opts[:encoding]
43
+ @encoding = @opts[:encoding]
44
+ else
45
+ @encoding = "utf8"
46
+ end
47
+
48
+ if @baza.opts.key?(:port)
49
+ @port = @baza.opts[:port].to_i
50
+ else
51
+ @port = 3306
52
+ end
53
+
54
+ reconnect
55
+ end
56
+
57
+ #Cleans the wref-map holding the tables.
58
+ def clean
59
+ tables.clean if tables
60
+ end
61
+
62
+ #Respawns the connection to the MySQL-database.
63
+ def reconnect
64
+ @mutex.synchronize do
65
+ args = {
66
+ host: @baza.opts[:host],
67
+ username: @baza.opts[:user],
68
+ password: @baza.opts[:pass],
69
+ database: @baza.opts[:db],
70
+ port: @port,
71
+ symbolize_keys: true,
72
+ cache_rows: false
73
+ }
74
+
75
+ #Symbolize keys should also be given here, else table-data wont be symbolized for some reason - knj.
76
+ @query_args = {symbolize_keys: true,}
77
+ @query_args[:cast] = false unless @baza.opts[:type_translation]
78
+ @query_args.merge!(@baza.opts[:query_args]) if @baza.opts[:query_args]
79
+
80
+ pos_args = [:as, :async, :cast_booleans, :database_timezone, :application_timezone, :cache_rows, :connect_flags, :cast]
81
+ pos_args.each do |key|
82
+ args[key] = @baza.opts[key] if @baza.opts.key?(key)
83
+ end
84
+
85
+ args[:as] = :array
86
+
87
+ tries = 0
88
+ begin
89
+ tries += 1
90
+ if @baza.opts[:conn]
91
+ @conn = @baza.opts[:conn]
92
+ else
93
+ require "mysql2"
94
+ @conn = Mysql2::Client.new(args)
95
+ end
96
+ rescue => e
97
+ if tries <= 3
98
+ if e.message == "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)"
99
+ sleep 1
100
+ tries += 1
101
+ retry
102
+ end
103
+ end
104
+
105
+ raise e
106
+ end
107
+
108
+ query("SET NAMES '#{esc(@encoding)}'") if @encoding
109
+ end
110
+ end
111
+
112
+ #Executes a query and returns the result.
113
+ def query(str)
114
+ str = str.to_s
115
+ str = str.force_encoding("UTF-8") if @encoding == "utf8" && str.respond_to?(:force_encoding)
116
+ tries = 0
117
+
118
+ begin
119
+ tries += 1
120
+ @mutex.synchronize do
121
+ return Baza::Driver::Mysql2::Result.new(self, @conn.query(str, @query_args))
122
+ end
123
+ rescue => e
124
+ if tries <= 3
125
+ if e.message == "MySQL server has gone away" || e.message == "closed MySQL connection" or e.message == "Can't connect to local MySQL server through socket"
126
+ sleep 0.5
127
+ reconnect
128
+ retry
129
+ elsif e.message.include?("No operations allowed after connection closed") or e.message == "This connection is still waiting for a result, try again once you have the result" or e.message == "Lock wait timeout exceeded; try restarting transaction"
130
+ reconnect
131
+ retry
132
+ end
133
+ end
134
+
135
+ raise e
136
+ end
137
+ end
138
+
139
+ #Executes an unbuffered query and returns the result that can be used to access the data.
140
+ def query_ubuf(str)
141
+ @mutex.synchronize do
142
+ return Baza::Driver::Mysql2::Result.new(self, @conn.query(str, @query_args.merge(stream: true)))
143
+ end
144
+ end
145
+
146
+ #Escapes a string to be safe to use in a query.
147
+ def escape(string)
148
+ return @conn.escape(string.to_s)
149
+ end
150
+
151
+ #Returns the last inserted ID for the connection.
152
+ def last_id
153
+ @mutex.synchronize { return @conn.last_id.to_i }
154
+ end
155
+
156
+ #Closes the connection threadsafe.
157
+ def close
158
+ @mutex.synchronize { @conn.close }
159
+ end
160
+
161
+ #Destroyes the connection.
162
+ def destroy
163
+ @conn = nil
164
+ @baza = nil
165
+ @mutex = nil
166
+ @encoding = nil
167
+ @query_args = nil
168
+ @port = nil
169
+ end
170
+
171
+ #Inserts multiple rows in a table. Can return the inserted IDs if asked to in arguments.
172
+ def insert_multi(tablename, arr_hashes, args = nil)
173
+ sql = "INSERT INTO `#{tablename}` ("
174
+
175
+ first = true
176
+ if args && args[:keys]
177
+ keys = args[:keys]
178
+ elsif arr_hashes.first.is_a?(Hash)
179
+ keys = arr_hashes.first.keys
180
+ else
181
+ raise "Could not figure out keys."
182
+ end
183
+
184
+ keys.each do |col_name|
185
+ sql << "," unless first
186
+ first = false if first
187
+ sql << "`#{self.esc_col(col_name)}`"
188
+ end
189
+
190
+ sql << ") VALUES ("
191
+
192
+ first = true
193
+ arr_hashes.each do |hash|
194
+ if first
195
+ first = false
196
+ else
197
+ sql << "),("
198
+ end
199
+
200
+ first_key = true
201
+ if hash.is_a?(Array)
202
+ hash.each do |val|
203
+ if first_key
204
+ first_key = false
205
+ else
206
+ sql << ","
207
+ end
208
+
209
+ sql << @baza.sqlval(val)
210
+ end
211
+ else
212
+ hash.each do |key, val|
213
+ if first_key
214
+ first_key = false
215
+ else
216
+ sql << ","
217
+ end
218
+
219
+ sql << @baza.sqlval(val)
220
+ end
221
+ end
222
+ end
223
+
224
+ sql << ")"
225
+
226
+ return sql if args && args[:return_sql]
227
+
228
+ query(sql)
229
+
230
+ if args && args[:return_id]
231
+ first_id = self.last_id
232
+ raise "Invalid ID: #{first_id}" if first_id.to_i <= 0
233
+ ids = [first_id]
234
+ 1.upto(arr_hashes.length - 1) do |count|
235
+ ids << first_id + count
236
+ end
237
+
238
+ ids_length = ids.length
239
+ arr_hashes_length = arr_hashes.length
240
+ raise "Invalid length (#{ids_length}, #{arr_hashes_length})." if ids_length != arr_hashes_length
241
+
242
+ return ids
243
+ else
244
+ return nil
245
+ end
246
+ end
247
+
248
+ def transaction
249
+ @baza.q("START TRANSACTION")
250
+
251
+ begin
252
+ yield @baza
253
+ @baza.q("COMMIT")
254
+ rescue
255
+ @baza.q("ROLLBACK")
256
+ raise
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,2 @@
1
+ class Baza::Driver::Mysql2::Column < Baza::Driver::Mysql::Column
2
+ end
@@ -0,0 +1,2 @@
1
+ class Baza::Driver::Mysql2::Columns < Baza::Driver::Mysql::Columns
2
+ end
@@ -0,0 +1,2 @@
1
+ class Baza::Driver::Mysql2::Index < Baza::Driver::Mysql::Index
2
+ end
@@ -0,0 +1,2 @@
1
+ class Baza::Driver::Mysql2::Indexes < Baza::Driver::Mysql::Indexes
2
+ end
@@ -0,0 +1,26 @@
1
+ # This class controls the result for the MySQL2 driver.
2
+ class Baza::Driver::Mysql2::Result < Baza::ResultBase
3
+ # Constructor. This should not be called manually.
4
+ def initialize(driver, result)
5
+ @result = result
6
+ @type_translation = driver.baza.opts[:type_translation]
7
+ end
8
+
9
+ # Returns a single result.
10
+ def fetch
11
+ begin
12
+ return to_enum.next
13
+ rescue StopIteration
14
+ return false
15
+ end
16
+ end
17
+
18
+ # Loops over every single result yielding it.
19
+ def each
20
+ @result.each(as: :hash, symbolize_keys: true) do |row|
21
+ next unless row # This sometimes happens when streaming results...
22
+ row = Hash[row.map { |k, v| [k, v.to_s] }] if @type_translation == :string
23
+ yield row
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,2 @@
1
+ class Baza::Driver::Mysql2::Table < Baza::Driver::Mysql::Table
2
+ end
@@ -0,0 +1,2 @@
1
+ class Baza::Driver::Mysql2::Tables < Baza::Driver::Mysql::Tables
2
+ end
@@ -0,0 +1,178 @@
1
+ class Baza::Driver::MysqlJava < Baza::JdbcDriver
2
+ path = "#{File.dirname(__FILE__)}/mysql_java"
3
+
4
+ autoload :Table, "#{path}/table"
5
+ autoload :Tables, "#{path}/tables"
6
+ autoload :Column, "#{path}/column"
7
+ autoload :Columns, "#{path}/columns"
8
+ autoload :Index, "#{path}/index"
9
+ autoload :Indexes, "#{path}/indexes"
10
+ autoload :Result, "#{path}/result"
11
+ autoload :UnbufferedResult, "#{path}/unbuffered_result"
12
+ autoload :Sqlspecs, "#{path}/sqlspecs"
13
+
14
+ attr_reader :conn, :conns
15
+
16
+ #Helper to enable automatic registering of database using Baza::Db.from_object
17
+ def self.from_object(args)
18
+ if args[:object].class.name == "Java::ComMysqlJdbc::JDBC4Connection"
19
+ return {
20
+ type: :success,
21
+ args: {
22
+ type: :mysql_java,
23
+ conn: args[:object]
24
+ }
25
+ }
26
+ end
27
+
28
+ return nil
29
+ end
30
+
31
+ def initialize(baza)
32
+ super
33
+
34
+ @opts = @baza.opts
35
+
36
+ if @opts[:encoding]
37
+ @encoding = @opts[:encoding]
38
+ else
39
+ @encoding = 'utf8'
40
+ end
41
+
42
+ if @baza.opts.key?(:port)
43
+ @port = @baza.opts[:port].to_i
44
+ else
45
+ @port = 3306
46
+ end
47
+
48
+ @java_rs_data = {}
49
+ reconnect
50
+ end
51
+
52
+ #Respawns the connection to the MySQL-database.
53
+ def reconnect
54
+ @mutex.synchronize do
55
+ if @baza.opts[:conn]
56
+ @jdbc_loaded = true
57
+ @conn = @baza.opts[:conn]
58
+ else
59
+ com.mysql.jdbc.Driver
60
+ @conn = java.sql::DriverManager.getConnection("jdbc:mysql://#{@baza.opts[:host]}:#{@port}/#{@baza.opts[:db]}?user=#{@baza.opts[:user]}&password=#{@baza.opts[:pass]}&populateInsertRowWithDefaultValues=true&zeroDateTimeBehavior=round&characterEncoding=#{@encoding}&holdResultsOpenOverStatementClose=true")
61
+ end
62
+
63
+ query_no_result_set("SET SQL_MODE = ''")
64
+ query_no_result_set("SET NAMES '#{self.esc(@encoding)}'") if @encoding
65
+ end
66
+ end
67
+
68
+ #Returns the last inserted ID for the connection.
69
+ def last_id
70
+ data = query("SELECT LAST_INSERT_ID() AS id").fetch
71
+ return data[:id].to_i if data[:id]
72
+ raise "Could not figure out last inserted ID."
73
+ end
74
+
75
+ #Closes the connection threadsafe.
76
+ def close
77
+ @mutex.synchronize { @conn.close }
78
+ end
79
+
80
+ #Destroyes the connection.
81
+ def destroy
82
+ @conn = nil
83
+ @baza = nil
84
+ @mutex = nil
85
+ @encoding = nil
86
+ @query_args = nil
87
+ @port = nil
88
+ end
89
+
90
+ #Inserts multiple rows in a table. Can return the inserted IDs if asked to in arguments.
91
+ def insert_multi(tablename, arr_hashes, args = nil)
92
+ sql = "INSERT INTO `#{tablename}` ("
93
+
94
+ first = true
95
+ if args && args[:keys]
96
+ keys = args[:keys]
97
+ elsif arr_hashes.first.is_a?(Hash)
98
+ keys = arr_hashes.first.keys
99
+ else
100
+ raise "Could not figure out keys."
101
+ end
102
+
103
+ keys.each do |col_name|
104
+ sql << "," unless first
105
+ first = false if first
106
+ sql << "`#{self.esc_col(col_name)}`"
107
+ end
108
+
109
+ sql << ") VALUES ("
110
+
111
+ first = true
112
+ arr_hashes.each do |hash|
113
+ if first
114
+ first = false
115
+ else
116
+ sql << "),("
117
+ end
118
+
119
+ first_key = true
120
+ if hash.is_a?(Array)
121
+ hash.each do |val|
122
+ if first_key
123
+ first_key = false
124
+ else
125
+ sql << ","
126
+ end
127
+
128
+ sql << @baza.sqlval(val)
129
+ end
130
+ else
131
+ hash.each do |key, val|
132
+ if first_key
133
+ first_key = false
134
+ else
135
+ sql << ","
136
+ end
137
+
138
+ sql << @baza.sqlval(val)
139
+ end
140
+ end
141
+ end
142
+
143
+ sql << ")"
144
+
145
+ return sql if args && args[:return_sql]
146
+
147
+ query_no_result_set(sql)
148
+
149
+ if args && args[:return_id]
150
+ first_id = self.last_id
151
+ raise "Invalid ID: #{first_id}" if first_id.to_i <= 0
152
+ ids = [first_id]
153
+ 1.upto(arr_hashes.length - 1) do |count|
154
+ ids << first_id + count
155
+ end
156
+
157
+ ids_length = ids.length
158
+ arr_hashes_length = arr_hashes.length
159
+ raise "Invalid length (#{ids_length}, #{arr_hashes_length})." if ids_length != arr_hashes_length
160
+
161
+ return ids
162
+ else
163
+ return nil
164
+ end
165
+ end
166
+
167
+ def transaction
168
+ query_no_result_set("START TRANSACTION")
169
+
170
+ begin
171
+ yield @baza
172
+ query_no_result_set("COMMIT")
173
+ rescue
174
+ query_no_result_set("ROLLBACK")
175
+ raise
176
+ end
177
+ end
178
+ end