sequel 4.12.0 → 4.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +64 -0
- data/Rakefile +3 -1
- data/bin/sequel +13 -5
- data/doc/release_notes/4.13.0.txt +169 -0
- data/doc/sql.rdoc +3 -3
- data/lib/sequel/adapters/do.rb +11 -23
- data/lib/sequel/adapters/do/mysql.rb +8 -0
- data/lib/sequel/adapters/do/postgres.rb +8 -0
- data/lib/sequel/adapters/do/{sqlite.rb → sqlite3.rb} +9 -0
- data/lib/sequel/adapters/jdbc.rb +16 -139
- data/lib/sequel/adapters/jdbc/as400.rb +9 -0
- data/lib/sequel/adapters/jdbc/cubrid.rb +9 -0
- data/lib/sequel/adapters/jdbc/db2.rb +9 -0
- data/lib/sequel/adapters/jdbc/derby.rb +9 -0
- data/lib/sequel/adapters/jdbc/{firebird.rb → firebirdsql.rb} +9 -0
- data/lib/sequel/adapters/jdbc/h2.rb +10 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +9 -0
- data/lib/sequel/adapters/jdbc/{informix.rb → informix-sqli.rb} +9 -0
- data/lib/sequel/adapters/jdbc/{progress.rb → jdbcprogress.rb} +9 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +10 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +14 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +9 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -0
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +23 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +10 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -0
- data/lib/sequel/adapters/odbc.rb +6 -14
- data/lib/sequel/adapters/odbc/db2.rb +9 -0
- data/lib/sequel/adapters/odbc/mssql.rb +8 -0
- data/lib/sequel/adapters/odbc/progress.rb +8 -0
- data/lib/sequel/adapters/oracle.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +1 -1
- data/lib/sequel/adapters/shared/firebird.rb +8 -1
- data/lib/sequel/adapters/shared/mssql.rb +68 -27
- data/lib/sequel/adapters/shared/mysql.rb +3 -5
- data/lib/sequel/adapters/shared/oracle.rb +17 -3
- data/lib/sequel/adapters/shared/postgres.rb +9 -4
- data/lib/sequel/adapters/shared/sqlanywhere.rb +6 -6
- data/lib/sequel/database/connecting.rb +38 -17
- data/lib/sequel/dataset/actions.rb +6 -2
- data/lib/sequel/dataset/graph.rb +18 -20
- data/lib/sequel/dataset/misc.rb +37 -0
- data/lib/sequel/dataset/prepared_statements.rb +1 -2
- data/lib/sequel/dataset/query.rb +1 -0
- data/lib/sequel/dataset/sql.rb +17 -10
- data/lib/sequel/extensions/dataset_source_alias.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +14 -10
- data/lib/sequel/extensions/pg_enum.rb +135 -0
- data/lib/sequel/extensions/pg_hstore.rb +4 -6
- data/lib/sequel/extensions/pg_inet.rb +4 -5
- data/lib/sequel/extensions/pg_interval.rb +3 -3
- data/lib/sequel/extensions/pg_json.rb +16 -12
- data/lib/sequel/extensions/pg_range.rb +5 -3
- data/lib/sequel/extensions/pg_row.rb +2 -2
- data/lib/sequel/extensions/round_timestamps.rb +52 -0
- data/lib/sequel/model.rb +5 -2
- data/lib/sequel/model/associations.rb +29 -3
- data/lib/sequel/model/base.rb +68 -29
- data/lib/sequel/plugins/class_table_inheritance.rb +25 -16
- data/lib/sequel/plugins/column_select.rb +57 -0
- data/lib/sequel/plugins/composition.rb +14 -16
- data/lib/sequel/plugins/dirty.rb +9 -11
- data/lib/sequel/plugins/insert_returning_select.rb +70 -0
- data/lib/sequel/plugins/instance_filters.rb +7 -9
- data/lib/sequel/plugins/lazy_attributes.rb +16 -4
- data/lib/sequel/plugins/list.rb +9 -0
- data/lib/sequel/plugins/modification_detection.rb +90 -0
- data/lib/sequel/plugins/serialization.rb +13 -15
- data/lib/sequel/plugins/serialization_modification_detection.rb +9 -9
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/timestamps.rb +6 -6
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +7 -0
- data/spec/adapters/postgres_spec.rb +41 -0
- data/spec/bin_spec.rb +4 -1
- data/spec/core/database_spec.rb +6 -0
- data/spec/core/dataset_spec.rb +100 -90
- data/spec/core/object_graph_spec.rb +5 -0
- data/spec/extensions/class_table_inheritance_spec.rb +18 -13
- data/spec/extensions/column_select_spec.rb +108 -0
- data/spec/extensions/composition_spec.rb +20 -0
- data/spec/extensions/dataset_source_alias_spec.rb +51 -0
- data/spec/extensions/insert_returning_select_spec.rb +46 -0
- data/spec/extensions/lazy_attributes_spec.rb +24 -20
- data/spec/extensions/list_spec.rb +5 -0
- data/spec/extensions/modification_detection_spec.rb +80 -0
- data/spec/extensions/pg_enum_spec.rb +64 -0
- data/spec/extensions/pg_json_spec.rb +7 -13
- data/spec/extensions/prepared_statements_spec.rb +6 -4
- data/spec/extensions/round_timestamps_spec.rb +43 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +10 -1
- data/spec/extensions/serialization_spec.rb +18 -0
- data/spec/extensions/single_table_inheritance_spec.rb +5 -0
- data/spec/extensions/timestamps_spec.rb +6 -0
- data/spec/integration/plugin_test.rb +14 -8
- data/spec/integration/prepared_statement_test.rb +12 -0
- data/spec/model/associations_spec.rb +24 -0
- data/spec/model/model_spec.rb +13 -3
- data/spec/model/record_spec.rb +24 -1
- metadata +22 -6
@@ -1,8 +1,17 @@
|
|
1
|
+
Sequel::JDBC.load_driver('com.ibm.as400.access.AS400JDBCDriver')
|
1
2
|
Sequel.require 'adapters/jdbc/transactions'
|
2
3
|
Sequel.require 'adapters/utils/emulate_offset_with_row_number'
|
3
4
|
|
4
5
|
module Sequel
|
5
6
|
module JDBC
|
7
|
+
Sequel.synchronize do
|
8
|
+
DATABASE_SETUP[:as400] = proc do |db|
|
9
|
+
db.extend(Sequel::JDBC::AS400::DatabaseMethods)
|
10
|
+
db.dataset_class = Sequel::JDBC::AS400::Dataset
|
11
|
+
com.ibm.as400.access.AS400JDBCDriver
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
6
15
|
# Database and Dataset support for AS400 databases accessed via JDBC.
|
7
16
|
module AS400
|
8
17
|
# Instance methods for AS400 Database objects accessed via JDBC.
|
@@ -1,8 +1,17 @@
|
|
1
|
+
Sequel::JDBC.load_driver('Java::cubrid.jdbc.driver.CUBRIDDriver')
|
1
2
|
Sequel.require 'adapters/shared/cubrid'
|
2
3
|
Sequel.require 'adapters/jdbc/transactions'
|
3
4
|
|
4
5
|
module Sequel
|
5
6
|
module JDBC
|
7
|
+
Sequel.synchronize do
|
8
|
+
DATABASE_SETUP[:cubrid] = proc do |db|
|
9
|
+
db.extend(Sequel::JDBC::Cubrid::DatabaseMethods)
|
10
|
+
db.extend_datasets Sequel::Cubrid::DatasetMethods
|
11
|
+
Java::cubrid.jdbc.driver.CUBRIDDriver
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
6
15
|
module Cubrid
|
7
16
|
module DatabaseMethods
|
8
17
|
extend Sequel::Database::ResetIdentifierMangling
|
@@ -1,8 +1,17 @@
|
|
1
|
+
Sequel::JDBC.load_driver('com.ibm.db2.jcc.DB2Driver')
|
1
2
|
Sequel.require 'adapters/shared/db2'
|
2
3
|
Sequel.require 'adapters/jdbc/transactions'
|
3
4
|
|
4
5
|
module Sequel
|
5
6
|
module JDBC
|
7
|
+
Sequel.synchronize do
|
8
|
+
DATABASE_SETUP[:db2] = proc do |db|
|
9
|
+
db.extend(Sequel::JDBC::DB2::DatabaseMethods)
|
10
|
+
db.dataset_class = Sequel::JDBC::DB2::Dataset
|
11
|
+
com.ibm.db2.jcc.DB2Driver
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
6
15
|
class TypeConvertor
|
7
16
|
def DB2Clob(r, i)
|
8
17
|
if v = r.getClob(i)
|
@@ -1,7 +1,16 @@
|
|
1
|
+
Sequel::JDBC.load_driver('org.apache.derby.jdbc.EmbeddedDriver', :Derby)
|
1
2
|
Sequel.require 'adapters/jdbc/transactions'
|
2
3
|
|
3
4
|
module Sequel
|
4
5
|
module JDBC
|
6
|
+
Sequel.synchronize do
|
7
|
+
DATABASE_SETUP[:derby] = proc do |db|
|
8
|
+
db.extend(Sequel::JDBC::Derby::DatabaseMethods)
|
9
|
+
db.dataset_class = Sequel::JDBC::Derby::Dataset
|
10
|
+
org.apache.derby.jdbc.EmbeddedDriver
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
# Database and Dataset support for Derby databases accessed via JDBC.
|
6
15
|
module Derby
|
7
16
|
# Instance methods for Derby Database objects accessed via JDBC.
|
@@ -1,8 +1,17 @@
|
|
1
|
+
Sequel::JDBC.load_driver('org.firebirdsql.jdbc.FBDriver')
|
1
2
|
Sequel.require 'adapters/shared/firebird'
|
2
3
|
Sequel.require 'adapters/jdbc/transactions'
|
3
4
|
|
4
5
|
module Sequel
|
5
6
|
module JDBC
|
7
|
+
Sequel.synchronize do
|
8
|
+
DATABASE_SETUP[:firebirdsql] = proc do |db|
|
9
|
+
db.extend(Sequel::JDBC::Firebird::DatabaseMethods)
|
10
|
+
db.extend_datasets Sequel::Firebird::DatasetMethods
|
11
|
+
org.firebirdsql.jdbc.FBDriver
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
6
15
|
# Database and Dataset instance methods for Firebird specific
|
7
16
|
# support via JDBC.
|
8
17
|
module Firebird
|
@@ -1,5 +1,15 @@
|
|
1
|
+
Sequel::JDBC.load_driver('org.h2.Driver', :H2)
|
2
|
+
|
1
3
|
module Sequel
|
2
4
|
module JDBC
|
5
|
+
Sequel.synchronize do
|
6
|
+
DATABASE_SETUP[:h2] = proc do |db|
|
7
|
+
db.extend(Sequel::JDBC::H2::DatabaseMethods)
|
8
|
+
db.dataset_class = Sequel::JDBC::H2::Dataset
|
9
|
+
org.h2.Driver
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
3
13
|
# Database and Dataset support for H2 databases accessed via JDBC.
|
4
14
|
module H2
|
5
15
|
# Instance methods for H2 Database objects accessed via JDBC.
|
@@ -1,7 +1,16 @@
|
|
1
|
+
Sequel::JDBC.load_driver('org.hsqldb.jdbcDriver', :HSQLDB)
|
1
2
|
Sequel.require 'adapters/jdbc/transactions'
|
2
3
|
|
3
4
|
module Sequel
|
4
5
|
module JDBC
|
6
|
+
Sequel.synchronize do
|
7
|
+
DATABASE_SETUP[:hsqldb] = proc do |db|
|
8
|
+
db.extend(Sequel::JDBC::HSQLDB::DatabaseMethods)
|
9
|
+
db.dataset_class = Sequel::JDBC::HSQLDB::Dataset
|
10
|
+
org.hsqldb.jdbcDriver
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
# Database and Dataset support for HSQLDB databases accessed via JDBC.
|
6
15
|
module HSQLDB
|
7
16
|
# Instance methods for HSQLDB Database objects accessed via JDBC.
|
@@ -1,7 +1,16 @@
|
|
1
|
+
Sequel::JDBC.load_driver('com.informix.jdbc.IfxDriver')
|
1
2
|
Sequel.require 'adapters/shared/informix'
|
2
3
|
|
3
4
|
module Sequel
|
4
5
|
module JDBC
|
6
|
+
Sequel.synchronize do
|
7
|
+
DATABASE_SETUP[:"informix-sqli"] = proc do |db|
|
8
|
+
db.extend(Sequel::JDBC::Informix::DatabaseMethods)
|
9
|
+
db.extend_datasets Sequel::Informix::DatasetMethods
|
10
|
+
com.informix.jdbc.IfxDriver
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
# Database and Dataset instance methods for Informix specific
|
6
15
|
# support via JDBC.
|
7
16
|
module Informix
|
@@ -1,8 +1,17 @@
|
|
1
|
+
Sequel::JDBC.load_driver('com.progress.sql.jdbc.JdbcProgressDriver')
|
1
2
|
Sequel.require 'adapters/shared/progress'
|
2
3
|
Sequel.require 'adapters/jdbc/transactions'
|
3
4
|
|
4
5
|
module Sequel
|
5
6
|
module JDBC
|
7
|
+
Sequel.synchronize do
|
8
|
+
DATABASE_SETUP[:jdbcprogress] = proc do |db|
|
9
|
+
db.extend(Sequel::JDBC::Progress::DatabaseMethods)
|
10
|
+
db.extend_datasets Sequel::Progress::DatasetMethods
|
11
|
+
com.progress.sql.jdbc.JdbcProgressDriver
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
6
15
|
# Database and Dataset instance methods for Progress v9 specific
|
7
16
|
# support via JDBC.
|
8
17
|
module Progress
|
@@ -1,7 +1,17 @@
|
|
1
|
+
Sequel::JDBC.load_driver('Java::net.sourceforge.jtds.jdbc.Driver', :JTDS)
|
1
2
|
Sequel.require 'adapters/jdbc/mssql'
|
2
3
|
|
3
4
|
module Sequel
|
4
5
|
module JDBC
|
6
|
+
Sequel.synchronize do
|
7
|
+
DATABASE_SETUP[:jtds] = proc do |db|
|
8
|
+
db.extend(Sequel::JDBC::JTDS::DatabaseMethods)
|
9
|
+
db.dataset_class = Sequel::JDBC::JTDS::Dataset
|
10
|
+
db.send(:set_mssql_unicode_strings)
|
11
|
+
Java::net.sourceforge.jtds.jdbc.Driver
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
5
15
|
# Database and Dataset instance methods for JTDS specific
|
6
16
|
# support via JDBC.
|
7
17
|
module JTDS
|
@@ -1,7 +1,16 @@
|
|
1
|
+
Sequel::JDBC.load_driver('com.mysql.jdbc.Driver', :MySQL)
|
1
2
|
Sequel.require 'adapters/shared/mysql'
|
2
3
|
|
3
4
|
module Sequel
|
4
5
|
module JDBC
|
6
|
+
Sequel.synchronize do
|
7
|
+
DATABASE_SETUP[:mysql] = proc do |db|
|
8
|
+
db.extend(Sequel::JDBC::MySQL::DatabaseMethods)
|
9
|
+
db.extend_datasets Sequel::MySQL::DatasetMethods
|
10
|
+
com.mysql.jdbc.Driver
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
# Database and Dataset instance methods for MySQL specific
|
6
15
|
# support via JDBC.
|
7
16
|
module MySQL
|
@@ -26,6 +35,11 @@ module Sequel
|
|
26
35
|
false
|
27
36
|
end
|
28
37
|
|
38
|
+
# Raise a disconnect error if the SQL state of the cause of the exception indicates so.
|
39
|
+
def disconnect_error?(exception, opts)
|
40
|
+
exception.message =~ /\ACommunications link failure/ || super
|
41
|
+
end
|
42
|
+
|
29
43
|
# Get the last inserted id using LAST_INSERT_ID().
|
30
44
|
def last_insert_id(conn, opts=OPTS)
|
31
45
|
if stmt = opts[:stmt]
|
@@ -1,8 +1,17 @@
|
|
1
|
+
Sequel::JDBC.load_driver('Java::oracle.jdbc.driver.OracleDriver')
|
1
2
|
Sequel.require 'adapters/shared/oracle'
|
2
3
|
Sequel.require 'adapters/jdbc/transactions'
|
3
4
|
|
4
5
|
module Sequel
|
5
6
|
module JDBC
|
7
|
+
Sequel.synchronize do
|
8
|
+
DATABASE_SETUP[:oracle] = proc do |db|
|
9
|
+
db.extend(Sequel::JDBC::Oracle::DatabaseMethods)
|
10
|
+
db.dataset_class = Sequel::JDBC::Oracle::Dataset
|
11
|
+
Java::oracle.jdbc.driver.OracleDriver
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
6
15
|
class TypeConvertor
|
7
16
|
JAVA_BIG_DECIMAL_CONSTRUCTOR = java.math.BigDecimal.java_class.constructor(Java::long).method(:new_instance)
|
8
17
|
|
@@ -1,9 +1,18 @@
|
|
1
|
+
Sequel::JDBC.load_driver('org.postgresql.Driver', :Postgres)
|
1
2
|
Sequel.require 'adapters/shared/postgres'
|
2
3
|
|
3
4
|
module Sequel
|
4
5
|
Postgres::CONVERTED_EXCEPTIONS << NativeException
|
5
6
|
|
6
7
|
module JDBC
|
8
|
+
Sequel.synchronize do
|
9
|
+
DATABASE_SETUP[:postgresql] = proc do |db|
|
10
|
+
db.extend(Sequel::JDBC::Postgres::DatabaseMethods)
|
11
|
+
db.dataset_class = Sequel::JDBC::Postgres::Dataset
|
12
|
+
org.postgresql.Driver
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
7
16
|
class TypeConvertor
|
8
17
|
# Return PostgreSQL array types as ruby Arrays instead of
|
9
18
|
# JDBC PostgreSQL driver-specific array type. Only used if the
|
@@ -3,6 +3,29 @@ Sequel.require 'adapters/jdbc/transactions'
|
|
3
3
|
|
4
4
|
module Sequel
|
5
5
|
module JDBC
|
6
|
+
drv = [
|
7
|
+
lambda{Java::sybase.jdbc4.sqlanywhere.IDriver},
|
8
|
+
lambda{Java::ianywhere.ml.jdbcodbc.jdbc4.IDriver},
|
9
|
+
lambda{Java::sybase.jdbc.sqlanywhere.IDriver},
|
10
|
+
lambda{Java::ianywhere.ml.jdbcodbc.jdbc.IDriver},
|
11
|
+
lambda{Java::com.sybase.jdbc4.jdbc.Sybdriver},
|
12
|
+
lambda{Java::com.sybase.jdbc3.jdbc.Sybdriver}
|
13
|
+
].each do |class_proc|
|
14
|
+
begin
|
15
|
+
break class_proc.call
|
16
|
+
rescue NameError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
raise(Sequel::AdapterNotFound, "no suitable SQLAnywhere JDBC driver found") unless drv
|
20
|
+
|
21
|
+
Sequel.synchronize do
|
22
|
+
DATABASE_SETUP[:sqlanywhere] = proc do |db|
|
23
|
+
db.extend(Sequel::JDBC::SqlAnywhere::DatabaseMethods)
|
24
|
+
db.dataset_class = Sequel::JDBC::SqlAnywhere::Dataset
|
25
|
+
drv
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
6
29
|
class TypeConvertor
|
7
30
|
def SqlAnywhereBoolean(r, i)
|
8
31
|
if v = Short(r, i)
|
@@ -1,7 +1,17 @@
|
|
1
|
+
Sequel::JDBC.load_driver('org.sqlite.JDBC', :SQLite3)
|
1
2
|
Sequel.require 'adapters/shared/sqlite'
|
2
3
|
|
3
4
|
module Sequel
|
4
5
|
module JDBC
|
6
|
+
Sequel.synchronize do
|
7
|
+
DATABASE_SETUP[:sqlite] = proc do |db|
|
8
|
+
db.extend(Sequel::JDBC::SQLite::DatabaseMethods)
|
9
|
+
db.extend_datasets Sequel::SQLite::DatasetMethods
|
10
|
+
db.set_integer_booleans
|
11
|
+
org.sqlite.JDBC
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
5
15
|
# Database and Dataset support for SQLite databases accessed via JDBC.
|
6
16
|
module SQLite
|
7
17
|
# Instance methods for SQLite Database objects accessed via JDBC.
|
@@ -1,7 +1,17 @@
|
|
1
|
+
Sequel::JDBC.load_driver('com.microsoft.sqlserver.jdbc.SQLServerDriver')
|
1
2
|
Sequel.require 'adapters/jdbc/mssql'
|
2
3
|
|
3
4
|
module Sequel
|
4
5
|
module JDBC
|
6
|
+
Sequel.synchronize do
|
7
|
+
DATABASE_SETUP[:sqlserver] = proc do |db|
|
8
|
+
db.extend(Sequel::JDBC::SQLServer::DatabaseMethods)
|
9
|
+
db.extend_datasets Sequel::MSSQL::DatasetMethods
|
10
|
+
db.send(:set_mssql_unicode_strings)
|
11
|
+
com.microsoft.sqlserver.jdbc.SQLServerDriver
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
5
15
|
# Database and Dataset instance methods for SQLServer specific
|
6
16
|
# support via JDBC.
|
7
17
|
module SQLServer
|
data/lib/sequel/adapters/odbc.rb
CHANGED
@@ -2,6 +2,10 @@ require 'odbc'
|
|
2
2
|
|
3
3
|
module Sequel
|
4
4
|
module ODBC
|
5
|
+
# Contains procs keyed on subadapter type that extend the
|
6
|
+
# given database object so it supports the correct database type.
|
7
|
+
DATABASE_SETUP = {}
|
8
|
+
|
5
9
|
class Database < Sequel::Database
|
6
10
|
set_adapter_scheme :odbc
|
7
11
|
|
@@ -61,20 +65,8 @@ module Sequel
|
|
61
65
|
private
|
62
66
|
|
63
67
|
def adapter_initialize
|
64
|
-
|
65
|
-
|
66
|
-
Sequel.require 'adapters/odbc/mssql'
|
67
|
-
extend Sequel::ODBC::MSSQL::DatabaseMethods
|
68
|
-
self.dataset_class = Sequel::ODBC::MSSQL::Dataset
|
69
|
-
set_mssql_unicode_strings
|
70
|
-
when 'progress'
|
71
|
-
Sequel.require 'adapters/shared/progress'
|
72
|
-
extend Sequel::Progress::DatabaseMethods
|
73
|
-
extend_datasets(Sequel::Progress::DatasetMethods)
|
74
|
-
when 'db2'
|
75
|
-
Sequel.require 'adapters/shared/db2'
|
76
|
-
extend ::Sequel::DB2::DatabaseMethods
|
77
|
-
extend_datasets ::Sequel::DB2::DatasetMethods
|
68
|
+
if (db_type = @opts[:db_type]) && (prok = Sequel::Database.load_adapter(db_type.to_sym, :map=>DATABASE_SETUP, :subdir=>'odbc'))
|
69
|
+
prok.call(self)
|
78
70
|
end
|
79
71
|
end
|
80
72
|
|
@@ -2,6 +2,14 @@ Sequel.require 'adapters/shared/mssql'
|
|
2
2
|
|
3
3
|
module Sequel
|
4
4
|
module ODBC
|
5
|
+
Sequel.synchronize do
|
6
|
+
DATABASE_SETUP[:mssql] = proc do |db|
|
7
|
+
db.extend Sequel::ODBC::MSSQL::DatabaseMethods
|
8
|
+
db.dataset_class = Sequel::ODBC::MSSQL::Dataset
|
9
|
+
db.send(:set_mssql_unicode_strings)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
5
13
|
# Database and Dataset instance methods for MSSQL specific
|
6
14
|
# support via ODBC.
|
7
15
|
module MSSQL
|
@@ -108,7 +108,7 @@ module Sequel
|
|
108
108
|
# PGconn subclass for connection specific methods used with the
|
109
109
|
# pg, postgres, or postgres-pr driver.
|
110
110
|
class Adapter < ::PGconn
|
111
|
-
DISCONNECT_ERROR_RE = /\A(?:could not receive data from server|no connection to the server|connection not open)/
|
111
|
+
DISCONNECT_ERROR_RE = /\A(?:could not receive data from server|no connection to the server|connection not open|terminating connection due to administrator command)/
|
112
112
|
|
113
113
|
self.translate_results = false if respond_to?(:translate_results=)
|
114
114
|
|
@@ -175,7 +175,14 @@ module Sequel
|
|
175
175
|
|
176
176
|
# Insert a record returning the record inserted
|
177
177
|
def insert_select(*values)
|
178
|
-
|
178
|
+
with_sql_first(insert_select_sql(*values))
|
179
|
+
end
|
180
|
+
|
181
|
+
# The SQL to use for an insert_select, adds a RETURNING clause to the insert
|
182
|
+
# unless the RETURNING clause is already present.
|
183
|
+
def insert_select_sql(*values)
|
184
|
+
ds = opts[:returning] ? self : returning
|
185
|
+
ds.insert_sql(*values)
|
179
186
|
end
|
180
187
|
|
181
188
|
def requires_sql_standard_datetimes?
|
@@ -525,7 +525,6 @@ module Sequel
|
|
525
525
|
DATEPART_SECOND_MIDDLE = ') + datepart(ns, '.freeze
|
526
526
|
DATEPART_SECOND_CLOSE = ")/1000000000.0) AS double precision)".freeze
|
527
527
|
DATEPART_OPEN = "datepart(".freeze
|
528
|
-
TIMESTAMP_USEC_FORMAT = ".%03d".freeze
|
529
528
|
OUTPUT_INSERTED = " OUTPUT INSERTED.*".freeze
|
530
529
|
HEX_START = '0x'.freeze
|
531
530
|
UNICODE_STRING_START = "N'".freeze
|
@@ -624,7 +623,14 @@ module Sequel
|
|
624
623
|
# Use the OUTPUT clause to get the value of all columns for the newly inserted record.
|
625
624
|
def insert_select(*values)
|
626
625
|
return unless supports_insert_select?
|
627
|
-
|
626
|
+
with_sql_first(insert_select_sql(*values))
|
627
|
+
end
|
628
|
+
|
629
|
+
# Add OUTPUT clause unless there is already an existing output clause, then return
|
630
|
+
# the SQL to insert.
|
631
|
+
def insert_select_sql(*values)
|
632
|
+
ds = (opts[:output] || opts[:returning]) ? self : output(nil, [SQL::ColumnAll.new(:inserted)])
|
633
|
+
ds.insert_sql(*values)
|
628
634
|
end
|
629
635
|
|
630
636
|
# Specify a table for a SELECT ... INTO query.
|
@@ -658,20 +664,31 @@ module Sequel
|
|
658
664
|
raise(Error, "SQL Server versions 2000 and earlier do not support the OUTPUT clause") unless supports_output_clause?
|
659
665
|
output = {}
|
660
666
|
case values
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
667
|
+
when Hash
|
668
|
+
output[:column_list], output[:select_list] = values.keys, values.values
|
669
|
+
when Array
|
670
|
+
output[:select_list] = values
|
665
671
|
end
|
666
672
|
output[:into] = into
|
667
|
-
clone(
|
673
|
+
clone(:output => output)
|
668
674
|
end
|
669
675
|
|
670
676
|
# MSSQL uses [] to quote identifiers.
|
671
677
|
def quoted_identifier_append(sql, name)
|
672
678
|
sql << BRACKET_OPEN << name.to_s.gsub(/\]/, DOUBLE_BRACKET_CLOSE) << BRACKET_CLOSE
|
673
679
|
end
|
674
|
-
|
680
|
+
|
681
|
+
# Emulate RETURNING using the output clause. This only handles values that are simple column references.
|
682
|
+
def returning(*values)
|
683
|
+
values = values.map do |v|
|
684
|
+
unless r = unqualified_column_for(v)
|
685
|
+
raise(Error, "cannot emulate RETURNING via OUTPUT for value: #{v.inspect}")
|
686
|
+
end
|
687
|
+
r
|
688
|
+
end
|
689
|
+
clone(:returning=>values)
|
690
|
+
end
|
691
|
+
|
675
692
|
# On MSSQL 2012+ add a default order to the current dataset if an offset is used.
|
676
693
|
# The default offset emulation using a subquery would be used in the unordered
|
677
694
|
# case by default, and that also adds a default order, so it's better to just
|
@@ -738,11 +755,16 @@ module Sequel
|
|
738
755
|
is_2012_or_later?
|
739
756
|
end
|
740
757
|
|
741
|
-
# MSSQL 2005+ supports the
|
758
|
+
# MSSQL 2005+ supports the OUTPUT clause.
|
742
759
|
def supports_output_clause?
|
743
760
|
is_2005_or_later?
|
744
761
|
end
|
745
762
|
|
763
|
+
# MSSQL 2005+ can emulate RETURNING via the OUTPUT clause.
|
764
|
+
def supports_returning?(type)
|
765
|
+
supports_insert_select?
|
766
|
+
end
|
767
|
+
|
746
768
|
# MSSQL 2005+ supports window functions
|
747
769
|
def supports_window_functions?
|
748
770
|
true
|
@@ -816,6 +838,10 @@ module Sequel
|
|
816
838
|
end
|
817
839
|
alias update_from_sql delete_from2_sql
|
818
840
|
|
841
|
+
def delete_output_sql(sql)
|
842
|
+
output_sql(sql, :DELETED)
|
843
|
+
end
|
844
|
+
|
819
845
|
# There is no function on Microsoft SQL Server that does character length
|
820
846
|
# and respects trailing spaces (datalength respects trailing spaces, but
|
821
847
|
# counts bytes instead of characters). Use a hack to work around the
|
@@ -844,22 +870,10 @@ module Sequel
|
|
844
870
|
@db.schema(self).map{|k, v| k if v[:primary_key] == true}.compact.first
|
845
871
|
end
|
846
872
|
|
847
|
-
# MSSQL raises an error if you try to provide more than 3 decimal places
|
848
|
-
# for a fractional timestamp. This probably doesn't work for smalldatetime
|
849
|
-
# fields.
|
850
|
-
def format_timestamp_usec(usec)
|
851
|
-
sprintf(TIMESTAMP_USEC_FORMAT, usec/1000)
|
852
|
-
end
|
853
|
-
|
854
|
-
# Use OUTPUT INSERTED.* to return all columns of the inserted row,
|
855
|
-
# for use with the prepared statement code.
|
856
873
|
def insert_output_sql(sql)
|
857
|
-
|
858
|
-
sql << OUTPUT_INSERTED
|
859
|
-
else
|
860
|
-
output_sql(sql)
|
861
|
-
end
|
874
|
+
output_sql(sql, :INSERTED)
|
862
875
|
end
|
876
|
+
alias update_output_sql insert_output_sql
|
863
877
|
|
864
878
|
# Handle CROSS APPLY and OUTER APPLY JOIN types
|
865
879
|
def join_type_sql(join_type)
|
@@ -964,9 +978,16 @@ module Sequel
|
|
964
978
|
end
|
965
979
|
|
966
980
|
# SQL fragment for MSSQL's OUTPUT clause.
|
967
|
-
def output_sql(sql)
|
981
|
+
def output_sql(sql, type)
|
968
982
|
return unless supports_output_clause?
|
969
|
-
|
983
|
+
if output = @opts[:output]
|
984
|
+
output_list_sql(sql, output)
|
985
|
+
elsif values = @opts[:returning]
|
986
|
+
output_returning_sql(sql, type, values)
|
987
|
+
end
|
988
|
+
end
|
989
|
+
|
990
|
+
def output_list_sql(sql, output)
|
970
991
|
sql << OUTPUT
|
971
992
|
column_list_append(sql, output[:select_list])
|
972
993
|
if into = output[:into]
|
@@ -979,8 +1000,28 @@ module Sequel
|
|
979
1000
|
end
|
980
1001
|
end
|
981
1002
|
end
|
982
|
-
|
983
|
-
|
1003
|
+
|
1004
|
+
def output_returning_sql(sql, type, values)
|
1005
|
+
sql << OUTPUT
|
1006
|
+
if values.empty?
|
1007
|
+
literal_append(sql, SQL::ColumnAll.new(type))
|
1008
|
+
else
|
1009
|
+
values = values.map do |v|
|
1010
|
+
case v
|
1011
|
+
when SQL::AliasedExpression
|
1012
|
+
Sequel.qualify(type, v.expression).as(v.alias)
|
1013
|
+
else
|
1014
|
+
Sequel.qualify(type, v)
|
1015
|
+
end
|
1016
|
+
end
|
1017
|
+
column_list_append(sql, values)
|
1018
|
+
end
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
# MSSQL supports millisecond timestamp precision.
|
1022
|
+
def timestamp_precision
|
1023
|
+
3
|
1024
|
+
end
|
984
1025
|
|
985
1026
|
# Only include the primary table in the main update clause
|
986
1027
|
def update_table_sql(sql)
|