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.
Files changed (162) hide show
  1. data/CHANGELOG +168 -0
  2. data/README.rdoc +77 -95
  3. data/Rakefile +100 -80
  4. data/bin/sequel +2 -1
  5. data/doc/advanced_associations.rdoc +23 -32
  6. data/doc/cheat_sheet.rdoc +23 -40
  7. data/doc/dataset_filtering.rdoc +6 -6
  8. data/doc/prepared_statements.rdoc +22 -22
  9. data/doc/release_notes/2.12.0.txt +534 -0
  10. data/doc/schema.rdoc +3 -1
  11. data/doc/sharding.rdoc +8 -8
  12. data/doc/virtual_rows.rdoc +65 -0
  13. data/lib/sequel.rb +1 -1
  14. data/lib/{sequel_core → sequel}/adapters/ado.rb +3 -3
  15. data/lib/{sequel_core → sequel}/adapters/db2.rb +0 -0
  16. data/lib/{sequel_core → sequel}/adapters/dbi.rb +1 -1
  17. data/lib/{sequel_core → sequel}/adapters/do.rb +9 -5
  18. data/lib/{sequel_core → sequel}/adapters/do/mysql.rb +1 -1
  19. data/lib/{sequel_core → sequel}/adapters/do/postgres.rb +1 -1
  20. data/lib/{sequel_core → sequel}/adapters/do/sqlite.rb +1 -1
  21. data/lib/{sequel_core → sequel}/adapters/firebird.rb +84 -80
  22. data/lib/{sequel_core → sequel}/adapters/informix.rb +1 -1
  23. data/lib/{sequel_core → sequel}/adapters/jdbc.rb +21 -14
  24. data/lib/{sequel_core → sequel}/adapters/jdbc/h2.rb +14 -13
  25. data/lib/{sequel_core → sequel}/adapters/jdbc/mysql.rb +1 -1
  26. data/lib/{sequel_core → sequel}/adapters/jdbc/oracle.rb +1 -1
  27. data/lib/{sequel_core → sequel}/adapters/jdbc/postgresql.rb +1 -1
  28. data/lib/{sequel_core → sequel}/adapters/jdbc/sqlite.rb +1 -1
  29. data/lib/{sequel_core → sequel}/adapters/mysql.rb +60 -39
  30. data/lib/{sequel_core → sequel}/adapters/odbc.rb +8 -4
  31. data/lib/{sequel_core → sequel}/adapters/openbase.rb +0 -0
  32. data/lib/{sequel_core → sequel}/adapters/oracle.rb +38 -7
  33. data/lib/{sequel_core → sequel}/adapters/postgres.rb +24 -24
  34. data/lib/{sequel_core → sequel}/adapters/shared/mssql.rb +5 -5
  35. data/lib/{sequel_core → sequel}/adapters/shared/mysql.rb +126 -71
  36. data/lib/{sequel_core → sequel}/adapters/shared/oracle.rb +7 -10
  37. data/lib/{sequel_core → sequel}/adapters/shared/postgres.rb +159 -125
  38. data/lib/{sequel_core → sequel}/adapters/shared/progress.rb +1 -2
  39. data/lib/{sequel_core → sequel}/adapters/shared/sqlite.rb +72 -67
  40. data/lib/{sequel_core → sequel}/adapters/sqlite.rb +11 -7
  41. data/lib/{sequel_core → sequel}/adapters/utils/date_format.rb +0 -0
  42. data/lib/{sequel_core → sequel}/adapters/utils/stored_procedures.rb +0 -0
  43. data/lib/{sequel_core → sequel}/adapters/utils/unsupported.rb +19 -0
  44. data/lib/{sequel_core → sequel}/connection_pool.rb +7 -5
  45. data/lib/sequel/core.rb +221 -0
  46. data/lib/{sequel_core → sequel}/core_sql.rb +91 -49
  47. data/lib/{sequel_core → sequel}/database.rb +264 -149
  48. data/lib/{sequel_core/schema/generator.rb → sequel/database/schema_generator.rb} +6 -2
  49. data/lib/{sequel_core/database/schema.rb → sequel/database/schema_methods.rb} +12 -12
  50. data/lib/sequel/database/schema_sql.rb +224 -0
  51. data/lib/{sequel_core → sequel}/dataset.rb +78 -236
  52. data/lib/{sequel_core → sequel}/dataset/convenience.rb +99 -61
  53. data/lib/{sequel_core/object_graph.rb → sequel/dataset/graph.rb} +16 -14
  54. data/lib/{sequel_core → sequel}/dataset/prepared_statements.rb +1 -1
  55. data/lib/{sequel_core → sequel}/dataset/sql.rb +150 -99
  56. data/lib/sequel/deprecated.rb +593 -0
  57. data/lib/sequel/deprecated_migration.rb +91 -0
  58. data/lib/sequel/exceptions.rb +48 -0
  59. data/lib/sequel/extensions/blank.rb +42 -0
  60. data/lib/{sequel_model → sequel/extensions}/inflector.rb +8 -1
  61. data/lib/{sequel_core → sequel/extensions}/migration.rb +1 -1
  62. data/lib/{sequel_core/dataset → sequel/extensions}/pagination.rb +0 -0
  63. data/lib/{sequel_core → sequel/extensions}/pretty_table.rb +7 -0
  64. data/lib/{sequel_core/dataset → sequel/extensions}/query.rb +7 -0
  65. data/lib/sequel/extensions/string_date_time.rb +47 -0
  66. data/lib/sequel/metaprogramming.rb +43 -0
  67. data/lib/sequel/model.rb +110 -0
  68. data/lib/sequel/model/associations.rb +1300 -0
  69. data/lib/sequel/model/base.rb +937 -0
  70. data/lib/sequel/model/deprecated.rb +204 -0
  71. data/lib/sequel/model/deprecated_hooks.rb +103 -0
  72. data/lib/sequel/model/deprecated_inflector.rb +335 -0
  73. data/lib/sequel/model/deprecated_validations.rb +388 -0
  74. data/lib/sequel/model/errors.rb +39 -0
  75. data/lib/{sequel_model → sequel/model}/exceptions.rb +4 -4
  76. data/lib/sequel/model/inflections.rb +208 -0
  77. data/lib/sequel/model/plugins.rb +76 -0
  78. data/lib/sequel/plugins/caching.rb +122 -0
  79. data/lib/sequel/plugins/hook_class_methods.rb +122 -0
  80. data/lib/sequel/plugins/schema.rb +53 -0
  81. data/lib/sequel/plugins/serialization.rb +117 -0
  82. data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
  83. data/lib/sequel/plugins/validation_class_methods.rb +384 -0
  84. data/lib/sequel/plugins/validation_helpers.rb +150 -0
  85. data/lib/{sequel_core → sequel}/sql.rb +125 -190
  86. data/lib/{sequel_core → sequel}/version.rb +2 -1
  87. data/lib/sequel_core.rb +1 -172
  88. data/lib/sequel_model.rb +1 -91
  89. data/spec/adapters/firebird_spec.rb +5 -5
  90. data/spec/adapters/informix_spec.rb +1 -1
  91. data/spec/adapters/mysql_spec.rb +128 -42
  92. data/spec/adapters/oracle_spec.rb +47 -19
  93. data/spec/adapters/postgres_spec.rb +64 -52
  94. data/spec/adapters/spec_helper.rb +1 -1
  95. data/spec/adapters/sqlite_spec.rb +12 -17
  96. data/spec/{sequel_core → core}/connection_pool_spec.rb +10 -10
  97. data/spec/{sequel_core → core}/core_ext_spec.rb +19 -19
  98. data/spec/{sequel_core → core}/core_sql_spec.rb +68 -71
  99. data/spec/{sequel_core → core}/database_spec.rb +135 -99
  100. data/spec/{sequel_core → core}/dataset_spec.rb +398 -242
  101. data/spec/{sequel_core → core}/expression_filters_spec.rb +13 -13
  102. data/spec/core/migration_spec.rb +263 -0
  103. data/spec/{sequel_core → core}/object_graph_spec.rb +10 -10
  104. data/spec/{sequel_core → core}/pretty_table_spec.rb +2 -2
  105. data/spec/{sequel_core → core}/schema_generator_spec.rb +0 -0
  106. data/spec/{sequel_core → core}/schema_spec.rb +8 -10
  107. data/spec/{sequel_core → core}/spec_helper.rb +29 -2
  108. data/spec/{sequel_core → core}/version_spec.rb +0 -0
  109. data/spec/extensions/blank_spec.rb +67 -0
  110. data/spec/extensions/caching_spec.rb +201 -0
  111. data/spec/{sequel_model/hooks_spec.rb → extensions/hook_class_methods_spec.rb} +8 -23
  112. data/spec/{sequel_model → extensions}/inflector_spec.rb +3 -0
  113. data/spec/{sequel_core → extensions}/migration_spec.rb +4 -4
  114. data/spec/extensions/pagination_spec.rb +99 -0
  115. data/spec/extensions/pretty_table_spec.rb +91 -0
  116. data/spec/extensions/query_spec.rb +85 -0
  117. data/spec/{sequel_model → extensions}/schema_spec.rb +22 -1
  118. data/spec/extensions/serialization_spec.rb +109 -0
  119. data/spec/extensions/single_table_inheritance_spec.rb +53 -0
  120. data/spec/{sequel_model → extensions}/spec_helper.rb +13 -4
  121. data/spec/extensions/string_date_time_spec.rb +93 -0
  122. data/spec/{sequel_model/validations_spec.rb → extensions/validation_class_methods_spec.rb} +15 -103
  123. data/spec/extensions/validation_helpers_spec.rb +291 -0
  124. data/spec/integration/dataset_test.rb +31 -0
  125. data/spec/integration/eager_loader_test.rb +17 -30
  126. data/spec/integration/schema_test.rb +8 -5
  127. data/spec/integration/spec_helper.rb +17 -0
  128. data/spec/integration/transaction_test.rb +68 -0
  129. data/spec/{sequel_model → model}/association_reflection_spec.rb +0 -0
  130. data/spec/{sequel_model → model}/associations_spec.rb +23 -10
  131. data/spec/{sequel_model → model}/base_spec.rb +29 -20
  132. data/spec/{sequel_model → model}/caching_spec.rb +16 -14
  133. data/spec/{sequel_model → model}/dataset_methods_spec.rb +0 -0
  134. data/spec/{sequel_model → model}/eager_loading_spec.rb +8 -8
  135. data/spec/model/hooks_spec.rb +472 -0
  136. data/spec/model/inflector_spec.rb +126 -0
  137. data/spec/{sequel_model → model}/model_spec.rb +25 -20
  138. data/spec/model/plugins_spec.rb +142 -0
  139. data/spec/{sequel_model → model}/record_spec.rb +121 -62
  140. data/spec/model/schema_spec.rb +92 -0
  141. data/spec/model/spec_helper.rb +124 -0
  142. data/spec/model/validations_spec.rb +1080 -0
  143. metadata +136 -107
  144. data/lib/sequel_core/core_ext.rb +0 -217
  145. data/lib/sequel_core/dataset/callback.rb +0 -13
  146. data/lib/sequel_core/dataset/schema.rb +0 -15
  147. data/lib/sequel_core/deprecated.rb +0 -26
  148. data/lib/sequel_core/exceptions.rb +0 -44
  149. data/lib/sequel_core/schema.rb +0 -2
  150. data/lib/sequel_core/schema/sql.rb +0 -325
  151. data/lib/sequel_model/association_reflection.rb +0 -267
  152. data/lib/sequel_model/associations.rb +0 -499
  153. data/lib/sequel_model/base.rb +0 -539
  154. data/lib/sequel_model/caching.rb +0 -82
  155. data/lib/sequel_model/dataset_methods.rb +0 -26
  156. data/lib/sequel_model/eager_loading.rb +0 -370
  157. data/lib/sequel_model/hooks.rb +0 -101
  158. data/lib/sequel_model/plugins.rb +0 -62
  159. data/lib/sequel_model/record.rb +0 -568
  160. data/lib/sequel_model/schema.rb +0 -49
  161. data/lib/sequel_model/validations.rb +0 -429
  162. 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
@@ -1,2 +0,0 @@
1
- require 'sequel_core/schema/generator'
2
- require 'sequel_core/schema/sql'
@@ -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