sequel 2.8.0 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +34 -0
- data/COPYING +1 -1
- data/Rakefile +1 -1
- data/bin/sequel +12 -5
- data/doc/advanced_associations.rdoc +17 -3
- data/lib/sequel_core/adapters/informix.rb +1 -1
- data/lib/sequel_core/adapters/postgres.rb +12 -2
- data/lib/sequel_core/adapters/shared/mssql.rb +3 -1
- data/lib/sequel_core/adapters/shared/mysql.rb +14 -0
- data/lib/sequel_core/adapters/shared/oracle.rb +7 -6
- data/lib/sequel_core/adapters/shared/postgres.rb +170 -3
- data/lib/sequel_core/adapters/shared/progress.rb +1 -1
- data/lib/sequel_core/adapters/shared/sqlite.rb +11 -6
- data/lib/sequel_core/adapters/sqlite.rb +8 -0
- data/lib/sequel_core/dataset/sql.rb +23 -19
- data/lib/sequel_core/dataset/unsupported.rb +12 -0
- data/lib/sequel_core/schema/sql.rb +3 -1
- data/lib/sequel_model.rb +1 -1
- data/lib/sequel_model/associations.rb +1 -1
- data/lib/sequel_model/base.rb +2 -1
- data/lib/sequel_model/dataset_methods.rb +1 -1
- data/lib/sequel_model/eager_loading.rb +1 -1
- data/lib/sequel_model/exceptions.rb +7 -0
- data/lib/sequel_model/record.rb +22 -13
- data/lib/sequel_model/validations.rb +8 -4
- data/spec/adapters/mysql_spec.rb +17 -0
- data/spec/adapters/postgres_spec.rb +69 -0
- data/spec/adapters/sqlite_spec.rb +38 -3
- data/spec/integration/dataset_test.rb +51 -0
- data/spec/integration/schema_test.rb +4 -0
- data/spec/sequel_core/core_ext_spec.rb +2 -2
- data/spec/sequel_core/dataset_spec.rb +35 -1
- data/spec/sequel_core/schema_spec.rb +7 -0
- data/spec/sequel_model/association_reflection_spec.rb +13 -13
- data/spec/sequel_model/hooks_spec.rb +9 -5
- data/spec/sequel_model/validations_spec.rb +1 -1
- metadata +3 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,37 @@
|
|
1
|
+
=== 2.9.0 (2009-01-12)
|
2
|
+
|
3
|
+
* Add -L option to sequel command line tool to load all .rb files in the given directory (pkondzior, jeremyevans)
|
4
|
+
|
5
|
+
* Fix Dataset#destroy for model datasets that can't handle nested queries (jeremyevans)
|
6
|
+
|
7
|
+
* Improve the error messages in parts of Sequel::Model (jeremyevans, pusewicz)
|
8
|
+
|
9
|
+
* Much better support for Dataset#{union,except,intersect}, allowing chaining and respecting order (jeremyevans)
|
10
|
+
|
11
|
+
* Default to logging only WARNING level messages when connecting to PostgreSQL (jeremyevans)
|
12
|
+
|
13
|
+
* Fix add_foreign_key for MySQL (jeremyevans, aphyr)
|
14
|
+
|
15
|
+
* Correctly literalize BigDecimal NaN and (+-)Infinity values (#256) (jeremyevans)
|
16
|
+
|
17
|
+
* Make Sequel raise an Error if you attempt to subclass Sequel::Model before setting up a database connection (jeremyevans)
|
18
|
+
|
19
|
+
* Add Sequel::BeforeHookFailed exception to be raised when a record fails because a before hook fails (bougyman)
|
20
|
+
|
21
|
+
* Add Sequel::ValidationFailed exception to be raised when a record fails because a validation fails (bougyman)
|
22
|
+
|
23
|
+
* Make Database#schema raise an error if given a table that doesn't exist (jeremyevans) (#255)
|
24
|
+
|
25
|
+
* Make Model#inspect call Model#inspect_values private method for easier overloading (bougyman)
|
26
|
+
|
27
|
+
* Add methods to create and drop functions, triggers, and procedural languages on PostgreSQL (jeremyevans)
|
28
|
+
|
29
|
+
* Fix Dataset#count when using UNION, EXCEPT, or INTERSECT (jeremyevans)
|
30
|
+
|
31
|
+
* Make SQLite keep table's primary key information when dropping columns (jmhodges)
|
32
|
+
|
33
|
+
* Support dropping indicies on SQLite (jmhodges)
|
34
|
+
|
1
35
|
=== 2.8.0 (2008-12-05)
|
2
36
|
|
3
37
|
* Support drop column operations inside a transaction on sqlite (jeremyevans)
|
data/COPYING
CHANGED
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ require "fileutils"
|
|
12
12
|
include FileUtils
|
13
13
|
|
14
14
|
NAME = 'sequel'
|
15
|
-
VERS = '2.
|
15
|
+
VERS = '2.9.0'
|
16
16
|
CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage", "www/public/*.html"]
|
17
17
|
RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
|
18
18
|
'Sequel: The Database Toolkit for Ruby', '--main', 'README']
|
data/bin/sequel
CHANGED
@@ -10,6 +10,7 @@ env = nil
|
|
10
10
|
logfile = nil
|
11
11
|
migrate_dir = nil
|
12
12
|
migrate_ver = nil
|
13
|
+
load_dir = nil
|
13
14
|
|
14
15
|
opts = OptionParser.new do |opts|
|
15
16
|
opts.banner = "Sequel: The Database Toolkit for Ruby"
|
@@ -29,10 +30,6 @@ opts = OptionParser.new do |opts|
|
|
29
30
|
exit
|
30
31
|
end
|
31
32
|
|
32
|
-
opts.on("-l", "--log logfile", "log SQL statements to log file") do |v|
|
33
|
-
logfile = v
|
34
|
-
end
|
35
|
-
|
36
33
|
opts.on("-e", "--env ENV", "use environment config for database") do |v|
|
37
34
|
env = v
|
38
35
|
end
|
@@ -41,6 +38,14 @@ opts = OptionParser.new do |opts|
|
|
41
38
|
echo = true
|
42
39
|
end
|
43
40
|
|
41
|
+
opts.on("-l", "--log logfile", "log SQL statements to log file") do |v|
|
42
|
+
logfile = v
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on("-L", "--load-dir DIR", "loads all *.rb from specifed directory") do |v|
|
46
|
+
load_dir = v
|
47
|
+
end
|
48
|
+
|
44
49
|
opts.on("-m", "--migrate-directory DIR", "run the migrations in directory") do |v|
|
45
50
|
migrate_dir = v
|
46
51
|
end
|
@@ -48,7 +53,7 @@ opts = OptionParser.new do |opts|
|
|
48
53
|
opts.on("-M", "--migrate-version VER", "migrate the database to version given") do |v|
|
49
54
|
migrate_ver = Integer(v)
|
50
55
|
end
|
51
|
-
|
56
|
+
|
52
57
|
opts.on_tail("-v", "--version", "Show version") do
|
53
58
|
class << Gem; attr_accessor :loaded_specs; end
|
54
59
|
begin
|
@@ -101,6 +106,8 @@ rescue => e
|
|
101
106
|
exit 1
|
102
107
|
end
|
103
108
|
|
109
|
+
Dir["#{load_dir}/**/*.rb"].each{|f| load(f)} if load_dir
|
110
|
+
|
104
111
|
require 'irb'
|
105
112
|
puts "Your database is stored in DB..."
|
106
113
|
IRB.start
|
@@ -229,7 +229,7 @@ Sequel::Model:
|
|
229
229
|
@author.books
|
230
230
|
|
231
231
|
If you use an association other than belongs_to in the associated model, things
|
232
|
-
are a bit more involved:
|
232
|
+
are a bit more involved (has_many :through a has_many association):
|
233
233
|
|
234
234
|
ActiveRecord:
|
235
235
|
|
@@ -317,8 +317,18 @@ firm.invoices.first.client doesn't do another query to get the firm/client.
|
|
317
317
|
|
318
318
|
===Polymorphic Associations
|
319
319
|
|
320
|
-
Polymorphic associations are really a design flaw
|
321
|
-
|
320
|
+
Polymorphic associations are really a design flaw. The only advantage
|
321
|
+
polymorphic associations offer is that they require fewer join tables.
|
322
|
+
|
323
|
+
Proof by Reductio ad absurdum: If fewer join tables are preferable, then surely
|
324
|
+
fewer tables and columns are preferrable, so you might as well store all of
|
325
|
+
your data in a single column in a single table if you think polymorphic
|
326
|
+
associations are a good idea.
|
327
|
+
|
328
|
+
Compelling Argument: Polymorphic associations are more complex than normal
|
329
|
+
associations, and they break referential integrity, so the only reason you
|
330
|
+
should use them is if you are already stuck with an existing design that
|
331
|
+
uses them. You should never use them in new code.
|
322
332
|
|
323
333
|
ActiveRecord:
|
324
334
|
|
@@ -426,6 +436,10 @@ powerful.
|
|
426
436
|
|
427
437
|
===many_to_one/one_to_many not referencing primary key
|
428
438
|
|
439
|
+
This can now be handled easily in Sequel using the :primary_key association
|
440
|
+
option. However, this example shows how the association was possible before
|
441
|
+
the introduction of that option.
|
442
|
+
|
429
443
|
Let's say you have two tables, invoices and clients, where each client is
|
430
444
|
associated with many invoices. However, instead of using the client's primary
|
431
445
|
key, the invoice is associated to the client by name (this is bad database
|
@@ -37,7 +37,7 @@ module Sequel
|
|
37
37
|
class Dataset < Sequel::Dataset
|
38
38
|
include UnsupportedIntersectExcept
|
39
39
|
|
40
|
-
SELECT_CLAUSE_ORDER = %w'limit distinct columns from join where having group
|
40
|
+
SELECT_CLAUSE_ORDER = %w'limit distinct columns from join where having group compounds order'.freeze
|
41
41
|
|
42
42
|
def literal(v)
|
43
43
|
case v
|
@@ -79,8 +79,6 @@ rescue LoadError => e
|
|
79
79
|
end
|
80
80
|
|
81
81
|
module Sequel
|
82
|
-
# Top level module for holding all PostgreSQL-related modules and classes
|
83
|
-
# for Sequel.
|
84
82
|
module Postgres
|
85
83
|
CONVERTED_EXCEPTIONS << PGError
|
86
84
|
|
@@ -105,12 +103,19 @@ module Sequel
|
|
105
103
|
}
|
106
104
|
|
107
105
|
@use_iso_date_format = true
|
106
|
+
@client_min_messages = :warning
|
108
107
|
|
109
108
|
# As an optimization, Sequel sets the date style to ISO, so that PostgreSQL provides
|
110
109
|
# the date in a known format that Sequel can parse faster. This can be turned off
|
111
110
|
# if you require a date style other than ISO.
|
112
111
|
metaattr_accessor :use_iso_date_format
|
113
112
|
|
113
|
+
# By default, Sequel sets the minimum level of log messages sent to the client
|
114
|
+
# to WARNING, where PostgreSQL uses a default of NOTICE. This is to avoid a lot
|
115
|
+
# of mostly useless messages when running migrations, such as a couple of lines
|
116
|
+
# for every serial primary key field.
|
117
|
+
metaattr_accessor :client_min_messages
|
118
|
+
|
114
119
|
# PGconn subclass for connection specific methods used with the
|
115
120
|
# pg, postgres, or postgres-pr driver.
|
116
121
|
class Adapter < ::PGconn
|
@@ -127,6 +132,11 @@ module Sequel
|
|
127
132
|
@db.log_info(sql)
|
128
133
|
execute(sql)
|
129
134
|
end
|
135
|
+
if cmm = Postgres.client_min_messages
|
136
|
+
sql = "SET client_min_messages = '#{cmm.to_s.upcase}'"
|
137
|
+
@db.log_info(sql)
|
138
|
+
execute(sql)
|
139
|
+
end
|
130
140
|
end
|
131
141
|
|
132
142
|
# Execute the given SQL with this connection. If a block is given,
|
@@ -37,7 +37,7 @@ module Sequel
|
|
37
37
|
module DatasetMethods
|
38
38
|
include Dataset::UnsupportedIntersectExcept
|
39
39
|
|
40
|
-
SELECT_CLAUSE_ORDER = %w'limit distinct columns from with join where group order having
|
40
|
+
SELECT_CLAUSE_ORDER = %w'limit distinct columns from with join where group order having compounds'.freeze
|
41
41
|
|
42
42
|
def complex_expression_sql(op, args)
|
43
43
|
case op
|
@@ -54,6 +54,8 @@ module Sequel
|
|
54
54
|
|
55
55
|
def literal(v)
|
56
56
|
case v
|
57
|
+
when LiteralString
|
58
|
+
v
|
57
59
|
when String
|
58
60
|
"N#{super}"
|
59
61
|
when Time
|
@@ -1,4 +1,10 @@
|
|
1
1
|
module Sequel
|
2
|
+
module Schema
|
3
|
+
module SQL
|
4
|
+
# Keep default column_references_sql for add_foreign_key support
|
5
|
+
alias default_column_references_sql column_references_sql
|
6
|
+
end
|
7
|
+
end
|
2
8
|
module MySQL
|
3
9
|
# Methods shared by Database instances that connect to MySQL,
|
4
10
|
# currently supported by the native and JDBC adapters.
|
@@ -15,6 +21,14 @@ module Sequel
|
|
15
21
|
# drop index cases.
|
16
22
|
def alter_table_sql(table, op)
|
17
23
|
case op[:op]
|
24
|
+
when :add_column
|
25
|
+
if related = op.delete(:table)
|
26
|
+
sql = super(table, op)
|
27
|
+
op[:table] = related
|
28
|
+
[sql, "ALTER TABLE #{quote_schema_table(table)} ADD FOREIGN KEY (#{quote_identifier(op[:name])})#{default_column_references_sql(op)}"]
|
29
|
+
else
|
30
|
+
super(table, op)
|
31
|
+
end
|
18
32
|
when :rename_column
|
19
33
|
"ALTER TABLE #{quote_schema_table(table)} CHANGE COLUMN #{quote_identifier(op[:name])} #{quote_identifier(op[:new_name])} #{type_literal(op)}"
|
20
34
|
when :set_column_type
|
@@ -15,7 +15,13 @@ module Sequel
|
|
15
15
|
module DatasetMethods
|
16
16
|
include Dataset::UnsupportedIntersectExceptAll
|
17
17
|
|
18
|
-
SELECT_CLAUSE_ORDER = %w'distinct columns from join where group having
|
18
|
+
SELECT_CLAUSE_ORDER = %w'distinct columns from join where group having compounds order limit'.freeze
|
19
|
+
|
20
|
+
# Oracle uses MINUS instead of EXCEPT, and doesn't support EXCEPT ALL
|
21
|
+
def except(dataset, all = false)
|
22
|
+
raise(Sequel::Error, "EXCEPT ALL not supported") if all
|
23
|
+
compound_clone(:minus, dataset, all)
|
24
|
+
end
|
19
25
|
|
20
26
|
def empty?
|
21
27
|
db[:dual].where(exists).get(1) == nil
|
@@ -41,11 +47,6 @@ module Sequel
|
|
41
47
|
end
|
42
48
|
end
|
43
49
|
|
44
|
-
# Oracle uses MINUS instead of EXCEPT, and doesn't support EXCEPT ALL
|
45
|
-
def select_except_sql(sql, opts)
|
46
|
-
sql << " MINUS #{opts[:except].sql}" if opts[:except]
|
47
|
-
end
|
48
|
-
|
49
50
|
# Oracle requires a subselect to do limit and offset
|
50
51
|
def select_limit_sql(sql, opts)
|
51
52
|
if limit = opts[:limit]
|
@@ -1,4 +1,32 @@
|
|
1
1
|
module Sequel
|
2
|
+
# Top level module for holding all PostgreSQL-related modules and classes
|
3
|
+
# for Sequel. There are a few module level accessors that are added via
|
4
|
+
# metaprogramming. These are:
|
5
|
+
# * client_min_messages (only available when using the native adapter) -
|
6
|
+
# Change the minimum level of messages that PostgreSQL will send to the
|
7
|
+
# the client. The PostgreSQL default is NOTICE, the Sequel default is
|
8
|
+
# WARNING. Set to nil to not change the server default.
|
9
|
+
# * force_standard_strings - Set to false to not force the use of
|
10
|
+
# standard strings
|
11
|
+
# * use_iso_date_format (only available when using the native adapter) -
|
12
|
+
# Set to false to not change the date format to
|
13
|
+
# ISO. This disables one of Sequel's optimizations.
|
14
|
+
#
|
15
|
+
# Changes in these settings only affect future connections. To make
|
16
|
+
# sure that they are applied, they should generally be called right
|
17
|
+
# after the Database object is instantiated and before a connection
|
18
|
+
# is actually made. For example, to use whatever the server defaults are:
|
19
|
+
#
|
20
|
+
# DB = Sequel.postgres(...)
|
21
|
+
# Sequel::Postgres.client_min_messages = nil
|
22
|
+
# Sequel::Postgres.force_standard_strings = false
|
23
|
+
# Sequel::Postgres.use_iso_date_format = false
|
24
|
+
# # A connection to the server is not made until here
|
25
|
+
# DB[:t].all
|
26
|
+
#
|
27
|
+
# The reason they can't be done earlier is that the Sequel::Postgres
|
28
|
+
# module is not loaded until a Database object which uses PostgreSQL
|
29
|
+
# is created.
|
2
30
|
module Postgres
|
3
31
|
# Array of exceptions that need to be converted. JDBC
|
4
32
|
# uses NativeExceptions, the native adapter uses PGError.
|
@@ -7,7 +35,7 @@ module Sequel
|
|
7
35
|
@force_standard_strings = true
|
8
36
|
|
9
37
|
# By default, Sequel forces the use of standard strings, so that
|
10
|
-
# '\\' is interpreted as
|
38
|
+
# '\\' is interpreted as \\ and not \. While PostgreSQL defaults
|
11
39
|
# to interpreting plain strings as extended strings, this will change
|
12
40
|
# in a future version of PostgreSQL. Sequel assumes that SQL standard
|
13
41
|
# strings will be used.
|
@@ -127,12 +155,122 @@ module Sequel
|
|
127
155
|
SQL_ROLLBACK = 'ROLLBACK'.freeze
|
128
156
|
SQL_RELEASE_SAVEPOINT = 'RELEASE SAVEPOINT autopoint_%d'.freeze
|
129
157
|
SYSTEM_TABLE_REGEXP = /^pg|sql/.freeze
|
158
|
+
|
159
|
+
# Creates the function in the database. See create_function_sql for arguments.
|
160
|
+
def create_function(*args)
|
161
|
+
self << create_function_sql(*args)
|
162
|
+
end
|
163
|
+
|
164
|
+
# SQL statement to create database function. Arguments:
|
165
|
+
# * name : name of the function to create
|
166
|
+
# * definition : string definition of the function, or object file for a dynamically loaded C function.
|
167
|
+
# * opts : options hash:
|
168
|
+
# * :args : function arguments, can be either a symbol or string specifying a type or an array of 1-3 elements:
|
169
|
+
# * element 1 : argument data type
|
170
|
+
# * element 2 : argument name
|
171
|
+
# * element 3 : argument mode (e.g. in, out, inout)
|
172
|
+
# * :behavior : Should be IMMUTABLE, STABLE, or VOLATILE. PostgreSQL assumes VOLATILE by default.
|
173
|
+
# * :cost : The estimated cost of the function, used by the query planner.
|
174
|
+
# * :language : The language the function uses. SQL is the default.
|
175
|
+
# * :link_symbol : For a dynamically loaded see function, the function's link symbol if different from the definition argument.
|
176
|
+
# * :returns : The data type returned by the function. If you are using OUT or INOUT argument modes, this is ignored.
|
177
|
+
# Otherwise, if this is not specified, void is used by default to specify the function is not supposed to return a value.
|
178
|
+
# * :rows : The estimated number of rows the function will return. Only use if the function returns SETOF something.
|
179
|
+
# * :security_definer : Makes the privileges of the function the same as the privileges of the user who defined the function instead of
|
180
|
+
# the privileges of the user who runs the function. There are security implications when doing this, see the PostgreSQL documentation.
|
181
|
+
# * :set : Configuration variables to set while the function is being run, can be a hash or an array of two pairs. search_path is
|
182
|
+
# often used here if :security_definer is used.
|
183
|
+
# * :strict : Makes the function return NULL when any argument is NULL.
|
184
|
+
def create_function_sql(name, definition, opts={})
|
185
|
+
args = opts[:args]
|
186
|
+
if !opts[:args].is_a?(Array) || !opts[:args].any?{|a| Array(a).length == 3 and %w'OUT INOUT'.include?(a[2].to_s)}
|
187
|
+
returns = opts[:returns] || 'void'
|
188
|
+
end
|
189
|
+
language = opts[:language] || 'SQL'
|
190
|
+
<<-END
|
191
|
+
CREATE#{' OR REPLACE' if opts[:replace]} FUNCTION #{name}#{sql_function_args(args)}
|
192
|
+
#{"RETURNS #{returns}" if returns}
|
193
|
+
LANGUAGE #{language}
|
194
|
+
#{opts[:behavior].to_s.upcase if opts[:behavior]}
|
195
|
+
#{'STRICT' if opts[:strict]}
|
196
|
+
#{'SECURITY DEFINER' if opts[:security_definer]}
|
197
|
+
#{"COST #{opts[:cost]}" if opts[:cost]}
|
198
|
+
#{"ROWS #{opts[:rows]}" if opts[:rows]}
|
199
|
+
#{opts[:set].map{|k,v| " SET #{k} = #{v}"}.join("\n") if opts[:set]}
|
200
|
+
AS #{literal(definition.to_s)}#{", #{literal(opts[:link_symbol].to_s)}" if opts[:link_symbol]}
|
201
|
+
END
|
202
|
+
end
|
203
|
+
|
204
|
+
# Create the procedural language in the database. See create_language_sql for arguments.
|
205
|
+
def create_language(*args)
|
206
|
+
self << create_language_sql(*args)
|
207
|
+
end
|
208
|
+
|
209
|
+
# SQL for creating a procedural language. Arguments:
|
210
|
+
# * name : Name of the procedural language (e.g. plpgsql)
|
211
|
+
# * opts : options hash:
|
212
|
+
# * :handler : The name of a previously registered function used as a call handler for this language.
|
213
|
+
# * :trusted : Marks the language being created as trusted, allowing unprivileged users to create functions using this language.
|
214
|
+
# * :validator : The name of previously registered function used as a validator of functions defined in this language.
|
215
|
+
def create_language_sql(name, opts={})
|
216
|
+
"CREATE#{' TRUSTED' if opts[:trusted]} LANGUAGE #{name}#{" HANDLER #{opts[:handler]}" if opts[:handler]}#{" VALIDATOR #{opts[:validator]}" if opts[:validator]}"
|
217
|
+
end
|
218
|
+
|
219
|
+
# Create a trigger in the database. See create_trigger_sql for arguments.
|
220
|
+
def create_trigger(*args)
|
221
|
+
self << create_trigger_sql(*args)
|
222
|
+
end
|
223
|
+
|
224
|
+
# SQL for creating a database trigger. Arguments:
|
225
|
+
# * table : the table on which this trigger operates
|
226
|
+
# * name : the name of this trigger
|
227
|
+
# * function : the function to call for this trigger, which should return type trigger.
|
228
|
+
# * opts : options hash:
|
229
|
+
# * :after : Calls the trigger after execution instead of before.
|
230
|
+
# * :args : An argument or array of arguments to pass to the function.
|
231
|
+
# * :each_row : Calls the trigger for each row instead of for each statement.
|
232
|
+
# * :events : Can be :insert, :update, :delete, or an array of any of those. Calls the trigger whenever that type of statement is used. By default,
|
233
|
+
# the trigger is called for insert, update, or delete.
|
234
|
+
def create_trigger_sql(table, name, function, opts={})
|
235
|
+
events = opts[:events] ? Array(opts[:events]) : [:insert, :update, :delete]
|
236
|
+
whence = opts[:after] ? 'AFTER' : 'BEFORE'
|
237
|
+
"CREATE TRIGGER #{name} #{whence} #{events.map{|e| e.to_s.upcase}.join(' OR ')} ON #{quote_schema_table(table)}#{' FOR EACH ROW' if opts[:each_row]} EXECUTE PROCEDURE #{function}(#{Array(opts[:args]).map{|a| literal(a)}.join(', ')})"
|
238
|
+
end
|
130
239
|
|
131
240
|
# The default schema to use if none is specified (default: public)
|
132
241
|
def default_schema
|
133
242
|
@default_schema ||= :public
|
134
243
|
end
|
135
244
|
|
245
|
+
# Drops the function from the database. See drop_function_sql for arguments.
|
246
|
+
def drop_function(*args)
|
247
|
+
self << drop_function_sql(*args)
|
248
|
+
end
|
249
|
+
|
250
|
+
# SQL for dropping a function from the database. Arguments:
|
251
|
+
# * name : name of the function to drop
|
252
|
+
# * opts : options hash:
|
253
|
+
# * :args : The arguments for the function. See create_function_sql.
|
254
|
+
# * :cascade : Drop other objects depending on this function.
|
255
|
+
# * :if_exists : Don't raise an error if the function doesn't exist.
|
256
|
+
def drop_function_sql(name, opts={})
|
257
|
+
"DROP FUNCTION#{' IF EXISTS' if opts[:if_exists]} #{name}#{sql_function_args(opts[:args])}#{' CASCADE' if opts[:cascade]}"
|
258
|
+
end
|
259
|
+
|
260
|
+
# Drops a procedural language from the database. See drop_language_sql for arguments.
|
261
|
+
def drop_language(*args)
|
262
|
+
self << drop_language_sql(*args)
|
263
|
+
end
|
264
|
+
|
265
|
+
# SQL for dropping a procedural language from the database. Arguments:
|
266
|
+
# * name : name of the procedural language to drop
|
267
|
+
# * opts : options hash:
|
268
|
+
# * :cascade : Drop other objects depending on this function.
|
269
|
+
# * :if_exists : Don't raise an error if the function doesn't exist.
|
270
|
+
def drop_language_sql(name, opts={})
|
271
|
+
"DROP LANGUAGE#{' IF EXISTS' if opts[:if_exists]} #{name}#{' CASCADE' if opts[:cascade]}"
|
272
|
+
end
|
273
|
+
|
136
274
|
# Remove the cached entries for primary keys and sequences when dropping a table.
|
137
275
|
def drop_table(*names)
|
138
276
|
names.each do |name|
|
@@ -148,6 +286,21 @@ module Sequel
|
|
148
286
|
"DROP TABLE #{quote_schema_table(name)} CASCADE"
|
149
287
|
end
|
150
288
|
|
289
|
+
# Drops a trigger from the database. See drop_trigger_sql for arguments.
|
290
|
+
def drop_trigger(*args)
|
291
|
+
self << drop_trigger_sql(*args)
|
292
|
+
end
|
293
|
+
|
294
|
+
# SQL for dropping a trigger from the database. Arguments:
|
295
|
+
# * table : table from which to drop the trigger
|
296
|
+
# * name : name of the trigger to drop
|
297
|
+
# * opts : options hash:
|
298
|
+
# * :cascade : Drop other objects depending on this function.
|
299
|
+
# * :if_exists : Don't raise an error if the function doesn't exist.
|
300
|
+
def drop_trigger_sql(table, name, opts={})
|
301
|
+
"DROP TRIGGER#{' IF EXISTS' if opts[:if_exists]} #{name} ON #{quote_schema_table(table)}#{' CASCADE' if opts[:cascade]}"
|
302
|
+
end
|
303
|
+
|
151
304
|
# PostgreSQL specific index SQL.
|
152
305
|
def index_definition_sql(table_name, index)
|
153
306
|
index_name = index[:name] || default_index_name(table_name, index[:columns])
|
@@ -375,6 +528,11 @@ module Sequel
|
|
375
528
|
end
|
376
529
|
ds
|
377
530
|
end
|
531
|
+
|
532
|
+
# Turns an array of argument specifiers into an SQL fragment used for function arguments. See create_function_sql.
|
533
|
+
def sql_function_args(args)
|
534
|
+
"(#{Array(args).map{|a| Array(a).reverse.join(' ')}.join(', ')})"
|
535
|
+
end
|
378
536
|
end
|
379
537
|
|
380
538
|
# Instance methods for datasets that connect to a PostgreSQL database.
|
@@ -394,7 +552,7 @@ module Sequel
|
|
394
552
|
QUERY_PLAN = 'QUERY PLAN'.to_sym
|
395
553
|
ROW_EXCLUSIVE = 'ROW EXCLUSIVE'.freeze
|
396
554
|
ROW_SHARE = 'ROW SHARE'.freeze
|
397
|
-
SELECT_CLAUSE_ORDER = %w'distinct columns from join where group having
|
555
|
+
SELECT_CLAUSE_ORDER = %w'distinct columns from join where group having compounds order limit lock'.freeze
|
398
556
|
SHARE = 'SHARE'.freeze
|
399
557
|
SHARE_ROW_EXCLUSIVE = 'SHARE ROW EXCLUSIVE'.freeze
|
400
558
|
SHARE_UPDATE_EXCLUSIVE = 'SHARE UPDATE EXCLUSIVE'.freeze
|
@@ -476,7 +634,7 @@ module Sequel
|
|
476
634
|
when LiteralString
|
477
635
|
v
|
478
636
|
when SQL::Blob
|
479
|
-
db.synchronize{|c| "
|
637
|
+
db.synchronize{|c| "'#{c.escape_bytea(v)}'"}
|
480
638
|
when String
|
481
639
|
db.synchronize{|c| "'#{c.escape_string(v)}'"}
|
482
640
|
when Time
|
@@ -526,6 +684,15 @@ module Sequel
|
|
526
684
|
pk = db.primary_key(opts[:from].first)
|
527
685
|
insert_returning_sql(pk ? Sequel::SQL::Identifier.new(pk) : 'NULL'.lit, *values)
|
528
686
|
end
|
687
|
+
|
688
|
+
# PostgreSQL is smart and can use parantheses around all datasets to get
|
689
|
+
# the correct answers.
|
690
|
+
def select_compounds_sql(sql, opts)
|
691
|
+
return unless opts[:compounds]
|
692
|
+
opts[:compounds].each do |type, dataset, all|
|
693
|
+
sql.replace("(#{sql} #{type.to_s.upcase}#{' ALL' if all} #{subselect_sql(dataset)})")
|
694
|
+
end
|
695
|
+
end
|
529
696
|
|
530
697
|
# The order of clauses in the SELECT SQL statement
|
531
698
|
def select_clause_order
|