sequel_core 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +39 -1
- data/Rakefile +1 -1
- data/doc/dataset_filtering.rdoc +5 -87
- data/lib/sequel_core.rb +20 -13
- data/lib/sequel_core/adapters/mysql.rb +12 -11
- data/lib/sequel_core/adapters/odbc_mssql.rb +3 -3
- data/lib/sequel_core/adapters/oracle.rb +2 -2
- data/lib/sequel_core/adapters/postgres.rb +46 -26
- data/lib/sequel_core/adapters/sqlite.rb +12 -0
- data/lib/sequel_core/core_sql.rb +7 -0
- data/lib/sequel_core/database.rb +12 -14
- data/lib/sequel_core/dataset.rb +6 -3
- data/lib/sequel_core/dataset/sql.rb +28 -25
- data/lib/sequel_core/object_graph.rb +23 -21
- data/lib/sequel_core/schema/sql.rb +5 -1
- data/lib/sequel_core/sql.rb +76 -5
- data/spec/adapters/mysql_spec.rb +33 -9
- data/spec/adapters/postgres_spec.rb +35 -3
- data/spec/adapters/sqlite_spec.rb +14 -2
- data/spec/core_sql_spec.rb +38 -3
- data/spec/database_spec.rb +19 -1
- data/spec/dataset_spec.rb +60 -66
- data/spec/{blockless_filters_spec.rb → expression_filters_spec.rb} +2 -10
- data/spec/object_graph_spec.rb +5 -0
- data/spec/schema_spec.rb +6 -6
- data/spec/spec_config.rb.example +2 -1
- data/spec/spec_helper.rb +0 -6
- metadata +3 -6
- data/lib/sequel_core/dataset/parse_tree_sequelizer.rb +0 -310
- data/lib/sequel_core/dataset/sequelizer.rb +0 -50
- data/spec/sequelizer_spec.rb +0 -504
data/CHANGELOG
CHANGED
@@ -1,4 +1,42 @@
|
|
1
|
-
===
|
1
|
+
=== 2.2.0 (2008-07-05)
|
2
|
+
|
3
|
+
* Filter blocks now yield a SQL::VirtualRow argument, which is useful if another library defines operator methods on Symbol (jeremyevans)
|
4
|
+
|
5
|
+
* Add Symbol#identifier method, to make x__a be treated as "x__a" instead of "x"."a" (jeremyevans)
|
6
|
+
|
7
|
+
* Dataset#update no longer takes a block, please use a hash argument with the expression syntax instead (jeremyevans)
|
8
|
+
|
9
|
+
* ParseTree support has been removed from Sequel (jeremyevans)
|
10
|
+
|
11
|
+
* Database#drop_column is now supported in the SQLite adapter (abhay)
|
12
|
+
|
13
|
+
* Tinyint columns can now be considered integers instead of booleans by setting Sequel.convert_tinyint_to_bool = false (samsouder)
|
14
|
+
|
15
|
+
* Allow the use of URL parameters in connection strings (jeremyevans)
|
16
|
+
|
17
|
+
* Ignore any previously selected columns when using Dataset#graph for the first time (jeremyevans)
|
18
|
+
|
19
|
+
* Dataset#graph now accepts a block which is passed to join_table (jeremyevans)
|
20
|
+
|
21
|
+
* Make Dataset#columns ignore any filtering, ordering, and distinct clauses (jeremyevans)
|
22
|
+
|
23
|
+
* Use the safer connection-specific string escaping methods for PostgreSQL (jeremyevans)
|
24
|
+
|
25
|
+
* Database#transaction now yields a connection when using the Postgres adapter, just like it does for other adapters (jeremyevans)
|
26
|
+
|
27
|
+
* Dataset#count now works for a limited dataset (divoxx)
|
28
|
+
|
29
|
+
* Database#add_index is now supported in the SQLite adapter (abhay)
|
30
|
+
|
31
|
+
* Sequel's MySQL adapter should no longer conflict with ActiveRecord's use of MySQL (careo)
|
32
|
+
|
33
|
+
* Treat Hash as expression instead of column alias when used in DISTINCT, ORDER BY, and GROUP BY clauses (jeremyevans)
|
34
|
+
|
35
|
+
* PostgreSQL bytea fields are now fully supported (dlee)
|
36
|
+
|
37
|
+
* For PostgreSQL, don't raise an error when assigning a value to a SERIAL PRIMARY KEY field when inserting records (jeremyevans)
|
38
|
+
|
39
|
+
=== 2.1.0 (2008-06-17)
|
2
40
|
|
3
41
|
* Support bitwise operators for NumericExpressions: &, |, ^, ~, <<, >> (jeremyevans)
|
4
42
|
|
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ include FileUtils
|
|
9
9
|
# Configuration
|
10
10
|
##############################################################################
|
11
11
|
NAME = "sequel_core"
|
12
|
-
VERS = "2.
|
12
|
+
VERS = "2.2.0"
|
13
13
|
CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage"]
|
14
14
|
RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
|
15
15
|
'Sequel: The Database Toolkit for Ruby: Core Library and Adapters', \
|
data/doc/dataset_filtering.rdoc
CHANGED
@@ -145,114 +145,32 @@ Or against SQL functions:
|
|
145
145
|
|
146
146
|
You can search SQL strings using the #like method:
|
147
147
|
|
148
|
-
items.filter(:name.like('Acme%').sql
|
148
|
+
items.filter(:name.like('Acme%')).sql
|
149
149
|
#=> "SELECT * FROM items WHERE (name LIKE 'Acme%')"
|
150
150
|
|
151
151
|
You can specify a Regexp as a like argument, but this will probably only work
|
152
152
|
on PostgreSQL and MySQL:
|
153
153
|
|
154
|
-
items.filter(:name.like(/Acme.*/).sql
|
154
|
+
items.filter(:name.like(/Acme.*/)).sql
|
155
155
|
#=> "SELECT * FROM items WHERE (name ~ 'Acme.*')"
|
156
156
|
|
157
157
|
Like can also take more than one argument:
|
158
158
|
|
159
|
-
items.filter(:name.like('Acme%', /Beta.*/).sql
|
159
|
+
items.filter(:name.like('Acme%', /Beta.*/)).sql
|
160
160
|
#=> "SELECT * FROM items WHERE ((name LIKE 'Acme%') OR (name ~ 'Beta.*'))"
|
161
161
|
|
162
162
|
== String concatenation
|
163
163
|
|
164
164
|
You can concatenate SQL strings using Array#sql_string_join:
|
165
165
|
|
166
|
-
items.filter([:name, :comment].sql_string_join.like('%acme%').sql
|
166
|
+
items.filter([:name, :comment].sql_string_join.like('%acme%')).sql
|
167
167
|
#=> "SELECT * FROM items WHERE ((name || comment) LIKE 'Acme%')"
|
168
168
|
|
169
169
|
Array#sql_string_join also takes a join argument:
|
170
170
|
|
171
|
-
items.filter([:name, :comment].sql_string_join(' ').like('%acme%').sql
|
171
|
+
items.filter([:name, :comment].sql_string_join(' ').like('%acme%')).sql
|
172
172
|
#=> "SELECT * FROM items WHERE ((name || ' ' || comment) LIKE 'Acme%')"
|
173
173
|
|
174
|
-
== Filtering using expressions with blocks
|
175
|
-
|
176
|
-
Most SQL expressions that you can can create with expressions you can also express inside blocks. This was previously the only way to specify expressions using ruby code. Filtering with blocks requires that you install ParseTree, ruby2ruby, and their dependencies. It's slower than using the equivalent expression without a block, and the syntax inside the block is different in some cases. Because it requires ParseTree, it can only be used with MRI (Matz's Ruby Interpreter) 1.8.*, as ParseTree doesn't run on any other ruby implementation (blockless filters should work on other ruby implementations).
|
177
|
-
|
178
|
-
In general, filtering with a block should only be used with legacy code. ParseTree filters are currently deprecated, and support for them will be removed in Sequel 2.2. To use the expression filtering syntax inside blocks, set:
|
179
|
-
|
180
|
-
Sequel.use_parse_tree = false
|
181
|
-
# or
|
182
|
-
SEQUEL_NO_PARSE_TREE = true
|
183
|
-
require 'sequel'
|
184
|
-
|
185
|
-
These will become no-ops in Sequel 2.2, as the expression syntax inside blocks will be the only supported behavior.
|
186
|
-
|
187
|
-
To filter with a block, supply a block to filter with the appropriate ruby code:
|
188
|
-
|
189
|
-
items.filter{:price < 100}.sql
|
190
|
-
#=> "SELECT * FROM items WHERE (price < 100)
|
191
|
-
|
192
|
-
Sequel is smart enough to literalize values correctly, even if you compare against arrays or ranges:
|
193
|
-
|
194
|
-
items.filter{:category == 'ruby'}.sql
|
195
|
-
#=> "SELECT * FROM items WHERE (category = 'ruby')"
|
196
|
-
|
197
|
-
items.filter{:category == ['ruby', 'other']}.sql
|
198
|
-
#=> "SELECT * FROM items WHERE (category IN ('ruby', 'other'))"
|
199
|
-
|
200
|
-
items.filter{:price == (100..200)}.sql
|
201
|
-
#=> "SELECT * FROM items WHERE (price >= 100 AND price <= 200)"
|
202
|
-
|
203
|
-
=== Negating conditions
|
204
|
-
|
205
|
-
You can use the negation operator (!) anywhere:
|
206
|
-
|
207
|
-
items.filter{:category != 'ruby'}.sql
|
208
|
-
#=> "SELECT * FROM items WHERE NOT (category = 'ruby')"
|
209
|
-
|
210
|
-
items.filter{!:active}.sql
|
211
|
-
#=> "SELECT * FROM items WHERE (active = 'f')"
|
212
|
-
|
213
|
-
=== Comparing against column references
|
214
|
-
|
215
|
-
You can also compare against other columns:
|
216
|
-
|
217
|
-
items.filter{:credit > :debit}.sql
|
218
|
-
#=> "SELECT * FROM items WHERE (credit > debit)
|
219
|
-
|
220
|
-
Or against SQL functions:
|
221
|
-
|
222
|
-
items.filter{:price < :max[:price] + 100}.sql
|
223
|
-
#=> "SELECT * FROM items WHERE (price < (max(price) + 100))"
|
224
|
-
|
225
|
-
=== Concatenating conditions with logical operators
|
226
|
-
|
227
|
-
Expressions can be nested and combined using logical operators:
|
228
|
-
|
229
|
-
items.filter{(:price < 100 && :age < 27) || :category == 'ruby'}.sql
|
230
|
-
#=> "SELECT * FROM items WHERE (((price < 100) AND (age < 27)) OR (category = 'ruby'))"
|
231
|
-
|
232
|
-
Another way to concatenate conditions is to specify each condition as a separate statement:
|
233
|
-
|
234
|
-
items.filter do
|
235
|
-
:price < 100
|
236
|
-
:category == 'ruby'
|
237
|
-
end.sql
|
238
|
-
#=> "SELECT * FROM items WHERE ((price < 100) AND (category = 'ruby'))"
|
239
|
-
|
240
|
-
=== Special methods
|
241
|
-
|
242
|
-
Inside blocks, Sequel recognizes the special methods nil/nil?, in/in? and like/like?:
|
243
|
-
|
244
|
-
items.filter{:price.nil?}.sql
|
245
|
-
#=> "SELECT * FROM items WHERE (price IS NULL)"
|
246
|
-
|
247
|
-
items.filter{:category.in ['ruby', 'other']}.sql
|
248
|
-
#=> "SELECT * FROM items WHERE (category IN ('ruby', 'other'))"
|
249
|
-
|
250
|
-
items.filter{:price.in 100..200}.sql
|
251
|
-
#=> "SELECT * FROM items WHERE (price >= 100 AND price <= 200)"
|
252
|
-
|
253
|
-
items.filter{:category.like 'ruby%'}.sql
|
254
|
-
#=> "SELECT * FROM items WHERE (category LIKE 'ruby%')"
|
255
|
-
|
256
174
|
== Filtering using sub-queries
|
257
175
|
|
258
176
|
One of the best features of Sequel is the ability to use datasets as sub-queries. Sub-queries can be very useful for filtering records, and many times provide a simpler alternative to table joins. Sub-queries can be used in all forms of filters:
|
data/lib/sequel_core.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
require f
|
3
3
|
end
|
4
4
|
%w"core_ext sql core_sql connection_pool exceptions pretty_table
|
5
|
-
dataset migration schema database worker object_graph
|
5
|
+
dataset migration schema database worker object_graph".each do |f|
|
6
6
|
require "sequel_core/#{f}"
|
7
7
|
end
|
8
8
|
|
@@ -13,8 +13,8 @@ end
|
|
13
13
|
#
|
14
14
|
# DB = Sequel.sqlite # Memory database
|
15
15
|
# DB = Sequel.sqlite('blog.db')
|
16
|
-
# DB = Sequel.postgres('database_name', :user=>'user',
|
17
|
-
# :password=>'password', :host=>'host', :port=>5432,
|
16
|
+
# DB = Sequel.postgres('database_name', :user=>'user',
|
17
|
+
# :password=>'password', :host=>'host', :port=>5432,
|
18
18
|
# :max_connections=>10)
|
19
19
|
#
|
20
20
|
# If a block is given to these methods, it is passed the opened Database
|
@@ -27,20 +27,16 @@ end
|
|
27
27
|
#
|
28
28
|
# Sequel.datetime_class = DateTime
|
29
29
|
#
|
30
|
-
# Sequel
|
31
|
-
#
|
32
|
-
# be the only behavior allowed in Sequel 2.2). To set it not to use
|
33
|
-
# ParseTree filters:
|
30
|
+
# Sequel converts the column type tinyint to a boolean by default,
|
31
|
+
# you can override the conversion to use tinyint as an integer:
|
34
32
|
#
|
35
|
-
# Sequel.
|
33
|
+
# Sequel.convert_tinyint_to_bool = false
|
36
34
|
module Sequel
|
37
35
|
@datetime_class = Time
|
38
|
-
@
|
39
|
-
|
36
|
+
@convert_tinyint_to_bool = true
|
37
|
+
|
40
38
|
metaattr_accessor :datetime_class
|
41
|
-
metaattr_accessor :
|
42
|
-
|
43
|
-
Deprecation.deprecation_message_stream = $stderr
|
39
|
+
metaattr_accessor :convert_tinyint_to_bool
|
44
40
|
|
45
41
|
# Creates a new database object based on the supplied connection string
|
46
42
|
# and optional arguments. The specified scheme determines the database
|
@@ -97,6 +93,17 @@ module Sequel
|
|
97
93
|
def self.single_threaded=(value)
|
98
94
|
Database.single_threaded = value
|
99
95
|
end
|
96
|
+
|
97
|
+
# Always returns false, since ParseTree support has been removed.
|
98
|
+
def self.use_parse_tree
|
99
|
+
false
|
100
|
+
end
|
101
|
+
|
102
|
+
# Raises an error if attempting to turn ParseTree support on (since it no longer exists).
|
103
|
+
# Otherwise, is a no-op.
|
104
|
+
def self.use_parse_tree=(val)
|
105
|
+
raise(Error, 'ParseTree support has been removed from Sequel') if val
|
106
|
+
end
|
100
107
|
|
101
108
|
### Private Class Methods ###
|
102
109
|
|
@@ -4,7 +4,7 @@ require 'mysql'
|
|
4
4
|
class Mysql::Result
|
5
5
|
MYSQL_TYPES = {
|
6
6
|
0 => :to_d, # MYSQL_TYPE_DECIMAL
|
7
|
-
|
7
|
+
1 => :to_i, # MYSQL_TYPE_TINY
|
8
8
|
2 => :to_i, # MYSQL_TYPE_SHORT
|
9
9
|
3 => :to_i, # MYSQL_TYPE_LONG
|
10
10
|
4 => :to_f, # MYSQL_TYPE_FLOAT
|
@@ -22,11 +22,11 @@ class Mysql::Result
|
|
22
22
|
# 16 => :to_s, # MYSQL_TYPE_BIT
|
23
23
|
246 => :to_d, # MYSQL_TYPE_NEWDECIMAL
|
24
24
|
247 => :to_i, # MYSQL_TYPE_ENUM
|
25
|
-
248 => :to_i # MYSQL_TYPE_SET
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
248 => :to_i, # MYSQL_TYPE_SET
|
26
|
+
249 => :to_blob, # MYSQL_TYPE_TINY_BLOB
|
27
|
+
250 => :to_blob, # MYSQL_TYPE_MEDIUM_BLOB
|
28
|
+
251 => :to_blob, # MYSQL_TYPE_LONG_BLOB
|
29
|
+
252 => :to_blob, # MYSQL_TYPE_BLOB
|
30
30
|
# 253 => :to_s, # MYSQL_TYPE_VAR_STRING
|
31
31
|
# 254 => :to_s, # MYSQL_TYPE_STRING
|
32
32
|
# 255 => :to_s # MYSQL_TYPE_GEOMETRY
|
@@ -34,7 +34,7 @@ class Mysql::Result
|
|
34
34
|
|
35
35
|
def convert_type(v, type)
|
36
36
|
if v
|
37
|
-
if type == 1
|
37
|
+
if type == 1 && Sequel.convert_tinyint_to_bool
|
38
38
|
# We special case tinyint here to avoid adding
|
39
39
|
# a method to an ancestor of Fixnum
|
40
40
|
v.to_i == 0 ? false : true
|
@@ -69,7 +69,7 @@ class Mysql::Result
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
def
|
72
|
+
def sequel_each_hash(with_table = nil)
|
73
73
|
c = columns
|
74
74
|
while row = fetch_row
|
75
75
|
h = {}
|
@@ -77,6 +77,7 @@ class Mysql::Result
|
|
77
77
|
yield h
|
78
78
|
end
|
79
79
|
end
|
80
|
+
|
80
81
|
end
|
81
82
|
|
82
83
|
module Sequel
|
@@ -388,7 +389,7 @@ module Sequel
|
|
388
389
|
opts = opts ? @opts.merge(opts) : @opts
|
389
390
|
|
390
391
|
if order = opts[:order]
|
391
|
-
sql << " ORDER BY #{
|
392
|
+
sql << " ORDER BY #{expression_list(order)}"
|
392
393
|
end
|
393
394
|
if limit = opts[:limit]
|
394
395
|
sql << " LIMIT #{limit}"
|
@@ -442,7 +443,7 @@ module Sequel
|
|
442
443
|
opts = opts ? @opts.merge(opts) : @opts
|
443
444
|
|
444
445
|
if order = opts[:order]
|
445
|
-
sql << " ORDER BY #{
|
446
|
+
sql << " ORDER BY #{expression_list(order)}"
|
446
447
|
end
|
447
448
|
if limit = opts[:limit]
|
448
449
|
sql << " LIMIT #{limit}"
|
@@ -470,7 +471,7 @@ module Sequel
|
|
470
471
|
def fetch_rows(sql)
|
471
472
|
@db.execute_select(sql) do |r|
|
472
473
|
@columns = r.columns
|
473
|
-
r.
|
474
|
+
r.sequel_each_hash {|row| yield row}
|
474
475
|
end
|
475
476
|
self
|
476
477
|
end
|
@@ -38,7 +38,7 @@ module Sequel
|
|
38
38
|
select_columns = columns ? column_list(columns) : WILDCARD
|
39
39
|
|
40
40
|
if distinct = opts[:distinct]
|
41
|
-
distinct_clause = distinct.empty? ? "DISTINCT" : "DISTINCT ON (#{
|
41
|
+
distinct_clause = distinct.empty? ? "DISTINCT" : "DISTINCT ON (#{expression_list(distinct)})"
|
42
42
|
sql = "SELECT #{top}#{distinct_clause} #{select_columns}"
|
43
43
|
else
|
44
44
|
sql = "SELECT #{top}#{select_columns}"
|
@@ -62,11 +62,11 @@ module Sequel
|
|
62
62
|
end
|
63
63
|
|
64
64
|
if group = opts[:group]
|
65
|
-
sql << " GROUP BY #{
|
65
|
+
sql << " GROUP BY #{expression_list(group)}"
|
66
66
|
end
|
67
67
|
|
68
68
|
if order = opts[:order]
|
69
|
-
sql << " ORDER BY #{
|
69
|
+
sql << " ORDER BY #{expression_list(order)}"
|
70
70
|
end
|
71
71
|
|
72
72
|
if having = opts[:having]
|
@@ -143,7 +143,7 @@ module Sequel
|
|
143
143
|
end
|
144
144
|
|
145
145
|
if group = opts[:group]
|
146
|
-
sql << " GROUP BY #{
|
146
|
+
sql << " GROUP BY #{expression_list(group)}"
|
147
147
|
end
|
148
148
|
|
149
149
|
if having = opts[:having]
|
@@ -162,7 +162,7 @@ module Sequel
|
|
162
162
|
end
|
163
163
|
|
164
164
|
if order = opts[:order]
|
165
|
-
sql << " ORDER BY #{
|
165
|
+
sql << " ORDER BY #{expression_list(order)}"
|
166
166
|
end
|
167
167
|
|
168
168
|
if limit = opts[:limit]
|
@@ -4,7 +4,41 @@ rescue LoadError => e
|
|
4
4
|
begin
|
5
5
|
require 'postgres'
|
6
6
|
class PGconn
|
7
|
-
|
7
|
+
unless method_defined?(:escape_string)
|
8
|
+
if self.respond_to?(:escape)
|
9
|
+
def escape_string(str)
|
10
|
+
self.class.escape(str)
|
11
|
+
end
|
12
|
+
else
|
13
|
+
def escape_string(obj)
|
14
|
+
raise Sequel::Error, "string escaping not supported with this postgres driver. Try using ruby-pg, ruby-postgres, or postgres-pr."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
unless method_defined?(:escape_bytea)
|
19
|
+
if self.respond_to?(:escape_bytea)
|
20
|
+
def escape_bytea(obj)
|
21
|
+
self.class.escape_bytea(obj)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
begin
|
25
|
+
require 'postgres-pr/typeconv/conv'
|
26
|
+
require 'postgres-pr/typeconv/bytea'
|
27
|
+
extend Postgres::Conversion
|
28
|
+
def escape_bytea(obj)
|
29
|
+
self.class.encode_bytea(obj)
|
30
|
+
end
|
31
|
+
metaalias :unescape_bytea, :decode_bytea
|
32
|
+
rescue
|
33
|
+
def escape_bytea(obj)
|
34
|
+
raise Sequel::Error, "bytea escaping not supported with this postgres driver. Try using ruby-pg, ruby-postgres, or postgres-pr."
|
35
|
+
end
|
36
|
+
def self.unescape_bytea(obj)
|
37
|
+
raise Sequel::Error, "bytea unescaping not supported with this postgres driver. Try using ruby-pg, ruby-postgres, or postgres-pr."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
8
42
|
alias_method :finish, :close unless method_defined?(:finish)
|
9
43
|
end
|
10
44
|
class PGresult
|
@@ -22,24 +56,6 @@ end
|
|
22
56
|
module Sequel
|
23
57
|
module Postgres
|
24
58
|
class Adapter < ::PGconn
|
25
|
-
# the pure-ruby postgres adapter does not have a quote method.
|
26
|
-
TRUE = 'true'.freeze
|
27
|
-
FALSE = 'false'.freeze
|
28
|
-
NULL = 'NULL'.freeze
|
29
|
-
|
30
|
-
def self.quote(obj)
|
31
|
-
case obj
|
32
|
-
when TrueClass
|
33
|
-
TRUE
|
34
|
-
when FalseClass
|
35
|
-
FALSE
|
36
|
-
when NilClass
|
37
|
-
NULL
|
38
|
-
else
|
39
|
-
"'#{escape_string(obj.to_s)}'"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
59
|
def connected?
|
44
60
|
status == Adapter::CONNECTION_OK
|
45
61
|
end
|
@@ -160,7 +176,7 @@ module Sequel
|
|
160
176
|
|
161
177
|
PG_TYPES = {
|
162
178
|
16 => lambda{ |s| Adapter.string_to_bool(s) }, # boolean
|
163
|
-
17 => lambda{ |s| Adapter.unescape_bytea(s) }, # bytea
|
179
|
+
17 => lambda{ |s| Adapter.unescape_bytea(s).to_blob }, # bytea
|
164
180
|
20 => lambda{ |s| s.to_i }, # int8
|
165
181
|
21 => lambda{ |s| s.to_i }, # int2
|
166
182
|
22 => lambda{ |s| s.to_i }, # int2vector
|
@@ -245,9 +261,7 @@ module Sequel
|
|
245
261
|
result = conn.last_insert_id(table)
|
246
262
|
return result if result
|
247
263
|
rescue PGError => e
|
248
|
-
|
249
|
-
# value, while the primary key is serial.
|
250
|
-
raise Error.new(e.message =~ RE_CURRVAL_ERROR ? "Could not return primary key value for the inserted record. Are you specifying a primary key value for a serial primary key?" : e.message)
|
264
|
+
raise(Error, e.message) unless RE_CURRVAL_ERROR.match(e.message)
|
251
265
|
end
|
252
266
|
|
253
267
|
case values
|
@@ -310,7 +324,7 @@ module Sequel
|
|
310
324
|
end
|
311
325
|
begin
|
312
326
|
conn.transaction_depth += 1
|
313
|
-
yield
|
327
|
+
yield conn
|
314
328
|
rescue ::Exception => e
|
315
329
|
if conn.transaction_depth > 1
|
316
330
|
log_info(SQL_ROLLBACK_TO_SAVEPOINT % [conn.transaction_depth - 1])
|
@@ -393,17 +407,23 @@ module Sequel
|
|
393
407
|
end
|
394
408
|
|
395
409
|
PG_TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S".freeze
|
410
|
+
BOOL_FALSE = 'false'.freeze
|
411
|
+
BOOL_TRUE = 'true'.freeze
|
396
412
|
|
397
413
|
def literal(v)
|
398
414
|
case v
|
399
415
|
when LiteralString
|
400
416
|
v
|
401
|
-
when String
|
402
|
-
|
417
|
+
when String
|
418
|
+
db.synchronize{|c| "'#{SQL::Blob === v ? c.escape_bytea(v) : c.escape_string(v)}'"}
|
403
419
|
when Time
|
404
420
|
"#{v.strftime(PG_TIMESTAMP_FORMAT)}.#{sprintf("%06d",v.usec)}'"
|
405
421
|
when DateTime
|
406
422
|
"#{v.strftime(PG_TIMESTAMP_FORMAT)}.#{sprintf("%06d", (v.sec_fraction * 86400000000).to_i)}'"
|
423
|
+
when TrueClass
|
424
|
+
BOOL_TRUE
|
425
|
+
when FalseClass
|
426
|
+
BOOL_FALSE
|
407
427
|
else
|
408
428
|
super
|
409
429
|
end
|