sequel 3.13.0 → 3.14.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 (60) hide show
  1. data/CHANGELOG +36 -0
  2. data/doc/release_notes/3.14.0.txt +118 -0
  3. data/lib/sequel/adapters/oracle.rb +7 -2
  4. data/lib/sequel/adapters/shared/mssql.rb +9 -3
  5. data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
  6. data/lib/sequel/connection_pool/threaded.rb +3 -3
  7. data/lib/sequel/database/connecting.rb +47 -11
  8. data/lib/sequel/database/dataset.rb +17 -6
  9. data/lib/sequel/database/dataset_defaults.rb +15 -3
  10. data/lib/sequel/database/logging.rb +4 -3
  11. data/lib/sequel/database/misc.rb +33 -21
  12. data/lib/sequel/database/query.rb +61 -22
  13. data/lib/sequel/database/schema_generator.rb +108 -45
  14. data/lib/sequel/database/schema_methods.rb +8 -5
  15. data/lib/sequel/dataset/actions.rb +194 -45
  16. data/lib/sequel/dataset/features.rb +1 -1
  17. data/lib/sequel/dataset/graph.rb +51 -43
  18. data/lib/sequel/dataset/misc.rb +29 -5
  19. data/lib/sequel/dataset/mutation.rb +0 -1
  20. data/lib/sequel/dataset/prepared_statements.rb +14 -2
  21. data/lib/sequel/dataset/query.rb +268 -125
  22. data/lib/sequel/dataset/sql.rb +33 -44
  23. data/lib/sequel/extensions/migration.rb +3 -2
  24. data/lib/sequel/extensions/pagination.rb +1 -1
  25. data/lib/sequel/model/associations.rb +89 -87
  26. data/lib/sequel/model/base.rb +386 -109
  27. data/lib/sequel/model/errors.rb +15 -1
  28. data/lib/sequel/model/exceptions.rb +3 -3
  29. data/lib/sequel/model/inflections.rb +2 -2
  30. data/lib/sequel/model/plugins.rb +9 -5
  31. data/lib/sequel/plugins/rcte_tree.rb +43 -15
  32. data/lib/sequel/plugins/schema.rb +6 -5
  33. data/lib/sequel/plugins/serialization.rb +1 -1
  34. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  35. data/lib/sequel/plugins/tree.rb +33 -1
  36. data/lib/sequel/timezones.rb +16 -10
  37. data/lib/sequel/version.rb +1 -1
  38. data/spec/adapters/mssql_spec.rb +36 -2
  39. data/spec/adapters/mysql_spec.rb +4 -4
  40. data/spec/adapters/postgres_spec.rb +1 -1
  41. data/spec/adapters/spec_helper.rb +2 -2
  42. data/spec/core/database_spec.rb +8 -1
  43. data/spec/core/dataset_spec.rb +36 -1
  44. data/spec/extensions/pagination_spec.rb +1 -1
  45. data/spec/extensions/rcte_tree_spec.rb +40 -8
  46. data/spec/extensions/schema_spec.rb +5 -0
  47. data/spec/extensions/serialization_spec.rb +4 -4
  48. data/spec/extensions/single_table_inheritance_spec.rb +7 -0
  49. data/spec/extensions/tree_spec.rb +36 -0
  50. data/spec/integration/dataset_test.rb +19 -0
  51. data/spec/integration/prepared_statement_test.rb +2 -2
  52. data/spec/integration/schema_test.rb +1 -1
  53. data/spec/integration/spec_helper.rb +4 -4
  54. data/spec/integration/timezone_test.rb +27 -21
  55. data/spec/model/associations_spec.rb +5 -5
  56. data/spec/model/dataset_methods_spec.rb +13 -0
  57. data/spec/model/hooks_spec.rb +31 -0
  58. data/spec/model/record_spec.rb +24 -7
  59. data/spec/model/validations_spec.rb +9 -4
  60. metadata +6 -4
@@ -58,7 +58,11 @@ module Sequel
58
58
  end
59
59
  end
60
60
 
61
- # Set the method to call on identifiers going into the database
61
+ # Set the method to call on identifiers going into the database:
62
+ #
63
+ # DB[:items] # SELECT * FROM items
64
+ # DB.identifier_input_method = :upcase
65
+ # DB[:items] # SELECT * FROM ITEMS
62
66
  def identifier_input_method=(v)
63
67
  reset_schema_utility_dataset
64
68
  @identifier_input_method = v || ""
@@ -77,13 +81,21 @@ module Sequel
77
81
  end
78
82
  end
79
83
 
80
- # Set the method to call on identifiers coming from the database
84
+ # Set the method to call on identifiers coming from the database:
85
+ #
86
+ # DB[:items].first # {:id=>1, :name=>'foo'}
87
+ # DB.identifier_output_method = :upcase
88
+ # DB[:items].first # {:ID=>1, :NAME=>'foo'}
81
89
  def identifier_output_method=(v)
82
90
  reset_schema_utility_dataset
83
91
  @identifier_output_method = v || ""
84
92
  end
85
93
 
86
- # Whether to quote identifiers (columns and tables) for this database
94
+ # Set whether to quote identifiers (columns and tables) for this database:
95
+ #
96
+ # DB[:items] # SELECT * FROM items
97
+ # DB.quote_identifiers = true
98
+ # DB[:items] # SELECT * FROM "items"
87
99
  def quote_identifiers=(v)
88
100
  reset_schema_utility_dataset
89
101
  @quote_identifiers = v
@@ -9,7 +9,7 @@ module Sequel
9
9
  # level instead of info level.
10
10
  attr_accessor :log_warn_duration
11
11
 
12
- # Array of SQL loggers to use for this database
12
+ # Array of SQL loggers to use for this database.
13
13
  attr_accessor :loggers
14
14
 
15
15
  # Log a message at level info to all loggers.
@@ -33,7 +33,9 @@ module Sequel
33
33
  end
34
34
  end
35
35
 
36
- # Remove any existing loggers and just use the given logger.
36
+ # Remove any existing loggers and just use the given logger:
37
+ #
38
+ # DB.logger = Logger.new($stdout)
37
39
  def logger=(logger)
38
40
  @loggers = Array(logger)
39
41
  end
@@ -57,6 +59,5 @@ module Sequel
57
59
  def log_each(level, message)
58
60
  @loggers.each{|logger| logger.send(level, message)}
59
61
  end
60
-
61
62
  end
62
63
  end
@@ -16,24 +16,24 @@ module Sequel
16
16
  end
17
17
  private_class_method :uri_to_options
18
18
 
19
- # The options for this database
19
+ # The options hash for this database
20
20
  attr_reader :opts
21
21
 
22
22
  # Constructs a new instance of a database connection with the specified
23
23
  # options hash.
24
24
  #
25
- # Sequel::Database is an abstract class that is not useful by itself.
25
+ # Accepts the following options:
26
+ # :default_schema :: The default schema to use, should generally be nil
27
+ # :disconnection_proc :: A proc used to disconnect the connection
28
+ # :identifier_input_method :: A string method symbol to call on identifiers going into the database
29
+ # :identifier_output_method :: A string method symbol to call on identifiers coming from the database
30
+ # :logger :: A specific logger to use
31
+ # :loggers :: An array of loggers to use
32
+ # :quote_identifiers :: Whether to quote identifiers
33
+ # :servers :: A hash specifying a server/shard specific options, keyed by shard symbol
34
+ # :single_threaded :: Whether to use a single-threaded connection pool
26
35
  #
27
- # Takes the following options:
28
- # * :default_schema : The default schema to use, should generally be nil
29
- # * :disconnection_proc: A proc used to disconnect the connection.
30
- # * :identifier_input_method: A string method symbol to call on identifiers going into the database
31
- # * :identifier_output_method: A string method symbol to call on identifiers coming from the database
32
- # * :loggers : An array of loggers to use.
33
- # * :quote_identifiers : Whether to quote identifiers
34
- # * :single_threaded : Whether to use a single-threaded connection pool
35
- #
36
- # All options given are also passed to the ConnectionPool. If a block
36
+ # All options given are also passed to the connection pool. If a block
37
37
  # is given, it is used as the connection_proc for the ConnectionPool.
38
38
  def initialize(opts = {}, &block)
39
39
  @opts ||= opts
@@ -58,6 +58,9 @@ module Sequel
58
58
  end
59
59
 
60
60
  # Cast the given type to a literal type
61
+ #
62
+ # DB.cast_type_literal(Float) # double precision
63
+ # DB.cast_type_literal(:foo) # foo
61
64
  def cast_type_literal(type)
62
65
  type_literal(:type=>type)
63
66
  end
@@ -69,28 +72,33 @@ module Sequel
69
72
  "#<#{self.class}: #{(uri rescue opts).inspect}>"
70
73
  end
71
74
 
72
- # Proxy the literal call to the dataset, used for default values.
75
+ # Proxy the literal call to the dataset.
76
+ #
77
+ # DB.literal(1) # 1
78
+ # DB.literal(:a) # a
79
+ # DB.literal('a') # 'a'
73
80
  def literal(v)
74
81
  schema_utility_dataset.literal(v)
75
82
  end
76
83
 
77
- # Default serial primary key options.
84
+ # Default serial primary key options, used by the table creation
85
+ # code.
78
86
  def serial_primary_key_options
79
87
  {:primary_key => true, :type => Integer, :auto_increment => true}
80
88
  end
81
89
 
82
90
  # Whether the database and adapter support prepared transactions
83
- # (two-phase commit), false by default
91
+ # (two-phase commit), false by default.
84
92
  def supports_prepared_transactions?
85
93
  false
86
94
  end
87
95
 
88
- # Whether the database and adapter support savepoints, false by default
96
+ # Whether the database and adapter support savepoints, false by default.
89
97
  def supports_savepoints?
90
98
  false
91
99
  end
92
100
 
93
- # Whether the database and adapter support transaction isolation levels, false by default
101
+ # Whether the database and adapter support transaction isolation levels, false by default.
94
102
  def supports_transaction_isolation_levels?
95
103
  false
96
104
  end
@@ -110,12 +118,17 @@ module Sequel
110
118
  end
111
119
  end
112
120
 
113
- # Returns the URI identifying the database.
121
+ # Returns the URI identifying the database, which may not be the
122
+ # same as the URI used when connecting.
114
123
  # This method can raise an error if the database used options
115
- # instead of a connection string.
124
+ # instead of a connection string, and will not include uri
125
+ # parameters.
126
+ #
127
+ # Sequel.connect('postgres://localhost/db?user=billg').url
128
+ # # => "postgres://billg@localhost/db"
116
129
  def uri
117
130
  uri = URI::Generic.new(
118
- self.class.adapter_scheme.to_s,
131
+ adapter_scheme.to_s,
119
132
  nil,
120
133
  @opts[:host],
121
134
  @opts[:port],
@@ -203,7 +216,6 @@ module Sequel
203
216
 
204
217
  # Typecast the value to a DateTime or Time depending on Sequel.datetime_class
205
218
  def typecast_value_datetime(value)
206
- raise(Sequel::InvalidValue, "invalid value for Datetime: #{value.inspect}") unless [DateTime, Date, Time, String, Hash].any?{|c| value.is_a?(c)}
207
219
  klass = Sequel.datetime_class
208
220
  if value.is_a?(Hash)
209
221
  klass.send(klass == Time ? :mktime : :new, *[:year, :month, :day, :hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
@@ -26,7 +26,7 @@ module Sequel
26
26
  MYSQL_TIMESTAMP_RE = /\ACURRENT_(?:DATE|TIMESTAMP)?\z/
27
27
  STRING_DEFAULT_RE = /\A'(.*)'\z/
28
28
 
29
- # The prepared statement objects for this database, keyed by name
29
+ # The prepared statement object hash for this database, keyed by name symbol
30
30
  attr_reader :prepared_statements
31
31
 
32
32
  # The default transaction isolation level for this database,
@@ -44,6 +44,9 @@ module Sequel
44
44
 
45
45
  # Call the prepared statement with the given name with the given hash
46
46
  # of arguments.
47
+ #
48
+ # DB[:items].filter(:id=>1).prepare(:first, :sa)
49
+ # DB.call(:sa) # SELECT * FROM items WHERE id = 1
47
50
  def call(ps_name, hash={})
48
51
  prepared_statements[ps_name].call(hash)
49
52
  end
@@ -55,7 +58,7 @@ module Sequel
55
58
  end
56
59
 
57
60
  # Method that should be used when submitting any DDL (Data Definition
58
- # Language) SQL. By default, calls execute_dui.
61
+ # Language) SQL, such as +create_table+. By default, calls +execute_dui+.
59
62
  # This method should not be called directly by user code.
60
63
  def execute_ddl(sql, opts={}, &block)
61
64
  execute_dui(sql, opts, &block)
@@ -77,11 +80,9 @@ module Sequel
77
80
 
78
81
  # Returns a single value from the database, e.g.:
79
82
  #
80
- # # SELECT 1
81
- # DB.get(1) #=> 1
82
- #
83
- # # SELECT version()
84
- # DB.get(:version.sql_function) #=> ...
83
+ # DB.get(1) # SELECT 1
84
+ # # => 1
85
+ # DB.get{version{}} # SELECT server_version()
85
86
  def get(*args, &block)
86
87
  dataset.get(*args, &block)
87
88
  end
@@ -92,13 +93,18 @@ module Sequel
92
93
  # depending on if the index is unique.
93
94
  #
94
95
  # Should not include the primary key index, functional indexes, or partial indexes.
96
+ #
97
+ # DB.indexes(:artists)
98
+ # # => {:artists_name_ukey=>{:columns=>[:name], :unique=>true}}
95
99
  def indexes(table, opts={})
96
100
  raise NotImplemented, "#indexes should be overridden by adapters"
97
101
  end
98
102
 
99
103
  # Runs the supplied SQL statement string on the database server. Returns nil.
100
104
  # Options:
101
- # * :server - The server to run the SQL on.
105
+ # :server :: The server to run the SQL on.
106
+ #
107
+ # DB.run("SET some_server_variable = 42")
102
108
  def run(sql, opts={})
103
109
  execute_ddl(sql, opts)
104
110
  nil
@@ -109,13 +115,40 @@ module Sequel
109
115
  # the first member being the column name, and the second member being a hash of column information.
110
116
  # Available options are:
111
117
  #
112
- # * :reload - Get fresh information from the database, instead of using
113
- # cached information. If table_name is blank, :reload should be used
114
- # unless you are sure that schema has not been called before with a
115
- # table_name, otherwise you may only getting the schemas for tables
116
- # that have been requested explicitly.
117
- # * :schema - An explicit schema to use. It may also be implicitly provided
118
- # via the table name.
118
+ # :reload :: Ignore any cached results, and get fresh information from the database.
119
+ # :schema :: An explicit schema to use. It may also be implicitly provided
120
+ # via the table name.
121
+ #
122
+ # If schema parsing is supported by the database, the column information should at least contain the
123
+ # following columns:
124
+ #
125
+ # :allow_null :: Whether NULL is an allowed value for the column.
126
+ # :db_type :: The database type for the column, as a database specific string.
127
+ # :default :: The database default for the column, as a database specific string.
128
+ # :primary_key :: Whether the columns is a primary key column. If this column is not present,
129
+ # it means that primary key information is unavailable, not that the column
130
+ # is not a primary key.
131
+ # :ruby_default :: The database default for the column, as a ruby object. In many cases, complex
132
+ # database defaults cannot be parsed into ruby objects.
133
+ # :type :: A symbol specifying the type, such as :integer or :string.
134
+ #
135
+ # Example:
136
+ #
137
+ # DB.schema(:artists)
138
+ # # [[:id,
139
+ # # {:type=>:integer,
140
+ # # :primary_key=>true,
141
+ # # :default=>"nextval('artist_id_seq'::regclass)",
142
+ # # :ruby_default=>nil,
143
+ # # :db_type=>"integer",
144
+ # # :allow_null=>false}],
145
+ # # [:name,
146
+ # # {:type=>:string,
147
+ # # :primary_key=>false,
148
+ # # :default=>nil,
149
+ # # :ruby_default=>nil,
150
+ # # :db_type=>"text",
151
+ # # :allow_null=>false}]]
119
152
  def schema(table, opts={})
120
153
  raise(Error, 'schema parsing is not implemented on this database') unless respond_to?(:schema_parse_table, true)
121
154
 
@@ -134,6 +167,8 @@ module Sequel
134
167
 
135
168
  # Returns true if a table with the given name exists. This requires a query
136
169
  # to the database.
170
+ #
171
+ # DB.table_exists?(:foo) # => false
137
172
  def table_exists?(name)
138
173
  begin
139
174
  from(name).first
@@ -144,6 +179,8 @@ module Sequel
144
179
  end
145
180
 
146
181
  # Return all tables in the database as an array of symbols.
182
+ #
183
+ # DB.tables # => [:albums, :artists]
147
184
  def tables(opts={})
148
185
  raise NotImplemented, "#tables should be overridden by adapters"
149
186
  end
@@ -155,13 +192,15 @@ module Sequel
155
192
  # The following options are respected:
156
193
  #
157
194
  # :isolation :: The transaction isolation level to use for this transaction,
158
- # should be :uncommitted, :committed, :repeatable, or :serializable.
195
+ # should be :uncommitted, :committed, :repeatable, or :serializable,
196
+ # used if given and the database/adapter supports customizable
197
+ # transaction isolation levels.
159
198
  # :prepare :: A string to use as the transaction identifier for a
160
199
  # prepared transaction (two-phase commit), if the database/adapter
161
- # supports prepared transactions
162
- # :server :: The server to use for the transaction
200
+ # supports prepared transactions.
201
+ # :server :: The server to use for the transaction.
163
202
  # :savepoint :: Whether to create a new savepoint for this transaction,
164
- # only respected if the database adapter supports savepoints. By
203
+ # only respected if the database/adapter supports savepoints. By
165
204
  # default Sequel will reuse an existing transaction, so if you want to
166
205
  # use a savepoint you must use this option.
167
206
  def transaction(opts={}, &block)
@@ -175,7 +214,7 @@ module Sequel
175
214
 
176
215
  # Internal generic transaction method. Any exception raised by the given
177
216
  # block will cause the transaction to be rolled back. If the exception is
178
- # not Sequel::Rollback, the error will be reraised. If no exception occurs
217
+ # not a Sequel::Rollback, the error will be reraised. If no exception occurs
179
218
  # inside the block, the transaction is commited.
180
219
  def _transaction(conn, opts={})
181
220
  begin
@@ -379,8 +418,8 @@ module Sequel
379
418
  end
380
419
 
381
420
  # Match the database's column type to a ruby type via a
382
- # regular expression. The following ruby types are supported:
383
- # integer, string, date, datetime, boolean, and float.
421
+ # regular expression, and return the ruby type as a symbol
422
+ # such as :integer or :string.
384
423
  def schema_column_type(db_type)
385
424
  case db_type
386
425
  when /\Ainterval\z/io
@@ -19,13 +19,13 @@ module Sequel
19
19
  GENERIC_TYPES=[String, Integer, Fixnum, Bignum, Float, Numeric, BigDecimal,
20
20
  Date, DateTime, Time, File, TrueClass, FalseClass]
21
21
 
22
- # Return the columns created by this generator
22
+ # Return the column hashes created by this generator
23
23
  attr_reader :columns
24
24
 
25
- # Return the constraints created by this generator
25
+ # Return the constraint hashes created by this generator
26
26
  attr_reader :constraints
27
27
 
28
- # Return the indexes created by this generator
28
+ # Return the index hashes created by this generator
29
29
  attr_reader :indexes
30
30
 
31
31
  # Set the database in which to create the table, and evaluate the block
@@ -50,14 +50,26 @@ module Sequel
50
50
  end
51
51
  end
52
52
 
53
- # Add a unnamed constraint to the DDL, specified by the given block
54
- # or args.
53
+ # Add an unnamed constraint to the DDL, specified by the given block
54
+ # or args:
55
+ #
56
+ # check(:num=>1..5) # CHECK num >= 1 AND num <= 5
57
+ # check{num > 5} # CHECK num > 5
55
58
  def check(*args, &block)
56
59
  constraint(nil, *args, &block)
57
60
  end
58
61
 
59
62
  # Add a column with the given name, type, and opts to the DDL.
60
63
  #
64
+ # column :num, :integer
65
+ # # num INTEGER
66
+ #
67
+ # column :name, String, :null=>false, :default=>'a'
68
+ # # name varchar(255) NOT NULL DEFAULT 'a'
69
+ #
70
+ # inet :ip
71
+ # # ip inet
72
+ #
61
73
  # You can also create columns via method missing, so the following are
62
74
  # equivalent:
63
75
  #
@@ -66,30 +78,32 @@ module Sequel
66
78
  #
67
79
  # The following options are supported:
68
80
  #
69
- # * :default - The default value for the column.
70
- # * :index - Create an index on this column.
71
- # * :key - For foreign key columns, the column in the associated table
72
- # that this column references. Unnecessary if this column
73
- # references the primary key of the associated table.
74
- # * :null - Mark the column as allowing NULL values (if true),
75
- # or not allowing NULL values (if false). If unspecified, will default
76
- # to whatever the database default is.
77
- # * :on_delete - Specify the behavior of this column when being deleted.
78
- # See Schema::SQL#on_delete_clause for options.
79
- # * :on_update - Specify the behavior of this column when being updated.
80
- # See Schema::SQL#on_delete_clause for options.
81
- # * :size - The size of the column, generally used with string
82
- # columns to specify the maximum number of characters the column will hold.
83
- # An array of two integers can be provided to set the size and the
84
- # precision, respectively, of decimal columns.
85
- # * :unique - Mark the column as unique, generally has the same effect as
86
- # creating a unique index on the column.
87
- # * :unsigned - Make the column type unsigned, only useful for integer
88
- # columns.
89
- # * :deferrable - This ensure Referential Integrity will work even if
90
- # reference table will use for its foreign key a value that does not
91
- # exists(yet) on referenced table. Basically it adds
92
- # DEFERRABLE INITIALLY DEFERRED on key creation.
81
+ # :default :: The default value for the column.
82
+ # :deferrable :: This ensure Referential Integrity will work even if
83
+ # reference table will use for its foreign key a value that does not
84
+ # exists(yet) on referenced table. Basically it adds
85
+ # DEFERRABLE INITIALLY DEFERRED on key creation.
86
+ # :index :: Create an index on this column.
87
+ # :key :: For foreign key columns, the column in the associated table
88
+ # that this column references. Unnecessary if this column
89
+ # references the primary key of the associated table.
90
+ # :null :: Mark the column as allowing NULL values (if true),
91
+ # or not allowing NULL values (if false). If unspecified, will default
92
+ # to whatever the database default is.
93
+ # :on_delete :: Specify the behavior of this column when being deleted
94
+ # (:restrict, cascade, :set_null, :set_default, :no_action).
95
+ # :on_update :: Specify the behavior of this column when being updated
96
+ # (:restrict, cascade, :set_null, :set_default, :no_action).
97
+ # :primary_key :: Make the column as a single primary key column. This should only
98
+ # be used if you have a single, nonautoincrementing primary key column.
99
+ # :size :: The size of the column, generally used with string
100
+ # columns to specify the maximum number of characters the column will hold.
101
+ # An array of two integers can be provided to set the size and the
102
+ # precision, respectively, of decimal columns.
103
+ # :unique :: Mark the column as unique, generally has the same effect as
104
+ # creating a unique index on the column.
105
+ # :unsigned :: Make the column type unsigned, only useful for integer
106
+ # columns.
93
107
  def column(name, type, opts = {})
94
108
  columns << {:name => name, :type => type}.merge(opts)
95
109
  index(name) if opts[:index]
@@ -97,12 +111,19 @@ module Sequel
97
111
 
98
112
  # Adds a named constraint (or unnamed if name is nil) to the DDL,
99
113
  # with the given block or args.
114
+ #
115
+ # constraint(:blah, :num=>1..5) # CONSTRAINT blah CHECK num >= 1 AND num <= 5
116
+ # check(:foo){num > 5} # CONSTRAINT foo CHECK num > 5
100
117
  def constraint(name, *args, &block)
101
118
  constraints << {:name => name, :type => :check, :check => block || args}
102
119
  end
103
120
 
104
121
  # Add a foreign key in the table that references another table to the DDL. See column
105
122
  # for available options.
123
+ #
124
+ # foreign_key(:artist_id) # artist_id INTEGER
125
+ # foreign_key(:artist_id, :artists) # artist_id INTEGER REFERENCES artists
126
+ # foreign_key(:artist_id, :artists, :key=>:id) # artist_id INTEGER REFERENCES artists(id)
106
127
  def foreign_key(name, table=nil, opts = {})
107
128
  opts = case table
108
129
  when Hash
@@ -131,31 +152,38 @@ module Sequel
131
152
  # Add an index on the given column(s) with the given options to the DDL.
132
153
  # The available options are:
133
154
  #
134
- # * :type - The type of index to use (only supported by some databases)
135
- # * :unique - Make the index unique, so duplicate values are not allowed.
136
- # * :where - Create a partial index (only supported by some databases)
155
+ # :type :: The type of index to use (only supported by some databases)
156
+ # :unique :: Make the index unique, so duplicate values are not allowed.
157
+ # :where :: Create a partial index (only supported by some databases)
158
+ #
159
+ # index :name
160
+ # # CREATE INDEX table_name_index ON table (name)
161
+ #
162
+ # index [:artist_id, :name]
163
+ # # CREATE INDEX table_artist_id_name_index ON table (artist_id, name)
137
164
  def index(columns, opts = {})
138
165
  indexes << {:columns => Array(columns)}.merge(opts)
139
166
  end
140
167
 
141
- # Add a column with the given type, name, and opts to the DDL. See column for available
168
+ # Add a column with the given type, name, and opts to the DDL. See +column+ for available
142
169
  # options.
143
170
  def method_missing(type, name = nil, opts = {})
144
171
  name ? column(name, type, opts) : super
145
172
  end
146
173
 
147
- # Add primary key information to the DDL. Takes between one and three
148
- # arguments. The last one is an options hash as for Generator#column.
149
- # The first one distinguishes two modes: an array of existing column
150
- # names adds a composite primary key constraint. A single symbol adds a
151
- # new column of that name and makes it the primary key. In that case the
152
- # optional middle argument denotes the type.
174
+ # Adds an autoincrementing primary key column or a primary key constraint to the DDL.
175
+ # To create a constraint, the first argument should be an array of column symbols
176
+ # specifying the primary key columns. To create an autoincrementing primary key
177
+ # column, a single symbol can be used. In both cases, an options hash can be used
178
+ # as the second argument.
179
+ #
180
+ # If you want to create a primary key column that is not autoincrementing, you
181
+ # should not use this method. Instead, you should use the regular +column+ method
182
+ # with a <tt>:primary_key=>true</tt> option.
153
183
  #
154
184
  # Examples:
155
185
  # primary_key(:id)
156
- # primary_key(:zip_code, :null => false)
157
186
  # primary_key([:street_number, :house_number])
158
- # primary_key(:id, :string, :auto_increment => false)
159
187
  def primary_key(name, *args)
160
188
  return composite_primary_key(name, *args) if name.is_a?(Array)
161
189
  @primary_key = @db.serial_primary_key_options.merge({:name => name})
@@ -170,7 +198,7 @@ module Sequel
170
198
  @primary_key
171
199
  end
172
200
 
173
- # The name of the primary key for this table, if it has a primary key.
201
+ # The name of the primary key for this generator, if it has a primary key.
174
202
  def primary_key_name
175
203
  @primary_key[:name] if @primary_key
176
204
  end
@@ -181,6 +209,8 @@ module Sequel
181
209
  end
182
210
 
183
211
  # Add a unique constraint on the given columns to the DDL.
212
+ #
213
+ # unique(:name) # UNIQUE (name)
184
214
  def unique(columns, opts = {})
185
215
  constraints << {:type => :unique, :columns => Array(columns)}.merge(opts)
186
216
  end
@@ -205,7 +235,7 @@ module Sequel
205
235
  # to instantiate directly. Instances are created by Database#alter_table.
206
236
  # It is used to specify table alteration parameters. It takes a Database
207
237
  # object and a block of operations to perform on the table, and
208
- # gives the Database a table an array of operations, which the database uses to
238
+ # gives the Database an array of table altering operations, which the database uses to
209
239
  # alter a table's description.
210
240
  #
211
241
  # For more information on Sequel's support for schema modification, see
@@ -224,17 +254,25 @@ module Sequel
224
254
 
225
255
  # Add a column with the given name, type, and opts to the DDL for the table.
226
256
  # See Generator#column for the available options.
257
+ #
258
+ # add_column(:name, String) # ADD COLUMN name varchar(255)
227
259
  def add_column(name, type, opts = {})
228
260
  @operations << {:op => :add_column, :name => name, :type => type}.merge(opts)
229
261
  end
230
262
 
231
263
  # Add a constraint with the given name and args to the DDL for the table.
232
264
  # See Generator#constraint.
265
+ #
266
+ # add_constraint(:valid_name, :name.like('A%'))
267
+ # # ADD CONSTRAINT valid_name CHECK (name LIKE 'A%')
233
268
  def add_constraint(name, *args, &block)
234
269
  @operations << {:op => :add_constraint, :name => name, :type => :check, :check => block || args}
235
270
  end
236
271
 
237
272
  # Add a unique constraint to the given column(s)
273
+ #
274
+ # add_unique_constraint(:name) # ADD UNIQUE (name)
275
+ # add_unique_constraint(:name, :name=>:unique_name) # ADD CONSTRAINT unique_name UNIQUE (name)
238
276
  def add_unique_constraint(columns, opts = {})
239
277
  @operations << {:op => :add_constraint, :type => :unique, :columns => Array(columns)}.merge(opts)
240
278
  end
@@ -246,8 +284,11 @@ module Sequel
246
284
  # keys. In this case, it will assume the columns exists and will only add
247
285
  # the constraint.
248
286
  #
249
- # NOTE: If you need to add a foreign key constraint to an existing column
287
+ # NOTE: If you need to add a foreign key constraint to a single existing column
250
288
  # use the composite key syntax even if it is only one column.
289
+ #
290
+ # add_foreign_key(:artist_id, :table) # ADD COLUMN artist_id integer REFERENCES table
291
+ # add_foreign_key([:name], :table) # ADD FOREIGN KEY (name) REFERENCES table
251
292
  def add_foreign_key(name, table, opts = {})
252
293
  return add_composite_foreign_key(name, table, opts) if name.is_a?(Array)
253
294
  add_column(name, Integer, {:table=>table}.merge(opts))
@@ -261,12 +302,18 @@ module Sequel
261
302
 
262
303
  # Add an index on the given columns to the DDL for the table. See
263
304
  # Generator#index for available options.
305
+ #
306
+ # add_index(:artist_id) # CREATE INDEX table_artist_id_index ON table (artist_id)
264
307
  def add_index(columns, opts = {})
265
308
  @operations << {:op => :add_index, :columns => Array(columns)}.merge(opts)
266
309
  end
267
310
 
268
311
  # Add a primary key to the DDL for the table. See Generator#column
269
- # for the available options.
312
+ # for the available options. Like +add_foreign_key+, if you specify
313
+ # the column name as an array, it just creates a constraint:
314
+ #
315
+ # add_primary_key(:id) # ADD COLUMN id serial PRIMARY KEY
316
+ # add_primary_key([:artist_id, :name]) # ADD PRIMARY KEY (artist_id, name)
270
317
  def add_primary_key(name, opts = {})
271
318
  return add_composite_primary_key(name, opts) if name.is_a?(Array)
272
319
  opts = @db.serial_primary_key_options.merge(opts)
@@ -280,36 +327,52 @@ module Sequel
280
327
  end
281
328
 
282
329
  # Remove a column from the DDL for the table.
330
+ #
331
+ # drop_column(:artist_id) # DROP COLUMN artist_id
283
332
  def drop_column(name)
284
333
  @operations << {:op => :drop_column, :name => name}
285
334
  end
286
335
 
287
336
  # Remove a constraint from the DDL for the table.
337
+ #
338
+ # drop_constraint(:unique_name) # DROP CONSTRAINT unique_name
288
339
  def drop_constraint(name)
289
340
  @operations << {:op => :drop_constraint, :name => name}
290
341
  end
291
342
 
292
343
  # Remove an index from the DDL for the table.
344
+ #
345
+ # drop_index(:artist_id) # DROP INDEX table_artist_id_index
346
+ # drop_index([:a, :b]) # DROP INDEX table_a_b_index
347
+ # drop_index([:a, :b], :name=>:foo) # DROP INDEX foo
293
348
  def drop_index(columns, options={})
294
349
  @operations << {:op => :drop_index, :columns => Array(columns)}.merge(options)
295
350
  end
296
351
 
297
352
  # Modify a column's name in the DDL for the table.
353
+ #
354
+ # rename_column(:name, :artist_name) # RENAME COLUMN name TO artist_name
298
355
  def rename_column(name, new_name, opts = {})
299
356
  @operations << {:op => :rename_column, :name => name, :new_name => new_name}.merge(opts)
300
357
  end
301
358
 
302
359
  # Modify a column's default value in the DDL for the table.
360
+ #
361
+ # set_column_default(:artist_name, 'a') # ALTER COLUMN artist_name SET DEFAULT 'a'
303
362
  def set_column_default(name, default)
304
363
  @operations << {:op => :set_column_default, :name => name, :default => default}
305
364
  end
306
365
 
307
366
  # Modify a column's type in the DDL for the table.
367
+ #
368
+ # set_column_type(:artist_name, 'char(10)') # ALTER COLUMN artist_name TYPE char(10)
308
369
  def set_column_type(name, type, opts={})
309
370
  @operations << {:op => :set_column_type, :name => name, :type => type}.merge(opts)
310
371
  end
311
372
 
312
373
  # Modify a column's NOT NULL constraint.
374
+ #
375
+ # set_column_allow_null(:artist_name, false) # ALTER COLUMN artist_name SET NOT NULL
313
376
  def set_column_allow_null(name, allow_null)
314
377
  @operations << {:op => :set_column_null, :name => name, :null => allow_null}
315
378
  end