sequel 3.21.0 → 3.32.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 +539 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/advanced_associations.rdoc +17 -0
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +8 -0
- 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 +89 -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/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +129 -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 +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +5 -7
- 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 +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +52 -0
- data/lib/sequel/adapters/jdbc/derby.rb +260 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +66 -30
- data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
- data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +231 -78
- data/lib/sequel/adapters/mock.rb +339 -0
- data/lib/sequel/adapters/mysql.rb +85 -184
- data/lib/sequel/adapters/mysql2.rb +26 -25
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +1 -6
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +355 -53
- data/lib/sequel/adapters/postgres.rb +194 -33
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +328 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +278 -107
- data/lib/sequel/adapters/shared/mysql.rb +203 -65
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +237 -46
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +200 -50
- data/lib/sequel/adapters/sqlite.rb +29 -21
- data/lib/sequel/adapters/swift/mysql.rb +12 -7
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +160 -19
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- 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 +68 -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 +104 -19
- data/lib/sequel/database/query.rb +163 -59
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +240 -76
- data/lib/sequel/dataset/features.rb +91 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +59 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +676 -267
- 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/query.rb +1 -1
- 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 +1081 -344
- data/lib/sequel/model/base.rb +420 -133
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +20 -10
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +43 -10
- 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 +68 -7
- data/lib/sequel/plugins/nested_attributes.rb +65 -10
- 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 +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- 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 +109 -52
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +135 -30
- data/spec/adapters/mysql_spec.rb +244 -212
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +267 -78
- 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 +21 -30
- data/spec/core/database_spec.rb +789 -512
- data/spec/core/dataset_spec.rb +1176 -1061
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +419 -0
- data/spec/core/object_graph_spec.rb +86 -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/active_model_spec.rb +13 -0
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +114 -22
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +53 -0
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/migration_spec.rb +35 -32
- data/spec/extensions/named_timezones_spec.rb +23 -3
- data/spec/extensions/nested_attributes_spec.rb +97 -88
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +53 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +5 -8
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +81 -43
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +18 -29
- data/spec/extensions/spec_helper.rb +13 -61
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +661 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +500 -67
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +367 -119
- data/spec/integration/prepared_statement_test.rb +222 -125
- data/spec/integration/schema_test.rb +217 -39
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +182 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +955 -662
- data/spec/model/base_spec.rb +275 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +349 -67
- data/spec/model/model_spec.rb +222 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +381 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +117 -73
|
@@ -13,20 +13,17 @@ module Sequel
|
|
|
13
13
|
# Database instance methods for MSSQL databases accessed via JDBC.
|
|
14
14
|
module DatabaseMethods
|
|
15
15
|
PRIMARY_KEY_INDEX_RE = /\Apk__/i.freeze
|
|
16
|
+
ATAT_IDENTITY = 'SELECT @@IDENTITY'.freeze
|
|
17
|
+
SCOPE_IDENTITY = 'SELECT SCOPE_IDENTITY()'.freeze
|
|
16
18
|
|
|
17
19
|
include Sequel::MSSQL::DatabaseMethods
|
|
18
20
|
|
|
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
21
|
private
|
|
25
22
|
|
|
26
23
|
# Get the last inserted id using SCOPE_IDENTITY().
|
|
27
24
|
def last_insert_id(conn, opts={})
|
|
28
25
|
statement(conn) do |stmt|
|
|
29
|
-
sql = opts[:prepared] ?
|
|
26
|
+
sql = opts[:prepared] ? ATAT_IDENTITY : SCOPE_IDENTITY
|
|
30
27
|
rs = log_yield(sql){stmt.executeQuery(sql)}
|
|
31
28
|
rs.next
|
|
32
29
|
rs.getInt(1)
|
|
@@ -43,33 +40,6 @@ module Sequel
|
|
|
43
40
|
def primary_key_index_re
|
|
44
41
|
PRIMARY_KEY_INDEX_RE
|
|
45
42
|
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
43
|
end
|
|
74
44
|
end
|
|
75
45
|
end
|
|
@@ -8,11 +8,7 @@ module Sequel
|
|
|
8
8
|
# Database instance methods for MySQL databases accessed via JDBC.
|
|
9
9
|
module DatabaseMethods
|
|
10
10
|
include Sequel::MySQL::DatabaseMethods
|
|
11
|
-
|
|
12
|
-
# Return instance of Sequel::JDBC::MySQL::Dataset with the given opts.
|
|
13
|
-
def dataset(opts=nil)
|
|
14
|
-
Sequel::JDBC::MySQL::Dataset.new(self, opts)
|
|
15
|
-
end
|
|
11
|
+
LAST_INSERT_ID = 'SELECT LAST_INSERT_ID()'.freeze
|
|
16
12
|
|
|
17
13
|
private
|
|
18
14
|
|
|
@@ -39,7 +35,7 @@ module Sequel
|
|
|
39
35
|
end
|
|
40
36
|
else
|
|
41
37
|
statement(conn) do |stmt|
|
|
42
|
-
rs = stmt.executeQuery(
|
|
38
|
+
rs = stmt.executeQuery(LAST_INSERT_ID)
|
|
43
39
|
rs.next
|
|
44
40
|
rs.getInt(1)
|
|
45
41
|
end
|
|
@@ -56,17 +52,21 @@ module Sequel
|
|
|
56
52
|
def schema_column_type(db_type)
|
|
57
53
|
db_type == 'tinyint(1)' ? :boolean : super
|
|
58
54
|
end
|
|
55
|
+
|
|
56
|
+
# By default, MySQL 'where id is null' selects the last inserted id.
|
|
57
|
+
# Turn that off unless explicitly enabled.
|
|
58
|
+
def setup_connection(conn)
|
|
59
|
+
super
|
|
60
|
+
sql = "SET SQL_AUTO_IS_NULL=0"
|
|
61
|
+
statement(conn){|s| log_yield(sql){s.execute(sql)}} unless opts[:auto_is_null]
|
|
62
|
+
conn
|
|
63
|
+
end
|
|
59
64
|
end
|
|
60
65
|
|
|
61
66
|
# Dataset class for MySQL datasets accessed via JDBC.
|
|
62
67
|
class Dataset < JDBC::Dataset
|
|
63
68
|
include Sequel::MySQL::DatasetMethods
|
|
64
69
|
|
|
65
|
-
# Use execute_insert to execute the insert_sql.
|
|
66
|
-
def insert(*values)
|
|
67
|
-
execute_insert(insert_sql(*values))
|
|
68
|
-
end
|
|
69
|
-
|
|
70
70
|
# Use execute_insert to execute the replace_sql.
|
|
71
71
|
def replace(*args)
|
|
72
72
|
execute_insert(replace_sql(*args))
|
|
@@ -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
|
|
@@ -6,44 +7,106 @@ module Sequel
|
|
|
6
7
|
module Oracle
|
|
7
8
|
# Instance methods for Oracle Database objects accessed via JDBC.
|
|
8
9
|
module DatabaseMethods
|
|
10
|
+
PRIMARY_KEY_INDEX_RE = /\Asys_/i.freeze
|
|
11
|
+
|
|
9
12
|
include Sequel::Oracle::DatabaseMethods
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
include Sequel::JDBC::Transactions
|
|
14
|
+
|
|
15
|
+
def self.extended(db)
|
|
16
|
+
db.instance_eval do
|
|
17
|
+
@autosequence = opts[:autosequence]
|
|
18
|
+
@primary_key_sequences = {}
|
|
19
|
+
end
|
|
17
20
|
end
|
|
18
21
|
|
|
19
22
|
private
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
def last_insert_id(conn, opts)
|
|
25
|
+
unless sequence = opts[:sequence]
|
|
26
|
+
if t = opts[:table]
|
|
27
|
+
sequence = sequence_for_table(t)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
if sequence
|
|
31
|
+
sql = "SELECT #{literal(sequence)}.currval FROM dual"
|
|
32
|
+
statement(conn) do |stmt|
|
|
33
|
+
begin
|
|
34
|
+
rs = log_yield(sql){stmt.executeQuery(sql)}
|
|
35
|
+
rs.next
|
|
36
|
+
rs.getInt(1)
|
|
37
|
+
rescue java.sql.SQLException
|
|
38
|
+
nil
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
25
42
|
end
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
-
def
|
|
29
|
-
|
|
43
|
+
|
|
44
|
+
# Primary key indexes appear to start with sys_ on Oracle
|
|
45
|
+
def primary_key_index_re
|
|
46
|
+
PRIMARY_KEY_INDEX_RE
|
|
30
47
|
end
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
48
|
+
|
|
49
|
+
def schema_parse_table(*)
|
|
50
|
+
sch = super
|
|
51
|
+
sch.each do |c, s|
|
|
52
|
+
if s[:type] == :decimal && s[:scale] == -127
|
|
53
|
+
s[:type] = :integer
|
|
54
|
+
elsif s[:db_type] == 'DATE'
|
|
55
|
+
s[:type] = :datetime
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
sch
|
|
36
59
|
end
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
60
|
+
|
|
61
|
+
def schema_parse_table_skip?(h, schema)
|
|
62
|
+
super || (h[:table_schem] != current_user unless schema)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# As of Oracle 9.2, releasing savepoints is no longer supported.
|
|
66
|
+
def supports_releasing_savepoints?
|
|
67
|
+
false
|
|
41
68
|
end
|
|
42
69
|
end
|
|
43
70
|
|
|
44
71
|
# Dataset class for Oracle datasets accessed via JDBC.
|
|
45
72
|
class Dataset < JDBC::Dataset
|
|
46
73
|
include Sequel::Oracle::DatasetMethods
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
JAVA_BIG_DECIMAL = ::Sequel::JDBC::Dataset::JAVA_BIG_DECIMAL
|
|
78
|
+
|
|
79
|
+
class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
|
|
80
|
+
def oracle_decimal(v)
|
|
81
|
+
if v.scale == 0
|
|
82
|
+
i = v.long_value
|
|
83
|
+
if v.equals(JAVA_BIG_DECIMAL.new(i))
|
|
84
|
+
i
|
|
85
|
+
else
|
|
86
|
+
decimal(v)
|
|
87
|
+
end
|
|
88
|
+
else
|
|
89
|
+
decimal(v)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
ORACLE_DECIMAL_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:oracle_decimal)
|
|
95
|
+
|
|
96
|
+
def convert_type_oracle_timestamp(v)
|
|
97
|
+
db.to_application_timestamp(v.to_string)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def convert_type_proc(v)
|
|
101
|
+
case v
|
|
102
|
+
when JAVA_BIG_DECIMAL
|
|
103
|
+
ORACLE_DECIMAL_METHOD
|
|
104
|
+
when Java::OracleSql::TIMESTAMP
|
|
105
|
+
method(:convert_type_oracle_timestamp)
|
|
106
|
+
else
|
|
107
|
+
super
|
|
108
|
+
end
|
|
109
|
+
end
|
|
47
110
|
end
|
|
48
111
|
end
|
|
49
112
|
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)
|
|
@@ -78,6 +73,7 @@ module Sequel
|
|
|
78
73
|
# Dataset subclass used for datasets that connect to PostgreSQL via JDBC.
|
|
79
74
|
class Dataset < JDBC::Dataset
|
|
80
75
|
include Sequel::Postgres::DatasetMethods
|
|
76
|
+
APOS = Dataset::APOS
|
|
81
77
|
|
|
82
78
|
# Add the shared PostgreSQL prepared statement methods
|
|
83
79
|
def prepare(*args)
|
|
@@ -87,8 +83,8 @@ module Sequel
|
|
|
87
83
|
end
|
|
88
84
|
|
|
89
85
|
# Literalize strings similar to the native postgres adapter
|
|
90
|
-
def
|
|
91
|
-
db.synchronize{|c|
|
|
86
|
+
def literal_string_append(sql, v)
|
|
87
|
+
sql << APOS << db.synchronize{|c| c.escape_string(v)} << APOS
|
|
92
88
|
end
|
|
93
89
|
end
|
|
94
90
|
end
|
|
@@ -7,18 +7,14 @@ module Sequel
|
|
|
7
7
|
# Instance methods for SQLite Database objects accessed via JDBC.
|
|
8
8
|
module DatabaseMethods
|
|
9
9
|
include Sequel::SQLite::DatabaseMethods
|
|
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
|
|
10
|
+
LAST_INSERT_ROWID = 'SELECT last_insert_rowid()'.freeze
|
|
15
11
|
|
|
16
12
|
private
|
|
17
13
|
|
|
18
14
|
# Use last_insert_rowid() to get the last inserted id.
|
|
19
15
|
def last_insert_id(conn, opts={})
|
|
20
16
|
statement(conn) do |stmt|
|
|
21
|
-
rs = stmt.executeQuery(
|
|
17
|
+
rs = stmt.executeQuery(LAST_INSERT_ROWID)
|
|
22
18
|
rs.next
|
|
23
19
|
rs.getInt(1)
|
|
24
20
|
end
|
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
# Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
|
|
13
|
+
# for the getColumns result set specifies an incorrect type for the
|
|
14
|
+
# IS_AUTOINCREMENT column. The column is a string, but the type is
|
|
15
|
+
# specified as a short. This causes getObject() to throw a
|
|
16
|
+
# com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
|
|
17
|
+
# from char to SMALLINT is unsupported." Using getString() rather
|
|
18
|
+
# than getObject() for this column avoids the problem.
|
|
19
|
+
# Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
|
|
20
|
+
module MetadataDatasetMethods
|
|
21
|
+
def process_result_set_convert(cols, result, rn)
|
|
22
|
+
while result.next
|
|
23
|
+
row = {}
|
|
24
|
+
cols.each do |n, i, p|
|
|
25
|
+
v = (n == :is_autoincrement ? result.getString(i) : result.getObject(i))
|
|
26
|
+
row[n] = if v
|
|
27
|
+
if p
|
|
28
|
+
p.call(v)
|
|
29
|
+
elsif p.nil?
|
|
30
|
+
cols[i-1][2] = p = convert_type_proc(v)
|
|
31
|
+
if p
|
|
32
|
+
p.call(v)
|
|
33
|
+
else
|
|
34
|
+
v
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
v
|
|
38
|
+
end
|
|
39
|
+
else
|
|
40
|
+
v
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
row.delete(rn) if rn
|
|
44
|
+
yield row
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def process_result_set_no_convert(cols, result, rn)
|
|
49
|
+
while result.next
|
|
50
|
+
row = {}
|
|
51
|
+
cols.each do |n, i|
|
|
52
|
+
row[n] = (n == :is_autoincrement ? result.getString(i) : result.getObject(i))
|
|
53
|
+
end
|
|
54
|
+
row.delete(rn) if rn
|
|
55
|
+
yield row
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def metadata_dataset
|
|
61
|
+
super.extend(MetadataDatasetMethods)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Dataset class for SQLServer datasets accessed via JDBC.
|
|
66
|
+
class Dataset < JDBC::Dataset
|
|
67
|
+
include Sequel::MSSQL::DatasetMethods
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
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
|
+
|