sequel 2.11.0 → 2.12.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +168 -0
- data/README.rdoc +77 -95
- data/Rakefile +100 -80
- data/bin/sequel +2 -1
- data/doc/advanced_associations.rdoc +23 -32
- data/doc/cheat_sheet.rdoc +23 -40
- data/doc/dataset_filtering.rdoc +6 -6
- data/doc/prepared_statements.rdoc +22 -22
- data/doc/release_notes/2.12.0.txt +534 -0
- data/doc/schema.rdoc +3 -1
- data/doc/sharding.rdoc +8 -8
- data/doc/virtual_rows.rdoc +65 -0
- data/lib/sequel.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/ado.rb +3 -3
- data/lib/{sequel_core → sequel}/adapters/db2.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/dbi.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/do.rb +9 -5
- data/lib/{sequel_core → sequel}/adapters/do/mysql.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/do/postgres.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/do/sqlite.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/firebird.rb +84 -80
- data/lib/{sequel_core → sequel}/adapters/informix.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc.rb +21 -14
- data/lib/{sequel_core → sequel}/adapters/jdbc/h2.rb +14 -13
- data/lib/{sequel_core → sequel}/adapters/jdbc/mysql.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc/oracle.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc/postgresql.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc/sqlite.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/mysql.rb +60 -39
- data/lib/{sequel_core → sequel}/adapters/odbc.rb +8 -4
- data/lib/{sequel_core → sequel}/adapters/openbase.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/oracle.rb +38 -7
- data/lib/{sequel_core → sequel}/adapters/postgres.rb +24 -24
- data/lib/{sequel_core → sequel}/adapters/shared/mssql.rb +5 -5
- data/lib/{sequel_core → sequel}/adapters/shared/mysql.rb +126 -71
- data/lib/{sequel_core → sequel}/adapters/shared/oracle.rb +7 -10
- data/lib/{sequel_core → sequel}/adapters/shared/postgres.rb +159 -125
- data/lib/{sequel_core → sequel}/adapters/shared/progress.rb +1 -2
- data/lib/{sequel_core → sequel}/adapters/shared/sqlite.rb +72 -67
- data/lib/{sequel_core → sequel}/adapters/sqlite.rb +11 -7
- data/lib/{sequel_core → sequel}/adapters/utils/date_format.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/utils/stored_procedures.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/utils/unsupported.rb +19 -0
- data/lib/{sequel_core → sequel}/connection_pool.rb +7 -5
- data/lib/sequel/core.rb +221 -0
- data/lib/{sequel_core → sequel}/core_sql.rb +91 -49
- data/lib/{sequel_core → sequel}/database.rb +264 -149
- data/lib/{sequel_core/schema/generator.rb → sequel/database/schema_generator.rb} +6 -2
- data/lib/{sequel_core/database/schema.rb → sequel/database/schema_methods.rb} +12 -12
- data/lib/sequel/database/schema_sql.rb +224 -0
- data/lib/{sequel_core → sequel}/dataset.rb +78 -236
- data/lib/{sequel_core → sequel}/dataset/convenience.rb +99 -61
- data/lib/{sequel_core/object_graph.rb → sequel/dataset/graph.rb} +16 -14
- data/lib/{sequel_core → sequel}/dataset/prepared_statements.rb +1 -1
- data/lib/{sequel_core → sequel}/dataset/sql.rb +150 -99
- data/lib/sequel/deprecated.rb +593 -0
- data/lib/sequel/deprecated_migration.rb +91 -0
- data/lib/sequel/exceptions.rb +48 -0
- data/lib/sequel/extensions/blank.rb +42 -0
- data/lib/{sequel_model → sequel/extensions}/inflector.rb +8 -1
- data/lib/{sequel_core → sequel/extensions}/migration.rb +1 -1
- data/lib/{sequel_core/dataset → sequel/extensions}/pagination.rb +0 -0
- data/lib/{sequel_core → sequel/extensions}/pretty_table.rb +7 -0
- data/lib/{sequel_core/dataset → sequel/extensions}/query.rb +7 -0
- data/lib/sequel/extensions/string_date_time.rb +47 -0
- data/lib/sequel/metaprogramming.rb +43 -0
- data/lib/sequel/model.rb +110 -0
- data/lib/sequel/model/associations.rb +1300 -0
- data/lib/sequel/model/base.rb +937 -0
- data/lib/sequel/model/deprecated.rb +204 -0
- data/lib/sequel/model/deprecated_hooks.rb +103 -0
- data/lib/sequel/model/deprecated_inflector.rb +335 -0
- data/lib/sequel/model/deprecated_validations.rb +388 -0
- data/lib/sequel/model/errors.rb +39 -0
- data/lib/{sequel_model → sequel/model}/exceptions.rb +4 -4
- data/lib/sequel/model/inflections.rb +208 -0
- data/lib/sequel/model/plugins.rb +76 -0
- data/lib/sequel/plugins/caching.rb +122 -0
- data/lib/sequel/plugins/hook_class_methods.rb +122 -0
- data/lib/sequel/plugins/schema.rb +53 -0
- data/lib/sequel/plugins/serialization.rb +117 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
- data/lib/sequel/plugins/validation_class_methods.rb +384 -0
- data/lib/sequel/plugins/validation_helpers.rb +150 -0
- data/lib/{sequel_core → sequel}/sql.rb +125 -190
- data/lib/{sequel_core → sequel}/version.rb +2 -1
- data/lib/sequel_core.rb +1 -172
- data/lib/sequel_model.rb +1 -91
- data/spec/adapters/firebird_spec.rb +5 -5
- data/spec/adapters/informix_spec.rb +1 -1
- data/spec/adapters/mysql_spec.rb +128 -42
- data/spec/adapters/oracle_spec.rb +47 -19
- data/spec/adapters/postgres_spec.rb +64 -52
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +12 -17
- data/spec/{sequel_core → core}/connection_pool_spec.rb +10 -10
- data/spec/{sequel_core → core}/core_ext_spec.rb +19 -19
- data/spec/{sequel_core → core}/core_sql_spec.rb +68 -71
- data/spec/{sequel_core → core}/database_spec.rb +135 -99
- data/spec/{sequel_core → core}/dataset_spec.rb +398 -242
- data/spec/{sequel_core → core}/expression_filters_spec.rb +13 -13
- data/spec/core/migration_spec.rb +263 -0
- data/spec/{sequel_core → core}/object_graph_spec.rb +10 -10
- data/spec/{sequel_core → core}/pretty_table_spec.rb +2 -2
- data/spec/{sequel_core → core}/schema_generator_spec.rb +0 -0
- data/spec/{sequel_core → core}/schema_spec.rb +8 -10
- data/spec/{sequel_core → core}/spec_helper.rb +29 -2
- data/spec/{sequel_core → core}/version_spec.rb +0 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/caching_spec.rb +201 -0
- data/spec/{sequel_model/hooks_spec.rb → extensions/hook_class_methods_spec.rb} +8 -23
- data/spec/{sequel_model → extensions}/inflector_spec.rb +3 -0
- data/spec/{sequel_core → extensions}/migration_spec.rb +4 -4
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/{sequel_model → extensions}/schema_spec.rb +22 -1
- data/spec/extensions/serialization_spec.rb +109 -0
- data/spec/extensions/single_table_inheritance_spec.rb +53 -0
- data/spec/{sequel_model → extensions}/spec_helper.rb +13 -4
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/{sequel_model/validations_spec.rb → extensions/validation_class_methods_spec.rb} +15 -103
- data/spec/extensions/validation_helpers_spec.rb +291 -0
- data/spec/integration/dataset_test.rb +31 -0
- data/spec/integration/eager_loader_test.rb +17 -30
- data/spec/integration/schema_test.rb +8 -5
- data/spec/integration/spec_helper.rb +17 -0
- data/spec/integration/transaction_test.rb +68 -0
- data/spec/{sequel_model → model}/association_reflection_spec.rb +0 -0
- data/spec/{sequel_model → model}/associations_spec.rb +23 -10
- data/spec/{sequel_model → model}/base_spec.rb +29 -20
- data/spec/{sequel_model → model}/caching_spec.rb +16 -14
- data/spec/{sequel_model → model}/dataset_methods_spec.rb +0 -0
- data/spec/{sequel_model → model}/eager_loading_spec.rb +8 -8
- data/spec/model/hooks_spec.rb +472 -0
- data/spec/model/inflector_spec.rb +126 -0
- data/spec/{sequel_model → model}/model_spec.rb +25 -20
- data/spec/model/plugins_spec.rb +142 -0
- data/spec/{sequel_model → model}/record_spec.rb +121 -62
- data/spec/model/schema_spec.rb +92 -0
- data/spec/model/spec_helper.rb +124 -0
- data/spec/model/validations_spec.rb +1080 -0
- metadata +136 -107
- data/lib/sequel_core/core_ext.rb +0 -217
- data/lib/sequel_core/dataset/callback.rb +0 -13
- data/lib/sequel_core/dataset/schema.rb +0 -15
- data/lib/sequel_core/deprecated.rb +0 -26
- data/lib/sequel_core/exceptions.rb +0 -44
- data/lib/sequel_core/schema.rb +0 -2
- data/lib/sequel_core/schema/sql.rb +0 -325
- data/lib/sequel_model/association_reflection.rb +0 -267
- data/lib/sequel_model/associations.rb +0 -499
- data/lib/sequel_model/base.rb +0 -539
- data/lib/sequel_model/caching.rb +0 -82
- data/lib/sequel_model/dataset_methods.rb +0 -26
- data/lib/sequel_model/eager_loading.rb +0 -370
- data/lib/sequel_model/hooks.rb +0 -101
- data/lib/sequel_model/plugins.rb +0 -62
- data/lib/sequel_model/record.rb +0 -568
- data/lib/sequel_model/schema.rb +0 -49
- data/lib/sequel_model/validations.rb +0 -429
- data/spec/sequel_model/plugins_spec.rb +0 -80
data/lib/sequel_core.rb
CHANGED
@@ -1,172 +1 @@
|
|
1
|
-
|
2
|
-
require f
|
3
|
-
end
|
4
|
-
%w"core_ext sql core_sql connection_pool exceptions pretty_table
|
5
|
-
dataset migration schema database object_graph version".each do |f|
|
6
|
-
require "sequel_core/#{f}"
|
7
|
-
end
|
8
|
-
|
9
|
-
# Top level module for Sequel
|
10
|
-
#
|
11
|
-
# There are some class methods that are added via metaprogramming, one for
|
12
|
-
# each supported adapter. For example:
|
13
|
-
#
|
14
|
-
# DB = Sequel.sqlite # Memory database
|
15
|
-
# DB = Sequel.sqlite('blog.db')
|
16
|
-
# DB = Sequel.postgres('database_name', :user=>'user',
|
17
|
-
# :password=>'password', :host=>'host', :port=>5432,
|
18
|
-
# :max_connections=>10)
|
19
|
-
#
|
20
|
-
# If a block is given to these methods, it is passed the opened Database
|
21
|
-
# object, which is closed (disconnected) when the block exits. For example:
|
22
|
-
#
|
23
|
-
# Sequel.sqlite('blog.db'){|db| puts db.users.count}
|
24
|
-
#
|
25
|
-
# Sequel converts the column type tinyint to a boolean by default,
|
26
|
-
# you can override the conversion to use tinyint as an integer:
|
27
|
-
#
|
28
|
-
# Sequel.convert_tinyint_to_bool = false
|
29
|
-
#
|
30
|
-
# Sequel converts two digit years in Dates and DateTimes by default,
|
31
|
-
# so 01/02/03 is interpreted at January 2nd, 2003, and 12/13/99 is interpreted
|
32
|
-
# as December 13, 1999.. You can override this # to treat those dates as
|
33
|
-
# January 2nd, 0003 and December 13, 0099, respectively, by setting:
|
34
|
-
#
|
35
|
-
# Sequel.convert_two_digit_years = false
|
36
|
-
#
|
37
|
-
# Sequel can use either Time or DateTime for times returned from the
|
38
|
-
# database. It defaults to Time. To change it to DateTime, use:
|
39
|
-
#
|
40
|
-
# Sequel.datetime_class = DateTime
|
41
|
-
module Sequel
|
42
|
-
@convert_tinyint_to_bool = true
|
43
|
-
@convert_two_digit_years = true
|
44
|
-
@datetime_class = Time
|
45
|
-
|
46
|
-
metaattr_accessor :convert_tinyint_to_bool
|
47
|
-
metaattr_accessor :convert_two_digit_years
|
48
|
-
metaattr_accessor :datetime_class
|
49
|
-
|
50
|
-
# Creates a new database object based on the supplied connection string
|
51
|
-
# and optional arguments. The specified scheme determines the database
|
52
|
-
# class used, and the rest of the string specifies the connection options.
|
53
|
-
# For example:
|
54
|
-
#
|
55
|
-
# DB = Sequel.connect('sqlite:/') # Memory database
|
56
|
-
# DB = Sequel.connect('sqlite://blog.db') # ./blog.db
|
57
|
-
# DB = Sequel.connect('sqlite:///blog.db') # /blog.db
|
58
|
-
# DB = Sequel.connect('postgres://user:password@host:port/database_name')
|
59
|
-
# DB = Sequel.connect('sqlite:///blog.db', :max_connections=>10)
|
60
|
-
#
|
61
|
-
# If a block is given, it is passed the opened Database object, which is
|
62
|
-
# closed when the block exits. For example:
|
63
|
-
#
|
64
|
-
# Sequel.connect('sqlite://blog.db'){|db| puts db.users.count}
|
65
|
-
#
|
66
|
-
# This is also aliased as Sequel.open.
|
67
|
-
def self.connect(*args, &block)
|
68
|
-
Database.connect(*args, &block)
|
69
|
-
end
|
70
|
-
metaalias :open, :connect
|
71
|
-
|
72
|
-
# Set the method to call on identifiers going into the database. This affects
|
73
|
-
# the literalization of identifiers by calling this method on them before they are input.
|
74
|
-
# Sequel upcases identifiers in all SQL strings for most databases, so to turn that off:
|
75
|
-
#
|
76
|
-
# Sequel.identifier_input_method = nil
|
77
|
-
#
|
78
|
-
# to downcase instead:
|
79
|
-
#
|
80
|
-
# Sequel.identifier_input_method = :downcase
|
81
|
-
#
|
82
|
-
# Other string methods work as well.
|
83
|
-
def self.identifier_input_method=(value)
|
84
|
-
Database.identifier_input_method = value
|
85
|
-
end
|
86
|
-
|
87
|
-
# Set the method to call on identifiers coming out of the database. This affects
|
88
|
-
# the literalization of identifiers by calling this method on them when they are
|
89
|
-
# retrieved from the database. Sequel downcases identifiers retrieved for most
|
90
|
-
# databases, so to turn that off:
|
91
|
-
#
|
92
|
-
# Sequel.identifier_output_method = nil
|
93
|
-
#
|
94
|
-
# to upcase instead:
|
95
|
-
#
|
96
|
-
# Sequel.identifier_output_method = :upcase
|
97
|
-
#
|
98
|
-
# Other string methods work as well.
|
99
|
-
def self.identifier_output_method=(value)
|
100
|
-
Database.identifier_output_method = value
|
101
|
-
end
|
102
|
-
|
103
|
-
# Set whether to quote identifiers for all databases by default. By default,
|
104
|
-
# Sequel quotes identifiers in all SQL strings, so to turn that off:
|
105
|
-
#
|
106
|
-
# Sequel.quote_identifiers = false
|
107
|
-
def self.quote_identifiers=(value)
|
108
|
-
Database.quote_identifiers = value
|
109
|
-
end
|
110
|
-
|
111
|
-
# Set whether to set the single threaded mode for all databases by default. By default,
|
112
|
-
# Sequel uses a threadsafe connection pool, which isn't as fast as the
|
113
|
-
# single threaded connection pool. If your program will only have one thread,
|
114
|
-
# and speed is a priority, you may want to set this to true:
|
115
|
-
#
|
116
|
-
# Sequel.single_threaded = true
|
117
|
-
def self.single_threaded=(value)
|
118
|
-
Database.single_threaded = value
|
119
|
-
end
|
120
|
-
|
121
|
-
# Set whether to upcase identifiers for all databases by default. By default,
|
122
|
-
# Sequel upcases identifiers unless the database folds unquoted identifiers to
|
123
|
-
# lower case (MySQL, PostgreSQL, and SQLite).
|
124
|
-
#
|
125
|
-
# Sequel.upcase_identifiers = false
|
126
|
-
#
|
127
|
-
# This will set the indentifier_input_method to :upcase if value is true
|
128
|
-
# or nil if value is false.
|
129
|
-
def self.upcase_identifiers=(value)
|
130
|
-
Database.upcase_identifiers = value
|
131
|
-
end
|
132
|
-
|
133
|
-
# Always returns false, since ParseTree support has been removed.
|
134
|
-
def self.use_parse_tree
|
135
|
-
false
|
136
|
-
end
|
137
|
-
|
138
|
-
# Raises an error if attempting to turn ParseTree support on (since it no longer exists).
|
139
|
-
# Otherwise, is a no-op.
|
140
|
-
def self.use_parse_tree=(val)
|
141
|
-
raise(Error, 'ParseTree support has been removed from Sequel') if val
|
142
|
-
end
|
143
|
-
|
144
|
-
### Private Class Methods ###
|
145
|
-
|
146
|
-
# Helper method that the database adapter class methods that are added to Sequel via
|
147
|
-
# metaprogramming use to parse arguments.
|
148
|
-
def self.adapter_method(adapter, *args, &block) # :nodoc:
|
149
|
-
raise(::Sequel::Error, "Wrong number of arguments, 0-2 arguments valid") if args.length > 2
|
150
|
-
opts = {:adapter=>adapter.to_sym}
|
151
|
-
opts[:database] = args.shift if args.length >= 1 && !(args[0].is_a?(Hash))
|
152
|
-
if Hash === (arg = args[0])
|
153
|
-
opts.merge!(arg)
|
154
|
-
elsif !arg.nil?
|
155
|
-
raise ::Sequel::Error, "Wrong format of arguments, either use (), (String), (Hash), or (String, Hash)"
|
156
|
-
end
|
157
|
-
connect(opts, &block)
|
158
|
-
end
|
159
|
-
|
160
|
-
# Method that adds a database adapter class method to Sequel that calls
|
161
|
-
# Sequel.adapter_method.
|
162
|
-
def self.def_adapter_method(*adapters) # :nodoc:
|
163
|
-
adapters.each do |adapter|
|
164
|
-
instance_eval("def #{adapter}(*args, &block); adapter_method('#{adapter}', *args, &block) end")
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
private_class_method :adapter_method, :def_adapter_method
|
169
|
-
|
170
|
-
# Add the database adapter class methods to Sequel via metaprogramming
|
171
|
-
def_adapter_method(*Database::ADAPTERS)
|
172
|
-
end
|
1
|
+
require 'sequel/core'
|
data/lib/sequel_model.rb
CHANGED
@@ -1,91 +1 @@
|
|
1
|
-
require '
|
2
|
-
%w"inflector base hooks record schema association_reflection dataset_methods
|
3
|
-
associations caching plugins validations eager_loading exceptions".each do |f|
|
4
|
-
require "sequel_model/#{f}"
|
5
|
-
end
|
6
|
-
|
7
|
-
module Sequel
|
8
|
-
# Holds the nameless subclasses that are created with
|
9
|
-
# Sequel::Model(), necessary for reopening subclasses with the
|
10
|
-
# Sequel::Model() superclass specified.
|
11
|
-
@models = {}
|
12
|
-
|
13
|
-
# Lets you create a Model subclass with its dataset already set.
|
14
|
-
# source can be an existing dataset or a symbol (in which case
|
15
|
-
# it will create a dataset using the default database with
|
16
|
-
# source as the table name).
|
17
|
-
#
|
18
|
-
# Example:
|
19
|
-
# class Comment < Sequel::Model(:something)
|
20
|
-
# table_name # => :something
|
21
|
-
# end
|
22
|
-
def self.Model(source)
|
23
|
-
@models[source] ||= Class.new(Model).set_dataset(source)
|
24
|
-
end
|
25
|
-
|
26
|
-
# Model has some methods that are added via metaprogramming:
|
27
|
-
#
|
28
|
-
# * All of the methods in DATASET_METHODS have class methods created that call
|
29
|
-
# the Model's dataset with the method of the same name with the given
|
30
|
-
# arguments.
|
31
|
-
# * All of the methods in HOOKS have class methods created that accept
|
32
|
-
# either a method name symbol or an optional tag and a block. These
|
33
|
-
# methods run the code as a callback at the specified time. For example:
|
34
|
-
#
|
35
|
-
# Model.before_save :do_something
|
36
|
-
# Model.before_save(:do_something_else){ self.something_else = 42}
|
37
|
-
# object = Model.new
|
38
|
-
# object.save
|
39
|
-
#
|
40
|
-
# Would run the object's :do_something method following by the code
|
41
|
-
# block related to :do_something_else. Note that if you specify a
|
42
|
-
# block, a tag is optional. If the tag is not nil, it will overwrite
|
43
|
-
# a previous block with the same tag. This allows hooks to work with
|
44
|
-
# systems that reload code.
|
45
|
-
# * All of the methods in HOOKS also create instance methods, but you
|
46
|
-
# should not override these instance methods.
|
47
|
-
# * The following instance_methods all call the class method of the same
|
48
|
-
# name: columns, dataset, db, primary_key, str_columns.
|
49
|
-
# * The following class level attr_readers are created: allowed_columns,
|
50
|
-
# cache_store, cache_ttl, dataset_methods, primary_key, restricted_columns,
|
51
|
-
# sti_dataset, and sti_key. You should not usually need to
|
52
|
-
# access these directly.
|
53
|
-
# * All validation methods also accept the options specified in #validates_each,
|
54
|
-
# in addition to the options specified in the RDoc for that method.
|
55
|
-
# * The following class level attr_accessors are created: raise_on_typecast_failure,
|
56
|
-
# raise_on_save_failure, strict_param_setting, typecast_empty_string_to_nil,
|
57
|
-
# and typecast_on_assignment:
|
58
|
-
#
|
59
|
-
# # Don't raise an error if a validation attempt fails in
|
60
|
-
# # save/create/save_changes/etc.
|
61
|
-
# Model.raise_on_save_failure = false
|
62
|
-
# Model.before_save{false}
|
63
|
-
# Model.new.save # => nil
|
64
|
-
# # Don't raise errors in new/set/update/etc. if an attempt to
|
65
|
-
# # access a missing/restricted method occurs (just silently
|
66
|
-
# # skip it)
|
67
|
-
# Model.strict_param_setting = false
|
68
|
-
# Model.new(:id=>1) # No Error
|
69
|
-
# # Don't typecast attribute values on assignment
|
70
|
-
# Model.typecast_on_assignment = false
|
71
|
-
# m = Model.new
|
72
|
-
# m.number = '10'
|
73
|
-
# m.number # => '10' instead of 10
|
74
|
-
# # Don't typecast empty string to nil for non-string, non-blob columns.
|
75
|
-
# Model.typecast_empty_string_to_nil = false
|
76
|
-
# m.number = ''
|
77
|
-
# m.number # => '' instead of nil
|
78
|
-
# # Don't raise if unable to typecast data for a column
|
79
|
-
# Model.typecast_empty_string_to_nil = true
|
80
|
-
# Model.raise_on_typecast_failure = false
|
81
|
-
# m.not_null_column = '' # => nil
|
82
|
-
# m.number = 'A' # => 'A'
|
83
|
-
#
|
84
|
-
# * The following class level method aliases are defined:
|
85
|
-
# * Model.dataset= => set_dataset
|
86
|
-
# * Model.is_a => is
|
87
|
-
class Model
|
88
|
-
extend Enumerable
|
89
|
-
extend Associations
|
90
|
-
end
|
91
|
-
end
|
1
|
+
require 'sequel/model'
|
@@ -26,7 +26,7 @@ FIREBIRD_DB.create_table! :test5 do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
context "A Firebird database" do
|
29
|
-
|
29
|
+
before do
|
30
30
|
@db = FIREBIRD_DB
|
31
31
|
end
|
32
32
|
|
@@ -43,7 +43,7 @@ context "A Firebird database" do
|
|
43
43
|
end
|
44
44
|
|
45
45
|
context "A Firebird dataset" do
|
46
|
-
|
46
|
+
before do
|
47
47
|
@d = FIREBIRD_DB[:test]
|
48
48
|
@d.delete # remove all records
|
49
49
|
end
|
@@ -212,7 +212,7 @@ context "A Firebird dataset" do
|
|
212
212
|
end
|
213
213
|
|
214
214
|
context "A Firebird dataset with a timestamp field" do
|
215
|
-
|
215
|
+
before do
|
216
216
|
@d = FIREBIRD_DB[:test3]
|
217
217
|
@d.delete
|
218
218
|
end
|
@@ -226,7 +226,7 @@ context "A Firebird dataset with a timestamp field" do
|
|
226
226
|
end
|
227
227
|
|
228
228
|
context "A Firebird database" do
|
229
|
-
|
229
|
+
before do
|
230
230
|
@db = FIREBIRD_DB
|
231
231
|
end
|
232
232
|
|
@@ -342,7 +342,7 @@ context "A Firebird database" do
|
|
342
342
|
end
|
343
343
|
|
344
344
|
context "Postgres::Dataset#insert" do
|
345
|
-
|
345
|
+
before do
|
346
346
|
@ds = FIREBIRD_DB[:test5]
|
347
347
|
@ds.delete
|
348
348
|
end
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -44,7 +44,7 @@ else
|
|
44
44
|
end
|
45
45
|
|
46
46
|
context "MySQL", '#create_table' do
|
47
|
-
|
47
|
+
before do
|
48
48
|
@db = MYSQL_DB
|
49
49
|
end
|
50
50
|
after(:each) do
|
@@ -57,10 +57,10 @@ context "MySQL", '#create_table' do
|
|
57
57
|
end
|
58
58
|
|
59
59
|
context "A MySQL database" do
|
60
|
-
|
60
|
+
before do
|
61
61
|
@db = MYSQL_DB
|
62
62
|
end
|
63
|
-
|
63
|
+
after do
|
64
64
|
Sequel.convert_tinyint_to_bool = true
|
65
65
|
end
|
66
66
|
|
@@ -96,14 +96,10 @@ context "A MySQL database" do
|
|
96
96
|
Sequel.convert_tinyint_to_bool = false
|
97
97
|
@db.schema(:booltest, :reload=>true).should == [[:value, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :db_type=>"tinyint(4)"}]]
|
98
98
|
end
|
99
|
-
|
100
|
-
specify "should get the schema all database tables if no table name is used" do
|
101
|
-
@db.schema(:booltest, :reload=>true).should == @db.schema(nil, :reload=>true)[:booltest]
|
102
|
-
end
|
103
99
|
end
|
104
100
|
|
105
101
|
context "A MySQL dataset" do
|
106
|
-
|
102
|
+
before do
|
107
103
|
@d = MYSQL_DB[:items]
|
108
104
|
@d.delete # remove all records
|
109
105
|
MYSQL_DB.sqls.clear
|
@@ -274,10 +270,10 @@ context "A MySQL dataset" do
|
|
274
270
|
end
|
275
271
|
|
276
272
|
context "MySQL datasets" do
|
277
|
-
|
273
|
+
before do
|
278
274
|
@d = MYSQL_DB[:orders]
|
279
275
|
end
|
280
|
-
|
276
|
+
after do
|
281
277
|
Sequel.convert_tinyint_to_bool = true
|
282
278
|
end
|
283
279
|
|
@@ -285,11 +281,9 @@ context "MySQL datasets" do
|
|
285
281
|
@d.quote_identifiers = true
|
286
282
|
market = 'ICE'
|
287
283
|
ack_stamp = Time.now - 15 * 60 # 15 minutes ago
|
288
|
-
@d.
|
289
|
-
|
290
|
-
|
291
|
-
group_by :minute.sql_function(:from_unixtime.sql_function(:ack))
|
292
|
-
end.sql.should == \
|
284
|
+
@d.select(:market, :minute.sql_function(:from_unixtime.sql_function(:ack)).as(:minute)).
|
285
|
+
where{|o|(:ack.sql_number > ack_stamp) & {:market => market}}.
|
286
|
+
group_by(:minute.sql_function(:from_unixtime.sql_function(:ack))).sql.should == \
|
293
287
|
"SELECT `market`, minute(from_unixtime(`ack`)) AS `minute` FROM `orders` WHERE ((`ack` > #{@d.literal(ack_stamp)}) AND (`market` = 'ICE')) GROUP BY minute(from_unixtime(`ack`))"
|
294
288
|
end
|
295
289
|
|
@@ -319,7 +313,7 @@ context "MySQL datasets" do
|
|
319
313
|
end
|
320
314
|
|
321
315
|
context "MySQL join expressions" do
|
322
|
-
|
316
|
+
before do
|
323
317
|
@ds = MYSQL_DB[:nodes]
|
324
318
|
@ds.db.meta_def(:server_version) {50014}
|
325
319
|
end
|
@@ -370,7 +364,7 @@ context "MySQL join expressions" do
|
|
370
364
|
end
|
371
365
|
|
372
366
|
context "Joined MySQL dataset" do
|
373
|
-
|
367
|
+
before do
|
374
368
|
@ds = MYSQL_DB[:nodes]
|
375
369
|
end
|
376
370
|
|
@@ -394,7 +388,7 @@ context "Joined MySQL dataset" do
|
|
394
388
|
end
|
395
389
|
|
396
390
|
context "A MySQL database" do
|
397
|
-
|
391
|
+
before do
|
398
392
|
@db = MYSQL_DB
|
399
393
|
end
|
400
394
|
|
@@ -485,21 +479,21 @@ context "A MySQL database", "with table options" do
|
|
485
479
|
end
|
486
480
|
|
487
481
|
specify "should allow to pass custom options (engine, charset, collate) for table creation" do
|
488
|
-
statements = @db.
|
482
|
+
statements = @db.send(:create_table_sql_list, :items, *(@g.create_info << @options))
|
489
483
|
statements.should == [
|
490
484
|
"CREATE TABLE items (size integer, name text) ENGINE=MyISAM DEFAULT CHARSET=latin2 DEFAULT COLLATE=swedish"
|
491
485
|
]
|
492
486
|
end
|
493
487
|
|
494
488
|
specify "should use default options if specified (engine, charset, collate) for table creation" do
|
495
|
-
statements = @db.
|
489
|
+
statements = @db.send(:create_table_sql_list, :items, *(@g.create_info))
|
496
490
|
statements.should == [
|
497
491
|
"CREATE TABLE items (size integer, name text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8"
|
498
492
|
]
|
499
493
|
end
|
500
494
|
|
501
495
|
specify "should not use default if option has a nil value" do
|
502
|
-
statements = @db.
|
496
|
+
statements = @db.send(:create_table_sql_list, :items, *(@g.create_info << {:engine=>nil, :charset=>nil, :collate=>nil}))
|
503
497
|
statements.should == [
|
504
498
|
"CREATE TABLE items (size integer, name text)"
|
505
499
|
]
|
@@ -507,7 +501,7 @@ context "A MySQL database", "with table options" do
|
|
507
501
|
end
|
508
502
|
|
509
503
|
context "A MySQL database" do
|
510
|
-
|
504
|
+
before do
|
511
505
|
@db = MYSQL_DB
|
512
506
|
end
|
513
507
|
|
@@ -516,7 +510,7 @@ context "A MySQL database" do
|
|
516
510
|
boolean :active1, :default => true
|
517
511
|
boolean :active2, :default => false
|
518
512
|
end
|
519
|
-
statements = @db.
|
513
|
+
statements = @db.send(:create_table_sql_list, :items, *g.create_info)
|
520
514
|
statements.should == [
|
521
515
|
"CREATE TABLE items (active1 boolean DEFAULT 1, active2 boolean DEFAULT 0)"
|
522
516
|
]
|
@@ -527,7 +521,7 @@ context "A MySQL database" do
|
|
527
521
|
foreign_key :p_id, :table => :users, :key => :id,
|
528
522
|
:null => false, :on_delete => :cascade
|
529
523
|
end
|
530
|
-
@db.
|
524
|
+
@db.send(:create_table_sql_list, :items, *g.create_info).should == [
|
531
525
|
"CREATE TABLE items (p_id integer NOT NULL, FOREIGN KEY (p_id) REFERENCES users(id) ON DELETE CASCADE)"
|
532
526
|
]
|
533
527
|
end
|
@@ -536,7 +530,7 @@ specify "should correctly format ALTER TABLE statements with foreign keys" do
|
|
536
530
|
g = Sequel::Schema::AlterTableGenerator.new(@db) do
|
537
531
|
add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade
|
538
532
|
end
|
539
|
-
@db.
|
533
|
+
@db.send(:alter_table_sql_list, :items, g.operations).should == [[
|
540
534
|
"ALTER TABLE items ADD COLUMN p_id integer NOT NULL",
|
541
535
|
"ALTER TABLE items ADD FOREIGN KEY (p_id) REFERENCES users(id) ON DELETE CASCADE"
|
542
536
|
]]
|
@@ -584,7 +578,7 @@ if %w'localhost 127.0.0.1 ::1'.include?(MYSQL_URI.host) and MYSQL_DB.class.adapt
|
|
584
578
|
end
|
585
579
|
|
586
580
|
context "A grouped MySQL dataset" do
|
587
|
-
|
581
|
+
before do
|
588
582
|
MYSQL_DB[:test2].delete
|
589
583
|
MYSQL_DB[:test2] << {:name => '11', :value => 10}
|
590
584
|
MYSQL_DB[:test2] << {:name => '11', :value => 20}
|
@@ -606,16 +600,13 @@ context "A grouped MySQL dataset" do
|
|
606
600
|
end
|
607
601
|
|
608
602
|
context "A MySQL database" do
|
609
|
-
setup do
|
610
|
-
end
|
611
|
-
|
612
603
|
specify "should support fulltext indexes" do
|
613
604
|
g = Sequel::Schema::Generator.new(MYSQL_DB) do
|
614
605
|
text :title
|
615
606
|
text :body
|
616
607
|
full_text_index [:title, :body]
|
617
608
|
end
|
618
|
-
MYSQL_DB.
|
609
|
+
MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
|
619
610
|
"CREATE TABLE posts (title text, body text)",
|
620
611
|
"CREATE FULLTEXT INDEX posts_title_body_index ON posts (title, body)"
|
621
612
|
]
|
@@ -637,7 +628,7 @@ context "A MySQL database" do
|
|
637
628
|
point :geom
|
638
629
|
spatial_index [:geom]
|
639
630
|
end
|
640
|
-
MYSQL_DB.
|
631
|
+
MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
|
641
632
|
"CREATE TABLE posts (geom point)",
|
642
633
|
"CREATE SPATIAL INDEX posts_geom_index ON posts (geom)"
|
643
634
|
]
|
@@ -648,7 +639,7 @@ context "A MySQL database" do
|
|
648
639
|
text :title
|
649
640
|
index :title, :type => :hash
|
650
641
|
end
|
651
|
-
MYSQL_DB.
|
642
|
+
MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
|
652
643
|
"CREATE TABLE posts (title text)",
|
653
644
|
"CREATE INDEX posts_title_index ON posts (title) USING hash"
|
654
645
|
]
|
@@ -659,7 +650,7 @@ context "A MySQL database" do
|
|
659
650
|
text :title
|
660
651
|
index :title, :type => :hash, :unique => true
|
661
652
|
end
|
662
|
-
MYSQL_DB.
|
653
|
+
MYSQL_DB.send(:create_table_sql_list, :posts, *g.create_info).should == [
|
663
654
|
"CREATE TABLE posts (title text)",
|
664
655
|
"CREATE UNIQUE INDEX posts_title_index ON posts (title) USING hash"
|
665
656
|
]
|
@@ -667,9 +658,9 @@ context "A MySQL database" do
|
|
667
658
|
end
|
668
659
|
|
669
660
|
context "MySQL::Dataset#insert" do
|
670
|
-
|
661
|
+
before do
|
671
662
|
@d = MYSQL_DB[:items]
|
672
|
-
@d.delete
|
663
|
+
@d.delete
|
673
664
|
MYSQL_DB.sqls.clear
|
674
665
|
end
|
675
666
|
|
@@ -711,9 +702,9 @@ context "MySQL::Dataset#insert" do
|
|
711
702
|
end
|
712
703
|
|
713
704
|
context "MySQL::Dataset#multi_insert" do
|
714
|
-
|
705
|
+
before do
|
715
706
|
@d = MYSQL_DB[:items]
|
716
|
-
@d.delete
|
707
|
+
@d.delete
|
717
708
|
MYSQL_DB.sqls.clear
|
718
709
|
end
|
719
710
|
|
@@ -774,7 +765,7 @@ context "MySQL::Dataset#multi_insert" do
|
|
774
765
|
end
|
775
766
|
|
776
767
|
specify "should support inserting using columns and values arrays" do
|
777
|
-
@d.
|
768
|
+
@d.import([:name, :value], [['abc', 1], ['def', 2]])
|
778
769
|
|
779
770
|
MYSQL_DB.sqls.should == [
|
780
771
|
SQL_BEGIN,
|
@@ -789,8 +780,70 @@ context "MySQL::Dataset#multi_insert" do
|
|
789
780
|
end
|
790
781
|
end
|
791
782
|
|
783
|
+
context "MySQL::Dataset#insert_ignore" do
|
784
|
+
before do
|
785
|
+
@d = MYSQL_DB[:items]
|
786
|
+
@d.delete
|
787
|
+
MYSQL_DB.sqls.clear
|
788
|
+
end
|
789
|
+
|
790
|
+
specify "should add the IGNORE keyword when inserting" do
|
791
|
+
@d.insert_ignore.multi_insert([{:name => 'abc'}, {:name => 'def'}])
|
792
|
+
|
793
|
+
MYSQL_DB.sqls.should == [
|
794
|
+
SQL_BEGIN,
|
795
|
+
"INSERT IGNORE INTO items (name) VALUES ('abc'), ('def')",
|
796
|
+
SQL_COMMIT
|
797
|
+
]
|
798
|
+
|
799
|
+
@d.all.should == [
|
800
|
+
{:name => 'abc', :value => nil}, {:name => 'def', :value => nil}
|
801
|
+
]
|
802
|
+
end
|
803
|
+
end
|
804
|
+
|
805
|
+
context "MySQL::Dataset#on_duplicate_key_update" do
|
806
|
+
before do
|
807
|
+
@d = MYSQL_DB[:items]
|
808
|
+
@d.delete
|
809
|
+
MYSQL_DB.sqls.clear
|
810
|
+
end
|
811
|
+
|
812
|
+
specify "should add the ON DUPLICATE KEY UPDATE and ALL columns when no args given" do
|
813
|
+
@d.on_duplicate_key_update.import([:name,:value],
|
814
|
+
[['abc', 1], ['def',2]]
|
815
|
+
)
|
816
|
+
|
817
|
+
MYSQL_DB.sqls.should == [
|
818
|
+
SQL_BEGIN,
|
819
|
+
"INSERT INTO items (name, value) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE name=VALUES(name), value=VALUES(value)",
|
820
|
+
SQL_COMMIT
|
821
|
+
]
|
822
|
+
|
823
|
+
@d.all.should == [
|
824
|
+
{:name => 'abc', :value => 1}, {:name => 'def', :value => 2}
|
825
|
+
]
|
826
|
+
end
|
827
|
+
specify "should add the ON DUPLICATE KEY UPDATE and columns specified when args are given" do
|
828
|
+
@d.on_duplicate_key_update(:value).import([:name,:value],
|
829
|
+
[['abc', 1], ['def',2]]
|
830
|
+
)
|
831
|
+
|
832
|
+
MYSQL_DB.sqls.should == [
|
833
|
+
SQL_BEGIN,
|
834
|
+
"INSERT INTO items (name, value) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE value=VALUES(value)",
|
835
|
+
SQL_COMMIT
|
836
|
+
]
|
837
|
+
|
838
|
+
@d.all.should == [
|
839
|
+
{:name => 'abc', :value => 1}, {:name => 'def', :value => 2}
|
840
|
+
]
|
841
|
+
end
|
842
|
+
|
843
|
+
end
|
844
|
+
|
792
845
|
context "MySQL::Dataset#replace" do
|
793
|
-
|
846
|
+
before do
|
794
847
|
MYSQL_DB.drop_table(:items) if MYSQL_DB.table_exists?(:items)
|
795
848
|
MYSQL_DB.create_table :items do
|
796
849
|
integer :id, :unique => true
|
@@ -814,7 +867,7 @@ context "MySQL::Dataset#replace" do
|
|
814
867
|
end
|
815
868
|
|
816
869
|
context "MySQL::Dataset#complex_expression_sql" do
|
817
|
-
|
870
|
+
before do
|
818
871
|
@d = MYSQL_DB.dataset
|
819
872
|
end
|
820
873
|
|
@@ -832,7 +885,7 @@ context "MySQL::Dataset#complex_expression_sql" do
|
|
832
885
|
specify "should handle string concatenation with CONCAT if more than one record" do
|
833
886
|
@d.literal([:x, :y].sql_string_join).should == "CONCAT(x, y)"
|
834
887
|
@d.literal([:x, :y].sql_string_join(' ')).should == "CONCAT(x, ' ', y)"
|
835
|
-
@d.literal([:x.sql_function(:y), 1, 'z'.lit].sql_string_join(:y
|
888
|
+
@d.literal([:x.sql_function(:y), 1, 'z'.lit].sql_string_join(:y.sql_subscript(1))).should == "CONCAT(x(y), y[1], '1', y[1], z)"
|
836
889
|
end
|
837
890
|
|
838
891
|
specify "should handle string concatenation as simple string if just one record" do
|
@@ -843,7 +896,7 @@ end
|
|
843
896
|
|
844
897
|
unless MYSQL_DB.class.adapter_scheme == :do
|
845
898
|
context "MySQL Stored Procedures" do
|
846
|
-
|
899
|
+
after do
|
847
900
|
MYSQL_DB.execute('DROP PROCEDURE test_sproc')
|
848
901
|
end
|
849
902
|
|
@@ -879,3 +932,36 @@ unless MYSQL_DB.class.adapter_scheme == :do
|
|
879
932
|
end
|
880
933
|
end
|
881
934
|
end
|
935
|
+
|
936
|
+
if MYSQL_DB.class.adapter_scheme == :mysql
|
937
|
+
context "MySQL bad date/time conversions" do
|
938
|
+
after do
|
939
|
+
Sequel::MySQL.convert_invalid_date_time = false
|
940
|
+
end
|
941
|
+
|
942
|
+
specify "should raise an exception when a bad date/time is used and convert_invalid_date_time is false" do
|
943
|
+
Sequel::MySQL.convert_invalid_date_time = false
|
944
|
+
proc{MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value}.should raise_error(Sequel::InvalidValue)
|
945
|
+
proc{MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value}.should raise_error(Sequel::InvalidValue)
|
946
|
+
proc{MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value}.should raise_error(Sequel::InvalidValue)
|
947
|
+
end
|
948
|
+
|
949
|
+
specify "should not use a nil value bad date/time is used and convert_invalid_date_time is nil or :nil" do
|
950
|
+
Sequel::MySQL.convert_invalid_date_time = nil
|
951
|
+
MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == nil
|
952
|
+
MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == nil
|
953
|
+
MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == nil
|
954
|
+
Sequel::MySQL.convert_invalid_date_time = :nil
|
955
|
+
MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == nil
|
956
|
+
MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == nil
|
957
|
+
MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == nil
|
958
|
+
end
|
959
|
+
|
960
|
+
specify "should not use a nil value bad date/time is used and convert_invalid_date_time is :string" do
|
961
|
+
Sequel::MySQL.convert_invalid_date_time = :string
|
962
|
+
MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == '0000-00-00'
|
963
|
+
MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == '0000-00-00 00:00:00'
|
964
|
+
MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == '25:00:00'
|
965
|
+
end
|
966
|
+
end
|
967
|
+
end
|