sequel 3.21.0 → 3.29.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 (200) hide show
  1. data/CHANGELOG +413 -3
  2. data/README.rdoc +20 -6
  3. data/Rakefile +23 -16
  4. data/bin/sequel +1 -5
  5. data/doc/association_basics.rdoc +210 -43
  6. data/doc/dataset_basics.rdoc +4 -4
  7. data/doc/mass_assignment.rdoc +54 -0
  8. data/doc/migration.rdoc +15 -538
  9. data/doc/model_hooks.rdoc +72 -27
  10. data/doc/opening_databases.rdoc +86 -50
  11. data/doc/prepared_statements.rdoc +40 -13
  12. data/doc/reflection.rdoc +8 -2
  13. data/doc/release_notes/3.22.0.txt +39 -0
  14. data/doc/release_notes/3.23.0.txt +172 -0
  15. data/doc/release_notes/3.24.0.txt +420 -0
  16. data/doc/release_notes/3.25.0.txt +88 -0
  17. data/doc/release_notes/3.26.0.txt +88 -0
  18. data/doc/release_notes/3.27.0.txt +82 -0
  19. data/doc/release_notes/3.28.0.txt +304 -0
  20. data/doc/release_notes/3.29.0.txt +459 -0
  21. data/doc/schema_modification.rdoc +547 -0
  22. data/doc/sharding.rdoc +7 -1
  23. data/doc/testing.rdoc +115 -0
  24. data/doc/transactions.rdoc +137 -0
  25. data/doc/virtual_rows.rdoc +2 -2
  26. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  27. data/lib/sequel/adapters/ado.rb +40 -18
  28. data/lib/sequel/adapters/amalgalite.rb +15 -7
  29. data/lib/sequel/adapters/db2.rb +175 -86
  30. data/lib/sequel/adapters/dbi.rb +15 -15
  31. data/lib/sequel/adapters/do/mysql.rb +0 -5
  32. data/lib/sequel/adapters/do/postgres.rb +0 -5
  33. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  34. data/lib/sequel/adapters/do.rb +17 -36
  35. data/lib/sequel/adapters/firebird.rb +27 -208
  36. data/lib/sequel/adapters/ibmdb.rb +448 -0
  37. data/lib/sequel/adapters/informix.rb +6 -23
  38. data/lib/sequel/adapters/jdbc/as400.rb +5 -31
  39. data/lib/sequel/adapters/jdbc/db2.rb +44 -0
  40. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  41. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  42. data/lib/sequel/adapters/jdbc/h2.rb +26 -17
  43. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  44. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  45. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  46. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  47. data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
  48. data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
  49. data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
  50. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  51. data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
  52. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  53. data/lib/sequel/adapters/jdbc.rb +107 -38
  54. data/lib/sequel/adapters/mock.rb +315 -0
  55. data/lib/sequel/adapters/mysql.rb +78 -182
  56. data/lib/sequel/adapters/mysql2.rb +24 -23
  57. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  58. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  59. data/lib/sequel/adapters/odbc.rb +28 -9
  60. data/lib/sequel/adapters/openbase.rb +2 -4
  61. data/lib/sequel/adapters/oracle.rb +349 -51
  62. data/lib/sequel/adapters/postgres.rb +169 -21
  63. data/lib/sequel/adapters/shared/access.rb +21 -6
  64. data/lib/sequel/adapters/shared/db2.rb +288 -0
  65. data/lib/sequel/adapters/shared/firebird.rb +214 -0
  66. data/lib/sequel/adapters/shared/informix.rb +45 -0
  67. data/lib/sequel/adapters/shared/mssql.rb +108 -65
  68. data/lib/sequel/adapters/shared/mysql.rb +56 -13
  69. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  70. data/lib/sequel/adapters/shared/oracle.rb +185 -34
  71. data/lib/sequel/adapters/shared/postgres.rb +107 -58
  72. data/lib/sequel/adapters/shared/progress.rb +0 -6
  73. data/lib/sequel/adapters/shared/sqlite.rb +168 -41
  74. data/lib/sequel/adapters/sqlite.rb +27 -18
  75. data/lib/sequel/adapters/swift/mysql.rb +9 -5
  76. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  77. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  78. data/lib/sequel/adapters/swift.rb +5 -5
  79. data/lib/sequel/adapters/tinytds.rb +152 -17
  80. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
  81. data/lib/sequel/ast_transformer.rb +190 -0
  82. data/lib/sequel/connection_pool/threaded.rb +3 -2
  83. data/lib/sequel/connection_pool.rb +1 -1
  84. data/lib/sequel/core.rb +46 -5
  85. data/lib/sequel/database/connecting.rb +5 -6
  86. data/lib/sequel/database/dataset.rb +4 -4
  87. data/lib/sequel/database/dataset_defaults.rb +59 -1
  88. data/lib/sequel/database/logging.rb +1 -1
  89. data/lib/sequel/database/misc.rb +100 -19
  90. data/lib/sequel/database/query.rb +153 -58
  91. data/lib/sequel/database/schema_generator.rb +8 -5
  92. data/lib/sequel/database/schema_methods.rb +59 -29
  93. data/lib/sequel/dataset/actions.rb +194 -57
  94. data/lib/sequel/dataset/features.rb +81 -8
  95. data/lib/sequel/dataset/graph.rb +8 -7
  96. data/lib/sequel/dataset/misc.rb +50 -23
  97. data/lib/sequel/dataset/mutation.rb +5 -6
  98. data/lib/sequel/dataset/prepared_statements.rb +32 -15
  99. data/lib/sequel/dataset/query.rb +223 -42
  100. data/lib/sequel/dataset/sql.rb +58 -61
  101. data/lib/sequel/dataset.rb +8 -0
  102. data/lib/sequel/exceptions.rb +4 -0
  103. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  104. data/lib/sequel/extensions/migration.rb +6 -4
  105. data/lib/sequel/extensions/named_timezones.rb +5 -0
  106. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  107. data/lib/sequel/extensions/to_dot.rb +95 -83
  108. data/lib/sequel/model/associations.rb +997 -331
  109. data/lib/sequel/model/base.rb +386 -129
  110. data/lib/sequel/model/errors.rb +1 -1
  111. data/lib/sequel/model/exceptions.rb +5 -1
  112. data/lib/sequel/model.rb +15 -8
  113. data/lib/sequel/plugins/association_pks.rb +22 -4
  114. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  115. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  116. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  117. data/lib/sequel/plugins/force_encoding.rb +6 -6
  118. data/lib/sequel/plugins/identity_map.rb +114 -7
  119. data/lib/sequel/plugins/many_through_many.rb +65 -7
  120. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  121. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  122. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  123. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  124. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  125. data/lib/sequel/plugins/serialization.rb +6 -1
  126. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  127. data/lib/sequel/plugins/sharding.rb +12 -25
  128. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  129. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  130. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  131. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  132. data/lib/sequel/sql.rb +107 -51
  133. data/lib/sequel/timezones.rb +44 -35
  134. data/lib/sequel/version.rb +1 -1
  135. data/spec/adapters/db2_spec.rb +146 -0
  136. data/spec/adapters/mssql_spec.rb +65 -29
  137. data/spec/adapters/mysql_spec.rb +122 -123
  138. data/spec/adapters/oracle_spec.rb +48 -76
  139. data/spec/adapters/postgres_spec.rb +213 -61
  140. data/spec/adapters/spec_helper.rb +6 -5
  141. data/spec/adapters/sqlite_spec.rb +35 -21
  142. data/spec/core/connection_pool_spec.rb +71 -92
  143. data/spec/core/core_sql_spec.rb +20 -31
  144. data/spec/core/database_spec.rb +729 -508
  145. data/spec/core/dataset_spec.rb +980 -1044
  146. data/spec/core/expression_filters_spec.rb +159 -42
  147. data/spec/core/mock_adapter_spec.rb +378 -0
  148. data/spec/core/object_graph_spec.rb +48 -114
  149. data/spec/core/schema_generator_spec.rb +3 -3
  150. data/spec/core/schema_spec.rb +298 -38
  151. data/spec/core/spec_helper.rb +6 -48
  152. data/spec/extensions/association_pks_spec.rb +38 -0
  153. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  154. data/spec/extensions/columns_introspection_spec.rb +91 -0
  155. data/spec/extensions/dataset_associations_spec.rb +199 -0
  156. data/spec/extensions/defaults_setter_spec.rb +64 -0
  157. data/spec/extensions/identity_map_spec.rb +162 -0
  158. data/spec/extensions/instance_hooks_spec.rb +71 -0
  159. data/spec/extensions/many_through_many_spec.rb +195 -20
  160. data/spec/extensions/migration_spec.rb +17 -17
  161. data/spec/extensions/named_timezones_spec.rb +22 -2
  162. data/spec/extensions/nested_attributes_spec.rb +4 -0
  163. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  164. data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
  165. data/spec/extensions/prepared_statements_spec.rb +72 -0
  166. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  167. data/spec/extensions/schema_dumper_spec.rb +2 -2
  168. data/spec/extensions/schema_spec.rb +13 -21
  169. data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
  170. data/spec/extensions/serialization_spec.rb +5 -8
  171. data/spec/extensions/single_table_inheritance_spec.rb +11 -0
  172. data/spec/extensions/spec_helper.rb +7 -1
  173. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  174. data/spec/extensions/to_dot_spec.rb +3 -5
  175. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  176. data/spec/extensions/xml_serializer_spec.rb +16 -4
  177. data/spec/integration/associations_test.rb +522 -21
  178. data/spec/integration/database_test.rb +4 -2
  179. data/spec/integration/dataset_test.rb +375 -62
  180. data/spec/integration/eager_loader_test.rb +19 -21
  181. data/spec/integration/model_test.rb +80 -1
  182. data/spec/integration/plugin_test.rb +304 -116
  183. data/spec/integration/prepared_statement_test.rb +200 -120
  184. data/spec/integration/schema_test.rb +161 -30
  185. data/spec/integration/spec_helper.rb +39 -30
  186. data/spec/integration/timezone_test.rb +38 -12
  187. data/spec/integration/transaction_test.rb +172 -5
  188. data/spec/integration/type_test.rb +17 -3
  189. data/spec/model/association_reflection_spec.rb +174 -7
  190. data/spec/model/associations_spec.rb +849 -661
  191. data/spec/model/base_spec.rb +255 -95
  192. data/spec/model/dataset_methods_spec.rb +7 -27
  193. data/spec/model/eager_loading_spec.rb +640 -676
  194. data/spec/model/hooks_spec.rb +309 -67
  195. data/spec/model/model_spec.rb +207 -167
  196. data/spec/model/plugins_spec.rb +24 -13
  197. data/spec/model/record_spec.rb +321 -218
  198. data/spec/model/spec_helper.rb +13 -71
  199. data/spec/model/validations_spec.rb +11 -0
  200. metadata +95 -38
@@ -241,16 +241,6 @@ module Sequel
241
241
  self << drop_language_sql(name, opts)
242
242
  end
243
243
 
244
- # Remove the cached entries for primary keys and sequences when dropping a table.
245
- def drop_table(*names)
246
- names.each do |name|
247
- name = quote_schema_table(name)
248
- @primary_keys.delete(name)
249
- @primary_key_sequences.delete(name)
250
- end
251
- super
252
- end
253
-
254
244
  # Drops a trigger from the database. Arguments:
255
245
  # * table : table from which to drop the trigger
256
246
  # * name : name of the trigger to drop
@@ -294,6 +284,16 @@ module Sequel
294
284
  dataset.from(:pg_class).join(:pg_locks, :relation=>:relfilenode).select(:pg_class__relname, Sequel::SQL::ColumnAll.new(:pg_locks))
295
285
  end
296
286
 
287
+ # Notifies the given channel. See the PostgreSQL NOTIFY documentation. Options:
288
+ #
289
+ # :payload :: The payload string to use for the NOTIFY statement. Only supported
290
+ # in PostgreSQL 9.0+.
291
+ # :server :: The server to which to send the NOTIFY statement, if the sharding support
292
+ # is being used.
293
+ def notify(channel, opts={})
294
+ execute_ddl("NOTIFY #{channel}#{", #{literal(opts[:payload].to_s)}" if opts[:payload]}", opts)
295
+ end
296
+
297
297
  # Return primary key for the given table.
298
298
  def primary_key(table, opts={})
299
299
  quoted_table = quote_schema_table(table)
@@ -358,6 +358,11 @@ module Sequel
358
358
  @supports_prepared_transactions = self['SHOW max_prepared_transactions'].get.to_i > 0
359
359
  end
360
360
 
361
+ # PostgreSQL supports CREATE TABLE IF NOT EXISTS on 9.1+
362
+ def supports_create_table_if_not_exists?
363
+ server_version >= 90100
364
+ end
365
+
361
366
  # PostgreSQL supports savepoints
362
367
  def supports_savepoints?
363
368
  true
@@ -368,30 +373,24 @@ module Sequel
368
373
  true
369
374
  end
370
375
 
371
- # Whether the given table exists in the database
376
+ # Array of symbols specifying table names in the current database.
377
+ # The dataset used is yielded to the block if one is provided,
378
+ # otherwise, an array of symbols of table names is returned.
372
379
  #
373
380
  # Options:
374
381
  # * :schema - The schema to search (default_schema by default)
375
382
  # * :server - The server to use
376
- def table_exists?(table, opts={})
377
- im = input_identifier_meth
378
- schema, table = schema_and_table(table)
379
- opts[:schema] ||= schema
380
- tables(opts){|ds| !ds.first(:relname=>im.call(table)).nil?}
383
+ def tables(opts={}, &block)
384
+ pg_class_relname('r', opts, &block)
381
385
  end
382
-
383
- # Array of symbols specifying table names in the current database.
384
- # The dataset used is yielded to the block if one is provided,
385
- # otherwise, an array of symbols of table names is returned.
386
+
387
+ # Array of symbols specifying view names in the current database.
386
388
  #
387
389
  # Options:
388
390
  # * :schema - The schema to search (default_schema by default)
389
391
  # * :server - The server to use
390
- def tables(opts={})
391
- ds = metadata_dataset.from(:pg_class).filter(:relkind=>'r').select(:relname).exclude(SQL::StringExpression.like(:relname, SYSTEM_TABLE_REGEXP)).server(opts[:server]).join(:pg_namespace, :oid=>:relnamespace)
392
- ds = filter_schema(ds, opts)
393
- m = output_identifier_meth
394
- block_given? ? yield(ds) : ds.map{|r| m.call(r[:relname])}
392
+ def views(opts={})
393
+ pg_class_relname('v', opts)
395
394
  end
396
395
 
397
396
  private
@@ -399,8 +398,8 @@ module Sequel
399
398
  # If the :prepare option is given and we aren't in a savepoint,
400
399
  # prepare the transaction for a two-phase commit.
401
400
  def commit_transaction(conn, opts={})
402
- if opts[:prepare] && Thread.current[:sequel_transaction_depth] <= 1
403
- log_connection_execute(conn, "PREPARE TRANSACTION #{literal(opts[:prepare])}")
401
+ if (s = opts[:prepare]) && @transactions[conn][:savepoint_level] <= 1
402
+ log_connection_execute(conn, "PREPARE TRANSACTION #{literal(s)}")
404
403
  else
405
404
  super
406
405
  end
@@ -454,11 +453,6 @@ module Sequel
454
453
  "DROP LANGUAGE#{' IF EXISTS' if opts[:if_exists]} #{name}#{' CASCADE' if opts[:cascade]}"
455
454
  end
456
455
 
457
- # Always CASCADE the table drop
458
- def drop_table_sql(name)
459
- "DROP TABLE #{quote_schema_table(name)} CASCADE"
460
- end
461
-
462
456
  # SQL for dropping a trigger from the database.
463
457
  def drop_trigger_sql(table, name, opts={})
464
458
  "DROP TRIGGER#{' IF EXISTS' if opts[:if_exists]} #{name} ON #{quote_schema_table(table)}#{' CASCADE' if opts[:cascade]}"
@@ -540,12 +534,29 @@ module Sequel
540
534
  conn.execute(sql)
541
535
  end
542
536
 
537
+ # Backbone of the tables and views support.
538
+ def pg_class_relname(type, opts)
539
+ ds = metadata_dataset.from(:pg_class).filter(:relkind=>type).select(:relname).exclude(SQL::StringExpression.like(:relname, SYSTEM_TABLE_REGEXP)).server(opts[:server]).join(:pg_namespace, :oid=>:relnamespace)
540
+ ds = filter_schema(ds, opts)
541
+ m = output_identifier_meth
542
+ block_given? ? yield(ds) : ds.map{|r| m.call(r[:relname])}
543
+ end
544
+
543
545
  # Use a dollar sign instead of question mark for the argument
544
546
  # placeholder.
545
547
  def prepared_arg_placeholder
546
548
  PREPARED_ARG_PLACEHOLDER
547
549
  end
548
550
 
551
+ # Remove the cached entries for primary keys and sequences when a table is
552
+ # changed.
553
+ def remove_cached_schema(table)
554
+ tab = quote_schema_table(table)
555
+ @primary_keys.delete(tab)
556
+ @primary_key_sequences.delete(tab)
557
+ super
558
+ end
559
+
549
560
  # SQL DDL statement for renaming a table. PostgreSQL doesn't allow you to change a table's schema in
550
561
  # a rename table operation, so speciying a new schema in new_name will not have an effect.
551
562
  def rename_table_sql(name, new_name)
@@ -560,8 +571,8 @@ module Sequel
560
571
 
561
572
  # The dataset used for parsing table schemas, using the pg_* system catalogs.
562
573
  def schema_parse_table(table_name, opts)
563
- m = output_identifier_meth
564
- m2 = input_identifier_meth
574
+ m = output_identifier_meth(opts[:dataset])
575
+ m2 = input_identifier_meth(opts[:dataset])
565
576
  ds = metadata_dataset.select(:pg_attribute__attname___name,
566
577
  SQL::Function.new(:format_type, :pg_type__oid, :pg_attribute__atttypmod).as(:db_type),
567
578
  SQL::Function.new(:pg_get_expr, :pg_attrdef__adbin, :pg_class__oid).as(:default),
@@ -628,10 +639,14 @@ module Sequel
628
639
  BOOL_TRUE = 'true'.freeze
629
640
  COMMA_SEPARATOR = ', '.freeze
630
641
  DELETE_CLAUSE_METHODS = Dataset.clause_methods(:delete, %w'from using where')
642
+ DELETE_CLAUSE_METHODS_91 = Dataset.clause_methods(:delete, %w'with from using where returning')
631
643
  EXCLUSIVE = 'EXCLUSIVE'.freeze
632
644
  EXPLAIN = 'EXPLAIN '.freeze
633
645
  EXPLAIN_ANALYZE = 'EXPLAIN ANALYZE '.freeze
634
646
  FOR_SHARE = ' FOR SHARE'.freeze
647
+ INSERT_CLAUSE_METHODS = Dataset.clause_methods(:insert, %w'into columns values')
648
+ INSERT_CLAUSE_METHODS_82 = Dataset.clause_methods(:insert, %w'into columns values returning')
649
+ INSERT_CLAUSE_METHODS_91 = Dataset.clause_methods(:insert, %w'with into columns values returning')
635
650
  LOCK = 'LOCK TABLE %s IN %s MODE'.freeze
636
651
  NULL = LiteralString.new('NULL').freeze
637
652
  PG_TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S".freeze
@@ -645,17 +660,23 @@ module Sequel
645
660
  SHARE_UPDATE_EXCLUSIVE = 'SHARE UPDATE EXCLUSIVE'.freeze
646
661
  SQL_WITH_RECURSIVE = "WITH RECURSIVE ".freeze
647
662
  UPDATE_CLAUSE_METHODS = Dataset.clause_methods(:update, %w'table set from where')
663
+ UPDATE_CLAUSE_METHODS_91 = Dataset.clause_methods(:update, %w'with table set from where returning')
648
664
 
649
665
  # Shared methods for prepared statements when used with PostgreSQL databases.
650
666
  module PreparedStatementMethods
651
667
  # Override insert action to use RETURNING if the server supports it.
668
+ def run(&block)
669
+ if @prepared_type == :insert && supports_insert_select?
670
+ fetch_rows(prepared_sql){|r| return r.values.first}
671
+ else
672
+ super
673
+ end
674
+ end
675
+
652
676
  def prepared_sql
653
677
  return @prepared_sql if @prepared_sql
678
+ @opts[:returning] = insert_pk if @prepared_type == :insert && supports_insert_select?
654
679
  super
655
- if @prepared_type == :insert and !@opts[:disable_insert_returning] and server_version >= 80200
656
- @prepared_sql = insert_returning_pk_sql(*@prepared_modify_values)
657
- meta_def(:insert_returning_pk_sql){|*args| prepared_sql}
658
- end
659
680
  @prepared_sql
660
681
  end
661
682
  end
@@ -680,7 +701,7 @@ module Sequel
680
701
  def complex_expression_sql(op, args)
681
702
  case op
682
703
  when :^
683
- "(#{literal(args.at(0))} # #{literal(args.at(1))})"
704
+ "(#{args.collect{|a| literal(a)}.join(" # ")})"
684
705
  else
685
706
  super
686
707
  end
@@ -709,25 +730,22 @@ module Sequel
709
730
  end
710
731
 
711
732
  # Insert given values into the database.
712
- def insert(*values)
713
- if @opts[:sql]
714
- execute_insert(insert_sql(*values))
715
- elsif @opts[:disable_insert_returning] || server_version < 80200
716
- execute_insert(insert_sql(*values), :table=>opts[:from].first, :values=>values.size == 1 ? values.first : values)
733
+ def insert(*values, &block)
734
+ if @opts[:returning]
735
+ super
736
+ elsif !@opts[:sql] && supports_insert_select?
737
+ returning(insert_pk).insert(*values){|r| return r.values.first}
738
+ elsif (f = opts[:from]) && !f.empty?
739
+ execute_insert(insert_sql(*values), :table=>f.first, :values=>values.size == 1 ? values.first : values)
717
740
  else
718
- clone(default_server_opts(:sql=>insert_returning_pk_sql(*values))).single_value
741
+ super
719
742
  end
720
743
  end
721
744
 
722
- # Use the RETURNING clause to return the columns listed in returning.
723
- def insert_returning_sql(returning, *values)
724
- "#{insert_sql(*values)} RETURNING #{column_list(Array(returning))}"
725
- end
726
-
727
745
  # Insert a record returning the record inserted
728
746
  def insert_select(*values)
729
- return if opts[:disable_insert_returning] || server_version < 80200
730
- naked.clone(default_server_opts(:sql=>insert_returning_sql(nil, *values))).single_record
747
+ return unless supports_insert_select?
748
+ returning.insert(*values){|r| return r}
731
749
  end
732
750
 
733
751
  # Locks all tables in the dataset's FROM clause (but not in JOINs) with
@@ -752,6 +770,12 @@ module Sequel
752
770
  [insert_sql(columns, LiteralString.new('VALUES ' + values.map {|r| literal(Array(r))}.join(COMMA_SEPARATOR)))]
753
771
  end
754
772
 
773
+ # PostgreSQL supports using the WITH clause in subqueries if it
774
+ # supports using WITH at all (i.e. on PostgreSQL 8.4+).
775
+ def supports_cte_in_subqueries?
776
+ supports_cte?
777
+ end
778
+
755
779
  # DISTINCT ON is a PostgreSQL extension
756
780
  def supports_distinct_on?
757
781
  true
@@ -762,6 +786,14 @@ module Sequel
762
786
  true
763
787
  end
764
788
 
789
+ def supports_returning?(type)
790
+ if type == :insert
791
+ server_version >= 80200 && !opts[:disable_insert_returning]
792
+ else
793
+ server_version >= 90100
794
+ end
795
+ end
796
+
765
797
  # PostgreSQL supports timezones in literal timestamps
766
798
  def supports_timestamp_timezones?
767
799
  true
@@ -781,7 +813,7 @@ module Sequel
781
813
 
782
814
  # PostgreSQL allows deleting from joined datasets
783
815
  def delete_clause_methods
784
- DELETE_CLAUSE_METHODS
816
+ server_version >= 90100 ? DELETE_CLAUSE_METHODS_91 : DELETE_CLAUSE_METHODS
785
817
  end
786
818
 
787
819
  # Only include the primary table in the main delete clause
@@ -794,12 +826,23 @@ module Sequel
794
826
  join_from_sql(:USING, sql)
795
827
  end
796
828
 
797
- # Use the RETURNING clause to return the primary key of the inserted record, if it exists
798
- def insert_returning_pk_sql(*values)
829
+ # PostgreSQL allows a RETURNING clause.
830
+ def insert_clause_methods
831
+ if server_version >= 90100
832
+ INSERT_CLAUSE_METHODS_91
833
+ elsif server_version >= 80200
834
+ INSERT_CLAUSE_METHODS_82
835
+ else
836
+ INSERT_CLAUSE_METHODS
837
+ end
838
+ end
839
+
840
+ # Return the primary key to use for RETURNING in an INSERT statement
841
+ def insert_pk
799
842
  pk = db.primary_key(opts[:from].first) if opts[:from] && !opts[:from].empty?
800
- insert_returning_sql(pk ? Sequel::SQL::Identifier.new(pk) : NULL, *values)
843
+ pk ? Sequel::SQL::Identifier.new(pk) : NULL
801
844
  end
802
-
845
+
803
846
  # For multiple table support, PostgreSQL requires at least
804
847
  # two from tables, with joins allowed.
805
848
  def join_from_sql(type, sql)
@@ -836,6 +879,12 @@ module Sequel
836
879
  server_version >= 80400 ? SELECT_CLAUSE_METHODS_84 : SELECT_CLAUSE_METHODS
837
880
  end
838
881
 
882
+ # PostgreSQL requires parentheses around compound datasets if they use
883
+ # CTEs, and using them in other places doesn't hurt.
884
+ def compound_dataset_sql(ds)
885
+ "(#{super})"
886
+ end
887
+
839
888
  # Support FOR SHARE locking when using the :share lock style.
840
889
  def select_lock_sql(sql)
841
890
  @opts[:lock] == :share ? (sql << FOR_SHARE) : super
@@ -866,7 +915,7 @@ module Sequel
866
915
 
867
916
  # PostgreSQL splits the main table from the joined tables
868
917
  def update_clause_methods
869
- UPDATE_CLAUSE_METHODS
918
+ server_version >= 90100 ? UPDATE_CLAUSE_METHODS_91 : UPDATE_CLAUSE_METHODS
870
919
  end
871
920
 
872
921
  # Use FROM to specify additional tables in an update query
@@ -6,12 +6,6 @@ module Sequel
6
6
  def database_type
7
7
  :progress
8
8
  end
9
-
10
- def dataset(opts = nil)
11
- ds = super
12
- ds.extend(DatasetMethods)
13
- ds
14
- end
15
9
  end
16
10
 
17
11
  module DatasetMethods