arel_extensions 0.8.4 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,7 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
3
  Arel::Visitors::PostgreSQL.class_eval do
4
+ Arel::Visitors::PostgreSQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'DOW'}
4
5
 
5
6
  def visit_ArelExtensions_Nodes_Rand o, collector
6
7
  collector << "RANDOM("
@@ -91,17 +92,7 @@ module ArelExtensions
91
92
  end
92
93
 
93
94
  def visit_ArelExtensions_Nodes_Duration o, collector
94
- #visit left for period
95
- if o.left == "d"
96
- collector << "EXTRACT(DAY FROM"
97
- elsif o.left == "m"
98
- collector << "EXTRACT(MONTH FROM "
99
- elsif (o.left == "w")
100
- collector << "EXTRACT(WEEK FROM"
101
- elsif (o.left == "y")
102
- collector << "EXTRACT(YEAR FROM"
103
- end
104
- #visit right
95
+ collector << "EXTRACT(#{Arel::Visitors::PostgreSQL::DATE_MAPPING[o.left]} FROM "
105
96
  collector = visit o.right, collector
106
97
  collector << ")"
107
98
  collector
@@ -130,7 +121,7 @@ module ArelExtensions
130
121
  end
131
122
 
132
123
  def visit_ArelExtensions_Nodes_Wday o, collector
133
- collector << "DATE_PART('dow', "
124
+ collector << "EXRTACT(DOW, "
134
125
  collector = visit o.date, collector
135
126
  collector << ")"
136
127
  collector
@@ -1,6 +1,7 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
3
  Arel::Visitors::SQLite.class_eval do
4
+ Arel::Visitors::SQLite::DATE_MAPPING = {'d' => '%d', 'm' => '%m', 'w' => '%W', 'y' => '%Y', 'wd' => '%w', 'M' => '%M'}
4
5
 
5
6
  #String functions
6
7
  def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
@@ -47,17 +48,7 @@ module ArelExtensions
47
48
  end
48
49
 
49
50
  def visit_ArelExtensions_Nodes_Duration o, collector
50
- #visit left for period
51
- if(o.left == "d")
52
- collector << "strftime('%d',"
53
- elsif(o.left == "m")
54
- collector << "strftime('%m',"
55
- elsif (o.left == "w")
56
- collector << "strftime('%W',"
57
- elsif (o.left == "y")
58
- collector << "strftime('%Y',"
59
- end
60
- #visit right
51
+ collector << "strftime('#{Arel::Visitors::SQLite::DATE_MAPPING[o.left]}'#{Arel::Visitors::SQLite::COMMA}"
61
52
  collector = visit o.right, collector
62
53
  collector << ")"
63
54
  collector
@@ -55,10 +55,12 @@ module ArelExtensions
55
55
 
56
56
  # String functions
57
57
  def visit_ArelExtensions_Nodes_Concat o, collector
58
+ collector << '('
58
59
  o.expressions.each_with_index { |arg, i|
59
60
  collector = visit arg, collector
60
61
  collector << ' || ' unless i == o.expressions.length - 1
61
62
  }
63
+ collector << ")"
62
64
  collector
63
65
  end
64
66
 
@@ -150,6 +152,26 @@ module ArelExtensions
150
152
  collector
151
153
  end
152
154
 
155
+ def visit_ArelExtensions_Nodes_Format o, collector
156
+ case o.col_type
157
+ when :date, :datetime
158
+ collector << "STRFTIME("
159
+ collector = visit o.right, collector
160
+ collector << Arel::Visitors::ToSql::COMMA
161
+ collector = visit o.left, collector
162
+ collector << ")"
163
+ when :integer, :float, :decimal
164
+ collector << "FORMAT("
165
+ collector = visit o.left, collector
166
+ collector << Arel::Visitors::ToSql::COMMA
167
+ collector = visit o.right, collector
168
+ collector << ")"
169
+ else
170
+ collector = visit o.left, collector
171
+ end
172
+ collector
173
+ end
174
+
153
175
  #comparators
154
176
 
155
177
  def visit_ArelExtensions_Nodes_Coalesce o, collector
data/test/database.yml CHANGED
@@ -27,11 +27,13 @@ jdbc-postgresql:
27
27
  oracle:
28
28
  adapter: oracle_enhanced
29
29
  database: xe
30
- username: travis
30
+ username: ruby
31
+ password: oci8
31
32
  jdbc-oracle:
32
33
  adapter: oracle_enhanced
33
34
  database: xe
34
- username: travis
35
+ username: ruby
36
+ password: oci8
35
37
  ibm_db:
36
38
  adapter: ibm_db
37
39
  username: travis
@@ -0,0 +1,2 @@
1
+ alter user sys identified by admin;
2
+ alter user system identified by admin;
@@ -0,0 +1,29 @@
1
+ CREATE USER oracle_enhanced IDENTIFIED BY oracle_enhanced;
2
+
3
+ GRANT unlimited tablespace, create session, create table, create sequence,
4
+ create procedure, create trigger, create view, create materialized view,
5
+ create database link, create synonym, create type, ctxapp TO oracle_enhanced;
6
+
7
+ CREATE USER oracle_enhanced_schema IDENTIFIED BY oracle_enhanced_schema;
8
+
9
+ GRANT unlimited tablespace, create session, create table, create sequence,
10
+ create procedure, create trigger, create view, create materialized view,
11
+ create database link, create synonym, create type, ctxapp TO oracle_enhanced_schema;
12
+
13
+ CREATE USER arunit IDENTIFIED BY arunit;
14
+
15
+ GRANT unlimited tablespace, create session, create table, create sequence,
16
+ create procedure, create trigger, create view, create materialized view,
17
+ create database link, create synonym, create type, ctxapp TO arunit;
18
+
19
+ CREATE USER arunit2 IDENTIFIED BY arunit2;
20
+
21
+ GRANT unlimited tablespace, create session, create table, create sequence,
22
+ create procedure, create trigger, create view, create materialized view,
23
+ create database link, create synonym, create type, ctxapp TO arunit2;
24
+
25
+ CREATE USER ruby IDENTIFIED BY oci8;
26
+ GRANT connect, resource, create view,create synonym TO ruby;
27
+ GRANT EXECUTE ON dbms_lock TO ruby;
28
+ GRANT CREATE VIEW TO ruby;
29
+ GRANT unlimited tablespace to ruby;
@@ -46,8 +46,8 @@ module ArelExtensions
46
46
  # String Functions
47
47
  it "should accept functions on strings" do
48
48
  c = @table[:name]
49
- compile(c + 'test').must_be_like %{"users"."name" || 'test'}
50
- compile(c + 'test' + ' chain').must_be_like %{"users"."name" || 'test' || ' chain'}
49
+ compile(c + 'test').must_be_like %{("users"."name" || 'test')}
50
+ compile(c + 'test' + ' chain').must_be_like %{("users"."name" || 'test' || ' chain')}
51
51
  compile(c.length).must_be_like %{LENGTH("users"."name")}
52
52
  compile(c.length.round + 42).must_be_like %{(ROUND(LENGTH("users"."name")) + 42)}
53
53
  compile(c.locate('test')).must_be_like %{LOCATE('test', "users"."name")}
@@ -7,7 +7,13 @@ module ArelExtensions
7
7
  class ListTest < Minitest::Test
8
8
  def setup_db
9
9
  ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
10
- ActiveRecord::Base.establish_connection(ENV['DB'].try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
10
+ if ENV['DB'] == 'oracle' && ((defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx") || (RUBY_PLATFORM == 'java')) # not supported
11
+ @env_db = (RUBY_PLATFORM == 'java' ? "jdbc-sqlite" : 'sqlite')
12
+ skip "Platform not supported"
13
+ else
14
+ @env_db = ENV['DB']
15
+ end
16
+ ActiveRecord::Base.establish_connection(@env_db.try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
11
17
  ActiveRecord::Base.default_timezone = :utc
12
18
  @cnx = ActiveRecord::Base.connection
13
19
  $sqlite ||= false
@@ -31,12 +37,12 @@ module ArelExtensions
31
37
  end
32
38
  end
33
39
  end
34
- if File.exist?("init/#{ENV['DB']}.sql")
35
- sql = File.read("init/#{ENV['DB']}.sql")
40
+ if File.exist?("init/#{@env_db}.sql")
41
+ sql = File.read("init/#{@env_db}.sql")
36
42
  @cnx.execute(sql) unless sql.blank?
37
43
  end
38
- @cnx.drop_table(:users) rescue nil
39
- @cnx.create_table :users do |t|
44
+ @cnx.drop_table(:user_tests) rescue nil
45
+ @cnx.create_table :user_tests do |t|
40
46
  t.column :age, :integer
41
47
  t.column :name, :string
42
48
  t.column :comments, :text
@@ -44,23 +50,19 @@ module ArelExtensions
44
50
  t.column :updated_at, :datetime
45
51
  t.column :score, :decimal, :precision => 20, :scale => 10
46
52
  end
47
- @cnx.drop_table(:products) rescue nil
48
- @cnx.create_table :products do |t|
53
+ @cnx.drop_table(:product_tests) rescue nil
54
+ @cnx.create_table :product_tests do |t|
49
55
  t.column :price, :decimal, :precision => 20, :scale => 10
50
56
  end
51
57
  end
52
58
 
53
- def teardown_db
54
- @cnx.drop_table(:users)
55
- @cnx.drop_table(:products)
56
- end
57
-
58
59
  class User < ActiveRecord::Base
60
+ self.table_name = 'user_tests'
59
61
  end
60
62
  class Product < ActiveRecord::Base
63
+ self.table_name = 'product_tests'
61
64
  end
62
65
 
63
-
64
66
  def setup
65
67
  d = Date.new(2016,05,23)
66
68
  setup_db
@@ -90,7 +92,8 @@ module ArelExtensions
90
92
  end
91
93
 
92
94
  def teardown
93
- teardown_db
95
+ @cnx.drop_table(:user_tests)
96
+ @cnx.drop_table(:product_tests)
94
97
  end
95
98
 
96
99
  def t(scope, node)
@@ -109,17 +112,15 @@ module ArelExtensions
109
112
  end
110
113
 
111
114
  def test_ceil
112
- if !$sqlite || !$load_extension_disabled
113
- assert_equal 1, t(@neg, @score.ceil)
114
- assert_equal 63, t(@arthur, @age.ceil + 42)
115
- end
115
+ skip "Sqlite version can't load extension for ceil" if $sqlite && $load_extension_disabled
116
+ assert_equal 1, t(@neg, @score.ceil)
117
+ assert_equal 63, t(@arthur, @age.ceil + 42)
116
118
  end
117
119
 
118
120
  def test_floor
119
- if !$sqlite || !$load_extension_disabled
120
- assert_equal 0, t(@neg, @score.floor)
121
- assert_equal 42, t(@arthur, @score.floor - 23)
122
- end
121
+ skip "Sqlite version can't load extension for floor" if $sqlite && $load_extension_disabled
122
+ assert_equal 0, t(@neg, @score.floor)
123
+ assert_equal 42, t(@arthur, @score.floor - 23)
123
124
  end
124
125
 
125
126
  def test_rand
@@ -146,8 +147,8 @@ module ArelExtensions
146
147
  def test_concat
147
148
  assert_equal 'Camille Camille', t(@camille, @name + ' ' + @name)
148
149
  assert_equal 'Laure 2', t(@laure, @name + ' ' + 2)
149
- if ENV['DB'] == 'postgresql'
150
- assert_equal "Lucas Sophie", t(User.reorder(nil).from(User.select(:name).where(:name => ['Lucas', 'Sophie']).reorder(:name).as('users')), @name.group_concat(' '))
150
+ if @env_db == 'postgresql'
151
+ assert_equal "Lucas Sophie", t(User.reorder(nil).from(User.select(:name).where(:name => ['Lucas', 'Sophie']).reorder(:name).as('user_tests')), @name.group_concat(' '))
151
152
  else
152
153
  assert_equal "Lucas Sophie", t(User.where(:name => ['Lucas', 'Sophie']).reorder(:name), @name.group_concat(' '))
153
154
  end
@@ -160,32 +161,35 @@ module ArelExtensions
160
161
  end
161
162
 
162
163
  def test_locate
163
- if !$sqlite || !$load_extension_disabled
164
- assert_equal 1, t(@camille, @name.locate("C"))
165
- assert_equal 0, t(@lucas, @name.locate("z"))
166
- assert_equal 5, t(@lucas, @name.locate("s"))
167
- end
164
+ skip "Sqlite version can't load extension for locate" if $sqlite && $load_extension_disabled
165
+ assert_equal 1, t(@camille, @name.locate("C"))
166
+ assert_equal 0, t(@lucas, @name.locate("z"))
167
+ assert_equal 5, t(@lucas, @name.locate("s"))
168
168
  end
169
169
 
170
170
  def test_find_in_set
171
- if !$sqlite || !$load_extension_disabled
172
- assert 4, t(@neg, @comments & 2)
173
- assert 2, t(@neg, @comments & 6)
174
- end
171
+ skip "Sqlite version can't load extension for find_in_set" if $sqlite && $load_extension_disabled
172
+ assert_equal 5, t(@neg, @comments & 2)
173
+ assert_equal 0, t(@neg, @comments & 6) # not found
175
174
  end
176
175
 
177
176
  def test_string_comparators
178
- assert 1, t(@neg, @name >= 'test')
179
- assert 1, t(@neg, @name <= @comments)
177
+ skip "Oracle can't use math operators to compare strings, any function to do that?" if @env_db == 'oracle'
178
+ if @env_db == 'postgresql' # may return real boolean
179
+ assert t(@neg, @name >= 'Mest') == true || t(@neg, @name >= 'Mest') == 't' # depends of ar version
180
+ assert t(@neg, @name <= (@name + 'Z')) == true || t(@neg, @name <= (@name + 'Z')) == 't'
181
+ else
182
+ assert_equal 1, t(@neg, @name >= 'Mest')
183
+ assert_equal 1, t(@neg, @name <= (@name + 'Z'))
184
+ end
180
185
  end
181
186
 
182
- def test_regexp_not_regex
183
- if !$sqlite || !$load_extension_disabled
184
- assert_equal 1, User.where(@name =~ '^M').count
185
- assert_equal 6, User.where(@name !~ '^L').count
186
- assert_equal 1, User.where(@name =~ /^M/).count
187
- assert_equal 6, User.where(@name !~ /^L/).count
188
- end
187
+ def test_regexp_not_regexp
188
+ skip "Sqlite version can't load extension for regexp" if $sqlite && $load_extension_disabled
189
+ assert_equal 1, User.where(@name =~ '^M').count
190
+ assert_equal 6, User.where(@name !~ '^L').count
191
+ assert_equal 1, User.where(@name =~ /^M/).count
192
+ assert_equal 6, User.where(@name !~ /^L/).count
189
193
  end
190
194
 
191
195
  def test_imatches
@@ -195,26 +199,27 @@ module ArelExtensions
195
199
  end
196
200
 
197
201
  def test_replace
198
- assert_equal "LucaX", t(@lucas, @name.replace("s","X"))
199
- assert_equal "replace", t(@lucas, @name.replace(@name,"replace"))
202
+ assert_equal "LucaX", t(@lucas, @name.replace("s", "X"))
203
+ assert_equal "replace", t(@lucas, @name.replace(@name, "replace"))
200
204
  end
201
205
 
202
206
  def test_soundex
203
- if (!$sqlite || !$load_extension_disabled) && (ENV['DB'] != 'postgresql')
204
- assert_equal "C540", t(@camille, @name.soundex)
205
- assert_equal 8, User.where(@name.soundex.eq(@name.soundex)).count
206
- end
207
+ skip "Sqlite version can't load extension for soundex" if $sqlite && $load_extension_disabled
208
+ skip "PostgreSql version can't load extension for soundex" if @env_db == 'postgresql'
209
+ assert_equal "C540", t(@camille, @name.soundex)
210
+ assert_equal 8, User.where(@name.soundex.eq(@name.soundex)).count
207
211
  end
208
212
 
209
213
  def test_trim
210
214
  assert_equal "Myun", t(@myung, @name.rtrim("g"))
211
215
  assert_equal "yung", t(@myung, @name.ltrim("M"))
212
216
  assert_equal "yung", t(@myung, (@name + "M").trim("M"))
217
+ skip "Oracle does not accept multi char trim" if @env_db == 'oracle'
213
218
  assert_equal "", t(@myung, @name.rtrim(@name))
214
219
  end
215
220
 
216
221
  def test_coalesce
217
- if ENV['DB'] == 'postgresql'
222
+ if @env_db == 'postgresql'
218
223
  assert_equal 100, t(@test, @age.coalesce(100))
219
224
  assert_equal "Camille", t(@camille, @name.coalesce(nil, "default"))
220
225
  assert_equal 20, t(@test, @age.coalesce(nil, 20))
@@ -224,7 +229,10 @@ module ArelExtensions
224
229
  end
225
230
  end
226
231
 
227
- def test_comparator
232
+
233
+
234
+ # Comparators
235
+ def test_number_comparator
228
236
  assert_equal 2, User.where(@age < 6).count
229
237
  assert_equal 2, User.where(@age <= 10).count
230
238
  assert_equal 3, User.where(@age > 20).count
@@ -232,27 +240,31 @@ module ArelExtensions
232
240
  assert_equal 1, User.where(@age > 5).where(@age < 20).count
233
241
  end
234
242
 
243
+ def test_date_comparator
244
+ d = Date.new(2016,05,23)
245
+ assert_equal 0, User.where(@created_at < d).count
246
+ assert_equal 8, User.where(@created_at >= d).count
247
+ end
248
+
235
249
  def test_date_duration
236
250
  #Year
237
- assert_equal 2016, @lucas.select((User.arel_table[:created_at].year).as("res")).first.res.to_i
251
+ assert_equal 2016, t(@lucas, @created_at.year).to_i
238
252
  assert_equal 0, User.where(@created_at.year.eq("2012")).count
239
253
  #Month
240
- assert_equal 5, @camille.select((User.arel_table[:created_at].month).as("res")).first.res.to_i
241
- assert_equal 8,User.where(User.arel_table[:created_at].month.eq("05")).count
254
+ assert_equal 5, t(@camille, @created_at.month).to_i
255
+ assert_equal 8, User.where(@created_at.month.eq("05")).count
242
256
  #Week
243
- assert_equal 21,User.where(User.arel_table[:name].eq("Arthur")).select((User.arel_table[:created_at].week).as("res")).first.res.to_i
244
- assert_equal 8,User.where(User.arel_table[:created_at].month.eq("05")).count
257
+ assert_equal 21, t(@arthur, @created_at.week).to_i
258
+ assert_equal 8, User.where(@created_at.month.eq("05")).count
245
259
  #Day
246
- assert_equal 23,User.where(User.arel_table[:name].eq("Laure")).select((User.arel_table[:created_at].day).as("res")).first.res.to_i
247
- assert_equal 0,User.where(User.arel_table[:created_at].day.eq("05")).count
260
+ assert_equal 23, t(@laure, @created_at.day).to_i
261
+ assert_equal 0, User.where(@created_at.day.eq("05")).count
248
262
  end
249
263
 
250
-
251
264
  def test_is_null
252
265
  assert_equal "Test", User.where(@age.is_null).select(@name).first.name
253
266
  end
254
267
 
255
-
256
268
  def test_math_plus
257
269
  d = Date.new(1997, 6, 15)
258
270
  #Concat String
@@ -261,7 +273,8 @@ module ArelExtensions
261
273
  assert_equal "Sophie1997-06-15", t(@sophie, @name + d)
262
274
  assert_equal "Sophie15", t(@sophie, @name + @age)
263
275
  assert_equal "SophieSophie", t(@sophie, @name + @name)
264
- assert_equal "Sophie2016-05-23", t(@sophie, @name + @created_at)
276
+ #FIXME: should work as expected in Oracle
277
+ assert_equal "Sophie2016-05-23", t(@sophie, @name + @created_at) unless @env_db == 'oracle'
265
278
  #concat Integer
266
279
  assert_equal 1, User.where((@age + 10).eq(33)).count
267
280
  assert_equal 1, User.where((@age + "1").eq(6)).count
@@ -276,8 +289,8 @@ module ArelExtensions
276
289
  def test_math_moins
277
290
  d = Date.new(2016,05,20)
278
291
  #Datediff
279
- assert_equal 8, User.where((User.arel_table[:created_at] - User.arel_table[:created_at]).eq(0)).count
280
- assert_equal 3, User.where(User.arel_table[:name].eq("Laure")).select((User.arel_table[:created_at] - d).as("res")).first.res.abs.to_i
292
+ assert_equal 8, User.where((@created_at - User.arel_table[:created_at]).eq(0)).count
293
+ assert_equal 3, @laure.select((User.arel_table[:created_at] - d).as("res")).first.res.abs.to_i
281
294
  #Substraction
282
295
  assert_equal 0, User.where((@age - 10).eq(50)).count
283
296
  assert_equal 0, User.where((@age - "10").eq(50)).count
@@ -285,7 +298,7 @@ module ArelExtensions
285
298
 
286
299
  def test_wday
287
300
  d = Date.new(2016, 6, 26)
288
- assert_equal 1, t(@myung, @created_at.wday).to_i
301
+ assert_equal (@env_db == 'oracle' ? 2 : 1), t(@myung, @created_at.wday).to_i # monday
289
302
  assert_equal 0, User.select(d.wday).as("res").first.to_i
290
303
  end
291
304
 
@@ -7,16 +7,22 @@ module ArelExtensions
7
7
  class InsertManagerTest < Minitest::Test
8
8
  def setup_db
9
9
  ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
10
- ActiveRecord::Base.establish_connection(ENV['DB'].try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
10
+ if ENV['DB'] == 'oracle' && ((defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx") || (RUBY_PLATFORM == 'java')) # not supported
11
+ @env_db = (RUBY_PLATFORM == 'java' ? "jdbc-sqlite" : 'sqlite')
12
+ skip "Platform not supported"
13
+ else
14
+ @env_db = ENV['DB']
15
+ end
16
+ ActiveRecord::Base.establish_connection(@env_db.try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
11
17
  ActiveRecord::Base.default_timezone = :utc
12
18
  @cnx = ActiveRecord::Base.connection
13
19
  Arel::Table.engine = ActiveRecord::Base
14
- if File.exist?("init/#{ENV['DB']}.sql")
15
- sql = File.read("init/#{ENV['DB']}.sql")
20
+ if File.exist?("init/#{@env_db}.sql")
21
+ sql = File.read("init/#{@env_db}.sql")
16
22
  @cnx.execute(sql) unless sql.blank?
17
23
  end
18
- @cnx.drop_table(:users) rescue nil
19
- @cnx.create_table :users do |t|
24
+ @cnx.drop_table(:user_tests) rescue nil
25
+ @cnx.create_table :user_tests do |t|
20
26
  t.column :age, :integer
21
27
  t.column :name, :string
22
28
  t.column :comments, :text
@@ -28,7 +34,7 @@ module ArelExtensions
28
34
 
29
35
  def setup
30
36
  setup_db
31
- @table = Arel::Table.new(:users)
37
+ @table = Arel::Table.new(:user_tests)
32
38
  @cols = ['id', 'name', 'comments', 'created_at']
33
39
  @data = [
34
40
  [23, 'nom1', "sdfdsfdsfsdfsd fdsf dsf dsf sdf afdg fsdg sg sd gsdfg e 54435 344", '2016-01-01'],
@@ -37,7 +43,7 @@ module ArelExtensions
37
43
  end
38
44
 
39
45
  def teardown
40
- @cnx.drop_table(:users)
46
+ @cnx.drop_table(:user_tests)
41
47
  end
42
48
 
43
49
  # Math Functions