sequel 3.28.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 +119 -3
- data/Rakefile +5 -3
- data/bin/sequel +1 -5
- data/doc/model_hooks.rdoc +9 -1
- data/doc/opening_databases.rdoc +49 -40
- data/doc/prepared_statements.rdoc +27 -6
- data/doc/release_notes/3.28.0.txt +2 -2
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +18 -9
- data/doc/transactions.rdoc +41 -1
- data/lib/sequel/adapters/ado.rb +28 -17
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/amalgalite.rb +11 -7
- data/lib/sequel/adapters/db2.rb +122 -70
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do.rb +5 -36
- 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/firebird.rb +3 -6
- data/lib/sequel/adapters/ibmdb.rb +24 -16
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +47 -11
- data/lib/sequel/adapters/jdbc/as400.rb +5 -24
- data/lib/sequel/adapters/jdbc/db2.rb +0 -5
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
- data/lib/sequel/adapters/jdbc/h2.rb +10 -12
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
- data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +64 -51
- data/lib/sequel/adapters/mysql2.rb +15 -9
- data/lib/sequel/adapters/odbc.rb +13 -6
- data/lib/sequel/adapters/odbc/db2.rb +0 -4
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +333 -51
- data/lib/sequel/adapters/postgres.rb +80 -27
- data/lib/sequel/adapters/shared/access.rb +0 -6
- data/lib/sequel/adapters/shared/db2.rb +13 -15
- data/lib/sequel/adapters/shared/firebird.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +23 -18
- data/lib/sequel/adapters/shared/mysql.rb +6 -6
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -30
- data/lib/sequel/adapters/shared/postgres.rb +35 -18
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +116 -37
- data/lib/sequel/adapters/sqlite.rb +16 -8
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/tinytds.rb +13 -10
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
- data/lib/sequel/core.rb +40 -0
- data/lib/sequel/database/connecting.rb +1 -2
- data/lib/sequel/database/dataset.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +58 -0
- data/lib/sequel/database/misc.rb +62 -2
- data/lib/sequel/database/query.rb +113 -49
- data/lib/sequel/database/schema_methods.rb +7 -2
- data/lib/sequel/dataset/actions.rb +37 -19
- data/lib/sequel/dataset/features.rb +24 -0
- data/lib/sequel/dataset/graph.rb +7 -6
- data/lib/sequel/dataset/misc.rb +11 -3
- data/lib/sequel/dataset/mutation.rb +2 -3
- data/lib/sequel/dataset/prepared_statements.rb +6 -4
- data/lib/sequel/dataset/query.rb +46 -15
- data/lib/sequel/dataset/sql.rb +28 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/model.rb +2 -1
- data/lib/sequel/model/associations.rb +115 -33
- data/lib/sequel/model/base.rb +91 -31
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +6 -10
- data/lib/sequel/plugins/prepared_statements.rb +12 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/sharding.rb +0 -5
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/timezones.rb +42 -42
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +29 -29
- data/spec/adapters/mysql_spec.rb +86 -104
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +98 -33
- data/spec/adapters/spec_helper.rb +0 -5
- data/spec/adapters/sqlite_spec.rb +24 -21
- data/spec/core/connection_pool_spec.rb +9 -15
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +491 -227
- data/spec/core/dataset_spec.rb +638 -1051
- data/spec/core/expression_filters_spec.rb +0 -1
- 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 +51 -114
- data/spec/core/spec_helper.rb +3 -90
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +3 -0
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/spec_helper.rb +4 -0
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/integration/associations_test.rb +123 -12
- data/spec/integration/dataset_test.rb +140 -47
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +179 -128
- data/spec/integration/prepared_statement_test.rb +92 -91
- data/spec/integration/schema_test.rb +42 -23
- data/spec/integration/spec_helper.rb +25 -31
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +161 -34
- data/spec/integration/type_test.rb +3 -3
- data/spec/model/association_reflection_spec.rb +83 -7
- data/spec/model/associations_spec.rb +393 -676
- data/spec/model/base_spec.rb +186 -116
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +343 -867
- data/spec/model/hooks_spec.rb +160 -79
- data/spec/model/model_spec.rb +118 -165
- data/spec/model/plugins_spec.rb +7 -13
- data/spec/model/record_spec.rb +138 -207
- data/spec/model/spec_helper.rb +10 -73
- metadata +14 -8
|
@@ -9,11 +9,6 @@ module Sequel
|
|
|
9
9
|
module DatabaseMethods
|
|
10
10
|
include Sequel::Informix::DatabaseMethods
|
|
11
11
|
|
|
12
|
-
# Return instance of Sequel::JDBC::Informix::Dataset with the given opts.
|
|
13
|
-
def dataset(opts=nil)
|
|
14
|
-
Sequel::JDBC::Informix::Dataset.new(self, opts)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
12
|
private
|
|
18
13
|
|
|
19
14
|
# TODO: implement
|
|
@@ -8,11 +8,6 @@ module Sequel
|
|
|
8
8
|
# Database instance methods for JTDS databases accessed via JDBC.
|
|
9
9
|
module DatabaseMethods
|
|
10
10
|
include Sequel::JDBC::MSSQL::DatabaseMethods
|
|
11
|
-
|
|
12
|
-
# Return instance of Sequel::JDBC::JTDS::Dataset with the given opts.
|
|
13
|
-
def dataset(opts=nil)
|
|
14
|
-
Sequel::JDBC::JTDS::Dataset.new(self, opts)
|
|
15
|
-
end
|
|
16
11
|
end
|
|
17
12
|
|
|
18
13
|
# Dataset class for JTDS datasets accessed via JDBC.
|
|
@@ -9,11 +9,6 @@ module Sequel
|
|
|
9
9
|
module DatabaseMethods
|
|
10
10
|
include Sequel::MySQL::DatabaseMethods
|
|
11
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
|
|
16
|
-
|
|
17
12
|
private
|
|
18
13
|
|
|
19
14
|
# The database name for the given database. Need to parse it out
|
|
@@ -71,11 +66,6 @@ module Sequel
|
|
|
71
66
|
class Dataset < JDBC::Dataset
|
|
72
67
|
include Sequel::MySQL::DatasetMethods
|
|
73
68
|
|
|
74
|
-
# Use execute_insert to execute the insert_sql.
|
|
75
|
-
def insert(*values)
|
|
76
|
-
execute_insert(insert_sql(*values))
|
|
77
|
-
end
|
|
78
|
-
|
|
79
69
|
# Use execute_insert to execute the replace_sql.
|
|
80
70
|
def replace(*args)
|
|
81
71
|
execute_insert(replace_sql(*args))
|
|
@@ -9,16 +9,83 @@ module Sequel
|
|
|
9
9
|
module DatabaseMethods
|
|
10
10
|
include Sequel::Oracle::DatabaseMethods
|
|
11
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
|
|
18
|
+
end
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
private
|
|
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
|
|
40
|
+
end
|
|
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
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def schema_parse_table_skip?(h, schema)
|
|
55
|
+
super || (h[:table_schem] != current_user unless schema)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# As of Oracle 9.2, releasing savepoints is no longer supported.
|
|
59
|
+
def supports_releasing_savepoints?
|
|
60
|
+
false
|
|
16
61
|
end
|
|
17
62
|
end
|
|
18
63
|
|
|
19
64
|
# Dataset class for Oracle datasets accessed via JDBC.
|
|
20
65
|
class Dataset < JDBC::Dataset
|
|
21
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
|
|
22
89
|
end
|
|
23
90
|
end
|
|
24
91
|
end
|
|
@@ -47,17 +47,6 @@ 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
|
|
|
63
52
|
# Use setNull for nil arguments as the default behavior of setString
|
|
@@ -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.
|
|
@@ -9,11 +9,6 @@ module Sequel
|
|
|
9
9
|
module DatabaseMethods
|
|
10
10
|
include Sequel::JDBC::MSSQL::DatabaseMethods
|
|
11
11
|
|
|
12
|
-
# Return instance of Sequel::JDBC::SQLServer::Dataset with the given opts.
|
|
13
|
-
def dataset(opts=nil)
|
|
14
|
-
Sequel::JDBC::SQLServer::Dataset.new(self, opts)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
12
|
def metadata_dataset
|
|
18
13
|
ds = super
|
|
19
14
|
# Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
|
|
@@ -3,30 +3,79 @@ module Sequel
|
|
|
3
3
|
module Transactions
|
|
4
4
|
TRANSACTION_BEGIN = 'Transaction.begin'.freeze
|
|
5
5
|
TRANSACTION_COMMIT = 'Transaction.commit'.freeze
|
|
6
|
+
TRANSACTION_RELEASE_SP = 'Transaction.release_savepoint'.freeze
|
|
6
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
|
|
7
16
|
|
|
8
17
|
private
|
|
9
18
|
|
|
19
|
+
# Most JDBC drivers that support savepoints support releasing them.
|
|
20
|
+
def supports_releasing_savepoints?
|
|
21
|
+
true
|
|
22
|
+
end
|
|
23
|
+
|
|
10
24
|
# Use JDBC connection's setAutoCommit to false to start transactions
|
|
11
25
|
def begin_transaction(conn, opts={})
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
14
38
|
end
|
|
15
39
|
|
|
16
40
|
# Use JDBC connection's commit method to commit transactions
|
|
17
41
|
def commit_transaction(conn, opts={})
|
|
18
|
-
|
|
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
|
|
19
52
|
end
|
|
20
53
|
|
|
21
54
|
# Use JDBC connection's setAutoCommit to true to enable non-transactional behavior
|
|
22
|
-
def remove_transaction(conn)
|
|
23
|
-
|
|
24
|
-
|
|
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
|
|
25
65
|
end
|
|
26
66
|
|
|
27
67
|
# Use JDBC connection's rollback method to rollback transactions
|
|
28
68
|
def rollback_transaction(conn, opts={})
|
|
29
|
-
|
|
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
|
|
30
79
|
end
|
|
31
80
|
end
|
|
32
81
|
end
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
module Sequel
|
|
2
|
+
module Mock
|
|
3
|
+
# Connection class for Sequel's mock adapter.
|
|
4
|
+
class Connection
|
|
5
|
+
# Sequel::Mock::Database object that created this connection
|
|
6
|
+
attr_reader :db
|
|
7
|
+
|
|
8
|
+
# Shard this connection operates on, when using Sequel's
|
|
9
|
+
# sharding support (always :default for databases not using
|
|
10
|
+
# sharding).
|
|
11
|
+
attr_reader :server
|
|
12
|
+
|
|
13
|
+
# The specific database options for this connection.
|
|
14
|
+
attr_reader :opts
|
|
15
|
+
|
|
16
|
+
# Store the db, server, and opts.
|
|
17
|
+
def initialize(db, server, opts)
|
|
18
|
+
@db = db
|
|
19
|
+
@server = server
|
|
20
|
+
@opts = opts
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Delegate to the db's #_execute method.
|
|
24
|
+
def execute(sql)
|
|
25
|
+
@db.send(:_execute, self, sql)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Database class for Sequel's mock adapter.
|
|
30
|
+
class Database < Sequel::Database
|
|
31
|
+
set_adapter_scheme :mock
|
|
32
|
+
|
|
33
|
+
# Set the autogenerated primary key integer
|
|
34
|
+
# to be returned when running an insert query.
|
|
35
|
+
# Argument types supported:
|
|
36
|
+
#
|
|
37
|
+
# nil :: Return nil for all inserts
|
|
38
|
+
# Integer :: Starting integer for next insert, with
|
|
39
|
+
# futher inserts getting an incremented
|
|
40
|
+
# value
|
|
41
|
+
# Array :: First insert gets the first value in the
|
|
42
|
+
# array, second gets the second value, etc.
|
|
43
|
+
# Proc :: Called with the insert SQL query, uses
|
|
44
|
+
# the value returned
|
|
45
|
+
# Class :: Should be an Exception subclass, will create a new
|
|
46
|
+
# instance an raise it wrapped in a DatabaseError.
|
|
47
|
+
attr_writer :autoid
|
|
48
|
+
|
|
49
|
+
# Set the columns to set in the dataset when the dataset fetches
|
|
50
|
+
# rows. Argument types supported:
|
|
51
|
+
# nil :: Set no columns
|
|
52
|
+
# Array of Symbols: Used for all datasets
|
|
53
|
+
# Array (otherwise): First retrieval gets the first value in the
|
|
54
|
+
# array, second gets the second value, etc.
|
|
55
|
+
# Proc :: Called with the select SQL query, uses the value
|
|
56
|
+
# returned, which should be an array of symbols
|
|
57
|
+
attr_writer :columns
|
|
58
|
+
|
|
59
|
+
# Set the hashes to yield by execute when retrieving rows.
|
|
60
|
+
# Argument types supported:
|
|
61
|
+
#
|
|
62
|
+
# nil :: Yield no rows
|
|
63
|
+
# Hash :: Always yield a single row with this hash
|
|
64
|
+
# Array of Hashes :: Yield separately for each hash in this array
|
|
65
|
+
# Array (otherwise) :: First retrieval gets the first value
|
|
66
|
+
# in the array, second gets the second value, etc.
|
|
67
|
+
# Proc :: Called with the select SQL query, uses
|
|
68
|
+
# the value returned, which should be a hash or
|
|
69
|
+
# array of hashes.
|
|
70
|
+
# Class :: Should be an Exception subclass, will create a new
|
|
71
|
+
# instance an raise it wrapped in a DatabaseError.
|
|
72
|
+
attr_writer :fetch
|
|
73
|
+
|
|
74
|
+
# Set the number of rows to return from update or delete.
|
|
75
|
+
# Argument types supported:
|
|
76
|
+
#
|
|
77
|
+
# nil :: Return 0 for all updates and deletes
|
|
78
|
+
# Integer :: Used for all updates and deletes
|
|
79
|
+
# Array :: First update/delete gets the first value in the
|
|
80
|
+
# array, second gets the second value, etc.
|
|
81
|
+
# Proc :: Called with the update/delete SQL query, uses
|
|
82
|
+
# the value returned.
|
|
83
|
+
# Class :: Should be an Exception subclass, will create a new
|
|
84
|
+
# instance an raise it wrapped in a DatabaseError.
|
|
85
|
+
attr_writer :numrows
|
|
86
|
+
|
|
87
|
+
# Additional options supported:
|
|
88
|
+
#
|
|
89
|
+
# :autoid :: Call #autoid= with the value
|
|
90
|
+
# :columns :: Call #columns= with the value
|
|
91
|
+
# :fetch :: Call #fetch= with the value
|
|
92
|
+
# :numrows :: Call #numrows= with the value
|
|
93
|
+
# :extend :: A module the object is extended with.
|
|
94
|
+
# :sqls :: The array to store the SQL queries in.
|
|
95
|
+
def initialize(opts=nil)
|
|
96
|
+
super
|
|
97
|
+
self.autoid = opts[:autoid]
|
|
98
|
+
self.columns = opts[:columns]
|
|
99
|
+
self.fetch = opts[:fetch]
|
|
100
|
+
self.numrows = opts[:numrows]
|
|
101
|
+
extend(opts[:extend]) if opts[:extend]
|
|
102
|
+
@sqls = opts[:sqls] || []
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Return a related Connection option connecting to the given shard.
|
|
106
|
+
def connect(server)
|
|
107
|
+
Connection.new(self, server, server_opts(server))
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Store the sql used for later retrieval with #sqls, and return
|
|
111
|
+
# the appropriate value using either the #autoid, #fetch, or
|
|
112
|
+
# #numrows methods.
|
|
113
|
+
def execute(sql, opts={}, &block)
|
|
114
|
+
synchronize(opts[:server]){|c| _execute(c, sql, opts, &block)}
|
|
115
|
+
end
|
|
116
|
+
alias execute_ddl execute
|
|
117
|
+
|
|
118
|
+
# Store the sql used, and return the value of the #numrows method.
|
|
119
|
+
def execute_dui(sql, opts={})
|
|
120
|
+
execute(sql, opts.merge(:meth=>:numrows))
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Store the sql used, and return the value of the #autoid method.
|
|
124
|
+
def execute_insert(sql, opts={})
|
|
125
|
+
execute(sql, opts.merge(:meth=>:autoid))
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Return all stored SQL queries, and clear the cache
|
|
129
|
+
# of SQL queries.
|
|
130
|
+
def sqls
|
|
131
|
+
s = @sqls.dup
|
|
132
|
+
@sqls.clear
|
|
133
|
+
s
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Enable use of savepoints.
|
|
137
|
+
def supports_savepoints?
|
|
138
|
+
true
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
private
|
|
142
|
+
|
|
143
|
+
def _autoid(sql, v, ds=nil)
|
|
144
|
+
case v
|
|
145
|
+
when Integer
|
|
146
|
+
if ds
|
|
147
|
+
ds.autoid += 1 if ds.autoid.is_a?(Integer)
|
|
148
|
+
else
|
|
149
|
+
@autoid += 1
|
|
150
|
+
end
|
|
151
|
+
v
|
|
152
|
+
else
|
|
153
|
+
_nextres(v, sql, nil)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def _execute(c, sql, opts={}, &block)
|
|
158
|
+
sql += " -- args: #{opts[:arguments].inspect}" if opts[:arguments]
|
|
159
|
+
sql += " -- #{@opts[:append]}" if @opts[:append]
|
|
160
|
+
sql += " -- #{c.server}" if c.server != :default
|
|
161
|
+
log_info(sql)
|
|
162
|
+
@sqls << sql
|
|
163
|
+
|
|
164
|
+
ds = opts[:dataset]
|
|
165
|
+
begin
|
|
166
|
+
if block
|
|
167
|
+
columns(ds, sql) if ds
|
|
168
|
+
_fetch(sql, ds._fetch || @fetch, &block)
|
|
169
|
+
elsif meth = opts[:meth]
|
|
170
|
+
if meth == :numrows
|
|
171
|
+
_numrows(sql, ds.numrows || @numrows)
|
|
172
|
+
else
|
|
173
|
+
v = ds.autoid
|
|
174
|
+
_autoid(sql, v || @autoid, (ds if v))
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
rescue => e
|
|
178
|
+
raise_error(e)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def _fetch(sql, f, &block)
|
|
183
|
+
case f
|
|
184
|
+
when Hash
|
|
185
|
+
yield f.dup
|
|
186
|
+
when Array
|
|
187
|
+
if f.all?{|h| h.is_a?(Hash)}
|
|
188
|
+
f.each{|h| yield h.dup}
|
|
189
|
+
else
|
|
190
|
+
_fetch(sql, f.shift, &block)
|
|
191
|
+
end
|
|
192
|
+
when Proc
|
|
193
|
+
h = f.call(sql)
|
|
194
|
+
if h.is_a?(Hash)
|
|
195
|
+
yield h.dup
|
|
196
|
+
elsif h
|
|
197
|
+
h.each{|h1| yield h1.dup}
|
|
198
|
+
end
|
|
199
|
+
when Class
|
|
200
|
+
if f < Exception
|
|
201
|
+
raise f
|
|
202
|
+
else
|
|
203
|
+
raise Error, "Invalid @autoid/@numrows attribute: #{v.inspect}"
|
|
204
|
+
end
|
|
205
|
+
when nil
|
|
206
|
+
# nothing
|
|
207
|
+
else
|
|
208
|
+
raise Error, "Invalid @fetch attribute: #{f.inspect}"
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def _nextres(v, sql, default)
|
|
213
|
+
case v
|
|
214
|
+
when Integer
|
|
215
|
+
v
|
|
216
|
+
when Array
|
|
217
|
+
v.empty? ? default : _nextres(v.shift, sql, default)
|
|
218
|
+
when Proc
|
|
219
|
+
v.call(sql)
|
|
220
|
+
when Class
|
|
221
|
+
if v < Exception
|
|
222
|
+
raise v
|
|
223
|
+
else
|
|
224
|
+
raise Error, "Invalid @autoid/@numrows attribute: #{v.inspect}"
|
|
225
|
+
end
|
|
226
|
+
when nil
|
|
227
|
+
default
|
|
228
|
+
else
|
|
229
|
+
raise Error, "Invalid @autoid/@numrows attribute: #{v.inspect}"
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def _numrows(sql, v)
|
|
234
|
+
_nextres(v, sql, 0)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def columns(ds, sql, cs=@columns)
|
|
238
|
+
case cs
|
|
239
|
+
when Array
|
|
240
|
+
unless cs.empty?
|
|
241
|
+
if cs.all?{|c| c.is_a?(Symbol)}
|
|
242
|
+
ds.columns(*cs)
|
|
243
|
+
else
|
|
244
|
+
columns(ds, sql, cs.shift)
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
when Proc
|
|
248
|
+
ds.columns(*cs.call(sql))
|
|
249
|
+
when nil
|
|
250
|
+
# nothing
|
|
251
|
+
else
|
|
252
|
+
raise Error, "Invalid @columns attribute: #{cs.inspect}"
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def disconnect_connection(c)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def quote_identifiers_default
|
|
260
|
+
false
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def identifier_input_method_default
|
|
264
|
+
nil
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def identifier_input_method_default
|
|
268
|
+
nil
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
class Dataset < Sequel::Dataset
|
|
273
|
+
Database::DatasetClass = self
|
|
274
|
+
|
|
275
|
+
# Override the databases's autoid setting for this dataset
|
|
276
|
+
attr_accessor :autoid
|
|
277
|
+
|
|
278
|
+
# Override the databases's fetch setting for this dataset
|
|
279
|
+
attr_accessor :_fetch
|
|
280
|
+
|
|
281
|
+
# Override the databases's numrows setting for this dataset
|
|
282
|
+
attr_accessor :numrows
|
|
283
|
+
|
|
284
|
+
# If arguments are provided, use them to set the columns
|
|
285
|
+
# for this dataset and return self. Otherwise, use the
|
|
286
|
+
# default Sequel behavior and return the columns.
|
|
287
|
+
def columns(*cs)
|
|
288
|
+
if cs.empty?
|
|
289
|
+
super
|
|
290
|
+
else
|
|
291
|
+
@columns = cs
|
|
292
|
+
self
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def fetch_rows(sql, &block)
|
|
297
|
+
execute(sql, &block)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
private
|
|
301
|
+
|
|
302
|
+
def execute(sql, opts={}, &block)
|
|
303
|
+
super(sql, opts.merge(:dataset=>self), &block)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def execute_dui(sql, opts={}, &block)
|
|
307
|
+
super(sql, opts.merge(:dataset=>self), &block)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def execute_insert(sql, opts={}, &block)
|
|
311
|
+
super(sql, opts.merge(:dataset=>self), &block)
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
end
|