sequel_core 2.2.0 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. metadata +30 -101
  2. data/CHANGELOG +0 -1519
  3. data/COPYING +0 -19
  4. data/README +0 -313
  5. data/Rakefile +0 -158
  6. data/bin/sequel +0 -117
  7. data/doc/cheat_sheet.rdoc +0 -225
  8. data/doc/dataset_filtering.rdoc +0 -182
  9. data/lib/sequel_core.rb +0 -136
  10. data/lib/sequel_core/adapters/adapter_skeleton.rb +0 -68
  11. data/lib/sequel_core/adapters/ado.rb +0 -90
  12. data/lib/sequel_core/adapters/db2.rb +0 -160
  13. data/lib/sequel_core/adapters/dbi.rb +0 -127
  14. data/lib/sequel_core/adapters/informix.rb +0 -89
  15. data/lib/sequel_core/adapters/jdbc.rb +0 -110
  16. data/lib/sequel_core/adapters/mysql.rb +0 -486
  17. data/lib/sequel_core/adapters/odbc.rb +0 -167
  18. data/lib/sequel_core/adapters/odbc_mssql.rb +0 -106
  19. data/lib/sequel_core/adapters/openbase.rb +0 -76
  20. data/lib/sequel_core/adapters/oracle.rb +0 -182
  21. data/lib/sequel_core/adapters/postgres.rb +0 -560
  22. data/lib/sequel_core/adapters/sqlite.rb +0 -270
  23. data/lib/sequel_core/connection_pool.rb +0 -194
  24. data/lib/sequel_core/core_ext.rb +0 -197
  25. data/lib/sequel_core/core_sql.rb +0 -184
  26. data/lib/sequel_core/database.rb +0 -462
  27. data/lib/sequel_core/database/schema.rb +0 -156
  28. data/lib/sequel_core/dataset.rb +0 -457
  29. data/lib/sequel_core/dataset/callback.rb +0 -13
  30. data/lib/sequel_core/dataset/convenience.rb +0 -245
  31. data/lib/sequel_core/dataset/pagination.rb +0 -96
  32. data/lib/sequel_core/dataset/query.rb +0 -41
  33. data/lib/sequel_core/dataset/schema.rb +0 -15
  34. data/lib/sequel_core/dataset/sql.rb +0 -889
  35. data/lib/sequel_core/deprecated.rb +0 -26
  36. data/lib/sequel_core/exceptions.rb +0 -42
  37. data/lib/sequel_core/migration.rb +0 -187
  38. data/lib/sequel_core/object_graph.rb +0 -216
  39. data/lib/sequel_core/pretty_table.rb +0 -71
  40. data/lib/sequel_core/schema.rb +0 -2
  41. data/lib/sequel_core/schema/generator.rb +0 -239
  42. data/lib/sequel_core/schema/sql.rb +0 -326
  43. data/lib/sequel_core/sql.rb +0 -812
  44. data/lib/sequel_core/worker.rb +0 -68
  45. data/spec/adapters/informix_spec.rb +0 -96
  46. data/spec/adapters/mysql_spec.rb +0 -765
  47. data/spec/adapters/oracle_spec.rb +0 -222
  48. data/spec/adapters/postgres_spec.rb +0 -441
  49. data/spec/adapters/sqlite_spec.rb +0 -413
  50. data/spec/connection_pool_spec.rb +0 -363
  51. data/spec/core_ext_spec.rb +0 -156
  52. data/spec/core_sql_spec.rb +0 -427
  53. data/spec/database_spec.rb +0 -963
  54. data/spec/dataset_spec.rb +0 -2933
  55. data/spec/expression_filters_spec.rb +0 -316
  56. data/spec/migration_spec.rb +0 -261
  57. data/spec/object_graph_spec.rb +0 -230
  58. data/spec/pretty_table_spec.rb +0 -58
  59. data/spec/rcov.opts +0 -6
  60. data/spec/schema_generator_spec.rb +0 -122
  61. data/spec/schema_spec.rb +0 -422
  62. data/spec/spec.opts +0 -0
  63. data/spec/spec_config.rb +0 -7
  64. data/spec/spec_config.rb.example +0 -8
  65. data/spec/spec_helper.rb +0 -55
  66. data/spec/worker_spec.rb +0 -96
@@ -1,127 +0,0 @@
1
- require 'dbi'
2
-
3
- module Sequel
4
- module DBI
5
- class Database < Sequel::Database
6
- attr_writer :lowercase
7
-
8
- set_adapter_scheme :dbi
9
-
10
- DBI_ADAPTERS = {
11
- :ado => "ADO",
12
- :db2 => "DB2",
13
- :frontbase => "FrontBase",
14
- :interbase => "InterBase",
15
- :msql => "Msql",
16
- :mysql => "Mysql",
17
- :odbc => "ODBC",
18
- :oracle => "Oracle",
19
- :pg => "pg",
20
- :proxy => "Proxy",
21
- :sqlite => "SQLite",
22
- :sqlrelay => "SQLRelay"
23
- }
24
-
25
- # Converts a uri to an options hash. These options are then passed
26
- # to a newly created database object.
27
- def self.uri_to_options(uri)
28
- database = (m = /\/(.*)/.match(uri.path)) && (m[1])
29
- if m = /dbi-(.+)/.match(uri.scheme)
30
- adapter = DBI_ADAPTERS[m[1].to_sym] || m[1]
31
- database = "#{adapter}:dbname=#{database}"
32
- end
33
- {
34
- :user => uri.user,
35
- :password => uri.password,
36
- :host => uri.host,
37
- :port => uri.port,
38
- :database => database
39
- }
40
- end
41
-
42
-
43
- def connect
44
- dbname = @opts[:database]
45
- if dbname !~ /^DBI:/ then
46
- dbname = "DBI:#{dbname}"
47
- [:host, :port].each{|sym| dbname += ";#{sym}=#{@opts[sym]}" unless @opts[sym].blank?}
48
- end
49
- ::DBI.connect(dbname, @opts[:user], @opts[:password])
50
- end
51
-
52
- def disconnect
53
- @pool.disconnect {|c| c.disconnect}
54
- end
55
-
56
- def dataset(opts = nil)
57
- DBI::Dataset.new(self, opts)
58
- end
59
-
60
- def execute(sql)
61
- log_info(sql)
62
- @pool.hold do |conn|
63
- conn.execute(sql)
64
- end
65
- end
66
-
67
- def do(sql)
68
- log_info(sql)
69
- @pool.hold do |conn|
70
- conn.do(sql)
71
- end
72
- end
73
-
74
- # Converts all column names to lowercase
75
- def lowercase
76
- @lowercase ||= false
77
- end
78
- end
79
-
80
- class Dataset < Sequel::Dataset
81
- def literal(v)
82
- case v
83
- when Time
84
- literal(v.iso8601)
85
- when Date, DateTime
86
- literal(v.to_s)
87
- else
88
- super
89
- end
90
- end
91
-
92
- def fetch_rows(sql, &block)
93
- @db.synchronize do
94
- s = @db.execute sql
95
- begin
96
- @columns = s.column_names.map do |c|
97
- @db.lowercase ? c.downcase.to_sym : c.to_sym
98
- end
99
- s.fetch {|r| yield hash_row(s, r)}
100
- ensure
101
- s.finish rescue nil
102
- end
103
- end
104
- self
105
- end
106
-
107
- def hash_row(stmt, row)
108
- @columns.inject({}) do |m, c|
109
- m[c] = row.shift
110
- m
111
- end
112
- end
113
-
114
- def insert(*values)
115
- @db.do insert_sql(*values)
116
- end
117
-
118
- def update(*args, &block)
119
- @db.do update_sql(*args, &block)
120
- end
121
-
122
- def delete(opts = nil)
123
- @db.do delete_sql(opts)
124
- end
125
- end
126
- end
127
- end
@@ -1,89 +0,0 @@
1
- require 'informix'
2
-
3
- module Sequel
4
- module Informix
5
- class Database < Sequel::Database
6
- set_adapter_scheme :informix
7
-
8
- # AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
9
- #
10
- # def auto_increment_sql
11
- # AUTO_INCREMENT
12
- # end
13
-
14
- def connect
15
- ::Informix.connect(@opts[:database], @opts[:user], @opts[:password])
16
- end
17
-
18
- def disconnect
19
- @pool.disconnect {|c| c.close}
20
- end
21
-
22
- def dataset(opts = nil)
23
- Sequel::Informix::Dataset.new(self, opts)
24
- end
25
-
26
- # Returns number of rows affected
27
- def execute(sql)
28
- log_info(sql)
29
- @pool.hold {|c| c.immediate(sql)}
30
- end
31
- alias_method :do, :execute
32
-
33
- def query(sql, &block)
34
- log_info(sql)
35
- @pool.hold {|c| block[c.cursor(sql)]}
36
- end
37
- end
38
-
39
- class Dataset < Sequel::Dataset
40
- def literal(v)
41
- case v
42
- when Time
43
- literal(v.iso8601)
44
- when Date, DateTime
45
- literal(v.to_s)
46
- else
47
- super
48
- end
49
- end
50
-
51
- def select_sql(opts = nil)
52
- limit = opts.delete(:limit)
53
- offset = opts.delete(:offset)
54
- sql = super
55
- if limit
56
- limit = "FIRST #{limit}"
57
- offset = offset ? "SKIP #{offset}" : ""
58
- sql.sub!(/^select /i,"SELECT #{offset} #{limit} ")
59
- end
60
- sql
61
- end
62
-
63
- def fetch_rows(sql, &block)
64
- @db.synchronize do
65
- @db.query(sql) do |cursor|
66
- begin
67
- cursor.open.each_hash(&block)
68
- ensure
69
- cursor.drop
70
- end
71
- end
72
- end
73
- self
74
- end
75
-
76
- def insert(*values)
77
- @db.do insert_sql(*values)
78
- end
79
-
80
- def update(*args, &block)
81
- @db.do update_sql(*args, &block)
82
- end
83
-
84
- def delete(opts = nil)
85
- @db.do delete_sql(opts)
86
- end
87
- end
88
- end
89
- end
@@ -1,110 +0,0 @@
1
- require 'java'
2
-
3
- module Sequel
4
- module JDBC
5
- module JavaLang; include_package 'java.lang'; end
6
- module JavaSQL; include_package 'java.sql'; end
7
-
8
- def self.load_driver(driver)
9
- JavaLang::Class.forName(driver)
10
- # "com.mysql.jdbc.Driver"
11
- end
12
-
13
- class Database < Sequel::Database
14
- set_adapter_scheme :jdbc
15
-
16
- def connect
17
- unless conn_string = @opts[:uri] || @opts[:url] || @opts[:database]
18
- raise Error, "No connection string specified"
19
- end
20
- unless conn_string =~ /^jdbc:/
21
- conn_string = "jdbc:#{conn_string}"
22
- end
23
- JavaSQL::DriverManager.getConnection(
24
- conn_string,
25
- @opts[:user],
26
- @opts[:password]
27
- )
28
- # "jdbc:mysql://127.0.0.1:3306/ruby?user=root"
29
- # "mysql://127.0.0.1:3306/ruby?user=root"
30
- end
31
-
32
- def disconnect
33
- @pool.disconnect {|c| c.close}
34
- end
35
-
36
- def dataset(opts = nil)
37
- JDBC::Dataset.new(self, opts)
38
- end
39
-
40
- def execute_and_forget(sql)
41
- log_info(sql)
42
- @pool.hold do |conn|
43
- stmt = conn.createStatement
44
- begin
45
- stmt.executeQuery(sql)
46
- ensure
47
- stmt.close
48
- end
49
- end
50
- end
51
-
52
- def execute(sql)
53
- log_info(sql)
54
- @pool.hold do |conn|
55
- stmt = conn.createStatement
56
- begin
57
- yield stmt.executeQuery(sql)
58
- ensure
59
- stmt.close
60
- end
61
- end
62
- end
63
- end
64
-
65
- class Dataset < Sequel::Dataset
66
- def literal(v)
67
- case v
68
- when Time
69
- literal(v.iso8601)
70
- when Date, DateTime
71
- literal(v.to_s)
72
- else
73
- super
74
- end
75
- end
76
-
77
- def fetch_rows(sql, &block)
78
- @db.synchronize do
79
- @db.execute(sql) do |result|
80
- # get column names
81
- meta = result.getMetaData
82
- column_count = meta.getColumnCount
83
- @columns = []
84
- column_count.times {|i| @columns << meta.getColumnName(i+1).to_sym}
85
-
86
- # get rows
87
- while result.next
88
- row = {}
89
- @columns.each_with_index {|v, i| row[v] = result.getObject(i+1)}
90
- yield row
91
- end
92
- end
93
- end
94
- self
95
- end
96
-
97
- def insert(*values)
98
- @db.execute_and_forget insert_sql(*values)
99
- end
100
-
101
- def update(*args, &block)
102
- @db.execute_and_forget update_sql(*args, &block)
103
- end
104
-
105
- def delete(opts = nil)
106
- @db.execute_and_forget delete_sql(opts)
107
- end
108
- end
109
- end
110
- end
@@ -1,486 +0,0 @@
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_sequel_time, # MYSQL_TYPE_TIMESTAMP
14
- 8 => :to_i, # MYSQL_TYPE_LONGLONG
15
- 9 => :to_i, # MYSQL_TYPE_INT24
16
- 10 => :to_date, # MYSQL_TYPE_DATE
17
- 11 => :to_time, # MYSQL_TYPE_TIME
18
- 12 => :to_sequel_time, # MYSQL_TYPE_DATETIME
19
- 13 => :to_i, # MYSQL_TYPE_YEAR
20
- 14 => :to_date, # 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_blob, # MYSQL_TYPE_TINY_BLOB
27
- 250 => :to_blob, # MYSQL_TYPE_MEDIUM_BLOB
28
- 251 => :to_blob, # MYSQL_TYPE_LONG_BLOB
29
- 252 => :to_blob, # 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
- if v
37
- if type == 1 && Sequel.convert_tinyint_to_bool
38
- # We special case tinyint here to avoid adding
39
- # a method to an ancestor of Fixnum
40
- v.to_i == 0 ? false : true
41
- else
42
- (t = MYSQL_TYPES[type]) ? v.send(t) : v
43
- end
44
- else
45
- nil
46
- end
47
- end
48
-
49
- def columns(with_table = nil)
50
- unless @columns
51
- @column_types = []
52
- @columns = fetch_fields.map do |f|
53
- @column_types << f.type
54
- (with_table ? "#{f.table}.#{f.name}" : f.name).to_sym
55
- end
56
- end
57
- @columns
58
- end
59
-
60
- def each_array(with_table = nil)
61
- c = columns
62
- while row = fetch_row
63
- c.each_with_index do |f, i|
64
- if (t = MYSQL_TYPES[@column_types[i]]) && (v = row[i])
65
- row[i] = v.send(t)
66
- end
67
- end
68
- yield row
69
- end
70
- end
71
-
72
- def sequel_each_hash(with_table = nil)
73
- c = columns
74
- while row = fetch_row
75
- h = {}
76
- c.each_with_index {|f, i| h[f] = convert_type(row[i], @column_types[i])}
77
- yield h
78
- end
79
- end
80
-
81
- end
82
-
83
- module Sequel
84
- module MySQL
85
- class Database < Sequel::Database
86
- set_adapter_scheme :mysql
87
-
88
- def server_version
89
- @server_version ||= pool.hold do |conn|
90
- if conn.respond_to?(:server_version)
91
- pool.hold {|c| c.server_version}
92
- else
93
- m = /(\d+)\.(\d+)\.(\d+)/.match(get(:version[]))
94
- (m[1].to_i * 10000) + (m[2].to_i * 100) + m[3].to_i
95
- end
96
- end
97
- end
98
-
99
- def serial_primary_key_options
100
- {:primary_key => true, :type => :integer, :auto_increment => true}
101
- end
102
-
103
- AUTO_INCREMENT = 'AUTO_INCREMENT'.freeze
104
-
105
- def auto_increment_sql
106
- AUTO_INCREMENT
107
- end
108
-
109
- def connect
110
- conn = Mysql.init
111
- conn.options(Mysql::OPT_LOCAL_INFILE, "client")
112
- conn.real_connect(
113
- @opts[:host] || 'localhost',
114
- @opts[:user],
115
- @opts[:password],
116
- @opts[:database],
117
- @opts[:port],
118
- @opts[:socket],
119
- Mysql::CLIENT_MULTI_RESULTS +
120
- Mysql::CLIENT_MULTI_STATEMENTS +
121
- Mysql::CLIENT_COMPRESS
122
- )
123
- conn.query_with_result = false
124
- if encoding = @opts[:encoding] || @opts[:charset]
125
- conn.query("set character_set_connection = '#{encoding}'")
126
- conn.query("set character_set_client = '#{encoding}'")
127
- conn.query("set character_set_database = '#{encoding}'")
128
- conn.query("set character_set_server = '#{encoding}'")
129
- conn.query("set character_set_results = '#{encoding}'")
130
- end
131
- conn.reconnect = true
132
- conn
133
- end
134
-
135
- def disconnect
136
- @pool.disconnect {|c| c.close}
137
- end
138
-
139
- def tables
140
- @pool.hold do |conn|
141
- conn.list_tables.map {|t| t.to_sym}
142
- end
143
- end
144
-
145
- def dataset(opts = nil)
146
- MySQL::Dataset.new(self, opts)
147
- end
148
-
149
- def execute(sql, &block)
150
- begin
151
- log_info(sql)
152
- @pool.hold do |conn|
153
- conn.query(sql)
154
- block[conn] if block
155
- end
156
- rescue Mysql::Error => e
157
- raise Error.new(e.message)
158
- end
159
- end
160
-
161
- def execute_select(sql, &block)
162
- execute(sql) do |c|
163
- r = c.use_result
164
- begin
165
- block[r]
166
- ensure
167
- r.free
168
- end
169
- end
170
- end
171
-
172
- def alter_table_sql(table, op)
173
- type = type_literal(op[:type])
174
- type << '(255)' if type == 'varchar'
175
- case op[:op]
176
- when :rename_column
177
- "ALTER TABLE #{table} CHANGE COLUMN #{literal(op[:name])} #{literal(op[:new_name])} #{type}"
178
- when :set_column_type
179
- "ALTER TABLE #{table} CHANGE COLUMN #{literal(op[:name])} #{literal(op[:name])} #{type}"
180
- when :drop_index
181
- "DROP INDEX #{default_index_name(table, op[:columns])} ON #{table}"
182
- else
183
- super(table, op)
184
- end
185
- end
186
-
187
- def column_definition_sql(column)
188
- if column[:type] == :check
189
- return constraint_definition_sql(column)
190
- end
191
- sql = "#{literal(column[:name].to_sym)} #{TYPES[column[:type]]}"
192
- column[:size] ||= 255 if column[:type] == :varchar
193
- elements = column[:size] || column[:elements]
194
- sql << literal(Array(elements)) if elements
195
- sql << UNSIGNED if column[:unsigned]
196
- sql << UNIQUE if column[:unique]
197
- sql << NOT_NULL if column[:null] == false
198
- sql << NULL if column[:null] == true
199
- sql << " DEFAULT #{literal(column[:default])}" if column.include?(:default)
200
- sql << PRIMARY_KEY if column[:primary_key]
201
- sql << " #{auto_increment_sql}" if column[:auto_increment]
202
- if column[:table]
203
- sql << ", FOREIGN KEY (#{literal(column[:name].to_sym)}) REFERENCES #{column[:table]}"
204
- sql << literal(Array(column[:key])) if column[:key]
205
- sql << " ON DELETE #{on_delete_clause(column[:on_delete])}" if column[:on_delete]
206
- end
207
- sql
208
- end
209
-
210
- def index_definition_sql(table_name, index)
211
- index_name = index[:name] || default_index_name(table_name, index[:columns])
212
- unique = "UNIQUE " if index[:unique]
213
- case index[:type]
214
- when :full_text
215
- "CREATE FULLTEXT INDEX #{index_name} ON #{table_name} #{literal(index[:columns])}"
216
- when :spatial
217
- "CREATE SPATIAL INDEX #{index_name} ON #{table_name} #{literal(index[:columns])}"
218
- when nil
219
- "CREATE #{unique}INDEX #{index_name} ON #{table_name} #{literal(index[:columns])}"
220
- else
221
- "CREATE #{unique}INDEX #{index_name} ON #{table_name} #{literal(index[:columns])} USING #{index[:type]}"
222
- end
223
- end
224
-
225
- def transaction
226
- @pool.hold do |conn|
227
- @transactions ||= []
228
- if @transactions.include? Thread.current
229
- return yield(conn)
230
- end
231
- log_info(SQL_BEGIN)
232
- conn.query(SQL_BEGIN)
233
- begin
234
- @transactions << Thread.current
235
- yield(conn)
236
- rescue ::Exception => e
237
- log_info(SQL_ROLLBACK)
238
- conn.query(SQL_ROLLBACK)
239
- raise (Mysql::Error === e ? Error.new(e.message) : e) unless Error::Rollback === e
240
- ensure
241
- unless e
242
- log_info(SQL_COMMIT)
243
- conn.query(SQL_COMMIT)
244
- end
245
- @transactions.delete(Thread.current)
246
- end
247
- end
248
- end
249
-
250
- # Changes the database in use by issuing a USE statement.
251
- def use(db_name)
252
- disconnect
253
- @opts[:database] = db_name if self << "USE #{db_name}"
254
- @schemas = nil
255
- self
256
- end
257
-
258
- private
259
- def connection_pool_default_options
260
- super.merge(:pool_convert_exceptions=>false)
261
- end
262
-
263
- def schema_ds_dataset
264
- ds = schema_utility_dataset.clone
265
- ds.quote_identifiers = true
266
- ds
267
- end
268
-
269
- def schema_ds_filter(table_name, opts)
270
- filt = super
271
- # Restrict it to the given or current database, unless specifically requesting :database = nil
272
- filt = SQL::BooleanExpression.new(:AND, filt, {:c__table_schema=>opts[:database] || self.opts[:database]}) if opts[:database] || !opts.include?(:database)
273
- filt
274
- end
275
-
276
- def schema_ds_join(table_name, opts)
277
- [:information_schema__columns, {:table_schema => :table_schema, :table_name => :table_name}, :c]
278
- end
279
- end
280
-
281
- class Dataset < Sequel::Dataset
282
- def quoted_identifier(c)
283
- "`#{c}`"
284
- end
285
-
286
- TRUE = '1'
287
- FALSE = '0'
288
-
289
- def literal(v)
290
- case v
291
- when LiteralString
292
- v
293
- when String
294
- "'#{::Mysql.quote(v)}'"
295
- when true
296
- TRUE
297
- when false
298
- FALSE
299
- else
300
- super
301
- end
302
- end
303
-
304
- # Returns a join clause based on the specified join type
305
- # and condition. MySQL's NATURAL join is 'semantically
306
- # equivalent to a JOIN with a USING clause that names all
307
- # columns that exist in both tables. The constraint
308
- # expression may be nil, so join expression can accept two
309
- # arguments.
310
- #
311
- # === Note
312
- # Full outer joins (:full_outer) are not implemented in
313
- # MySQL (as of v6.0), nor is there currently a work around
314
- # implementation in Sequel. Straight joins with 'ON
315
- # <condition>' are not yet implemented.
316
- #
317
- # === Example
318
- # @ds = MYSQL_DB[:nodes]
319
- # @ds.join_table(:natural_left_outer, :nodes)
320
- # # join SQL is 'NATURAL LEFT OUTER JOIN nodes'
321
- def join_table(type, table, expr=nil, table_alias=nil)
322
- type = :inner if (type == :cross) && !expr.nil?
323
- raise(Sequel::Error::InvalidJoinType, "MySQL doesn't support FULL OUTER JOIN") if type == :full_outer
324
- super(type, table, expr, table_alias)
325
- end
326
-
327
-
328
- def join_type_sql(join_type)
329
- case join_type
330
- when :straight then 'STRAIGHT_JOIN'
331
- when :natural_inner then 'NATURAL LEFT JOIN'
332
- else super
333
- end
334
- end
335
-
336
- def insert_default_values_sql
337
- "INSERT INTO #{source_list(@opts[:from])} () VALUES ()"
338
- end
339
-
340
- def complex_expression_sql(op, args)
341
- case op
342
- when :~, :'!~', :'~*', :'!~*', :LIKE, :'NOT LIKE', :ILIKE, :'NOT ILIKE'
343
- "(#{literal(args.at(0))} #{'NOT ' if [:'NOT LIKE', :'NOT ILIKE', :'!~', :'!~*'].include?(op)}#{[:~, :'!~', :'~*', :'!~*'].include?(op) ? 'REGEXP' : 'LIKE'} #{'BINARY ' if [:~, :'!~', :LIKE, :'NOT LIKE'].include?(op)}#{literal(args.at(1))})"
344
- when :'||'
345
- if args.length > 1
346
- "CONCAT(#{args.collect{|a| literal(a)}.join(', ')})"
347
- else
348
- literal(args.at(0))
349
- end
350
- else
351
- super(op, args)
352
- end
353
- end
354
-
355
- def match_expr(l, r)
356
- case r
357
- when Regexp
358
- r.casefold? ? \
359
- "(#{literal(l)} REGEXP #{literal(r.source)})" :
360
- "(#{literal(l)} REGEXP BINARY #{literal(r.source)})"
361
- else
362
- super
363
- end
364
- end
365
-
366
- def full_text_search(cols, terms, opts = {})
367
- mode = opts[:boolean] ? " IN BOOLEAN MODE" : ""
368
- s = if Array === terms
369
- if mode.blank?
370
- "MATCH #{literal(Array(cols))} AGAINST #{literal(terms)}"
371
- else
372
- "MATCH #{literal(Array(cols))} AGAINST (#{literal(terms)[1...-1]}#{mode})"
373
- end
374
- else
375
- "MATCH #{literal(Array(cols))} AGAINST (#{literal(terms)}#{mode})"
376
- end
377
- filter(s)
378
- end
379
-
380
- # MySQL allows HAVING clause on ungrouped datasets.
381
- def having(*cond, &block)
382
- @opts[:having] = {}
383
- x = filter(*cond, &block)
384
- end
385
-
386
- # MySQL supports ORDER and LIMIT clauses in UPDATE statements.
387
- def update_sql(values, opts = nil, &block)
388
- sql = super
389
- opts = opts ? @opts.merge(opts) : @opts
390
-
391
- if order = opts[:order]
392
- sql << " ORDER BY #{expression_list(order)}"
393
- end
394
- if limit = opts[:limit]
395
- sql << " LIMIT #{limit}"
396
- end
397
-
398
- sql
399
- end
400
-
401
- def replace_sql(*values)
402
- from = source_list(@opts[:from])
403
- if values.empty?
404
- "REPLACE INTO #{from} DEFAULT VALUES"
405
- else
406
- values = values[0] if values.size == 1
407
-
408
- # if hash or array with keys we need to transform the values
409
- if @transform && (values.is_a?(Hash) || (values.is_a?(Array) && values.keys))
410
- values = transform_save(values)
411
- end
412
-
413
- case values
414
- when Array
415
- if values.empty?
416
- "REPLACE INTO #{from} DEFAULT VALUES"
417
- else
418
- "REPLACE INTO #{from} VALUES #{literal(values)}"
419
- end
420
- when Hash
421
- if values.empty?
422
- "REPLACE INTO #{from} DEFAULT VALUES"
423
- else
424
- fl, vl = [], []
425
- values.each {|k, v| fl << literal(k.is_a?(String) ? k.to_sym : k); vl << literal(v)}
426
- "REPLACE INTO #{from} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
427
- end
428
- when Dataset
429
- "REPLACE INTO #{from} #{literal(values)}"
430
- else
431
- if values.respond_to?(:values)
432
- replace_sql(values.values)
433
- else
434
- "REPLACE INTO #{from} VALUES (#{literal(values)})"
435
- end
436
- end
437
- end
438
- end
439
-
440
- # MySQL supports ORDER and LIMIT clauses in DELETE statements.
441
- def delete_sql(opts = nil)
442
- sql = super
443
- opts = opts ? @opts.merge(opts) : @opts
444
-
445
- if order = opts[:order]
446
- sql << " ORDER BY #{expression_list(order)}"
447
- end
448
- if limit = opts[:limit]
449
- sql << " LIMIT #{limit}"
450
- end
451
-
452
- sql
453
- end
454
-
455
- def insert(*values)
456
- @db.execute(insert_sql(*values)) {|c| c.insert_id}
457
- end
458
-
459
- def update(*args, &block)
460
- @db.execute(update_sql(*args, &block)) {|c| c.affected_rows}
461
- end
462
-
463
- def replace(*args)
464
- @db.execute(replace_sql(*args)) {|c| c.insert_id}
465
- end
466
-
467
- def delete(opts = nil)
468
- @db.execute(delete_sql(opts)) {|c| c.affected_rows}
469
- end
470
-
471
- def fetch_rows(sql)
472
- @db.execute_select(sql) do |r|
473
- @columns = r.columns
474
- r.sequel_each_hash {|row| yield row}
475
- end
476
- self
477
- end
478
-
479
- def multi_insert_sql(columns, values)
480
- columns = column_list(columns)
481
- values = values.map {|r| literal(Array(r))}.join(COMMA_SEPARATOR)
482
- ["INSERT INTO #{source_list(@opts[:from])} (#{columns}) VALUES #{values}"]
483
- end
484
- end
485
- end
486
- end