sequel 4.23.0 → 4.24.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/CHANGELOG +26 -0
- data/Rakefile +1 -1
- data/doc/release_notes/4.24.0.txt +99 -0
- data/doc/sql.rdoc +10 -1
- data/lib/sequel/adapters/jdbc.rb +7 -0
- data/lib/sequel/adapters/jdbc/cubrid.rb +1 -1
- data/lib/sequel/adapters/jdbc/db2.rb +1 -1
- data/lib/sequel/adapters/jdbc/derby.rb +1 -1
- data/lib/sequel/adapters/jdbc/h2.rb +1 -1
- data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -1
- data/lib/sequel/adapters/jdbc/mssql.rb +1 -1
- data/lib/sequel/adapters/jdbc/mysql.rb +2 -2
- data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +14 -6
- data/lib/sequel/adapters/shared/mssql.rb +1 -1
- data/lib/sequel/core.rb +12 -1
- data/lib/sequel/database/connecting.rb +1 -2
- data/lib/sequel/extensions/pg_inet_ops.rb +200 -0
- data/lib/sequel/plugins/association_pks.rb +63 -18
- data/lib/sequel/plugins/auto_validations.rb +43 -9
- data/lib/sequel/plugins/class_table_inheritance.rb +236 -179
- data/lib/sequel/plugins/update_refresh.rb +26 -1
- data/lib/sequel/plugins/validation_helpers.rb +7 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/adapters/postgres_spec.rb +61 -0
- data/spec/core_extensions_spec.rb +5 -1
- data/spec/extensions/association_pks_spec.rb +73 -1
- data/spec/extensions/auto_validations_spec.rb +34 -0
- data/spec/extensions/class_table_inheritance_spec.rb +58 -54
- data/spec/extensions/pg_inet_ops_spec.rb +101 -0
- data/spec/extensions/spec_helper.rb +5 -5
- data/spec/extensions/update_refresh_spec.rb +12 -0
- data/spec/extensions/validation_helpers_spec.rb +7 -0
- data/spec/integration/plugin_test.rb +48 -13
- metadata +6 -4
- data/lib/sequel/adapters/db2.rb +0 -229
- data/lib/sequel/adapters/dbi.rb +0 -102
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ce66a463879671227d5446f7e224b1610bccd9f
|
4
|
+
data.tar.gz: e16b849b789b960f5c6d86dd7049a61ebe42c169
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ac3191f57bffb08c000deef706301c4b6628cb707ef9f870df162d7d55d3ed21982f931c3b9bbc3658cf4a693e7aa2b45d8a3dd1c62a0345d9d2d88dd7dc391
|
7
|
+
data.tar.gz: d05096b10746ea930ecd79f8cde66e295b9b5e99002c64df479369473a1bb603b36c9a69ce2462fecd33c1dc3217705bac651d590dca4c58a85edd44b1c515b3
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
=== 4.24.0 (2015-07-01)
|
2
|
+
|
3
|
+
* Allow class_table_inheritance plugin to support subclasses that don't add additional columns (QuinnHarris, jeremyevans) (#1030)
|
4
|
+
|
5
|
+
* Add :columns option to update_refresh plugin, specifying the columns to include in the RETURNING clause (celsworth) (#1029)
|
6
|
+
|
7
|
+
* Use column symbol key for auto validation unique errors if the unique index is on a single column (jeremyevans)
|
8
|
+
|
9
|
+
* Allow :timeout option to Database#listen in the postgres adapter to be a callable object (celsworth) (#1028)
|
10
|
+
|
11
|
+
* Add pg_inet_ops extension, for DSL support for PostgreSQL inet/cidr operators and functions (celsworth, jeremyevans) (#1024)
|
12
|
+
|
13
|
+
* Support :*_opts options in auto_validations plugin, for setting options for the underlying validation methods (celsworth, jeremyevans) (#1026)
|
14
|
+
|
15
|
+
* Support :delay_pks association option in association_pks to delay setting of associated_pks until after saving (jeremyevans)
|
16
|
+
|
17
|
+
* Make jdbc subadapters work if they issue queries while the subadapter is being loaded (jeremyevans) (#1022)
|
18
|
+
|
19
|
+
* Handle 64-bit auto incrementing primary keys in jdbc subadapters (DougEverly) (#1018, #1019)
|
20
|
+
|
21
|
+
* Remove the deprecated db2 and dbi adapters (jeremyevans)
|
22
|
+
|
23
|
+
* Make auto_validation plugin use :from=>:values option to setup validations on the underlying columns (jeremyevans)
|
24
|
+
|
25
|
+
* Add :from=>:values option to validation_helpers methods, for getting values from the values hash instead of a method call (jeremyevans)
|
26
|
+
|
1
27
|
=== 4.23.0 (2015-06-01)
|
2
28
|
|
3
29
|
* Make dataset.call_sproc(:insert) work in the jdbc adapter (flash-gordon) (#1013)
|
data/Rakefile
CHANGED
@@ -86,7 +86,7 @@ run_spec = proc do |patterns|
|
|
86
86
|
lib_dir = File.join(File.dirname(File.expand_path(__FILE__)), 'lib')
|
87
87
|
rubylib = ENV['RUBYLIB']
|
88
88
|
ENV['RUBYLIB'] ? (ENV['RUBYLIB'] += ":#{lib_dir}") : (ENV['RUBYLIB'] = lib_dir)
|
89
|
-
if RUBY_PLATFORM =~ /mingw32/
|
89
|
+
if RUBY_PLATFORM =~ /mingw32/ || RUBY_DESCRIPTION =~ /windows/i
|
90
90
|
patterns = patterns.split.map{|pat| Dir[pat].to_a}.flatten.join(' ')
|
91
91
|
end
|
92
92
|
sh "#{FileUtils::RUBY} -e \"ARGV.each{|f| require f}\" #{patterns}"
|
@@ -0,0 +1,99 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A pg_inet_ops extension has been added, for DSL support for
|
4
|
+
calling PostgreSQL inet functions and operators. Example:
|
5
|
+
|
6
|
+
r = Sequel.pg_inet_op(:inet)
|
7
|
+
|
8
|
+
~r # ~inet
|
9
|
+
r & :other # inet & other
|
10
|
+
r | :other # inet | other
|
11
|
+
r << :other # inet << other
|
12
|
+
r >> :other # inet >> other
|
13
|
+
|
14
|
+
r.contained_by(:other) # inet << other
|
15
|
+
r.contained_by_or_equals(:other) # inet <<= other
|
16
|
+
r.contains(:other) # inet >> other
|
17
|
+
r.contains_or_equals(:other) # inet >>= other
|
18
|
+
r.contains_or_contained_by(:other) # inet && other
|
19
|
+
|
20
|
+
r.abbrev # abbrev(inet)
|
21
|
+
r.broadcast # broadcast(inet)
|
22
|
+
r.family # family(inet)
|
23
|
+
r.host # host(inet)
|
24
|
+
r.hostmask # hostmask(inet)
|
25
|
+
r.masklen # masklen(inet)
|
26
|
+
r.netmask # netmask(inet)
|
27
|
+
r.network # network(inet)
|
28
|
+
r.set_masklen(16) # set_masklen(inet, 16)
|
29
|
+
r.text # text(inet)
|
30
|
+
|
31
|
+
* The association_pks plugin now supports a :delay_pks association
|
32
|
+
option. When set to true, this makes the methods created by the
|
33
|
+
plugin usable on new objects, by delaying the saving of the
|
34
|
+
associated pks until after the new object has been saved. When
|
35
|
+
set to :always, this also changes the behavior of the methods
|
36
|
+
for existing objects, so that nothing is persisted until the
|
37
|
+
object has been saved. Example:
|
38
|
+
|
39
|
+
Album.plugin :association_pks
|
40
|
+
Album.many_to_many :tags, :delay_pks=>true
|
41
|
+
|
42
|
+
album = Album.new(:tag_pks=>[1,2,3]) # No database query
|
43
|
+
album.save # Queries to insert album, and then update albums_tags
|
44
|
+
|
45
|
+
* The class_table_inheritance plugin now supports subclasses that
|
46
|
+
don't require additional columns, and therefore do not need to
|
47
|
+
join to additional tables. It now loads the
|
48
|
+
single_table_inheritance plugin and supports options that were
|
49
|
+
previously only supported by single_table_inheritance, such as the
|
50
|
+
:key_map and :key_chooser options.
|
51
|
+
|
52
|
+
* The validation_helpers plugin now supports a :from=>:values option
|
53
|
+
in the validation methods, which will take the value directly from
|
54
|
+
the values hash instead of calling the related method. This
|
55
|
+
allows validation_helpers to differentiate between validations on
|
56
|
+
underlying database column and validations on the model.
|
57
|
+
|
58
|
+
The auto_validations plugin has been modified to use this feature,
|
59
|
+
since all validations it generates are for validations on the
|
60
|
+
underlying database columns.
|
61
|
+
|
62
|
+
* The auto_validations plugin now supports options to pass to each
|
63
|
+
of the underlying validation methods:
|
64
|
+
|
65
|
+
Sequel::Model.plugin :auto_validations,
|
66
|
+
:unique_opts=>{:only_if_modified=>true}
|
67
|
+
|
68
|
+
In addition to :unique_opts, there is support for :not_null_opts
|
69
|
+
(for NOT NULL columns without a default), :explicit_not_null_opts
|
70
|
+
(for NOT NULL columns with a default), :max_length_opts, and
|
71
|
+
:schema_types_opts.
|
72
|
+
|
73
|
+
* The update_refresh plugin now accepts a :columns option, which
|
74
|
+
specifies the columns to refresh. This option is currently only
|
75
|
+
respected if the related dataset supports RETURNING.
|
76
|
+
|
77
|
+
* The :timeout option to Database#listen in the postgres adapter can
|
78
|
+
now be a callable object, previously it had to be Numeric. This
|
79
|
+
allows you to dynamically change the timeout based on current
|
80
|
+
application state.
|
81
|
+
|
82
|
+
= Other Improvements
|
83
|
+
|
84
|
+
* The uniqueness validations added by the auto_validations plugin now
|
85
|
+
use a symbol key in the related Errors instance if the underlying
|
86
|
+
index was on a single column. Previously, the uniqueness
|
87
|
+
validations for a single column would use an array key in the
|
88
|
+
related Errors instance.
|
89
|
+
|
90
|
+
* The jdbc subadapters now correctly handle 64-bit autoincrementing
|
91
|
+
primary keys.
|
92
|
+
|
93
|
+
* The jdbc subadapters now work correctly if they issue queries while
|
94
|
+
the subadapter is being loaded. This can happen in the
|
95
|
+
jdbc/postgresql adapter if the pg_hstore extension is used.
|
96
|
+
|
97
|
+
= Backwards Compatibility
|
98
|
+
|
99
|
+
* The deprecated db2 and dbi adapters have been removed.
|
data/doc/sql.rdoc
CHANGED
@@ -237,6 +237,15 @@ If the database supports schema qualified functions, Sequel can handle them by c
|
|
237
237
|
DB[:albums].select{schema__function.function(col, 2, "a")}
|
238
238
|
# SELECT schema.function(col, 2, 'a') FROM albums
|
239
239
|
|
240
|
+
=== Portable/Emulated Functions
|
241
|
+
|
242
|
+
Sequel offers some support for portable SQL functions, allowing you to call standard SQL functions, where Sequel will emulate support on databases that lack native support.
|
243
|
+
Some examples are:
|
244
|
+
|
245
|
+
Sequel.char_length(:column) # char_length(column)
|
246
|
+
Sequel.extract(:year, :column) # extract(year FROM column)
|
247
|
+
Sequel.trim(:column) # trim(column)
|
248
|
+
|
240
249
|
=== Equality Operator (=)
|
241
250
|
|
242
251
|
Sequel uses hashes to specify equality:
|
@@ -506,7 +515,7 @@ Note that using +ilike+ with a regular expression will always make the regexp ca
|
|
506
515
|
|
507
516
|
=== Order Specifications (ASC, DESC)
|
508
517
|
|
509
|
-
Sequel supports specifying ascending or descending order using the asc+ and +desc+ method on most Sequel-specific expression objects:
|
518
|
+
Sequel supports specifying ascending or descending order using the +asc+ and +desc+ method on most Sequel-specific expression objects:
|
510
519
|
|
511
520
|
Sequel.expr(:column).asc # "column" ASC
|
512
521
|
Sequel.expr(:column).qualify(:table).desc # "table"."column" DESC
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -354,6 +354,7 @@ module Sequel
|
|
354
354
|
raise(Error, "No connection string specified") unless uri
|
355
355
|
|
356
356
|
resolved_uri = jndi? ? get_uri_from_jndi : uri
|
357
|
+
setup_type_convertor_map_early
|
357
358
|
|
358
359
|
@driver = if (match = /\Ajdbc:([^:]+)/.match(resolved_uri)) && (prok = Sequel::Database.load_adapter(match[1].to_sym, :map=>DATABASE_SETUP, :subdir=>'jdbc'))
|
359
360
|
prok.call(self)
|
@@ -640,7 +641,13 @@ module Sequel
|
|
640
641
|
h[:table_schem] == 'INFORMATION_SCHEMA'
|
641
642
|
end
|
642
643
|
|
644
|
+
# Called after loading subadapter-specific code, overridable by subadapters.
|
643
645
|
def setup_type_convertor_map
|
646
|
+
end
|
647
|
+
|
648
|
+
# Called before loading subadapter-specific code, necessary so that subadapter initialization code
|
649
|
+
# that runs queries works correctly. This cannot be overriding in subadapters,
|
650
|
+
def setup_type_convertor_map_early
|
644
651
|
@type_convertor_map = TypeConvertor::MAP.merge(Java::JavaSQL::Types::TIMESTAMP=>timestamp_convertor)
|
645
652
|
@basic_type_convertor_map = TypeConvertor::BASIC_MAP
|
646
653
|
end
|
@@ -46,7 +46,7 @@ module Sequel
|
|
46
46
|
rs = stmt.getGeneratedKeys
|
47
47
|
begin
|
48
48
|
if rs.next
|
49
|
-
rs.
|
49
|
+
rs.getLong(1)
|
50
50
|
else
|
51
51
|
0
|
52
52
|
end
|
@@ -57,7 +57,7 @@ module Sequel
|
|
57
57
|
statement(conn) do |st|
|
58
58
|
rs = st.executeQuery(LAST_INSERT_ID)
|
59
59
|
rs.next
|
60
|
-
rs.
|
60
|
+
rs.getLong(1)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
@@ -439,14 +439,16 @@ module Sequel
|
|
439
439
|
# :after_listen :: An object that responds to +call+ that is called with the underlying connection after the LISTEN
|
440
440
|
# statement is sent, but before the connection starts waiting for notifications.
|
441
441
|
# :loop :: Whether to continually wait for notifications, instead of just waiting for a single
|
442
|
-
# notification. If this option is given, a block must be provided. If this object responds to call
|
442
|
+
# notification. If this option is given, a block must be provided. If this object responds to +call+, it is
|
443
443
|
# called with the underlying connection after each notification is received (after the block is called).
|
444
444
|
# If a :timeout option is used, and a callable object is given, the object will also be called if the
|
445
445
|
# timeout expires. If :loop is used and you want to stop listening, you can either break from inside the
|
446
446
|
# block given to #listen, or you can throw :stop from inside the :loop object's call method or the block.
|
447
447
|
# :server :: The server on which to listen, if the sharding support is being used.
|
448
|
-
# :timeout :: How long to wait for a notification, in seconds (can provide a float value for
|
449
|
-
#
|
448
|
+
# :timeout :: How long to wait for a notification, in seconds (can provide a float value for fractional seconds).
|
449
|
+
# If this object responds to +call+, it will be called and should return the number of seconds to wait.
|
450
|
+
# If the loop option is also specified, the object will be called on each iteration to obtain a new
|
451
|
+
# timeout value. If not given or nil, waits indefinitely.
|
450
452
|
#
|
451
453
|
# This method is only supported if pg is used as the underlying ruby driver. It returns the
|
452
454
|
# channel the notification was sent to (as a string), unless :loop was used, in which case it returns nil.
|
@@ -465,19 +467,25 @@ module Sequel
|
|
465
467
|
conn.execute(sql)
|
466
468
|
end
|
467
469
|
opts[:after_listen].call(conn) if opts[:after_listen]
|
468
|
-
timeout = opts[:timeout]
|
470
|
+
timeout = opts[:timeout]
|
471
|
+
if timeout
|
472
|
+
timeout_block = timeout.respond_to?(:call) ? timeout : proc{timeout}
|
473
|
+
end
|
474
|
+
|
469
475
|
if l = opts[:loop]
|
470
476
|
raise Error, 'calling #listen with :loop requires a block' unless block
|
471
477
|
loop_call = l.respond_to?(:call)
|
472
478
|
catch(:stop) do
|
473
479
|
loop do
|
474
|
-
|
480
|
+
t = timeout_block ? [timeout_block.call] : []
|
481
|
+
conn.wait_for_notify(*t, &block)
|
475
482
|
l.call(conn) if loop_call
|
476
483
|
end
|
477
484
|
end
|
478
485
|
nil
|
479
486
|
else
|
480
|
-
|
487
|
+
t = timeout_block ? [timeout_block.call] : []
|
488
|
+
conn.wait_for_notify(*t, &block)
|
481
489
|
end
|
482
490
|
ensure
|
483
491
|
conn.execute("UNLISTEN *")
|
@@ -37,7 +37,7 @@ module Sequel
|
|
37
37
|
# Execute the given stored procedure with the given name.
|
38
38
|
#
|
39
39
|
# Options:
|
40
|
-
# :args :: Arguments to stored procedure. For named
|
40
|
+
# :args :: Arguments to stored procedure. For named arguments, this should be a
|
41
41
|
# hash keyed by argument named. For unnamed arguments, this should be an
|
42
42
|
# array. Output parameters to the function are specified using :output.
|
43
43
|
# You can also name output parameters and provide a type by using an
|
data/lib/sequel/core.rb
CHANGED
@@ -84,11 +84,22 @@ module Sequel
|
|
84
84
|
# DB = Sequel.connect('postgres://user:password@host:port/database_name')
|
85
85
|
# DB = Sequel.connect('sqlite:///blog.db', :max_connections=>10)
|
86
86
|
#
|
87
|
+
# You can also pass a single options hash:
|
88
|
+
#
|
89
|
+
# DB = Sequel.connect(:adapter=>'sqlite', :database=>'./blog.db')
|
90
|
+
#
|
87
91
|
# If a block is given, it is passed the opened +Database+ object, which is
|
88
92
|
# closed when the block exits. For example:
|
89
93
|
#
|
90
94
|
# Sequel.connect('sqlite://blog.db'){|db| puts db[:users].count}
|
91
|
-
#
|
95
|
+
#
|
96
|
+
# If a block is not given, a reference to this database will be held in
|
97
|
+
# <tt>Sequel::DATABASES</tt> until it is removed manually. This is by
|
98
|
+
# design, and used by <tt>Sequel::Model</tt> to pick the default
|
99
|
+
# database. It is recommended to pass a block if you do not want the
|
100
|
+
# resulting Database object to remain in memory until the process
|
101
|
+
# terminates.
|
102
|
+
#
|
92
103
|
# For details, see the {"Connecting to a Database" guide}[rdoc-ref:doc/opening_databases.rdoc].
|
93
104
|
# To set up a master/slave or sharded database connection, see the {"Master/Slave Databases and Sharding" guide}[rdoc-ref:doc/sharding.rdoc].
|
94
105
|
def self.connect(*args, &block)
|
@@ -6,7 +6,7 @@ module Sequel
|
|
6
6
|
# ---------------------
|
7
7
|
|
8
8
|
# Array of supported database adapters
|
9
|
-
ADAPTERS = %w'ado amalgalite cubrid
|
9
|
+
ADAPTERS = %w'ado amalgalite cubrid do firebird ibmdb informix jdbc mock mysql mysql2 odbc oracle postgres sqlanywhere sqlite swift tinytds'.collect(&:to_sym)
|
10
10
|
|
11
11
|
@single_threaded = false
|
12
12
|
|
@@ -42,7 +42,6 @@ module Sequel
|
|
42
42
|
else
|
43
43
|
uri = URI.parse(conn_string)
|
44
44
|
scheme = uri.scheme
|
45
|
-
scheme = :dbi if scheme =~ /\Adbi-/
|
46
45
|
c = adapter_class(scheme)
|
47
46
|
uri_options = c.send(:uri_to_options, uri)
|
48
47
|
uri.query.split('&').collect{|s| s.split('=')}.each{|k,v| uri_options[k.to_sym] = v if k && !k.empty?} unless uri.query.to_s.strip.empty?
|
@@ -0,0 +1,200 @@
|
|
1
|
+
# The pg_inet_ops extension adds support to Sequel's DSL to make
|
2
|
+
# it easier to call PostgreSQL inet functions and operators.
|
3
|
+
#
|
4
|
+
# To load the extension:
|
5
|
+
#
|
6
|
+
# Sequel.extension :pg_inet_ops
|
7
|
+
#
|
8
|
+
# The most common usage is passing an expression to Sequel.pg_inet_op:
|
9
|
+
#
|
10
|
+
# r = Sequel.pg_inet_op(:inet)
|
11
|
+
#
|
12
|
+
# Also, on most Sequel expression objects, you can call the pg_inet
|
13
|
+
# method:
|
14
|
+
#
|
15
|
+
# r = Sequel.expr(:ip).pg_inet
|
16
|
+
#
|
17
|
+
# If you have loaded the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
|
18
|
+
# or you have loaded the core_refinements extension
|
19
|
+
# and have activated refinements for the file, you can also use Symbol#pg_inet:
|
20
|
+
#
|
21
|
+
# r = :inet.pg_inet
|
22
|
+
#
|
23
|
+
# This creates a Sequel::Postgres::InetOp object that can be used
|
24
|
+
# for easier querying:
|
25
|
+
#
|
26
|
+
# ~r # ~inet
|
27
|
+
# r & other # inet & other
|
28
|
+
# r | other # inet | other
|
29
|
+
# r << :other # inet << other
|
30
|
+
# r >> :other # inet >> other
|
31
|
+
#
|
32
|
+
# r.contained_by(:other) # inet << other
|
33
|
+
# r.contained_by_or_equals(:other) # inet <<= other
|
34
|
+
# r.contains(:other) # inet >> other
|
35
|
+
# r.contains_or_equals(:other) # inet >>= other
|
36
|
+
# r.contains_or_contained_by(:other) # inet && other
|
37
|
+
#
|
38
|
+
# r.abbrev # abbrev(inet)
|
39
|
+
# r.broadcast # broadcast(inet)
|
40
|
+
# r.family # family(inet)
|
41
|
+
# r.host # host(inet)
|
42
|
+
# r.hostmask # hostmask(inet)
|
43
|
+
# r.masklen # masklen(inet)
|
44
|
+
# r.netmask # netmask(inet)
|
45
|
+
# r.network # network(inet)
|
46
|
+
# r.set_masklen(16) # set_masklen(inet, 16)
|
47
|
+
# r.text # text(inet)
|
48
|
+
#
|
49
|
+
# If a String or IPAddr instance is passed to Sequel.pg_inet_op, it will automatically
|
50
|
+
# be cast to +inet+. To treat the object as a +cidr+, you must cast it before passing
|
51
|
+
# it to Sequel.pg_inet_op:
|
52
|
+
#
|
53
|
+
# r = Sequel.pg_inet_op(Sequel.cast('1.2.3.4', :cidr))
|
54
|
+
#
|
55
|
+
# See the PostgreSQL network function and operator documentation for more
|
56
|
+
# details on what these functions and operators do.
|
57
|
+
|
58
|
+
require 'ipaddr'
|
59
|
+
|
60
|
+
module Sequel
|
61
|
+
module Postgres
|
62
|
+
# The InetOp class is a simple container for a single object that
|
63
|
+
# defines methods that yield Sequel expression objects representing
|
64
|
+
# PostgreSQL inet operators and functions.
|
65
|
+
#
|
66
|
+
# Most methods in this class are defined via metaprogramming, see
|
67
|
+
# the pg_inet_ops extension documentation for details on the API.
|
68
|
+
class InetOp < Sequel::SQL::Wrapper
|
69
|
+
include Sequel::SQL::BitwiseMethods
|
70
|
+
|
71
|
+
# For String and IPAddr instances, wrap them in a cast to inet,
|
72
|
+
# to avoid ambiguity issues when calling operator methods.
|
73
|
+
def initialize(v)
|
74
|
+
case v
|
75
|
+
when ::Sequel::LiteralString
|
76
|
+
# nothing
|
77
|
+
when String, IPAddr
|
78
|
+
v = Sequel.cast(v, :inet)
|
79
|
+
end
|
80
|
+
super
|
81
|
+
end
|
82
|
+
|
83
|
+
OPERATORS = {
|
84
|
+
:contained_by_or_equals => ["(".freeze, " <<= ".freeze, ")".freeze].freeze,
|
85
|
+
:contains_or_equals => ["(".freeze, " >>= ".freeze, ")".freeze].freeze,
|
86
|
+
:contains_or_contained_by => ["(".freeze, " && ".freeze, ")".freeze].freeze,
|
87
|
+
}.freeze
|
88
|
+
|
89
|
+
OPERATORS.keys.each do |f|
|
90
|
+
class_eval("def #{f}(v) Sequel::SQL::BooleanExpression.new(:NOOP, operator(:#{f}, v)) end", __FILE__, __LINE__)
|
91
|
+
end
|
92
|
+
|
93
|
+
%w'<< >>'.each do |f|
|
94
|
+
class_eval("def #{f}(v) Sequel::SQL::BooleanExpression.new(:NOOP, super) end", __FILE__, __LINE__)
|
95
|
+
end
|
96
|
+
|
97
|
+
%w'& | +'.each do |f|
|
98
|
+
class_eval("def #{f}(v) self.class.new(super) end", __FILE__, __LINE__)
|
99
|
+
end
|
100
|
+
|
101
|
+
%w'abbrev host text'.each do |f|
|
102
|
+
class_eval("def #{f}() Sequel::SQL::StringExpression.new(:NOOP, function(:#{f})) end", __FILE__, __LINE__)
|
103
|
+
end
|
104
|
+
|
105
|
+
%w'family masklen'.each do |f|
|
106
|
+
class_eval("def #{f}() Sequel::SQL::NumericExpression.new(:NOOP, function(:#{f})) end", __FILE__, __LINE__)
|
107
|
+
end
|
108
|
+
|
109
|
+
%w'broadcast hostmask netmask network'.each do |f|
|
110
|
+
class_eval("def #{f}() self.class.new(function(:#{f})) end", __FILE__, __LINE__)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Return the receiver.
|
114
|
+
def pg_inet
|
115
|
+
self
|
116
|
+
end
|
117
|
+
|
118
|
+
# Return an expression for the bitwise NOT of the receiver
|
119
|
+
def ~
|
120
|
+
self.class.new(super)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Return an expression for the subtraction of the argument from the receiver
|
124
|
+
def -(v)
|
125
|
+
case v
|
126
|
+
when Integer
|
127
|
+
self.class.new(super)
|
128
|
+
else
|
129
|
+
Sequel::SQL::NumericExpression.new(:NOOP, super)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Return an expression for the calling of the set_masklen function with the receiver and the given argument
|
134
|
+
def set_masklen(v)
|
135
|
+
self.class.new(Sequel::SQL::Function.new(:set_masklen, self, v))
|
136
|
+
end
|
137
|
+
|
138
|
+
alias contained_by <<
|
139
|
+
alias contains >>
|
140
|
+
|
141
|
+
undef_method :*, :/
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
# Handle PostgreSQL specific operator types
|
146
|
+
def operator(type, other)
|
147
|
+
Sequel::SQL::PlaceholderLiteralString.new(OPERATORS[type], [value, other])
|
148
|
+
end
|
149
|
+
|
150
|
+
# Return a function called with the receiver.
|
151
|
+
def function(name)
|
152
|
+
Sequel::SQL::Function.new(name, self)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
module InetOpMethods
|
157
|
+
# Wrap the receiver in an InetOp so you can easily use the PostgreSQL
|
158
|
+
# inet functions and operators with it.
|
159
|
+
def pg_inet
|
160
|
+
InetOp.new(self)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
module SQL::Builders
|
166
|
+
# Return the expression wrapped in the Postgres::InetOp.
|
167
|
+
def pg_inet_op(v)
|
168
|
+
case v
|
169
|
+
when Postgres::InetOp
|
170
|
+
v
|
171
|
+
else
|
172
|
+
Postgres::InetOp.new(v)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class SQL::GenericExpression
|
178
|
+
include Sequel::Postgres::InetOpMethods
|
179
|
+
end
|
180
|
+
|
181
|
+
class LiteralString
|
182
|
+
include Sequel::Postgres::InetOpMethods
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# :nocov:
|
187
|
+
if Sequel.core_extensions?
|
188
|
+
class Symbol
|
189
|
+
include Sequel::Postgres::InetOpMethods
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
if defined?(Sequel::CoreRefinements)
|
194
|
+
module Sequel::CoreRefinements
|
195
|
+
refine Symbol do
|
196
|
+
include Sequel::Postgres::InetOpMethods
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
# :nocov:
|