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.
- data/CHANGELOG +56 -0
- data/README.rdoc +82 -58
- data/Rakefile +6 -5
- data/bin/sequel +1 -1
- data/doc/active_record.rdoc +67 -52
- data/doc/advanced_associations.rdoc +33 -48
- data/doc/association_basics.rdoc +41 -51
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +47 -43
- data/doc/mass_assignment.rdoc +1 -1
- data/doc/migration.rdoc +4 -5
- data/doc/model_hooks.rdoc +3 -3
- data/doc/object_model.rdoc +31 -25
- data/doc/opening_databases.rdoc +19 -5
- data/doc/prepared_statements.rdoc +2 -2
- data/doc/querying.rdoc +109 -52
- data/doc/reflection.rdoc +6 -6
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/schema_modification.rdoc +22 -13
- data/doc/sharding.rdoc +8 -9
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +47 -7
- data/doc/thread_safety.rdoc +1 -1
- data/doc/transactions.rdoc +1 -1
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +29 -43
- data/lib/sequel/adapters/do/postgres.rb +1 -4
- data/lib/sequel/adapters/jdbc.rb +14 -3
- data/lib/sequel/adapters/jdbc/db2.rb +9 -0
- data/lib/sequel/adapters/jdbc/derby.rb +41 -4
- data/lib/sequel/adapters/jdbc/jtds.rb +11 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -6
- data/lib/sequel/adapters/mock.rb +10 -4
- data/lib/sequel/adapters/postgres.rb +1 -28
- data/lib/sequel/adapters/shared/mssql.rb +23 -13
- data/lib/sequel/adapters/shared/postgres.rb +46 -0
- data/lib/sequel/adapters/swift.rb +21 -13
- data/lib/sequel/adapters/swift/mysql.rb +1 -0
- data/lib/sequel/adapters/swift/postgres.rb +4 -5
- data/lib/sequel/adapters/swift/sqlite.rb +2 -1
- data/lib/sequel/adapters/tinytds.rb +14 -2
- data/lib/sequel/adapters/utils/pg_types.rb +5 -0
- data/lib/sequel/core.rb +29 -17
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +3 -0
- data/lib/sequel/dataset/actions.rb +5 -6
- data/lib/sequel/dataset/query.rb +7 -7
- data/lib/sequel/dataset/sql.rb +5 -18
- data/lib/sequel/extensions/core_extensions.rb +8 -12
- data/lib/sequel/extensions/pg_array.rb +59 -33
- data/lib/sequel/extensions/pg_array_ops.rb +32 -4
- data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -1
- data/lib/sequel/extensions/pg_hstore.rb +32 -17
- data/lib/sequel/extensions/pg_hstore_ops.rb +32 -3
- data/lib/sequel/extensions/pg_inet.rb +1 -2
- data/lib/sequel/extensions/pg_interval.rb +0 -1
- data/lib/sequel/extensions/pg_json.rb +41 -23
- data/lib/sequel/extensions/pg_range.rb +36 -11
- data/lib/sequel/extensions/pg_range_ops.rb +32 -4
- data/lib/sequel/extensions/pg_row.rb +572 -0
- data/lib/sequel/extensions/pg_row_ops.rb +164 -0
- data/lib/sequel/extensions/query.rb +3 -3
- data/lib/sequel/extensions/schema_dumper.rb +7 -8
- data/lib/sequel/extensions/select_remove.rb +1 -1
- data/lib/sequel/model/base.rb +1 -0
- data/lib/sequel/no_core_ext.rb +1 -1
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/validation_helpers.rb +31 -0
- data/lib/sequel/sql.rb +64 -44
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +37 -12
- data/spec/adapters/mysql_spec.rb +39 -75
- data/spec/adapters/oracle_spec.rb +11 -11
- data/spec/adapters/postgres_spec.rb +414 -237
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +14 -14
- data/spec/core/database_spec.rb +6 -6
- data/spec/core/dataset_spec.rb +169 -205
- data/spec/core/expression_filters_spec.rb +182 -295
- data/spec/core/object_graph_spec.rb +6 -6
- data/spec/core/schema_spec.rb +14 -14
- data/spec/core/spec_helper.rb +1 -0
- data/spec/{extensions/core_extensions_spec.rb → core_extensions_spec.rb} +208 -14
- data/spec/extensions/columns_introspection_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +28 -36
- data/spec/extensions/many_through_many_spec.rb +4 -4
- data/spec/extensions/pg_array_ops_spec.rb +15 -7
- data/spec/extensions/pg_array_spec.rb +81 -48
- data/spec/extensions/pg_auto_parameterize_spec.rb +2 -2
- data/spec/extensions/pg_hstore_ops_spec.rb +13 -9
- data/spec/extensions/pg_hstore_spec.rb +66 -65
- data/spec/extensions/pg_inet_spec.rb +2 -4
- data/spec/extensions/pg_interval_spec.rb +2 -3
- data/spec/extensions/pg_json_spec.rb +20 -18
- data/spec/extensions/pg_range_ops_spec.rb +11 -4
- data/spec/extensions/pg_range_spec.rb +30 -7
- data/spec/extensions/pg_row_ops_spec.rb +48 -0
- data/spec/extensions/pg_row_plugin_spec.rb +45 -0
- data/spec/extensions/pg_row_spec.rb +323 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/query_literals_spec.rb +11 -11
- data/spec/extensions/query_spec.rb +3 -3
- data/spec/extensions/schema_dumper_spec.rb +20 -4
- data/spec/extensions/schema_spec.rb +18 -41
- data/spec/extensions/select_remove_spec.rb +4 -4
- data/spec/extensions/spec_helper.rb +4 -8
- data/spec/extensions/to_dot_spec.rb +5 -5
- data/spec/extensions/validation_class_methods_spec.rb +28 -16
- data/spec/integration/associations_test.rb +20 -20
- data/spec/integration/dataset_test.rb +98 -98
- data/spec/integration/eager_loader_test.rb +13 -27
- data/spec/integration/plugin_test.rb +5 -5
- data/spec/integration/prepared_statement_test.rb +22 -13
- data/spec/integration/schema_test.rb +28 -18
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/integration/timezone_test.rb +2 -2
- data/spec/integration/type_test.rb +15 -6
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +4 -4
- data/spec/model/base_spec.rb +5 -5
- data/spec/model/eager_loading_spec.rb +15 -15
- data/spec/model/model_spec.rb +32 -32
- data/spec/model/record_spec.rb +16 -0
- data/spec/model/spec_helper.rb +2 -6
- data/spec/model/validations_spec.rb +1 -1
- 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.
|
|
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
|
|
29
|
-
|
|
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.
|
data/lib/sequel/adapters/mock.rb
CHANGED
|
@@ -50,12 +50,17 @@ module Sequel
|
|
|
50
50
|
'postgres' => lambda do |db|
|
|
51
51
|
db.instance_eval do
|
|
52
52
|
@server_version = 90103
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
join(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
#
|
|
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
|
|
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
|
-
|
|
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
|
|
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).
|
|
85
|
-
rescue
|
|
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
|
|
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
|
-
|
|
142
|
-
res.
|
|
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,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 << ::
|
|
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.
|
|
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
|
-
|
|
15
|
-
|
|
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
|