viking-sequel 3.10.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.
- data/CHANGELOG +3134 -0
- data/COPYING +19 -0
- data/README.rdoc +723 -0
- data/Rakefile +193 -0
- data/bin/sequel +196 -0
- data/doc/advanced_associations.rdoc +644 -0
- data/doc/cheat_sheet.rdoc +218 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/dataset_filtering.rdoc +158 -0
- data/doc/opening_databases.rdoc +296 -0
- data/doc/prepared_statements.rdoc +104 -0
- data/doc/reflection.rdoc +84 -0
- data/doc/release_notes/1.0.txt +38 -0
- data/doc/release_notes/1.1.txt +143 -0
- data/doc/release_notes/1.3.txt +101 -0
- data/doc/release_notes/1.4.0.txt +53 -0
- data/doc/release_notes/1.5.0.txt +155 -0
- data/doc/release_notes/2.0.0.txt +298 -0
- data/doc/release_notes/2.1.0.txt +271 -0
- data/doc/release_notes/2.10.0.txt +328 -0
- data/doc/release_notes/2.11.0.txt +215 -0
- data/doc/release_notes/2.12.0.txt +534 -0
- data/doc/release_notes/2.2.0.txt +253 -0
- data/doc/release_notes/2.3.0.txt +88 -0
- data/doc/release_notes/2.4.0.txt +106 -0
- data/doc/release_notes/2.5.0.txt +137 -0
- data/doc/release_notes/2.6.0.txt +157 -0
- data/doc/release_notes/2.7.0.txt +166 -0
- data/doc/release_notes/2.8.0.txt +171 -0
- data/doc/release_notes/2.9.0.txt +97 -0
- data/doc/release_notes/3.0.0.txt +221 -0
- data/doc/release_notes/3.1.0.txt +406 -0
- data/doc/release_notes/3.10.0.txt +286 -0
- data/doc/release_notes/3.2.0.txt +268 -0
- data/doc/release_notes/3.3.0.txt +192 -0
- data/doc/release_notes/3.4.0.txt +325 -0
- data/doc/release_notes/3.5.0.txt +510 -0
- data/doc/release_notes/3.6.0.txt +366 -0
- data/doc/release_notes/3.7.0.txt +179 -0
- data/doc/release_notes/3.8.0.txt +151 -0
- data/doc/release_notes/3.9.0.txt +233 -0
- data/doc/schema.rdoc +36 -0
- data/doc/sharding.rdoc +113 -0
- data/doc/virtual_rows.rdoc +205 -0
- data/lib/sequel.rb +1 -0
- data/lib/sequel/adapters/ado.rb +90 -0
- data/lib/sequel/adapters/ado/mssql.rb +30 -0
- data/lib/sequel/adapters/amalgalite.rb +176 -0
- data/lib/sequel/adapters/db2.rb +139 -0
- data/lib/sequel/adapters/dbi.rb +113 -0
- data/lib/sequel/adapters/do.rb +188 -0
- data/lib/sequel/adapters/do/mysql.rb +49 -0
- data/lib/sequel/adapters/do/postgres.rb +91 -0
- data/lib/sequel/adapters/do/sqlite.rb +40 -0
- data/lib/sequel/adapters/firebird.rb +283 -0
- data/lib/sequel/adapters/informix.rb +77 -0
- data/lib/sequel/adapters/jdbc.rb +587 -0
- data/lib/sequel/adapters/jdbc/as400.rb +58 -0
- data/lib/sequel/adapters/jdbc/h2.rb +133 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
- data/lib/sequel/adapters/mysql.rb +421 -0
- data/lib/sequel/adapters/odbc.rb +143 -0
- data/lib/sequel/adapters/odbc/mssql.rb +42 -0
- data/lib/sequel/adapters/openbase.rb +64 -0
- data/lib/sequel/adapters/oracle.rb +131 -0
- data/lib/sequel/adapters/postgres.rb +504 -0
- data/lib/sequel/adapters/shared/mssql.rb +490 -0
- data/lib/sequel/adapters/shared/mysql.rb +498 -0
- data/lib/sequel/adapters/shared/oracle.rb +195 -0
- data/lib/sequel/adapters/shared/postgres.rb +830 -0
- data/lib/sequel/adapters/shared/progress.rb +44 -0
- data/lib/sequel/adapters/shared/sqlite.rb +389 -0
- data/lib/sequel/adapters/sqlite.rb +224 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
- data/lib/sequel/connection_pool.rb +99 -0
- data/lib/sequel/connection_pool/sharded_single.rb +84 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
- data/lib/sequel/connection_pool/single.rb +29 -0
- data/lib/sequel/connection_pool/threaded.rb +150 -0
- data/lib/sequel/core.rb +293 -0
- data/lib/sequel/core_sql.rb +241 -0
- data/lib/sequel/database.rb +1079 -0
- data/lib/sequel/database/schema_generator.rb +327 -0
- data/lib/sequel/database/schema_methods.rb +203 -0
- data/lib/sequel/database/schema_sql.rb +320 -0
- data/lib/sequel/dataset.rb +32 -0
- data/lib/sequel/dataset/actions.rb +441 -0
- data/lib/sequel/dataset/features.rb +86 -0
- data/lib/sequel/dataset/graph.rb +254 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +227 -0
- data/lib/sequel/dataset/query.rb +709 -0
- data/lib/sequel/dataset/sql.rb +996 -0
- data/lib/sequel/exceptions.rb +51 -0
- data/lib/sequel/extensions/blank.rb +43 -0
- data/lib/sequel/extensions/inflector.rb +242 -0
- data/lib/sequel/extensions/looser_typecasting.rb +21 -0
- data/lib/sequel/extensions/migration.rb +239 -0
- data/lib/sequel/extensions/named_timezones.rb +61 -0
- data/lib/sequel/extensions/pagination.rb +100 -0
- data/lib/sequel/extensions/pretty_table.rb +82 -0
- data/lib/sequel/extensions/query.rb +52 -0
- data/lib/sequel/extensions/schema_dumper.rb +271 -0
- data/lib/sequel/extensions/sql_expr.rb +122 -0
- data/lib/sequel/extensions/string_date_time.rb +46 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
- data/lib/sequel/metaprogramming.rb +9 -0
- data/lib/sequel/model.rb +120 -0
- data/lib/sequel/model/associations.rb +1514 -0
- data/lib/sequel/model/base.rb +1069 -0
- data/lib/sequel/model/default_inflections.rb +45 -0
- data/lib/sequel/model/errors.rb +39 -0
- data/lib/sequel/model/exceptions.rb +21 -0
- data/lib/sequel/model/inflections.rb +162 -0
- data/lib/sequel/model/plugins.rb +70 -0
- data/lib/sequel/plugins/active_model.rb +59 -0
- data/lib/sequel/plugins/association_dependencies.rb +103 -0
- data/lib/sequel/plugins/association_proxies.rb +41 -0
- data/lib/sequel/plugins/boolean_readers.rb +53 -0
- data/lib/sequel/plugins/caching.rb +141 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
- data/lib/sequel/plugins/composition.rb +138 -0
- data/lib/sequel/plugins/force_encoding.rb +72 -0
- data/lib/sequel/plugins/hook_class_methods.rb +126 -0
- data/lib/sequel/plugins/identity_map.rb +116 -0
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/instance_hooks.rb +57 -0
- data/lib/sequel/plugins/lazy_attributes.rb +77 -0
- data/lib/sequel/plugins/many_through_many.rb +208 -0
- data/lib/sequel/plugins/nested_attributes.rb +206 -0
- data/lib/sequel/plugins/optimistic_locking.rb +81 -0
- data/lib/sequel/plugins/rcte_tree.rb +281 -0
- data/lib/sequel/plugins/schema.rb +66 -0
- data/lib/sequel/plugins/serialization.rb +166 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
- data/lib/sequel/plugins/subclasses.rb +45 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
- data/lib/sequel/plugins/timestamps.rb +87 -0
- data/lib/sequel/plugins/touch.rb +118 -0
- data/lib/sequel/plugins/typecast_on_load.rb +72 -0
- data/lib/sequel/plugins/validation_class_methods.rb +405 -0
- data/lib/sequel/plugins/validation_helpers.rb +223 -0
- data/lib/sequel/sql.rb +1020 -0
- data/lib/sequel/timezones.rb +161 -0
- data/lib/sequel/version.rb +12 -0
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/firebird_spec.rb +407 -0
- data/spec/adapters/informix_spec.rb +97 -0
- data/spec/adapters/mssql_spec.rb +403 -0
- data/spec/adapters/mysql_spec.rb +1019 -0
- data/spec/adapters/oracle_spec.rb +286 -0
- data/spec/adapters/postgres_spec.rb +969 -0
- data/spec/adapters/spec_helper.rb +51 -0
- data/spec/adapters/sqlite_spec.rb +432 -0
- data/spec/core/connection_pool_spec.rb +808 -0
- data/spec/core/core_sql_spec.rb +417 -0
- data/spec/core/database_spec.rb +1662 -0
- data/spec/core/dataset_spec.rb +3827 -0
- data/spec/core/expression_filters_spec.rb +595 -0
- data/spec/core/object_graph_spec.rb +296 -0
- data/spec/core/schema_generator_spec.rb +159 -0
- data/spec/core/schema_spec.rb +830 -0
- data/spec/core/spec_helper.rb +56 -0
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/active_model_spec.rb +76 -0
- data/spec/extensions/association_dependencies_spec.rb +127 -0
- data/spec/extensions/association_proxies_spec.rb +50 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/boolean_readers_spec.rb +92 -0
- data/spec/extensions/caching_spec.rb +250 -0
- data/spec/extensions/class_table_inheritance_spec.rb +252 -0
- data/spec/extensions/composition_spec.rb +194 -0
- data/spec/extensions/force_encoding_spec.rb +117 -0
- data/spec/extensions/hook_class_methods_spec.rb +470 -0
- data/spec/extensions/identity_map_spec.rb +202 -0
- data/spec/extensions/inflector_spec.rb +181 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/instance_hooks_spec.rb +133 -0
- data/spec/extensions/lazy_attributes_spec.rb +153 -0
- data/spec/extensions/looser_typecasting_spec.rb +39 -0
- data/spec/extensions/many_through_many_spec.rb +884 -0
- data/spec/extensions/migration_spec.rb +332 -0
- data/spec/extensions/named_timezones_spec.rb +72 -0
- data/spec/extensions/nested_attributes_spec.rb +396 -0
- data/spec/extensions/optimistic_locking_spec.rb +100 -0
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/extensions/rcte_tree_spec.rb +205 -0
- data/spec/extensions/schema_dumper_spec.rb +357 -0
- data/spec/extensions/schema_spec.rb +127 -0
- data/spec/extensions/serialization_spec.rb +209 -0
- data/spec/extensions/single_table_inheritance_spec.rb +96 -0
- data/spec/extensions/spec_helper.rb +91 -0
- data/spec/extensions/sql_expr_spec.rb +89 -0
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/extensions/subclasses_spec.rb +52 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
- data/spec/extensions/thread_local_timezones_spec.rb +45 -0
- data/spec/extensions/timestamps_spec.rb +150 -0
- data/spec/extensions/touch_spec.rb +155 -0
- data/spec/extensions/typecast_on_load_spec.rb +69 -0
- data/spec/extensions/validation_class_methods_spec.rb +984 -0
- data/spec/extensions/validation_helpers_spec.rb +438 -0
- data/spec/integration/associations_test.rb +281 -0
- data/spec/integration/database_test.rb +26 -0
- data/spec/integration/dataset_test.rb +963 -0
- data/spec/integration/eager_loader_test.rb +734 -0
- data/spec/integration/model_test.rb +130 -0
- data/spec/integration/plugin_test.rb +814 -0
- data/spec/integration/prepared_statement_test.rb +213 -0
- data/spec/integration/schema_test.rb +361 -0
- data/spec/integration/spec_helper.rb +73 -0
- data/spec/integration/timezone_test.rb +55 -0
- data/spec/integration/transaction_test.rb +122 -0
- data/spec/integration/type_test.rb +96 -0
- data/spec/model/association_reflection_spec.rb +175 -0
- data/spec/model/associations_spec.rb +2633 -0
- data/spec/model/base_spec.rb +418 -0
- data/spec/model/dataset_methods_spec.rb +78 -0
- data/spec/model/eager_loading_spec.rb +1391 -0
- data/spec/model/hooks_spec.rb +240 -0
- data/spec/model/inflector_spec.rb +26 -0
- data/spec/model/model_spec.rb +593 -0
- data/spec/model/plugins_spec.rb +236 -0
- data/spec/model/record_spec.rb +1500 -0
- data/spec/model/spec_helper.rb +97 -0
- data/spec/model/validations_spec.rb +153 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +346 -0
@@ -0,0 +1,595 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
Regexp.send(:include, Sequel::SQL::StringMethods)
|
4
|
+
String.send(:include, Sequel::SQL::StringMethods)
|
5
|
+
|
6
|
+
context "Blockless Ruby Filters" do
|
7
|
+
before do
|
8
|
+
db = Sequel::Database.new
|
9
|
+
db.quote_identifiers = false
|
10
|
+
@d = db[:items]
|
11
|
+
def @d.l(*args, &block)
|
12
|
+
literal(filter_expr(*args, &block))
|
13
|
+
end
|
14
|
+
def @d.lit(*args)
|
15
|
+
literal(*args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should support boolean columns directly" do
|
20
|
+
@d.l(:x).should == 'x'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should support NOT via Symbol#~" do
|
24
|
+
@d.l(~:x).should == 'NOT x'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should support qualified columns" do
|
28
|
+
@d.l(:x__y).should == 'x.y'
|
29
|
+
@d.l(~:x__y).should == 'NOT x.y'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should support NOT with SQL functions" do
|
33
|
+
@d.l(~:is_blah.sql_function).should == 'NOT is_blah()'
|
34
|
+
@d.l(~:is_blah.sql_function(:x)).should == 'NOT is_blah(x)'
|
35
|
+
@d.l(~:is_blah.sql_function(:x__y)).should == 'NOT is_blah(x.y)'
|
36
|
+
@d.l(~:is_blah.sql_function(:x, :x__y)).should == 'NOT is_blah(x, x.y)'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should handle multiple ~" do
|
40
|
+
@d.l(~~:x).should == 'x'
|
41
|
+
@d.l(~~~:x).should == 'NOT x'
|
42
|
+
@d.l(~~(:x & :y)).should == '(x AND y)'
|
43
|
+
@d.l(~~(:x | :y)).should == '(x OR y)'
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should support = via Hash" do
|
47
|
+
@d.l(:x => 100).should == '(x = 100)'
|
48
|
+
@d.l(:x => 'a').should == '(x = \'a\')'
|
49
|
+
@d.l(:x => true).should == '(x IS TRUE)'
|
50
|
+
@d.l(:x => false).should == '(x IS FALSE)'
|
51
|
+
@d.l(:x => nil).should == '(x IS NULL)'
|
52
|
+
@d.l(:x => [1,2,3]).should == '(x IN (1, 2, 3))'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should use = 't' and != 't' OR IS NULL if IS TRUE is not supported" do
|
56
|
+
@d.meta_def(:supports_is_true?){false}
|
57
|
+
@d.l(:x => true).should == "(x = 't')"
|
58
|
+
@d.l(~{:x => true}).should == "((x != 't') OR (x IS NULL))"
|
59
|
+
@d.l(:x => false).should == "(x = 'f')"
|
60
|
+
@d.l(~{:x => false}).should == "((x != 'f') OR (x IS NULL))"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should support != via Hash#~" do
|
64
|
+
@d.l(~{:x => 100}).should == '(x != 100)'
|
65
|
+
@d.l(~{:x => 'a'}).should == '(x != \'a\')'
|
66
|
+
@d.l(~{:x => true}).should == '(x IS NOT TRUE)'
|
67
|
+
@d.l(~{:x => false}).should == '(x IS NOT FALSE)'
|
68
|
+
@d.l(~{:x => nil}).should == '(x IS NOT NULL)'
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should support ~ via Hash and Regexp (if supported by database)" do
|
72
|
+
@d.l(:x => /blah/).should == '(x ~ \'blah\')'
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should support !~ via Hash#~ and Regexp" do
|
76
|
+
@d.l(~{:x => /blah/}).should == '(x !~ \'blah\')'
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should support LIKE via Symbol#like" do
|
80
|
+
@d.l(:x.like('a')).should == '(x LIKE \'a\')'
|
81
|
+
@d.l(:x.like(/a/)).should == '(x ~ \'a\')'
|
82
|
+
@d.l(:x.like('a', 'b')).should == '((x LIKE \'a\') OR (x LIKE \'b\'))'
|
83
|
+
@d.l(:x.like(/a/, /b/i)).should == '((x ~ \'a\') OR (x ~* \'b\'))'
|
84
|
+
@d.l(:x.like('a', /b/)).should == '((x LIKE \'a\') OR (x ~ \'b\'))'
|
85
|
+
|
86
|
+
@d.l('a'.like(:x)).should == "('a' LIKE x)"
|
87
|
+
@d.l('a'.like(:x, 'b')).should == "(('a' LIKE x) OR ('a' LIKE 'b'))"
|
88
|
+
@d.l('a'.like(:x, /b/)).should == "(('a' LIKE x) OR ('a' ~ 'b'))"
|
89
|
+
@d.l('a'.like(:x, /b/i)).should == "(('a' LIKE x) OR ('a' ~* 'b'))"
|
90
|
+
|
91
|
+
@d.l(/a/.like(:x)).should == "('a' ~ x)"
|
92
|
+
@d.l(/a/.like(:x, 'b')).should == "(('a' ~ x) OR ('a' ~ 'b'))"
|
93
|
+
@d.l(/a/.like(:x, /b/)).should == "(('a' ~ x) OR ('a' ~ 'b'))"
|
94
|
+
@d.l(/a/.like(:x, /b/i)).should == "(('a' ~ x) OR ('a' ~* 'b'))"
|
95
|
+
|
96
|
+
@d.l(/a/i.like(:x)).should == "('a' ~* x)"
|
97
|
+
@d.l(/a/i.like(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
98
|
+
@d.l(/a/i.like(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
99
|
+
@d.l(/a/i.like(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should support NOT LIKE via Symbol#like and Symbol#~" do
|
103
|
+
@d.l(~:x.like('a')).should == '(x NOT LIKE \'a\')'
|
104
|
+
@d.l(~:x.like(/a/)).should == '(x !~ \'a\')'
|
105
|
+
@d.l(~:x.like('a', 'b')).should == '((x NOT LIKE \'a\') AND (x NOT LIKE \'b\'))'
|
106
|
+
@d.l(~:x.like(/a/, /b/i)).should == '((x !~ \'a\') AND (x !~* \'b\'))'
|
107
|
+
@d.l(~:x.like('a', /b/)).should == '((x NOT LIKE \'a\') AND (x !~ \'b\'))'
|
108
|
+
|
109
|
+
@d.l(~'a'.like(:x)).should == "('a' NOT LIKE x)"
|
110
|
+
@d.l(~'a'.like(:x, 'b')).should == "(('a' NOT LIKE x) AND ('a' NOT LIKE 'b'))"
|
111
|
+
@d.l(~'a'.like(:x, /b/)).should == "(('a' NOT LIKE x) AND ('a' !~ 'b'))"
|
112
|
+
@d.l(~'a'.like(:x, /b/i)).should == "(('a' NOT LIKE x) AND ('a' !~* 'b'))"
|
113
|
+
|
114
|
+
@d.l(~/a/.like(:x)).should == "('a' !~ x)"
|
115
|
+
@d.l(~/a/.like(:x, 'b')).should == "(('a' !~ x) AND ('a' !~ 'b'))"
|
116
|
+
@d.l(~/a/.like(:x, /b/)).should == "(('a' !~ x) AND ('a' !~ 'b'))"
|
117
|
+
@d.l(~/a/.like(:x, /b/i)).should == "(('a' !~ x) AND ('a' !~* 'b'))"
|
118
|
+
|
119
|
+
@d.l(~/a/i.like(:x)).should == "('a' !~* x)"
|
120
|
+
@d.l(~/a/i.like(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
121
|
+
@d.l(~/a/i.like(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
122
|
+
@d.l(~/a/i.like(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should support ILIKE via Symbol#ilike" do
|
126
|
+
@d.l(:x.ilike('a')).should == '(x ILIKE \'a\')'
|
127
|
+
@d.l(:x.ilike(/a/)).should == '(x ~* \'a\')'
|
128
|
+
@d.l(:x.ilike('a', 'b')).should == '((x ILIKE \'a\') OR (x ILIKE \'b\'))'
|
129
|
+
@d.l(:x.ilike(/a/, /b/i)).should == '((x ~* \'a\') OR (x ~* \'b\'))'
|
130
|
+
@d.l(:x.ilike('a', /b/)).should == '((x ILIKE \'a\') OR (x ~* \'b\'))'
|
131
|
+
|
132
|
+
@d.l('a'.ilike(:x)).should == "('a' ILIKE x)"
|
133
|
+
@d.l('a'.ilike(:x, 'b')).should == "(('a' ILIKE x) OR ('a' ILIKE 'b'))"
|
134
|
+
@d.l('a'.ilike(:x, /b/)).should == "(('a' ILIKE x) OR ('a' ~* 'b'))"
|
135
|
+
@d.l('a'.ilike(:x, /b/i)).should == "(('a' ILIKE x) OR ('a' ~* 'b'))"
|
136
|
+
|
137
|
+
@d.l(/a/.ilike(:x)).should == "('a' ~* x)"
|
138
|
+
@d.l(/a/.ilike(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
139
|
+
@d.l(/a/.ilike(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
140
|
+
@d.l(/a/.ilike(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
141
|
+
|
142
|
+
@d.l(/a/i.ilike(:x)).should == "('a' ~* x)"
|
143
|
+
@d.l(/a/i.ilike(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
144
|
+
@d.l(/a/i.ilike(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
145
|
+
@d.l(/a/i.ilike(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should support NOT ILIKE via Symbol#ilike and Symbol#~" do
|
149
|
+
@d.l(~:x.ilike('a')).should == '(x NOT ILIKE \'a\')'
|
150
|
+
@d.l(~:x.ilike(/a/)).should == '(x !~* \'a\')'
|
151
|
+
@d.l(~:x.ilike('a', 'b')).should == '((x NOT ILIKE \'a\') AND (x NOT ILIKE \'b\'))'
|
152
|
+
@d.l(~:x.ilike(/a/, /b/i)).should == '((x !~* \'a\') AND (x !~* \'b\'))'
|
153
|
+
@d.l(~:x.ilike('a', /b/)).should == '((x NOT ILIKE \'a\') AND (x !~* \'b\'))'
|
154
|
+
|
155
|
+
@d.l(~'a'.ilike(:x)).should == "('a' NOT ILIKE x)"
|
156
|
+
@d.l(~'a'.ilike(:x, 'b')).should == "(('a' NOT ILIKE x) AND ('a' NOT ILIKE 'b'))"
|
157
|
+
@d.l(~'a'.ilike(:x, /b/)).should == "(('a' NOT ILIKE x) AND ('a' !~* 'b'))"
|
158
|
+
@d.l(~'a'.ilike(:x, /b/i)).should == "(('a' NOT ILIKE x) AND ('a' !~* 'b'))"
|
159
|
+
|
160
|
+
@d.l(~/a/.ilike(:x)).should == "('a' !~* x)"
|
161
|
+
@d.l(~/a/.ilike(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
162
|
+
@d.l(~/a/.ilike(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
163
|
+
@d.l(~/a/.ilike(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
164
|
+
|
165
|
+
@d.l(~/a/i.ilike(:x)).should == "('a' !~* x)"
|
166
|
+
@d.l(~/a/i.ilike(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
167
|
+
@d.l(~/a/i.ilike(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
168
|
+
@d.l(~/a/i.ilike(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should support negating ranges via Hash#~ and Range" do
|
172
|
+
@d.l(~{:x => 1..5}).should == '((x < 1) OR (x > 5))'
|
173
|
+
@d.l(~{:x => 1...5}).should == '((x < 1) OR (x >= 5))'
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should support negating NOT IN via Hash#~ and Dataset or Array" do
|
177
|
+
@d.l(~{:x => @d.select(:i)}).should == '(x NOT IN (SELECT i FROM items))'
|
178
|
+
@d.l(~{:x => [1,2,3]}).should == '(x NOT IN (1, 2, 3))'
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should support + - * / via Symbol#+,-,*,/" do
|
182
|
+
@d.l(:x + 1 > 100).should == '((x + 1) > 100)'
|
183
|
+
@d.l((:x * :y) < 100.01).should == '((x * y) < 100.01)'
|
184
|
+
@d.l((:x - :y/2) >= 100000000000000000000000000000000000).should == '((x - (y / 2)) >= 100000000000000000000000000000000000)'
|
185
|
+
@d.l((((:x - :y)/(:x + :y))*:z) <= 100).should == '((((x - y) / (x + y)) * z) <= 100)'
|
186
|
+
@d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).should == '((((x - y) / (x + y)) * z) > 100)'
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should not allow negation of string expressions" do
|
190
|
+
proc{~:x.sql_string}.should raise_error
|
191
|
+
proc{~([:x, :y].sql_string_join)}.should raise_error
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should not allow mathematical or string operations on true, false, or nil" do
|
195
|
+
proc{:x + 1}.should_not raise_error
|
196
|
+
proc{:x - true}.should raise_error(Sequel::Error)
|
197
|
+
proc{:x / false}.should raise_error(Sequel::Error)
|
198
|
+
proc{:x * nil}.should raise_error(Sequel::Error)
|
199
|
+
proc{[:x, nil].sql_string_join}.should raise_error(Sequel::Error)
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should not allow mathematical or string operations on boolean complex expressions" do
|
203
|
+
proc{:x + (:y + 1)}.should_not raise_error
|
204
|
+
proc{:x - (~:y)}.should raise_error(Sequel::Error)
|
205
|
+
proc{:x / (:y & :z)}.should raise_error(Sequel::Error)
|
206
|
+
proc{:x * (:y | :z)}.should raise_error(Sequel::Error)
|
207
|
+
proc{:x + :y.like('a')}.should raise_error(Sequel::Error)
|
208
|
+
proc{:x - :y.like(/a/)}.should raise_error(Sequel::Error)
|
209
|
+
proc{:x * :y.like(/a/i)}.should raise_error(Sequel::Error)
|
210
|
+
proc{:x + ~:y.like('a')}.should raise_error(Sequel::Error)
|
211
|
+
proc{:x - ~:y.like(/a/)}.should raise_error(Sequel::Error)
|
212
|
+
proc{:x * ~:y.like(/a/i)}.should raise_error(Sequel::Error)
|
213
|
+
proc{[:x, ~:y.like(/a/i)].sql_string_join}.should raise_error(Sequel::Error)
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should support AND conditions via &" do
|
217
|
+
@d.l(:x & :y).should == '(x AND y)'
|
218
|
+
@d.l(:x.sql_boolean & :y).should == '(x AND y)'
|
219
|
+
@d.l(:x & :y & :z).should == '(x AND y AND z)'
|
220
|
+
@d.l(:x & {:y => :z}).should == '(x AND (y = z))'
|
221
|
+
@d.l({:y => :z} & :x).should == '((y = z) AND x)'
|
222
|
+
@d.l({:x => :a} & {:y => :z}).should == '((x = a) AND (y = z))'
|
223
|
+
@d.l((:x + 200 < 0) & (:y - 200 < 0)).should == '(((x + 200) < 0) AND ((y - 200) < 0))'
|
224
|
+
@d.l(:x & ~:y).should == '(x AND NOT y)'
|
225
|
+
@d.l(~:x & :y).should == '(NOT x AND y)'
|
226
|
+
@d.l(~:x & ~:y).should == '(NOT x AND NOT y)'
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should support OR conditions via |" do
|
230
|
+
@d.l(:x | :y).should == '(x OR y)'
|
231
|
+
@d.l(:x.sql_boolean | :y).should == '(x OR y)'
|
232
|
+
@d.l(:x | :y | :z).should == '(x OR y OR z)'
|
233
|
+
@d.l(:x | {:y => :z}).should == '(x OR (y = z))'
|
234
|
+
@d.l({:y => :z} | :x).should == '((y = z) OR x)'
|
235
|
+
@d.l({:x => :a} | {:y => :z}).should == '((x = a) OR (y = z))'
|
236
|
+
@d.l((:x.sql_number > 200) | (:y.sql_number < 200)).should == '((x > 200) OR (y < 200))'
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should support & | combinations" do
|
240
|
+
@d.l((:x | :y) & :z).should == '((x OR y) AND z)'
|
241
|
+
@d.l(:x | (:y & :z)).should == '(x OR (y AND z))'
|
242
|
+
@d.l((:x & :w) | (:y & :z)).should == '((x AND w) OR (y AND z))'
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should support & | with ~" do
|
246
|
+
@d.l(~((:x | :y) & :z)).should == '((NOT x AND NOT y) OR NOT z)'
|
247
|
+
@d.l(~(:x | (:y & :z))).should == '(NOT x AND (NOT y OR NOT z))'
|
248
|
+
@d.l(~((:x & :w) | (:y & :z))).should == '((NOT x OR NOT w) AND (NOT y OR NOT z))'
|
249
|
+
@d.l(~((:x.sql_number > 200) | (:y & :z))).should == '((x <= 200) AND (NOT y OR NOT z))'
|
250
|
+
end
|
251
|
+
|
252
|
+
it "should support LiteralString" do
|
253
|
+
@d.l('x'.lit).should == '(x)'
|
254
|
+
@d.l(~'x'.lit).should == 'NOT x'
|
255
|
+
@d.l(~~'x'.lit).should == 'x'
|
256
|
+
@d.l(~(('x'.lit | :y) & :z)).should == '((NOT x AND NOT y) OR NOT z)'
|
257
|
+
@d.l(~(:x | 'y'.lit)).should == '(NOT x AND NOT y)'
|
258
|
+
@d.l(~('x'.lit & 'y'.lit)).should == '(NOT x OR NOT y)'
|
259
|
+
@d.l({'y'.lit => 'z'.lit} & 'x'.lit).should == '((y = z) AND x)'
|
260
|
+
@d.l(('x'.lit > 200) & ('y'.lit < 200)).should == '((x > 200) AND (y < 200))'
|
261
|
+
@d.l(~('x'.lit + 1 > 100)).should == '((x + 1) <= 100)'
|
262
|
+
@d.l('x'.lit.like(/a/)).should == '(x ~ \'a\')'
|
263
|
+
@d.l('x'.lit + 1 > 100).should == '((x + 1) > 100)'
|
264
|
+
@d.l(('x'.lit * :y) < 100.01).should == '((x * y) < 100.01)'
|
265
|
+
@d.l(('x'.lit - :y/2) >= 100000000000000000000000000000000000).should == '((x - (y / 2)) >= 100000000000000000000000000000000000)'
|
266
|
+
@d.l(('z'.lit * (('x'.lit / :y)/(:x + :y))) <= 100).should == '((z * (x / y / (x + y))) <= 100)'
|
267
|
+
@d.l(~(((('x'.lit - :y)/(:x + :y))*:z) <= 100)).should == '((((x - y) / (x + y)) * z) > 100)'
|
268
|
+
end
|
269
|
+
|
270
|
+
it "should support hashes by ANDing the conditions" do
|
271
|
+
@d.l(:x => 100, :y => 'a')[1...-1].split(' AND ').sort.should == ['(x = 100)', '(y = \'a\')']
|
272
|
+
@d.l(:x => true, :y => false)[1...-1].split(' AND ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
|
273
|
+
@d.l(:x => nil, :y => [1,2,3])[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should support sql_expr on hashes" do
|
277
|
+
@d.l({:x => 100, :y => 'a'}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x = 100)', '(y = \'a\')']
|
278
|
+
@d.l({:x => true, :y => false}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
|
279
|
+
@d.l({:x => nil, :y => [1,2,3]}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
|
280
|
+
end
|
281
|
+
|
282
|
+
it "should support sql_negate on hashes" do
|
283
|
+
@d.l({:x => 100, :y => 'a'}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x != 100)', '(y != \'a\')']
|
284
|
+
@d.l({:x => true, :y => false}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
|
285
|
+
@d.l({:x => nil, :y => [1,2,3]}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should support ~ on hashes" do
|
289
|
+
@d.l(~{:x => 100, :y => 'a'})[1...-1].split(' OR ').sort.should == ['(x != 100)', '(y != \'a\')']
|
290
|
+
@d.l(~{:x => true, :y => false})[1...-1].split(' OR ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
|
291
|
+
@d.l(~{:x => nil, :y => [1,2,3]})[1...-1].split(' OR ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
|
292
|
+
end
|
293
|
+
|
294
|
+
it "should support sql_or on hashes" do
|
295
|
+
@d.l({:x => 100, :y => 'a'}.sql_or)[1...-1].split(' OR ').sort.should == ['(x = 100)', '(y = \'a\')']
|
296
|
+
@d.l({:x => true, :y => false}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
|
297
|
+
@d.l({:x => nil, :y => [1,2,3]}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should support arrays with all two pairs the same as hashes" do
|
301
|
+
@d.l([[:x, 100],[:y, 'a']]).should == '((x = 100) AND (y = \'a\'))'
|
302
|
+
@d.l([[:x, true], [:y, false]]).should == '((x IS TRUE) AND (y IS FALSE))'
|
303
|
+
@d.l([[:x, nil], [:y, [1,2,3]]]).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should support sql_expr on arrays with all two pairs" do
|
307
|
+
@d.l([[:x, 100],[:y, 'a']].sql_expr).should == '((x = 100) AND (y = \'a\'))'
|
308
|
+
@d.l([[:x, true], [:y, false]].sql_expr).should == '((x IS TRUE) AND (y IS FALSE))'
|
309
|
+
@d.l([[:x, nil], [:y, [1,2,3]]].sql_expr).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
|
310
|
+
end
|
311
|
+
|
312
|
+
it "should support sql_negate on arrays with all two pairs" do
|
313
|
+
@d.l([[:x, 100],[:y, 'a']].sql_negate).should == '((x != 100) AND (y != \'a\'))'
|
314
|
+
@d.l([[:x, true], [:y, false]].sql_negate).should == '((x IS NOT TRUE) AND (y IS NOT FALSE))'
|
315
|
+
@d.l([[:x, nil], [:y, [1,2,3]]].sql_negate).should == '((x IS NOT NULL) AND (y NOT IN (1, 2, 3)))'
|
316
|
+
end
|
317
|
+
|
318
|
+
it "should support ~ on arrays with all two pairs" do
|
319
|
+
@d.l(~[[:x, 100],[:y, 'a']]).should == '((x != 100) OR (y != \'a\'))'
|
320
|
+
@d.l(~[[:x, true], [:y, false]]).should == '((x IS NOT TRUE) OR (y IS NOT FALSE))'
|
321
|
+
@d.l(~[[:x, nil], [:y, [1,2,3]]]).should == '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
|
322
|
+
end
|
323
|
+
|
324
|
+
it "should support sql_or on arrays with all two pairs" do
|
325
|
+
@d.l([[:x, 100],[:y, 'a']].sql_or).should == '((x = 100) OR (y = \'a\'))'
|
326
|
+
@d.l([[:x, true], [:y, false]].sql_or).should == '((x IS TRUE) OR (y IS FALSE))'
|
327
|
+
@d.l([[:x, nil], [:y, [1,2,3]]].sql_or).should == '((x IS NULL) OR (y IN (1, 2, 3)))'
|
328
|
+
end
|
329
|
+
|
330
|
+
it "should emulate columns for array values" do
|
331
|
+
@d.l([:x, :y]=>[[1,2], [3,4]].sql_array).should == '((x, y) IN ((1, 2), (3, 4)))'
|
332
|
+
@d.l([:x, :y, :z]=>[[1,2,5], [3,4,6]]).should == '((x, y, z) IN ((1, 2, 5), (3, 4, 6)))'
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should emulate multiple column in if not supported" do
|
336
|
+
@d.meta_def(:supports_multiple_column_in?){false}
|
337
|
+
@d.l([:x, :y]=>[[1,2], [3,4]].sql_array).should == '(((x = 1) AND (y = 2)) OR ((x = 3) AND (y = 4)))'
|
338
|
+
@d.l([:x, :y, :z]=>[[1,2,5], [3,4,6]]).should == '(((x = 1) AND (y = 2) AND (z = 5)) OR ((x = 3) AND (y = 4) AND (z = 6)))'
|
339
|
+
end
|
340
|
+
|
341
|
+
it "should support Array#sql_string_join for concatenation of SQL strings" do
|
342
|
+
@d.lit([:x].sql_string_join).should == '(x)'
|
343
|
+
@d.lit([:x].sql_string_join(', ')).should == '(x)'
|
344
|
+
@d.lit([:x, :y].sql_string_join).should == '(x || y)'
|
345
|
+
@d.lit([:x, :y].sql_string_join(', ')).should == "(x || ', ' || y)"
|
346
|
+
@d.lit([:x.sql_function(1), :y.sql_subscript(1)].sql_string_join).should == '(x(1) || y[1])'
|
347
|
+
@d.lit([:x.sql_function(1), 'y.z'.lit].sql_string_join(', ')).should == "(x(1) || ', ' || y.z)"
|
348
|
+
@d.lit([:x, 1, :y].sql_string_join).should == "(x || '1' || y)"
|
349
|
+
@d.lit([:x, 1, :y].sql_string_join(', ')).should == "(x || ', ' || '1' || ', ' || y)"
|
350
|
+
@d.lit([:x, 1, :y].sql_string_join(:y__z)).should == "(x || y.z || '1' || y.z || y)"
|
351
|
+
@d.lit([:x, 1, :y].sql_string_join(1)).should == "(x || '1' || '1' || '1' || y)"
|
352
|
+
@d.lit([:x, :y].sql_string_join('y.x || x.y'.lit)).should == "(x || y.x || x.y || y)"
|
353
|
+
@d.lit([[:x, :y].sql_string_join, [:a, :b].sql_string_join].sql_string_join).should == "(x || y || a || b)"
|
354
|
+
end
|
355
|
+
|
356
|
+
it "should support StringExpression#+ for concatenation of SQL strings" do
|
357
|
+
@d.lit(:x.sql_string + :y).should == '(x || y)'
|
358
|
+
@d.lit([:x].sql_string_join + :y).should == '(x || y)'
|
359
|
+
@d.lit([:x, :z].sql_string_join(' ') + :y).should == "(x || ' ' || z || y)"
|
360
|
+
end
|
361
|
+
|
362
|
+
it "should be supported inside blocks" do
|
363
|
+
@d.l{[[:x, nil], [:y, [1,2,3]]].sql_or}.should == '((x IS NULL) OR (y IN (1, 2, 3)))'
|
364
|
+
@d.l{~[[:x, nil], [:y, [1,2,3]]]}.should == '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
|
365
|
+
@d.l{~(((('x'.lit - :y)/(:x + :y))*:z) <= 100)}.should == '((((x - y) / (x + y)) * z) > 100)'
|
366
|
+
@d.l{{:x => :a} & {:y => :z}}.should == '((x = a) AND (y = z))'
|
367
|
+
end
|
368
|
+
|
369
|
+
it "should support &, |, ^, ~, <<, and >> for NumericExpressions" do
|
370
|
+
@d.l(:x.sql_number & 1 > 100).should == '((x & 1) > 100)'
|
371
|
+
@d.l(:x.sql_number | 1 > 100).should == '((x | 1) > 100)'
|
372
|
+
@d.l(:x.sql_number ^ 1 > 100).should == '((x ^ 1) > 100)'
|
373
|
+
@d.l(~:x.sql_number > 100).should == '(~x > 100)'
|
374
|
+
@d.l(:x.sql_number << 1 > 100).should == '((x << 1) > 100)'
|
375
|
+
@d.l(:x.sql_number >> 1 > 100).should == '((x >> 1) > 100)'
|
376
|
+
@d.l((:x + 1) & 1 > 100).should == '(((x + 1) & 1) > 100)'
|
377
|
+
@d.l((:x + 1) | 1 > 100).should == '(((x + 1) | 1) > 100)'
|
378
|
+
@d.l((:x + 1) ^ 1 > 100).should == '(((x + 1) ^ 1) > 100)'
|
379
|
+
@d.l(~(:x + 1) > 100).should == '(~(x + 1) > 100)'
|
380
|
+
@d.l((:x + 1) << 1 > 100).should == '(((x + 1) << 1) > 100)'
|
381
|
+
@d.l((:x + 1) >> 1 > 100).should == '(((x + 1) >> 1) > 100)'
|
382
|
+
@d.l((:x + 1) & (:x + 2) > 100).should == '(((x + 1) & (x + 2)) > 100)'
|
383
|
+
end
|
384
|
+
|
385
|
+
it "should raise an error if use a Bitwise method on a ComplexExpression that isn't a NumericExpression" do
|
386
|
+
proc{(:x + 1) & (:x & 2)}.should raise_error(Sequel::Error)
|
387
|
+
end
|
388
|
+
|
389
|
+
it "should raise an error if use a Boolean method on a ComplexExpression that isn't a BooleanExpression" do
|
390
|
+
proc{:x & (:x + 2)}.should raise_error(Sequel::Error)
|
391
|
+
end
|
392
|
+
|
393
|
+
it "should raise an error if attempting to invert a ComplexExpression that isn't a BooleanExpression" do
|
394
|
+
proc{Sequel::SQL::BooleanExpression.invert(:x + 2)}.should raise_error(Sequel::Error)
|
395
|
+
end
|
396
|
+
|
397
|
+
it "should return self on .lit" do
|
398
|
+
y = :x + 1
|
399
|
+
y.lit.should == y
|
400
|
+
end
|
401
|
+
|
402
|
+
it "should return have .sql_literal operate like .to_s" do
|
403
|
+
y = :x + 1
|
404
|
+
y.sql_literal(@d).should == '(x + 1)'
|
405
|
+
y.sql_literal(@d).should == y.to_s(@d)
|
406
|
+
y.sql_literal(@d).should == @d.literal(y)
|
407
|
+
end
|
408
|
+
|
409
|
+
it "should support SQL::Constants" do
|
410
|
+
@d.l({:x => Sequel::NULL}).should == '(x IS NULL)'
|
411
|
+
@d.l({:x => Sequel::NOTNULL}).should == '(x IS NOT NULL)'
|
412
|
+
@d.l({:x => Sequel::TRUE}).should == '(x IS TRUE)'
|
413
|
+
@d.l({:x => Sequel::FALSE}).should == '(x IS FALSE)'
|
414
|
+
@d.l({:x => Sequel::SQLTRUE}).should == '(x IS TRUE)'
|
415
|
+
@d.l({:x => Sequel::SQLFALSE}).should == '(x IS FALSE)'
|
416
|
+
end
|
417
|
+
|
418
|
+
it "should support negation of SQL::Constants" do
|
419
|
+
@d.l(~{:x => Sequel::NULL}).should == '(x IS NOT NULL)'
|
420
|
+
@d.l(~{:x => Sequel::NOTNULL}).should == '(x IS NULL)'
|
421
|
+
@d.l(~{:x => Sequel::TRUE}).should == '(x IS NOT TRUE)'
|
422
|
+
@d.l(~{:x => Sequel::FALSE}).should == '(x IS NOT FALSE)'
|
423
|
+
@d.l(~{:x => Sequel::SQLTRUE}).should == '(x IS NOT TRUE)'
|
424
|
+
@d.l(~{:x => Sequel::SQLFALSE}).should == '(x IS NOT FALSE)'
|
425
|
+
end
|
426
|
+
|
427
|
+
it "should raise an error if trying to create an invalid complex expression" do
|
428
|
+
proc{Sequel::SQL::ComplexExpression.new(:BANG, 1, 2)}.should raise_error(Sequel::Error)
|
429
|
+
end
|
430
|
+
|
431
|
+
it "should raise an error if trying to literalize an invalid complex expression" do
|
432
|
+
ce = :x + 1
|
433
|
+
ce.instance_variable_set(:@op, :BANG)
|
434
|
+
proc{@d.lit(ce)}.should raise_error(Sequel::Error)
|
435
|
+
end
|
436
|
+
|
437
|
+
it "should support equality comparison of two expressions" do
|
438
|
+
e1 = ~:comment.like('%:hidden:%')
|
439
|
+
e2 = ~:comment.like('%:hidden:%')
|
440
|
+
e1.should == e2
|
441
|
+
end
|
442
|
+
|
443
|
+
if RUBY_VERSION < '1.9.0'
|
444
|
+
it "should not allow inequality operations on true, false, or nil" do
|
445
|
+
proc{:x > 1}.should_not raise_error
|
446
|
+
proc{:x < true}.should raise_error(Sequel::Error)
|
447
|
+
proc{:x >= false}.should raise_error(Sequel::Error)
|
448
|
+
proc{:x <= nil}.should raise_error(Sequel::Error)
|
449
|
+
end
|
450
|
+
|
451
|
+
it "should not allow inequality operations on boolean complex expressions" do
|
452
|
+
proc{:x > (:y > 5)}.should raise_error(Sequel::Error)
|
453
|
+
proc{:x < (:y < 5)}.should raise_error(Sequel::Error)
|
454
|
+
proc{:x >= (:y >= 5)}.should raise_error(Sequel::Error)
|
455
|
+
proc{:x <= (:y <= 5)}.should raise_error(Sequel::Error)
|
456
|
+
proc{:x > {:y => nil}}.should raise_error(Sequel::Error)
|
457
|
+
proc{:x < ~{:y => nil}}.should raise_error(Sequel::Error)
|
458
|
+
proc{:x >= {:y => 5}}.should raise_error(Sequel::Error)
|
459
|
+
proc{:x <= ~{:y => 5}}.should raise_error(Sequel::Error)
|
460
|
+
proc{:x >= {:y => [1,2,3]}}.should raise_error(Sequel::Error)
|
461
|
+
proc{:x <= ~{:y => [1,2,3]}}.should raise_error(Sequel::Error)
|
462
|
+
end
|
463
|
+
|
464
|
+
it "should support >, <, >=, and <= via Symbol#>,<,>=,<=" do
|
465
|
+
@d.l(:x > 100).should == '(x > 100)'
|
466
|
+
@d.l(:x < 100.01).should == '(x < 100.01)'
|
467
|
+
@d.l(:x >= 100000000000000000000000000000000000).should == '(x >= 100000000000000000000000000000000000)'
|
468
|
+
@d.l(:x <= 100).should == '(x <= 100)'
|
469
|
+
end
|
470
|
+
|
471
|
+
it "should support negation of >, <, >=, and <= via Symbol#~" do
|
472
|
+
@d.l(~(:x > 100)).should == '(x <= 100)'
|
473
|
+
@d.l(~(:x < 100.01)).should == '(x >= 100.01)'
|
474
|
+
@d.l(~(:x >= 100000000000000000000000000000000000)).should == '(x < 100000000000000000000000000000000000)'
|
475
|
+
@d.l(~(:x <= 100)).should == '(x > 100)'
|
476
|
+
end
|
477
|
+
|
478
|
+
it "should support double negation via ~" do
|
479
|
+
@d.l(~~(:x > 100)).should == '(x > 100)'
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
context Sequel::SQL::VirtualRow do
|
485
|
+
before do
|
486
|
+
db = Sequel::Database.new
|
487
|
+
db.quote_identifiers = true
|
488
|
+
@d = db[:items]
|
489
|
+
@d.meta_def(:supports_window_functions?){true}
|
490
|
+
def @d.l(*args, &block)
|
491
|
+
literal(filter_expr(*args, &block))
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
it "should treat methods without arguments as identifiers" do
|
496
|
+
@d.l{column}.should == '"column"'
|
497
|
+
end
|
498
|
+
|
499
|
+
it "should treat methods without arguments that have embedded double underscores as qualified identifiers" do
|
500
|
+
@d.l{table__column}.should == '"table"."column"'
|
501
|
+
end
|
502
|
+
|
503
|
+
it "should treat methods with arguments as functions with the arguments" do
|
504
|
+
@d.l{function(arg1, 10, 'arg3')}.should == 'function("arg1", 10, \'arg3\')'
|
505
|
+
end
|
506
|
+
|
507
|
+
it "should treat methods with a block and no arguments as a function call with no arguments" do
|
508
|
+
@d.l{version{}}.should == 'version()'
|
509
|
+
end
|
510
|
+
|
511
|
+
it "should treat methods with a block and a leading argument :* as a function call with the SQL wildcard" do
|
512
|
+
@d.l{count(:*){}}.should == 'count(*)'
|
513
|
+
end
|
514
|
+
|
515
|
+
it "should treat methods with a block and a leading argument :distinct as a function call with DISTINCT and the additional method arguments" do
|
516
|
+
@d.l{count(:distinct, column1){}}.should == 'count(DISTINCT "column1")'
|
517
|
+
@d.l{count(:distinct, column1, column2){}}.should == 'count(DISTINCT "column1", "column2")'
|
518
|
+
end
|
519
|
+
|
520
|
+
it "should raise an error if an unsupported argument is used with a block" do
|
521
|
+
proc{@d.l{count(:blah){}}}.should raise_error(Sequel::Error)
|
522
|
+
end
|
523
|
+
|
524
|
+
it "should treat methods with a block and a leading argument :over as a window function call" do
|
525
|
+
@d.l{rank(:over){}}.should == 'rank() OVER ()'
|
526
|
+
end
|
527
|
+
|
528
|
+
it "should support :partition options for window function calls" do
|
529
|
+
@d.l{rank(:over, :partition=>column1){}}.should == 'rank() OVER (PARTITION BY "column1")'
|
530
|
+
@d.l{rank(:over, :partition=>[column1, column2]){}}.should == 'rank() OVER (PARTITION BY "column1", "column2")'
|
531
|
+
end
|
532
|
+
|
533
|
+
it "should support :args options for window function calls" do
|
534
|
+
@d.l{avg(:over, :args=>column1){}}.should == 'avg("column1") OVER ()'
|
535
|
+
@d.l{avg(:over, :args=>[column1, column2]){}}.should == 'avg("column1", "column2") OVER ()'
|
536
|
+
end
|
537
|
+
|
538
|
+
it "should support :order option for window function calls" do
|
539
|
+
@d.l{rank(:over, :order=>column1){}}.should == 'rank() OVER (ORDER BY "column1")'
|
540
|
+
@d.l{rank(:over, :order=>[column1, column2]){}}.should == 'rank() OVER (ORDER BY "column1", "column2")'
|
541
|
+
end
|
542
|
+
|
543
|
+
it "should support :window option for window function calls" do
|
544
|
+
@d.l{rank(:over, :window=>:win){}}.should == 'rank() OVER ("win")'
|
545
|
+
end
|
546
|
+
|
547
|
+
it "should support :*=>true option for window function calls" do
|
548
|
+
@d.l{count(:over, :* =>true){}}.should == 'count(*) OVER ()'
|
549
|
+
end
|
550
|
+
|
551
|
+
it "should support :frame=>:all option for window function calls" do
|
552
|
+
@d.l{rank(:over, :frame=>:all){}}.should == 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)'
|
553
|
+
end
|
554
|
+
|
555
|
+
it "should support :frame=>:rows option for window function calls" do
|
556
|
+
@d.l{rank(:over, :frame=>:rows){}}.should == 'rank() OVER (ROWS UNBOUNDED PRECEDING)'
|
557
|
+
end
|
558
|
+
|
559
|
+
it "should raise an error if an invalid :frame option is used" do
|
560
|
+
proc{@d.l{rank(:over, :frame=>:blah){}}}.should raise_error(Sequel::Error)
|
561
|
+
end
|
562
|
+
|
563
|
+
it "should support all these options together" do
|
564
|
+
@d.l{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}.should == 'count(*) OVER ("win" PARTITION BY "a" ORDER BY "b" ROWS UNBOUNDED PRECEDING)'
|
565
|
+
end
|
566
|
+
|
567
|
+
it "should raise an error if window functions are not supported" do
|
568
|
+
@d.meta_def(:supports_window_functions?){false}
|
569
|
+
proc{@d.l{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}}.should raise_error(Sequel::Error)
|
570
|
+
proc{Sequel::Dataset.new(nil).filter{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}.sql}.should raise_error(Sequel::Error)
|
571
|
+
end
|
572
|
+
|
573
|
+
it "should deal with classes without requiring :: prefix" do
|
574
|
+
@d.l{date < Date.today}.should == "(\"date\" < '#{Date.today}')"
|
575
|
+
@d.l{date < Sequel::CURRENT_DATE}.should == "(\"date\" < CURRENT_DATE)"
|
576
|
+
@d.l{num < Math::PI.to_i}.should == "(\"num\" < 3)"
|
577
|
+
end
|
578
|
+
|
579
|
+
it "should deal with methods added to Object after requiring Sequel" do
|
580
|
+
class Object
|
581
|
+
def adsoiwemlsdaf; 42; end
|
582
|
+
end
|
583
|
+
Sequel::BasicObject.remove_methods!
|
584
|
+
@d.l{a > adsoiwemlsdaf}.should == '("a" > "adsoiwemlsdaf")'
|
585
|
+
end
|
586
|
+
|
587
|
+
it "should deal with private methods added to Kernel after requiring Sequel" do
|
588
|
+
module Kernel
|
589
|
+
private
|
590
|
+
def adsoiwemlsdaf2; 42; end
|
591
|
+
end
|
592
|
+
Sequel::BasicObject.remove_methods!
|
593
|
+
@d.l{a > adsoiwemlsdaf2}.should == '("a" > "adsoiwemlsdaf2")'
|
594
|
+
end
|
595
|
+
end
|