sequel 2.10.0 → 2.11.0

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.
Files changed (78) hide show
  1. data/CHANGELOG +51 -1
  2. data/README.rdoc +2 -2
  3. data/Rakefile +2 -2
  4. data/doc/advanced_associations.rdoc +6 -18
  5. data/doc/release_notes/1.0.txt +38 -0
  6. data/doc/release_notes/1.1.txt +143 -0
  7. data/doc/release_notes/1.3.txt +101 -0
  8. data/doc/release_notes/1.4.0.txt +53 -0
  9. data/doc/release_notes/1.5.0.txt +155 -0
  10. data/doc/release_notes/2.0.0.txt +298 -0
  11. data/doc/release_notes/2.1.0.txt +271 -0
  12. data/doc/release_notes/2.10.0.txt +328 -0
  13. data/doc/release_notes/2.11.0.txt +215 -0
  14. data/doc/release_notes/2.2.0.txt +253 -0
  15. data/doc/release_notes/2.3.0.txt +88 -0
  16. data/doc/release_notes/2.4.0.txt +106 -0
  17. data/doc/release_notes/2.5.0.txt +137 -0
  18. data/doc/release_notes/2.6.0.txt +157 -0
  19. data/doc/release_notes/2.7.0.txt +166 -0
  20. data/doc/release_notes/2.8.0.txt +171 -0
  21. data/doc/release_notes/2.9.0.txt +97 -0
  22. data/lib/sequel_core/adapters/ado.rb +3 -0
  23. data/lib/sequel_core/adapters/db2.rb +0 -11
  24. data/lib/sequel_core/adapters/dbi.rb +0 -11
  25. data/lib/sequel_core/adapters/do.rb +0 -12
  26. data/lib/sequel_core/adapters/firebird.rb +21 -16
  27. data/lib/sequel_core/adapters/informix.rb +1 -11
  28. data/lib/sequel_core/adapters/jdbc.rb +1 -13
  29. data/lib/sequel_core/adapters/jdbc/h2.rb +3 -11
  30. data/lib/sequel_core/adapters/jdbc/mysql.rb +0 -17
  31. data/lib/sequel_core/adapters/jdbc/postgresql.rb +3 -15
  32. data/lib/sequel_core/adapters/mysql.rb +31 -27
  33. data/lib/sequel_core/adapters/odbc.rb +34 -28
  34. data/lib/sequel_core/adapters/openbase.rb +0 -11
  35. data/lib/sequel_core/adapters/oracle.rb +11 -9
  36. data/lib/sequel_core/adapters/postgres.rb +14 -17
  37. data/lib/sequel_core/adapters/shared/mssql.rb +6 -15
  38. data/lib/sequel_core/adapters/shared/mysql.rb +29 -14
  39. data/lib/sequel_core/adapters/shared/oracle.rb +4 -0
  40. data/lib/sequel_core/adapters/shared/postgres.rb +30 -35
  41. data/lib/sequel_core/adapters/shared/progress.rb +4 -0
  42. data/lib/sequel_core/adapters/shared/sqlite.rb +73 -13
  43. data/lib/sequel_core/adapters/sqlite.rb +8 -18
  44. data/lib/sequel_core/adapters/utils/date_format.rb +21 -0
  45. data/lib/sequel_core/{dataset → adapters/utils}/stored_procedures.rb +0 -0
  46. data/lib/sequel_core/{dataset → adapters/utils}/unsupported.rb +0 -0
  47. data/lib/sequel_core/core_ext.rb +1 -1
  48. data/lib/sequel_core/core_sql.rb +9 -4
  49. data/lib/sequel_core/database.rb +63 -62
  50. data/lib/sequel_core/dataset.rb +9 -4
  51. data/lib/sequel_core/dataset/convenience.rb +10 -9
  52. data/lib/sequel_core/dataset/prepared_statements.rb +1 -1
  53. data/lib/sequel_core/dataset/sql.rb +130 -36
  54. data/lib/sequel_core/schema/sql.rb +2 -2
  55. data/lib/sequel_core/sql.rb +44 -51
  56. data/lib/sequel_core/version.rb +1 -1
  57. data/lib/sequel_model/associations.rb +25 -17
  58. data/lib/sequel_model/base.rb +35 -7
  59. data/lib/sequel_model/caching.rb +1 -6
  60. data/lib/sequel_model/record.rb +23 -5
  61. data/lib/sequel_model/validations.rb +20 -5
  62. data/spec/adapters/firebird_spec.rb +6 -1
  63. data/spec/adapters/mysql_spec.rb +12 -0
  64. data/spec/adapters/postgres_spec.rb +2 -2
  65. data/spec/adapters/sqlite_spec.rb +81 -2
  66. data/spec/integration/dataset_test.rb +2 -2
  67. data/spec/integration/type_test.rb +12 -2
  68. data/spec/sequel_core/core_sql_spec.rb +46 -12
  69. data/spec/sequel_core/database_spec.rb +24 -12
  70. data/spec/sequel_core/dataset_spec.rb +82 -32
  71. data/spec/sequel_core/schema_spec.rb +16 -0
  72. data/spec/sequel_model/associations_spec.rb +89 -0
  73. data/spec/sequel_model/base_spec.rb +66 -0
  74. data/spec/sequel_model/eager_loading_spec.rb +32 -0
  75. data/spec/sequel_model/record_spec.rb +9 -9
  76. data/spec/sequel_model/spec_helper.rb +3 -0
  77. data/spec/sequel_model/validations_spec.rb +63 -3
  78. metadata +41 -4
@@ -37,17 +37,6 @@ module Sequel
37
37
  end
38
38
 
39
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
40
  def fetch_rows(sql)
52
41
  execute(sql) do |result|
53
42
  begin
@@ -78,15 +78,6 @@ module Sequel
78
78
  class Dataset < Sequel::Dataset
79
79
  include DatasetMethods
80
80
 
81
- def literal(v)
82
- case v
83
- when OraDate
84
- literal(Time.local(*v.to_a))
85
- else
86
- super
87
- end
88
- end
89
-
90
81
  def fetch_rows(sql, &block)
91
82
  execute(sql) do |cursor|
92
83
  begin
@@ -102,6 +93,17 @@ module Sequel
102
93
  end
103
94
  self
104
95
  end
96
+
97
+ private
98
+
99
+ def literal_other(v)
100
+ case v
101
+ when OraDate
102
+ literal_time(Time.local(*v.to_a))
103
+ else
104
+ super
105
+ end
106
+ end
105
107
  end
106
108
  end
107
109
  end
@@ -85,7 +85,7 @@ module Sequel
85
85
  # Hash with integer keys and proc values for converting PostgreSQL types.
86
86
  PG_TYPES = {
87
87
  16 => lambda{ |s| s == 't' }, # boolean
88
- 17 => lambda{ |s| Adapter.unescape_bytea(s).to_blob }, # bytea
88
+ 17 => lambda{ |s| ::Sequel::SQL::Blob.new(Adapter.unescape_bytea(s)) }, # bytea
89
89
  20 => lambda{ |s| s.to_i }, # int8
90
90
  21 => lambda{ |s| s.to_i }, # int2
91
91
  22 => lambda{ |s| s.to_i }, # int2vector
@@ -326,23 +326,9 @@ module Sequel
326
326
  end
327
327
  end
328
328
 
329
- # Literalize strings and blobs using code from the native adapter.
330
- def literal(v)
331
- case v
332
- when LiteralString
333
- v
334
- when SQL::Blob
335
- db.synchronize{|c| "'#{c.escape_bytea(v)}'"}
336
- when String
337
- db.synchronize{|c| "'#{c.escape_string(v)}'"}
338
- else
339
- super
340
- end
341
- end
342
-
343
329
  if SEQUEL_POSTGRES_USES_PG
344
330
 
345
- PREPARED_ARG_PLACEHOLDER = '$'.lit.freeze
331
+ PREPARED_ARG_PLACEHOLDER = LiteralString.new('$').freeze
346
332
 
347
333
  # PostgreSQL specific argument mapper used for mapping the named
348
334
  # argument hash to a array with numbered arguments. Only used with
@@ -373,7 +359,7 @@ module Sequel
373
359
  @prepared_args << y
374
360
  i = @prepared_args.length
375
361
  end
376
- "#{prepared_arg_placeholder}#{i}#{"::#{type}" if type}".lit
362
+ LiteralString.new("#{prepared_arg_placeholder}#{i}#{"::#{type}" if type}")
377
363
  end
378
364
  end
379
365
 
@@ -451,6 +437,17 @@ module Sequel
451
437
  PREPARED_ARG_PLACEHOLDER
452
438
  end
453
439
  end
440
+
441
+ private
442
+
443
+ def literal_blob(v)
444
+ db.synchronize{|c| "'#{c.escape_bytea(v)}'"}
445
+ end
446
+
447
+ def literal_string(v)
448
+ db.synchronize{|c| "'#{c.escape_string(v)}'"}
449
+ end
450
+
454
451
  end
455
452
  end
456
453
  end
@@ -1,3 +1,5 @@
1
+ require 'sequel_core/adapters/utils/unsupported'
2
+
1
3
  module Sequel
2
4
  module MSSQL
3
5
  module DatabaseMethods
@@ -52,21 +54,6 @@ module Sequel
52
54
  filter("CONTAINS (#{literal(cols)}, #{literal(terms)})")
53
55
  end
54
56
 
55
- def literal(v)
56
- case v
57
- when LiteralString
58
- v
59
- when String
60
- "N#{super}"
61
- when Time
62
- literal(v.iso8601)
63
- when Date, DateTime
64
- literal(v.to_s)
65
- else
66
- super
67
- end
68
- end
69
-
70
57
  def multi_insert_sql(columns, values)
71
58
  values = values.map {|r| "SELECT #{expression_list(r)}" }.join(" UNION ALL ")
72
59
  ["INSERT INTO #{source_list(@opts[:from])} (#{identifier_list(columns)}) #{values}"]
@@ -83,6 +70,10 @@ module Sequel
83
70
 
84
71
  private
85
72
 
73
+ def literal_string(v)
74
+ "N#{super}"
75
+ end
76
+
86
77
  def select_clause_order
87
78
  SELECT_CLAUSE_ORDER
88
79
  end
@@ -1,3 +1,5 @@
1
+ require 'sequel_core/adapters/utils/unsupported'
2
+
1
3
  module Sequel
2
4
  module Schema
3
5
  module SQL
@@ -146,8 +148,15 @@ module Sequel
146
148
 
147
149
  BOOL_TRUE = '1'.freeze
148
150
  BOOL_FALSE = '0'.freeze
151
+ CAST_TYPES = {String=>:CHAR, Integer=>:SIGNED, Time=>:DATETIME, DateTime=>:DATETIME, Numeric=>:DECIMAL, BigDecimal=>:DECIMAL, File=>:BINARY}
152
+ TIMESTAMP_FORMAT = "'%Y-%m-%d %H:%M:%S'".freeze
149
153
  COMMA_SEPARATOR = ', '.freeze
150
154
 
155
+ # MySQL can't use the varchar type in a cast.
156
+ def cast_sql(expr, type)
157
+ "CAST(#{literal(expr)} AS #{CAST_TYPES[type] || db.send(:type_literal_base, :type=>type)})"
158
+ end
159
+
151
160
  # MySQL specific syntax for LIKE/REGEXP searches, as well as
152
161
  # string concatenation.
153
162
  def complex_expression_sql(op, args)
@@ -224,20 +233,6 @@ module Sequel
224
233
  end
225
234
  end
226
235
 
227
- # Override the default boolean values.
228
- def literal(v)
229
- case v
230
- when true
231
- BOOL_TRUE
232
- when false
233
- BOOL_FALSE
234
- when DateTime, Time
235
- v.strftime("'%Y-%m-%d %H:%M:%S'")
236
- else
237
- super
238
- end
239
- end
240
-
241
236
  # MySQL specific syntax for inserting multiple values at once.
242
237
  def multi_insert_sql(columns, values)
243
238
  values = values.map {|r| literal(Array(r))}.join(COMMA_SEPARATOR)
@@ -307,6 +302,26 @@ module Sequel
307
302
 
308
303
  private
309
304
 
305
+ # Use MySQL Timestamp format
306
+ def literal_datetime(v)
307
+ v.strftime(TIMESTAMP_FORMAT)
308
+ end
309
+
310
+ # Use 0 for false on MySQL
311
+ def literal_false
312
+ BOOL_FALSE
313
+ end
314
+
315
+ # Use MySQL Timestamp format
316
+ def literal_time(v)
317
+ v.strftime(TIMESTAMP_FORMAT)
318
+ end
319
+
320
+ # Use 1 for true on MySQL
321
+ def literal_true
322
+ BOOL_TRUE
323
+ end
324
+
310
325
  # MySQL doesn't support DISTINCT ON
311
326
  def select_distinct_sql(sql, opts)
312
327
  if opts[:distinct]
@@ -1,3 +1,6 @@
1
+ require 'sequel_core/adapters/utils/date_format'
2
+ require 'sequel_core/adapters/utils/unsupported'
3
+
1
4
  module Sequel
2
5
  module Oracle
3
6
  module DatabaseMethods
@@ -13,6 +16,7 @@ module Sequel
13
16
 
14
17
  module DatasetMethods
15
18
  include Dataset::UnsupportedIntersectExceptAll
19
+ include Dataset::SQLStandardDateFormat
16
20
 
17
21
  SELECT_CLAUSE_ORDER = %w'distinct columns from join where group having compounds order limit'.freeze
18
22
 
@@ -161,7 +161,7 @@ module Sequel
161
161
 
162
162
  # Methods shared by Database instances that connect to PostgreSQL.
163
163
  module DatabaseMethods
164
- PREPARED_ARG_PLACEHOLDER = '$'.lit.freeze
164
+ PREPARED_ARG_PLACEHOLDER = LiteralString.new('$').freeze
165
165
  RE_CURRVAL_ERROR = /currval of sequence "(.*)" is not yet defined in this session|relation "(.*)" does not exist/.freeze
166
166
  SQL_BEGIN = 'BEGIN'.freeze
167
167
  SQL_SAVEPOINT = 'SAVEPOINT autopoint_%d'.freeze
@@ -333,9 +333,7 @@ module Sequel
333
333
 
334
334
  # Dataset containing all current database locks
335
335
  def locks
336
- dataset.from(:pg_class, :pg_locks).
337
- select(:pg_class__relname, :pg_locks.*).
338
- filter(:pg_class__relfilenode=>:pg_locks__relation)
336
+ dataset.from(:pg_class).join(:pg_locks, :relation=>:relfilenode).select(:pg_class__relname, Sequel::SQL::ColumnAll.new(:pg_locks))
339
337
  end
340
338
 
341
339
  # Return primary key for the given table.
@@ -552,6 +550,7 @@ module Sequel
552
550
  FOR_SHARE = ' FOR SHARE'.freeze
553
551
  FOR_UPDATE = ' FOR UPDATE'.freeze
554
552
  LOCK = 'LOCK TABLE %s IN %s MODE'.freeze
553
+ NULL = LiteralString.new('NULL').freeze
555
554
  PG_TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S".freeze
556
555
  QUERY_PLAN = 'QUERY PLAN'.to_sym
557
556
  ROW_EXCLUSIVE = 'ROW EXCLUSIVE'.freeze
@@ -614,7 +613,7 @@ module Sequel
614
613
  # Insert given values into the database.
615
614
  def insert(*values)
616
615
  if !@opts[:sql] and server_version >= 80200
617
- single_value(:sql=>insert_returning_pk_sql(*values))
616
+ single_value(default_server_opts(:sql=>insert_returning_pk_sql(*values)))
618
617
  else
619
618
  execute_insert(insert_sql(*values), :table=>opts[:from].first,
620
619
  :values=>values.size == 1 ? values.first : values)
@@ -628,32 +627,9 @@ module Sequel
628
627
 
629
628
  # Insert a record returning the record inserted
630
629
  def insert_select(*values)
631
- single_record(:naked=>true, :sql=>insert_returning_sql(nil, *values)) if server_version >= 80200
630
+ single_record(default_server_opts(:naked=>true, :sql=>insert_returning_sql(nil, *values))) if server_version >= 80200
632
631
  end
633
632
 
634
- # Handle microseconds for Time and DateTime values, as well as PostgreSQL
635
- # specific boolean values and string escaping.
636
- def literal(v)
637
- case v
638
- when LiteralString
639
- v
640
- when SQL::Blob
641
- "'#{v.gsub(/[\000-\037\047\134\177-\377]/){|b| "\\#{("%o" % b[0..1].unpack("C")[0]).rjust(3, '0')}"}}'"
642
- when String
643
- "'#{v.gsub("'", "''")}'"
644
- when Time
645
- "#{v.strftime(PG_TIMESTAMP_FORMAT)}.#{sprintf("%06d",v.usec)}'"
646
- when DateTime
647
- "#{v.strftime(PG_TIMESTAMP_FORMAT)}.#{sprintf("%06d", (v.sec_fraction * 86400000000).to_i)}'"
648
- when TrueClass
649
- BOOL_TRUE
650
- when FalseClass
651
- BOOL_FALSE
652
- else
653
- super
654
- end
655
- end
656
-
657
633
  # Locks the table with the specified mode.
658
634
  def lock(mode, server=nil)
659
635
  sql = LOCK % [source_list(@opts[:from]), mode]
@@ -678,17 +654,36 @@ module Sequel
678
654
 
679
655
  private
680
656
 
681
- # Call execute_insert on the database object with the given values.
682
- def execute_insert(sql, opts={})
683
- @db.execute_insert(sql, {:server=>@opts[:server] || :default}.merge(opts))
684
- end
685
-
686
657
  # Use the RETURNING clause to return the primary key of the inserted record, if it exists
687
658
  def insert_returning_pk_sql(*values)
688
659
  pk = db.primary_key(opts[:from].first)
689
- insert_returning_sql(pk ? Sequel::SQL::Identifier.new(pk) : 'NULL'.lit, *values)
660
+ insert_returning_sql(pk ? Sequel::SQL::Identifier.new(pk) : NULL, *values)
690
661
  end
691
662
 
663
+ def literal_blob(v)
664
+ "'#{v.gsub(/[\000-\037\047\134\177-\377]/){|b| "\\#{("%o" % b[0..1].unpack("C")[0]).rjust(3, '0')}"}}'"
665
+ end
666
+
667
+ def literal_datetime(v)
668
+ "#{v.strftime(PG_TIMESTAMP_FORMAT)}.#{sprintf("%06d", (v.sec_fraction * 86400000000).to_i)}'"
669
+ end
670
+
671
+ def literal_false
672
+ BOOL_FALSE
673
+ end
674
+
675
+ def literal_string(v)
676
+ "'#{v.gsub("'", "''")}'"
677
+ end
678
+
679
+ def literal_true
680
+ BOOL_TRUE
681
+ end
682
+
683
+ def literal_time(v)
684
+ "#{v.strftime(PG_TIMESTAMP_FORMAT)}.#{sprintf("%06d",v.usec)}'"
685
+ end
686
+
692
687
  # PostgreSQL is smart and can use parantheses around all datasets to get
693
688
  # the correct answers.
694
689
  def select_compounds_sql(sql, opts)
@@ -1,3 +1,6 @@
1
+ require 'sequel_core/adapters/utils/date_format'
2
+ require 'sequel_core/adapters/utils/unsupported'
3
+
1
4
  module Sequel
2
5
  module Progress
3
6
  module DatabaseMethods
@@ -11,6 +14,7 @@ module Sequel
11
14
 
12
15
  module DatasetMethods
13
16
  include Dataset::UnsupportedIntersectExcept
17
+ include Dataset::SQLStandardDateFormat
14
18
 
15
19
  SELECT_CLAUSE_ORDER = %w'limit distinct columns from join where group order having compounds'.freeze
16
20
 
@@ -1,3 +1,5 @@
1
+ require 'sequel_core/adapters/utils/unsupported'
2
+
1
3
  module Sequel
2
4
  module SQLite
3
5
  module DatabaseMethods
@@ -22,14 +24,45 @@ module Sequel
22
24
  when :add_column, :add_index, :drop_index
23
25
  super
24
26
  when :drop_column
25
- columns_str = (schema_parse_table(table, {}).map{|c| c[0]} - Array(op[:name])).join(",")
26
- defined_columns_str = column_list_sql parse_pragma(table, {}).reject{ |c| c[:name] == op[:name].to_s}
27
- ["CREATE TEMPORARY TABLE #{table}_backup(#{defined_columns_str})",
28
- "INSERT INTO #{table}_backup SELECT #{columns_str} FROM #{table}",
29
- "DROP TABLE #{table}",
30
- "CREATE TABLE #{table}(#{defined_columns_str})",
31
- "INSERT INTO #{table} SELECT #{columns_str} FROM #{table}_backup",
32
- "DROP TABLE #{table}_backup"]
27
+ qt = quote_schema_table(table)
28
+ bt = quote_identifier(backup_table_name(qt.gsub('`', '')))
29
+ columns_str = dataset.send(:identifier_list, columns_for(table, :except => op[:name]))
30
+ defined_columns_str = column_list_sql(defined_columns_for(table, :except => op[:name]))
31
+ ["CREATE TEMPORARY TABLE #{bt}(#{defined_columns_str})",
32
+ "INSERT INTO #{bt} SELECT #{columns_str} FROM #{qt}",
33
+ "DROP TABLE #{qt}",
34
+ "CREATE TABLE #{qt}(#{defined_columns_str})",
35
+ "INSERT INTO #{qt} SELECT #{columns_str} FROM #{bt}",
36
+ "DROP TABLE #{bt}"]
37
+ when :rename_column
38
+ qt = quote_schema_table(table)
39
+ bt = quote_identifier(backup_table_name(qt.gsub('`', '')))
40
+ old_columns = dataset.send(:identifier_list, columns_for(table))
41
+ new_columns_arr = columns_for(table)
42
+
43
+ # Replace the old column in place. This is extremely important.
44
+ new_columns_arr[new_columns_arr.index(op[:name])] = op[:new_name]
45
+
46
+ new_columns = dataset.send(:identifier_list, new_columns_arr)
47
+
48
+ def_old_columns = column_list_sql(defined_columns_for(table))
49
+
50
+ def_new_columns_arr = defined_columns_for(table).map do |c|
51
+ c[:name] = op[:new_name].to_s if c[:name] == op[:name].to_s
52
+ c
53
+ end
54
+
55
+ def_new_columns = column_list_sql(def_new_columns_arr)
56
+
57
+ [
58
+ "CREATE TEMPORARY TABLE #{bt}(#{def_old_columns})",
59
+ "INSERT INTO #{bt}(#{old_columns}) SELECT #{old_columns} FROM #{qt}",
60
+ "DROP TABLE #{qt}",
61
+ "CREATE TABLE #{qt}(#{def_new_columns})",
62
+ "INSERT INTO #{qt}(#{new_columns}) SELECT #{old_columns} FROM #{bt}",
63
+ "DROP TABLE #{bt}"
64
+ ]
65
+
33
66
  else
34
67
  raise Error, "Unsupported ALTER TABLE operation"
35
68
  end
@@ -92,6 +125,32 @@ module Sequel
92
125
  end
93
126
 
94
127
  private
128
+
129
+ # The array of column symbols in the table, except for ones given in opts[:except]
130
+ def backup_table_name(table, opts={})
131
+ (opts[:times]||1000).times do |i|
132
+ table_name = "#{table}_backup#{i}"
133
+ return table_name unless table_exists?(table_name)
134
+ end
135
+ end
136
+
137
+ # The array of column symbols in the table, except for ones given in opts[:except]
138
+ def columns_for(table, opts={})
139
+ cols = schema_parse_table(table, {}).map{|c| c[0]}
140
+ cols = cols - Array(opts[:except])
141
+ cols
142
+ end
143
+
144
+ # The array of column schema hashes, except for the ones given in opts[:except]
145
+ def defined_columns_for(table, opts={})
146
+ cols = parse_pragma(table, {})
147
+ cols.each{|c| c[:default] = LiteralString.new(c[:default]) if c[:default]}
148
+ if opts[:except]
149
+ nono= Array(opts[:except]).compact.map{|n| n.to_s}
150
+ cols.reject!{|c| nono.include? c[:name] }
151
+ end
152
+ cols
153
+ end
95
154
 
96
155
  # SQLite folds unquoted identifiers to lowercase, so it shouldn't need to upcase identifiers on input.
97
156
  def identifier_input_method_default
@@ -183,16 +242,17 @@ module Sequel
183
242
  end
184
243
 
185
244
  private
245
+
246
+ def literal_blob(v)
247
+ blob = ''
248
+ v.each_byte{|x| blob << sprintf('%02x', x)}
249
+ "X'#{blob}'"
250
+ end
186
251
 
187
252
  # SQLite uses string literals instead of identifiers in AS clauses.
188
253
  def as_sql(expression, aliaz)
189
254
  "#{expression} AS #{literal(aliaz.to_s)}"
190
255
  end
191
-
192
- # Call execute_insert on the database with the given SQL.
193
- def execute_insert(sql, opts={})
194
- @db.execute_insert(sql, {:server=>@opts[:server] || :default}.merge(opts))
195
- end
196
256
  end
197
257
  end
198
258
  end