sequel 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +32 -0
  3. data/doc/active_record.rdoc +2 -2
  4. data/doc/cheat_sheet.rdoc +0 -5
  5. data/doc/opening_databases.rdoc +3 -2
  6. data/doc/prepared_statements.rdoc +6 -0
  7. data/doc/release_notes/4.1.0.txt +85 -0
  8. data/doc/schema_modification.rdoc +9 -2
  9. data/lib/sequel/adapters/jdbc.rb +5 -0
  10. data/lib/sequel/adapters/mysql2.rb +24 -3
  11. data/lib/sequel/adapters/odbc.rb +6 -4
  12. data/lib/sequel/adapters/postgres.rb +25 -0
  13. data/lib/sequel/adapters/shared/mysql.rb +4 -29
  14. data/lib/sequel/adapters/shared/postgres.rb +14 -3
  15. data/lib/sequel/adapters/shared/sqlite.rb +4 -0
  16. data/lib/sequel/adapters/utils/replace.rb +36 -0
  17. data/lib/sequel/database/query.rb +1 -0
  18. data/lib/sequel/database/schema_generator.rb +12 -5
  19. data/lib/sequel/database/schema_methods.rb +2 -0
  20. data/lib/sequel/dataset/features.rb +5 -0
  21. data/lib/sequel/extensions/pg_json_ops.rb +0 -6
  22. data/lib/sequel/model/associations.rb +1 -1
  23. data/lib/sequel/plugins/instance_filters.rb +11 -1
  24. data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -2
  25. data/lib/sequel/plugins/prepared_statements.rb +38 -9
  26. data/lib/sequel/plugins/update_primary_key.rb +10 -0
  27. data/lib/sequel/sql.rb +1 -1
  28. data/lib/sequel/version.rb +1 -1
  29. data/spec/adapters/mysql_spec.rb +1 -22
  30. data/spec/adapters/postgres_spec.rb +79 -2
  31. data/spec/core/database_spec.rb +10 -0
  32. data/spec/core/dataset_spec.rb +8 -3
  33. data/spec/core/expression_filters_spec.rb +1 -1
  34. data/spec/core/schema_spec.rb +17 -2
  35. data/spec/extensions/caching_spec.rb +2 -2
  36. data/spec/extensions/hook_class_methods_spec.rb +0 -4
  37. data/spec/extensions/instance_filters_spec.rb +22 -0
  38. data/spec/extensions/migration_spec.rb +5 -5
  39. data/spec/extensions/nested_attributes_spec.rb +4 -4
  40. data/spec/extensions/prepared_statements_spec.rb +37 -26
  41. data/spec/extensions/update_primary_key_spec.rb +13 -0
  42. data/spec/integration/dataset_test.rb +36 -0
  43. data/spec/model/associations_spec.rb +20 -2
  44. data/spec/model/hooks_spec.rb +1 -7
  45. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f1f6d7107eb83ff3840572817d310bdf10371ad
4
- data.tar.gz: 4f04ad59f41290e20d2aba5af08947ef0ceb52e0
3
+ metadata.gz: a449facae4b3dcc14c19ce0f524ca2025db4c74e
4
+ data.tar.gz: 19e4bbb80143055d03da8134f6308363ff8e2406
5
5
  SHA512:
6
- metadata.gz: 355ac8d6ada27fbb499219b662c1a0a884777b0f6e95e98681415acc321bcef3178e494e5252fffa3417b086c3fcc2c04bd6fa9f45fbdc7d0f894fe5883fcbc8
7
- data.tar.gz: 5cb1f4ef00bfaabc721e75baf1b02756e2b82a9f9c1fa2c241f01a6d717bee27c6d37b7c0bfd6876c85d9d0b78447a1d57ee9e2f6906902cf079f9d1773c0c9d
6
+ metadata.gz: 68c5cbe1672f325a040584b37b78188c34322b6505b7b267d61d7103ee8a3f2364e335324f330a4c63e239eb21896c66242c9c62de91b2052d6bc2ad03289dcf
7
+ data.tar.gz: 0ee8a1dbc5118fa916c90f112142b3580b2dbbfb4a5eca8f3f5924b510043e488cfbc2d1f1335db587a30b8dfe3a3b02754b46586ce770a38b6bc76ddb004fd0
data/CHANGELOG CHANGED
@@ -1,3 +1,35 @@
1
+ === 4.1.0 (2013-08-01)
2
+
3
+ * Support :inherits option in Database#create_table on PostgreSQL, for table inheritance (jeremyevans)
4
+
5
+ * Handle dropping indexes for schema qualified tables on PostgreSQL (jeremyevans)
6
+
7
+ * Add Database#error_info on PostgreSQL 9.3+ if pg-0.16.0+ is used, to get a hash of metadata for a given database exception (jeremyevans)
8
+
9
+ * Allow prepared_statements plugin to work with instance_filters and update_primary_key plugins (jeremyevans)
10
+
11
+ * Support deferrable exclusion constraints on PostgreSQL using the :deferrable option (mfoody) (#687)
12
+
13
+ * Make Database#run and #<< accept SQL::PlaceholderLiteralString values (jeremyevans)
14
+
15
+ * Deprecate :driver option in odbc adapter since it appears to be broken (jeremyevans)
16
+
17
+ * Support :drvconnect option in odbc adapter for supplying the ODBC connection string directly (jeremyevans)
18
+
19
+ * Support mysql2 0.3.12+ result streaming via Dataset#stream (jeremyevans)
20
+
21
+ * Convert Java::JavaUtil::HashMap to ruby Hash in jdbc adapter, for better handling of PostgreSQL hstore type (jeremyevans) (#686)
22
+
23
+ * Raise NoMatchingRow if calling add_association with a primary key value that doesn't match an existing row (jeremyevans)
24
+
25
+ * Allow PostgreSQL add_constraint to support :not_valid option (jeremyevans)
26
+
27
+ * Allow CHECK constraints to have options by using an options hash as the constraint name (jeremyevans)
28
+
29
+ * Correctly raise error when using an invalid virtual row block function call (jeremyevans)
30
+
31
+ * Support REPLACE on SQLite via Dataset#replace and #multi_replace (etehtsea) (#681)
32
+
1
33
  === 4.0.0 (2013-07-01)
2
34
 
3
35
  * Correctly parse composite primary keys on SQLite 3.7.16+ (jeremyevans)
@@ -742,12 +742,12 @@ ActiveRecord Method :: Notes, Workarounds
742
742
  <tt>clear_active_connections!</tt> :: Sequel doesn't leak connections like ActiveRecord, so you don't need to worry about this
743
743
  <tt>clear_reloadable_connections!</tt> :: Sequel doesn't leak connections like ActiveRecord, so you don't need to worry about this
744
744
  +content_columns+ :: Not needed internally, you can probably do <tt>Album.columns.map{|x| x.to_s}.delete_if{|x| x == Album.primary_key || x =~ /_(id|count)\z/}</tt>
745
- +decrement_counter+ :: <tt>Album.where(:id=>:id).update(:counter_name=>:counter_name - 1)</tt>
745
+ +decrement_counter+ :: <tt>Album.where(:id=>:id).update(:counter_name=>Sequel.-(:counter_name, 1))</tt>
746
746
  +define_attribute_methods+, +define_read_methods+ :: <tt>def_column_accessor(*columns)</tt>, a private method
747
747
  <tt>descends_from_active_record?</tt> :: Not needed internally, if using single table inheritance, <tt>Album.sti_dataset.model == Album</tt>
748
748
  +find_each+, +find_in_batches+ :: Use the +pagination+ extension
749
749
  <tt>generated_methods?</tt> :: No equivalent
750
- +increment_counter+ :: <tt>Album.where(:id=>:id).update(:counter_name=>:counter_name + 1)</tt>
750
+ +increment_counter+ :: <tt>Album.where(:id=>:id).update(:counter_name=>Sequel.+(:counter_name, 1))</tt>
751
751
  <tt>instance_method_already_implemented?</tt> :: No equivalent, Sequel does not create column accessors that override other methods, it just skips them.
752
752
  <tt>match_attribute_method?</tt> :: No equivalent
753
753
  +readonly_attributes+ :: No equivalent
data/doc/cheat_sheet.rdoc CHANGED
@@ -166,11 +166,6 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
166
166
 
167
167
  DB.drop_table :items
168
168
 
169
- DB.create_table :test do
170
- String :zipcode
171
- enum :system, :elements => ['mac', 'linux', 'windows']
172
- end
173
-
174
169
  == Aliasing
175
170
 
176
171
  DB[:items].select(Sequel.as(:name, :item_name))
@@ -321,8 +321,9 @@ The :database option given ODBC database should be the DSN (Descriptive Service
321
321
 
322
322
  The :host and :port options are not respected. The following additional options are supported:
323
323
 
324
- :db_type :: Can be specified as 'mssql' or 'progress' to use SQL syntax specific to those databases.
325
- :driver :: The name of the ODBC driver to utilize.
324
+ :db_type :: Can be specified as 'mssql', 'progress', or 'db2' to use SQL syntax specific to those databases.
325
+ :drvconnect :: Can be given an ODBC connection string, and will use ODBC::Database#drvconnect to
326
+ do the connection. Typical usage would be: <tt>Sequel.odbc(:drvconnect=>'driver={...};...')</tt>
326
327
 
327
328
  === openbase
328
329
 
@@ -31,6 +31,12 @@ placeholders, e.g.:
31
31
 
32
32
  ds = DB[:items].where(:name=>:$n)
33
33
 
34
+ You can use these placeholders in most places where you can use the value
35
+ directly. For example, if you want to use placeholders while also using
36
+ raw SQL, you can do:
37
+
38
+ ds = DB["SELECT * FROM items WHERE name = ?", :$n]
39
+
34
40
  == Bound Variables
35
41
 
36
42
  Using bound variables for this query is simple:
@@ -0,0 +1,85 @@
1
+ = New Features
2
+
3
+ * Database#run and #<< now accept SQL::PlaceholderLiteralString
4
+ objects, allowing you to more easily run arbitrary DDL queries with
5
+ placeholders:
6
+
7
+ DB.run Sequel.lit("CREATE TABLE ? (? integer)", :table, :column)
8
+
9
+ * You can now provide options for check constraints by calling the
10
+ constraint/add_constraint methods with a hash as the first argument.
11
+ On PostgreSQL, you can now use the :not_valid option for check
12
+ constraints, so they are enforced for inserts and updates, but
13
+ not for existing rows.
14
+
15
+ DB.create_table(:table) do
16
+ ...
17
+ constraint({:name=>:constraint_name, :not_valid=>true}) do
18
+ column_name > 10
19
+ end
20
+ end
21
+
22
+ * Dataset#stream has been added to the mysql2 adapter, and will have
23
+ the dataset stream results if used with mysql2 0.3.12+. This
24
+ allows you to process large datasets without keeping the entire
25
+ dataset in memory.
26
+
27
+ DB[:large_table].stream.each{|r| ...}
28
+
29
+ * Database#error_info has been added to the postgres adapter. It
30
+ is supported on PostgreSQL 9.3+ if pg-0.16.0+ is used as the
31
+ underlying driver, and it gives you a hash of metadata related
32
+ to the exception:
33
+
34
+ DB[:table_name].insert(1) rescue DB.error_info($!)
35
+ # => {:schema=>"public", :table=>"table_name", :column=>nil,
36
+ :constraint=>"constraint_name", :type=>nil}
37
+
38
+ * The :deferrable option is now supported when adding exclusion
39
+ constraints on PostgreSQL, to allow setting up deferred exclusion
40
+ constraints.
41
+
42
+ * The :inherits option is now supported in Database#create_table on
43
+ PostgreSQL, for table inheritance:
44
+
45
+ DB.create_table(:t1, :inherits=>:t0){}
46
+ # CREATE TABLE t1 () INHERITS (t0)
47
+
48
+ * Dataset#replace and #multi_replace are now supported on SQLite,
49
+ just as they have been previously on MySQL.
50
+
51
+ * In the jdbc adapter, Java::JavaUtil::HashMap objects are now
52
+ converted to ruby Hash objects. This is to make it easier to
53
+ handle the PostgreSQL hstore type when using the jdbc/postgres
54
+ adapter.
55
+
56
+ * The odbc adapter now supports a :drvconnect option that accepts
57
+ an ODBC connection string that is passed to ruby-odbc verbatim.
58
+
59
+ = Other Improvements
60
+
61
+ * The prepared_statements plugin no longer breaks the
62
+ instance_filters and update_primary_key plugins.
63
+
64
+ * Dropping indexes for tables in a specific schema is now supported
65
+ on PostgreSQL. Sequel now explicitly specifies the same schema
66
+ as the table when dropping such indexes.
67
+
68
+ * Calling Model#add_association methods with a primary key value
69
+ now raises a Sequel::NoMatchingRow if there is no object in the
70
+ associated table with that primary key. Previously, this
71
+ situation was not handled and resulted in a NoMethodError being
72
+ raised later.
73
+
74
+ * When an invalid virtual row block function call is detected, an
75
+ error is now properly raised. Previously, the error was not
76
+ raised until the SQL was produced for the query.
77
+
78
+ = Backwards Compatibility
79
+
80
+ * The :driver option to the odbc adapter is deprecated and will be
81
+ removed in a future version. It is thought to be broken, and
82
+ users wanting to use DSN-less connections should use the new
83
+ :drvconnect option.
84
+
85
+ * The Postgres::ArrayOp#text_op private method has been removed.
@@ -88,6 +88,9 @@ method, the fourth argument is the options hash. The following options are supp
88
88
  :primary_key :: Mark this column as the primary key. This is used instead of the
89
89
  primary key method if you want a non-autoincrementing primary key.
90
90
  :primary_key_constraint_name :: The name to give the primary key constraint.
91
+ :type :: Overrides the type given as the method name or a separate argument.
92
+ Not usually used by +column+ itself, but often by other methods such
93
+ as +primary_key+ or +foreign_key+.
91
94
  :unique :: Mark the column as unique, generally has the same effect as
92
95
  creating a unique index on the column.
93
96
  :unique_constraint_name :: The name to give the unique key constraint.
@@ -137,12 +140,16 @@ as it's third argument. A simple example is:
137
140
  String :name
138
141
  end
139
142
 
140
- +foreign_key+ accepts some specific options:
143
+ +foreign_key+ accepts the same options as +column+. For example, to have a unique foreign key with varchar(16) type:
144
+
145
+ foreign_key :column_name, :unique=>true, :type=>'varchar(16)'
146
+
147
+ +foreign_key+ also accepts some specific options:
141
148
 
142
149
  :deferrable :: Makes the foreign key constraint checks deferrable, so they aren't checked
143
150
  until the end of the transaction.
144
151
  :foreign_key_constraint_name :: The name to give the foreign key constraint.
145
- :key :: For foreign key columns, the column in the associated table
152
+ :key :: The column in the associated table
146
153
  that this column references. Unnecessary if this column
147
154
  references the primary key of the associated table, at least
148
155
  on most databases.
@@ -696,6 +696,7 @@ module Sequel
696
696
  JAVA_BIG_DECIMAL = Java::JavaMath::BigDecimal
697
697
  JAVA_BYTE_ARRAY = Java::byte[]
698
698
  JAVA_UUID = Java::JavaUtil::UUID
699
+ JAVA_HASH_MAP = Java::JavaUtil::HashMap
699
700
 
700
701
  # Handle type conversions for common Java types.
701
702
  class TYPE_TRANSLATOR
@@ -717,6 +718,7 @@ module Sequel
717
718
  lines
718
719
  end
719
720
  def uuid(v) v.to_string end
721
+ def hash_map(v) v.to_hash end
720
722
  end
721
723
  TYPE_TRANSLATOR_INSTANCE = tt = TYPE_TRANSLATOR.new
722
724
 
@@ -730,6 +732,7 @@ module Sequel
730
732
  BLOB_METHOD = tt.method(:blob)
731
733
  CLOB_METHOD = tt.method(:clob)
732
734
  UUID_METHOD = tt.method(:uuid)
735
+ HASH_MAP_METHOD = tt.method(:hash_map)
733
736
 
734
737
  # Convert the given Java timestamp to an instance of Sequel.datetime_class.
735
738
  def convert_type_timestamp(v)
@@ -759,6 +762,8 @@ module Sequel
759
762
  CLOB_METHOD
760
763
  when JAVA_UUID
761
764
  UUID_METHOD
765
+ when JAVA_HASH_MAP
766
+ HASH_MAP_METHOD
762
767
  else
763
768
  false
764
769
  end
@@ -72,9 +72,23 @@ module Sequel
72
72
  # yield the connection if a block is given.
73
73
  def _execute(conn, sql, opts)
74
74
  begin
75
- r = log_yield((log_sql = opts[:log_sql]) ? sql + log_sql : sql){conn.query(sql, :database_timezone => timezone, :application_timezone => Sequel.application_timezone)}
75
+ stream = opts[:stream]
76
+ r = log_yield((log_sql = opts[:log_sql]) ? sql + log_sql : sql){conn.query(sql, :database_timezone => timezone, :application_timezone => Sequel.application_timezone, :stream=>stream)}
76
77
  if opts[:type] == :select
77
- yield r if r
78
+ if r
79
+ if stream
80
+ begin
81
+ r2 = yield r
82
+ ensure
83
+ # If r2 is nil, it means the block did not exit normally,
84
+ # so the rest of the results must be drained to prevent
85
+ # "commands out of sync" errors.
86
+ r.each{} unless r2
87
+ end
88
+ else
89
+ yield r
90
+ end
91
+ end
78
92
  elsif block_given?
79
93
  yield conn
80
94
  end
@@ -145,6 +159,13 @@ module Sequel
145
159
  self
146
160
  end
147
161
 
162
+ # Return a clone of the dataset that will stream rows when iterating
163
+ # over the result set, so it can handle large datasets that
164
+ # won't fit in memory (Requires mysql 0.3.12 to have an effect).
165
+ def stream
166
+ clone(:stream=>true)
167
+ end
168
+
148
169
  private
149
170
 
150
171
  # Whether to cast tinyint(1) columns to integer instead of boolean.
@@ -156,7 +177,7 @@ module Sequel
156
177
 
157
178
  # Set the :type option to :select if it hasn't been set.
158
179
  def execute(sql, opts=OPTS, &block)
159
- super(sql, {:type=>:select}.merge(opts), &block)
180
+ super(sql, {:type=>:select, :stream=>@opts[:stream]}.merge(opts), &block)
160
181
  end
161
182
 
162
183
  # Handle correct quoting of strings using ::Mysql2::Client#escape.
@@ -11,7 +11,10 @@ module Sequel
11
11
 
12
12
  def connect(server)
13
13
  opts = server_opts(server)
14
- if opts.include? :driver
14
+ conn = if opts.include?(:drvconnect)
15
+ ::ODBC::Database.new.drvconnect(opts[:drvconnect])
16
+ elsif opts.include?(:driver)
17
+ Deprecation.deprecate("The odbc driver's handling of the :driver option is thought to be broken and will probably be removed in the future. If you are successfully using it, please contact the developers.")
15
18
  drv = ::ODBC::Driver.new
16
19
  drv.name = 'Sequel ODBC Driver130'
17
20
  opts.each do |param, value|
@@ -20,10 +23,9 @@ module Sequel
20
23
  end
21
24
  drv.attrs[param.to_s.upcase] = value.to_s
22
25
  end
23
- db = ::ODBC::Database.new
24
- conn = db.drvconnect(drv)
26
+ ::ODBC::Database.new.drvconnect(drv)
25
27
  else
26
- conn = ::ODBC::connect(opts[:database], opts[:user], opts[:password])
28
+ ::ODBC::connect(opts[:database], opts[:user], opts[:password])
27
29
  end
28
30
  conn.autocommit = true
29
31
  conn
@@ -276,6 +276,31 @@ module Sequel
276
276
  rescue PGError, IOError
277
277
  end
278
278
  end
279
+
280
+ if SEQUEL_POSTGRES_USES_PG && Object.const_defined?(:PG) && ::PG.const_defined?(:Constants) && ::PG::Constants.const_defined?(:PG_DIAG_SCHEMA_NAME)
281
+ # Return a hash of information about the related PGError (or Sequel::DatabaseError that
282
+ # wraps a PGError), with the following entries:
283
+ #
284
+ # :schema :: The schema name related to the error
285
+ # :table :: The table name related to the error
286
+ # :column :: the column name related to the error
287
+ # :constraint :: The constraint name related to the error
288
+ # :type :: The datatype name related to the error
289
+ #
290
+ # This requires a PostgreSQL 9.3+ server and 9.3+ client library,
291
+ # and ruby-pg 0.16.0+ to be supported.
292
+ def error_info(e)
293
+ e = e.wrapped_exception if e.is_a?(DatabaseError)
294
+ r = e.result
295
+ h = {}
296
+ h[:schema] = r.error_field(::PG::PG_DIAG_SCHEMA_NAME)
297
+ h[:table] = r.error_field(::PG::PG_DIAG_TABLE_NAME)
298
+ h[:column] = r.error_field(::PG::PG_DIAG_COLUMN_NAME)
299
+ h[:constraint] = r.error_field(::PG::PG_DIAG_CONSTRAINT_NAME)
300
+ h[:type] = r.error_field(::PG::PG_DIAG_DATATYPE_NAME)
301
+ h
302
+ end
303
+ end
279
304
 
280
305
  # Execute the given SQL with the given args on an available connection.
281
306
  def execute(sql, opts=OPTS, &block)
@@ -1,4 +1,5 @@
1
1
  Sequel.require 'adapters/utils/split_alter_table'
2
+ Sequel.require 'adapters/utils/replace'
2
3
 
3
4
  module Sequel
4
5
  Dataset::NON_SQL_OPTIONS << :insert_ignore
@@ -532,7 +533,6 @@ module Sequel
532
533
  PAREN_CLOSE = Dataset::PAREN_CLOSE
533
534
  NOT_SPACE = Dataset::NOT_SPACE
534
535
  FROM = Dataset::FROM
535
- INSERT = Dataset::INSERT
536
536
  COMMA = Dataset::COMMA
537
537
  LIMIT = Dataset::LIMIT
538
538
  GROUP_BY = Dataset::GROUP_BY
@@ -552,7 +552,6 @@ module Sequel
552
552
  EMPTY_COLUMNS = " ()".freeze
553
553
  EMPTY_VALUES = " VALUES ()".freeze
554
554
  IGNORE = " IGNORE".freeze
555
- REPLACE = 'REPLACE'.freeze
556
555
  ON_DUPLICATE_KEY_UPDATE = " ON DUPLICATE KEY UPDATE ".freeze
557
556
  EQ_VALUES = '=VALUES('.freeze
558
557
  EQ = '='.freeze
@@ -565,7 +564,9 @@ module Sequel
565
564
  QUAD_BACKSLASH = "\\\\\\\\".freeze
566
565
  BLOB_START = "0x".freeze
567
566
  HSTAR = "H*".freeze
568
-
567
+
568
+ include Sequel::Dataset::Replace
569
+
569
570
  # MySQL specific syntax for LIKE/REGEXP searches, as well as
570
571
  # string concatenation.
571
572
  def complex_expression_sql_append(sql, op, args)
@@ -647,11 +648,6 @@ module Sequel
647
648
  SQL::PlaceholderLiteralString.new((opts[:boolean] ? MATCH_AGAINST_BOOLEAN : MATCH_AGAINST), [Array(cols), terms])
648
649
  end
649
650
 
650
- # MySQL allows HAVING clause on ungrouped datasets.
651
- def having(*cond, &block)
652
- _filter(:having, *cond, &block)
653
- end
654
-
655
651
  # Transforms an CROSS JOIN to an INNER JOIN if the expr is not nil.
656
652
  # Raises an error on use of :full_outer type, since MySQL doesn't support it.
657
653
  def join_table(type, table, expr=nil, opts=OPTS, &block)
@@ -719,23 +715,7 @@ module Sequel
719
715
  def quoted_identifier_append(sql, c)
720
716
  sql << BACKTICK << c.to_s.gsub(BACKTICK_RE, DOUBLE_BACKTICK) << BACKTICK
721
717
  end
722
-
723
- # Execute a REPLACE statement on the database.
724
- def replace(*values)
725
- execute_insert(replace_sql(*values))
726
- end
727
718
 
728
- # MySQL specific syntax for REPLACE (aka UPSERT, or update if exists,
729
- # insert if it doesn't).
730
- def replace_sql(*values)
731
- clone(:replace=>true).insert_sql(*values)
732
- end
733
-
734
- # Replace multiple rows in a single query.
735
- def multi_replace(*values)
736
- clone(:replace=>true).multi_insert(*values)
737
- end
738
-
739
719
  # MySQL can emulate DISTINCT ON with its non-standard GROUP BY implementation,
740
720
  # though the rows returned cannot be made deterministic through ordering.
741
721
  def supports_distinct_on?
@@ -832,11 +812,6 @@ module Sequel
832
812
  sql << IGNORE if opts[:update_ignore]
833
813
  end
834
814
 
835
- # If this is an replace instead of an insert, use replace instead
836
- def insert_insert_sql(sql)
837
- sql << (@opts[:replace] ? REPLACE : INSERT)
838
- end
839
-
840
815
  # MySQL supports INSERT ... ON DUPLICATE KEY UPDATE
841
816
  def insert_on_duplicate_key_update_sql(sql)
842
817
  if update_cols = opts[:on_duplicate_key_update]
@@ -636,8 +636,10 @@ module Sequel
636
636
  case constraint[:type]
637
637
  when :exclude
638
638
  elements = constraint[:elements].map{|c, op| "#{literal(c)} WITH #{op}"}.join(', ')
639
- "#{"CONSTRAINT #{quote_identifier(constraint[:name])} " if constraint[:name]}EXCLUDE USING #{constraint[:using]||'gist'} (#{elements})#{" WHERE #{filter_expr(constraint[:where])}" if constraint[:where]}"
640
- when :foreign_key
639
+ sql = "#{"CONSTRAINT #{quote_identifier(constraint[:name])} " if constraint[:name]}EXCLUDE USING #{constraint[:using]||'gist'} (#{elements})#{" WHERE #{filter_expr(constraint[:where])}" if constraint[:where]}"
640
+ constraint_deferrable_sql_append(sql, constraint[:deferrable])
641
+ sql
642
+ when :foreign_key, :check
641
643
  sql = super
642
644
  if constraint[:not_valid]
643
645
  sql << " NOT VALID"
@@ -768,6 +770,14 @@ module Sequel
768
770
  "CREATE #{temp_or_unlogged_sql}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{options[:temp] ? quote_identifier(name) : quote_schema_table(name)}"
769
771
  end
770
772
 
773
+ def create_table_sql(name, generator, options)
774
+ sql = super
775
+ if inherits = options[:inherits]
776
+ sql << " INHERITS (#{Array(inherits).map{|t| quote_schema_table(t)}.join(', ')})"
777
+ end
778
+ sql
779
+ end
780
+
771
781
  # Use a PostgreSQL-specific create table generator
772
782
  def create_table_generator_class
773
783
  Postgres::CreateTableGenerator
@@ -797,7 +807,8 @@ module Sequel
797
807
 
798
808
  # Support :if_exists, :cascade, and :concurrently options.
799
809
  def drop_index_sql(table, op)
800
- "DROP INDEX#{' CONCURRENTLY' if op[:concurrently]}#{' IF EXISTS' if op[:if_exists]} #{quote_identifier(op[:name] || default_index_name(table, op[:columns]))}#{' CASCADE' if op[:cascade]}"
810
+ sch, _ = schema_and_table(table)
811
+ "DROP INDEX#{' CONCURRENTLY' if op[:concurrently]}#{' IF EXISTS' if op[:if_exists]} #{"#{quote_identifier(sch)}." if sch}#{quote_identifier(op[:name] || default_index_name(table, op[:columns]))}#{' CASCADE' if op[:cascade]}"
801
812
  end
802
813
 
803
814
  # SQL for dropping a procedural language from the database.