sequel 3.13.0 → 3.14.0

Sign up to get free protection for your applications and to get access to all the features.
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