sequel 5.83.1 → 5.84.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.
- checksums.yaml +4 -4
- data/lib/sequel/adapters/shared/sqlite.rb +3 -1
- data/lib/sequel/database/schema_methods.rb +2 -0
- data/lib/sequel/extensions/pg_json_ops.rb +328 -1
- data/lib/sequel/sql.rb +8 -5
- data/lib/sequel/version.rb +2 -2
- metadata +2 -236
- data/CHANGELOG +0 -1397
- data/README.rdoc +0 -936
- data/doc/advanced_associations.rdoc +0 -884
- data/doc/association_basics.rdoc +0 -1859
- data/doc/bin_sequel.rdoc +0 -146
- data/doc/cheat_sheet.rdoc +0 -255
- data/doc/code_order.rdoc +0 -104
- data/doc/core_extensions.rdoc +0 -405
- data/doc/dataset_basics.rdoc +0 -96
- data/doc/dataset_filtering.rdoc +0 -222
- data/doc/extensions.rdoc +0 -77
- data/doc/fork_safety.rdoc +0 -84
- data/doc/mass_assignment.rdoc +0 -98
- data/doc/migration.rdoc +0 -660
- data/doc/model_dataset_method_design.rdoc +0 -129
- data/doc/model_hooks.rdoc +0 -254
- data/doc/model_plugins.rdoc +0 -270
- data/doc/mssql_stored_procedures.rdoc +0 -43
- data/doc/object_model.rdoc +0 -563
- data/doc/opening_databases.rdoc +0 -439
- data/doc/postgresql.rdoc +0 -611
- data/doc/prepared_statements.rdoc +0 -144
- data/doc/querying.rdoc +0 -1070
- data/doc/reflection.rdoc +0 -120
- data/doc/release_notes/5.0.0.txt +0 -159
- data/doc/release_notes/5.1.0.txt +0 -31
- data/doc/release_notes/5.10.0.txt +0 -84
- data/doc/release_notes/5.11.0.txt +0 -83
- data/doc/release_notes/5.12.0.txt +0 -141
- data/doc/release_notes/5.13.0.txt +0 -27
- data/doc/release_notes/5.14.0.txt +0 -63
- data/doc/release_notes/5.15.0.txt +0 -39
- data/doc/release_notes/5.16.0.txt +0 -110
- data/doc/release_notes/5.17.0.txt +0 -31
- data/doc/release_notes/5.18.0.txt +0 -69
- data/doc/release_notes/5.19.0.txt +0 -28
- data/doc/release_notes/5.2.0.txt +0 -33
- data/doc/release_notes/5.20.0.txt +0 -89
- data/doc/release_notes/5.21.0.txt +0 -87
- data/doc/release_notes/5.22.0.txt +0 -48
- data/doc/release_notes/5.23.0.txt +0 -56
- data/doc/release_notes/5.24.0.txt +0 -56
- data/doc/release_notes/5.25.0.txt +0 -32
- data/doc/release_notes/5.26.0.txt +0 -35
- data/doc/release_notes/5.27.0.txt +0 -21
- data/doc/release_notes/5.28.0.txt +0 -16
- data/doc/release_notes/5.29.0.txt +0 -22
- data/doc/release_notes/5.3.0.txt +0 -121
- data/doc/release_notes/5.30.0.txt +0 -20
- data/doc/release_notes/5.31.0.txt +0 -148
- data/doc/release_notes/5.32.0.txt +0 -46
- data/doc/release_notes/5.33.0.txt +0 -24
- data/doc/release_notes/5.34.0.txt +0 -40
- data/doc/release_notes/5.35.0.txt +0 -56
- data/doc/release_notes/5.36.0.txt +0 -60
- data/doc/release_notes/5.37.0.txt +0 -30
- data/doc/release_notes/5.38.0.txt +0 -28
- data/doc/release_notes/5.39.0.txt +0 -19
- data/doc/release_notes/5.4.0.txt +0 -80
- data/doc/release_notes/5.40.0.txt +0 -40
- data/doc/release_notes/5.41.0.txt +0 -25
- data/doc/release_notes/5.42.0.txt +0 -136
- data/doc/release_notes/5.43.0.txt +0 -98
- data/doc/release_notes/5.44.0.txt +0 -32
- data/doc/release_notes/5.45.0.txt +0 -34
- data/doc/release_notes/5.46.0.txt +0 -87
- data/doc/release_notes/5.47.0.txt +0 -59
- data/doc/release_notes/5.48.0.txt +0 -14
- data/doc/release_notes/5.49.0.txt +0 -59
- data/doc/release_notes/5.5.0.txt +0 -61
- data/doc/release_notes/5.50.0.txt +0 -78
- data/doc/release_notes/5.51.0.txt +0 -47
- data/doc/release_notes/5.52.0.txt +0 -87
- data/doc/release_notes/5.53.0.txt +0 -23
- data/doc/release_notes/5.54.0.txt +0 -27
- data/doc/release_notes/5.55.0.txt +0 -21
- data/doc/release_notes/5.56.0.txt +0 -51
- data/doc/release_notes/5.57.0.txt +0 -23
- data/doc/release_notes/5.58.0.txt +0 -31
- data/doc/release_notes/5.59.0.txt +0 -73
- data/doc/release_notes/5.6.0.txt +0 -31
- data/doc/release_notes/5.60.0.txt +0 -22
- data/doc/release_notes/5.61.0.txt +0 -43
- data/doc/release_notes/5.62.0.txt +0 -132
- data/doc/release_notes/5.63.0.txt +0 -33
- data/doc/release_notes/5.64.0.txt +0 -50
- data/doc/release_notes/5.65.0.txt +0 -21
- data/doc/release_notes/5.66.0.txt +0 -24
- data/doc/release_notes/5.67.0.txt +0 -32
- data/doc/release_notes/5.68.0.txt +0 -61
- data/doc/release_notes/5.69.0.txt +0 -26
- data/doc/release_notes/5.7.0.txt +0 -108
- data/doc/release_notes/5.70.0.txt +0 -35
- data/doc/release_notes/5.71.0.txt +0 -21
- data/doc/release_notes/5.72.0.txt +0 -33
- data/doc/release_notes/5.73.0.txt +0 -66
- data/doc/release_notes/5.74.0.txt +0 -45
- data/doc/release_notes/5.75.0.txt +0 -35
- data/doc/release_notes/5.76.0.txt +0 -86
- data/doc/release_notes/5.77.0.txt +0 -63
- data/doc/release_notes/5.78.0.txt +0 -67
- data/doc/release_notes/5.79.0.txt +0 -28
- data/doc/release_notes/5.8.0.txt +0 -170
- data/doc/release_notes/5.80.0.txt +0 -40
- data/doc/release_notes/5.81.0.txt +0 -31
- data/doc/release_notes/5.82.0.txt +0 -61
- data/doc/release_notes/5.83.0.txt +0 -56
- data/doc/release_notes/5.9.0.txt +0 -99
- data/doc/schema_modification.rdoc +0 -679
- data/doc/security.rdoc +0 -443
- data/doc/sharding.rdoc +0 -286
- data/doc/sql.rdoc +0 -648
- data/doc/testing.rdoc +0 -204
- data/doc/thread_safety.rdoc +0 -15
- data/doc/transactions.rdoc +0 -250
- data/doc/validations.rdoc +0 -558
- data/doc/virtual_rows.rdoc +0 -265
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5677b07054121f55f100f0629d8102cabdd9db454263c5199a8f401bea891992
|
|
4
|
+
data.tar.gz: ca57e632e3e66c3a4003f988e5240da6a6eed0de9a143ac3985bd0603e0d9073
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2ea8e58679c4ae2455588b584b959b3be691c177823cf336b77fa7b5910e716d9ca88e54024bbef44ec58d3fa8d66070acbf94e8c32a4294126ab2e618f4285e
|
|
7
|
+
data.tar.gz: acf4e565dd754b16ea0c07a11fe67cd21c9d5833ac1cf70c384a8da2c1b7c9ffd324358dbab9a8196d5a249365cc11870e6c807d07dbc631d359b413977f14ed
|
|
@@ -349,7 +349,7 @@ module Sequel
|
|
|
349
349
|
ps
|
|
350
350
|
end
|
|
351
351
|
|
|
352
|
-
# Support creating STRICT AND/OR WITHOUT ROWID tables via :strict and :without_rowid options
|
|
352
|
+
# Support creating STRICT AND/OR WITHOUT ROWID tables via :strict and :without_rowid options, and VIRTUAL tables with :using option.
|
|
353
353
|
def create_table_sql(name, generator, options)
|
|
354
354
|
if options[:strict] && options[:without_rowid]
|
|
355
355
|
"#{super} STRICT, WITHOUT ROWID"
|
|
@@ -357,6 +357,8 @@ module Sequel
|
|
|
357
357
|
"#{super} STRICT"
|
|
358
358
|
elsif options[:without_rowid]
|
|
359
359
|
"#{super} WITHOUT ROWID"
|
|
360
|
+
elsif options[:using]
|
|
361
|
+
"CREATE VIRTUAL TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{create_table_table_name_sql(name, options)} USING #{options[:using]}"
|
|
360
362
|
else
|
|
361
363
|
super
|
|
362
364
|
end
|
|
@@ -191,6 +191,8 @@ module Sequel
|
|
|
191
191
|
# The +any+ type is treated like a SQLite column in a non-strict table,
|
|
192
192
|
# allowing any type of data to be stored. This option is supported on
|
|
193
193
|
# SQLite 3.37.0+.
|
|
194
|
+
# :using :: Create a VIRTUAL table with the given USING clause. The value should be
|
|
195
|
+
# a string, as it is used directly in the SQL query.
|
|
194
196
|
# :without_rowid :: Create a WITHOUT ROWID table. Every row in SQLite has a special
|
|
195
197
|
# 'rowid' column, that uniquely identifies that row within the table.
|
|
196
198
|
# If this option is used, the 'rowid' column is omitted, which can
|
|
@@ -132,6 +132,17 @@
|
|
|
132
132
|
# j.is_not_json(type: :array) # j IS NOT JSON ARRAY
|
|
133
133
|
# j.is_not_json(unique: true) # j IS NOT JSON WITH UNIQUE
|
|
134
134
|
#
|
|
135
|
+
# On PostgreSQL 17+, the additional JSON functions are supported (see method documentation
|
|
136
|
+
# for additional options):
|
|
137
|
+
#
|
|
138
|
+
# j.exists('$.foo') # json_exists(jsonb_column, '$.foo')
|
|
139
|
+
# j.value('$.foo') # json_value(jsonb_column, '$.foo')
|
|
140
|
+
# j.query('$.foo') # json_query(jsonb_column, '$.foo')
|
|
141
|
+
#
|
|
142
|
+
# j.exists('$.foo', passing: {a: 1}) # json_exists(jsonb_column, '$.foo' PASSING 1 AS a)
|
|
143
|
+
# j.value('$.foo', returning: Time) # json_value(jsonb_column, '$.foo' RETURNING timestamp)
|
|
144
|
+
# j.query('$.foo', wrapper: true) # json_query(jsonb_column, '$.foo' WITH WRAPPER)
|
|
145
|
+
#
|
|
135
146
|
# If you are also using the pg_json extension, you should load it before
|
|
136
147
|
# loading this extension. Doing so will allow you to use the #op method on
|
|
137
148
|
# JSONHash, JSONHarray, JSONBHash, and JSONBArray, allowing you to perform json/jsonb operations
|
|
@@ -224,7 +235,25 @@ module Sequel
|
|
|
224
235
|
function(:each_text)
|
|
225
236
|
end
|
|
226
237
|
|
|
227
|
-
#
|
|
238
|
+
# Return whether the given JSON path yields any items in the receiver.
|
|
239
|
+
# Options:
|
|
240
|
+
#
|
|
241
|
+
# :on_error :: How to handle errors when evaluating the JSON path expression.
|
|
242
|
+
# true :: Return true
|
|
243
|
+
# false :: Return false (default behavior)
|
|
244
|
+
# :null :: Return nil
|
|
245
|
+
# :error :: raise a DatabaseError
|
|
246
|
+
# :passing :: Variables to pass to the JSON path expression. Keys are variable
|
|
247
|
+
# names, values are the values of the variable.
|
|
248
|
+
#
|
|
249
|
+
# json_op.exists("$.a") # json_exists(json, '$.a')
|
|
250
|
+
# json_op.exists("$.a", passing: {a: 1}) # json_exists(json, '$.a' PASSING 1 AS a)
|
|
251
|
+
# json_op.exists("$.a", on_error: :error) # json_exists(json, '$.a' ERROR ON ERROR)
|
|
252
|
+
def exists(path, opts=OPTS)
|
|
253
|
+
Sequel::SQL::BooleanExpression.new(:NOOP, JSONExistsOp.new(self, path, opts))
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Returns a JSON value for the object at the given path.
|
|
228
257
|
#
|
|
229
258
|
# json_op.extract('a') # json_extract_path(json, 'a')
|
|
230
259
|
# json_op.extract('a', 'b') # json_extract_path(json, 'a', 'b')
|
|
@@ -299,6 +328,35 @@ module Sequel
|
|
|
299
328
|
SQL::Function.new(function_name(:populate_recordset), arg, self)
|
|
300
329
|
end
|
|
301
330
|
|
|
331
|
+
# Return the result of applying the JSON path expression to the receiver, by default
|
|
332
|
+
# returning results as jsonb. Options:
|
|
333
|
+
#
|
|
334
|
+
# :on_empty :: How to handle case where path expression yields an empty set.
|
|
335
|
+
# Uses same values as :on_error option.
|
|
336
|
+
# :on_error :: How to handle errors when evaluating the JSON path expression:
|
|
337
|
+
# :null :: Return nil (default)
|
|
338
|
+
# :empty_array :: Return an empty array
|
|
339
|
+
# :empty_object :: Return an empty object
|
|
340
|
+
# :error :: raise a DatabaseError
|
|
341
|
+
# any other value :: used as default value
|
|
342
|
+
# :passing :: Variables to pass to the JSON path expression. Keys are variable
|
|
343
|
+
# names, values are the values of the variable.
|
|
344
|
+
# :returning :: The data type to return (jsonb by default)
|
|
345
|
+
# :wrapper :: How to wrap returned values:
|
|
346
|
+
# true, :unconditional :: Always wrap returning values in an array
|
|
347
|
+
# :conditional :: Only wrap multiple return values in an array
|
|
348
|
+
# :omit_quotes :: Do not wrap scalar strings in quotes
|
|
349
|
+
#
|
|
350
|
+
# json_op.query("$.a") # json_query(json, '$.a')
|
|
351
|
+
# json_op.query("$.a", passing: {a: 1}) # json_query(json, '$.a' PASSING 1 AS a)
|
|
352
|
+
# json_op.query("$.a", on_error: :empty_array) # json_query(json, '$.a' EMPTY ARRAY ON ERROR)
|
|
353
|
+
# json_op.query("$.a", returning: Time) # json_query(json, '$.a' RETURNING timestamp)
|
|
354
|
+
# json_op.query("$.a", on_empty: 2) # json_query(json, '$.a' DEFAULT 2 ON EMPTY)
|
|
355
|
+
# json_op.query("$.a", wrapper: true) # json_query(json, '$.a' WITH WRAPPER)
|
|
356
|
+
def query(path, opts=OPTS)
|
|
357
|
+
self.class.new(JSONQueryOp.new(self, path, opts))
|
|
358
|
+
end
|
|
359
|
+
|
|
302
360
|
# Returns a json value stripped of all internal null values.
|
|
303
361
|
#
|
|
304
362
|
# json_op.strip_nulls # json_strip_nulls(json)
|
|
@@ -329,6 +387,34 @@ module Sequel
|
|
|
329
387
|
function(:typeof)
|
|
330
388
|
end
|
|
331
389
|
|
|
390
|
+
# If called without arguments, operates as SQL::Wrapper#value. Otherwise,
|
|
391
|
+
# return the result of applying the JSON path expression to the receiver, by default
|
|
392
|
+
# returning results as text. Options:
|
|
393
|
+
#
|
|
394
|
+
# :on_empty :: How to handle case where path expression yields an empty set.
|
|
395
|
+
# Uses same values as :on_error option.
|
|
396
|
+
# :on_error :: How to handle errors when evaluating the JSON path expression.
|
|
397
|
+
# :null :: Return nil (default)
|
|
398
|
+
# :error :: raise a DatabaseError
|
|
399
|
+
# any other value :: used as default value
|
|
400
|
+
# :passing :: Variables to pass to the JSON path expression. Keys are variable
|
|
401
|
+
# names, values are the values of the variable.
|
|
402
|
+
# :returning :: The data type to return (text by default)
|
|
403
|
+
#
|
|
404
|
+
# json_op.value("$.a") # json_value(json, '$.a')
|
|
405
|
+
# json_op.value("$.a", passing: {a: 1}) # json_value(json, '$.a' PASSING 1 AS a)
|
|
406
|
+
# json_op.value("$.a", on_error: :error) # json_value(json, '$.a' ERROR ON ERROR)
|
|
407
|
+
# json_op.value("$.a", returning: Time) # json_value(json, '$.a' RETURNING timestamp)
|
|
408
|
+
# json_op.value("$.a", on_empty: 2) # json_value(json, '$.a' DEFAULT 2 ON EMPTY)
|
|
409
|
+
def value(path=(no_args_given = true), opts=OPTS)
|
|
410
|
+
if no_args_given
|
|
411
|
+
# Act as SQL::Wrapper#value
|
|
412
|
+
super()
|
|
413
|
+
else
|
|
414
|
+
Sequel::SQL::StringExpression.new(:NOOP, JSONValueOp.new(self, path, opts))
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
332
418
|
private
|
|
333
419
|
|
|
334
420
|
# Internals of IS [NOT] JSON support
|
|
@@ -705,6 +791,247 @@ module Sequel
|
|
|
705
791
|
end
|
|
706
792
|
end
|
|
707
793
|
|
|
794
|
+
# Object representing json_exists calls
|
|
795
|
+
class JSONExistsOp < SQL::Expression
|
|
796
|
+
ON_ERROR_SQL = {
|
|
797
|
+
true => 'TRUE',
|
|
798
|
+
false => 'FALSE',
|
|
799
|
+
:null => 'UNKNOWN',
|
|
800
|
+
:error => 'ERROR',
|
|
801
|
+
}.freeze
|
|
802
|
+
private_constant :ON_ERROR_SQL
|
|
803
|
+
|
|
804
|
+
# Expression (context_item in PostgreSQL terms), usually JSONBaseOp instance
|
|
805
|
+
attr_reader :expr
|
|
806
|
+
|
|
807
|
+
# JSON path expression to apply against the expression
|
|
808
|
+
attr_reader :path
|
|
809
|
+
|
|
810
|
+
# Variables to set in the JSON path expression
|
|
811
|
+
attr_reader :passing
|
|
812
|
+
|
|
813
|
+
# How to handle errors when evaluating the JSON path expression
|
|
814
|
+
attr_reader :on_error
|
|
815
|
+
|
|
816
|
+
# See JSONBaseOp#exists for documentation on the options.
|
|
817
|
+
def initialize(expr, path, opts=OPTS)
|
|
818
|
+
@expr = expr
|
|
819
|
+
@path = path
|
|
820
|
+
@passing = opts[:passing]
|
|
821
|
+
@on_error = opts[:on_error]
|
|
822
|
+
freeze
|
|
823
|
+
end
|
|
824
|
+
|
|
825
|
+
# Append the SQL function call expression to the SQL
|
|
826
|
+
def to_s_append(ds, sql)
|
|
827
|
+
to_s_append_function_name(ds, sql)
|
|
828
|
+
to_s_append_args_passing(ds, sql)
|
|
829
|
+
to_s_append_on_error(ds, sql)
|
|
830
|
+
sql << ')'
|
|
831
|
+
end
|
|
832
|
+
|
|
833
|
+
# Support transforming of function call expression
|
|
834
|
+
def sequel_ast_transform(transformer)
|
|
835
|
+
opts = {}
|
|
836
|
+
transform_opts(transformer, opts)
|
|
837
|
+
self.class.new(transformer.call(@expr), @path, opts)
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
private
|
|
841
|
+
|
|
842
|
+
# Set the :passing and :on_error options when doing an
|
|
843
|
+
# AST transform.
|
|
844
|
+
def transform_opts(transformer, opts)
|
|
845
|
+
if @passing
|
|
846
|
+
passing = opts[:passing] = {}
|
|
847
|
+
@passing.each do |k, v|
|
|
848
|
+
passing[k] = transformer.call(v)
|
|
849
|
+
end
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
opts[:on_error] = @on_error
|
|
853
|
+
end
|
|
854
|
+
|
|
855
|
+
def to_s_append_function_name(ds, sql)
|
|
856
|
+
sql << 'json_exists('
|
|
857
|
+
end
|
|
858
|
+
|
|
859
|
+
# Append the expression, path, and optional PASSING fragments
|
|
860
|
+
def to_s_append_args_passing(ds, sql)
|
|
861
|
+
ds.literal_append(sql, @expr)
|
|
862
|
+
sql << ', '
|
|
863
|
+
ds.literal_append(sql, @path)
|
|
864
|
+
|
|
865
|
+
if (passing = @passing) && !passing.empty?
|
|
866
|
+
sql << ' PASSING '
|
|
867
|
+
comma = false
|
|
868
|
+
passing.each do |k, v|
|
|
869
|
+
if comma
|
|
870
|
+
sql << ', '
|
|
871
|
+
else
|
|
872
|
+
comma = true
|
|
873
|
+
end
|
|
874
|
+
ds.literal_append(sql, v)
|
|
875
|
+
sql << " AS " << k.to_s
|
|
876
|
+
end
|
|
877
|
+
end
|
|
878
|
+
end
|
|
879
|
+
|
|
880
|
+
# Append the optional ON ERROR fragments
|
|
881
|
+
def to_s_append_on_error(ds, sql)
|
|
882
|
+
unless @on_error.nil?
|
|
883
|
+
sql << " "
|
|
884
|
+
to_s_append_on_value(ds, sql, @on_error)
|
|
885
|
+
sql << " ON ERROR"
|
|
886
|
+
end
|
|
887
|
+
end
|
|
888
|
+
|
|
889
|
+
# Append the value to use for ON ERROR
|
|
890
|
+
def to_s_append_on_value(ds, sql, value)
|
|
891
|
+
sql << ON_ERROR_SQL.fetch(value)
|
|
892
|
+
end
|
|
893
|
+
end
|
|
894
|
+
|
|
895
|
+
# Object representing json_value calls
|
|
896
|
+
class JSONValueOp < JSONExistsOp
|
|
897
|
+
ON_SQL = {
|
|
898
|
+
:null => 'NULL',
|
|
899
|
+
:error => 'ERROR',
|
|
900
|
+
}.freeze
|
|
901
|
+
private_constant :ON_SQL
|
|
902
|
+
|
|
903
|
+
# The database type to cast returned values to
|
|
904
|
+
attr_reader :returning
|
|
905
|
+
|
|
906
|
+
# How to handle cases where the JSON path expression evaluation yields
|
|
907
|
+
# an empty set.
|
|
908
|
+
attr_reader :on_empty
|
|
909
|
+
|
|
910
|
+
# See JSONBaseOp#value for documentation of the options.
|
|
911
|
+
def initialize(expr, path, opts=OPTS)
|
|
912
|
+
@returning = opts[:returning]
|
|
913
|
+
@on_empty = opts[:on_empty]
|
|
914
|
+
super
|
|
915
|
+
end
|
|
916
|
+
|
|
917
|
+
private
|
|
918
|
+
|
|
919
|
+
# Also handle transforming the returning and on_empty options.
|
|
920
|
+
def transform_opts(transformer, opts)
|
|
921
|
+
super
|
|
922
|
+
opts[:returning] = @returning
|
|
923
|
+
on_error = @on_error
|
|
924
|
+
on_error = transformer.call(on_error) unless on_sql_value(on_error)
|
|
925
|
+
opts[:on_error] = on_error
|
|
926
|
+
on_empty = @on_empty
|
|
927
|
+
on_empty = transformer.call(on_empty) unless on_sql_value(on_empty)
|
|
928
|
+
opts[:on_empty] = on_empty
|
|
929
|
+
end
|
|
930
|
+
|
|
931
|
+
def to_s_append_function_name(ds, sql)
|
|
932
|
+
sql << 'json_value('
|
|
933
|
+
end
|
|
934
|
+
|
|
935
|
+
# Also append the optional RETURNING fragment
|
|
936
|
+
def to_s_append_args_passing(ds, sql)
|
|
937
|
+
super
|
|
938
|
+
|
|
939
|
+
if @returning
|
|
940
|
+
sql << ' RETURNING ' << ds.db.cast_type_literal(@returning).to_s
|
|
941
|
+
end
|
|
942
|
+
end
|
|
943
|
+
|
|
944
|
+
# Also append the optional ON EMPTY fragment
|
|
945
|
+
def to_s_append_on_error(ds, sql)
|
|
946
|
+
unless @on_empty.nil?
|
|
947
|
+
sql << " "
|
|
948
|
+
to_s_append_on_value(ds, sql, @on_empty)
|
|
949
|
+
sql << " ON EMPTY"
|
|
950
|
+
end
|
|
951
|
+
|
|
952
|
+
super
|
|
953
|
+
end
|
|
954
|
+
|
|
955
|
+
# Handle DEFAULT values in ON EMPTY/ON ERROR fragments
|
|
956
|
+
def to_s_append_on_value(ds, sql, value)
|
|
957
|
+
if v = on_sql_value(value)
|
|
958
|
+
sql << v
|
|
959
|
+
else
|
|
960
|
+
sql << 'DEFAULT '
|
|
961
|
+
default_literal_append(ds, sql, value)
|
|
962
|
+
end
|
|
963
|
+
end
|
|
964
|
+
|
|
965
|
+
# Do not auto paramterize default value, as PostgreSQL doesn't allow it.
|
|
966
|
+
def default_literal_append(ds, sql, v)
|
|
967
|
+
if sql.respond_to?(:skip_auto_param)
|
|
968
|
+
sql.skip_auto_param do
|
|
969
|
+
ds.literal_append(sql, v)
|
|
970
|
+
end
|
|
971
|
+
else
|
|
972
|
+
ds.literal_append(sql, v)
|
|
973
|
+
end
|
|
974
|
+
end
|
|
975
|
+
|
|
976
|
+
def on_sql_value(value)
|
|
977
|
+
ON_SQL[value]
|
|
978
|
+
end
|
|
979
|
+
end
|
|
980
|
+
|
|
981
|
+
# Object representing json_query calls
|
|
982
|
+
class JSONQueryOp < JSONValueOp
|
|
983
|
+
ON_SQL = {
|
|
984
|
+
:null => 'NULL',
|
|
985
|
+
:error => 'ERROR',
|
|
986
|
+
:empty_array => 'EMPTY ARRAY',
|
|
987
|
+
:empty_object => 'EMPTY OBJECT',
|
|
988
|
+
}.freeze
|
|
989
|
+
private_constant :ON_SQL
|
|
990
|
+
|
|
991
|
+
WRAPPER = {
|
|
992
|
+
:conditional => ' WITH CONDITIONAL WRAPPER',
|
|
993
|
+
:unconditional => ' WITH WRAPPER',
|
|
994
|
+
:omit_quotes => ' OMIT QUOTES'
|
|
995
|
+
}
|
|
996
|
+
WRAPPER[true] = WRAPPER[:unconditional]
|
|
997
|
+
WRAPPER.freeze
|
|
998
|
+
private_constant :WRAPPER
|
|
999
|
+
|
|
1000
|
+
# How to handle wrapping of results
|
|
1001
|
+
attr_reader :wrapper
|
|
1002
|
+
|
|
1003
|
+
# See JSONBaseOp#query for documentation of the options.
|
|
1004
|
+
def initialize(expr, path, opts=OPTS)
|
|
1005
|
+
@wrapper = opts[:wrapper]
|
|
1006
|
+
super
|
|
1007
|
+
end
|
|
1008
|
+
|
|
1009
|
+
private
|
|
1010
|
+
|
|
1011
|
+
# Also handle transforming the wrapper option
|
|
1012
|
+
def transform_opts(transformer, opts)
|
|
1013
|
+
super
|
|
1014
|
+
opts[:wrapper] = @wrapper
|
|
1015
|
+
end
|
|
1016
|
+
|
|
1017
|
+
def to_s_append_function_name(ds, sql)
|
|
1018
|
+
sql << 'json_query('
|
|
1019
|
+
end
|
|
1020
|
+
|
|
1021
|
+
# Also append the optional WRAPPER/OMIT QUOTES fragment
|
|
1022
|
+
def to_s_append_args_passing(ds, sql)
|
|
1023
|
+
super
|
|
1024
|
+
|
|
1025
|
+
if @wrapper
|
|
1026
|
+
sql << WRAPPER.fetch(@wrapper)
|
|
1027
|
+
end
|
|
1028
|
+
end
|
|
1029
|
+
|
|
1030
|
+
def on_sql_value(value)
|
|
1031
|
+
ON_SQL[value]
|
|
1032
|
+
end
|
|
1033
|
+
end
|
|
1034
|
+
|
|
708
1035
|
module JSONOpMethods
|
|
709
1036
|
# Wrap the receiver in an JSONOp so you can easily use the PostgreSQL
|
|
710
1037
|
# json functions and operators with it.
|
data/lib/sequel/sql.rb
CHANGED
|
@@ -153,13 +153,16 @@ module Sequel
|
|
|
153
153
|
class ComplexExpression < Expression
|
|
154
154
|
# A hash of the opposite for each operator symbol, used for inverting
|
|
155
155
|
# objects.
|
|
156
|
-
|
|
156
|
+
OPERATOR_INVERSIONS = {:AND => :OR, :OR => :AND, :< => :>=, :> => :<=,
|
|
157
157
|
:<= => :>, :>= => :<, :'=' => :'!=' , :'!=' => :'=', :LIKE => :'NOT LIKE',
|
|
158
158
|
:'NOT LIKE' => :LIKE, :~ => :'!~', :'!~' => :~, :IN => :'NOT IN',
|
|
159
159
|
:'NOT IN' => :IN, :IS => :'IS NOT', :'IS NOT' => :IS, :'~*' => :'!~*',
|
|
160
160
|
:'!~*' => :'~*', :NOT => :NOOP, :NOOP => :NOT, :ILIKE => :'NOT ILIKE',
|
|
161
161
|
:'NOT ILIKE'=>:ILIKE}.freeze
|
|
162
162
|
|
|
163
|
+
# SEQUEL6: Remove
|
|
164
|
+
OPERTATOR_INVERSIONS = OPERATOR_INVERSIONS
|
|
165
|
+
|
|
163
166
|
# Standard mathematical operators used in +NumericMethods+
|
|
164
167
|
MATHEMATICAL_OPERATORS = [:+, :-, :/, :*, :**].freeze
|
|
165
168
|
|
|
@@ -1142,9 +1145,9 @@ module Sequel
|
|
|
1142
1145
|
when BooleanExpression
|
|
1143
1146
|
case op = ce.op
|
|
1144
1147
|
when :AND, :OR
|
|
1145
|
-
BooleanExpression.new(
|
|
1148
|
+
BooleanExpression.new(OPERATOR_INVERSIONS[op], *ce.args.map{|a| BooleanExpression.invert(a)})
|
|
1146
1149
|
when :IN, :"NOT IN"
|
|
1147
|
-
BooleanExpression.new(
|
|
1150
|
+
BooleanExpression.new(OPERATOR_INVERSIONS[op], *ce.args.dup)
|
|
1148
1151
|
else
|
|
1149
1152
|
if ce.args.length == 2
|
|
1150
1153
|
case ce.args[1]
|
|
@@ -1153,10 +1156,10 @@ module Sequel
|
|
|
1153
1156
|
# can result in incorrect behavior for ANY/SOME/ALL operators.
|
|
1154
1157
|
BooleanExpression.new(:NOT, ce)
|
|
1155
1158
|
else
|
|
1156
|
-
BooleanExpression.new(
|
|
1159
|
+
BooleanExpression.new(OPERATOR_INVERSIONS[op], *ce.args.dup)
|
|
1157
1160
|
end
|
|
1158
1161
|
else
|
|
1159
|
-
BooleanExpression.new(
|
|
1162
|
+
BooleanExpression.new(OPERATOR_INVERSIONS[op], *ce.args.dup)
|
|
1160
1163
|
end
|
|
1161
1164
|
end
|
|
1162
1165
|
when StringExpression, NumericExpression
|
data/lib/sequel/version.rb
CHANGED
|
@@ -6,11 +6,11 @@ module Sequel
|
|
|
6
6
|
|
|
7
7
|
# The minor version of Sequel. Bumped for every non-patch level
|
|
8
8
|
# release, generally around once a month.
|
|
9
|
-
MINOR =
|
|
9
|
+
MINOR = 84
|
|
10
10
|
|
|
11
11
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
|
12
12
|
# releases that fix regressions from previous versions.
|
|
13
|
-
TINY =
|
|
13
|
+
TINY = 0
|
|
14
14
|
|
|
15
15
|
# The version of Sequel you are using, as a string (e.g. "2.11.0")
|
|
16
16
|
VERSION = [MAJOR, MINOR, TINY].join('.').freeze
|