sequel 3.21.0 → 3.24.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 +112 -0
- data/README.rdoc +15 -1
- data/doc/association_basics.rdoc +159 -40
- data/doc/model_hooks.rdoc +64 -27
- data/doc/prepared_statements.rdoc +8 -4
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado.rb +2 -1
- data/lib/sequel/adapters/db2.rb +8 -1
- data/lib/sequel/adapters/firebird.rb +25 -9
- data/lib/sequel/adapters/informix.rb +4 -19
- data/lib/sequel/adapters/jdbc/h2.rb +5 -0
- data/lib/sequel/adapters/jdbc/informix.rb +31 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
- data/lib/sequel/adapters/jdbc.rb +39 -20
- data/lib/sequel/adapters/odbc.rb +2 -0
- data/lib/sequel/adapters/oracle.rb +12 -0
- data/lib/sequel/adapters/postgres.rb +30 -1
- data/lib/sequel/adapters/shared/access.rb +10 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +106 -11
- data/lib/sequel/adapters/shared/mysql.rb +25 -7
- data/lib/sequel/adapters/shared/postgres.rb +39 -6
- data/lib/sequel/adapters/shared/sqlite.rb +57 -5
- data/lib/sequel/adapters/sqlite.rb +8 -3
- data/lib/sequel/adapters/swift/mysql.rb +9 -0
- data/lib/sequel/adapters/tinytds.rb +4 -3
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/misc.rb +6 -0
- data/lib/sequel/database/query.rb +33 -3
- data/lib/sequel/database/schema_methods.rb +13 -4
- data/lib/sequel/dataset/features.rb +6 -0
- data/lib/sequel/dataset/prepared_statements.rb +17 -2
- data/lib/sequel/dataset/query.rb +17 -0
- data/lib/sequel/dataset/sql.rb +2 -53
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +4 -3
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +234 -32
- data/lib/sequel/model/base.rb +187 -60
- data/lib/sequel/model/exceptions.rb +3 -1
- data/lib/sequel/model.rb +5 -0
- data/lib/sequel/plugins/association_pks.rb +6 -4
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/identity_map.rb +2 -2
- data/lib/sequel/plugins/many_through_many.rb +33 -3
- data/lib/sequel/plugins/prepared_statements.rb +140 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +72 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -0
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/sql.rb +8 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +36 -0
- data/spec/adapters/mysql_spec.rb +6 -0
- data/spec/adapters/postgres_spec.rb +43 -18
- data/spec/adapters/spec_helper.rb +5 -0
- data/spec/core/connection_pool_spec.rb +56 -77
- data/spec/core/database_spec.rb +33 -0
- data/spec/core/dataset_spec.rb +127 -16
- data/spec/core/expression_filters_spec.rb +13 -0
- data/spec/core/schema_spec.rb +13 -1
- data/spec/core/spec_helper.rb +5 -0
- data/spec/extensions/association_pks_spec.rb +7 -0
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/many_through_many_spec.rb +77 -0
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/nested_attributes_spec.rb +1 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +69 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +36 -0
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +3 -1
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/xml_serializer_spec.rb +12 -0
- data/spec/integration/associations_test.rb +212 -0
- data/spec/integration/dataset_test.rb +8 -1
- data/spec/integration/plugin_test.rb +134 -0
- data/spec/integration/prepared_statement_test.rb +72 -1
- data/spec/integration/schema_test.rb +66 -8
- data/spec/integration/spec_helper.rb +5 -0
- data/spec/integration/transaction_test.rb +40 -0
- data/spec/integration/type_test.rb +7 -0
- data/spec/model/associations_spec.rb +463 -5
- data/spec/model/base_spec.rb +59 -0
- data/spec/model/eager_loading_spec.rb +269 -1
- data/spec/model/hooks_spec.rb +161 -0
- data/spec/model/record_spec.rb +30 -0
- data/spec/model/spec_helper.rb +5 -0
- metadata +29 -4
|
@@ -198,6 +198,7 @@ module Sequel
|
|
|
198
198
|
NULL = LiteralString.new('NULL').freeze
|
|
199
199
|
COMMA_SEPARATOR = ', '.freeze
|
|
200
200
|
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'with distinct limit columns from join where group having compounds order')
|
|
201
|
+
INSERT_CLAUSE_METHODS = clause_methods(:insert, %w'into columns values returning_select')
|
|
201
202
|
|
|
202
203
|
# Yield all rows returned by executing the given SQL and converting
|
|
203
204
|
# the types.
|
|
@@ -242,19 +243,13 @@ module Sequel
|
|
|
242
243
|
def insert_select(*values)
|
|
243
244
|
naked.clone(default_server_opts(:sql=>insert_returning_sql(nil, *values))).single_record
|
|
244
245
|
end
|
|
245
|
-
|
|
246
|
+
|
|
246
247
|
def requires_sql_standard_datetimes?
|
|
247
248
|
true
|
|
248
249
|
end
|
|
249
250
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
SELECT_CLAUSE_METHODS
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
def select_limit_sql(sql)
|
|
256
|
-
sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
|
|
257
|
-
sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
|
|
251
|
+
def supports_insert_select?
|
|
252
|
+
true
|
|
258
253
|
end
|
|
259
254
|
|
|
260
255
|
# Firebird does not support INTERSECT or EXCEPT
|
|
@@ -264,6 +259,16 @@ module Sequel
|
|
|
264
259
|
|
|
265
260
|
private
|
|
266
261
|
|
|
262
|
+
def insert_clause_methods
|
|
263
|
+
INSERT_CLAUSE_METHODS
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def insert_returning_select_sql(sql)
|
|
267
|
+
if opts.has_key?(:returning)
|
|
268
|
+
sql << " RETURNING #{column_list(Array(opts[:returning]))}"
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
267
272
|
def hash_row(stmt, row)
|
|
268
273
|
@columns.inject({}) do |m, c|
|
|
269
274
|
m[c] = row.shift
|
|
@@ -278,6 +283,17 @@ module Sequel
|
|
|
278
283
|
def literal_true
|
|
279
284
|
BOOL_TRUE
|
|
280
285
|
end
|
|
286
|
+
|
|
287
|
+
# The order of clauses in the SELECT SQL statement
|
|
288
|
+
def select_clause_methods
|
|
289
|
+
SELECT_CLAUSE_METHODS
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def select_limit_sql(sql)
|
|
293
|
+
sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
|
|
294
|
+
sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
|
|
295
|
+
end
|
|
296
|
+
|
|
281
297
|
end
|
|
282
298
|
end
|
|
283
299
|
end
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
require 'informix'
|
|
2
|
+
Sequel.require 'adapters/shared/informix'
|
|
2
3
|
|
|
3
4
|
module Sequel
|
|
4
5
|
module Informix
|
|
5
6
|
class Database < Sequel::Database
|
|
7
|
+
include DatabaseMethods
|
|
8
|
+
|
|
6
9
|
set_adapter_scheme :informix
|
|
7
10
|
|
|
8
|
-
TEMPORARY = 'TEMP '.freeze
|
|
9
|
-
|
|
10
11
|
def connect(server)
|
|
11
12
|
opts = server_opts(server)
|
|
12
13
|
::Informix.connect(opts[:database], opts[:user], opts[:password])
|
|
@@ -35,7 +36,7 @@ module Sequel
|
|
|
35
36
|
end
|
|
36
37
|
|
|
37
38
|
class Dataset < Sequel::Dataset
|
|
38
|
-
|
|
39
|
+
include DatasetMethods
|
|
39
40
|
|
|
40
41
|
def fetch_rows(sql)
|
|
41
42
|
execute(sql) do |cursor|
|
|
@@ -56,22 +57,6 @@ module Sequel
|
|
|
56
57
|
end
|
|
57
58
|
self
|
|
58
59
|
end
|
|
59
|
-
|
|
60
|
-
private
|
|
61
|
-
|
|
62
|
-
# Informix does not support INTERSECT or EXCEPT
|
|
63
|
-
def supports_intersect_except?
|
|
64
|
-
false
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def select_clause_methods
|
|
68
|
-
SELECT_CLAUSE_METHODS
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def select_limit_sql(sql)
|
|
72
|
-
sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
|
|
73
|
-
sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
|
|
74
|
-
end
|
|
75
60
|
end
|
|
76
61
|
end
|
|
77
62
|
end
|
|
@@ -33,6 +33,11 @@ module Sequel
|
|
|
33
33
|
{:primary_key => true, :type => :identity}
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
# H2 supports CREATE TABLE IF NOT EXISTS syntax.
|
|
37
|
+
def supports_create_table_if_not_exists?
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
|
|
36
41
|
# H2 supports prepared transactions
|
|
37
42
|
def supports_prepared_transactions?
|
|
38
43
|
true
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Sequel.require 'adapters/shared/informix'
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module JDBC
|
|
5
|
+
# Database and Dataset instance methods for Informix specific
|
|
6
|
+
# support via JDBC.
|
|
7
|
+
module Informix
|
|
8
|
+
# Database instance methods for Informix databases accessed via JDBC.
|
|
9
|
+
module DatabaseMethods
|
|
10
|
+
include Sequel::Informix::DatabaseMethods
|
|
11
|
+
|
|
12
|
+
# Return instance of Sequel::JDBC::Informix::Dataset with the given opts.
|
|
13
|
+
def dataset(opts=nil)
|
|
14
|
+
Sequel::JDBC::Informix::Dataset.new(self, opts)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
# TODO: implement
|
|
20
|
+
def last_insert_id(conn, opts={})
|
|
21
|
+
nil
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Dataset class for Informix datasets accessed via JDBC.
|
|
26
|
+
class Dataset < JDBC::Dataset
|
|
27
|
+
include Sequel::Informix::DatasetMethods
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Sequel.require 'adapters/jdbc/mssql'
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module JDBC
|
|
5
|
+
# Database and Dataset instance methods for JTDS specific
|
|
6
|
+
# support via JDBC.
|
|
7
|
+
module JTDS
|
|
8
|
+
# Database instance methods for JTDS databases accessed via JDBC.
|
|
9
|
+
module DatabaseMethods
|
|
10
|
+
include Sequel::JDBC::MSSQL::DatabaseMethods
|
|
11
|
+
|
|
12
|
+
# Return instance of Sequel::JDBC::JTDS::Dataset with the given opts.
|
|
13
|
+
def dataset(opts=nil)
|
|
14
|
+
Sequel::JDBC::JTDS::Dataset.new(self, opts)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Dataset class for JTDS datasets accessed via JDBC.
|
|
19
|
+
class Dataset < JDBC::Dataset
|
|
20
|
+
include Sequel::MSSQL::DatasetMethods
|
|
21
|
+
|
|
22
|
+
# Handle CLOB types retrieved via JTDS.
|
|
23
|
+
def convert_type(v)
|
|
24
|
+
case v
|
|
25
|
+
when Java::NetSourceforgeJtdsJdbc::ClobImpl
|
|
26
|
+
convert_type(v.getSubString(1, v.length))
|
|
27
|
+
else
|
|
28
|
+
super
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -16,11 +16,6 @@ module Sequel
|
|
|
16
16
|
|
|
17
17
|
include Sequel::MSSQL::DatabaseMethods
|
|
18
18
|
|
|
19
|
-
# Return instance of Sequel::JDBC::MSSQL::Dataset with the given opts.
|
|
20
|
-
def dataset(opts=nil)
|
|
21
|
-
Sequel::JDBC::MSSQL::Dataset.new(self, opts)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
19
|
private
|
|
25
20
|
|
|
26
21
|
# Get the last inserted id using SCOPE_IDENTITY().
|
|
@@ -43,33 +38,6 @@ module Sequel
|
|
|
43
38
|
def primary_key_index_re
|
|
44
39
|
PRIMARY_KEY_INDEX_RE
|
|
45
40
|
end
|
|
46
|
-
|
|
47
|
-
def metadata_dataset
|
|
48
|
-
ds = super
|
|
49
|
-
# Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
|
|
50
|
-
# for the getColumns result set specifies an incorrect type for the
|
|
51
|
-
# IS_AUTOINCREMENT column. The column is a string, but the type is
|
|
52
|
-
# specified as a short. This causes getObject() to throw a
|
|
53
|
-
# com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
|
|
54
|
-
# from char to SMALLINT is unsupported." Using getString() rather
|
|
55
|
-
# than getObject() for this column avoids the problem.
|
|
56
|
-
# Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
|
|
57
|
-
def ds.result_set_object_getter
|
|
58
|
-
lambda do |result, n, i|
|
|
59
|
-
if n == :is_autoincrement
|
|
60
|
-
@convert_types ? convert_type(result.getString(i)) : result.getString(i)
|
|
61
|
-
else
|
|
62
|
-
@convert_types ? convert_type(result.getObject(i)) : result.getObject(i)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
ds
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# Dataset class for MSSQL datasets accessed via JDBC.
|
|
71
|
-
class Dataset < JDBC::Dataset
|
|
72
|
-
include Sequel::MSSQL::DatasetMethods
|
|
73
41
|
end
|
|
74
42
|
end
|
|
75
43
|
end
|
|
@@ -56,6 +56,15 @@ module Sequel
|
|
|
56
56
|
def schema_column_type(db_type)
|
|
57
57
|
db_type == 'tinyint(1)' ? :boolean : super
|
|
58
58
|
end
|
|
59
|
+
|
|
60
|
+
# By default, MySQL 'where id is null' selects the last inserted id.
|
|
61
|
+
# Turn that off unless explicitly enabled.
|
|
62
|
+
def setup_connection(conn)
|
|
63
|
+
super
|
|
64
|
+
sql = "SET SQL_AUTO_IS_NULL=0"
|
|
65
|
+
statement(conn){|s| log_yield(sql){s.execute(sql)}} unless opts[:auto_is_null]
|
|
66
|
+
conn
|
|
67
|
+
end
|
|
59
68
|
end
|
|
60
69
|
|
|
61
70
|
# Dataset class for MySQL datasets accessed via JDBC.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Sequel.require 'adapters/jdbc/mssql'
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module JDBC
|
|
5
|
+
# Database and Dataset instance methods for SQLServer specific
|
|
6
|
+
# support via JDBC.
|
|
7
|
+
module SQLServer
|
|
8
|
+
# Database instance methods for SQLServer databases accessed via JDBC.
|
|
9
|
+
module DatabaseMethods
|
|
10
|
+
include Sequel::JDBC::MSSQL::DatabaseMethods
|
|
11
|
+
|
|
12
|
+
# Return instance of Sequel::JDBC::SQLServer::Dataset with the given opts.
|
|
13
|
+
def dataset(opts=nil)
|
|
14
|
+
Sequel::JDBC::SQLServer::Dataset.new(self, opts)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def metadata_dataset
|
|
18
|
+
ds = super
|
|
19
|
+
# Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
|
|
20
|
+
# for the getColumns result set specifies an incorrect type for the
|
|
21
|
+
# IS_AUTOINCREMENT column. The column is a string, but the type is
|
|
22
|
+
# specified as a short. This causes getObject() to throw a
|
|
23
|
+
# com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
|
|
24
|
+
# from char to SMALLINT is unsupported." Using getString() rather
|
|
25
|
+
# than getObject() for this column avoids the problem.
|
|
26
|
+
# Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
|
|
27
|
+
def ds.result_set_object_getter
|
|
28
|
+
lambda do |result, n, i|
|
|
29
|
+
if n == :is_autoincrement
|
|
30
|
+
@convert_types ? convert_type(result.getString(i)) : result.getString(i)
|
|
31
|
+
else
|
|
32
|
+
@convert_types ? convert_type(result.getObject(i)) : result.getObject(i)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
ds
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Dataset class for SQLServer datasets accessed via JDBC.
|
|
41
|
+
class Dataset < JDBC::Dataset
|
|
42
|
+
include Sequel::MSSQL::DatasetMethods
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
|
@@ -53,13 +53,15 @@ module Sequel
|
|
|
53
53
|
Java::oracle.jdbc.driver.OracleDriver
|
|
54
54
|
end,
|
|
55
55
|
:sqlserver=>proc do |db|
|
|
56
|
-
Sequel.ts_require 'adapters/jdbc/
|
|
57
|
-
db.extend(Sequel::JDBC::
|
|
56
|
+
Sequel.ts_require 'adapters/jdbc/sqlserver'
|
|
57
|
+
db.extend(Sequel::JDBC::SQLServer::DatabaseMethods)
|
|
58
|
+
db.send(:set_mssql_unicode_strings)
|
|
58
59
|
com.microsoft.sqlserver.jdbc.SQLServerDriver
|
|
59
60
|
end,
|
|
60
61
|
:jtds=>proc do |db|
|
|
61
|
-
Sequel.ts_require 'adapters/jdbc/
|
|
62
|
-
db.extend(Sequel::JDBC::
|
|
62
|
+
Sequel.ts_require 'adapters/jdbc/jtds'
|
|
63
|
+
db.extend(Sequel::JDBC::JTDS::DatabaseMethods)
|
|
64
|
+
db.send(:set_mssql_unicode_strings)
|
|
63
65
|
JDBC.load_gem('jtds')
|
|
64
66
|
Java::net.sourceforge.jtds.jdbc.Driver
|
|
65
67
|
end,
|
|
@@ -73,6 +75,11 @@ module Sequel
|
|
|
73
75
|
Sequel.ts_require 'adapters/jdbc/as400'
|
|
74
76
|
db.extend(Sequel::JDBC::AS400::DatabaseMethods)
|
|
75
77
|
com.ibm.as400.access.AS400JDBCDriver
|
|
78
|
+
end,
|
|
79
|
+
:"informix-sqli"=>proc do |db|
|
|
80
|
+
Sequel.ts_require 'adapters/jdbc/informix'
|
|
81
|
+
db.extend(Sequel::JDBC::Informix::DatabaseMethods)
|
|
82
|
+
com.informix.jdbc.IfxDriver
|
|
76
83
|
end
|
|
77
84
|
}
|
|
78
85
|
|
|
@@ -101,7 +108,7 @@ module Sequel
|
|
|
101
108
|
# True by default, can be set to false to roughly double performance when
|
|
102
109
|
# fetching rows.
|
|
103
110
|
attr_accessor :convert_types
|
|
104
|
-
|
|
111
|
+
|
|
105
112
|
# Call the DATABASE_SETUP proc directly after initialization,
|
|
106
113
|
# so the object always uses sub adapter specific code. Also,
|
|
107
114
|
# raise an error immediately if the connection doesn't have a
|
|
@@ -246,12 +253,14 @@ module Sequel
|
|
|
246
253
|
indexes
|
|
247
254
|
end
|
|
248
255
|
|
|
256
|
+
# Whether or not JNDI is being used for this connection.
|
|
257
|
+
def jndi?
|
|
258
|
+
!!(uri =~ JNDI_URI_REGEXP)
|
|
259
|
+
end
|
|
260
|
+
|
|
249
261
|
# All tables in this database
|
|
250
262
|
def tables(opts={})
|
|
251
|
-
|
|
252
|
-
m = output_identifier_meth
|
|
253
|
-
metadata(:getTables, nil, nil, nil, ['TABLE'].to_java(:string)){|h| ts << m.call(h[:table_name])}
|
|
254
|
-
ts
|
|
263
|
+
get_tables('TABLE', opts)
|
|
255
264
|
end
|
|
256
265
|
|
|
257
266
|
# The uri for this connection. You can specify the uri
|
|
@@ -264,11 +273,11 @@ module Sequel
|
|
|
264
273
|
ur =~ /^\Ajdbc:/ ? ur : "jdbc:#{ur}"
|
|
265
274
|
end
|
|
266
275
|
|
|
267
|
-
#
|
|
268
|
-
def
|
|
269
|
-
|
|
276
|
+
# All views in this database
|
|
277
|
+
def views(opts={})
|
|
278
|
+
get_tables('VIEW', opts)
|
|
270
279
|
end
|
|
271
|
-
|
|
280
|
+
|
|
272
281
|
private
|
|
273
282
|
|
|
274
283
|
# Close given adapter connections
|
|
@@ -325,6 +334,12 @@ module Sequel
|
|
|
325
334
|
end
|
|
326
335
|
end
|
|
327
336
|
|
|
337
|
+
# Gets the connection from JNDI.
|
|
338
|
+
def get_connection_from_jndi
|
|
339
|
+
jndi_name = JNDI_URI_REGEXP.match(uri)[1]
|
|
340
|
+
JavaxNaming::InitialContext.new.lookup(jndi_name).connection
|
|
341
|
+
end
|
|
342
|
+
|
|
328
343
|
# Gets the JDBC connection uri from the JNDI resource.
|
|
329
344
|
def get_uri_from_jndi
|
|
330
345
|
conn = get_connection_from_jndi
|
|
@@ -333,12 +348,14 @@ module Sequel
|
|
|
333
348
|
conn.close if conn
|
|
334
349
|
end
|
|
335
350
|
|
|
336
|
-
#
|
|
337
|
-
def
|
|
338
|
-
|
|
339
|
-
|
|
351
|
+
# Backbone of the tables and views support.
|
|
352
|
+
def get_tables(type, opts)
|
|
353
|
+
ts = []
|
|
354
|
+
m = output_identifier_meth
|
|
355
|
+
metadata(:getTables, nil, nil, nil, [type].to_java(:string)){|h| ts << m.call(h[:table_name])}
|
|
356
|
+
ts
|
|
340
357
|
end
|
|
341
|
-
|
|
358
|
+
|
|
342
359
|
# Support Date objects used in bound variables
|
|
343
360
|
def java_sql_date(date)
|
|
344
361
|
java.sql.Date.new(Time.local(date.year, date.month, date.day).to_i * 1000)
|
|
@@ -444,9 +461,11 @@ module Sequel
|
|
|
444
461
|
table = im.call(table)
|
|
445
462
|
pks, ts = [], []
|
|
446
463
|
metadata(:getPrimaryKeys, nil, schema, table) do |h|
|
|
464
|
+
next if h[:table_schem] == 'INFORMATION_SCHEMA'
|
|
447
465
|
pks << h[:column_name]
|
|
448
466
|
end
|
|
449
467
|
metadata(:getColumns, nil, schema, table, nil) do |h|
|
|
468
|
+
next if h[:table_schem] == 'INFORMATION_SCHEMA'
|
|
450
469
|
s = {:type=>schema_column_type(h[:type_name]), :db_type=>h[:type_name], :default=>(h[:column_def] == '' ? nil : h[:column_def]), :allow_null=>(h[:nullable] != 0), :primary_key=>pks.include?(h[:column_name]), :column_size=>h[:column_size], :scale=>h[:decimal_digits]}
|
|
451
470
|
if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
|
|
452
471
|
s[:type] = :integer
|
|
@@ -530,8 +549,8 @@ module Sequel
|
|
|
530
549
|
# Uses the database's setting by default, can be set to false to roughly
|
|
531
550
|
# double performance when fetching rows.
|
|
532
551
|
attr_accessor :convert_types
|
|
533
|
-
|
|
534
|
-
# Use the convert_types default setting from the database
|
|
552
|
+
|
|
553
|
+
# Use the convert_types default setting from the database.
|
|
535
554
|
def initialize(db, opts={})
|
|
536
555
|
@convert_types = db.convert_types
|
|
537
556
|
super
|
data/lib/sequel/adapters/odbc.rb
CHANGED
|
@@ -15,6 +15,7 @@ module Sequel
|
|
|
15
15
|
when 'mssql'
|
|
16
16
|
Sequel.ts_require 'adapters/odbc/mssql'
|
|
17
17
|
extend Sequel::ODBC::MSSQL::DatabaseMethods
|
|
18
|
+
set_mssql_unicode_strings
|
|
18
19
|
when 'progress'
|
|
19
20
|
Sequel.ts_require 'adapters/shared/progress'
|
|
20
21
|
extend Sequel::Progress::DatabaseMethods
|
|
@@ -116,6 +117,7 @@ module Sequel
|
|
|
116
117
|
when ::ODBC::TimeStamp
|
|
117
118
|
Sequel.database_to_application_timestamp([v.year, v.month, v.day, v.hour, v.minute, v.second])
|
|
118
119
|
when ::ODBC::Time
|
|
120
|
+
now = ::Time.now
|
|
119
121
|
Sequel.database_to_application_timestamp([now.year, now.month, now.day, v.hour, v.minute, v.second])
|
|
120
122
|
when ::ODBC::Date
|
|
121
123
|
Date.new(v.year, v.month, v.day)
|
|
@@ -24,6 +24,18 @@ module Sequel
|
|
|
24
24
|
conn = OCI8.new(opts[:user], opts[:password], dbname, opts[:privilege])
|
|
25
25
|
conn.autocommit = true
|
|
26
26
|
conn.non_blocking = true
|
|
27
|
+
|
|
28
|
+
# The ruby-oci8 gem which retrieves oracle columns with a type of
|
|
29
|
+
# DATE, TIMESTAMP, TIMESTAMP WITH TIME ZONE is complex based on the
|
|
30
|
+
# ruby version (1.9.2 or later) and Oracle version (9 or later)
|
|
31
|
+
# In the now standard case of 1.9.2 and Oracle 9 or later, the timezone
|
|
32
|
+
# is determined by the Oracle session timezone. Thus if the user
|
|
33
|
+
# requests Sequel provide UTC timezone to the application,
|
|
34
|
+
# we need to alter the session timezone to be UTC
|
|
35
|
+
if Sequel.application_timezone == :utc
|
|
36
|
+
conn.exec("ALTER SESSION SET TIME_ZONE='-00:00'")
|
|
37
|
+
end
|
|
38
|
+
|
|
27
39
|
conn
|
|
28
40
|
end
|
|
29
41
|
|
|
@@ -100,6 +100,11 @@ module Sequel
|
|
|
100
100
|
def timestamp(s) ::Sequel.database_to_application_timestamp(s) end
|
|
101
101
|
end.new
|
|
102
102
|
|
|
103
|
+
# Hash with type name symbols and callable values for converting PostgreSQL types.
|
|
104
|
+
# Non-builtin types that don't have fixed numbers should use this to register
|
|
105
|
+
# conversion procs.
|
|
106
|
+
PG_NAMED_TYPES = {}
|
|
107
|
+
|
|
103
108
|
# Hash with integer keys and callable values for converting PostgreSQL types.
|
|
104
109
|
PG_TYPES = {}
|
|
105
110
|
{
|
|
@@ -194,6 +199,10 @@ module Sequel
|
|
|
194
199
|
include Sequel::Postgres::DatabaseMethods
|
|
195
200
|
|
|
196
201
|
set_adapter_scheme :postgres
|
|
202
|
+
|
|
203
|
+
# A hash of conversion procs, keyed by type integer (oid) and
|
|
204
|
+
# having callable values for the conversion proc for that type.
|
|
205
|
+
attr_reader :conversion_procs
|
|
197
206
|
|
|
198
207
|
# Add the primary_keys and primary_key_sequences instance variables,
|
|
199
208
|
# so we can get the correct return values for inserted rows.
|
|
@@ -225,6 +234,7 @@ module Sequel
|
|
|
225
234
|
end
|
|
226
235
|
conn.db = self
|
|
227
236
|
conn.apply_connection_settings
|
|
237
|
+
@conversion_procs ||= get_conversion_procs(conn)
|
|
228
238
|
conn
|
|
229
239
|
end
|
|
230
240
|
|
|
@@ -305,6 +315,19 @@ module Sequel
|
|
|
305
315
|
end
|
|
306
316
|
end
|
|
307
317
|
end
|
|
318
|
+
|
|
319
|
+
# Return the conversion procs hash to use for this database
|
|
320
|
+
def get_conversion_procs(conn)
|
|
321
|
+
procs = PG_TYPES.dup
|
|
322
|
+
conn.execute("SELECT oid, typname FROM pg_type where typtype = 'b'") do |res|
|
|
323
|
+
res.ntuples.times do |recnum|
|
|
324
|
+
if pr = PG_NAMED_TYPES[res.getvalue(recnum, 1).to_sym]
|
|
325
|
+
procs[res.getvalue(recnum, 0).to_i] ||= pr
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
procs
|
|
330
|
+
end
|
|
308
331
|
end
|
|
309
332
|
|
|
310
333
|
# Dataset class for PostgreSQL datasets that use the pg, postgres, or
|
|
@@ -372,6 +395,11 @@ module Sequel
|
|
|
372
395
|
end
|
|
373
396
|
LiteralString.new("#{prepared_arg_placeholder}#{i}#{"::#{type}" if type}")
|
|
374
397
|
end
|
|
398
|
+
|
|
399
|
+
# Always assume a prepared argument.
|
|
400
|
+
def prepared_arg?(k)
|
|
401
|
+
true
|
|
402
|
+
end
|
|
375
403
|
end
|
|
376
404
|
|
|
377
405
|
# Allow use of bind arguments for PostgreSQL using the pg driver.
|
|
@@ -483,8 +511,9 @@ module Sequel
|
|
|
483
511
|
# field numers, type conversion procs, and name symbol arrays.
|
|
484
512
|
def fetch_rows_set_cols(res)
|
|
485
513
|
cols = []
|
|
514
|
+
procs = db.conversion_procs
|
|
486
515
|
res.nfields.times do |fieldnum|
|
|
487
|
-
cols << [fieldnum,
|
|
516
|
+
cols << [fieldnum, procs[res.ftype(fieldnum)], output_identifier(res.fname(fieldnum))]
|
|
488
517
|
end
|
|
489
518
|
@columns = cols.map{|c| c.at(2)}
|
|
490
519
|
cols
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
module Access
|
|
3
3
|
module DatabaseMethods
|
|
4
|
+
# Access uses type :access as the database_type
|
|
4
5
|
def database_type
|
|
5
6
|
:access
|
|
6
7
|
end
|
|
@@ -16,6 +17,7 @@ module Sequel
|
|
|
16
17
|
from(:MSysObjects).filter(:Type=>1, :Flags=>0).select_map(:Name).map{|x| x.to_sym}
|
|
17
18
|
end
|
|
18
19
|
|
|
20
|
+
# Access uses type Counter for an autoincrementing keys
|
|
19
21
|
def serial_primary_key_options
|
|
20
22
|
{:primary_key => true, :type=>:Counter}
|
|
21
23
|
end
|
|
@@ -34,16 +36,24 @@ module Sequel
|
|
|
34
36
|
module DatasetMethods
|
|
35
37
|
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'limit distinct columns from join where group order having compounds')
|
|
36
38
|
|
|
39
|
+
# Access doesn't support INTERSECT or EXCEPT
|
|
37
40
|
def supports_intersect_except?
|
|
38
41
|
false
|
|
39
42
|
end
|
|
40
43
|
|
|
41
44
|
private
|
|
42
45
|
|
|
46
|
+
# Access uses TOP for limits
|
|
47
|
+
def select_limit_sql(sql)
|
|
48
|
+
sql << " TOP #{@opts[:limit]}" if @opts[:limit]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Access uses [] for quoting identifiers
|
|
43
52
|
def quoted_identifier(v)
|
|
44
53
|
"[#{v}]"
|
|
45
54
|
end
|
|
46
55
|
|
|
56
|
+
# Access requires the limit clause come before other clauses
|
|
47
57
|
def select_clause_methods
|
|
48
58
|
SELECT_CLAUSE_METHODS
|
|
49
59
|
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Sequel
|
|
2
|
+
module Informix
|
|
3
|
+
module DatabaseMethods
|
|
4
|
+
TEMPORARY = 'TEMP '.freeze
|
|
5
|
+
|
|
6
|
+
# Informix uses the :informix database type
|
|
7
|
+
def database_type
|
|
8
|
+
:informix
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
# Informix has issues with quoted identifiers, so
|
|
14
|
+
# turn off database quoting by default.
|
|
15
|
+
def quote_identifiers_default
|
|
16
|
+
false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# SQL fragment for showing a table is temporary
|
|
20
|
+
def temporary_table_sql
|
|
21
|
+
TEMPORARY
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module DatasetMethods
|
|
26
|
+
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'limit distinct columns from join where having group compounds order')
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# Informix does not support INTERSECT or EXCEPT
|
|
31
|
+
def supports_intersect_except?
|
|
32
|
+
false
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def select_clause_methods
|
|
36
|
+
SELECT_CLAUSE_METHODS
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def select_limit_sql(sql)
|
|
40
|
+
sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
|
|
41
|
+
sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|