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
data/lib/sequel/dataset/graph.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
class Dataset
|
|
3
3
|
# ---------------------
|
|
4
|
-
# :section: Methods related to dataset graphing
|
|
4
|
+
# :section: 5 - Methods related to dataset graphing
|
|
5
5
|
# Dataset graphing changes the dataset to yield hashes where keys are table
|
|
6
6
|
# name symbols and values are hashes representing the columns related to
|
|
7
7
|
# that table. All of these methods return modified copies of the receiver.
|
|
@@ -115,7 +115,11 @@ module Sequel
|
|
|
115
115
|
add_columns = !ds.opts.include?(:graph_aliases)
|
|
116
116
|
|
|
117
117
|
# Setup the initial graph data structure if it doesn't exist
|
|
118
|
-
|
|
118
|
+
if graph = opts[:graph]
|
|
119
|
+
opts[:graph] = graph = graph.dup
|
|
120
|
+
select = opts[:select].dup
|
|
121
|
+
[:column_aliases, :table_aliases, :column_alias_num].each{|k| graph[k] = graph[k].dup}
|
|
122
|
+
else
|
|
119
123
|
master = alias_symbol(ds.first_source_alias)
|
|
120
124
|
raise_alias_error.call if master == table_alias
|
|
121
125
|
# Master hash storing all .graph related information
|
|
@@ -130,10 +134,33 @@ module Sequel
|
|
|
130
134
|
# aliased, but are not included if set_graph_aliases
|
|
131
135
|
# has been used.
|
|
132
136
|
if add_columns
|
|
133
|
-
select = opts[:select]
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
if (select = @opts[:select]) && !select.empty? && !(select.length == 1 && (select.first.is_a?(SQL::ColumnAll)))
|
|
138
|
+
select = select.each do |sel|
|
|
139
|
+
column = case sel
|
|
140
|
+
when Symbol
|
|
141
|
+
_, c, a = split_symbol(sel)
|
|
142
|
+
(a || c).to_sym
|
|
143
|
+
when SQL::Identifier
|
|
144
|
+
sel.value.to_sym
|
|
145
|
+
when SQL::QualifiedIdentifier
|
|
146
|
+
column = sel.column
|
|
147
|
+
column = column.value if column.is_a?(SQL::Identifier)
|
|
148
|
+
column.to_sym
|
|
149
|
+
when SQL::AliasedExpression
|
|
150
|
+
column = sel.aliaz
|
|
151
|
+
column = column.value if column.is_a?(SQL::Identifier)
|
|
152
|
+
column.to_sym
|
|
153
|
+
else
|
|
154
|
+
raise Error, "can't figure out alias to use for graphing for #{sel.inspect}"
|
|
155
|
+
end
|
|
156
|
+
column_aliases[column] = [master, column]
|
|
157
|
+
end
|
|
158
|
+
select = qualified_expression(select, master)
|
|
159
|
+
else
|
|
160
|
+
select = columns.map do |column|
|
|
161
|
+
column_aliases[column] = [master, column]
|
|
162
|
+
SQL::QualifiedIdentifier.new(master, column)
|
|
163
|
+
end
|
|
137
164
|
end
|
|
138
165
|
end
|
|
139
166
|
end
|
|
@@ -147,7 +174,6 @@ module Sequel
|
|
|
147
174
|
|
|
148
175
|
# Add the columns to the selection unless we are ignoring them
|
|
149
176
|
if add_table && add_columns
|
|
150
|
-
select = opts[:select]
|
|
151
177
|
column_aliases = graph[:column_aliases]
|
|
152
178
|
ca_num = graph[:column_alias_num]
|
|
153
179
|
# Which columns to add to the result set
|
|
@@ -165,15 +191,16 @@ module Sequel
|
|
|
165
191
|
column_alias = :"#{column_alias}_#{column_alias_num}"
|
|
166
192
|
ca_num[column_alias] += 1
|
|
167
193
|
end
|
|
168
|
-
[column_alias, SQL::QualifiedIdentifier.new(table_alias, column)
|
|
194
|
+
[column_alias, SQL::AliasedExpression.new(SQL::QualifiedIdentifier.new(table_alias, column), column_alias)]
|
|
169
195
|
else
|
|
170
|
-
|
|
196
|
+
ident = SQL::QualifiedIdentifier.new(table_alias, column)
|
|
197
|
+
[column, ident]
|
|
171
198
|
end
|
|
172
199
|
column_aliases[col_alias] = [table_alias, column]
|
|
173
200
|
select.push(identifier)
|
|
174
201
|
end
|
|
175
202
|
end
|
|
176
|
-
ds
|
|
203
|
+
add_columns ? ds.select(*select) : ds
|
|
177
204
|
end
|
|
178
205
|
|
|
179
206
|
# This allows you to manually specify the graph aliases to use
|
|
@@ -225,7 +252,7 @@ module Sequel
|
|
|
225
252
|
column ||= col_alias
|
|
226
253
|
gas[col_alias] = [table, column]
|
|
227
254
|
identifier = value || SQL::QualifiedIdentifier.new(table, column)
|
|
228
|
-
identifier = SQL::AliasedExpression.new(identifier, col_alias) if value
|
|
255
|
+
identifier = SQL::AliasedExpression.new(identifier, col_alias) if value || column != col_alias
|
|
229
256
|
identifier
|
|
230
257
|
end
|
|
231
258
|
[identifiers, gas]
|
data/lib/sequel/dataset/misc.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
class Dataset
|
|
3
3
|
# ---------------------
|
|
4
|
-
# :section: Miscellaneous methods
|
|
4
|
+
# :section: 6 - Miscellaneous methods
|
|
5
5
|
# These methods don't fit cleanly into another section.
|
|
6
6
|
# ---------------------
|
|
7
7
|
|
|
@@ -23,17 +23,13 @@ module Sequel
|
|
|
23
23
|
# DB[:posts]
|
|
24
24
|
#
|
|
25
25
|
# Sequel::Dataset is an abstract class that is not useful by itself. Each
|
|
26
|
-
# database
|
|
26
|
+
# database adapter provides a subclass of Sequel::Dataset, and has
|
|
27
27
|
# the Database#dataset method return an instance of that subclass.
|
|
28
28
|
def initialize(db, opts = nil)
|
|
29
29
|
@db = db
|
|
30
|
-
@quote_identifiers = db.quote_identifiers? if db.respond_to?(:quote_identifiers?)
|
|
31
|
-
@identifier_input_method = db.identifier_input_method if db.respond_to?(:identifier_input_method)
|
|
32
|
-
@identifier_output_method = db.identifier_output_method if db.respond_to?(:identifier_output_method)
|
|
33
30
|
@opts = opts || {}
|
|
34
|
-
@row_proc = nil
|
|
35
31
|
end
|
|
36
|
-
|
|
32
|
+
|
|
37
33
|
# Define a hash value such that datasets with the same DB, opts, and SQL
|
|
38
34
|
# will be consider equal.
|
|
39
35
|
def ==(o)
|
|
@@ -45,15 +41,6 @@ module Sequel
|
|
|
45
41
|
self == o
|
|
46
42
|
end
|
|
47
43
|
|
|
48
|
-
# Return the dataset as an aliased expression with the given alias. You can
|
|
49
|
-
# use this as a FROM or JOIN dataset, or as a column if this dataset
|
|
50
|
-
# returns a single row and column.
|
|
51
|
-
#
|
|
52
|
-
# DB.from(DB[:table].as(:b)) # SELECT * FROM (SELECT * FROM table) AS b
|
|
53
|
-
def as(aliaz)
|
|
54
|
-
::Sequel::SQL::AliasedExpression.new(self, aliaz)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
44
|
# Yield a dataset for each server in the connection pool that is tied to that server.
|
|
58
45
|
# Intended for use in sharded environments where all servers need to be modified
|
|
59
46
|
# with the same data:
|
|
@@ -96,10 +83,10 @@ module Sequel
|
|
|
96
83
|
# have a table, raises an error. If the table is aliased, returns the original
|
|
97
84
|
# table, not the alias
|
|
98
85
|
#
|
|
99
|
-
# DB[:table].
|
|
86
|
+
# DB[:table].first_source_table
|
|
100
87
|
# # => :table
|
|
101
88
|
#
|
|
102
|
-
# DB[:table___t].
|
|
89
|
+
# DB[:table___t].first_source_table
|
|
103
90
|
# # => :table
|
|
104
91
|
def first_source_table
|
|
105
92
|
source = @opts[:from]
|
|
@@ -120,16 +107,48 @@ module Sequel
|
|
|
120
107
|
# Define a hash value such that datasets with the same DB, opts, and SQL
|
|
121
108
|
# will have the same hash value
|
|
122
109
|
def hash
|
|
123
|
-
[db, opts.sort_by{|k| k.to_s}, sql].hash
|
|
110
|
+
[db, opts.sort_by{|k, v| k.to_s}, sql].hash
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# The String instance method to call on identifiers before sending them to
|
|
114
|
+
# the database.
|
|
115
|
+
def identifier_input_method
|
|
116
|
+
if defined?(@identifier_input_method)
|
|
117
|
+
@identifier_input_method
|
|
118
|
+
elsif db.respond_to?(:identifier_input_method)
|
|
119
|
+
@identifier_input_method = db.identifier_input_method
|
|
120
|
+
else
|
|
121
|
+
@identifier_input_method = nil
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# The String instance method to call on identifiers before sending them to
|
|
126
|
+
# the database.
|
|
127
|
+
def identifier_output_method
|
|
128
|
+
if defined?(@identifier_output_method)
|
|
129
|
+
@identifier_output_method
|
|
130
|
+
elsif db.respond_to?(:identifier_output_method)
|
|
131
|
+
@identifier_output_method = db.identifier_output_method
|
|
132
|
+
else
|
|
133
|
+
@identifier_output_method = nil
|
|
134
|
+
end
|
|
124
135
|
end
|
|
125
136
|
|
|
126
137
|
# Returns a string representation of the dataset including the class name
|
|
127
138
|
# and the corresponding SQL select statement.
|
|
128
139
|
def inspect
|
|
129
|
-
|
|
140
|
+
c = self.class
|
|
141
|
+
c = c.superclass while c.name.nil? || c.name == ''
|
|
142
|
+
"#<#{c.name}: #{sql.inspect}>"
|
|
130
143
|
end
|
|
131
144
|
|
|
132
|
-
#
|
|
145
|
+
# The alias to use for the row_number column, used when emulating OFFSET
|
|
146
|
+
# support and for eager limit strategies
|
|
147
|
+
def row_number_column
|
|
148
|
+
:x_sequel_row_number_x
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Splits a possible implicit alias in +c+, handling both SQL::AliasedExpressions
|
|
133
152
|
# and Symbols. Returns an array of two elements, with the first being the
|
|
134
153
|
# main expression, and the second being the alias.
|
|
135
154
|
def split_alias(c)
|
|
@@ -139,6 +158,8 @@ module Sequel
|
|
|
139
158
|
[c_table ? SQL::QualifiedIdentifier.new(c_table, column.to_sym) : column.to_sym, aliaz]
|
|
140
159
|
when SQL::AliasedExpression
|
|
141
160
|
[c.expression, c.aliaz]
|
|
161
|
+
when SQL::JoinClause
|
|
162
|
+
[c.table, c.table_alias]
|
|
142
163
|
else
|
|
143
164
|
[c, nil]
|
|
144
165
|
end
|
|
@@ -151,6 +172,10 @@ module Sequel
|
|
|
151
172
|
# used, where N is an integer starting at 0 and increasing until an
|
|
152
173
|
# unused one is found.
|
|
153
174
|
#
|
|
175
|
+
# You can provide a second addition array argument containing symbols
|
|
176
|
+
# that should not be considered valid table aliases. The current aliases
|
|
177
|
+
# for the FROM and JOIN tables are automatically included in this array.
|
|
178
|
+
#
|
|
154
179
|
# DB[:table].unused_table_alias(:t)
|
|
155
180
|
# # => :t
|
|
156
181
|
#
|
|
@@ -159,9 +184,11 @@ module Sequel
|
|
|
159
184
|
#
|
|
160
185
|
# DB[:table, :table_0].unused_table_alias(:table)
|
|
161
186
|
# # => :table_1
|
|
162
|
-
|
|
187
|
+
#
|
|
188
|
+
# DB[:table, :table_0].unused_table_alias(:table, [:table_1, :table_2])
|
|
189
|
+
# # => :table_3
|
|
190
|
+
def unused_table_alias(table_alias, used_aliases = [])
|
|
163
191
|
table_alias = alias_symbol(table_alias)
|
|
164
|
-
used_aliases = []
|
|
165
192
|
used_aliases += opts[:from].map{|t| alias_symbol(t)} if opts[:from]
|
|
166
193
|
used_aliases += opts[:join].map{|j| j.table_alias ? alias_alias_symbol(j.table_alias) : alias_symbol(j.table)} if opts[:join]
|
|
167
194
|
if used_aliases.include?(table_alias)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
class Dataset
|
|
3
3
|
# ---------------------
|
|
4
|
-
# :section: Mutation methods
|
|
4
|
+
# :section: 7 - Mutation methods
|
|
5
5
|
# These methods modify the receiving dataset and should be used with care.
|
|
6
6
|
# ---------------------
|
|
7
7
|
|
|
8
8
|
# All methods that should have a ! method added that modifies the receiver.
|
|
9
|
-
MUTATION_METHODS = QUERY_METHODS
|
|
9
|
+
MUTATION_METHODS = QUERY_METHODS - [:paginate, :naked]
|
|
10
10
|
|
|
11
11
|
# Setup mutation (e.g. filter!) methods. These operate the same as the
|
|
12
12
|
# non-! methods, but replace the options of the current dataset with the
|
|
@@ -21,17 +21,16 @@ module Sequel
|
|
|
21
21
|
def_mutation_method(*MUTATION_METHODS)
|
|
22
22
|
|
|
23
23
|
# Set the method to call on identifiers going into the database for this dataset
|
|
24
|
-
|
|
24
|
+
attr_writer :identifier_input_method
|
|
25
25
|
|
|
26
26
|
# Set the method to call on identifiers coming the database for this dataset
|
|
27
|
-
|
|
27
|
+
attr_writer :identifier_output_method
|
|
28
28
|
|
|
29
29
|
# Whether to quote identifiers for this dataset
|
|
30
30
|
attr_writer :quote_identifiers
|
|
31
31
|
|
|
32
|
-
# The row_proc for this database, should be
|
|
33
|
-
# a single hash argument and returns the object you want
|
|
34
|
-
# each to return.
|
|
32
|
+
# The row_proc for this database, should be any object that responds to +call+ with
|
|
33
|
+
# a single hash argument and returns the object you want #each to return.
|
|
35
34
|
attr_accessor :row_proc
|
|
36
35
|
|
|
37
36
|
# Add a mutation method to this dataset instance.
|
|
@@ -40,6 +39,12 @@ module Sequel
|
|
|
40
39
|
instance_eval("def #{meth}!(*args, &block); mutation_method(:#{meth}, *args, &block) end", __FILE__, __LINE__)
|
|
41
40
|
end
|
|
42
41
|
end
|
|
42
|
+
|
|
43
|
+
# Remove the row_proc from the current dataset.
|
|
44
|
+
def naked!
|
|
45
|
+
self.row_proc = nil
|
|
46
|
+
self
|
|
47
|
+
end
|
|
43
48
|
|
|
44
49
|
private
|
|
45
50
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
class Dataset
|
|
3
3
|
# ---------------------
|
|
4
|
-
# :section: Methods related to prepared statements or bound variables
|
|
4
|
+
# :section: 8 - Methods related to prepared statements or bound variables
|
|
5
5
|
# On some adapters, these use native prepared statements and bound variables, on others
|
|
6
6
|
# support is emulated. For details, see the {"Prepared Statements/Bound Variables" guide}[link:files/doc/prepared_statements_rdoc.html].
|
|
7
7
|
# ---------------------
|
|
@@ -12,9 +12,6 @@ module Sequel
|
|
|
12
12
|
# native database support for bind variables and prepared
|
|
13
13
|
# statements (as opposed to the emulated ones used by default).
|
|
14
14
|
module ArgumentMapper
|
|
15
|
-
SQL_QUERY_TYPE = Hash.new{|h,k| h[k] = k}
|
|
16
|
-
SQL_QUERY_TYPE[:first] = SQL_QUERY_TYPE[:all] = :select
|
|
17
|
-
|
|
18
15
|
# The name of the prepared statement, if any.
|
|
19
16
|
attr_accessor :prepared_statement_name
|
|
20
17
|
|
|
@@ -35,16 +32,9 @@ module Sequel
|
|
|
35
32
|
return @prepared_sql if @prepared_sql
|
|
36
33
|
@prepared_args ||= []
|
|
37
34
|
@prepared_sql = super
|
|
38
|
-
|
|
35
|
+
@opts[:sql] = @prepared_sql
|
|
39
36
|
@prepared_sql
|
|
40
37
|
end
|
|
41
|
-
|
|
42
|
-
private
|
|
43
|
-
|
|
44
|
-
# The type of query (:select, :insert, :delete, :update).
|
|
45
|
-
def sql_query_type
|
|
46
|
-
SQL_QUERY_TYPE[@prepared_type]
|
|
47
|
-
end
|
|
48
38
|
end
|
|
49
39
|
|
|
50
40
|
# Backbone of the prepared statement support. Grafts bind variable
|
|
@@ -63,6 +53,9 @@ module Sequel
|
|
|
63
53
|
# The array/hash of bound variable placeholder names.
|
|
64
54
|
attr_accessor :prepared_args
|
|
65
55
|
|
|
56
|
+
# The dataset that created this prepared statement.
|
|
57
|
+
attr_accessor :orig_dataset
|
|
58
|
+
|
|
66
59
|
# The argument to supply to insert and update, which may use
|
|
67
60
|
# placeholders specified by prepared_args
|
|
68
61
|
attr_accessor :prepared_modify_values
|
|
@@ -72,31 +65,46 @@ module Sequel
|
|
|
72
65
|
def call(bind_vars={}, &block)
|
|
73
66
|
bind(bind_vars).run(&block)
|
|
74
67
|
end
|
|
68
|
+
|
|
69
|
+
# Send the columns to the original dataset, as calling it
|
|
70
|
+
# on the prepared statement can cause problems.
|
|
71
|
+
def columns
|
|
72
|
+
orig_dataset.columns
|
|
73
|
+
end
|
|
75
74
|
|
|
76
75
|
# Returns the SQL for the prepared statement, depending on
|
|
77
76
|
# the type of the statement and the prepared_modify_values.
|
|
78
77
|
def prepared_sql
|
|
79
78
|
case @prepared_type
|
|
80
79
|
when :select, :all
|
|
80
|
+
# Most common scenario, so listed first.
|
|
81
81
|
select_sql
|
|
82
82
|
when :first
|
|
83
83
|
clone(:limit=>1).select_sql
|
|
84
|
+
when :insert_select
|
|
85
|
+
returning.insert_sql(*@prepared_modify_values)
|
|
84
86
|
when :insert
|
|
85
87
|
insert_sql(*@prepared_modify_values)
|
|
86
88
|
when :update
|
|
87
89
|
update_sql(*@prepared_modify_values)
|
|
88
90
|
when :delete
|
|
89
91
|
delete_sql
|
|
92
|
+
else
|
|
93
|
+
select_sql
|
|
90
94
|
end
|
|
91
95
|
end
|
|
92
96
|
|
|
93
97
|
# Changes the values of symbols if they start with $ and
|
|
94
98
|
# prepared_args is present. If so, they are considered placeholders,
|
|
95
99
|
# and they are substituted using prepared_arg.
|
|
96
|
-
def
|
|
100
|
+
def literal_symbol_append(sql, v)
|
|
97
101
|
if @opts[:bind_vars] and match = PLACEHOLDER_RE.match(v.to_s)
|
|
98
|
-
|
|
99
|
-
|
|
102
|
+
s = match[1].to_sym
|
|
103
|
+
if prepared_arg?(s)
|
|
104
|
+
literal_append(sql, prepared_arg(s))
|
|
105
|
+
else
|
|
106
|
+
sql << v.to_s
|
|
107
|
+
end
|
|
100
108
|
else
|
|
101
109
|
super
|
|
102
110
|
end
|
|
@@ -117,7 +125,10 @@ module Sequel
|
|
|
117
125
|
def run(&block)
|
|
118
126
|
case @prepared_type
|
|
119
127
|
when :select, :all
|
|
128
|
+
# Most common scenario, so listed first
|
|
120
129
|
all(&block)
|
|
130
|
+
when :insert_select
|
|
131
|
+
with_sql(prepared_sql).first
|
|
121
132
|
when :first
|
|
122
133
|
first
|
|
123
134
|
when :insert
|
|
@@ -126,6 +137,13 @@ module Sequel
|
|
|
126
137
|
update(*@prepared_modify_values)
|
|
127
138
|
when :delete
|
|
128
139
|
delete
|
|
140
|
+
when Array
|
|
141
|
+
case @prepared_type.at(0)
|
|
142
|
+
when :map, :to_hash
|
|
143
|
+
send(*@prepared_type, &block)
|
|
144
|
+
end
|
|
145
|
+
else
|
|
146
|
+
all(&block)
|
|
129
147
|
end
|
|
130
148
|
end
|
|
131
149
|
|
|
@@ -136,11 +154,16 @@ module Sequel
|
|
|
136
154
|
@opts[:bind_vars][k]
|
|
137
155
|
end
|
|
138
156
|
|
|
157
|
+
# Whether there is a bound value for the given key.
|
|
158
|
+
def prepared_arg?(k)
|
|
159
|
+
@opts[:bind_vars].has_key?(k)
|
|
160
|
+
end
|
|
161
|
+
|
|
139
162
|
# Use a clone of the dataset extended with prepared statement
|
|
140
163
|
# support and using the same argument hash so that you can use
|
|
141
164
|
# bind variables/prepared arguments in subselects.
|
|
142
|
-
def
|
|
143
|
-
ps = ds.prepare(:select)
|
|
165
|
+
def subselect_sql_append(sql, ds)
|
|
166
|
+
ps = ds.clone(:append_sql=>sql).prepare(:select)
|
|
144
167
|
ps = ps.bind(@opts[:bind_vars]) if @opts[:bind_vars]
|
|
145
168
|
ps.prepared_args = prepared_args
|
|
146
169
|
ps.prepared_sql
|
|
@@ -171,6 +194,11 @@ module Sequel
|
|
|
171
194
|
prepared_args << k
|
|
172
195
|
prepared_arg_placeholder
|
|
173
196
|
end
|
|
197
|
+
|
|
198
|
+
# Always assume there is a prepared arg in the argument mapper.
|
|
199
|
+
def prepared_arg?(k)
|
|
200
|
+
true
|
|
201
|
+
end
|
|
174
202
|
end
|
|
175
203
|
|
|
176
204
|
# Set the bind variables to use for the call. If bind variables have
|
|
@@ -184,11 +212,9 @@ module Sequel
|
|
|
184
212
|
clone(:bind_vars=>@opts[:bind_vars] ? @opts[:bind_vars].merge(bind_vars) : bind_vars)
|
|
185
213
|
end
|
|
186
214
|
|
|
187
|
-
# For the given type (:select, :insert, :update, or :delete),
|
|
188
|
-
# run the sql with the bind variables
|
|
189
|
-
#
|
|
190
|
-
# insert or update (if one of those types is used),
|
|
191
|
-
# which may contain placeholders.
|
|
215
|
+
# For the given type (:select, :first, :insert, :insert_select, :update, or :delete),
|
|
216
|
+
# run the sql with the bind variables specified in the hash. +values+ is a hash passed to
|
|
217
|
+
# insert or update (if one of those types is used), which may contain placeholders.
|
|
192
218
|
#
|
|
193
219
|
# DB[:table].filter(:id=>:$id).call(:first, :id=>1)
|
|
194
220
|
# # SELECT * FROM table WHERE id = ? LIMIT 1 -- (1)
|
|
@@ -197,11 +223,16 @@ module Sequel
|
|
|
197
223
|
prepare(type, nil, *values).call(bind_variables, &block)
|
|
198
224
|
end
|
|
199
225
|
|
|
200
|
-
# Prepare an SQL statement for later execution.
|
|
201
|
-
#
|
|
202
|
-
#
|
|
203
|
-
#
|
|
204
|
-
#
|
|
226
|
+
# Prepare an SQL statement for later execution. Takes a type similar to #call,
|
|
227
|
+
# and the +name+ symbol of the prepared statement. While +name+ defaults to +nil+,
|
|
228
|
+
# it should always be provided as a symbol for the name of the prepared statement,
|
|
229
|
+
# as some databases require that prepared statements have names.
|
|
230
|
+
#
|
|
231
|
+
# This returns a clone of the dataset extended with PreparedStatementMethods,
|
|
232
|
+
# which you can +call+ with the hash of bind variables to use.
|
|
233
|
+
# The prepared statement is also stored in
|
|
234
|
+
# the associated database, where it can be called by name.
|
|
235
|
+
# The following usage is identical:
|
|
205
236
|
#
|
|
206
237
|
# ps = DB[:table].filter(:name=>:$name).prepare(:first, :select_by_name)
|
|
207
238
|
#
|
|
@@ -223,6 +254,7 @@ module Sequel
|
|
|
223
254
|
def to_prepared_statement(type, values=nil)
|
|
224
255
|
ps = bind
|
|
225
256
|
ps.extend(PreparedStatementMethods)
|
|
257
|
+
ps.orig_dataset = self
|
|
226
258
|
ps.prepared_type = type
|
|
227
259
|
ps.prepared_modify_values = values
|
|
228
260
|
ps
|