arel_extensions 1.2.25 → 2.0.0.rc3
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/.rubocop.yml +4 -7
- data/.travis.yml +91 -61
- data/Gemfile +20 -15
- data/README.md +12 -17
- data/Rakefile +29 -40
- data/appveyor.yml +1 -1
- data/arel_extensions.gemspec +3 -3
- data/functions.html +3 -3
- data/gemfiles/rails3.gemfile +9 -9
- data/gemfiles/rails4.gemfile +13 -13
- data/gemfiles/rails5_0.gemfile +13 -13
- data/gemfiles/rails5_1_4.gemfile +13 -13
- data/gemfiles/rails5_2.gemfile +13 -13
- data/init/mssql.sql +4 -4
- data/init/mysql.sql +38 -38
- data/init/postgresql.sql +21 -21
- data/lib/arel_extensions/attributes.rb +1 -0
- data/lib/arel_extensions/boolean_functions.rb +14 -55
- data/lib/arel_extensions/common_sql_functions.rb +8 -7
- data/lib/arel_extensions/comparators.rb +15 -14
- data/lib/arel_extensions/date_duration.rb +5 -4
- data/lib/arel_extensions/insert_manager.rb +16 -17
- data/lib/arel_extensions/math.rb +12 -11
- data/lib/arel_extensions/math_functions.rb +22 -29
- data/lib/arel_extensions/nodes/abs.rb +1 -0
- data/lib/arel_extensions/nodes/blank.rb +1 -0
- data/lib/arel_extensions/nodes/case.rb +8 -11
- data/lib/arel_extensions/nodes/cast.rb +2 -4
- data/lib/arel_extensions/nodes/ceil.rb +1 -1
- data/lib/arel_extensions/nodes/change_case.rb +0 -0
- data/lib/arel_extensions/nodes/coalesce.rb +3 -2
- data/lib/arel_extensions/nodes/collate.rb +2 -1
- data/lib/arel_extensions/nodes/concat.rb +16 -7
- data/lib/arel_extensions/nodes/date_diff.rb +13 -10
- data/lib/arel_extensions/nodes/duration.rb +3 -0
- data/lib/arel_extensions/nodes/find_in_set.rb +1 -0
- data/lib/arel_extensions/nodes/floor.rb +1 -1
- data/lib/arel_extensions/nodes/format.rb +8 -34
- data/lib/arel_extensions/nodes/formatted_number.rb +23 -22
- data/lib/arel_extensions/nodes/function.rb +16 -25
- data/lib/arel_extensions/nodes/json.rb +36 -43
- data/lib/arel_extensions/nodes/length.rb +0 -5
- data/lib/arel_extensions/nodes/levenshtein_distance.rb +0 -0
- data/lib/arel_extensions/nodes/locate.rb +1 -0
- data/lib/arel_extensions/nodes/log10.rb +2 -1
- data/lib/arel_extensions/nodes/matches.rb +6 -4
- data/lib/arel_extensions/nodes/md5.rb +1 -0
- data/lib/arel_extensions/nodes/power.rb +5 -5
- data/lib/arel_extensions/nodes/rand.rb +1 -0
- data/lib/arel_extensions/nodes/repeat.rb +4 -2
- data/lib/arel_extensions/nodes/replace.rb +6 -22
- data/lib/arel_extensions/nodes/round.rb +6 -5
- data/lib/arel_extensions/nodes/soundex.rb +15 -15
- data/lib/arel_extensions/nodes/std.rb +21 -18
- data/lib/arel_extensions/nodes/substring.rb +16 -8
- data/lib/arel_extensions/nodes/then.rb +0 -0
- data/lib/arel_extensions/nodes/trim.rb +5 -3
- data/lib/arel_extensions/nodes/union.rb +5 -2
- data/lib/arel_extensions/nodes/union_all.rb +3 -0
- data/lib/arel_extensions/nodes/wday.rb +4 -0
- data/lib/arel_extensions/nodes.rb +1 -1
- data/lib/arel_extensions/null_functions.rb +7 -5
- data/lib/arel_extensions/predications.rb +34 -35
- data/lib/arel_extensions/railtie.rb +5 -5
- data/lib/arel_extensions/set_functions.rb +4 -2
- data/lib/arel_extensions/string_functions.rb +23 -52
- data/lib/arel_extensions/tasks.rb +5 -5
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/ibm_db.rb +12 -5
- data/lib/arel_extensions/visitors/mssql.rb +58 -64
- data/lib/arel_extensions/visitors/mysql.rb +98 -149
- data/lib/arel_extensions/visitors/oracle.rb +70 -73
- data/lib/arel_extensions/visitors/oracle12.rb +15 -2
- data/lib/arel_extensions/visitors/postgresql.rb +63 -116
- data/lib/arel_extensions/visitors/sqlite.rb +70 -83
- data/lib/arel_extensions/visitors/to_sql.rb +110 -142
- data/lib/arel_extensions/visitors.rb +60 -68
- data/lib/arel_extensions.rb +19 -81
- data/test/database.yml +0 -2
- data/test/helper.rb +18 -0
- data/test/real_db_test.rb +43 -28
- data/test/support/fake_record.rb +2 -2
- data/test/test_comparators.rb +12 -9
- data/test/visitors/test_bulk_insert_oracle.rb +8 -8
- data/test/visitors/test_bulk_insert_sqlite.rb +10 -9
- data/test/visitors/test_bulk_insert_to_sql.rb +10 -8
- data/test/visitors/test_oracle.rb +42 -42
- data/test/visitors/test_to_sql.rb +196 -361
- data/test/with_ar/all_agnostic_test.rb +160 -195
- data/test/with_ar/insert_agnostic_test.rb +4 -3
- data/test/with_ar/test_bulk_sqlite.rb +9 -6
- data/test/with_ar/test_math_sqlite.rb +12 -8
- data/test/with_ar/test_string_mysql.rb +11 -5
- data/test/with_ar/test_string_sqlite.rb +12 -4
- metadata +11 -22
- data/.github/workflows/ruby.yml +0 -102
- data/gemfiles/rails6.gemfile +0 -30
- data/gemfiles/rails6_1.gemfile +0 -30
- data/gemspecs/arel_extensions-v1.gemspec +0 -28
- data/gemspecs/arel_extensions-v2.gemspec +0 -28
- data/generate_gems.sh +0 -15
- data/lib/arel_extensions/nodes/aggregate_function.rb +0 -13
- data/lib/arel_extensions/nodes/sum.rb +0 -7
- data/lib/arel_extensions/visitors/convert_format.rb +0 -37
- data/test/arelx_test_helper.rb +0 -26
- data/version_v1.rb +0 -3
- data/version_v2.rb +0 -3
data/gemfiles/rails5_0.gemfile
CHANGED
@@ -7,23 +7,23 @@ group :development, :test do
|
|
7
7
|
gem 'activemodel', '~> 5.0'
|
8
8
|
gem 'activerecord', '5.0.6'
|
9
9
|
|
10
|
-
gem "sqlite3", '<= 1.3.13', platforms
|
11
|
-
gem "mysql2", '0.4.10', platforms
|
12
|
-
gem "pg",'< 1.0.0', platforms
|
10
|
+
gem "sqlite3", '<= 1.3.13', :platforms => [:mri, :mswin, :mingw]
|
11
|
+
gem "mysql2", '0.4.10', :platforms => [:mri, :mswin, :mingw]
|
12
|
+
gem "pg",'< 1.0.0', :platforms => [:mri, :mingw]
|
13
13
|
|
14
|
-
gem "tiny_tds", platforms
|
15
|
-
#
|
14
|
+
gem "tiny_tds", :platforms => [:mri, :mingw] if RUBY_PLATFORM =~ /windows/
|
15
|
+
#gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
|
16
16
|
|
17
|
-
gem 'ruby-oci8', platforms
|
17
|
+
gem 'ruby-oci8', :platforms => [:mri, :mswin, :mingw] if ENV.has_key? 'ORACLE_HOME'
|
18
18
|
gem 'activerecord-oracle_enhanced-adapter', '~> 1.7' if ENV.has_key? 'ORACLE_HOME'
|
19
19
|
|
20
20
|
# for JRuby
|
21
|
-
gem 'activerecord-jdbc-adapter', github
|
22
|
-
gem "jdbc-sqlite3", platforms
|
23
|
-
gem "activerecord-jdbcsqlite3-adapter", platforms
|
24
|
-
gem "activerecord-jdbcmysql-adapter", platforms
|
25
|
-
gem "activerecord-jdbcpostgresql-adapter", platforms
|
26
|
-
gem "activerecord-jdbcmssql-adapter", platforms
|
21
|
+
gem 'activerecord-jdbc-adapter', :github => 'jruby/activerecord-jdbc-adapter', :tag => 'v50.0', :platforms => :jruby
|
22
|
+
gem "jdbc-sqlite3", :platforms => :jruby
|
23
|
+
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
24
|
+
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
|
25
|
+
gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
|
26
|
+
gem "activerecord-jdbcmssql-adapter", :platforms => :jruby
|
27
27
|
end
|
28
28
|
|
29
|
-
gemspec path
|
29
|
+
gemspec :path => "../"
|
data/gemfiles/rails5_1_4.gemfile
CHANGED
@@ -8,23 +8,23 @@ group :development, :test do
|
|
8
8
|
gem 'activemodel', '5.1.4'
|
9
9
|
gem 'activerecord', '5.1.4'
|
10
10
|
|
11
|
-
gem "sqlite3", '<= 1.3.13', platforms
|
12
|
-
gem "mysql2", '0.4.10', platforms
|
13
|
-
gem "pg",'< 1.0.0', platforms
|
11
|
+
gem "sqlite3", '<= 1.3.13', :platforms => [:mri, :mswin, :mingw]
|
12
|
+
gem "mysql2", '0.4.10', :platforms => [:mri, :mswin, :mingw]
|
13
|
+
gem "pg",'< 1.0.0', :platforms => [:mri, :mingw]
|
14
14
|
|
15
|
-
gem "tiny_tds", platforms
|
16
|
-
#
|
15
|
+
gem "tiny_tds", :platforms => [:mri, :mingw] if RUBY_PLATFORM =~ /windows/
|
16
|
+
#gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
|
17
17
|
|
18
|
-
gem 'ruby-oci8', platforms
|
18
|
+
gem 'ruby-oci8', :platforms => [:mri, :mswin, :mingw] if ENV.has_key? 'ORACLE_HOME'
|
19
19
|
gem 'activerecord-oracle_enhanced-adapter', '~> 1.8' if ENV.has_key? 'ORACLE_HOME'
|
20
20
|
|
21
21
|
# for JRuby
|
22
|
-
gem 'activerecord-jdbc-adapter', github
|
23
|
-
gem "jdbc-sqlite3", platforms
|
24
|
-
gem "activerecord-jdbcsqlite3-adapter", platforms
|
25
|
-
gem "activerecord-jdbcmysql-adapter", platforms
|
26
|
-
gem "activerecord-jdbcpostgresql-adapter", platforms
|
27
|
-
gem "activerecord-jdbcmssql-adapter", platforms
|
22
|
+
gem 'activerecord-jdbc-adapter', :github => 'jruby/activerecord-jdbc-adapter', :tag => 'v51.0', :platforms => :jruby
|
23
|
+
gem "jdbc-sqlite3", :platforms => :jruby
|
24
|
+
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
25
|
+
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
|
26
|
+
gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
|
27
|
+
gem "activerecord-jdbcmssql-adapter", :platforms => :jruby
|
28
28
|
end
|
29
29
|
|
30
|
-
gemspec path
|
30
|
+
gemspec :path => "../"
|
data/gemfiles/rails5_2.gemfile
CHANGED
@@ -8,23 +8,23 @@ group :development, :test do
|
|
8
8
|
gem 'activemodel', '~> 5.2.0'
|
9
9
|
gem 'activerecord', '~> 5.2.0'
|
10
10
|
|
11
|
-
gem "sqlite3", '<= 1.3.13', platforms
|
12
|
-
gem "mysql2", '0.4.10', platforms
|
13
|
-
gem "pg",'< 1.0.0', platforms
|
11
|
+
gem "sqlite3", '<= 1.3.13', :platforms => [:mri, :mswin, :mingw]
|
12
|
+
gem "mysql2", '0.4.10', :platforms => [:mri, :mswin, :mingw]
|
13
|
+
gem "pg",'< 1.0.0', :platforms => [:mri, :mingw]
|
14
14
|
|
15
|
-
gem "tiny_tds", platforms
|
16
|
-
#
|
15
|
+
gem "tiny_tds", :platforms => [:mri, :mingw] if RUBY_PLATFORM =~ /windows/
|
16
|
+
#gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
|
17
17
|
|
18
|
-
gem 'ruby-oci8', platforms
|
18
|
+
gem 'ruby-oci8', :platforms => [:mri, :mswin, :mingw] if ENV.has_key? 'ORACLE_HOME'
|
19
19
|
gem 'activerecord-oracle_enhanced-adapter', '~> 5.2.0' if ENV.has_key? 'ORACLE_HOME'
|
20
20
|
|
21
21
|
# for JRuby
|
22
|
-
gem 'activerecord-jdbc-adapter', github
|
23
|
-
gem "jdbc-sqlite3", platforms
|
24
|
-
gem "activerecord-jdbcsqlite3-adapter", platforms
|
25
|
-
gem "activerecord-jdbcmysql-adapter", platforms
|
26
|
-
gem "activerecord-jdbcpostgresql-adapter", platforms
|
27
|
-
gem "activerecord-jdbcmssql-adapter", platforms
|
22
|
+
gem 'activerecord-jdbc-adapter', :github => 'jruby/activerecord-jdbc-adapter', :tag => 'v52.0', :platforms => :jruby
|
23
|
+
gem "jdbc-sqlite3", :platforms => :jruby
|
24
|
+
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
25
|
+
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
|
26
|
+
gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
|
27
|
+
gem "activerecord-jdbcmssql-adapter", :platforms => :jruby
|
28
28
|
end
|
29
29
|
|
30
|
-
gemspec path
|
30
|
+
gemspec :path => "../"
|
data/init/mssql.sql
CHANGED
@@ -83,7 +83,7 @@ BEGIN
|
|
83
83
|
END
|
84
84
|
SELECT @cv1 = @cv0, @i = @i + 1
|
85
85
|
END
|
86
|
-
RETURN @c
|
86
|
+
RETURN @c
|
87
87
|
END
|
88
88
|
GO
|
89
89
|
|
@@ -94,9 +94,9 @@ GO
|
|
94
94
|
--RETURNS TABLE
|
95
95
|
--AS
|
96
96
|
--BEGIN
|
97
|
-
-- RETURN ( SELECT [Value] FROM
|
98
|
-
-- (
|
99
|
-
-- SELECT
|
97
|
+
-- RETURN ( SELECT [Value] FROM
|
98
|
+
-- (
|
99
|
+
-- SELECT
|
100
100
|
-- [Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
|
101
101
|
-- CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
|
102
102
|
-- FROM (SELECT Number = ROW_NUMBER() OVER (ORDER BY name)
|
data/init/mysql.sql
CHANGED
@@ -1,45 +1,45 @@
|
|
1
1
|
DELIMITER $$
|
2
2
|
|
3
3
|
DROP FUNCTION IF EXISTS levenshtein_distance; $$
|
4
|
-
CREATE FUNCTION levenshtein_distance( s1 VARCHAR(255), s2 VARCHAR(255) )
|
5
|
-
RETURNS INT
|
6
|
-
DETERMINISTIC
|
7
|
-
BEGIN
|
8
|
-
DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
|
9
|
-
DECLARE s1_char CHAR;
|
10
|
-
-- max strlen=255
|
11
|
-
DECLARE cv0, cv1 VARBINARY(256);
|
4
|
+
CREATE FUNCTION levenshtein_distance( s1 VARCHAR(255), s2 VARCHAR(255) )
|
5
|
+
RETURNS INT
|
6
|
+
DETERMINISTIC
|
7
|
+
BEGIN
|
8
|
+
DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
|
9
|
+
DECLARE s1_char CHAR;
|
10
|
+
-- max strlen=255
|
11
|
+
DECLARE cv0, cv1 VARBINARY(256);
|
12
12
|
SET s1 = IFNULL(s1,''), s2 = IFNULL(s2,'');
|
13
|
-
SET s1_len = CHAR_LENGTH(IFNULL(s1,'')), s2_len = CHAR_LENGTH(IFNULL(s2,'')), cv1 = 0x00, j = 1, i = 1, c = 0;
|
14
|
-
IF s1_len = 0 THEN
|
15
|
-
RETURN s2_len;
|
16
|
-
ELSEIF s2_len = 0 THEN
|
17
|
-
RETURN s1_len;
|
18
|
-
ELSEIF s1 = s2 THEN
|
13
|
+
SET s1_len = CHAR_LENGTH(IFNULL(s1,'')), s2_len = CHAR_LENGTH(IFNULL(s2,'')), cv1 = 0x00, j = 1, i = 1, c = 0;
|
14
|
+
IF s1_len = 0 THEN
|
15
|
+
RETURN s2_len;
|
16
|
+
ELSEIF s2_len = 0 THEN
|
17
|
+
RETURN s1_len;
|
18
|
+
ELSEIF s1 = s2 THEN
|
19
19
|
RETURN 0;
|
20
|
-
ELSE
|
21
|
-
WHILE j <= s2_len DO
|
22
|
-
SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1;
|
23
|
-
END WHILE;
|
24
|
-
WHILE i <= s1_len DO
|
25
|
-
SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1;
|
26
|
-
WHILE j <= s2_len DO
|
27
|
-
SET c = c + 1;
|
28
|
-
IF s1_char = SUBSTRING(s2, j, 1) THEN
|
29
|
-
SET cost = 0; ELSE SET cost = 1;
|
30
|
-
END IF;
|
31
|
-
SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost;
|
32
|
-
IF c > c_temp THEN SET c = c_temp; END IF;
|
33
|
-
SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1;
|
34
|
-
IF c > c_temp THEN
|
35
|
-
SET c = c_temp;
|
36
|
-
END IF;
|
37
|
-
SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1;
|
38
|
-
END WHILE;
|
39
|
-
SET cv1 = cv0, i = i + 1;
|
40
|
-
END WHILE;
|
41
|
-
END IF;
|
42
|
-
RETURN c;
|
20
|
+
ELSE
|
21
|
+
WHILE j <= s2_len DO
|
22
|
+
SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1;
|
23
|
+
END WHILE;
|
24
|
+
WHILE i <= s1_len DO
|
25
|
+
SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1;
|
26
|
+
WHILE j <= s2_len DO
|
27
|
+
SET c = c + 1;
|
28
|
+
IF s1_char = SUBSTRING(s2, j, 1) THEN
|
29
|
+
SET cost = 0; ELSE SET cost = 1;
|
30
|
+
END IF;
|
31
|
+
SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost;
|
32
|
+
IF c > c_temp THEN SET c = c_temp; END IF;
|
33
|
+
SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1;
|
34
|
+
IF c > c_temp THEN
|
35
|
+
SET c = c_temp;
|
36
|
+
END IF;
|
37
|
+
SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1;
|
38
|
+
END WHILE;
|
39
|
+
SET cv1 = cv0, i = i + 1;
|
40
|
+
END WHILE;
|
41
|
+
END IF;
|
42
|
+
RETURN c;
|
43
43
|
END;$$
|
44
|
-
|
44
|
+
|
45
45
|
DELIMITER ;
|
data/init/postgresql.sql
CHANGED
@@ -4,17 +4,17 @@ CREATE OR REPLACE FUNCTION public.find_in_set(n INTEGER, s TEXT)
|
|
4
4
|
AS $function$
|
5
5
|
SELECT * FROM (
|
6
6
|
select int4(z.row_number) from (
|
7
|
-
select row_number() over(), y.x
|
7
|
+
select row_number() over(), y.x
|
8
8
|
from (select unnest(('{' || $2 || '}')::int[]) as x) as y
|
9
9
|
) as z
|
10
10
|
where z.x = $1
|
11
|
-
UNION ALL
|
11
|
+
UNION ALL
|
12
12
|
SELECT 0) z
|
13
13
|
LIMIT 1
|
14
14
|
$function$
|
15
15
|
;
|
16
16
|
|
17
|
-
CREATE OR REPLACE FUNCTION public.levenshtein_distance(s text, t text)
|
17
|
+
CREATE OR REPLACE FUNCTION public.levenshtein_distance(s text, t text)
|
18
18
|
RETURNS integer AS $$
|
19
19
|
DECLARE i integer;
|
20
20
|
DECLARE j integer;
|
@@ -48,58 +48,58 @@ BEGIN
|
|
48
48
|
d[i*(n+1)+j] := LEAST(d[(i-1)*(n+1)+j]+1, d[i*(n+1)+j-1]+1, d[(i-1)*(n+1)+j-1]+c);
|
49
49
|
END LOOP;
|
50
50
|
END LOOP;
|
51
|
-
|
52
|
-
return d[m*(n+1)+n];
|
51
|
+
|
52
|
+
return d[m*(n+1)+n];
|
53
53
|
END;
|
54
54
|
$$ LANGUAGE plpgsql IMMUTABLE;
|
55
55
|
|
56
|
-
CREATE OR REPLACE FUNCTION public.DateDiff(units VARCHAR(30), start_t TIMESTAMP, end_t TIMESTAMP)
|
56
|
+
CREATE OR REPLACE FUNCTION public.DateDiff(units VARCHAR(30), start_t TIMESTAMP, end_t TIMESTAMP)
|
57
57
|
RETURNS INT AS $$
|
58
58
|
DECLARE
|
59
|
-
diff_interval INTERVAL;
|
59
|
+
diff_interval INTERVAL;
|
60
60
|
diff INT = 0;
|
61
61
|
years_diff INT = 0;
|
62
62
|
BEGIN
|
63
63
|
IF units IN ('yy', 'yyyy', 'year', 'mm', 'm', 'month') THEN
|
64
64
|
years_diff = DATE_PART('year', end_t) - DATE_PART('year', start_t);
|
65
|
-
|
65
|
+
|
66
66
|
IF units IN ('yy', 'yyyy', 'year') THEN
|
67
67
|
-- SQL Server does not count full years passed (only difference between year parts)
|
68
68
|
RETURN years_diff;
|
69
69
|
ELSE
|
70
70
|
-- If end month is less than start month it will subtracted
|
71
|
-
RETURN years_diff * 12 + (DATE_PART('month', end_t) - DATE_PART('month', start_t));
|
71
|
+
RETURN years_diff * 12 + (DATE_PART('month', end_t) - DATE_PART('month', start_t));
|
72
72
|
END IF;
|
73
73
|
END IF;
|
74
|
-
|
75
|
-
-- Minus operator returns interval 'DDD days HH:MI:SS'
|
74
|
+
|
75
|
+
-- Minus operator returns interval 'DDD days HH:MI:SS'
|
76
76
|
diff_interval = end_t - start_t;
|
77
|
-
|
77
|
+
|
78
78
|
diff = diff + DATE_PART('day', diff_interval);
|
79
|
-
|
79
|
+
|
80
80
|
IF units IN ('wk', 'ww', 'week') THEN
|
81
81
|
diff = diff/7;
|
82
82
|
RETURN diff;
|
83
83
|
END IF;
|
84
|
-
|
84
|
+
|
85
85
|
IF units IN ('dd', 'd', 'day') THEN
|
86
86
|
RETURN diff;
|
87
87
|
END IF;
|
88
|
-
|
89
|
-
diff = diff * 24 + DATE_PART('hour', diff_interval);
|
90
|
-
|
88
|
+
|
89
|
+
diff = diff * 24 + DATE_PART('hour', diff_interval);
|
90
|
+
|
91
91
|
IF units IN ('hh', 'hour') THEN
|
92
92
|
RETURN diff;
|
93
93
|
END IF;
|
94
|
-
|
94
|
+
|
95
95
|
diff = diff * 60 + DATE_PART('minute', diff_interval);
|
96
|
-
|
96
|
+
|
97
97
|
IF units IN ('mi', 'n', 'minute') THEN
|
98
98
|
RETURN diff;
|
99
99
|
END IF;
|
100
|
-
|
100
|
+
|
101
101
|
diff = diff * 60 + DATE_PART('second', diff_interval);
|
102
|
-
|
102
|
+
|
103
103
|
RETURN diff;
|
104
104
|
END;
|
105
105
|
$$ LANGUAGE plpgsql;
|
@@ -1,15 +1,14 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
require 'arel_extensions/nodes/then'
|
4
2
|
|
5
3
|
module ArelExtensions
|
6
4
|
module BooleanFunctions
|
5
|
+
|
7
6
|
def ⋀(other)
|
8
7
|
self.and(other)
|
9
8
|
end
|
10
9
|
|
11
10
|
def and *others
|
12
|
-
Arel::Nodes::And.new
|
11
|
+
Arel::Nodes::And.new([self]+ others.flatten)
|
13
12
|
end
|
14
13
|
|
15
14
|
def ⋁(other)
|
@@ -17,7 +16,12 @@ module ArelExtensions
|
|
17
16
|
end
|
18
17
|
|
19
18
|
def or *others
|
20
|
-
|
19
|
+
args = others.flatten
|
20
|
+
if args.length == 1
|
21
|
+
Arel::Nodes::Or.new(self, args.first)
|
22
|
+
else
|
23
|
+
ArelExtensions::Nodes::Or.new([self]+ args)
|
24
|
+
end
|
21
25
|
end
|
22
26
|
|
23
27
|
def then(t, f = nil)
|
@@ -26,61 +30,16 @@ module ArelExtensions
|
|
26
30
|
end
|
27
31
|
end
|
28
32
|
|
29
|
-
|
33
|
+
Arel::Nodes::And.class_eval do
|
30
34
|
include ArelExtensions::BooleanFunctions
|
31
|
-
|
32
|
-
def self.new *children
|
33
|
-
children =
|
34
|
-
children.flatten.map { |c|
|
35
|
-
c.is_a?(self) ? c.children : c
|
36
|
-
}.flatten
|
37
|
-
super(children)
|
38
|
-
end
|
39
35
|
end
|
40
36
|
|
41
|
-
|
42
|
-
# stores @children, and hashes it all). However Arel's Or is defined
|
43
|
-
# as binary, with only @left and @right, and hashing only @left and @right.
|
44
|
-
#
|
45
|
-
# So reimplement its ctor and accessors.
|
46
|
-
|
47
|
-
class Arel::Nodes::Or
|
37
|
+
Arel::Nodes::Or.class_eval do
|
48
38
|
include ArelExtensions::BooleanFunctions
|
39
|
+
end
|
49
40
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
children =
|
54
|
-
children.flatten.map { |c|
|
55
|
-
c.is_a?(self) ? c.children : c
|
56
|
-
}.flatten
|
57
|
-
super(*children)
|
58
|
-
end
|
59
|
-
|
60
|
-
def initialize *children
|
61
|
-
@children = children
|
62
|
-
end
|
63
|
-
|
64
|
-
def initialize_copy(other)
|
65
|
-
super
|
66
|
-
@children = other.children.copy if other.children
|
67
|
-
end
|
68
|
-
|
69
|
-
def left
|
70
|
-
children.first
|
71
|
-
end
|
72
|
-
|
73
|
-
def right
|
74
|
-
children[1]
|
75
|
-
end
|
41
|
+
ArelExtensions::Nodes.const_set('Or',Class.new(Arel::Nodes::And)).class_eval do
|
42
|
+
include ArelExtensions::BooleanFunctions
|
43
|
+
end
|
76
44
|
|
77
|
-
def hash
|
78
|
-
children.hash
|
79
|
-
end
|
80
45
|
|
81
|
-
def eql?(other)
|
82
|
-
self.class == other.class &&
|
83
|
-
children == other.children
|
84
|
-
end
|
85
|
-
alias :== :eql?
|
86
|
-
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module ArelExtensions
|
2
2
|
class CommonSqlFunctions
|
3
|
+
|
3
4
|
def initialize(cnx)
|
4
5
|
@cnx = cnx
|
5
6
|
if cnx && cnx.adapter_name =~ /sqlite/i && !$load_extension_disabled
|
@@ -11,7 +12,7 @@ module ArelExtensions
|
|
11
12
|
db.enable_load_extension(0)
|
12
13
|
rescue => e
|
13
14
|
$load_extension_disabled = true
|
14
|
-
puts "
|
15
|
+
puts "can not load extensions #{e.inspect}"
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
@@ -38,12 +39,11 @@ module ArelExtensions
|
|
38
39
|
|
39
40
|
def add_sql_functions(env_db = nil)
|
40
41
|
env_db ||= @cnx.adapter_name
|
41
|
-
env_db = 'mysql' if env_db =~ /mysql/i
|
42
42
|
if env_db =~ /sqlite/i
|
43
43
|
begin
|
44
44
|
add_sqlite_functions
|
45
45
|
rescue => e
|
46
|
-
puts "
|
46
|
+
puts "can not add sqlite functions #{e.inspect}"
|
47
47
|
end
|
48
48
|
end
|
49
49
|
if File.exist?("init/#{env_db}.sql")
|
@@ -52,14 +52,15 @@ module ArelExtensions
|
|
52
52
|
sql.split(/^GO\s*$/).each {|str|
|
53
53
|
@cnx.execute(str.strip) unless str.blank?
|
54
54
|
}
|
55
|
-
elsif env_db =='mysql'
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
elsif env_db == 'mysql'
|
56
|
+
sql.split("$$")[1..-2].each { |str|
|
57
|
+
@cnx.execute(str.strip) unless str.strip.blank?
|
58
|
+
}
|
59
59
|
else
|
60
60
|
@cnx.execute(sql) unless sql.blank?
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
64
|
+
|
64
65
|
end
|
65
66
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module ArelExtensions
|
2
2
|
module Comparators
|
3
|
+
|
3
4
|
def >(other)
|
4
5
|
Arel::Nodes::GreaterThan.new self, Arel::Nodes.build_quoted(other, self)
|
5
6
|
end
|
@@ -16,34 +17,33 @@ module ArelExtensions
|
|
16
17
|
Arel::Nodes::LessThanOrEqual.new self, Arel::Nodes.build_quoted(other, self)
|
17
18
|
end
|
18
19
|
|
19
|
-
|
20
|
-
#
|
20
|
+
|
21
|
+
#REGEXP function
|
22
|
+
#Pattern matching using regular expressions
|
21
23
|
def =~(other)
|
22
|
-
|
23
|
-
|
24
|
+
# arg = self.relation.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s].type
|
25
|
+
# if arg == :string || arg == :text
|
24
26
|
Arel::Nodes::Regexp.new self, convert_regexp(other)
|
25
|
-
|
27
|
+
# end
|
26
28
|
end
|
27
29
|
|
28
|
-
#
|
29
|
-
#
|
30
|
+
#NOT_REGEXP function
|
31
|
+
#Negation of Regexp
|
30
32
|
def !~(other)
|
31
|
-
|
32
|
-
|
33
|
+
# arg = self.relation.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s].type
|
34
|
+
# if arg == :string || arg == :text
|
33
35
|
Arel::Nodes::NotRegexp.new self, convert_regexp(other)
|
34
|
-
|
36
|
+
# end
|
35
37
|
end
|
36
38
|
|
37
39
|
private
|
38
|
-
|
39
|
-
# Function used for not_regexp.
|
40
|
+
#Function use for not_regexp
|
40
41
|
def convert_regexp(other)
|
41
42
|
case other
|
42
43
|
when String
|
43
|
-
#
|
44
|
+
#Do nothing
|
44
45
|
when Regexp
|
45
46
|
other = other.source.gsub('\A','^')
|
46
|
-
other.gsub!('\z','$')
|
47
47
|
other.gsub!('\Z','$')
|
48
48
|
other.gsub!('\d','[0-9]')
|
49
49
|
other.gsub!('\D','[^0-9]')
|
@@ -54,5 +54,6 @@ module ArelExtensions
|
|
54
54
|
end
|
55
55
|
Arel::Nodes.build_quoted(other, self)
|
56
56
|
end
|
57
|
+
|
57
58
|
end
|
58
59
|
end
|
@@ -4,22 +4,22 @@ require 'arel_extensions/nodes/wday'
|
|
4
4
|
|
5
5
|
module ArelExtensions
|
6
6
|
module DateDuration
|
7
|
-
#
|
7
|
+
#function returns the year (as a number) given a date value.
|
8
8
|
def year
|
9
9
|
ArelExtensions::Nodes::Duration.new "y", self
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
#function returns the month (as a number) given a date value.
|
13
13
|
def month
|
14
14
|
ArelExtensions::Nodes::Duration.new "m", self
|
15
15
|
end
|
16
16
|
|
17
|
-
#
|
17
|
+
#function returns the week (as a number) given a date value.
|
18
18
|
def week
|
19
19
|
ArelExtensions::Nodes::Duration.new "w", self
|
20
20
|
end
|
21
21
|
|
22
|
-
#
|
22
|
+
#function returns the month (as a number) given a date value.
|
23
23
|
def day
|
24
24
|
ArelExtensions::Nodes::Duration.new "d", self
|
25
25
|
end
|
@@ -43,5 +43,6 @@ module ArelExtensions
|
|
43
43
|
def format(tpl)
|
44
44
|
ArelExtensions::Nodes::Format.new [self, tpl]
|
45
45
|
end
|
46
|
+
|
46
47
|
end
|
47
48
|
end
|
@@ -2,33 +2,32 @@ require 'arel'
|
|
2
2
|
|
3
3
|
module ArelExtensions
|
4
4
|
module InsertManager
|
5
|
+
|
5
6
|
def bulk_insert(cols, data)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
case cols.first
|
8
|
+
when String, Symbol
|
9
|
+
cols.each { |c|
|
10
|
+
@ast.columns << @ast.relation[c]
|
11
|
+
}
|
12
|
+
when Array
|
13
|
+
if String === cols.first.first
|
14
|
+
@ast.columns = cols.map {|c| [@ast.relation[c.first]] }
|
15
|
+
elsif Arel::Attributes::Attribute == cols.first.first
|
16
|
+
@ast.columns = cols
|
17
|
+
end
|
18
|
+
when NilClass
|
19
|
+
@ast.columns = @ast.relation.columns
|
17
20
|
end
|
18
|
-
|
19
|
-
res_columns = @ast.relation.columns
|
20
|
-
end
|
21
|
-
self.values = BulkValues.new(res_columns, data)
|
22
|
-
@ast.columns = res_columns
|
21
|
+
self.values = BulkValues.new(@ast.columns, data)
|
23
22
|
end
|
24
23
|
|
25
24
|
class BulkValues < Arel::Nodes::Node
|
26
25
|
attr_accessor :left, :cols
|
27
|
-
|
28
26
|
def initialize(cols, values)
|
29
27
|
@left = values
|
30
28
|
@cols = cols
|
31
29
|
end
|
32
30
|
end
|
31
|
+
|
33
32
|
end
|
34
33
|
end
|