sequel 3.21.0 → 3.41.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 +1131 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +106 -65
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +68 -52
- data/doc/advanced_associations.rdoc +201 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/bin_sequel.rdoc +144 -0
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +576 -0
- data/doc/opening_databases.rdoc +121 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- 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/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/release_notes/3.40.0.txt +73 -0
- data/doc/release_notes/3.41.0.txt +155 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- data/lib/sequel/adapters/ado/access.rb +334 -0
- data/lib/sequel/adapters/ado/mssql.rb +18 -12
- data/lib/sequel/adapters/ado.rb +69 -21
- data/lib/sequel/adapters/amalgalite.rb +17 -14
- data/lib/sequel/adapters/cubrid.rb +143 -0
- data/lib/sequel/adapters/db2.rb +178 -85
- data/lib/sequel/adapters/dbi.rb +19 -21
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +20 -39
- data/lib/sequel/adapters/firebird.rb +33 -210
- data/lib/sequel/adapters/ibmdb.rb +452 -0
- data/lib/sequel/adapters/informix.rb +6 -29
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
- data/lib/sequel/adapters/jdbc/db2.rb +78 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +68 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +308 -114
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +130 -230
- data/lib/sequel/adapters/mysql2.rb +64 -63
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +29 -10
- data/lib/sequel/adapters/openbase.rb +7 -11
- data/lib/sequel/adapters/oracle.rb +364 -57
- data/lib/sequel/adapters/postgres.rb +379 -145
- data/lib/sequel/adapters/shared/access.rb +236 -11
- data/lib/sequel/adapters/shared/cubrid.rb +216 -0
- data/lib/sequel/adapters/shared/db2.rb +353 -0
- data/lib/sequel/adapters/shared/firebird.rb +231 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +412 -116
- data/lib/sequel/adapters/shared/mysql.rb +396 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
- data/lib/sequel/adapters/shared/oracle.rb +262 -45
- data/lib/sequel/adapters/shared/postgres.rb +688 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +317 -96
- data/lib/sequel/adapters/sqlite.rb +109 -46
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +31 -27
- data/lib/sequel/adapters/tinytds.rb +177 -25
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +23 -13
- data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
- data/lib/sequel/connection_pool/single.rb +11 -3
- data/lib/sequel/connection_pool/threaded.rb +69 -20
- data/lib/sequel/connection_pool.rb +20 -18
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +66 -29
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +192 -51
- data/lib/sequel/database/query.rb +299 -114
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +310 -69
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +322 -68
- data/lib/sequel/dataset/sql.rb +716 -293
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/connection_validator.rb +109 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +539 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +334 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +212 -0
- data/lib/sequel/extensions/pg_range.rb +513 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +576 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +137 -16
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +134 -15
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +77 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +168 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -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 +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- 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 +57 -12
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +18 -6
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +57 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +721 -141
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +53 -39
- data/spec/adapters/mssql_spec.rb +261 -66
- data/spec/adapters/mysql_spec.rb +597 -352
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +2103 -341
- data/spec/adapters/spec_helper.rb +16 -6
- data/spec/adapters/sqlite_spec.rb +237 -76
- data/spec/core/connection_pool_spec.rb +270 -141
- data/spec/core/database_spec.rb +980 -524
- data/spec/core/dataset_spec.rb +1658 -1243
- data/spec/core/expression_filters_spec.rb +741 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +227 -33
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/caching_spec.rb +47 -51
- 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/connection_validator_spec.rb +118 -0
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +268 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +112 -0
- data/spec/extensions/pg_array_spec.rb +324 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +200 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +340 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- 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 +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +86 -48
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +65 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -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 +8 -11
- data/spec/extensions/touch_spec.rb +53 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +77 -68
- data/spec/extensions/validation_helpers_spec.rb +48 -37
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +25 -5
- data/spec/integration/dataset_test.rb +729 -141
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +871 -160
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +377 -57
- data/spec/integration/spec_helper.rb +49 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +40 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +223 -81
- data/spec/core/core_sql_spec.rb +0 -451
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
class Dataset
|
|
3
3
|
# ---------------------
|
|
4
|
-
# :section: Methods that execute code on the database
|
|
4
|
+
# :section: 2 - Methods that execute code on the database
|
|
5
5
|
# These methods all execute the dataset's SQL on the database.
|
|
6
6
|
# They don't return modified datasets, so if used in a method chain
|
|
7
7
|
# they should be the last method called.
|
|
8
8
|
# ---------------------
|
|
9
9
|
|
|
10
10
|
# Action methods defined by Sequel that execute code on the database.
|
|
11
|
-
ACTION_METHODS =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
ACTION_METHODS = (<<-METHS).split.map{|x| x.to_sym}
|
|
12
|
+
<< [] []= all avg count columns columns! delete each
|
|
13
|
+
empty? fetch_rows first get import insert insert_multiple interval last
|
|
14
|
+
map max min multi_insert range select_hash select_hash_groups select_map select_order_map
|
|
15
|
+
set single_record single_value sum to_csv to_hash to_hash_groups truncate update
|
|
16
|
+
METHS
|
|
15
17
|
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
# Inserts the given argument into the database. Returns self so it
|
|
19
|
+
# can be used safely when chaining:
|
|
20
|
+
#
|
|
21
|
+
# DB[:items] << {:id=>0, :name=>'Zero'} << DB[:old_items].select(:id, name)
|
|
22
|
+
def <<(arg)
|
|
23
|
+
insert(arg)
|
|
24
|
+
self
|
|
20
25
|
end
|
|
21
26
|
|
|
22
27
|
# Returns the first record matching the conditions. Examples:
|
|
@@ -72,7 +77,7 @@ module Sequel
|
|
|
72
77
|
# # => [:id, :name]
|
|
73
78
|
def columns
|
|
74
79
|
return @columns if @columns
|
|
75
|
-
ds = unfiltered.unordered.clone(:distinct => nil, :limit => 1)
|
|
80
|
+
ds = unfiltered.unordered.clone(:distinct => nil, :limit => 1, :offset=>nil)
|
|
76
81
|
ds.each{break}
|
|
77
82
|
@columns = ds.instance_variable_get(:@columns)
|
|
78
83
|
@columns || []
|
|
@@ -88,12 +93,30 @@ module Sequel
|
|
|
88
93
|
columns
|
|
89
94
|
end
|
|
90
95
|
|
|
91
|
-
# Returns the number of records in the dataset.
|
|
96
|
+
# Returns the number of records in the dataset. If an argument is provided,
|
|
97
|
+
# it is used as the argument to count. If a block is provided, it is
|
|
98
|
+
# treated as a virtual row, and the result is used as the argument to
|
|
99
|
+
# count.
|
|
92
100
|
#
|
|
93
101
|
# DB[:table].count # SELECT COUNT(*) AS count FROM table LIMIT 1
|
|
94
102
|
# # => 3
|
|
95
|
-
|
|
96
|
-
|
|
103
|
+
# DB[:table].count(:column) # SELECT COUNT(column) AS count FROM table LIMIT 1
|
|
104
|
+
# # => 2
|
|
105
|
+
# DB[:table].count{foo(column)} # SELECT COUNT(foo(column)) AS count FROM table LIMIT 1
|
|
106
|
+
# # => 1
|
|
107
|
+
def count(arg=(no_arg=true), &block)
|
|
108
|
+
if no_arg
|
|
109
|
+
if block
|
|
110
|
+
arg = Sequel.virtual_row(&block)
|
|
111
|
+
aggregate_dataset.get{COUNT(arg).as(count)}
|
|
112
|
+
else
|
|
113
|
+
aggregate_dataset.get{COUNT(:*){}.as(count)}.to_i
|
|
114
|
+
end
|
|
115
|
+
elsif block
|
|
116
|
+
raise Error, 'cannot provide both argument and block to Dataset#count'
|
|
117
|
+
else
|
|
118
|
+
aggregate_dataset.get{COUNT(arg).as(count)}
|
|
119
|
+
end
|
|
97
120
|
end
|
|
98
121
|
|
|
99
122
|
# Deletes the records in the dataset. The returned value should be
|
|
@@ -101,10 +124,15 @@ module Sequel
|
|
|
101
124
|
#
|
|
102
125
|
# DB[:table].delete # DELETE * FROM table
|
|
103
126
|
# # => 3
|
|
104
|
-
def delete
|
|
105
|
-
|
|
127
|
+
def delete(&block)
|
|
128
|
+
sql = delete_sql
|
|
129
|
+
if uses_returning?(:delete)
|
|
130
|
+
returning_fetch_rows(sql, &block)
|
|
131
|
+
else
|
|
132
|
+
execute_dui(sql)
|
|
133
|
+
end
|
|
106
134
|
end
|
|
107
|
-
|
|
135
|
+
|
|
108
136
|
# Iterates over the records in the dataset as they are yielded from the
|
|
109
137
|
# database adapter, and returns self.
|
|
110
138
|
#
|
|
@@ -114,23 +142,23 @@ module Sequel
|
|
|
114
142
|
# running additional queries inside the provided block. If you are
|
|
115
143
|
# running queries inside the block, you should use +all+ instead of +each+
|
|
116
144
|
# for the outer queries, or use a separate thread or shard inside +each+:
|
|
117
|
-
def each
|
|
145
|
+
def each
|
|
118
146
|
if @opts[:graph]
|
|
119
|
-
graph_each
|
|
147
|
+
graph_each{|r| yield r}
|
|
120
148
|
elsif row_proc = @row_proc
|
|
121
149
|
fetch_rows(select_sql){|r| yield row_proc.call(r)}
|
|
122
150
|
else
|
|
123
|
-
fetch_rows(select_sql
|
|
151
|
+
fetch_rows(select_sql){|r| yield r}
|
|
124
152
|
end
|
|
125
153
|
self
|
|
126
154
|
end
|
|
127
155
|
|
|
128
156
|
# Returns true if no records exist in the dataset, false otherwise
|
|
129
157
|
#
|
|
130
|
-
# DB[:table].empty? # SELECT 1 FROM table LIMIT 1
|
|
158
|
+
# DB[:table].empty? # SELECT 1 AS one FROM table LIMIT 1
|
|
131
159
|
# # => false
|
|
132
160
|
def empty?
|
|
133
|
-
get(1).nil?
|
|
161
|
+
get(Sequel::SQL::AliasedExpression.new(1, :one)).nil?
|
|
134
162
|
end
|
|
135
163
|
|
|
136
164
|
# Executes a select query and fetches records, yielding each record to the
|
|
@@ -194,12 +222,12 @@ module Sequel
|
|
|
194
222
|
#
|
|
195
223
|
# ds.get{sum(id)} # SELECT sum(id) FROM table LIMIT 1
|
|
196
224
|
# # => 6
|
|
197
|
-
def get(column=nil, &block)
|
|
198
|
-
if
|
|
199
|
-
raise(Error, ARG_BLOCK_ERROR_MSG)
|
|
200
|
-
select(column).single_value
|
|
201
|
-
else
|
|
225
|
+
def get(column=(no_arg=true; nil), &block)
|
|
226
|
+
if block
|
|
227
|
+
raise(Error, ARG_BLOCK_ERROR_MSG) unless no_arg
|
|
202
228
|
select(&block).single_value
|
|
229
|
+
else
|
|
230
|
+
select(column).single_value
|
|
203
231
|
end
|
|
204
232
|
end
|
|
205
233
|
|
|
@@ -219,43 +247,47 @@ module Sequel
|
|
|
219
247
|
# DB[:table].import([:x, :y], DB[:table2].select(:a, :b))
|
|
220
248
|
# # INSERT INTO table (x, y) SELECT a, b FROM table2
|
|
221
249
|
#
|
|
222
|
-
#
|
|
223
|
-
#
|
|
224
|
-
#
|
|
225
|
-
#
|
|
226
|
-
#
|
|
227
|
-
#
|
|
250
|
+
# Options:
|
|
251
|
+
# :commit_every :: Open a new transaction for every given number of records.
|
|
252
|
+
# For example, if you provide a value of 50, will commit
|
|
253
|
+
# after every 50 records.
|
|
254
|
+
# :server :: Set the server/shard to use for the transaction and insert
|
|
255
|
+
# queries.
|
|
256
|
+
# :slice :: Same as :commit_every, :commit_every takes precedence.
|
|
228
257
|
def import(columns, values, opts={})
|
|
229
258
|
return @db.transaction{insert(columns, values)} if values.is_a?(Dataset)
|
|
230
259
|
|
|
231
260
|
return if values.empty?
|
|
232
261
|
raise(Error, IMPORT_ERROR_MSG) if columns.empty?
|
|
262
|
+
ds = opts[:server] ? server(opts[:server]) : self
|
|
233
263
|
|
|
234
264
|
if slice_size = opts[:commit_every] || opts[:slice]
|
|
235
265
|
offset = 0
|
|
236
|
-
|
|
237
|
-
|
|
266
|
+
rows = []
|
|
267
|
+
while offset < values.length
|
|
268
|
+
rows << ds._import(columns, values[offset, slice_size], opts)
|
|
238
269
|
offset += slice_size
|
|
239
|
-
break if offset >= values.length
|
|
240
270
|
end
|
|
271
|
+
rows.flatten
|
|
241
272
|
else
|
|
242
|
-
|
|
243
|
-
@db.transaction{statements.each{|st| execute_dui(st)}}
|
|
273
|
+
ds._import(columns, values, opts)
|
|
244
274
|
end
|
|
245
275
|
end
|
|
246
|
-
|
|
276
|
+
|
|
247
277
|
# Inserts values into the associated table. The returned value is generally
|
|
248
278
|
# the value of the primary key for the inserted row, but that is adapter dependent.
|
|
249
279
|
#
|
|
250
280
|
# +insert+ handles a number of different argument formats:
|
|
251
|
-
#
|
|
252
|
-
#
|
|
253
|
-
#
|
|
254
|
-
#
|
|
255
|
-
#
|
|
256
|
-
#
|
|
257
|
-
#
|
|
258
|
-
#
|
|
281
|
+
# no arguments or single empty hash :: Uses DEFAULT VALUES
|
|
282
|
+
# single hash :: Most common format, treats keys as columns an values as values
|
|
283
|
+
# single array :: Treats entries as values, with no columns
|
|
284
|
+
# two arrays :: Treats first array as columns, second array as values
|
|
285
|
+
# single Dataset :: Treats as an insert based on a selection from the dataset given,
|
|
286
|
+
# with no columns
|
|
287
|
+
# array and dataset :: Treats as an insert based on a selection from the dataset
|
|
288
|
+
# given, with the columns given by the array.
|
|
289
|
+
#
|
|
290
|
+
# Examples:
|
|
259
291
|
#
|
|
260
292
|
# DB[:items].insert
|
|
261
293
|
# # INSERT INTO items DEFAULT VALUES
|
|
@@ -277,27 +309,35 @@ module Sequel
|
|
|
277
309
|
#
|
|
278
310
|
# DB[:items].insert([:a, :b], DB[:old_items])
|
|
279
311
|
# # INSERT INTO items (a, b) SELECT * FROM old_items
|
|
280
|
-
def insert(*values)
|
|
281
|
-
|
|
312
|
+
def insert(*values, &block)
|
|
313
|
+
sql = insert_sql(*values)
|
|
314
|
+
if uses_returning?(:insert)
|
|
315
|
+
returning_fetch_rows(sql, &block)
|
|
316
|
+
else
|
|
317
|
+
execute_insert(sql)
|
|
318
|
+
end
|
|
282
319
|
end
|
|
283
320
|
|
|
284
321
|
# Inserts multiple values. If a block is given it is invoked for each
|
|
285
322
|
# item in the given array before inserting it. See +multi_insert+ as
|
|
286
|
-
# a
|
|
287
|
-
# SQL statement.
|
|
323
|
+
# a possibly faster version that may be able to insert multiple
|
|
324
|
+
# records in one SQL statement (if supported by the database).
|
|
325
|
+
# Returns an array of primary keys of inserted rows.
|
|
288
326
|
#
|
|
289
327
|
# DB[:table].insert_multiple([{:x=>1}, {:x=>2}])
|
|
328
|
+
# # => [4, 5]
|
|
290
329
|
# # INSERT INTO table (x) VALUES (1)
|
|
291
330
|
# # INSERT INTO table (x) VALUES (2)
|
|
292
331
|
#
|
|
293
|
-
# DB[:table].insert_multiple([{:x=>1}, {:x=>2}]){|row| row[:y] = row[:x] * 2}
|
|
332
|
+
# DB[:table].insert_multiple([{:x=>1}, {:x=>2}]){|row| row[:y] = row[:x] * 2; row }
|
|
333
|
+
# # => [6, 7]
|
|
294
334
|
# # INSERT INTO table (x, y) VALUES (1, 2)
|
|
295
335
|
# # INSERT INTO table (x, y) VALUES (2, 4)
|
|
296
336
|
def insert_multiple(array, &block)
|
|
297
337
|
if block
|
|
298
|
-
array.
|
|
338
|
+
array.map{|i| insert(block.call(i))}
|
|
299
339
|
else
|
|
300
|
-
array.
|
|
340
|
+
array.map{|i| insert(i)}
|
|
301
341
|
end
|
|
302
342
|
end
|
|
303
343
|
|
|
@@ -310,7 +350,7 @@ module Sequel
|
|
|
310
350
|
aggregate_dataset.get{max(column) - min(column)}
|
|
311
351
|
end
|
|
312
352
|
|
|
313
|
-
# Reverses the order and then runs first. Note that this
|
|
353
|
+
# Reverses the order and then runs #first with the given arguments and block. Note that this
|
|
314
354
|
# will not necessarily give you the last record in the dataset,
|
|
315
355
|
# unless you have an unambiguous order. If there is not
|
|
316
356
|
# currently an order for this dataset, raises an +Error+.
|
|
@@ -318,7 +358,7 @@ module Sequel
|
|
|
318
358
|
# DB[:table].order(:id).last # SELECT * FROM table ORDER BY id DESC LIMIT 1
|
|
319
359
|
# # => {:id=>10}
|
|
320
360
|
#
|
|
321
|
-
# DB[:table].order(:id
|
|
361
|
+
# DB[:table].order(Sequel.desc(:id)).last(2) # SELECT * FROM table ORDER BY id ASC LIMIT 2
|
|
322
362
|
# # => [{:id=>1}, {:id=>2}]
|
|
323
363
|
def last(*args, &block)
|
|
324
364
|
raise(Error, 'No order specified') unless @opts[:order]
|
|
@@ -334,10 +374,20 @@ module Sequel
|
|
|
334
374
|
#
|
|
335
375
|
# DB[:table].map{|r| r[:id] * 2} # SELECT * FROM table
|
|
336
376
|
# # => [2, 4, 6, ...]
|
|
377
|
+
#
|
|
378
|
+
# You can also provide an array of column names:
|
|
379
|
+
#
|
|
380
|
+
# DB[:table].map([:id, :name]) # SELECT * FROM table
|
|
381
|
+
# # => [[1, 'A'], [2, 'B'], [3, 'C'], ...]
|
|
337
382
|
def map(column=nil, &block)
|
|
338
383
|
if column
|
|
339
384
|
raise(Error, ARG_BLOCK_ERROR_MSG) if block
|
|
340
|
-
|
|
385
|
+
return naked.map(column) if row_proc
|
|
386
|
+
if column.is_a?(Array)
|
|
387
|
+
super(){|r| r.values_at(*column)}
|
|
388
|
+
else
|
|
389
|
+
super(){|r| r[column]}
|
|
390
|
+
end
|
|
341
391
|
else
|
|
342
392
|
super(&block)
|
|
343
393
|
end
|
|
@@ -370,7 +420,7 @@ module Sequel
|
|
|
370
420
|
# otherwise some columns could be missed or set to null instead of to default
|
|
371
421
|
# values.
|
|
372
422
|
#
|
|
373
|
-
#
|
|
423
|
+
# This respects the same options as #import.
|
|
374
424
|
def multi_insert(hashes, opts={})
|
|
375
425
|
return if hashes.empty?
|
|
376
426
|
columns = hashes.first.keys
|
|
@@ -389,33 +439,65 @@ module Sequel
|
|
|
389
439
|
end
|
|
390
440
|
|
|
391
441
|
# Returns a hash with key_column values as keys and value_column values as
|
|
392
|
-
# values. Similar to to_hash, but only selects the
|
|
442
|
+
# values. Similar to to_hash, but only selects the columns given.
|
|
393
443
|
#
|
|
394
444
|
# DB[:table].select_hash(:id, :name) # SELECT id, name FROM table
|
|
395
445
|
# # => {1=>'a', 2=>'b', ...}
|
|
446
|
+
#
|
|
447
|
+
# You can also provide an array of column names for either the key_column,
|
|
448
|
+
# the value column, or both:
|
|
449
|
+
#
|
|
450
|
+
# DB[:table].select_hash([:id, :foo], [:name, :bar]) # SELECT * FROM table
|
|
451
|
+
# # {[1, 3]=>['a', 'c'], [2, 4]=>['b', 'd'], ...}
|
|
452
|
+
#
|
|
453
|
+
# When using this method, you must be sure that each expression has an alias
|
|
454
|
+
# that Sequel can determine. Usually you can do this by calling the #as method
|
|
455
|
+
# on the expression and providing an alias.
|
|
396
456
|
def select_hash(key_column, value_column)
|
|
397
|
-
|
|
457
|
+
_select_hash(:to_hash, key_column, value_column)
|
|
398
458
|
end
|
|
399
459
|
|
|
460
|
+
# Returns a hash with key_column values as keys and an array of value_column values.
|
|
461
|
+
# Similar to to_hash_groups, but only selects the columns given.
|
|
462
|
+
#
|
|
463
|
+
# DB[:table].select_hash(:name, :id) # SELECT id, name FROM table
|
|
464
|
+
# # => {'a'=>[1, 4, ...], 'b'=>[2, ...], ...}
|
|
465
|
+
#
|
|
466
|
+
# You can also provide an array of column names for either the key_column,
|
|
467
|
+
# the value column, or both:
|
|
468
|
+
#
|
|
469
|
+
# DB[:table].select_hash([:first, :middle], [:last, :id]) # SELECT * FROM table
|
|
470
|
+
# # {['a', 'b']=>[['c', 1], ['d', 2], ...], ...}
|
|
471
|
+
#
|
|
472
|
+
# When using this method, you must be sure that each expression has an alias
|
|
473
|
+
# that Sequel can determine. Usually you can do this by calling the #as method
|
|
474
|
+
# on the expression and providing an alias.
|
|
475
|
+
def select_hash_groups(key_column, value_column)
|
|
476
|
+
_select_hash(:to_hash_groups, key_column, value_column)
|
|
477
|
+
end
|
|
478
|
+
|
|
400
479
|
# Selects the column given (either as an argument or as a block), and
|
|
401
480
|
# returns an array of all values of that column in the dataset. If you
|
|
402
481
|
# give a block argument that returns an array with multiple entries,
|
|
403
|
-
# the contents of the resulting array are undefined.
|
|
482
|
+
# the contents of the resulting array are undefined. Raises an Error
|
|
483
|
+
# if called with both an argument and a block.
|
|
404
484
|
#
|
|
405
485
|
# DB[:table].select_map(:id) # SELECT id FROM table
|
|
406
486
|
# # => [3, 5, 8, 1, ...]
|
|
407
487
|
#
|
|
408
|
-
# DB[:table].select_map{
|
|
409
|
-
# # => [
|
|
488
|
+
# DB[:table].select_map{id * 2} # SELECT (id * 2) FROM table
|
|
489
|
+
# # => [6, 10, 16, 2, ...]
|
|
490
|
+
#
|
|
491
|
+
# You can also provide an array of column names:
|
|
492
|
+
#
|
|
493
|
+
# DB[:table].select_map([:id, :name]) # SELECT id, name FROM table
|
|
494
|
+
# # => [[1, 'A'], [2, 'B'], [3, 'C'], ...]
|
|
495
|
+
#
|
|
496
|
+
# If you provide an array of expressions, you must be sure that each entry
|
|
497
|
+
# in the array has an alias that Sequel can determine. Usually you can do this
|
|
498
|
+
# by calling the #as method on the expression and providing an alias.
|
|
410
499
|
def select_map(column=nil, &block)
|
|
411
|
-
|
|
412
|
-
ds = if column
|
|
413
|
-
raise(Error, ARG_BLOCK_ERROR_MSG) if block
|
|
414
|
-
ds.select(column)
|
|
415
|
-
else
|
|
416
|
-
ds.select(&block)
|
|
417
|
-
end
|
|
418
|
-
ds.map{|r| r.values.first}
|
|
500
|
+
_select_map(column, false, &block)
|
|
419
501
|
end
|
|
420
502
|
|
|
421
503
|
# The same as select_map, but in addition orders the array by the column.
|
|
@@ -423,19 +505,21 @@ module Sequel
|
|
|
423
505
|
# DB[:table].select_order_map(:id) # SELECT id FROM table ORDER BY id
|
|
424
506
|
# # => [1, 2, 3, 4, ...]
|
|
425
507
|
#
|
|
426
|
-
# DB[:table].select_order_map{
|
|
427
|
-
# # => [
|
|
508
|
+
# DB[:table].select_order_map{id * 2} # SELECT (id * 2) FROM table ORDER BY (id * 2)
|
|
509
|
+
# # => [2, 4, 6, 8, ...]
|
|
510
|
+
#
|
|
511
|
+
# You can also provide an array of column names:
|
|
512
|
+
#
|
|
513
|
+
# DB[:table].select_order_map([:id, :name]) # SELECT id, name FROM table ORDER BY id, name
|
|
514
|
+
# # => [[1, 'A'], [2, 'B'], [3, 'C'], ...]
|
|
515
|
+
#
|
|
516
|
+
# If you provide an array of expressions, you must be sure that each entry
|
|
517
|
+
# in the array has an alias that Sequel can determine. Usually you can do this
|
|
518
|
+
# by calling the #as method on the expression and providing an alias.
|
|
428
519
|
def select_order_map(column=nil, &block)
|
|
429
|
-
|
|
430
|
-
ds = if column
|
|
431
|
-
raise(Error, ARG_BLOCK_ERROR_MSG) if block
|
|
432
|
-
ds.select(column).order(unaliased_identifier(column))
|
|
433
|
-
else
|
|
434
|
-
ds.select(&block).order(&block)
|
|
435
|
-
end
|
|
436
|
-
ds.map{|r| r.values.first}
|
|
520
|
+
_select_map(column, true, &block)
|
|
437
521
|
end
|
|
438
|
-
|
|
522
|
+
|
|
439
523
|
# Alias for update, but not aliased directly so subclasses
|
|
440
524
|
# don't have to override both methods.
|
|
441
525
|
def set(*args)
|
|
@@ -499,11 +583,81 @@ module Sequel
|
|
|
499
583
|
#
|
|
500
584
|
# DB[:table].to_hash(:id) # SELECT * FROM table
|
|
501
585
|
# # {1=>{:id=>1, :name=>'Jim'}, 2=>{:id=>2, :name=>'Bob'}, ...}
|
|
586
|
+
#
|
|
587
|
+
# You can also provide an array of column names for either the key_column,
|
|
588
|
+
# the value column, or both:
|
|
589
|
+
#
|
|
590
|
+
# DB[:table].to_hash([:id, :foo], [:name, :bar]) # SELECT * FROM table
|
|
591
|
+
# # {[1, 3]=>['Jim', 'bo'], [2, 4]=>['Bob', 'be'], ...}
|
|
592
|
+
#
|
|
593
|
+
# DB[:table].to_hash([:id, :name]) # SELECT * FROM table
|
|
594
|
+
# # {[1, 'Jim']=>{:id=>1, :name=>'Jim'}, [2, 'Bob'=>{:id=>2, :name=>'Bob'}, ...}
|
|
502
595
|
def to_hash(key_column, value_column = nil)
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
596
|
+
h = {}
|
|
597
|
+
if value_column
|
|
598
|
+
return naked.to_hash(key_column, value_column) if row_proc
|
|
599
|
+
if value_column.is_a?(Array)
|
|
600
|
+
if key_column.is_a?(Array)
|
|
601
|
+
each{|r| h[r.values_at(*key_column)] = r.values_at(*value_column)}
|
|
602
|
+
else
|
|
603
|
+
each{|r| h[r[key_column]] = r.values_at(*value_column)}
|
|
604
|
+
end
|
|
605
|
+
else
|
|
606
|
+
if key_column.is_a?(Array)
|
|
607
|
+
each{|r| h[r.values_at(*key_column)] = r[value_column]}
|
|
608
|
+
else
|
|
609
|
+
each{|r| h[r[key_column]] = r[value_column]}
|
|
610
|
+
end
|
|
611
|
+
end
|
|
612
|
+
elsif key_column.is_a?(Array)
|
|
613
|
+
each{|r| h[r.values_at(*key_column)] = r}
|
|
614
|
+
else
|
|
615
|
+
each{|r| h[r[key_column]] = r}
|
|
616
|
+
end
|
|
617
|
+
h
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
# Returns a hash with one column used as key and the values being an
|
|
621
|
+
# array of column values. If the value_column is not given or nil, uses
|
|
622
|
+
# the entire hash as the value.
|
|
623
|
+
#
|
|
624
|
+
# DB[:table].to_hash(:name, :id) # SELECT * FROM table
|
|
625
|
+
# # {'Jim'=>[1, 4, 16, ...], 'Bob'=>[2], ...}
|
|
626
|
+
#
|
|
627
|
+
# DB[:table].to_hash(:name) # SELECT * FROM table
|
|
628
|
+
# # {'Jim'=>[{:id=>1, :name=>'Jim'}, {:id=>4, :name=>'Jim'}, ...], 'Bob'=>[{:id=>2, :name=>'Bob'}], ...}
|
|
629
|
+
#
|
|
630
|
+
# You can also provide an array of column names for either the key_column,
|
|
631
|
+
# the value column, or both:
|
|
632
|
+
#
|
|
633
|
+
# DB[:table].to_hash([:first, :middle], [:last, :id]) # SELECT * FROM table
|
|
634
|
+
# # {['Jim', 'Bob']=>[['Smith', 1], ['Jackson', 4], ...], ...}
|
|
635
|
+
#
|
|
636
|
+
# DB[:table].to_hash([:first, :middle]) # SELECT * FROM table
|
|
637
|
+
# # {['Jim', 'Bob']=>[{:id=>1, :first=>'Jim', :middle=>'Bob', :last=>'Smith'}, ...], ...}
|
|
638
|
+
def to_hash_groups(key_column, value_column = nil)
|
|
639
|
+
h = {}
|
|
640
|
+
if value_column
|
|
641
|
+
return naked.to_hash_groups(key_column, value_column) if row_proc
|
|
642
|
+
if value_column.is_a?(Array)
|
|
643
|
+
if key_column.is_a?(Array)
|
|
644
|
+
each{|r| (h[r.values_at(*key_column)] ||= []) << r.values_at(*value_column)}
|
|
645
|
+
else
|
|
646
|
+
each{|r| (h[r[key_column]] ||= []) << r.values_at(*value_column)}
|
|
647
|
+
end
|
|
648
|
+
else
|
|
649
|
+
if key_column.is_a?(Array)
|
|
650
|
+
each{|r| (h[r.values_at(*key_column)] ||= []) << r[value_column]}
|
|
651
|
+
else
|
|
652
|
+
each{|r| (h[r[key_column]] ||= []) << r[value_column]}
|
|
653
|
+
end
|
|
654
|
+
end
|
|
655
|
+
elsif key_column.is_a?(Array)
|
|
656
|
+
each{|r| (h[r.values_at(*key_column)] ||= []) << r}
|
|
657
|
+
else
|
|
658
|
+
each{|r| (h[r[key_column]] ||= []) << r}
|
|
506
659
|
end
|
|
660
|
+
h
|
|
507
661
|
end
|
|
508
662
|
|
|
509
663
|
# Truncates the dataset. Returns nil.
|
|
@@ -522,14 +676,81 @@ module Sequel
|
|
|
522
676
|
# DB[:table].update(:x=>nil) # UPDATE table SET x = NULL
|
|
523
677
|
# # => 10
|
|
524
678
|
#
|
|
525
|
-
# DB[:table].update(:x=>:x+1, :y=>0) # UPDATE table SET x = (x + 1),
|
|
679
|
+
# DB[:table].update(:x=>:x+1, :y=>0) # UPDATE table SET x = (x + 1), y = 0
|
|
526
680
|
# # => 10
|
|
527
|
-
def update(values={})
|
|
528
|
-
|
|
681
|
+
def update(values={}, &block)
|
|
682
|
+
sql = update_sql(values)
|
|
683
|
+
if uses_returning?(:update)
|
|
684
|
+
returning_fetch_rows(sql, &block)
|
|
685
|
+
else
|
|
686
|
+
execute_dui(sql)
|
|
687
|
+
end
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
# Execute the given SQL and return the number of rows deleted. This exists
|
|
691
|
+
# solely as an optimization, replacing with_sql(sql).delete. It's significantly
|
|
692
|
+
# faster as it does not require cloning the current dataset.
|
|
693
|
+
def with_sql_delete(sql)
|
|
694
|
+
execute_dui(sql)
|
|
529
695
|
end
|
|
530
696
|
|
|
697
|
+
protected
|
|
698
|
+
|
|
699
|
+
# Internals of #import. If primary key values are requested, use
|
|
700
|
+
# separate insert commands for each row. Otherwise, call #multi_insert_sql
|
|
701
|
+
# and execute each statement it gives separately.
|
|
702
|
+
def _import(columns, values, opts)
|
|
703
|
+
trans_opts = opts.merge(:server=>@opts[:server])
|
|
704
|
+
if opts[:return] == :primary_key
|
|
705
|
+
@db.transaction(trans_opts){values.map{|v| insert(columns, v)}}
|
|
706
|
+
else
|
|
707
|
+
stmts = multi_insert_sql(columns, values)
|
|
708
|
+
@db.transaction(trans_opts){stmts.each{|st| execute_dui(st)}}
|
|
709
|
+
end
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
# Return an array of arrays of values given by the symbols in ret_cols.
|
|
713
|
+
def _select_map_multiple(ret_cols)
|
|
714
|
+
map{|r| r.values_at(*ret_cols)}
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
# Returns an array of the first value in each row.
|
|
718
|
+
def _select_map_single
|
|
719
|
+
map{|r| r.values.first}
|
|
720
|
+
end
|
|
721
|
+
|
|
531
722
|
private
|
|
532
723
|
|
|
724
|
+
# Internals of +select_hash+ and +select_hash_groups+
|
|
725
|
+
def _select_hash(meth, key_column, value_column)
|
|
726
|
+
if key_column.is_a?(Array)
|
|
727
|
+
if value_column.is_a?(Array)
|
|
728
|
+
select(*(key_column + value_column)).send(meth, key_column.map{|c| hash_key_symbol(c)}, value_column.map{|c| hash_key_symbol(c)})
|
|
729
|
+
else
|
|
730
|
+
select(*(key_column + [value_column])).send(meth, key_column.map{|c| hash_key_symbol(c)}, hash_key_symbol(value_column))
|
|
731
|
+
end
|
|
732
|
+
elsif value_column.is_a?(Array)
|
|
733
|
+
select(key_column, *value_column).send(meth, hash_key_symbol(key_column), value_column.map{|c| hash_key_symbol(c)})
|
|
734
|
+
else
|
|
735
|
+
select(key_column, value_column).send(meth, hash_key_symbol(key_column), hash_key_symbol(value_column))
|
|
736
|
+
end
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
# Internals of +select_map+ and +select_order_map+
|
|
740
|
+
def _select_map(column, order, &block)
|
|
741
|
+
ds = naked.ungraphed
|
|
742
|
+
columns = Array(column)
|
|
743
|
+
virtual_row_columns(columns, block)
|
|
744
|
+
select_cols = order ? columns.map{|c| c.is_a?(SQL::OrderedExpression) ? c.expression : c} : columns
|
|
745
|
+
ds = ds.select(*select_cols)
|
|
746
|
+
ds = ds.order(*columns.map{|c| unaliased_identifier(c)}) if order
|
|
747
|
+
if column.is_a?(Array) || (columns.length > 1)
|
|
748
|
+
ds._select_map_multiple(select_cols.map{|c| hash_key_symbol(c)})
|
|
749
|
+
else
|
|
750
|
+
ds._select_map_single
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
|
|
533
754
|
# Set the server to use to :default unless it is already set in the passed opts
|
|
534
755
|
def default_server_opts(opts)
|
|
535
756
|
{:server=>@opts[:server] || :default}.merge(opts)
|
|
@@ -561,9 +782,21 @@ module Sequel
|
|
|
561
782
|
# specifying the symbol that is likely to be used as the hash key
|
|
562
783
|
# for the column when records are returned.
|
|
563
784
|
def hash_key_symbol(s)
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
785
|
+
case s
|
|
786
|
+
when Symbol
|
|
787
|
+
_, c, a = split_symbol(s)
|
|
788
|
+
(a || c).to_sym
|
|
789
|
+
when SQL::Identifier, SQL::Wrapper
|
|
790
|
+
hash_key_symbol(s.value)
|
|
791
|
+
when SQL::QualifiedIdentifier
|
|
792
|
+
hash_key_symbol(s.column)
|
|
793
|
+
when SQL::AliasedExpression
|
|
794
|
+
hash_key_symbol(s.aliaz)
|
|
795
|
+
when String
|
|
796
|
+
s.to_sym
|
|
797
|
+
else
|
|
798
|
+
raise(Error, "#{s.inspect} is not supported, should be a Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier, or SQL::AliasedExpression")
|
|
799
|
+
end
|
|
567
800
|
end
|
|
568
801
|
|
|
569
802
|
# Modify the identifier returned from the database based on the
|
|
@@ -580,6 +813,20 @@ module Sequel
|
|
|
580
813
|
def post_load(all_records)
|
|
581
814
|
end
|
|
582
815
|
|
|
816
|
+
# Called by insert/update/delete when returning is used.
|
|
817
|
+
# Yields each row as a plain hash to the block if one is given, or returns
|
|
818
|
+
# an array of plain hashes for all rows if a block is not given
|
|
819
|
+
def returning_fetch_rows(sql, &block)
|
|
820
|
+
if block
|
|
821
|
+
default_server.fetch_rows(sql, &block)
|
|
822
|
+
nil
|
|
823
|
+
else
|
|
824
|
+
rows = []
|
|
825
|
+
default_server.fetch_rows(sql){|r| rows << r}
|
|
826
|
+
rows
|
|
827
|
+
end
|
|
828
|
+
end
|
|
829
|
+
|
|
583
830
|
# Return the unaliased part of the identifier. Handles both
|
|
584
831
|
# implicit aliases in symbols, as well as SQL::AliasedExpression
|
|
585
832
|
# objects. Other objects are returned as is.
|
|
@@ -590,6 +837,13 @@ module Sequel
|
|
|
590
837
|
c_table ? SQL::QualifiedIdentifier.new(c_table, column.to_sym) : column.to_sym
|
|
591
838
|
when SQL::AliasedExpression
|
|
592
839
|
c.expression
|
|
840
|
+
when SQL::OrderedExpression
|
|
841
|
+
case expr = c.expression
|
|
842
|
+
when Symbol, SQL::AliasedExpression
|
|
843
|
+
SQL::OrderedExpression.new(unaliased_identifier(expr), c.descending, :nulls=>c.nulls)
|
|
844
|
+
else
|
|
845
|
+
c
|
|
846
|
+
end
|
|
593
847
|
else
|
|
594
848
|
c
|
|
595
849
|
end
|