sequel 0.4.4.1 → 0.4.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG +10 -0
  2. data/Rakefile +161 -159
  3. data/lib/sequel.rb +14 -10
  4. data/lib/sequel/adapters/adapter_skeleton.rb +2 -1
  5. data/lib/sequel/adapters/ado.rb +2 -1
  6. data/lib/sequel/adapters/db2.rb +5 -3
  7. data/lib/sequel/adapters/dbi.rb +2 -1
  8. data/lib/sequel/adapters/informix.rb +2 -1
  9. data/lib/sequel/adapters/jdbc.rb +3 -2
  10. data/lib/sequel/adapters/mysql.rb +268 -264
  11. data/lib/sequel/adapters/odbc.rb +7 -2
  12. data/lib/sequel/adapters/odbc_mssql.rb +1 -1
  13. data/lib/sequel/adapters/openbase.rb +2 -1
  14. data/lib/sequel/adapters/oracle.rb +2 -1
  15. data/lib/sequel/adapters/postgres.rb +32 -16
  16. data/lib/sequel/adapters/sqlite.rb +7 -6
  17. data/lib/sequel/array_keys.rb +295 -295
  18. data/lib/sequel/connection_pool.rb +1 -1
  19. data/lib/sequel/core_sql.rb +14 -5
  20. data/lib/sequel/database.rb +4 -4
  21. data/lib/sequel/dataset.rb +12 -10
  22. data/lib/sequel/dataset/convenience.rb +10 -8
  23. data/lib/sequel/dataset/sequelizer.rb +19 -16
  24. data/lib/sequel/dataset/sql.rb +43 -30
  25. data/lib/sequel/exceptions.rb +45 -0
  26. data/lib/sequel/migration.rb +7 -5
  27. data/lib/sequel/model.rb +1 -1
  28. data/lib/sequel/model/base.rb +3 -3
  29. data/lib/sequel/model/hooks.rb +0 -4
  30. data/lib/sequel/model/record.rb +9 -9
  31. data/lib/sequel/model/relations.rb +2 -2
  32. data/lib/sequel/pretty_table.rb +6 -3
  33. data/lib/sequel/schema/schema_sql.rb +11 -6
  34. data/lib/sequel/worker.rb +8 -7
  35. data/spec/adapters/sqlite_spec.rb +3 -3
  36. data/spec/array_keys_spec.rb +543 -543
  37. data/spec/connection_pool_spec.rb +6 -3
  38. data/spec/database_spec.rb +4 -4
  39. data/spec/dataset_spec.rb +25 -25
  40. data/spec/migration_spec.rb +1 -1
  41. data/spec/model_spec.rb +16 -16
  42. data/spec/sequelizer_spec.rb +7 -7
  43. data/spec/spec.opts +8 -0
  44. metadata +5 -5
  45. data/lib/sequel/error.rb +0 -22
@@ -1,265 +1,269 @@
1
- require 'mysql'
2
-
3
- # Monkey patch Mysql::Result to yield hashes with symbol keys
4
- class Mysql::Result
5
- MYSQL_TYPES = {
6
- 0 => :to_d, # MYSQL_TYPE_DECIMAL
7
- 1 => :to_i, # MYSQL_TYPE_TINY
8
- 2 => :to_i, # MYSQL_TYPE_SHORT
9
- 3 => :to_i, # MYSQL_TYPE_LONG
10
- 4 => :to_f, # MYSQL_TYPE_FLOAT
11
- 5 => :to_f, # MYSQL_TYPE_DOUBLE
12
- # 6 => ??, # MYSQL_TYPE_NULL
13
- 7 => :to_time, # MYSQL_TYPE_TIMESTAMP
14
- 8 => :to_i, # MYSQL_TYPE_LONGLONG
15
- 9 => :to_i, # MYSQL_TYPE_INT24
16
- 10 => :to_time, # MYSQL_TYPE_DATE
17
- 11 => :to_time, # MYSQL_TYPE_TIME
18
- 12 => :to_time, # MYSQL_TYPE_DATETIME
19
- 13 => :to_i, # MYSQL_TYPE_YEAR
20
- 14 => :to_time, # MYSQL_TYPE_NEWDATE
21
- # 15 => :to_s # MYSQL_TYPE_VARCHAR
22
- # 16 => :to_s, # MYSQL_TYPE_BIT
23
- 246 => :to_d, # MYSQL_TYPE_NEWDECIMAL
24
- 247 => :to_i, # MYSQL_TYPE_ENUM
25
- 248 => :to_i # MYSQL_TYPE_SET
26
- # 249 => :to_s, # MYSQL_TYPE_TINY_BLOB
27
- # 250 => :to_s, # MYSQL_TYPE_MEDIUM_BLOB
28
- # 251 => :to_s, # MYSQL_TYPE_LONG_BLOB
29
- # 252 => :to_s, # MYSQL_TYPE_BLOB
30
- # 253 => :to_s, # MYSQL_TYPE_VAR_STRING
31
- # 254 => :to_s, # MYSQL_TYPE_STRING
32
- # 255 => :to_s # MYSQL_TYPE_GEOMETRY
33
- }
34
-
35
- def convert_type(v, type)
36
- v ? ((t = MYSQL_TYPES[type]) ? v.send(t) : v) : nil
37
- end
38
-
39
- def columns(with_table = nil)
40
- unless @columns
41
- @column_types = []
42
- @columns = fetch_fields.map do |f|
43
- @column_types << f.type
44
- (with_table ? (f.table + "." + f.name) : f.name).to_sym
45
- end
46
- end
47
- @columns
48
- end
49
-
50
- def each_array(with_table = nil)
51
- c = columns
52
- while row = fetch_row
53
- c.each_with_index do |f, i|
54
- if (t = MYSQL_TYPES[@column_types[i]]) && (v = row[i])
55
- row[i] = v.send(t)
56
- end
57
- end
58
- row.keys = c
59
- yield row
60
- end
61
- end
62
-
63
- def each_hash(with_table = nil)
64
- c = columns
65
- while row = fetch_row
66
- h = {}
67
- c.each_with_index {|f, i| h[f] = convert_type(row[i], @column_types[i])}
68
- yield h
69
- end
70
- end
71
- end
72
-
73
- module Sequel
74
- module MySQL
75
- class Database < Sequel::Database
76
- set_adapter_scheme :mysql
77
-
78
- def serial_primary_key_options
79
- {:primary_key => true, :type => :integer, :auto_increment => true}
80
- end
81
-
82
- AUTO_INCREMENT = 'AUTO_INCREMENT'.freeze
83
-
84
- def auto_increment_sql
85
- AUTO_INCREMENT
86
- end
87
-
88
- def connect
89
- conn = Mysql.real_connect(@opts[:host], @opts[:user], @opts[:password],
90
- @opts[:database], @opts[:port], nil, Mysql::CLIENT_MULTI_RESULTS)
91
- conn.query_with_result = false
92
- if encoding = @opts[:encoding] || @opts[:charset]
93
- conn.query("set character_set_connection = '#{encoding}'")
94
- conn.query("set character_set_client = '#{encoding}'")
95
- conn.query("set character_set_results = '#{encoding}'")
96
- end
97
- conn.reconnect = true
98
- conn
99
- end
100
-
101
- def disconnect
102
- @pool.disconnect {|c| c.close}
103
- end
104
-
105
- def tables
106
- @pool.hold do |conn|
107
- conn.list_tables.map {|t| t.to_sym}
108
- end
109
- end
110
-
111
- def dataset(opts = nil)
112
- MySQL::Dataset.new(self, opts)
113
- end
114
-
115
- def execute(sql)
116
- @logger.info(sql) if @logger
117
- @pool.hold do |conn|
118
- conn.query(sql)
119
- end
120
- end
121
-
122
- def execute_select(sql)
123
- @logger.info(sql) if @logger
124
- @pool.hold do |conn|
125
- conn.query(sql)
126
- conn.use_result
127
- end
128
- end
129
-
130
- def execute_insert(sql)
131
- @logger.info(sql) if @logger
132
- @pool.hold do |conn|
133
- conn.query(sql)
134
- conn.insert_id
135
- end
136
- end
137
-
138
- def execute_affected(sql)
139
- @logger.info(sql) if @logger
140
- @pool.hold do |conn|
141
- conn.query(sql)
142
- conn.affected_rows
143
- end
144
- end
145
-
146
- def alter_table_sql(table, op)
147
- case op[:op]
148
- when :rename_column
149
- "ALTER TABLE #{table} CHANGE COLUMN #{literal(op[:name])} #{literal(op[:new_name])} #{op[:type]}"
150
- when :set_column_type
151
- "ALTER TABLE #{table} CHANGE COLUMN #{literal(op[:name])} #{literal(op[:name])} #{op[:type]}"
152
- when :drop_index
153
- "DROP INDEX #{default_index_name(table, op[:columns])} ON #{table}"
154
- else
155
- super(table, op)
156
- end
157
- end
158
-
159
- def transaction
160
- @pool.hold do |conn|
161
- @transactions ||= []
162
- if @transactions.include? Thread.current
163
- return yield(conn)
164
- end
165
- conn.query(SQL_BEGIN)
166
- begin
167
- @transactions << Thread.current
168
- result = yield(conn)
169
- conn.query(SQL_COMMIT)
170
- result
171
- rescue => e
172
- conn.query(SQL_ROLLBACK)
173
- raise e unless SequelRollbackError === e
174
- ensure
175
- @transactions.delete(Thread.current)
176
- end
177
- end
178
- end
179
- end
180
-
181
- class Dataset < Sequel::Dataset
182
- def quote_column_ref(c); "`#{c}`"; end
183
-
184
- TRUE = '1'
185
- FALSE = '0'
186
-
187
- def literal(v)
188
- case v
189
- when LiteralString: v
190
- when String: "'#{v.gsub(/'|\\/, '\&\&')}'"
191
- when true: TRUE
192
- when false: FALSE
193
- else
194
- super
195
- end
196
- end
197
-
198
- def match_expr(l, r)
199
- case r
200
- when Regexp:
201
- r.casefold? ? \
202
- "(#{literal(l)} REGEXP #{literal(r.source)})" :
203
- "(#{literal(l)} REGEXP BINARY #{literal(r.source)})"
204
- else
205
- super
206
- end
207
- end
208
-
209
- # MySQL supports ORDER and LIMIT clauses in UPDATE statements.
210
- def update_sql(values, opts = nil)
211
- sql = super
212
-
213
- opts = opts ? @opts.merge(opts) : @opts
214
-
215
- if order = opts[:order]
216
- sql << " ORDER BY #{column_list(order)}"
217
- end
218
-
219
- if limit = opts[:limit]
220
- sql << " LIMIT #{limit}"
221
- end
222
-
223
- sql
224
- end
225
-
226
- def insert(*values)
227
- @db.execute_insert(insert_sql(*values))
228
- end
229
-
230
- def update(*args, &block)
231
- @db.execute_affected(update_sql(*args, &block))
232
- end
233
-
234
- def delete(opts = nil)
235
- @db.execute_affected(delete_sql(opts))
236
- end
237
-
238
- def fetch_rows(sql)
239
- @db.synchronize do
240
- r = @db.execute_select(sql)
241
- begin
242
- @columns = r.columns
243
- r.each_hash {|row| yield row}
244
- ensure
245
- r.free
246
- end
247
- end
248
- self
249
- end
250
-
251
- def array_tuples_fetch_rows(sql, &block)
252
- @db.synchronize do
253
- r = @db.execute_select(sql)
254
- begin
255
- @columns = r.columns
256
- r.each_array(&block)
257
- ensure
258
- r.free
259
- end
260
- end
261
- self
262
- end
263
- end
264
- end
1
+ require 'mysql'
2
+
3
+ # Monkey patch Mysql::Result to yield hashes with symbol keys
4
+ class Mysql::Result
5
+ MYSQL_TYPES = {
6
+ 0 => :to_d, # MYSQL_TYPE_DECIMAL
7
+ 1 => :to_i, # MYSQL_TYPE_TINY
8
+ 2 => :to_i, # MYSQL_TYPE_SHORT
9
+ 3 => :to_i, # MYSQL_TYPE_LONG
10
+ 4 => :to_f, # MYSQL_TYPE_FLOAT
11
+ 5 => :to_f, # MYSQL_TYPE_DOUBLE
12
+ # 6 => ??, # MYSQL_TYPE_NULL
13
+ 7 => :to_time, # MYSQL_TYPE_TIMESTAMP
14
+ 8 => :to_i, # MYSQL_TYPE_LONGLONG
15
+ 9 => :to_i, # MYSQL_TYPE_INT24
16
+ 10 => :to_time, # MYSQL_TYPE_DATE
17
+ 11 => :to_time, # MYSQL_TYPE_TIME
18
+ 12 => :to_time, # MYSQL_TYPE_DATETIME
19
+ 13 => :to_i, # MYSQL_TYPE_YEAR
20
+ 14 => :to_time, # MYSQL_TYPE_NEWDATE
21
+ # 15 => :to_s # MYSQL_TYPE_VARCHAR
22
+ # 16 => :to_s, # MYSQL_TYPE_BIT
23
+ 246 => :to_d, # MYSQL_TYPE_NEWDECIMAL
24
+ 247 => :to_i, # MYSQL_TYPE_ENUM
25
+ 248 => :to_i # MYSQL_TYPE_SET
26
+ # 249 => :to_s, # MYSQL_TYPE_TINY_BLOB
27
+ # 250 => :to_s, # MYSQL_TYPE_MEDIUM_BLOB
28
+ # 251 => :to_s, # MYSQL_TYPE_LONG_BLOB
29
+ # 252 => :to_s, # MYSQL_TYPE_BLOB
30
+ # 253 => :to_s, # MYSQL_TYPE_VAR_STRING
31
+ # 254 => :to_s, # MYSQL_TYPE_STRING
32
+ # 255 => :to_s # MYSQL_TYPE_GEOMETRY
33
+ }
34
+
35
+ def convert_type(v, type)
36
+ v ? ((t = MYSQL_TYPES[type]) ? v.send(t) : v) : nil
37
+ end
38
+
39
+ def columns(with_table = nil)
40
+ unless @columns
41
+ @column_types = []
42
+ @columns = fetch_fields.map do |f|
43
+ @column_types << f.type
44
+ (with_table ? (f.table + "." + f.name) : f.name).to_sym
45
+ end
46
+ end
47
+ @columns
48
+ end
49
+
50
+ def each_array(with_table = nil)
51
+ c = columns
52
+ while row = fetch_row
53
+ c.each_with_index do |f, i|
54
+ if (t = MYSQL_TYPES[@column_types[i]]) && (v = row[i])
55
+ row[i] = v.send(t)
56
+ end
57
+ end
58
+ row.keys = c
59
+ yield row
60
+ end
61
+ end
62
+
63
+ def each_hash(with_table = nil)
64
+ c = columns
65
+ while row = fetch_row
66
+ h = {}
67
+ c.each_with_index {|f, i| h[f] = convert_type(row[i], @column_types[i])}
68
+ yield h
69
+ end
70
+ end
71
+ end
72
+
73
+ module Sequel
74
+ module MySQL
75
+ class Database < Sequel::Database
76
+ set_adapter_scheme :mysql
77
+
78
+ def serial_primary_key_options
79
+ {:primary_key => true, :type => :integer, :auto_increment => true}
80
+ end
81
+
82
+ AUTO_INCREMENT = 'AUTO_INCREMENT'.freeze
83
+
84
+ def auto_increment_sql
85
+ AUTO_INCREMENT
86
+ end
87
+
88
+ def connect
89
+ conn = Mysql.real_connect(@opts[:host], @opts[:user], @opts[:password],
90
+ @opts[:database], @opts[:port], nil, Mysql::CLIENT_MULTI_RESULTS)
91
+ conn.query_with_result = false
92
+ if encoding = @opts[:encoding] || @opts[:charset]
93
+ conn.query("set character_set_connection = '#{encoding}'")
94
+ conn.query("set character_set_client = '#{encoding}'")
95
+ conn.query("set character_set_results = '#{encoding}'")
96
+ end
97
+ conn.reconnect = true
98
+ conn
99
+ end
100
+
101
+ def disconnect
102
+ @pool.disconnect {|c| c.close}
103
+ end
104
+
105
+ def tables
106
+ @pool.hold do |conn|
107
+ conn.list_tables.map {|t| t.to_sym}
108
+ end
109
+ end
110
+
111
+ def dataset(opts = nil)
112
+ MySQL::Dataset.new(self, opts)
113
+ end
114
+
115
+ def execute(sql)
116
+ @logger.info(sql) if @logger
117
+ @pool.hold do |conn|
118
+ conn.query(sql)
119
+ end
120
+ end
121
+
122
+ def execute_select(sql)
123
+ @logger.info(sql) if @logger
124
+ @pool.hold do |conn|
125
+ conn.query(sql)
126
+ conn.use_result
127
+ end
128
+ end
129
+
130
+ def execute_insert(sql)
131
+ @logger.info(sql) if @logger
132
+ @pool.hold do |conn|
133
+ conn.query(sql)
134
+ conn.insert_id
135
+ end
136
+ end
137
+
138
+ def execute_affected(sql)
139
+ @logger.info(sql) if @logger
140
+ @pool.hold do |conn|
141
+ conn.query(sql)
142
+ conn.affected_rows
143
+ end
144
+ end
145
+
146
+ def alter_table_sql(table, op)
147
+ case op[:op]
148
+ when :rename_column
149
+ "ALTER TABLE #{table} CHANGE COLUMN #{literal(op[:name])} #{literal(op[:new_name])} #{op[:type]}"
150
+ when :set_column_type
151
+ "ALTER TABLE #{table} CHANGE COLUMN #{literal(op[:name])} #{literal(op[:name])} #{op[:type]}"
152
+ when :drop_index
153
+ "DROP INDEX #{default_index_name(table, op[:columns])} ON #{table}"
154
+ else
155
+ super(table, op)
156
+ end
157
+ end
158
+
159
+ def transaction
160
+ @pool.hold do |conn|
161
+ @transactions ||= []
162
+ if @transactions.include? Thread.current
163
+ return yield(conn)
164
+ end
165
+ conn.query(SQL_BEGIN)
166
+ begin
167
+ @transactions << Thread.current
168
+ result = yield(conn)
169
+ conn.query(SQL_COMMIT)
170
+ result
171
+ rescue => e
172
+ conn.query(SQL_ROLLBACK)
173
+ raise e unless Error::Rollback === e
174
+ ensure
175
+ @transactions.delete(Thread.current)
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ class Dataset < Sequel::Dataset
182
+ def quote_column_ref(c); "`#{c}`"; end
183
+
184
+ TRUE = '1'
185
+ FALSE = '0'
186
+
187
+ def literal(v)
188
+ case v
189
+ when LiteralString
190
+ v
191
+ when String
192
+ "'#{v.gsub(/'|\\/, '\&\&')}'"
193
+ when true
194
+ TRUE
195
+ when false
196
+ FALSE
197
+ else
198
+ super
199
+ end
200
+ end
201
+
202
+ def match_expr(l, r)
203
+ case r
204
+ when Regexp
205
+ r.casefold? ? \
206
+ "(#{literal(l)} REGEXP #{literal(r.source)})" :
207
+ "(#{literal(l)} REGEXP BINARY #{literal(r.source)})"
208
+ else
209
+ super
210
+ end
211
+ end
212
+
213
+ # MySQL supports ORDER and LIMIT clauses in UPDATE statements.
214
+ def update_sql(values, opts = nil)
215
+ sql = super
216
+
217
+ opts = opts ? @opts.merge(opts) : @opts
218
+
219
+ if order = opts[:order]
220
+ sql << " ORDER BY #{column_list(order)}"
221
+ end
222
+
223
+ if limit = opts[:limit]
224
+ sql << " LIMIT #{limit}"
225
+ end
226
+
227
+ sql
228
+ end
229
+
230
+ def insert(*values)
231
+ @db.execute_insert(insert_sql(*values))
232
+ end
233
+
234
+ def update(*args, &block)
235
+ @db.execute_affected(update_sql(*args, &block))
236
+ end
237
+
238
+ def delete(opts = nil)
239
+ @db.execute_affected(delete_sql(opts))
240
+ end
241
+
242
+ def fetch_rows(sql)
243
+ @db.synchronize do
244
+ r = @db.execute_select(sql)
245
+ begin
246
+ @columns = r.columns
247
+ r.each_hash {|row| yield row}
248
+ ensure
249
+ r.free
250
+ end
251
+ end
252
+ self
253
+ end
254
+
255
+ def array_tuples_fetch_rows(sql, &block)
256
+ @db.synchronize do
257
+ r = @db.execute_select(sql)
258
+ begin
259
+ @columns = r.columns
260
+ r.each_array(&block)
261
+ ensure
262
+ r.free
263
+ end
264
+ end
265
+ self
266
+ end
267
+ end
268
+ end
265
269
  end