sequel 2.11.0 → 2.12.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 +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
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
module Sequel
|
|
2
|
-
class Dataset
|
|
3
|
-
private
|
|
4
|
-
# This is run inside .all, after all
|
|
5
|
-
# of the records have been loaded
|
|
6
|
-
# via .each, but before any block passed
|
|
7
|
-
# to all is called. It is called with
|
|
8
|
-
# a single argument, an array of all
|
|
9
|
-
# returned records.
|
|
10
|
-
def post_load(all_records)
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
module Sequel
|
|
2
|
-
class Dataset
|
|
3
|
-
# Creates a view in the database with the given named based
|
|
4
|
-
# on the current dataset.
|
|
5
|
-
def create_view(name)
|
|
6
|
-
@db.create_view(name, self)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
# Creates or replaces a view in the database with the given
|
|
10
|
-
# named based on the current dataset.
|
|
11
|
-
def create_or_replace_view(name)
|
|
12
|
-
@db.create_or_replace_view(name, self)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
module Sequel
|
|
2
|
-
# This module makes it easy to add deprecation functionality to other classes.
|
|
3
|
-
module Deprecation # :nodoc:
|
|
4
|
-
# This sets the output stream for the deprecation messages. Set it to an IO
|
|
5
|
-
# (or any object that responds to puts) and it will call puts on that
|
|
6
|
-
# object with the deprecation message. Set to nil to ignore deprecation messages.
|
|
7
|
-
def self.deprecation_message_stream=(file)
|
|
8
|
-
@dms = file
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
# Set this to true to print tracebacks with every deprecation message,
|
|
12
|
-
# so you can see exactly where in your code the deprecated methods are
|
|
13
|
-
# being called.
|
|
14
|
-
def self.print_tracebacks=(pt)
|
|
15
|
-
@pt = pt
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# Puts the messages unaltered to the deprecation message stream
|
|
19
|
-
def self.deprecate(message)
|
|
20
|
-
if @dms
|
|
21
|
-
@dms.puts(message)
|
|
22
|
-
caller.each{|c| @dms.puts(c)} if @pt
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
module Sequel
|
|
2
|
-
# Represents an error raised in Sequel code.
|
|
3
|
-
class Error < ::StandardError
|
|
4
|
-
|
|
5
|
-
# Raised when Sequel is unable to load a specified adapter.
|
|
6
|
-
class AdapterNotFound < Error ; end
|
|
7
|
-
|
|
8
|
-
# Raised on an invalid operation.
|
|
9
|
-
class InvalidOperation < Error; end
|
|
10
|
-
|
|
11
|
-
# Error raised when an invalid statement is executed.
|
|
12
|
-
class InvalidStatement < Error; end
|
|
13
|
-
|
|
14
|
-
# Represents an Invalid transform.
|
|
15
|
-
class InvalidTransform < Error ; end
|
|
16
|
-
|
|
17
|
-
# Represents an invalid value stored in the database.
|
|
18
|
-
class InvalidValue < Error ; end
|
|
19
|
-
|
|
20
|
-
# Represents an attempt to performing filter operations when no filter has been specified yet.
|
|
21
|
-
class NoExistingFilter < Error ; end
|
|
22
|
-
|
|
23
|
-
# There was an error while waiting on a connection from the connection pool
|
|
24
|
-
class PoolTimeoutError < Error ; end
|
|
25
|
-
|
|
26
|
-
# Rollback is a special error used to rollback a transactions.
|
|
27
|
-
# A transaction block will catch this error and won't pass further up the stack.
|
|
28
|
-
class Rollback < Error ; end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# Generic error raised by the database adapters, indicating a
|
|
32
|
-
# problem originating from the database server.
|
|
33
|
-
class DatabaseError < Error; end
|
|
34
|
-
|
|
35
|
-
# Error raised when the Sequel is unable to connect to the database with the
|
|
36
|
-
# connection parameters it was given.
|
|
37
|
-
class DatabaseConnectionError < DatabaseError; end
|
|
38
|
-
|
|
39
|
-
# Error that should be raised by adapters when they determine that the connection
|
|
40
|
-
# to the database has been lost. Instructs the connection pool code to
|
|
41
|
-
# remove that connection from the pool so that other connections can be acquired
|
|
42
|
-
# automatically.
|
|
43
|
-
class DatabaseDisconnectError < DatabaseError; end
|
|
44
|
-
end
|
data/lib/sequel_core/schema.rb
DELETED
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
module Sequel
|
|
2
|
-
module Schema
|
|
3
|
-
module SQL
|
|
4
|
-
AUTOINCREMENT = 'AUTOINCREMENT'.freeze
|
|
5
|
-
CASCADE = 'CASCADE'.freeze
|
|
6
|
-
COMMA_SEPARATOR = ', '.freeze
|
|
7
|
-
NO_ACTION = 'NO ACTION'.freeze
|
|
8
|
-
NOT_NULL = ' NOT NULL'.freeze
|
|
9
|
-
NULL = ' NULL'.freeze
|
|
10
|
-
PRIMARY_KEY = ' PRIMARY KEY'.freeze
|
|
11
|
-
RESTRICT = 'RESTRICT'.freeze
|
|
12
|
-
SET_DEFAULT = 'SET DEFAULT'.freeze
|
|
13
|
-
SET_NULL = 'SET NULL'.freeze
|
|
14
|
-
TYPES = Hash.new {|h, k| k}
|
|
15
|
-
TYPES.merge!(:double=>'double precision', String=>'varchar(255)',
|
|
16
|
-
Integer=>'integer', Fixnum=>'integer', Bignum=>'bigint',
|
|
17
|
-
Float=>'double precision', BigDecimal=>'numeric', Numeric=>'numeric',
|
|
18
|
-
Date=>'date', DateTime=>'timestamp', Time=>'timestamp', File=>'blob',
|
|
19
|
-
TrueClass=>'boolean', FalseClass=>'boolean')
|
|
20
|
-
UNDERSCORE = '_'.freeze
|
|
21
|
-
UNIQUE = ' UNIQUE'.freeze
|
|
22
|
-
UNSIGNED = ' UNSIGNED'.freeze
|
|
23
|
-
|
|
24
|
-
# The SQL to execute to modify the DDL for the given table name. op
|
|
25
|
-
# should be one of the operations returned by the AlterTableGenerator.
|
|
26
|
-
def alter_table_sql(table, op)
|
|
27
|
-
quoted_name = quote_identifier(op[:name]) if op[:name]
|
|
28
|
-
alter_table_op = case op[:op]
|
|
29
|
-
when :add_column
|
|
30
|
-
"ADD COLUMN #{column_definition_sql(op)}"
|
|
31
|
-
when :drop_column
|
|
32
|
-
"DROP COLUMN #{quoted_name}"
|
|
33
|
-
when :rename_column
|
|
34
|
-
"RENAME COLUMN #{quoted_name} TO #{quote_identifier(op[:new_name])}"
|
|
35
|
-
when :set_column_type
|
|
36
|
-
"ALTER COLUMN #{quoted_name} TYPE #{type_literal(op)}"
|
|
37
|
-
when :set_column_default
|
|
38
|
-
"ALTER COLUMN #{quoted_name} SET DEFAULT #{literal(op[:default])}"
|
|
39
|
-
when :set_column_null
|
|
40
|
-
"ALTER COLUMN #{quoted_name} #{op[:null] ? 'DROP' : 'SET'} NOT NULL"
|
|
41
|
-
when :add_index
|
|
42
|
-
return index_definition_sql(table, op)
|
|
43
|
-
when :drop_index
|
|
44
|
-
return drop_index_sql(table, op)
|
|
45
|
-
when :add_constraint
|
|
46
|
-
"ADD #{constraint_definition_sql(op)}"
|
|
47
|
-
when :drop_constraint
|
|
48
|
-
"DROP CONSTRAINT #{quoted_name}"
|
|
49
|
-
else
|
|
50
|
-
raise Error, "Unsupported ALTER TABLE operation"
|
|
51
|
-
end
|
|
52
|
-
"ALTER TABLE #{quote_schema_table(table)} #{alter_table_op}"
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# Array of SQL DDL modification statements for the given table,
|
|
56
|
-
# corresponding to the DDL changes specified by the operations.
|
|
57
|
-
def alter_table_sql_list(table, operations)
|
|
58
|
-
operations.map{|op| alter_table_sql(table, op)}
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# The SQL string specify the autoincrement property, generally used by
|
|
62
|
-
# primary keys.
|
|
63
|
-
def auto_increment_sql
|
|
64
|
-
AUTOINCREMENT
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# SQL DDL fragment containing the column creation SQL for the given column.
|
|
68
|
-
def column_definition_sql(column)
|
|
69
|
-
return constraint_definition_sql(column) if column[:type] == :check
|
|
70
|
-
sql = "#{quote_identifier(column[:name])} #{type_literal(column)}"
|
|
71
|
-
sql << UNIQUE if column[:unique]
|
|
72
|
-
sql << NOT_NULL if column[:null] == false
|
|
73
|
-
sql << NULL if column[:null] == true
|
|
74
|
-
sql << " DEFAULT #{literal(column[:default])}" if column.include?(:default)
|
|
75
|
-
sql << PRIMARY_KEY if column[:primary_key]
|
|
76
|
-
sql << " #{auto_increment_sql}" if column[:auto_increment]
|
|
77
|
-
sql << column_references_sql(column) if column[:table]
|
|
78
|
-
sql
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# SQL DDL fragment containing the column creation
|
|
82
|
-
# SQL for all given columns, used instead a CREATE TABLE block.
|
|
83
|
-
def column_list_sql(columns)
|
|
84
|
-
columns.map{|c| column_definition_sql(c)}.join(COMMA_SEPARATOR)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# SQL DDL fragment for column foreign key references
|
|
88
|
-
def column_references_sql(column)
|
|
89
|
-
sql = " REFERENCES #{quote_schema_table(column[:table])}"
|
|
90
|
-
sql << "(#{Array(column[:key]).map{|x| quote_identifier(x)}.join(COMMA_SEPARATOR)})" if column[:key]
|
|
91
|
-
sql << " ON DELETE #{on_delete_clause(column[:on_delete])}" if column[:on_delete]
|
|
92
|
-
sql << " ON UPDATE #{on_delete_clause(column[:on_update])}" if column[:on_update]
|
|
93
|
-
sql
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# SQL DDL fragment specifying a constraint on a table.
|
|
97
|
-
def constraint_definition_sql(constraint)
|
|
98
|
-
sql = constraint[:name] ? "CONSTRAINT #{quote_identifier(constraint[:name])} " : ""
|
|
99
|
-
case constraint[:constraint_type]
|
|
100
|
-
when :primary_key
|
|
101
|
-
sql << "PRIMARY KEY #{literal(constraint[:columns])}"
|
|
102
|
-
when :foreign_key
|
|
103
|
-
sql << "FOREIGN KEY #{literal(constraint[:columns])}"
|
|
104
|
-
sql << column_references_sql(constraint)
|
|
105
|
-
when :unique
|
|
106
|
-
sql << "UNIQUE #{literal(constraint[:columns])}"
|
|
107
|
-
else
|
|
108
|
-
check = constraint[:check]
|
|
109
|
-
sql << "CHECK #{filter_expr((check.is_a?(Array) && check.length == 1) ? check.first : check)}"
|
|
110
|
-
end
|
|
111
|
-
sql
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
# Array of SQL DDL statements, the first for creating a table with the given
|
|
115
|
-
# name and column specifications, and the others for specifying indexes on
|
|
116
|
-
# the table.
|
|
117
|
-
def create_table_sql_list(name, columns, indexes = nil, options = {})
|
|
118
|
-
sql = ["CREATE TABLE #{quote_schema_table(name)} (#{column_list_sql(columns)})"]
|
|
119
|
-
sql.concat(index_list_sql_list(name, indexes)) if indexes && !indexes.empty?
|
|
120
|
-
sql
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
# Default index name for the table and columns, may be too long
|
|
124
|
-
# for certain databases.
|
|
125
|
-
def default_index_name(table_name, columns)
|
|
126
|
-
schema, table = schema_and_table(table_name)
|
|
127
|
-
"#{"#{schema}_" if schema and schema != default_schema}#{table}_#{columns.map{|c| c.is_one_of?(String, Symbol) ? c : literal(c).gsub(/\W/, '_')}.join(UNDERSCORE)}_index"
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
# The SQL to drop an index for the table.
|
|
131
|
-
def drop_index_sql(table, op)
|
|
132
|
-
"DROP INDEX #{quote_identifier(op[:name] || default_index_name(table, op[:columns]))}"
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
# SQL DDL statement to drop the table with the given name.
|
|
136
|
-
def drop_table_sql(name)
|
|
137
|
-
"DROP TABLE #{quote_schema_table(name)}"
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# Proxy the filter_expr call to the dataset, used for creating constraints.
|
|
141
|
-
def filter_expr(*args, &block)
|
|
142
|
-
schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr, *args, &block))
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
# SQL DDL statement for creating an index for the table with the given name
|
|
146
|
-
# and index specifications.
|
|
147
|
-
def index_definition_sql(table_name, index)
|
|
148
|
-
index_name = index[:name] || default_index_name(table_name, index[:columns])
|
|
149
|
-
if index[:type]
|
|
150
|
-
raise Error, "Index types are not supported for this database"
|
|
151
|
-
elsif index[:where]
|
|
152
|
-
raise Error, "Partial indexes are not supported for this database"
|
|
153
|
-
else
|
|
154
|
-
"CREATE #{'UNIQUE ' if index[:unique]}INDEX #{quote_identifier(index_name)} ON #{quote_identifier(table_name)} #{literal(index[:columns])}"
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# Array of SQL DDL statements, one for each index specification,
|
|
159
|
-
# for the given table.
|
|
160
|
-
def index_list_sql_list(table_name, indexes)
|
|
161
|
-
indexes.map{|i| index_definition_sql(table_name, i)}
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
# Proxy the literal call to the dataset, used for default values.
|
|
165
|
-
def literal(v)
|
|
166
|
-
schema_utility_dataset.literal(v)
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
# SQL DDL ON DELETE fragment to use, based on the given action.
|
|
170
|
-
# The following actions are recognized:
|
|
171
|
-
#
|
|
172
|
-
# * :cascade - Delete rows referencing this row.
|
|
173
|
-
# * :no_action (default) - Raise an error if other rows reference this
|
|
174
|
-
# row, allow deferring of the integrity check.
|
|
175
|
-
# * :restrict - Raise an error if other rows reference this row,
|
|
176
|
-
# but do not allow deferring the integrity check.
|
|
177
|
-
# * :set_default - Set columns referencing this row to their default value.
|
|
178
|
-
# * :set_null - Set columns referencing this row to NULL.
|
|
179
|
-
def on_delete_clause(action)
|
|
180
|
-
case action
|
|
181
|
-
when :restrict
|
|
182
|
-
RESTRICT
|
|
183
|
-
when :cascade
|
|
184
|
-
CASCADE
|
|
185
|
-
when :set_null
|
|
186
|
-
SET_NULL
|
|
187
|
-
when :set_default
|
|
188
|
-
SET_DEFAULT
|
|
189
|
-
else
|
|
190
|
-
NO_ACTION
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
# Proxy the quote_schema_table method to the dataset
|
|
195
|
-
def quote_schema_table(table)
|
|
196
|
-
schema_utility_dataset.quote_schema_table(table)
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
# Proxy the quote_identifier method to the dataset, used for quoting tables and columns.
|
|
200
|
-
def quote_identifier(v)
|
|
201
|
-
schema_utility_dataset.quote_identifier(v)
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
# SQL DDL statement for renaming a table.
|
|
205
|
-
def rename_table_sql(name, new_name)
|
|
206
|
-
"ALTER TABLE #{quote_schema_table(name)} RENAME TO #{quote_schema_table(new_name)}"
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
# Parse the schema from the database.
|
|
210
|
-
# If the table_name is not given, returns the schema for all tables as a hash.
|
|
211
|
-
# If the table_name is given, returns the schema for a single table as an
|
|
212
|
-
# array with all members being arrays of length 2. Available options are:
|
|
213
|
-
#
|
|
214
|
-
# * :reload - Get fresh information from the database, instead of using
|
|
215
|
-
# cached information. If table_name is blank, :reload should be used
|
|
216
|
-
# unless you are sure that schema has not been called before with a
|
|
217
|
-
# table_name, otherwise you may only getting the schemas for tables
|
|
218
|
-
# that have been requested explicitly.
|
|
219
|
-
# * :schema - An explicit schema to use. It may also be implicitly provided
|
|
220
|
-
# via the table name.
|
|
221
|
-
def schema(table = nil, opts={})
|
|
222
|
-
raise(Error, 'schema parsing is not implemented on this database') unless respond_to?(:schema_parse_table, true)
|
|
223
|
-
|
|
224
|
-
if table
|
|
225
|
-
sch, table_name = schema_and_table(table)
|
|
226
|
-
quoted_name = quote_schema_table(table)
|
|
227
|
-
end
|
|
228
|
-
opts = opts.merge(:schema=>sch) if sch && !opts.include?(:schema)
|
|
229
|
-
if opts[:reload] && @schemas
|
|
230
|
-
if table_name
|
|
231
|
-
@schemas.delete(quoted_name)
|
|
232
|
-
else
|
|
233
|
-
@schemas = nil
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
if @schemas
|
|
238
|
-
if table_name
|
|
239
|
-
return @schemas[quoted_name] if @schemas[quoted_name]
|
|
240
|
-
else
|
|
241
|
-
return @schemas
|
|
242
|
-
end
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
raise(Error, '#tables does not exist, you must provide a specific table to #schema') if table.nil? && !respond_to?(:tables, true)
|
|
246
|
-
|
|
247
|
-
@schemas ||= Hash.new do |h,k|
|
|
248
|
-
quote_name = quote_schema_table(k)
|
|
249
|
-
h[quote_name] if h.include?(quote_name)
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
if table_name
|
|
253
|
-
cols = schema_parse_table(table_name, opts)
|
|
254
|
-
raise(Error, 'schema parsing returned no columns, table probably doesn\'t exist') if cols.blank?
|
|
255
|
-
@schemas[quoted_name] = cols
|
|
256
|
-
else
|
|
257
|
-
tables.each{|t| @schemas[quote_schema_table(t)] = schema_parse_table(t.to_s, opts)}
|
|
258
|
-
@schemas
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
# The dataset to use for proxying certain schema methods.
|
|
263
|
-
def schema_utility_dataset
|
|
264
|
-
@schema_utility_dataset ||= dataset
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
private
|
|
268
|
-
|
|
269
|
-
# Remove the cached schema for the given schema name
|
|
270
|
-
def remove_cached_schema(table)
|
|
271
|
-
@schemas.delete(quote_schema_table(table)) if @schemas
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
# Remove the cached schema_utility_dataset, because the identifier
|
|
275
|
-
# quoting has changed.
|
|
276
|
-
def reset_schema_utility_dataset
|
|
277
|
-
@schema_utility_dataset = nil
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
# Match the database's column type to a ruby type via a
|
|
281
|
-
# regular expression. The following ruby types are supported:
|
|
282
|
-
# integer, string, date, datetime, boolean, and float.
|
|
283
|
-
def schema_column_type(db_type)
|
|
284
|
-
case db_type
|
|
285
|
-
when /\Atinyint/io
|
|
286
|
-
Sequel.convert_tinyint_to_bool ? :boolean : :integer
|
|
287
|
-
when /\Ainterval\z/io
|
|
288
|
-
:interval
|
|
289
|
-
when /\A(character( varying)?|varchar|text)/io
|
|
290
|
-
:string
|
|
291
|
-
when /\A(int(eger)?|bigint|smallint)/io
|
|
292
|
-
:integer
|
|
293
|
-
when /\Adate\z/io
|
|
294
|
-
:date
|
|
295
|
-
when /\A(datetime|timestamp( with(out)? time zone)?)\z/io
|
|
296
|
-
:datetime
|
|
297
|
-
when /\Atime( with(out)? time zone)?\z/io
|
|
298
|
-
:time
|
|
299
|
-
when /\Aboolean\z/io
|
|
300
|
-
:boolean
|
|
301
|
-
when /\A(real|float|double( precision)?)\z/io
|
|
302
|
-
:float
|
|
303
|
-
when /\A(numeric(\(\d+,\d+\))?|decimal|money)\z/io
|
|
304
|
-
:decimal
|
|
305
|
-
when /\Abytea\z/io
|
|
306
|
-
:blob
|
|
307
|
-
end
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
# SQL fragment specifying the type of a given column.
|
|
311
|
-
def type_literal(column)
|
|
312
|
-
type = type_literal_base(column)
|
|
313
|
-
column[:size] ||= 255 if type.to_s == 'varchar'
|
|
314
|
-
elements = column[:size] || column[:elements]
|
|
315
|
-
"#{type}#{literal(Array(elements)) if elements}#{UNSIGNED if column[:unsigned]}"
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
# SQL fragment specifying the base type of a given column,
|
|
319
|
-
# without the size or elements.
|
|
320
|
-
def type_literal_base(column)
|
|
321
|
-
TYPES[column[:type]]
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
end
|
|
325
|
-
end
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
module Sequel::Model::Associations
|
|
2
|
-
# Map of association type symbols to association reflection classes.
|
|
3
|
-
ASSOCIATION_TYPES = {}
|
|
4
|
-
|
|
5
|
-
# AssociationReflection is a Hash subclass that keeps information on Sequel::Model associations. It
|
|
6
|
-
# provides methods to reduce internal code duplication. It should not
|
|
7
|
-
# be instantiated by the user.
|
|
8
|
-
class AssociationReflection < Hash
|
|
9
|
-
# Name symbol for _add_ internal association method
|
|
10
|
-
def _add_method
|
|
11
|
-
:"_add_#{self[:name].to_s.singularize}"
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Name symbol for _dataset association method
|
|
15
|
-
def _dataset_method
|
|
16
|
-
:"_#{self[:name]}_dataset"
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Name symbol for _remove_all internal association method
|
|
20
|
-
def _remove_all_method
|
|
21
|
-
:"_remove_all_#{self[:name]}"
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Name symbol for _remove_ internal association method
|
|
25
|
-
def _remove_method
|
|
26
|
-
:"_remove_#{self[:name].to_s.singularize}"
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Name symbol for setter association method
|
|
30
|
-
def _setter_method
|
|
31
|
-
:"_#{self[:name]}="
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Name symbol for add_ association method
|
|
35
|
-
def add_method
|
|
36
|
-
:"add_#{self[:name].to_s.singularize}"
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# Name symbol for association method, the same as the name of the association.
|
|
40
|
-
def association_method
|
|
41
|
-
self[:name]
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# The class associated to the current model class via this association
|
|
45
|
-
def associated_class
|
|
46
|
-
self[:class] ||= self[:class_name].constantize
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Name symbol for dataset association method
|
|
50
|
-
def dataset_method
|
|
51
|
-
:"#{self[:name]}_dataset"
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Name symbol for _helper internal association method
|
|
55
|
-
def dataset_helper_method
|
|
56
|
-
:"_#{self[:name]}_dataset_helper"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Whether the dataset needs a primary key to function, true by default.
|
|
60
|
-
def dataset_need_primary_key?
|
|
61
|
-
true
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Whether to eagerly graph a lazy dataset, true by default.
|
|
65
|
-
def eager_graph_lazy_dataset?
|
|
66
|
-
true
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# Whether the associated object needs a primary key to be added/removed,
|
|
70
|
-
# false by default.
|
|
71
|
-
def need_associated_primary_key?
|
|
72
|
-
false
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Returns/sets the reciprocal association variable, if one exists
|
|
76
|
-
def reciprocal
|
|
77
|
-
return self[:reciprocal] if include?(:reciprocal)
|
|
78
|
-
r_type = reciprocal_type
|
|
79
|
-
key = self[:key]
|
|
80
|
-
associated_class.all_association_reflections.each do |assoc_reflect|
|
|
81
|
-
if assoc_reflect[:type] == r_type && assoc_reflect[:key] == key
|
|
82
|
-
return self[:reciprocal] = assoc_reflect[:name]
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
self[:reciprocal] = nil
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# Whether the reciprocal of this association returns an array of objects instead of a single object,
|
|
89
|
-
# true by default.
|
|
90
|
-
def reciprocal_array?
|
|
91
|
-
true
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# Name symbol for remove_all_ association method
|
|
95
|
-
def remove_all_method
|
|
96
|
-
:"remove_all_#{self[:name]}"
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
# Name symbol for remove_ association method
|
|
100
|
-
def remove_method
|
|
101
|
-
:"remove_#{self[:name].to_s.singularize}"
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Whether this association returns an array of objects instead of a single object,
|
|
105
|
-
# true by default.
|
|
106
|
-
def returns_array?
|
|
107
|
-
true
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# The columns to select when loading the association, nil by default.
|
|
111
|
-
def select
|
|
112
|
-
self[:select]
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
# By default, associations shouldn't set the reciprocal association to self.
|
|
116
|
-
def set_reciprocal_to_self?
|
|
117
|
-
false
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
# Name symbol for setter association method
|
|
121
|
-
def setter_method
|
|
122
|
-
:"#{self[:name]}="
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
class ManyToOneAssociationReflection < AssociationReflection
|
|
128
|
-
ASSOCIATION_TYPES[:many_to_one] = self
|
|
129
|
-
|
|
130
|
-
# Whether the dataset needs a primary key to function, false for many_to_one associations.
|
|
131
|
-
def dataset_need_primary_key?
|
|
132
|
-
false
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
# Default foreign key name symbol for foreign key in current model's table that points to
|
|
136
|
-
# the given association's table's primary key.
|
|
137
|
-
def default_key
|
|
138
|
-
:"#{self[:name]}_id"
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
# Whether to eagerly graph a lazy dataset, true for many_to_one associations
|
|
142
|
-
# only if the key is nil.
|
|
143
|
-
def eager_graph_lazy_dataset?
|
|
144
|
-
self[:key].nil?
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
# The key to use for the key hash when eager loading
|
|
148
|
-
def eager_loader_key
|
|
149
|
-
self[:key]
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
# The column in the associated table that the key in the current table references.
|
|
153
|
-
def primary_key
|
|
154
|
-
self[:primary_key] ||= associated_class.primary_key
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# Whether this association returns an array of objects instead of a single object,
|
|
158
|
-
# false for a many_to_one association.
|
|
159
|
-
def returns_array?
|
|
160
|
-
false
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
private
|
|
164
|
-
|
|
165
|
-
# The reciprocal type of a many_to_one association is a one_to_many association.
|
|
166
|
-
def reciprocal_type
|
|
167
|
-
:one_to_many
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
class OneToManyAssociationReflection < AssociationReflection
|
|
172
|
-
ASSOCIATION_TYPES[:one_to_many] = self
|
|
173
|
-
|
|
174
|
-
# Default foreign key name symbol for key in associated table that points to
|
|
175
|
-
# current table's primary key.
|
|
176
|
-
def default_key
|
|
177
|
-
:"#{self[:model].name.to_s.demodulize.underscore}_id"
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
# The key to use for the key hash when eager loading
|
|
181
|
-
def eager_loader_key
|
|
182
|
-
primary_key
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
# The column in the current table that the key in the associated table references.
|
|
186
|
-
def primary_key
|
|
187
|
-
self[:primary_key] ||= self[:model].primary_key
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
# One to many associations set the reciprocal to self.
|
|
191
|
-
def set_reciprocal_to_self?
|
|
192
|
-
true
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
# Whether the reciprocal of this association returns an array of objects instead of a single object,
|
|
196
|
-
# false for a one_to_many association.
|
|
197
|
-
def reciprocal_array?
|
|
198
|
-
false
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
private
|
|
202
|
-
|
|
203
|
-
# The reciprocal type of a one_to_many association is a many_to_one association.
|
|
204
|
-
def reciprocal_type
|
|
205
|
-
:many_to_one
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
class ManyToManyAssociationReflection < AssociationReflection
|
|
210
|
-
ASSOCIATION_TYPES[:many_to_many] = self
|
|
211
|
-
|
|
212
|
-
# Default name symbol for the join table.
|
|
213
|
-
def default_join_table
|
|
214
|
-
([self[:class_name].demodulize, self[:model].name.to_s.demodulize]. \
|
|
215
|
-
map{|i| i.pluralize.underscore}.sort.join('_')).to_sym
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
# Default foreign key name symbol for key in join table that points to
|
|
219
|
-
# current table's primary key (or :left_primary_key column).
|
|
220
|
-
def default_left_key
|
|
221
|
-
:"#{self[:model].name.to_s.demodulize.underscore}_id"
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
# Default foreign key name symbol for foreign key in join table that points to
|
|
225
|
-
# the association's table's primary key (or :right_primary_key column).
|
|
226
|
-
def default_right_key
|
|
227
|
-
:"#{self[:name].to_s.singularize}_id"
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
# The key to use for the key hash when eager loading
|
|
231
|
-
def eager_loader_key
|
|
232
|
-
self[:left_primary_key]
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
# Whether the associated object needs a primary key to be added/removed,
|
|
236
|
-
# true for many_to_many associations.
|
|
237
|
-
def need_associated_primary_key?
|
|
238
|
-
true
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
# Returns/sets the reciprocal association variable, if one exists
|
|
242
|
-
def reciprocal
|
|
243
|
-
return self[:reciprocal] if include?(:reciprocal)
|
|
244
|
-
left_key = self[:left_key]
|
|
245
|
-
right_key = self[:right_key]
|
|
246
|
-
join_table = self[:join_table]
|
|
247
|
-
associated_class.all_association_reflections.each do |assoc_reflect|
|
|
248
|
-
if assoc_reflect[:type] == :many_to_many && assoc_reflect[:left_key] == right_key \
|
|
249
|
-
&& assoc_reflect[:right_key] == left_key && assoc_reflect[:join_table] == join_table
|
|
250
|
-
return self[:reciprocal] = assoc_reflect[:name]
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
self[:reciprocal] = nil
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
# The primary key column to use in the associated table.
|
|
257
|
-
def right_primary_key
|
|
258
|
-
self[:right_primary_key] ||= associated_class.primary_key
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
# The columns to select when loading the association, associated_class.table_name.* by default.
|
|
262
|
-
def select
|
|
263
|
-
return self[:select] if include?(:select)
|
|
264
|
-
self[:select] ||= associated_class.table_name.*
|
|
265
|
-
end
|
|
266
|
-
end
|
|
267
|
-
end
|