sequel 4.0.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +32 -0
- data/doc/active_record.rdoc +2 -2
- data/doc/cheat_sheet.rdoc +0 -5
- data/doc/opening_databases.rdoc +3 -2
- data/doc/prepared_statements.rdoc +6 -0
- data/doc/release_notes/4.1.0.txt +85 -0
- data/doc/schema_modification.rdoc +9 -2
- data/lib/sequel/adapters/jdbc.rb +5 -0
- data/lib/sequel/adapters/mysql2.rb +24 -3
- data/lib/sequel/adapters/odbc.rb +6 -4
- data/lib/sequel/adapters/postgres.rb +25 -0
- data/lib/sequel/adapters/shared/mysql.rb +4 -29
- data/lib/sequel/adapters/shared/postgres.rb +14 -3
- data/lib/sequel/adapters/shared/sqlite.rb +4 -0
- data/lib/sequel/adapters/utils/replace.rb +36 -0
- data/lib/sequel/database/query.rb +1 -0
- data/lib/sequel/database/schema_generator.rb +12 -5
- data/lib/sequel/database/schema_methods.rb +2 -0
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/extensions/pg_json_ops.rb +0 -6
- data/lib/sequel/model/associations.rb +1 -1
- data/lib/sequel/plugins/instance_filters.rb +11 -1
- data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -2
- data/lib/sequel/plugins/prepared_statements.rb +38 -9
- data/lib/sequel/plugins/update_primary_key.rb +10 -0
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +1 -22
- data/spec/adapters/postgres_spec.rb +79 -2
- data/spec/core/database_spec.rb +10 -0
- data/spec/core/dataset_spec.rb +8 -3
- data/spec/core/expression_filters_spec.rb +1 -1
- data/spec/core/schema_spec.rb +17 -2
- data/spec/extensions/caching_spec.rb +2 -2
- data/spec/extensions/hook_class_methods_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +22 -0
- data/spec/extensions/migration_spec.rb +5 -5
- data/spec/extensions/nested_attributes_spec.rb +4 -4
- data/spec/extensions/prepared_statements_spec.rb +37 -26
- data/spec/extensions/update_primary_key_spec.rb +13 -0
- data/spec/integration/dataset_test.rb +36 -0
- data/spec/model/associations_spec.rb +20 -2
- data/spec/model/hooks_spec.rb +1 -7
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a449facae4b3dcc14c19ce0f524ca2025db4c74e
|
4
|
+
data.tar.gz: 19e4bbb80143055d03da8134f6308363ff8e2406
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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)
|
data/doc/active_record.rdoc
CHANGED
@@ -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
|
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
|
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))
|
data/doc/opening_databases.rdoc
CHANGED
@@ -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 '
|
325
|
-
:
|
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
|
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 ::
|
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.
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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.
|
data/lib/sequel/adapters/odbc.rb
CHANGED
@@ -11,7 +11,10 @@ module Sequel
|
|
11
11
|
|
12
12
|
def connect(server)
|
13
13
|
opts = server_opts(server)
|
14
|
-
if opts.include?
|
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
|
-
|
24
|
-
conn = db.drvconnect(drv)
|
26
|
+
::ODBC::Database.new.drvconnect(drv)
|
25
27
|
else
|
26
|
-
|
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
|
-
|
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
|
-
|
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.
|