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
@@ -1,18 +0,0 @@
1
- class Baza::Cloner
2
- def self.from_active_record_connection(connection)
3
- if connection.class.name.include?('Mysql2Adapter')
4
- config = connection.instance_variable_get(:@connection).instance_variable_get(:@query_options)
5
-
6
- Baza::Db.new(
7
- type: :mysql,
8
- subtype: :mysql2,
9
- host: config[:host],
10
- user: config[:username],
11
- pass: config[:password],
12
- db: config[:database]
13
- )
14
- else
15
- raise "Unsupported adapter: #{connection.class.name}"
16
- end
17
- end
18
- end
@@ -1,159 +0,0 @@
1
- class Baza::Driver::ActiveRecord
2
- attr_reader :baza, :conn, :sep_table, :sep_col, :sep_val, :symbolize, :conn_type
3
- attr_accessor :tables, :cols, :indexes
4
-
5
- def self.from_object(args)
6
- if args[:object].class.name.include?("ActiveRecord::ConnectionAdapters")
7
- if args[:object].class.name.include?("ConnectionPool")
8
- object_to_use = args[:object].connection
9
- else
10
- object_to_use = args[:object]
11
- end
12
-
13
- return {
14
- type: :success,
15
- args: {
16
- type: :active_record,
17
- conn: object_to_use
18
- }
19
- }
20
- end
21
-
22
- return nil
23
- end
24
-
25
- def initialize(baza)
26
- @baza = baza
27
- @conn = @baza.opts[:conn]
28
- conn_name = @conn.class.name.to_s.downcase
29
-
30
- if conn_name.include?("mysql")
31
- @sep_table = "`"
32
- @sep_col = "`"
33
- @sep_val = "'"
34
- @conn_type = :mysql
35
- elsif conn_name.include?("sqlite")
36
- @sep_table = "`"
37
- @sep_col = "`"
38
- @sep_val = "'"
39
- @conn_type = :sqlite3
40
- else
41
- raise "Unknown type: '#{conn_name}'."
42
- end
43
- end
44
-
45
- def query(str)
46
- Baza::Driver::ActiveRecord::Result.new(@conn.execute(str))
47
- end
48
-
49
- def escape(str)
50
- @conn.quote_string(str.to_s)
51
- end
52
-
53
- def esc_col(string)
54
- string = string.to_s
55
- raise "Invalid column-string: #{string}" if string.include?(@sep_col)
56
- return string
57
- end
58
-
59
- def esc_table(string)
60
- string = string.to_s
61
- raise "Invalid column-string: #{string}" if string.include?(@sep_col)
62
- return string
63
- end
64
-
65
- def close
66
- @conn.close
67
- end
68
-
69
- def transaction
70
- if @conn_type == :mysql
71
- query("START TRANSACTION")
72
- elsif @conn_type == :sqlite3
73
- query("BEGIN TRANSACTION")
74
- end
75
-
76
- begin
77
- yield @baza
78
- query("COMMIT")
79
- rescue
80
- query("ROLLBACK")
81
- raise
82
- end
83
- end
84
- end
85
-
86
- class Baza::Driver::ActiveRecord::Result
87
- def initialize(res)
88
- @res = res
89
- end
90
-
91
- def enum
92
- @enum ||= Enumerator.new do |y|
93
- each do |data|
94
- y << data
95
- end
96
- end
97
- end
98
-
99
- def fetch
100
- begin
101
- return enum.next
102
- rescue StopIteration
103
- return false
104
- end
105
- end
106
-
107
- def each(&blk)
108
- return unless @res
109
-
110
- if RUBY_ENGINE == "jruby"
111
- @res.each do |result|
112
- yield result.symbolize_keys
113
- end
114
- else
115
- @res.each(as: :hash) do |result|
116
- yield result.symbolize_keys
117
- end
118
- end
119
- end
120
- end
121
-
122
- class Baza::Driver::ActiveRecord::Tables
123
- def initialize(args)
124
- @args = args
125
-
126
- require_relative "../#{@args[:db].conn.conn_type}/#{@args[:db].conn.conn_type}_tables"
127
- @proxy_to = ::Baza::Driver.const_get(StringCases.snake_to_camel(@args[:db].conn.conn_type)).const_get(:Tables).new(@args)
128
- end
129
-
130
- def method_missing(name, *args, &blk)
131
- @proxy_to.__send__(name, *args, &blk)
132
- end
133
- end
134
-
135
- class Baza::Driver::ActiveRecord::Columns
136
- def initialize(args)
137
- @args = args
138
-
139
- require_relative "../#{@args[:db].conn.conn_type}/#{@args[:db].conn.conn_type}_columns"
140
- @proxy_to = ::Baza::Driver.const_get(StringCases.snake_to_camel(@args[:db].conn.conn_type)).const_get(:Columns).new(@args)
141
- end
142
-
143
- def method_missing(name, *args, &blk)
144
- @proxy_to.__send__(name, *args, &blk)
145
- end
146
- end
147
-
148
- class Baza::Driver::ActiveRecord::Indexes
149
- def initialize(args)
150
- @args = args
151
-
152
- require_relative "../#{@args[:db].conn.conn_type}/#{@args[:db].conn.conn_type}_indexes"
153
- @proxy_to = ::Baza::Driver.const_get(StringCases.snake_to_camel(@args[:db].conn.conn_type)).const_get(:Indexes).new(@args)
154
- end
155
-
156
- def method_missing(name, *args, &blk)
157
- @proxy_to.__send__(name, *args, &blk)
158
- end
159
- end
@@ -1,443 +0,0 @@
1
- class Baza::Driver::Mysql
2
- autoload :Table, "#{File.dirname(__FILE__)}/mysql_table"
3
- autoload :Tables, "#{File.dirname(__FILE__)}/mysql_tables"
4
- autoload :Column, "#{File.dirname(__FILE__)}/mysql_column"
5
- autoload :Columns, "#{File.dirname(__FILE__)}/mysql_columns"
6
- autoload :Index, "#{File.dirname(__FILE__)}/mysql_index"
7
- autoload :Indexes, "#{File.dirname(__FILE__)}/mysql_indexes"
8
- autoload :Result, "#{File.dirname(__FILE__)}/mysql_result"
9
- autoload :ResultJava, "#{File.dirname(__FILE__)}/mysql_result_java"
10
- autoload :ResultMysql2, "#{File.dirname(__FILE__)}/mysql_result_mysql2"
11
- autoload :ResultUnbuffered, "#{File.dirname(__FILE__)}/mysql_result_unbuffered"
12
- autoload :Sqlspecs, "#{File.dirname(__FILE__)}/mysql_sqlspecs"
13
-
14
- attr_reader :baza, :conn, :conns, :sep_table, :sep_col, :sep_val
15
- attr_accessor :tables, :cols, :indexes
16
-
17
- #Helper to enable automatic registering of database using Baza::Db.from_object
18
- def self.from_object(args)
19
- if args[:object].class.name == "Mysql2::Client"
20
- return {
21
- type: :success,
22
- args: {
23
- type: :mysql,
24
- subtype: :mysql2,
25
- conn: args[:object],
26
- query_args: {
27
- as: :hash,
28
- symbolize_keys: true
29
- }
30
- }
31
- }
32
- elsif args[:object].class.name == "Java::ComMysqlJdbc::JDBC4Connection"
33
- return {
34
- type: :success,
35
- args: {
36
- type: :mysql,
37
- subtype: :java,
38
- conn: args[:object],
39
- query_args: {
40
- as: :hash,
41
- symbolize_keys: true
42
- }
43
- }
44
- }
45
- end
46
-
47
- return nil
48
- end
49
-
50
- def initialize(baza)
51
- @baza = baza
52
- @opts = @baza.opts
53
- @sep_table = "`"
54
- @sep_col = "`"
55
- @sep_val = "'"
56
-
57
- require "monitor"
58
- @mutex = Monitor.new
59
-
60
- if @opts[:encoding]
61
- @encoding = @opts[:encoding]
62
- else
63
- @encoding = "utf8"
64
- end
65
-
66
- if @baza.opts.key?(:port)
67
- @port = @baza.opts[:port].to_i
68
- else
69
- @port = 3306
70
- end
71
-
72
- @java_rs_data = {}
73
- @subtype = @baza.opts[:subtype]
74
- @subtype ||= :mysql
75
- reconnect
76
- end
77
-
78
- #This method handels the closing of statements and results for the Java MySQL-mode.
79
- def java_mysql_resultset_killer(id)
80
- data = @java_rs_data[id]
81
- return nil unless data
82
-
83
- data[:res].close
84
- data[:stmt].close
85
- @java_rs_data.delete(id)
86
- end
87
-
88
- #Cleans the wref-map holding the tables.
89
- def clean
90
- tables.clean if tables
91
- end
92
-
93
- #Respawns the connection to the MySQL-database.
94
- def reconnect
95
- @mutex.synchronize do
96
- case @subtype
97
- when :mysql
98
- @conn = Mysql.real_connect(@baza.opts[:host], @baza.opts[:user], @baza.opts[:pass], @baza.opts[:db], @port)
99
- when :mysql2
100
- require "rubygems"
101
- require "mysql2"
102
-
103
- args = {
104
- host: @baza.opts[:host],
105
- username: @baza.opts[:user],
106
- password: @baza.opts[:pass],
107
- database: @baza.opts[:db],
108
- port: @port,
109
- symbolize_keys: true,
110
- cache_rows: false
111
- }
112
-
113
- #Symbolize keys should also be given here, else table-data wont be symbolized for some reason - knj.
114
- @query_args = {symbolize_keys: true}
115
- @query_args.merge!(@baza.opts[:query_args]) if @baza.opts[:query_args]
116
-
117
- pos_args = [:as, :async, :cast_booleans, :database_timezone, :application_timezone, :cache_rows, :connect_flags, :cast]
118
- pos_args.each do |key|
119
- args[key] = @baza.opts[key] if @baza.opts.key?(key)
120
- end
121
-
122
- args[:as] = :array if @opts[:result] == "array"
123
-
124
- tries = 0
125
- begin
126
- tries += 1
127
- if @baza.opts[:conn]
128
- @conn = @baza.opts[:conn]
129
- else
130
- @conn = Mysql2::Client.new(args)
131
- end
132
- rescue => e
133
- if tries <= 3
134
- if e.message == "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)"
135
- sleep 1
136
- tries += 1
137
- retry
138
- end
139
- end
140
-
141
- raise e
142
- end
143
- when :java
144
- if @baza.opts[:conn]
145
- @jdbc_loaded = true
146
- @conn = @baza.opts[:conn]
147
- else
148
- unless @jdbc_loaded
149
- require "java"
150
- require "/usr/share/java/mysql-connector-java.jar" if File.exists?("/usr/share/java/mysql-connector-java.jar")
151
- import "com.mysql.jdbc.Driver"
152
- @jdbc_loaded = true
153
- end
154
-
155
- @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")
156
- end
157
-
158
- query("SET SQL_MODE = ''")
159
- else
160
- raise "Unknown subtype: #{@subtype} (#{@subtype.class.name})"
161
- end
162
-
163
- query("SET NAMES '#{self.esc(@encoding)}'") if @encoding
164
- end
165
- end
166
-
167
- #Executes a query and returns the result.
168
- def query(str)
169
- str = str.to_s
170
- str = str.force_encoding("UTF-8") if @encoding == "utf8" and str.respond_to?(:force_encoding)
171
- tries = 0
172
-
173
- begin
174
- tries += 1
175
- @mutex.synchronize do
176
- case @subtype
177
- when :mysql
178
- return Baza::Driver::Mysql::Result.new(self, @conn.query(str))
179
- when :mysql2
180
- return Baza::Driver::Mysql::ResultMysql2.new(@conn.query(str, @query_args))
181
- when :java
182
- stmt = conn.create_statement
183
-
184
- if str.match(/^\s*(delete|update|create|drop|insert\s+into|alter|truncate)\s+/i)
185
- begin
186
- stmt.execute(str)
187
- ensure
188
- stmt.close
189
- end
190
-
191
- return nil
192
- else
193
- id = nil
194
-
195
- begin
196
- res = stmt.execute_query(str)
197
- ret = Baza::Driver::Mysql::ResultJava.new(@baza, @opts, res)
198
- id = ret.__id__
199
-
200
- #If ID is being reused we have to free the result.
201
- self.java_mysql_resultset_killer(id) if @java_rs_data.key?(id)
202
-
203
- #Save reference to result and statement, so we can close them when they are garbage collected.
204
- @java_rs_data[id] = {res: res, stmt: stmt}
205
- ObjectSpace.define_finalizer(ret, method(:java_mysql_resultset_killer))
206
-
207
- return ret
208
- rescue => e
209
- res.close if res
210
- stmt.close
211
- @java_rs_data.delete(id) if ret && id
212
-
213
- raise e
214
- end
215
- end
216
- else
217
- raise "Unknown subtype: '#{@subtype}'."
218
- end
219
- end
220
- rescue => e
221
- if tries <= 3
222
- 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"
223
- sleep 0.5
224
- reconnect
225
- retry
226
- 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"
227
- reconnect
228
- retry
229
- end
230
- end
231
-
232
- raise e
233
- end
234
- end
235
-
236
- #Executes an unbuffered query and returns the result that can be used to access the data.
237
- def query_ubuf(str)
238
- @mutex.synchronize do
239
- case @subtype
240
- when :mysql
241
- @conn.query_with_result = false
242
- return Baza::Driver::Mysql::ResultUnbuffered.new(@conn, @opts, @conn.query(str))
243
- when :mysql2
244
- return Baza::Driver::Mysql::ResultMysql2.new(@conn.query(str, @query_args.merge(stream: true)))
245
- when :java
246
- if str.match(/^\s*(delete|update|create|drop|insert\s+into)\s+/i)
247
- stmt = @conn.createStatement
248
-
249
- begin
250
- stmt.execute(str)
251
- ensure
252
- stmt.close
253
- end
254
-
255
- return nil
256
- else
257
- stmt = @conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY)
258
- stmt.setFetchSize(java.lang.Integer::MIN_VALUE)
259
-
260
- begin
261
- res = stmt.executeQuery(str)
262
- ret = Baza::Driver::Mysql::ResultJava.new(@baza, @opts, res)
263
-
264
- #Save reference to result and statement, so we can close them when they are garbage collected.
265
- @java_rs_data[ret.__id__] = {res: res, stmt: stmt}
266
- ObjectSpace.define_finalizer(ret, method("java_mysql_resultset_killer"))
267
-
268
- return ret
269
- rescue => e
270
- res.close if res
271
- stmt.close
272
- raise e
273
- end
274
- end
275
- else
276
- raise "Unknown subtype: '#{@subtype}'"
277
- end
278
- end
279
- end
280
-
281
- #Escapes a string to be safe to use in a query.
282
- def escape_alternative(string)
283
- case @subtype
284
- when :mysql
285
- return @conn.escape_string(string.to_s)
286
- when :mysql2
287
- return @conn.escape(string.to_s)
288
- when :java
289
- return escape(string)
290
- else
291
- raise "Unknown subtype: '#{@subtype}'."
292
- end
293
- end
294
-
295
- #An alternative to the MySQL framework's escape. This is copied from the Ruby/MySQL framework at: http://www.tmtm.org/en/ruby/mysql/
296
- def escape(string)
297
- return string.to_s.gsub(/([\0\n\r\032\'\"\\])/) do
298
- case $1
299
- when "\0" then "\\0"
300
- when "\n" then "\\n"
301
- when "\r" then "\\r"
302
- when "\032" then "\\Z"
303
- else "\\#{$1}"
304
- end
305
- end
306
- end
307
-
308
- #Escapes a string to be safe to use as a column in a query.
309
- def esc_col(string)
310
- string = string.to_s
311
- raise "Invalid column-string: #{string}" if string.include?(@sep_col)
312
- return string
313
- end
314
-
315
- alias :esc_table :esc_col
316
- alias :esc :escape
317
-
318
- #Returns the last inserted ID for the connection.
319
- def last_id
320
- case @subtype
321
- when :mysql
322
- @mutex.synchronize do
323
- return @conn.insert_id.to_i
324
- end
325
- when :mysql2
326
- @mutex.synchronize do
327
- return @conn.last_id.to_i
328
- end
329
- when :java
330
- data = self.query("SELECT LAST_INSERT_ID() AS id").fetch
331
- return data[:id].to_i if data.key?(:id)
332
- raise "Could not figure out last inserted ID."
333
- end
334
- end
335
-
336
- #Closes the connection threadsafe.
337
- def close
338
- @mutex.synchronize do
339
- @conn.close
340
- end
341
- end
342
-
343
- #Destroyes the connection.
344
- def destroy
345
- @conn = nil
346
- @baza = nil
347
- @mutex = nil
348
- @subtype = nil
349
- @encoding = nil
350
- @query_args = nil
351
- @port = nil
352
- end
353
-
354
- #Inserts multiple rows in a table. Can return the inserted IDs if asked to in arguments.
355
- def insert_multi(tablename, arr_hashes, args = nil)
356
- sql = "INSERT INTO `#{tablename}` ("
357
-
358
- first = true
359
- if args && args[:keys]
360
- keys = args[:keys]
361
- elsif arr_hashes.first.is_a?(Hash)
362
- keys = arr_hashes.first.keys
363
- else
364
- raise "Could not figure out keys."
365
- end
366
-
367
- keys.each do |col_name|
368
- sql << "," unless first
369
- first = false if first
370
- sql << "`#{self.esc_col(col_name)}`"
371
- end
372
-
373
- sql << ") VALUES ("
374
-
375
- first = true
376
- arr_hashes.each do |hash|
377
- if first
378
- first = false
379
- else
380
- sql << "),("
381
- end
382
-
383
- first_key = true
384
- if hash.is_a?(Array)
385
- hash.each do |val|
386
- if first_key
387
- first_key = false
388
- else
389
- sql << ","
390
- end
391
-
392
- sql << @baza.sqlval(val)
393
- end
394
- else
395
- hash.each do |key, val|
396
- if first_key
397
- first_key = false
398
- else
399
- sql << ","
400
- end
401
-
402
- sql << @baza.sqlval(val)
403
- end
404
- end
405
- end
406
-
407
- sql << ")"
408
-
409
- return sql if args && args[:return_sql]
410
-
411
- self.query(sql)
412
-
413
- if args && args[:return_id]
414
- first_id = self.last_id
415
- raise "Invalid ID: #{first_id}" if first_id.to_i <= 0
416
- ids = [first_id]
417
- 1.upto(arr_hashes.length - 1) do |count|
418
- ids << first_id + count
419
- end
420
-
421
- ids_length = ids.length
422
- arr_hashes_length = arr_hashes.length
423
- raise "Invalid length (#{ids_length}, #{arr_hashes_length})." if ids_length != arr_hashes_length
424
-
425
- return ids
426
- else
427
- return nil
428
- end
429
- end
430
-
431
- #Starts a transaction, yields the database and commits at the end.
432
- def transaction
433
- @baza.q("START TRANSACTION")
434
-
435
- begin
436
- yield @baza
437
- @baza.q("COMMIT")
438
- rescue
439
- @baza.q("ROLLBACK")
440
- raise
441
- end
442
- end
443
- end