sequel 3.21.0 → 3.29.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 +413 -3
- data/README.rdoc +20 -6
- data/Rakefile +23 -16
- data/bin/sequel +1 -5
- data/doc/association_basics.rdoc +210 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +86 -50
- data/doc/prepared_statements.rdoc +40 -13
- 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/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +115 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +15 -7
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +5 -31
- data/lib/sequel/adapters/jdbc/db2.rb +44 -0
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +26 -17
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +107 -38
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +78 -182
- data/lib/sequel/adapters/mysql2.rb +24 -23
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +349 -51
- data/lib/sequel/adapters/postgres.rb +169 -21
- data/lib/sequel/adapters/shared/access.rb +21 -6
- data/lib/sequel/adapters/shared/db2.rb +288 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +108 -65
- data/lib/sequel/adapters/shared/mysql.rb +56 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -34
- data/lib/sequel/adapters/shared/postgres.rb +107 -58
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +168 -41
- data/lib/sequel/adapters/sqlite.rb +27 -18
- data/lib/sequel/adapters/swift/mysql.rb +9 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +152 -17
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +46 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +100 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +194 -57
- data/lib/sequel/dataset/features.rb +81 -8
- data/lib/sequel/dataset/graph.rb +8 -7
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +32 -15
- data/lib/sequel/dataset/query.rb +223 -42
- data/lib/sequel/dataset/sql.rb +58 -61
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +997 -331
- data/lib/sequel/model/base.rb +386 -129
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +15 -8
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +65 -7
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -25
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +44 -35
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +65 -29
- data/spec/adapters/mysql_spec.rb +122 -123
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +213 -61
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +729 -508
- data/spec/core/dataset_spec.rb +980 -1044
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +4 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +522 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +375 -62
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +304 -116
- data/spec/integration/prepared_statement_test.rb +200 -120
- data/spec/integration/schema_test.rb +161 -30
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +172 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +174 -7
- data/spec/model/associations_spec.rb +849 -661
- data/spec/model/base_spec.rb +255 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +640 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +207 -167
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +321 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +95 -38
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
Sequel.require 'adapters/shared/oracle'
|
|
2
|
+
Sequel.require 'adapters/jdbc/transactions'
|
|
2
3
|
|
|
3
4
|
module Sequel
|
|
4
5
|
module JDBC
|
|
@@ -7,43 +8,84 @@ module Sequel
|
|
|
7
8
|
# Instance methods for Oracle Database objects accessed via JDBC.
|
|
8
9
|
module DatabaseMethods
|
|
9
10
|
include Sequel::Oracle::DatabaseMethods
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
include Sequel::JDBC::Transactions
|
|
12
|
+
|
|
13
|
+
def self.extended(db)
|
|
14
|
+
db.instance_eval do
|
|
15
|
+
@autosequence = opts[:autosequence]
|
|
16
|
+
@primary_key_sequences = {}
|
|
17
|
+
end
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
private
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
|
|
22
|
+
def last_insert_id(conn, opts)
|
|
23
|
+
unless sequence = opts[:sequence]
|
|
24
|
+
if t = opts[:table]
|
|
25
|
+
sequence = sequence_for_table(t)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
if sequence
|
|
29
|
+
sql = "SELECT #{literal(sequence)}.currval FROM dual"
|
|
30
|
+
statement(conn) do |stmt|
|
|
31
|
+
begin
|
|
32
|
+
rs = log_yield(sql){stmt.executeQuery(sql)}
|
|
33
|
+
rs.next
|
|
34
|
+
rs.getInt(1)
|
|
35
|
+
rescue java.sql.SQLException
|
|
36
|
+
nil
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
25
40
|
end
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
41
|
+
|
|
42
|
+
def schema_parse_table(*)
|
|
43
|
+
sch = super
|
|
44
|
+
sch.each do |c, s|
|
|
45
|
+
if s[:type] == :decimal && s[:scale] == -127
|
|
46
|
+
s[:type] = :integer
|
|
47
|
+
elsif s[:db_type] == 'DATE'
|
|
48
|
+
s[:type] = :datetime
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
sch
|
|
30
52
|
end
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
conn.setAutoCommit(true) if conn
|
|
35
|
-
@transactions.delete(Thread.current)
|
|
53
|
+
|
|
54
|
+
def schema_parse_table_skip?(h, schema)
|
|
55
|
+
super || (h[:table_schem] != current_user unless schema)
|
|
36
56
|
end
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
def
|
|
40
|
-
|
|
57
|
+
|
|
58
|
+
# As of Oracle 9.2, releasing savepoints is no longer supported.
|
|
59
|
+
def supports_releasing_savepoints?
|
|
60
|
+
false
|
|
41
61
|
end
|
|
42
62
|
end
|
|
43
63
|
|
|
44
64
|
# Dataset class for Oracle datasets accessed via JDBC.
|
|
45
65
|
class Dataset < JDBC::Dataset
|
|
46
66
|
include Sequel::Oracle::DatasetMethods
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def convert_type(v)
|
|
71
|
+
case v
|
|
72
|
+
when Java::JavaMath::BigDecimal
|
|
73
|
+
if v.scale == 0
|
|
74
|
+
i = v.long_value
|
|
75
|
+
if v.equals(Java::JavaMath::BigDecimal.new(i))
|
|
76
|
+
i
|
|
77
|
+
else
|
|
78
|
+
super
|
|
79
|
+
end
|
|
80
|
+
else
|
|
81
|
+
super
|
|
82
|
+
end
|
|
83
|
+
when Java::OracleSql::TIMESTAMP
|
|
84
|
+
db.to_application_timestamp(v.to_string)
|
|
85
|
+
else
|
|
86
|
+
super
|
|
87
|
+
end
|
|
88
|
+
end
|
|
47
89
|
end
|
|
48
90
|
end
|
|
49
91
|
end
|
|
@@ -47,19 +47,14 @@ module Sequel
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
# Return instance of Sequel::JDBC::Postgres::Dataset with the given opts.
|
|
51
|
-
def dataset(opts=nil)
|
|
52
|
-
Sequel::JDBC::Postgres::Dataset.new(self, opts)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# Run the INSERT sql on the database and return the primary key
|
|
56
|
-
# for the record.
|
|
57
|
-
def execute_insert(sql, opts={})
|
|
58
|
-
super(sql, {:type=>:insert}.merge(opts))
|
|
59
|
-
end
|
|
60
|
-
|
|
61
50
|
private
|
|
62
51
|
|
|
52
|
+
# Use setNull for nil arguments as the default behavior of setString
|
|
53
|
+
# with nil doesn't appear to work correctly on PostgreSQL.
|
|
54
|
+
def set_ps_arg(cps, arg, i)
|
|
55
|
+
arg.nil? ? cps.setNull(i, JavaSQL::Types::NULL) : super
|
|
56
|
+
end
|
|
57
|
+
|
|
63
58
|
# Extend the adapter with the JDBC PostgreSQL AdapterMethods
|
|
64
59
|
def setup_connection(conn)
|
|
65
60
|
conn = super(conn)
|
|
@@ -8,11 +8,6 @@ module Sequel
|
|
|
8
8
|
module DatabaseMethods
|
|
9
9
|
include Sequel::SQLite::DatabaseMethods
|
|
10
10
|
|
|
11
|
-
# Return Sequel::JDBC::SQLite::Dataset object with the given opts.
|
|
12
|
-
def dataset(opts=nil)
|
|
13
|
-
Sequel::JDBC::SQLite::Dataset.new(self, opts)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
11
|
private
|
|
17
12
|
|
|
18
13
|
# Use last_insert_rowid() to get the last inserted id.
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
def metadata_dataset
|
|
13
|
+
ds = super
|
|
14
|
+
# Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
|
|
15
|
+
# for the getColumns result set specifies an incorrect type for the
|
|
16
|
+
# IS_AUTOINCREMENT column. The column is a string, but the type is
|
|
17
|
+
# specified as a short. This causes getObject() to throw a
|
|
18
|
+
# com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
|
|
19
|
+
# from char to SMALLINT is unsupported." Using getString() rather
|
|
20
|
+
# than getObject() for this column avoids the problem.
|
|
21
|
+
# Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
|
|
22
|
+
def ds.result_set_object_getter
|
|
23
|
+
lambda do |result, n, i|
|
|
24
|
+
if n == :is_autoincrement
|
|
25
|
+
@convert_types ? convert_type(result.getString(i)) : result.getString(i)
|
|
26
|
+
else
|
|
27
|
+
@convert_types ? convert_type(result.getObject(i)) : result.getObject(i)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
ds
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Dataset class for SQLServer datasets accessed via JDBC.
|
|
36
|
+
class Dataset < JDBC::Dataset
|
|
37
|
+
include Sequel::MSSQL::DatasetMethods
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
module Sequel
|
|
2
|
+
module JDBC
|
|
3
|
+
module Transactions
|
|
4
|
+
TRANSACTION_BEGIN = 'Transaction.begin'.freeze
|
|
5
|
+
TRANSACTION_COMMIT = 'Transaction.commit'.freeze
|
|
6
|
+
TRANSACTION_RELEASE_SP = 'Transaction.release_savepoint'.freeze
|
|
7
|
+
TRANSACTION_ROLLBACK = 'Transaction.rollback'.freeze
|
|
8
|
+
TRANSACTION_ROLLBACK_SP = 'Transaction.rollback_savepoint'.freeze
|
|
9
|
+
TRANSACTION_SAVEPOINT= 'Transaction.savepoint'.freeze
|
|
10
|
+
|
|
11
|
+
# Check the JDBC DatabaseMetaData for savepoint support
|
|
12
|
+
def supports_savepoints?
|
|
13
|
+
return @supports_savepoints if defined?(@supports_savepoints)
|
|
14
|
+
@supports_savepoints = synchronize{|c| c.get_meta_data.supports_savepoints}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
# Most JDBC drivers that support savepoints support releasing them.
|
|
20
|
+
def supports_releasing_savepoints?
|
|
21
|
+
true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Use JDBC connection's setAutoCommit to false to start transactions
|
|
25
|
+
def begin_transaction(conn, opts={})
|
|
26
|
+
if supports_savepoints?
|
|
27
|
+
th = @transactions[conn]
|
|
28
|
+
if sps = th[:savepoints]
|
|
29
|
+
sps << log_yield(TRANSACTION_SAVEPOINT){conn.set_savepoint}
|
|
30
|
+
else
|
|
31
|
+
log_yield(TRANSACTION_BEGIN){conn.setAutoCommit(false)}
|
|
32
|
+
th[:savepoints] = []
|
|
33
|
+
end
|
|
34
|
+
th[:savepoint_level] += 1
|
|
35
|
+
else
|
|
36
|
+
log_yield(TRANSACTION_BEGIN){conn.setAutoCommit(false)}
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Use JDBC connection's commit method to commit transactions
|
|
41
|
+
def commit_transaction(conn, opts={})
|
|
42
|
+
if supports_savepoints?
|
|
43
|
+
sps = @transactions[conn][:savepoints]
|
|
44
|
+
if sps.empty?
|
|
45
|
+
log_yield(TRANSACTION_COMMIT){conn.commit}
|
|
46
|
+
elsif supports_releasing_savepoints?
|
|
47
|
+
log_yield(TRANSACTION_RELEASE_SP){supports_releasing_savepoints? ? conn.release_savepoint(sps.last) : sps.last}
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
log_yield(TRANSACTION_COMMIT){conn.commit}
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Use JDBC connection's setAutoCommit to true to enable non-transactional behavior
|
|
55
|
+
def remove_transaction(conn, committed)
|
|
56
|
+
if supports_savepoints?
|
|
57
|
+
sps = @transactions[conn][:savepoints]
|
|
58
|
+
conn.setAutoCommit(true) if sps.empty?
|
|
59
|
+
sps.pop
|
|
60
|
+
else
|
|
61
|
+
conn.setAutoCommit(true)
|
|
62
|
+
end
|
|
63
|
+
ensure
|
|
64
|
+
super
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Use JDBC connection's rollback method to rollback transactions
|
|
68
|
+
def rollback_transaction(conn, opts={})
|
|
69
|
+
if supports_savepoints?
|
|
70
|
+
sps = @transactions[conn][:savepoints]
|
|
71
|
+
if sps.empty?
|
|
72
|
+
log_yield(TRANSACTION_ROLLBACK){conn.rollback}
|
|
73
|
+
else
|
|
74
|
+
log_yield(TRANSACTION_ROLLBACK_SP){conn.rollback(sps.last)}
|
|
75
|
+
end
|
|
76
|
+
else
|
|
77
|
+
log_yield(TRANSACTION_ROLLBACK){conn.rollback}
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
|
@@ -32,47 +32,89 @@ module Sequel
|
|
|
32
32
|
DATABASE_SETUP = {:postgresql=>proc do |db|
|
|
33
33
|
Sequel.ts_require 'adapters/jdbc/postgresql'
|
|
34
34
|
db.extend(Sequel::JDBC::Postgres::DatabaseMethods)
|
|
35
|
+
db.dataset_class = Sequel::JDBC::Postgres::Dataset
|
|
35
36
|
JDBC.load_gem('postgres')
|
|
36
37
|
org.postgresql.Driver
|
|
37
38
|
end,
|
|
38
39
|
:mysql=>proc do |db|
|
|
39
40
|
Sequel.ts_require 'adapters/jdbc/mysql'
|
|
40
41
|
db.extend(Sequel::JDBC::MySQL::DatabaseMethods)
|
|
42
|
+
db.dataset_class = Sequel::JDBC::MySQL::Dataset
|
|
41
43
|
JDBC.load_gem('mysql')
|
|
42
44
|
com.mysql.jdbc.Driver
|
|
43
45
|
end,
|
|
44
46
|
:sqlite=>proc do |db|
|
|
45
47
|
Sequel.ts_require 'adapters/jdbc/sqlite'
|
|
46
48
|
db.extend(Sequel::JDBC::SQLite::DatabaseMethods)
|
|
49
|
+
db.dataset_class = Sequel::JDBC::SQLite::Dataset
|
|
47
50
|
JDBC.load_gem('sqlite3')
|
|
48
51
|
org.sqlite.JDBC
|
|
49
52
|
end,
|
|
50
53
|
:oracle=>proc do |db|
|
|
51
54
|
Sequel.ts_require 'adapters/jdbc/oracle'
|
|
52
55
|
db.extend(Sequel::JDBC::Oracle::DatabaseMethods)
|
|
56
|
+
db.dataset_class = Sequel::JDBC::Oracle::Dataset
|
|
53
57
|
Java::oracle.jdbc.driver.OracleDriver
|
|
54
58
|
end,
|
|
55
59
|
:sqlserver=>proc do |db|
|
|
56
|
-
Sequel.ts_require 'adapters/jdbc/
|
|
57
|
-
db.extend(Sequel::JDBC::
|
|
60
|
+
Sequel.ts_require 'adapters/jdbc/sqlserver'
|
|
61
|
+
db.extend(Sequel::JDBC::SQLServer::DatabaseMethods)
|
|
62
|
+
db.dataset_class = Sequel::JDBC::SQLServer::Dataset
|
|
63
|
+
db.send(:set_mssql_unicode_strings)
|
|
58
64
|
com.microsoft.sqlserver.jdbc.SQLServerDriver
|
|
59
65
|
end,
|
|
60
66
|
:jtds=>proc do |db|
|
|
61
|
-
Sequel.ts_require 'adapters/jdbc/
|
|
62
|
-
db.extend(Sequel::JDBC::
|
|
67
|
+
Sequel.ts_require 'adapters/jdbc/jtds'
|
|
68
|
+
db.extend(Sequel::JDBC::JTDS::DatabaseMethods)
|
|
69
|
+
db.dataset_class = Sequel::JDBC::JTDS::Dataset
|
|
70
|
+
db.send(:set_mssql_unicode_strings)
|
|
63
71
|
JDBC.load_gem('jtds')
|
|
64
72
|
Java::net.sourceforge.jtds.jdbc.Driver
|
|
65
73
|
end,
|
|
66
74
|
:h2=>proc do |db|
|
|
67
75
|
Sequel.ts_require 'adapters/jdbc/h2'
|
|
68
76
|
db.extend(Sequel::JDBC::H2::DatabaseMethods)
|
|
77
|
+
db.dataset_class = Sequel::JDBC::H2::Dataset
|
|
69
78
|
JDBC.load_gem('h2')
|
|
70
79
|
org.h2.Driver
|
|
71
80
|
end,
|
|
81
|
+
:hsqldb=>proc do |db|
|
|
82
|
+
Sequel.ts_require 'adapters/jdbc/hsqldb'
|
|
83
|
+
db.extend(Sequel::JDBC::HSQLDB::DatabaseMethods)
|
|
84
|
+
db.dataset_class = Sequel::JDBC::HSQLDB::Dataset
|
|
85
|
+
# Current gem is 1.8.1.3, but Sequel supports 2.2.5
|
|
86
|
+
org.hsqldb.jdbcDriver
|
|
87
|
+
end,
|
|
88
|
+
:derby=>proc do |db|
|
|
89
|
+
Sequel.ts_require 'adapters/jdbc/derby'
|
|
90
|
+
db.extend(Sequel::JDBC::Derby::DatabaseMethods)
|
|
91
|
+
db.dataset_class = Sequel::JDBC::Derby::Dataset
|
|
92
|
+
JDBC.load_gem('derby')
|
|
93
|
+
org.apache.derby.jdbc.EmbeddedDriver
|
|
94
|
+
end,
|
|
72
95
|
:as400=>proc do |db|
|
|
73
96
|
Sequel.ts_require 'adapters/jdbc/as400'
|
|
74
97
|
db.extend(Sequel::JDBC::AS400::DatabaseMethods)
|
|
98
|
+
db.dataset_class = Sequel::JDBC::AS400::Dataset
|
|
75
99
|
com.ibm.as400.access.AS400JDBCDriver
|
|
100
|
+
end,
|
|
101
|
+
:"informix-sqli"=>proc do |db|
|
|
102
|
+
Sequel.ts_require 'adapters/jdbc/informix'
|
|
103
|
+
db.extend(Sequel::JDBC::Informix::DatabaseMethods)
|
|
104
|
+
db.dataset_class = Sequel::JDBC::Informix::Dataset
|
|
105
|
+
com.informix.jdbc.IfxDriver
|
|
106
|
+
end,
|
|
107
|
+
:db2=>proc do |db|
|
|
108
|
+
Sequel.ts_require 'adapters/jdbc/db2'
|
|
109
|
+
db.extend(Sequel::JDBC::DB2::DatabaseMethods)
|
|
110
|
+
db.dataset_class = Sequel::JDBC::DB2::Dataset
|
|
111
|
+
com.ibm.db2.jcc.DB2Driver
|
|
112
|
+
end,
|
|
113
|
+
:firebirdsql=>proc do |db|
|
|
114
|
+
Sequel.ts_require 'adapters/jdbc/firebird'
|
|
115
|
+
db.extend(Sequel::JDBC::Firebird::DatabaseMethods)
|
|
116
|
+
db.dataset_class = Sequel::JDBC::Firebird::Dataset
|
|
117
|
+
org.firebirdsql.jdbc.FBDriver
|
|
76
118
|
end
|
|
77
119
|
}
|
|
78
120
|
|
|
@@ -101,7 +143,7 @@ module Sequel
|
|
|
101
143
|
# True by default, can be set to false to roughly double performance when
|
|
102
144
|
# fetching rows.
|
|
103
145
|
attr_accessor :convert_types
|
|
104
|
-
|
|
146
|
+
|
|
105
147
|
# Call the DATABASE_SETUP proc directly after initialization,
|
|
106
148
|
# so the object always uses sub adapter specific code. Also,
|
|
107
149
|
# raise an error immediately if the connection doesn't have a
|
|
@@ -180,11 +222,6 @@ module Sequel
|
|
|
180
222
|
setup_connection(conn)
|
|
181
223
|
end
|
|
182
224
|
|
|
183
|
-
# Return instances of JDBC::Dataset with the given opts.
|
|
184
|
-
def dataset(opts = nil)
|
|
185
|
-
JDBC::Dataset.new(self, opts)
|
|
186
|
-
end
|
|
187
|
-
|
|
188
225
|
# Execute the given SQL. If a block is given, if should be a SELECT
|
|
189
226
|
# statement or something else that returns rows.
|
|
190
227
|
def execute(sql, opts={}, &block)
|
|
@@ -246,12 +283,14 @@ module Sequel
|
|
|
246
283
|
indexes
|
|
247
284
|
end
|
|
248
285
|
|
|
286
|
+
# Whether or not JNDI is being used for this connection.
|
|
287
|
+
def jndi?
|
|
288
|
+
!!(uri =~ JNDI_URI_REGEXP)
|
|
289
|
+
end
|
|
290
|
+
|
|
249
291
|
# All tables in this database
|
|
250
292
|
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
|
|
293
|
+
get_tables('TABLE', opts)
|
|
255
294
|
end
|
|
256
295
|
|
|
257
296
|
# The uri for this connection. You can specify the uri
|
|
@@ -264,11 +303,11 @@ module Sequel
|
|
|
264
303
|
ur =~ /^\Ajdbc:/ ? ur : "jdbc:#{ur}"
|
|
265
304
|
end
|
|
266
305
|
|
|
267
|
-
#
|
|
268
|
-
def
|
|
269
|
-
|
|
306
|
+
# All views in this database
|
|
307
|
+
def views(opts={})
|
|
308
|
+
get_tables('VIEW', opts)
|
|
270
309
|
end
|
|
271
|
-
|
|
310
|
+
|
|
272
311
|
private
|
|
273
312
|
|
|
274
313
|
# Close given adapter connections
|
|
@@ -276,6 +315,12 @@ module Sequel
|
|
|
276
315
|
c.close
|
|
277
316
|
end
|
|
278
317
|
|
|
318
|
+
# Raise a disconnect error if the SQL state of the cause of the exception indicates so.
|
|
319
|
+
def disconnect_error?(exception, opts)
|
|
320
|
+
cause = exception.respond_to?(:cause) ? exception.cause : exception
|
|
321
|
+
super || (cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/)
|
|
322
|
+
end
|
|
323
|
+
|
|
279
324
|
# Execute the prepared statement. If the provided name is a
|
|
280
325
|
# dataset, use that as the prepared statement, otherwise use
|
|
281
326
|
# it as a key to look it up in the prepared_statements hash.
|
|
@@ -325,6 +370,12 @@ module Sequel
|
|
|
325
370
|
end
|
|
326
371
|
end
|
|
327
372
|
|
|
373
|
+
# Gets the connection from JNDI.
|
|
374
|
+
def get_connection_from_jndi
|
|
375
|
+
jndi_name = JNDI_URI_REGEXP.match(uri)[1]
|
|
376
|
+
JavaxNaming::InitialContext.new.lookup(jndi_name).connection
|
|
377
|
+
end
|
|
378
|
+
|
|
328
379
|
# Gets the JDBC connection uri from the JNDI resource.
|
|
329
380
|
def get_uri_from_jndi
|
|
330
381
|
conn = get_connection_from_jndi
|
|
@@ -333,12 +384,14 @@ module Sequel
|
|
|
333
384
|
conn.close if conn
|
|
334
385
|
end
|
|
335
386
|
|
|
336
|
-
#
|
|
337
|
-
def
|
|
338
|
-
|
|
339
|
-
|
|
387
|
+
# Backbone of the tables and views support.
|
|
388
|
+
def get_tables(type, opts)
|
|
389
|
+
ts = []
|
|
390
|
+
m = output_identifier_meth
|
|
391
|
+
metadata(:getTables, nil, nil, nil, [type].to_java(:string)){|h| ts << m.call(h[:table_name])}
|
|
392
|
+
ts
|
|
340
393
|
end
|
|
341
|
-
|
|
394
|
+
|
|
342
395
|
# Support Date objects used in bound variables
|
|
343
396
|
def java_sql_date(date)
|
|
344
397
|
java.sql.Date.new(Time.local(date.year, date.month, date.day).to_i * 1000)
|
|
@@ -383,12 +436,6 @@ module Sequel
|
|
|
383
436
|
end
|
|
384
437
|
end
|
|
385
438
|
|
|
386
|
-
# Treat SQLExceptions with a "Connection Error" SQLState as disconnects
|
|
387
|
-
def raise_error(exception, opts={})
|
|
388
|
-
cause = exception.respond_to?(:cause) ? exception.cause : exception
|
|
389
|
-
super(exception, {:disconnect => cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/}.merge(opts))
|
|
390
|
-
end
|
|
391
|
-
|
|
392
439
|
# Java being java, you need to specify the type of each argument
|
|
393
440
|
# for the prepared statement, and bind it individually. This
|
|
394
441
|
# guesses which JDBC method to use, and hopefully JRuby will convert
|
|
@@ -405,8 +452,8 @@ module Sequel
|
|
|
405
452
|
cps.setDouble(i, arg)
|
|
406
453
|
when TrueClass, FalseClass
|
|
407
454
|
cps.setBoolean(i, arg)
|
|
408
|
-
when
|
|
409
|
-
cps.
|
|
455
|
+
when NilClass
|
|
456
|
+
cps.setString(i, nil)
|
|
410
457
|
when DateTime
|
|
411
458
|
cps.setTimestamp(i, java_sql_datetime(arg))
|
|
412
459
|
when Date
|
|
@@ -435,8 +482,8 @@ module Sequel
|
|
|
435
482
|
|
|
436
483
|
# Parse the table schema for the given table.
|
|
437
484
|
def schema_parse_table(table, opts={})
|
|
438
|
-
m = output_identifier_meth
|
|
439
|
-
im = input_identifier_meth
|
|
485
|
+
m = output_identifier_meth(opts[:dataset])
|
|
486
|
+
im = input_identifier_meth(opts[:dataset])
|
|
440
487
|
ds = dataset
|
|
441
488
|
schema, table = schema_and_table(table)
|
|
442
489
|
schema ||= opts[:schema]
|
|
@@ -444,9 +491,11 @@ module Sequel
|
|
|
444
491
|
table = im.call(table)
|
|
445
492
|
pks, ts = [], []
|
|
446
493
|
metadata(:getPrimaryKeys, nil, schema, table) do |h|
|
|
494
|
+
next if schema_parse_table_skip?(h, schema)
|
|
447
495
|
pks << h[:column_name]
|
|
448
496
|
end
|
|
449
497
|
metadata(:getColumns, nil, schema, table, nil) do |h|
|
|
498
|
+
next if schema_parse_table_skip?(h, schema)
|
|
450
499
|
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
500
|
if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
|
|
452
501
|
s[:type] = :integer
|
|
@@ -456,6 +505,12 @@ module Sequel
|
|
|
456
505
|
ts
|
|
457
506
|
end
|
|
458
507
|
|
|
508
|
+
# Whether schema_parse_table should skip the given row when
|
|
509
|
+
# parsing the schema.
|
|
510
|
+
def schema_parse_table_skip?(h, schema)
|
|
511
|
+
h[:table_schem] == 'INFORMATION_SCHEMA'
|
|
512
|
+
end
|
|
513
|
+
|
|
459
514
|
# Yield a new statement object, and ensure that it is closed before returning.
|
|
460
515
|
def statement(conn)
|
|
461
516
|
stmt = conn.createStatement
|
|
@@ -476,6 +531,8 @@ module Sequel
|
|
|
476
531
|
|
|
477
532
|
class Dataset < Sequel::Dataset
|
|
478
533
|
include StoredProcedures
|
|
534
|
+
|
|
535
|
+
Database::DatasetClass = self
|
|
479
536
|
|
|
480
537
|
# Use JDBC PreparedStatements instead of emulated ones. Statements
|
|
481
538
|
# created using #prepare are cached at the connection level to allow
|
|
@@ -530,8 +587,8 @@ module Sequel
|
|
|
530
587
|
# Uses the database's setting by default, can be set to false to roughly
|
|
531
588
|
# double performance when fetching rows.
|
|
532
589
|
attr_accessor :convert_types
|
|
533
|
-
|
|
534
|
-
# Use the convert_types default setting from the database
|
|
590
|
+
|
|
591
|
+
# Use the convert_types default setting from the database.
|
|
535
592
|
def initialize(db, opts={})
|
|
536
593
|
@convert_types = db.convert_types
|
|
537
594
|
super
|
|
@@ -560,8 +617,10 @@ module Sequel
|
|
|
560
617
|
# Convert the type. Used for converting Java types to ruby types.
|
|
561
618
|
def convert_type(v)
|
|
562
619
|
case v
|
|
563
|
-
when Java::JavaSQL::Timestamp
|
|
564
|
-
|
|
620
|
+
when Java::JavaSQL::Timestamp
|
|
621
|
+
db.to_application_timestamp(v.to_string)
|
|
622
|
+
when Java::JavaSQL::Time
|
|
623
|
+
Sequel.string_to_time(v.to_string)
|
|
565
624
|
when Java::JavaSQL::Date
|
|
566
625
|
Sequel.string_to_date(v.to_string)
|
|
567
626
|
when Java::JavaIo::BufferedReader
|
|
@@ -574,6 +633,8 @@ module Sequel
|
|
|
574
633
|
Sequel::SQL::Blob.new(String.from_java_bytes(v))
|
|
575
634
|
when Java::JavaSQL::Blob
|
|
576
635
|
convert_type(v.getBytes(1, v.length))
|
|
636
|
+
when Java::JavaSQL::Clob
|
|
637
|
+
Sequel::SQL::Blob.new(v.getSubString(1, v.length))
|
|
577
638
|
else
|
|
578
639
|
v
|
|
579
640
|
end
|
|
@@ -592,7 +653,12 @@ module Sequel
|
|
|
592
653
|
cols = []
|
|
593
654
|
i = 0
|
|
594
655
|
meta.getColumnCount.times{cols << [output_identifier(meta.getColumnLabel(i+=1)), i]}
|
|
595
|
-
|
|
656
|
+
columns = cols.map{|c| c.at(0)}
|
|
657
|
+
if opts[:offset] && offset_returns_row_number_column?
|
|
658
|
+
rn = row_number_column
|
|
659
|
+
columns.delete(rn)
|
|
660
|
+
end
|
|
661
|
+
@columns = columns
|
|
596
662
|
blk = result_set_object_getter
|
|
597
663
|
# get rows
|
|
598
664
|
while result.next
|
|
@@ -600,8 +666,11 @@ module Sequel
|
|
|
600
666
|
cols.each do |n, i|
|
|
601
667
|
row[n] = blk.call(result, n, i)
|
|
602
668
|
end
|
|
669
|
+
row.delete(rn) if rn
|
|
603
670
|
yield row
|
|
604
671
|
end
|
|
672
|
+
ensure
|
|
673
|
+
result.close
|
|
605
674
|
end
|
|
606
675
|
|
|
607
676
|
# Proc that takes the ResultSet and an integer field number and returns
|