sequel 3.37.0 → 3.38.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 (129) hide show
  1. data/CHANGELOG +56 -0
  2. data/README.rdoc +82 -58
  3. data/Rakefile +6 -5
  4. data/bin/sequel +1 -1
  5. data/doc/active_record.rdoc +67 -52
  6. data/doc/advanced_associations.rdoc +33 -48
  7. data/doc/association_basics.rdoc +41 -51
  8. data/doc/cheat_sheet.rdoc +21 -21
  9. data/doc/core_extensions.rdoc +374 -0
  10. data/doc/dataset_basics.rdoc +5 -5
  11. data/doc/dataset_filtering.rdoc +47 -43
  12. data/doc/mass_assignment.rdoc +1 -1
  13. data/doc/migration.rdoc +4 -5
  14. data/doc/model_hooks.rdoc +3 -3
  15. data/doc/object_model.rdoc +31 -25
  16. data/doc/opening_databases.rdoc +19 -5
  17. data/doc/prepared_statements.rdoc +2 -2
  18. data/doc/querying.rdoc +109 -52
  19. data/doc/reflection.rdoc +6 -6
  20. data/doc/release_notes/3.38.0.txt +234 -0
  21. data/doc/schema_modification.rdoc +22 -13
  22. data/doc/sharding.rdoc +8 -9
  23. data/doc/sql.rdoc +154 -112
  24. data/doc/testing.rdoc +47 -7
  25. data/doc/thread_safety.rdoc +1 -1
  26. data/doc/transactions.rdoc +1 -1
  27. data/doc/validations.rdoc +1 -1
  28. data/doc/virtual_rows.rdoc +29 -43
  29. data/lib/sequel/adapters/do/postgres.rb +1 -4
  30. data/lib/sequel/adapters/jdbc.rb +14 -3
  31. data/lib/sequel/adapters/jdbc/db2.rb +9 -0
  32. data/lib/sequel/adapters/jdbc/derby.rb +41 -4
  33. data/lib/sequel/adapters/jdbc/jtds.rb +11 -0
  34. data/lib/sequel/adapters/jdbc/postgresql.rb +3 -6
  35. data/lib/sequel/adapters/mock.rb +10 -4
  36. data/lib/sequel/adapters/postgres.rb +1 -28
  37. data/lib/sequel/adapters/shared/mssql.rb +23 -13
  38. data/lib/sequel/adapters/shared/postgres.rb +46 -0
  39. data/lib/sequel/adapters/swift.rb +21 -13
  40. data/lib/sequel/adapters/swift/mysql.rb +1 -0
  41. data/lib/sequel/adapters/swift/postgres.rb +4 -5
  42. data/lib/sequel/adapters/swift/sqlite.rb +2 -1
  43. data/lib/sequel/adapters/tinytds.rb +14 -2
  44. data/lib/sequel/adapters/utils/pg_types.rb +5 -0
  45. data/lib/sequel/core.rb +29 -17
  46. data/lib/sequel/database/query.rb +1 -1
  47. data/lib/sequel/database/schema_generator.rb +3 -0
  48. data/lib/sequel/dataset/actions.rb +5 -6
  49. data/lib/sequel/dataset/query.rb +7 -7
  50. data/lib/sequel/dataset/sql.rb +5 -18
  51. data/lib/sequel/extensions/core_extensions.rb +8 -12
  52. data/lib/sequel/extensions/pg_array.rb +59 -33
  53. data/lib/sequel/extensions/pg_array_ops.rb +32 -4
  54. data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -1
  55. data/lib/sequel/extensions/pg_hstore.rb +32 -17
  56. data/lib/sequel/extensions/pg_hstore_ops.rb +32 -3
  57. data/lib/sequel/extensions/pg_inet.rb +1 -2
  58. data/lib/sequel/extensions/pg_interval.rb +0 -1
  59. data/lib/sequel/extensions/pg_json.rb +41 -23
  60. data/lib/sequel/extensions/pg_range.rb +36 -11
  61. data/lib/sequel/extensions/pg_range_ops.rb +32 -4
  62. data/lib/sequel/extensions/pg_row.rb +572 -0
  63. data/lib/sequel/extensions/pg_row_ops.rb +164 -0
  64. data/lib/sequel/extensions/query.rb +3 -3
  65. data/lib/sequel/extensions/schema_dumper.rb +7 -8
  66. data/lib/sequel/extensions/select_remove.rb +1 -1
  67. data/lib/sequel/model/base.rb +1 -0
  68. data/lib/sequel/no_core_ext.rb +1 -1
  69. data/lib/sequel/plugins/pg_row.rb +121 -0
  70. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  71. data/lib/sequel/plugins/validation_helpers.rb +31 -0
  72. data/lib/sequel/sql.rb +64 -44
  73. data/lib/sequel/version.rb +1 -1
  74. data/spec/adapters/mssql_spec.rb +37 -12
  75. data/spec/adapters/mysql_spec.rb +39 -75
  76. data/spec/adapters/oracle_spec.rb +11 -11
  77. data/spec/adapters/postgres_spec.rb +414 -237
  78. data/spec/adapters/spec_helper.rb +1 -1
  79. data/spec/adapters/sqlite_spec.rb +14 -14
  80. data/spec/core/database_spec.rb +6 -6
  81. data/spec/core/dataset_spec.rb +169 -205
  82. data/spec/core/expression_filters_spec.rb +182 -295
  83. data/spec/core/object_graph_spec.rb +6 -6
  84. data/spec/core/schema_spec.rb +14 -14
  85. data/spec/core/spec_helper.rb +1 -0
  86. data/spec/{extensions/core_extensions_spec.rb → core_extensions_spec.rb} +208 -14
  87. data/spec/extensions/columns_introspection_spec.rb +5 -5
  88. data/spec/extensions/hook_class_methods_spec.rb +28 -36
  89. data/spec/extensions/many_through_many_spec.rb +4 -4
  90. data/spec/extensions/pg_array_ops_spec.rb +15 -7
  91. data/spec/extensions/pg_array_spec.rb +81 -48
  92. data/spec/extensions/pg_auto_parameterize_spec.rb +2 -2
  93. data/spec/extensions/pg_hstore_ops_spec.rb +13 -9
  94. data/spec/extensions/pg_hstore_spec.rb +66 -65
  95. data/spec/extensions/pg_inet_spec.rb +2 -4
  96. data/spec/extensions/pg_interval_spec.rb +2 -3
  97. data/spec/extensions/pg_json_spec.rb +20 -18
  98. data/spec/extensions/pg_range_ops_spec.rb +11 -4
  99. data/spec/extensions/pg_range_spec.rb +30 -7
  100. data/spec/extensions/pg_row_ops_spec.rb +48 -0
  101. data/spec/extensions/pg_row_plugin_spec.rb +45 -0
  102. data/spec/extensions/pg_row_spec.rb +323 -0
  103. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  104. data/spec/extensions/query_literals_spec.rb +11 -11
  105. data/spec/extensions/query_spec.rb +3 -3
  106. data/spec/extensions/schema_dumper_spec.rb +20 -4
  107. data/spec/extensions/schema_spec.rb +18 -41
  108. data/spec/extensions/select_remove_spec.rb +4 -4
  109. data/spec/extensions/spec_helper.rb +4 -8
  110. data/spec/extensions/to_dot_spec.rb +5 -5
  111. data/spec/extensions/validation_class_methods_spec.rb +28 -16
  112. data/spec/integration/associations_test.rb +20 -20
  113. data/spec/integration/dataset_test.rb +98 -98
  114. data/spec/integration/eager_loader_test.rb +13 -27
  115. data/spec/integration/plugin_test.rb +5 -5
  116. data/spec/integration/prepared_statement_test.rb +22 -13
  117. data/spec/integration/schema_test.rb +28 -18
  118. data/spec/integration/spec_helper.rb +1 -1
  119. data/spec/integration/timezone_test.rb +2 -2
  120. data/spec/integration/type_test.rb +15 -6
  121. data/spec/model/association_reflection_spec.rb +1 -1
  122. data/spec/model/associations_spec.rb +4 -4
  123. data/spec/model/base_spec.rb +5 -5
  124. data/spec/model/eager_loading_spec.rb +15 -15
  125. data/spec/model/model_spec.rb +32 -32
  126. data/spec/model/record_spec.rb +16 -0
  127. data/spec/model/spec_helper.rb +2 -6
  128. data/spec/model/validations_spec.rb +1 -1
  129. metadata +16 -4
@@ -5,6 +5,17 @@ module Sequel
5
5
  # Database and Dataset instance methods for JTDS specific
6
6
  # support via JDBC.
7
7
  module JTDS
8
+ module DatabaseMethods
9
+ include Sequel::JDBC::MSSQL::DatabaseMethods
10
+
11
+ private
12
+
13
+ # Handle nil values by using setNull with the correct parameter type.
14
+ def set_ps_arg_nil(cps, i)
15
+ cps.setNull(i, cps.getParameterMetaData.getParameterType(i))
16
+ end
17
+ end
18
+
8
19
  # Dataset class for JTDS datasets accessed via JDBC.
9
20
  class Dataset < JDBC::Dataset
10
21
  include Sequel::MSSQL::DatasetMethods
@@ -15,18 +15,15 @@ module Sequel
15
15
  # Add the primary_keys and primary_key_sequences instance variables,
16
16
  # so we can get the correct return values for inserted rows.
17
17
  def self.extended(db)
18
- db.instance_eval do
19
- @primary_keys = {}
20
- @primary_key_sequences = {}
21
- end
18
+ db.send(:initialize_postgres_adapter)
22
19
  end
23
20
 
24
21
  private
25
22
 
26
23
  # Use setNull for nil arguments as the default behavior of setString
27
24
  # with nil doesn't appear to work correctly on PostgreSQL.
28
- def set_ps_arg(cps, arg, i)
29
- arg.nil? ? cps.setNull(i, JavaSQL::Types::NULL) : super
25
+ def set_ps_arg_nil(cps, i)
26
+ cps.setNull(i, JavaSQL::Types::NULL)
30
27
  end
31
28
 
32
29
  # Execute the connection configuration SQL queries on the connection.
@@ -50,12 +50,17 @@ module Sequel
50
50
  'postgres' => lambda do |db|
51
51
  db.instance_eval do
52
52
  @server_version = 90103
53
- @primary_keys = {}
54
- @primary_key_sequences = {}
53
+ initialize_postgres_adapter
54
+ end
55
+ db.extend(Module.new do
56
+ def bound_variable_arg(arg, conn)
57
+ arg
58
+ end
59
+
55
60
  def primary_key(table)
56
61
  :id
57
62
  end
58
- end
63
+ end)
59
64
  end
60
65
  }
61
66
 
@@ -127,6 +132,7 @@ module Sequel
127
132
  def initialize(opts={})
128
133
  super
129
134
  opts = @opts
135
+ @sqls = opts[:sqls] || []
130
136
  if mod_name = SHARED_ADAPTERS[opts[:host]]
131
137
  @shared_adapter = true
132
138
  require "sequel/adapters/shared/#{opts[:host]}"
@@ -141,7 +147,7 @@ module Sequel
141
147
  self.fetch = opts[:fetch]
142
148
  self.numrows = opts[:numrows]
143
149
  extend(opts[:extend]) if opts[:extend]
144
- @sqls = opts[:sqls] || []
150
+ sqls
145
151
  end
146
152
 
147
153
  # Return a related Connection option connecting to the given shard.
@@ -1,5 +1,4 @@
1
1
  Sequel.require 'adapters/shared/postgres'
2
- Sequel.require 'adapters/utils/pg_types'
3
2
 
4
3
  begin
5
4
  require 'pg'
@@ -157,10 +156,6 @@ module Sequel
157
156
 
158
157
  set_adapter_scheme :postgres
159
158
 
160
- # A hash of conversion procs, keyed by type integer (oid) and
161
- # having callable values for the conversion proc for that type.
162
- attr_reader :conversion_procs
163
-
164
159
  # Whether infinite timestamps should be converted on retrieval. By default, no
165
160
  # conversion is done, so an error is raised if you attempt to retrieve an infinite
166
161
  # timestamp. You can set this to :nil to convert to nil, :string to leave
@@ -172,8 +167,7 @@ module Sequel
172
167
  def initialize(*args)
173
168
  super
174
169
  @convert_infinite_timestamps = false
175
- @primary_keys = {}
176
- @primary_key_sequences = {}
170
+ initialize_postgres_adapter
177
171
  end
178
172
 
179
173
  # Convert given argument so that it can be used directly by pg. Currently, pg doesn't
@@ -232,7 +226,6 @@ module Sequel
232
226
  conn.instance_variable_set(:@db, self)
233
227
  conn.instance_variable_set(:@prepared_statements, {}) if SEQUEL_POSTGRES_USES_PG
234
228
  connection_configuration_sqls.each{|sql| conn.execute(sql)}
235
- @conversion_procs ||= get_conversion_procs(conn)
236
229
  conn
237
230
  end
238
231
 
@@ -354,12 +347,6 @@ module Sequel
354
347
  end
355
348
  end
356
349
 
357
- # Reset the database's conversion procs, requires a server query if there
358
- # any named types.
359
- def reset_conversion_procs
360
- synchronize{|conn| @conversion_procs = get_conversion_procs(conn)}
361
- end
362
-
363
350
  # If convert_infinite_timestamps is true and the value is infinite, return an appropriate
364
351
  # value based on the convert_infinite_timestamps setting.
365
352
  def to_application_timestamp(value)
@@ -447,20 +434,6 @@ module Sequel
447
434
  end
448
435
  end
449
436
 
450
- # Return the conversion procs hash to use for this database.
451
- def get_conversion_procs(conn)
452
- procs = PG_TYPES.dup
453
- procs[1184] = procs[1114] = method(:to_application_timestamp)
454
- unless (pgnt = PG_NAMED_TYPES).empty?
455
- conn.execute("SELECT oid, typname FROM pg_type where typtype = 'b' AND typname IN ('#{pgnt.keys.map{|type| conn.escape_string(type.to_s)}.join("', '")}')") do |res|
456
- res.ntuples.times do |i|
457
- procs[res.getvalue(i, 0).to_i] ||= pgnt[res.getvalue(i, 1).untaint.to_sym]
458
- end
459
- end
460
- end
461
- procs
462
- end
463
-
464
437
  # Return an appropriate value for the given infinite timestamp string.
465
438
  def infinite_timestamp_value(value)
466
439
  case convert_infinite_timestamps
@@ -93,9 +93,17 @@ module Sequel
93
93
  def views(opts={})
94
94
  information_schema_tables('VIEW', opts)
95
95
  end
96
-
96
+
97
97
  private
98
98
 
99
+ # Add dropping of the default constraint to the list of SQL queries.
100
+ # This is necessary before dropping the column or changing its type.
101
+ def add_drop_default_constraint_sql(sqls, table, column)
102
+ if constraint = default_constraint_name(table, column)
103
+ sqls << "ALTER TABLE #{quote_schema_table(table)} DROP CONSTRAINT #{constraint}"
104
+ end
105
+ end
106
+
99
107
  # MSSQL uses the IDENTITY(1,1) column for autoincrementing columns.
100
108
  def auto_increment_sql
101
109
  AUTO_INCREMENT
@@ -106,6 +114,10 @@ module Sequel
106
114
  case op[:op]
107
115
  when :add_column
108
116
  "ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op)}"
117
+ when :drop_column
118
+ sqls = []
119
+ add_drop_default_constraint_sql(sqls, table, op[:name])
120
+ sqls << super
109
121
  when :rename_column
110
122
  "sp_rename #{literal("#{quote_schema_table(table)}.#{quote_identifier(op[:name])}")}, #{literal(op[:new_name].to_s)}, 'COLUMN'"
111
123
  when :set_column_type
@@ -113,9 +125,7 @@ module Sequel
113
125
  if sch = schema(table)
114
126
  if cs = sch.each{|k, v| break v if k == op[:name]; nil}
115
127
  cs = cs.dup
116
- if constraint = default_constraint_name(table, op[:name])
117
- sqls << "ALTER TABLE #{quote_schema_table(table)} DROP CONSTRAINT #{constraint}"
118
- end
128
+ add_drop_default_constraint_sql(sqls, table, op[:name])
119
129
  cs[:default] = cs[:ruby_default]
120
130
  op = cs.merge!(op)
121
131
  default = op.delete(:default)
@@ -176,15 +186,15 @@ module Sequel
176
186
  end
177
187
 
178
188
  # The name of the constraint for setting the default value on the table and column.
179
- def default_constraint_name(table, column)
180
- from(:sysobjects___c_obj).
181
- join(:syscomments___com, :id=>:id).
182
- join(:sysobjects___t_obj, :id=>:c_obj__parent_obj).
183
- join(:sysconstraints___con, :constid=>:c_obj__id).
184
- join(:syscolumns___col, :id=>:t_obj__id, :colid=>:colid).
185
- where{{c_obj__uid=>user_id{}}}.
186
- where(:c_obj__xtype=>'D', :t_obj__name=>table.to_s, :col__name=>column.to_s).
187
- get(:c_obj__name)
189
+ # The SQL used to select default constraints utilizes MSSQL catalog views which were introduced in 2005.
190
+ # This method intentionally does not support MSSQL 2000.
191
+ def default_constraint_name(table, column_name)
192
+ if server_version >= 9000000
193
+ table_name = schema_and_table(table).compact.join('.')
194
+ self[:sys__default_constraints].
195
+ where{{:parent_object_id => object_id(table_name), col_name(:parent_object_id, :parent_column_id) => column_name.to_s}}.
196
+ get(:name)
197
+ end
188
198
  end
189
199
 
190
200
  # The SQL to drop an index for the table.
@@ -1,3 +1,5 @@
1
+ Sequel.require 'adapters/utils/pg_types'
2
+
1
3
  module Sequel
2
4
  # Top level module for holding all PostgreSQL-related modules and classes
3
5
  # for Sequel. There are a few module level accessors that are added via
@@ -146,6 +148,13 @@ module Sequel
146
148
  end_sql
147
149
  ).strip.gsub(/\s+/, ' ').freeze
148
150
 
151
+ # The Sequel extensions that require reseting of the conversion procs.
152
+ RESET_PROCS_EXTENSIONS = [:pg_array, :pg_hstore, :pg_inet, :pg_interval, :pg_json, :pg_range].freeze
153
+
154
+ # A hash of conversion procs, keyed by type integer (oid) and
155
+ # having callable values for the conversion proc for that type.
156
+ attr_reader :conversion_procs
157
+
149
158
  # Commit an existing prepared transaction with the given transaction
150
159
  # identifier string.
151
160
  def commit_prepared_transaction(transaction_id)
@@ -250,6 +259,17 @@ module Sequel
250
259
  self << drop_trigger_sql(table, name, opts)
251
260
  end
252
261
 
262
+ # If any of the extensions that require reseting the conversion procs
263
+ # is loaded, reset them. This is done here so that if you load
264
+ # multiple pg_* extensions in the same call, the conversion procs are
265
+ # only reset once instead of once for every extension.
266
+ def extension(*exts)
267
+ super
268
+ unless (RESET_PROCS_EXTENSIONS & exts).empty?
269
+ reset_conversion_procs
270
+ end
271
+ end
272
+
253
273
  # Return full foreign key information using the pg system tables, including
254
274
  # :name, :on_delete, :on_update, and :deferrable entries in the hashes.
255
275
  def foreign_key_list(table, opts={})
@@ -380,6 +400,12 @@ module Sequel
380
400
  end
381
401
  end
382
402
  end
403
+
404
+ # Reset the database's conversion procs, requires a server query if there
405
+ # any named types.
406
+ def reset_conversion_procs
407
+ @conversion_procs = get_conversion_procs
408
+ end
383
409
 
384
410
  # Reset the primary key sequence for the given table, baseing it on the
385
411
  # maximum current value of the table's primary key.
@@ -643,6 +669,18 @@ module Sequel
643
669
  end
644
670
  end
645
671
 
672
+ # Return a hash with oid keys and callable values, used for converting types.
673
+ def get_conversion_procs
674
+ procs = PG_TYPES.dup
675
+ procs[1184] = procs[1114] = method(:to_application_timestamp)
676
+ unless (pgnt = PG_NAMED_TYPES).empty?
677
+ from(:pg_type).where(:typtype=>'b', :typname=>pgnt.keys.map{|t| t.to_s}).select_map([:oid, :typname]).each do |oid, name|
678
+ procs[oid.to_i] ||= pgnt[name.untaint.to_sym]
679
+ end
680
+ end
681
+ procs
682
+ end
683
+
646
684
  # PostgreSQL folds unquoted identifiers to lowercase, so it shouldn't need to upcase identifiers on input.
647
685
  def identifier_input_method_default
648
686
  nil
@@ -676,6 +714,13 @@ module Sequel
676
714
  "CREATE #{unique}INDEX#{' CONCURRENTLY' if index[:concurrently]} #{quote_identifier(index_name)} ON #{quote_schema_table(table_name)} #{"USING #{index_type} " if index_type}#{expr}#{filter}"
677
715
  end
678
716
 
717
+ # Setup datastructures shared by all postgres adapters.
718
+ def initialize_postgres_adapter
719
+ @primary_keys = {}
720
+ @primary_key_sequences = {}
721
+ reset_conversion_procs
722
+ end
723
+
679
724
  # Backbone of the tables and views support.
680
725
  def pg_class_relname(type, opts)
681
726
  ds = metadata_dataset.from(:pg_class).filter(:relkind=>type).select(:relname).exclude(SQL::StringExpression.like(:relname, SYSTEM_TABLE_REGEXP)).server(opts[:server]).join(:pg_namespace, :oid=>:relnamespace)
@@ -716,6 +761,7 @@ module Sequel
716
761
  m = output_identifier_meth(opts[:dataset])
717
762
  m2 = input_identifier_meth(opts[:dataset])
718
763
  ds = metadata_dataset.select(:pg_attribute__attname___name,
764
+ SQL::Cast.new(:pg_attribute__atttypid, :integer).as(:oid),
719
765
  SQL::Function.new(:format_type, :pg_type__oid, :pg_attribute__atttypmod).as(:db_type),
720
766
  SQL::Function.new(:pg_get_expr, :pg_attrdef__adbin, :pg_class__oid).as(:default),
721
767
  SQL::BooleanExpression.new(:NOT, :pg_attribute__attnotnull).as(:allow_null),
@@ -1,11 +1,8 @@
1
- require 'swift'
2
-
3
1
  module Sequel
4
- # Module holding the Swift support for Sequel. Swift is a
5
- # ruby front-end for dbic++, a fast database access library
6
- # written in C++.
2
+ # Module holding the Swift DB support for Sequel. Swift DB is a
3
+ # collection of drivers used in Swift ORM.
7
4
  #
8
- # The Swift adapter currently supports PostgreSQL and MySQL:
5
+ # The Swift adapter currently supports PostgreSQL, MySQL and SQLite3
9
6
  #
10
7
  # Sequel.connect('swift://user:password@host/database?db_type=postgres')
11
8
  # Sequel.connect('swift://user:password@host/database?db_type=mysql')
@@ -60,7 +57,9 @@ module Sequel
60
57
 
61
58
  # Create an instance of swift_class for the given options.
62
59
  def connect(server)
63
- setup_connection(swift_class.new(server_opts(server)))
60
+ opts = server_opts(server)
61
+ opts[:pass] = opts[:password]
62
+ setup_connection(swift_class.new(opts))
64
63
  end
65
64
 
66
65
  # Execute the given SQL, yielding a Swift::Result if a block is given.
@@ -70,7 +69,7 @@ module Sequel
70
69
  res = log_yield(sql){conn.execute(sql)}
71
70
  yield res if block_given?
72
71
  nil
73
- rescue SwiftError => e
72
+ rescue ::Swift::Error => e
74
73
  raise_error(e)
75
74
  end
76
75
  end
@@ -81,8 +80,8 @@ module Sequel
81
80
  def execute_dui(sql, opts={})
82
81
  synchronize(opts[:server]) do |conn|
83
82
  begin
84
- log_yield(sql){conn.execute(sql).rows}
85
- rescue SwiftError => e
83
+ log_yield(sql){conn.execute(sql).affected_rows}
84
+ rescue ::Swift::Error => e
86
85
  raise_error(e)
87
86
  end
88
87
  end
@@ -94,7 +93,7 @@ module Sequel
94
93
  synchronize(opts[:server]) do |conn|
95
94
  begin
96
95
  log_yield(sql){conn.execute(sql).insert_id}
97
- rescue SwiftError => e
96
+ rescue ::Swift::Error => e
98
97
  raise_error(e)
99
98
  end
100
99
  end
@@ -138,8 +137,17 @@ module Sequel
138
137
  # Set the columns and yield the hashes to the block.
139
138
  def fetch_rows(sql)
140
139
  execute(sql) do |res|
141
- @columns = res.fields
142
- res.each{|h| yield h}
140
+ col_map = {}
141
+ @columns = res.fields.map do |c|
142
+ col_map[c] = output_identifier(c)
143
+ end
144
+ res.each do |r|
145
+ h = {}
146
+ r.each do |k, v|
147
+ h[col_map[k]] = v.is_a?(StringIO) ? SQL::Blob.new(v.read) : v
148
+ end
149
+ yield h
150
+ end
143
151
  end
144
152
  self
145
153
  end
@@ -1,3 +1,4 @@
1
+ require 'swift/db/mysql'
1
2
  Sequel.require 'adapters/shared/mysql'
2
3
 
3
4
  module Sequel
@@ -1,7 +1,8 @@
1
+ require 'swift/db/postgres'
1
2
  Sequel.require 'adapters/shared/postgres'
2
3
 
3
4
  module Sequel
4
- Postgres::CONVERTED_EXCEPTIONS << ::SwiftError
5
+ Postgres::CONVERTED_EXCEPTIONS << ::Swift::Error
5
6
 
6
7
  module Swift
7
8
  # Adapter, Database, and Dataset support for accessing a PostgreSQL
@@ -14,10 +15,7 @@ module Sequel
14
15
  # Add the primary_keys and primary_key_sequences instance variables,
15
16
  # so we can get the correct return values for inserted rows.
16
17
  def self.extended(db)
17
- db.instance_eval do
18
- @primary_keys = {}
19
- @primary_key_sequences = {}
20
- end
18
+ db.send(:initialize_postgres_adapter)
21
19
  end
22
20
 
23
21
  private
@@ -35,6 +33,7 @@ module Sequel
35
33
  # Extend the adapter with the Swift PostgreSQL AdapterMethods.
36
34
  def setup_connection(conn)
37
35
  conn = super(conn)
36
+ conn.native_bind_format = true
38
37
  connection_configuration_sqls.each{|sql| log_yield(sql){conn.execute(sql)}}
39
38
  conn
40
39
  end
@@ -1,3 +1,4 @@
1
+ require 'swift/db/sqlite3'
1
2
  Sequel.require 'adapters/shared/sqlite'
2
3
 
3
4
  module Sequel
@@ -25,7 +26,7 @@ module Sequel
25
26
 
26
27
  # Use Swift's escape method for quoting.
27
28
  def literal_string_append(sql, s)
28
- sql << db.synchronize{|c| c.escape(s)}
29
+ sql << APOS << db.synchronize{|c| c.escape(s)} << APOS
29
30
  end
30
31
  end
31
32
  end
@@ -6,13 +6,25 @@ module Sequel
6
6
  class Database < Sequel::Database
7
7
  include Sequel::MSSQL::DatabaseMethods
8
8
  set_adapter_scheme :tinytds
9
+
10
+ # Choose whether to use unicode strings on initialization
11
+ def initialize(*)
12
+ super
13
+ set_mssql_unicode_strings
14
+ end
9
15
 
10
16
  # Transfer the :user option to the :username option.
11
17
  def connect(server)
12
18
  opts = server_opts(server)
13
19
  opts[:username] = opts[:user]
14
- set_mssql_unicode_strings
15
- TinyTds::Client.new(opts)
20
+ c = TinyTds::Client.new(opts)
21
+
22
+ if (ts = opts[:textsize])
23
+ sql = "SET TEXTSIZE #{typecast_value_integer(ts)}"
24
+ log_yield(sql){c.execute(sql)}
25
+ end
26
+
27
+ c
16
28
  end
17
29
 
18
30
  # Execute the given +sql+ on the server. If the :return option