sequel 4.12.0 → 4.13.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.
- 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)
|