dohmysql 0.2.28 → 0.2.29
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.
- checksums.yaml +4 -4
- data/lib/dohmysql/handle.rb +12 -7
- data/lib/dohmysql/handle.rb.orig +257 -0
- data/test/handle.dt.rb +1 -0
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71dbf50aa43b65aab550b4d8489a072bc82df2cd
|
4
|
+
data.tar.gz: 1c736a76d25785dd5cd1851168f1bd39a869ff6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16ae0b567882ff00279319a515f0e6bb565b91ab8945611b4a44623f0422dc66185d3db33ab37e90df3866f6375d0d6a45634c2c576f8425c3a8653dc2c928f8
|
7
|
+
data.tar.gz: 8cd83b4d1d917e9202f653d4e98181b6fd3cd06ec11542b251e82206012528a141cb5f22539669dc6462e6dad9f2327f7a491abf97aa444609a830c9069f0b3b
|
data/lib/dohmysql/handle.rb
CHANGED
@@ -19,12 +19,9 @@ class Handle
|
|
19
19
|
def initialize(config)
|
20
20
|
@config = config
|
21
21
|
@testing_rollback = false
|
22
|
-
log_config = @config.dup
|
23
22
|
@config[:reconnect] = true if !@config.keys.include?(:reconnect)
|
24
|
-
|
25
|
-
|
26
|
-
@mysqlh = Mysql2::Client.new(@config)
|
27
|
-
DohDb.logger.call('connection', "new connection created: id #{@mysqlh.thread_id}")
|
23
|
+
@mysqlh = nil
|
24
|
+
reopen
|
28
25
|
end
|
29
26
|
|
30
27
|
def close
|
@@ -200,7 +197,7 @@ private
|
|
200
197
|
@mysqlh.query(sqlstr)
|
201
198
|
rescue Exception => excpt
|
202
199
|
DohDb.logger.call('error', "caught exception #{excpt.message} during query: #{sqlstr}")
|
203
|
-
|
200
|
+
reopen
|
204
201
|
raise
|
205
202
|
end
|
206
203
|
|
@@ -237,7 +234,6 @@ private
|
|
237
234
|
insert("#{keyword} INTO #{table} #{keystr} VALUES #{valuestrs.join(",")}")
|
238
235
|
end
|
239
236
|
|
240
|
-
|
241
237
|
def get_row_builder(row_builder = nil)
|
242
238
|
if row_builder.nil?
|
243
239
|
TypedRowBuilder.new
|
@@ -255,6 +251,15 @@ private
|
|
255
251
|
TypedRowBuilder.new(row_builder)
|
256
252
|
end
|
257
253
|
end
|
254
|
+
|
255
|
+
def reopen
|
256
|
+
close if !closed?
|
257
|
+
log_config = @config.dup
|
258
|
+
log_config.delete(:password)
|
259
|
+
DohDb.logger.call('connection', "creating connection with config: #{log_config}")
|
260
|
+
@mysqlh = Mysql2::Client.new(@config)
|
261
|
+
DohDb.logger.call('connection', "new connection created: id #{@mysqlh.thread_id}")
|
262
|
+
end
|
258
263
|
end
|
259
264
|
|
260
265
|
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'mysql2'
|
2
|
+
require 'dohutil/array_to_hash'
|
3
|
+
require 'dohmysql/logger'
|
4
|
+
require 'dohmysql/error'
|
5
|
+
require 'dohmysql/typed_row_builder'
|
6
|
+
require 'dohmysql/writable_row'
|
7
|
+
require 'dohmysql/hash_row'
|
8
|
+
require 'dohmysql/smart_row'
|
9
|
+
require 'dohmysql/to_sql'
|
10
|
+
Mysql2::Client.default_query_options[:cast_booleans] = true
|
11
|
+
|
12
|
+
module DohDb
|
13
|
+
|
14
|
+
class Handle
|
15
|
+
attr_reader :config, :mysqlh
|
16
|
+
|
17
|
+
def initialize(config)
|
18
|
+
@config = config
|
19
|
+
@testing_rollback = false
|
20
|
+
log_config = @config.dup
|
21
|
+
@config[:reconnect] = true if !@config.keys.include?(:reconnect)
|
22
|
+
log_config.delete(:password)
|
23
|
+
DohDb.logger.call('connection', "creating connection with config: #{log_config}")
|
24
|
+
@mysqlh = Mysql2::Client.new(@config)
|
25
|
+
DohDb.logger.call('connection', "new connection created: id #{@mysqlh.thread_id}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def close
|
29
|
+
unless closed?
|
30
|
+
begin
|
31
|
+
DohDb.logger.call('connection', "closing connection: id #{@mysqlh.thread_id}")
|
32
|
+
@mysqlh.close
|
33
|
+
ensure
|
34
|
+
@mysqlh = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def closed?
|
40
|
+
@mysqlh.nil?
|
41
|
+
end
|
42
|
+
|
43
|
+
def query(statement)
|
44
|
+
generic_query(statement)
|
45
|
+
retval = @mysqlh.affected_rows
|
46
|
+
DohDb.logger.call('result', "affected #{retval} rows")
|
47
|
+
retval
|
48
|
+
end
|
49
|
+
|
50
|
+
def update(statement)
|
51
|
+
generic_query(statement)
|
52
|
+
retval = @mysqlh.affected_rows
|
53
|
+
DohDb.logger.call('result', "updated #{retval} rows")
|
54
|
+
retval
|
55
|
+
end
|
56
|
+
|
57
|
+
def update_row(statement)
|
58
|
+
retval = update(statement)
|
59
|
+
raise UnexpectedQueryResult, "updated #{retval} rows; expected 1" unless retval == 1
|
60
|
+
retval
|
61
|
+
end
|
62
|
+
|
63
|
+
def update_hash(hash, table, primary_key_value, primary_key_name)
|
64
|
+
items = hash.keys.collect {|key| key + ' = ' + hash[key].to_sql}
|
65
|
+
query("UPDATE #{table} SET #{items.join(', ')} WHERE #{primary_key_name} = #{primary_key_value.to_sql}")
|
66
|
+
end
|
67
|
+
|
68
|
+
def insert(statement)
|
69
|
+
generic_query(statement)
|
70
|
+
retval = @mysqlh.last_id
|
71
|
+
DohDb.logger.call('result', "insert_id was #{retval}")
|
72
|
+
retval
|
73
|
+
end
|
74
|
+
|
75
|
+
def insert_hash(hash, table, quote_strings = true)
|
76
|
+
insert_hash_helper(hash, table, 'INSERT', quote_strings)
|
77
|
+
end
|
78
|
+
|
79
|
+
def insert_hashes(hashes, table, quote_strings = true)
|
80
|
+
insert_hashes_helper(hashes, table, 'INSERT', quote_strings)
|
81
|
+
end
|
82
|
+
|
83
|
+
def insert_ignore_hash(hash, table, quote_strings = true)
|
84
|
+
insert_hash_helper(hash, table, 'INSERT IGNORE', quote_strings)
|
85
|
+
end
|
86
|
+
|
87
|
+
def insert_ignore_hashes(hash, table, quote_strings = true)
|
88
|
+
insert_hashes_helper(hash, table, 'INSERT IGNORE', quote_strings)
|
89
|
+
end
|
90
|
+
|
91
|
+
def replace_hash(hash, table, quote_strings = true)
|
92
|
+
insert_hash_helper(hash, table, 'REPLACE', quote_strings)
|
93
|
+
end
|
94
|
+
|
95
|
+
# The most generic form of select.
|
96
|
+
# It calls to_s on the statement object to facilitate the use of sql builder objects.
|
97
|
+
def select(statement, row_builder = nil)
|
98
|
+
result_set = generic_query(statement)
|
99
|
+
DohDb.logger.call('result', "selected #{result_set.size} rows")
|
100
|
+
rows = get_row_builder(row_builder).build_rows(result_set)
|
101
|
+
rows
|
102
|
+
end
|
103
|
+
|
104
|
+
# Simple convenience wrapper around the generic select call.
|
105
|
+
# Throws an exception unless the result set is a single row.
|
106
|
+
# Returns the row selected.
|
107
|
+
def select_row(statement, row_builder = nil)
|
108
|
+
rows = select(statement, row_builder)
|
109
|
+
raise UnexpectedQueryResult, "selected #{rows.size} rows; expected 1" unless rows.size == 1
|
110
|
+
rows[0]
|
111
|
+
end
|
112
|
+
|
113
|
+
# Simple convenience wrapper around the generic select call.
|
114
|
+
# Throws an exception unless the result set is empty or a single row.
|
115
|
+
# Returns nil if the result set is empty, or the row selected.
|
116
|
+
def select_optional_row(statement, row_builder = nil)
|
117
|
+
rows = select(statement, row_builder)
|
118
|
+
raise UnexpectedQueryResult, "selected #{rows.size} rows; expected 0 or 1" if rows.size > 1
|
119
|
+
if rows.empty? then nil else rows[0] end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Simple convenience wrapper around select_row.
|
123
|
+
# Returns the first (and typically, the only) field from the selected row.
|
124
|
+
def select_field(statement, row_builder = nil)
|
125
|
+
select_row(statement, row_builder).at(0)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Simple convenience wrapper around select_optional_row.
|
129
|
+
# Returns the first (and typically, the only) field from the selected row, if any, or nil.
|
130
|
+
def select_optional_field(statement, row_builder = nil)
|
131
|
+
row = select_optional_row(statement, row_builder)
|
132
|
+
row && row.at(0)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Rows in the result set must have 2 or more fields.
|
136
|
+
# If there are 2 fields, returns a hash where each key is the first field in the result set, and the value is the second field.
|
137
|
+
# If there are more than 2 fields, returns a hash where each key is the first field in the result set,
|
138
|
+
# and the value is the row itself, as a Hash, and without the field used as a key.
|
139
|
+
def select_transpose(statement, row_builder = nil)
|
140
|
+
rows = select(statement, row_builder)
|
141
|
+
return {} if rows.empty?
|
142
|
+
field_count = rows.first.size
|
143
|
+
if field_count < 2
|
144
|
+
raise UnexpectedQueryResult, "must select at least 2 fields in order to transpose"
|
145
|
+
elsif field_count == 2
|
146
|
+
Doh.array_to_hash(rows) { |row| [row.at(0), row.at(1)] }
|
147
|
+
else
|
148
|
+
key_field = rows.first.keys.first
|
149
|
+
Doh.array_to_hash(rows) do |row|
|
150
|
+
value = row.to_h
|
151
|
+
value.delete(key_field)
|
152
|
+
[row.at(0), value]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns an array of arrays, where the individual arrays contain just the values from each database row -- they lack field names.
|
158
|
+
def select_values(statement, row_builder = nil)
|
159
|
+
select(statement, row_builder).collect { |row| row.values }
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns an array of the first (and typically, the only) field of every row in the result set.
|
163
|
+
def select_list(statement, row_builder = nil)
|
164
|
+
select(statement, row_builder).collect { |row| row.at(0) }
|
165
|
+
end
|
166
|
+
|
167
|
+
def transaction
|
168
|
+
query("START TRANSACTION")
|
169
|
+
need_rollback = true
|
170
|
+
begin
|
171
|
+
retval = yield(self)
|
172
|
+
if !@testing_rollback
|
173
|
+
query("COMMIT")
|
174
|
+
need_rollback = false
|
175
|
+
end
|
176
|
+
ensure
|
177
|
+
query("ROLLBACK") if need_rollback
|
178
|
+
end
|
179
|
+
retval
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_transaction_rollback
|
183
|
+
begin
|
184
|
+
@testing_rollback = true
|
185
|
+
yield(self)
|
186
|
+
ensure
|
187
|
+
@testing_rollback = false
|
188
|
+
end
|
189
|
+
end
|
190
|
+
private
|
191
|
+
def generic_query(statement)
|
192
|
+
sqlstr = statement.to_s
|
193
|
+
DohDb.logger.call('query', sqlstr)
|
194
|
+
@mysqlh.query(sqlstr)
|
195
|
+
rescue Exception => excpt
|
196
|
+
DohDb.logger.call('error', "caught exception #{excpt.message} during query: #{sqlstr}")
|
197
|
+
close
|
198
|
+
raise
|
199
|
+
end
|
200
|
+
|
201
|
+
def get_key_insert_str(keys)
|
202
|
+
"(`#{keys.join('`,`')}`)"
|
203
|
+
end
|
204
|
+
|
205
|
+
def insert_hash_helper(hash, table, keyword, quote_strings)
|
206
|
+
names = []
|
207
|
+
values = []
|
208
|
+
hash.each_pair do |key, value|
|
209
|
+
names.push(key)
|
210
|
+
values.push(if quote_strings || !value.is_a?(String) then value.to_sql else value end)
|
211
|
+
end
|
212
|
+
|
213
|
+
insert("#{keyword} INTO #{table} (`#{names.join('`,`')}`) VALUES (#{values.join(',')})")
|
214
|
+
end
|
215
|
+
|
216
|
+
def insert_hashes_helper(hashes, table, keyword, quote_strings)
|
217
|
+
<<<<<<< HEAD:lib/dohmysql/handle.rb
|
218
|
+
return if hashes.empty?
|
219
|
+
|
220
|
+
=======
|
221
|
+
>>>>>>> implement insert_hashes, mostly not-sharing with insert_hash for speed (3% or so decrease on unit test speeds when I had them shared):lib/doh/mysql/handle.rb
|
222
|
+
valuestrs = []
|
223
|
+
keys = hashes[0].keys
|
224
|
+
keystr = get_key_insert_str(keys)
|
225
|
+
hashes.each do |hash|
|
226
|
+
values = []
|
227
|
+
keys.each do |key|
|
228
|
+
value = hash[key]
|
229
|
+
values.push(if quote_strings || !value.is_a?(String) then value.to_sql else value end)
|
230
|
+
end
|
231
|
+
valuestrs.push("(#{values.join(',')})")
|
232
|
+
end
|
233
|
+
|
234
|
+
insert("#{keyword} INTO #{table} #{keystr} VALUES #{valuestrs.join(",")}")
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
def get_row_builder(row_builder = nil)
|
239
|
+
if row_builder.nil?
|
240
|
+
TypedRowBuilder.new
|
241
|
+
elsif row_builder == :read
|
242
|
+
TypedRowBuilder.new(ReadOnlyRow)
|
243
|
+
elsif row_builder == :hash
|
244
|
+
TypedRowBuilder.new(HashRow)
|
245
|
+
elsif row_builder == :write
|
246
|
+
TypedRowBuilder.new(WritableRow)
|
247
|
+
elsif row_builder == :smart
|
248
|
+
TypedRowBuilder.new(SmartRow)
|
249
|
+
elsif row_builder.respond_to?('build_rows')
|
250
|
+
row_builder
|
251
|
+
else
|
252
|
+
TypedRowBuilder.new(row_builder)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|
data/test/handle.dt.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dohmysql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.29
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Makani Mason
|
@@ -31,28 +31,28 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - '>='
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 0.2.
|
34
|
+
version: 0.2.15
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - '>='
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 0.2.
|
41
|
+
version: 0.2.15
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: dohlog
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - '>='
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: 0.2.
|
48
|
+
version: 0.2.4
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - '>='
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: 0.2.
|
55
|
+
version: 0.2.4
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: mysql2
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -73,28 +73,28 @@ dependencies:
|
|
73
73
|
requirements:
|
74
74
|
- - '>='
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: 0.1.
|
76
|
+
version: 0.1.14
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - '>='
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: 0.1.
|
83
|
+
version: 0.1.14
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: dohtest
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
88
|
- - '>='
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: 0.1.
|
90
|
+
version: 0.1.24
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - '>='
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: 0.1.
|
97
|
+
version: 0.1.24
|
98
98
|
description: wrapper classes around low level mysql gem to provide a better interface
|
99
99
|
email:
|
100
100
|
- devinfo@atpsoft.com
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- lib/dohmysql/error.rb
|
119
119
|
- lib/dohmysql/file_util.rb
|
120
120
|
- lib/dohmysql/handle.rb
|
121
|
+
- lib/dohmysql/handle.rb.orig
|
121
122
|
- lib/dohmysql/hash_row.rb
|
122
123
|
- lib/dohmysql/load_sql.rb
|
123
124
|
- lib/dohmysql/logger.rb
|
@@ -162,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
163
|
version: '0'
|
163
164
|
requirements: []
|
164
165
|
rubyforge_project:
|
165
|
-
rubygems_version: 2.0.
|
166
|
+
rubygems_version: 2.0.2
|
166
167
|
signing_key:
|
167
168
|
specification_version: 4
|
168
169
|
summary: friendly mysql client interface
|