arel_extensions 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +46 -0
  4. data/Gemfile +10 -0
  5. data/MIT-LICENSE.txt +20 -0
  6. data/README.md +101 -0
  7. data/Rakefile +14 -0
  8. data/arel_extensions.gemspec +32 -0
  9. data/functions.html +344 -0
  10. data/gemfiles/Gemfile.rails3 +10 -0
  11. data/gemfiles/Gemfile.rails5 +10 -0
  12. data/init/mssql.sql +6 -0
  13. data/init/mysql.sql +0 -0
  14. data/init/oracle.sql +31 -0
  15. data/init/postgresql.sql +12 -0
  16. data/init/sqlite.sql +1 -0
  17. data/lib/arel_extensions.rb +84 -0
  18. data/lib/arel_extensions/attributes.rb +26 -0
  19. data/lib/arel_extensions/comparators.rb +59 -0
  20. data/lib/arel_extensions/date_duration.rb +28 -0
  21. data/lib/arel_extensions/insert_manager.rb +33 -0
  22. data/lib/arel_extensions/math.rb +48 -0
  23. data/lib/arel_extensions/math_functions.rb +35 -0
  24. data/lib/arel_extensions/nodes.rb +27 -0
  25. data/lib/arel_extensions/nodes/abs.rb +6 -0
  26. data/lib/arel_extensions/nodes/ceil.rb +6 -0
  27. data/lib/arel_extensions/nodes/coalesce.rb +22 -0
  28. data/lib/arel_extensions/nodes/concat.rb +33 -0
  29. data/lib/arel_extensions/nodes/date_diff.rb +106 -0
  30. data/lib/arel_extensions/nodes/duration.rb +30 -0
  31. data/lib/arel_extensions/nodes/find_in_set.rb +16 -0
  32. data/lib/arel_extensions/nodes/floor.rb +6 -0
  33. data/lib/arel_extensions/nodes/function.rb +17 -0
  34. data/lib/arel_extensions/nodes/isnull.rb +30 -0
  35. data/lib/arel_extensions/nodes/length.rb +6 -0
  36. data/lib/arel_extensions/nodes/locate.rb +33 -0
  37. data/lib/arel_extensions/nodes/ltrim.rb +28 -0
  38. data/lib/arel_extensions/nodes/matches.rb +22 -0
  39. data/lib/arel_extensions/nodes/rand.rb +23 -0
  40. data/lib/arel_extensions/nodes/replace.rb +36 -0
  41. data/lib/arel_extensions/nodes/round.rb +15 -0
  42. data/lib/arel_extensions/nodes/rtrim.rb +29 -0
  43. data/lib/arel_extensions/nodes/soundex.rb +23 -0
  44. data/lib/arel_extensions/nodes/sum.rb +23 -0
  45. data/lib/arel_extensions/nodes/trim.rb +26 -0
  46. data/lib/arel_extensions/nodes/wday.rb +23 -0
  47. data/lib/arel_extensions/null_functions.rb +16 -0
  48. data/lib/arel_extensions/string_functions.rb +68 -0
  49. data/lib/arel_extensions/version.rb +4 -0
  50. data/lib/arel_extensions/visitors.rb +6 -0
  51. data/lib/arel_extensions/visitors/ibm_db.rb +206 -0
  52. data/lib/arel_extensions/visitors/mssql.rb +213 -0
  53. data/lib/arel_extensions/visitors/mysql.rb +184 -0
  54. data/lib/arel_extensions/visitors/oracle.rb +267 -0
  55. data/lib/arel_extensions/visitors/postgresql.rb +258 -0
  56. data/lib/arel_extensions/visitors/sqlite.rb +218 -0
  57. data/lib/arel_extensions/visitors/to_sql.rb +199 -0
  58. data/test/helper.rb +18 -0
  59. data/test/real_db_test.rb +251 -0
  60. data/test/support/fake_record.rb +137 -0
  61. data/test/test_comparators.rb +49 -0
  62. data/test/visitors/test_bulk_insert_oracle.rb +30 -0
  63. data/test/visitors/test_bulk_insert_sqlite.rb +31 -0
  64. data/test/visitors/test_bulk_insert_to_sql.rb +32 -0
  65. data/test/visitors/test_oracle.rb +105 -0
  66. data/test/visitors/test_to_sql.rb +148 -0
  67. data/test/with_ar/test_bulk_sqlite.rb +44 -0
  68. data/test/with_ar/test_math_sqlite.rb +59 -0
  69. data/test/with_ar/test_string_sqlite.rb +69 -0
  70. metadata +230 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 087006edf929bdce808d6e2ba04a9e39923caa51
4
+ data.tar.gz: 0aaa1834a9d6939366ce9bda87dbacc3e60db044
5
+ SHA512:
6
+ metadata.gz: 26248a966e70e85b6b4baf615e273d1fe80661be799f44d119ef244e83f3d8a37c09fe14e488746eda992bb84595a9e2821fcf1f3535648ccb3da0159c420c55
7
+ data.tar.gz: a4e60ee3fa48f9dbff4a50a3c73edec8ed3c172372b69e2cb1ef6587eabb1b03acef5c625a824c8b536a490b033f1785b1a4541152b6fcacf66cebeb095ac794
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ coverage/*
2
+ config/database.yml
3
+ spec/support/fixtures/*database*
4
+ *.DS_Store
5
+ debug.log
6
+ pkg
7
+ .bundle
8
+ *.swp
9
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,46 @@
1
+ language: ruby
2
+ sudo: false
3
+ cache: bundler
4
+ before_install:
5
+ # - sudo apt-get update -qq
6
+ # - sudo apt-get install -qq sqlite3
7
+ #addons:
8
+ # mariadb: '10.0'
9
+ services:
10
+ - mysql
11
+ - postgresql
12
+ before_script:
13
+ - mysql -e 'create database arext_test;'
14
+ - psql -c 'create database arext_test;' -U postgres
15
+ script:
16
+ - "bundle exec rake test"
17
+ # - "bundle exec rake test:sqlite3"
18
+ - "gem build arel_extensions.gemspec"
19
+ # - "ruby test/real_db_test.rb"
20
+ env:
21
+ global:
22
+ - JRUBY_OPTS='--dev -J-Xmx1024M'
23
+ rvm:
24
+ - rbx-2
25
+ - jruby-9.0.5.0
26
+ - jruby-head
27
+ - 2.0.0
28
+ - 2.1
29
+ - 2.2.5
30
+ - 2.3.1
31
+ - ruby-head
32
+ jdk:
33
+ - openjdk7
34
+ - oraclejdk7
35
+ - oraclejdk8
36
+ # - openjdk6
37
+ matrix:
38
+ fast_finish: true
39
+ # allow_failures:
40
+ # - rvm: jruby-9.0.5.0
41
+ # - rvm: jruby-head
42
+ # - rvm: ruby-head
43
+ # - rvm: jruby-head
44
+ bundler_args: --jobs 3 --retry 3
45
+ notifications:
46
+ email: false
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem "sqlite3", :platform => [:ruby, :mswin, :mingw]
7
+ # for JRuby
8
+ gem "jdbc-sqlite3", :platform => :jrubyend
9
+ gem 'activerecord', '~> 4.0'
10
+ end
data/MIT-LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007-2016 Faveod
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # Arel Extensions
2
+
3
+ Arel Extensions adds shortcuts, fixes and new ORM mappings (ruby to SQL) to Arel.
4
+ It aims to ensure pure ruby syntax for the biggest number of usual cases.
5
+ It allows to use more advanced SQL functions for any supported RDBMS.
6
+
7
+ Examples:
8
+ t is an Arel::Table for table my_table
9
+
10
+ ## Comparators
11
+
12
+ ```ruby
13
+ (t[:nb] > 42).to_sql # (same as (t[:nb].gt(42)).to_sql)
14
+ # => my_table.nb > 42
15
+ ```
16
+
17
+ ## Maths
18
+
19
+ Currently in Arel:
20
+ ```ruby
21
+ (t[:nb] + 42).to_sql
22
+ # => my_table.nb + 42
23
+ ```
24
+
25
+ But:
26
+ ```ruby
27
+ (t[:nb].sum + 42).to_sql
28
+ # => NoMethodError: undefined method `+' for #<Arel::Nodes::Sum>
29
+ ```
30
+
31
+ With Arel Extensions:
32
+ ```ruby
33
+ (t[:nb].sum + 42).to_sql
34
+ # => SUM(my_table.nb) + 42
35
+ ```
36
+
37
+ Other functions : ABS, RAND, ROUND, FLOOR, CEIL, MD5, FORMAT
38
+
39
+ ## String operations
40
+
41
+ ```ruby
42
+ (t[:name] + ' append').to_sql
43
+ # => CONCAT(my_table.name, ' append')
44
+
45
+ (t[:name].if_null('default')).to_sql
46
+ # => ISNULL(my_table.name, 'default')
47
+
48
+ (t[:name] =~ /\A[a-d_]+/).to_sql
49
+ # => my_table.name REGEXP '\^[a-d_]+'
50
+ ```
51
+
52
+ Other functions : SOUNDEX, LENGTH, REPLACE, LOCATE, TRIM
53
+
54
+ ### String Array operations
55
+
56
+ ```t[:list]``` is a classical varchar containing a comma separated list ("1,2,3,4")
57
+
58
+ ```ruby
59
+ (t[:list] & 3).to_sql
60
+ # => FIND_IN_SET('3', my_table.list)
61
+
62
+ (t[:list] & [2,3]).to_sql
63
+ # => FIND_IN_SET('2', my_table.list) OR FIND_IN_SET('3', my_table.list)
64
+ ```
65
+
66
+
67
+ ## Date & Time operations
68
+
69
+ ```ruby
70
+ (t[:birthdate] + 10.years).to_sql
71
+ # => ADDDATE(my_table.birthdate, INTERVAL 10 YEAR)
72
+
73
+ ((t[:birthdate] - Date.today) * -1).to_sql
74
+ # => DATEDIFF(my_table.birthdate, '2017-01-01') * -1
75
+
76
+ (t[:birthdate].week).to_sql
77
+ # => WEEK(my_table.birthdate)
78
+
79
+ t[:birthdate].month.to_sql
80
+ # => MONTH(my_table.birthdate)
81
+
82
+ t[:birthdate].year.to_sql
83
+ # => YEAR(my_table.birthdate)
84
+ ```
85
+
86
+ ## Unions (in next version)
87
+
88
+ ```ruby
89
+ (t.where(t[:name].eq('str')) + t.where(t[:name].eq('test'))).to_sql
90
+ # => SELECT * FROM my_table WHERE (name = 'str') UNION SELECT * FROM my_table WHERE (name= 'test')
91
+ ```
92
+
93
+ ## Stored Procedures and User-defined functions
94
+
95
+ To optimize queries, some classical functions are defined in databases missing any alternative native functions.
96
+ Examples :
97
+ - FIND_IN_SET
98
+
99
+ ## BULK INSERT / UPSERT
100
+
101
+ TODO
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+
6
+ desc "Default Task"
7
+ task default: [ :test ]
8
+
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/test_*.rb'
13
+ t.verbose = true
14
+ end
@@ -0,0 +1,32 @@
1
+ # # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ # require "arel_extensions"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "arel_extensions"
7
+ s.version = '0.8.0'
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Yann Azoury", "Mathilde Pechdi", "Félix Bellanger"]
10
+ s.email = ["yann.azoury@faveod.com", "mathilde.pechdimaldjian@gmail.com", "felix.bellanger@faveod.com"]
11
+ s.homepage = "https://github.com/Faveod/arel-extensions"
12
+ s.description = "Adds new features to Arel"
13
+ s.summary = "Extending Arel"
14
+ s.license = %q{MIT}
15
+
16
+ s.rdoc_options = ["--main", "README.md"]
17
+ s.extra_rdoc_files = ["MIT-LICENSE.txt", "README.md"]
18
+
19
+ # Manifest
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.require_paths = ["lib"]
23
+
24
+ s.add_dependency('arel', '~> 6.0')
25
+
26
+ s.add_development_dependency('minitest')
27
+ s.add_development_dependency('rdoc', '~> 4.0')
28
+ s.add_development_dependency('rake')
29
+ s.add_development_dependency('activesupport', '~> 4.0')
30
+ s.add_development_dependency('activemodel', '~> 4.0')
31
+ s.add_development_dependency('activerecord', '~> 4.0')
32
+ end
data/functions.html ADDED
@@ -0,0 +1,344 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Arel Extensions Features</title>
6
+ <style type="text/css">
7
+ .tg {border-collapse:collapse;border-spacing:0;}
8
+ .tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
9
+ .tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
10
+ .tg .tg-baqh{text-align:center;vertical-align:top}
11
+ .tg .tg-3oug{background-color:#fd6864;text-align:center;vertical-align:top}
12
+ .tg .tg-by3v{font-weight:bold;font-size:14px;text-align:center}
13
+ .tg .tg-jogk{font-style:italic;vertical-align:top}
14
+ .tg .tg-pjz5{font-weight:bold;font-size:14px;background-color:#f8a102;text-align:center;vertical-align:top}
15
+ .tg .tg-82sq{font-weight:bold;background-color:#ffce93;color:#330001;vertical-align:top}
16
+ .tg .tg-yw4l{vertical-align:top}
17
+ .tg .tg-j6lv{background-color:#96fffb;text-align:center;vertical-align:top}
18
+ .tg .tg-ffjm{font-weight:bold;background-color:#fffc9e;vertical-align:top}
19
+ .tg .tg-orpl{font-size:10px;background-color:#96fffb;vertical-align:top}
20
+ .tg .tg-4rp9{font-weight:bold;background-color:#ffffc7;vertical-align:top}
21
+ .tg .tg-72dn{font-weight:bold;background-color:#f7f6cd;vertical-align:top}
22
+ .tg .tg-9hbo{font-weight:bold;vertical-align:top}
23
+ </style>
24
+ </head>
25
+ <body>
26
+ <table class="tg">
27
+ <thead>
28
+ <tr>
29
+ <th class="tg-jogk"></th>
30
+ <th class="tg-by3v">Function / Example<br/>ToSql</th>
31
+ <th class="tg-pjz5">MySQL/MariaDB</th>
32
+ <th class="tg-pjz5">PostgreSQL</th>
33
+ <th class="tg-pjz5">SQLite</th>
34
+ <th class="tg-pjz5">Oracle</th>
35
+ <th class="tg-pjz5">MS SQL</th>
36
+ <th class="tg-pjz5">DB2</th>
37
+ </tr>
38
+ </thead>
39
+ <tr>
40
+ <td class="tg-82sq" rowspan="6"><br><br><br><br><br><br><br>Math<br>functions<br></td>
41
+ <td class="tg-yw4l">ABS<br>column.abs<br></td>
42
+ <td class="tg-baqh">✔</td>
43
+ <td class="tg-baqh">✔</td>
44
+ <td class="tg-baqh">✔</td>
45
+ <td class="tg-baqh">✔</td>
46
+ <td class="tg-baqh">✔</td>
47
+ <td class="tg-baqh">✔</td>
48
+ </tr>
49
+ <tr>
50
+ <td class="tg-yw4l">CEIL<br>column.ceil</td>
51
+ <td class="tg-baqh">✔</td>
52
+ <td class="tg-baqh">✔</td>
53
+ <td class="tg-3oug">require extension-functions.so</td>
54
+ <td class="tg-baqh">✔</td>
55
+ <td class="tg-j6lv">CEILING()</td>
56
+ <td class="tg-j6lv">CEILING()</td>
57
+ </tr>
58
+ <tr>
59
+ <td class="tg-yw4l">FLOOR<br>column.floor</td>
60
+ <td class="tg-baqh">✔</td>
61
+ <td class="tg-baqh">✔</td>
62
+ <td class="tg-3oug">require extension-functions.so</td>
63
+ <td class="tg-baqh">✔</td>
64
+ <td class="tg-baqh">✔</td>
65
+ <td class="tg-baqh">✔</td>
66
+ </tr>
67
+ <tr>
68
+ <td class="tg-yw4l">RAND<br>Arel.rand</td>
69
+ <td class="tg-baqh">✔</td>
70
+ <td class="tg-baqh">✔</td>
71
+ <td class="tg-j6lv">RANDOM()</td>
72
+ <td class="tg-j6lv">dbms_random.value()</td>
73
+ <td class="tg-baqh">✔</td>
74
+ <td class="tg-baqh">✔</td>
75
+ </tr>
76
+ <tr>
77
+ <td class="tg-yw4l">ROUND<br>column.round(precision = 0)</td>
78
+ <td class="tg-baqh">✔</td>
79
+ <td class="tg-baqh">✔</td>
80
+ <td class="tg-baqh">✔</td>
81
+ <td class="tg-baqh">✔</td>
82
+ <td class="tg-baqh">✔</td>
83
+ <td class="tg-baqh">✔</td>
84
+ </tr>
85
+ <tr>
86
+ <td class="tg-yw4l">SUM / AVG / MIN / MAX + x<br>column.sum + 42</td>
87
+ <td class="tg-baqh">✔</td>
88
+ <td class="tg-baqh">✔</td>
89
+ <td class="tg-baqh">✔</td>
90
+ <td class="tg-baqh">✔</td>
91
+ <td class="tg-baqh">✔</td>
92
+ <td class="tg-baqh">✔</td>
93
+ </tr>
94
+ <tr>
95
+ <td class="tg-ffjm" rowspan="11"><br><br><br><br><br><br><br><br><br>String <br>functions <br></td>
96
+ <td class="tg-yw4l">CONCAT<br>column + "string"</td>
97
+ <td class="tg-baqh">✔</td>
98
+ <td class="tg-baqh">✔</td>
99
+ <td class="tg-j6lv"> ||</td>
100
+ <td class="tg-baqh">✔</td>
101
+ <td class="tg-j6lv">+</td>
102
+ <td class="tg-baqh">✔</td>
103
+ </tr>
104
+ <tr>
105
+ <td class="tg-yw4l">LENGTH<br>column.length</td>
106
+ <td class="tg-baqh">✔</td>
107
+ <td class="tg-baqh">✔</td>
108
+ <td class="tg-baqh">✔</td>
109
+ <td class="tg-baqh">✔</td>
110
+ <td class="tg-j6lv">LEN()</td>
111
+ <td class="tg-baqh">✔</td>
112
+ </tr>
113
+ <tr>
114
+ <td class="tg-yw4l">LOCATE<br>column.locate("string")</td>
115
+ <td class="tg-baqh">✔</td>
116
+ <td class="tg-baqh">✔</td>
117
+ <td class="tg-j6lv">INSTR()</td>
118
+ <td class="tg-baqh">✔</td>
119
+ <td class="tg-j6lv">CHARINDEX()</td>
120
+ <td class="tg-baqh">✔</td>
121
+ </tr>
122
+ <tr>
123
+ <td class="tg-yw4l">FIND_IN_SET<br>column &amp; ("l")</td>
124
+ <td class="tg-baqh">✔</td>
125
+ <td class="tg-baqh">✔</td>
126
+ <td class="tg-orpl">db.create_function( "find_in_set", 1 ) <br>do |func, value1, value2|,<br>func.result =value1.index(value2)<br>end <br></td>
127
+ <td class="tg-baqh">✔</td>
128
+ <td class="tg-baqh">✔</td>
129
+ <td class="tg-baqh">✔</td>
130
+ </tr>
131
+ <tr>
132
+ <td class="tg-yw4l">SOUNDEX<br>column.soundex</td>
133
+ <td class="tg-baqh">✔</td>
134
+ <td class="tg-3oug">require fuzzystrmatch</td>
135
+ <td class="tg-baqh">✔</td>
136
+ <td class="tg-baqh">✔</td>
137
+ <td class="tg-baqh">✔</td>
138
+ <td class="tg-baqh">✔</td>
139
+ </tr>
140
+ <tr>
141
+ <td class="tg-yw4l">REPLACE<br>column.replace("s","X")</td>
142
+ <td class="tg-baqh">✔</td>
143
+ <td class="tg-baqh">✔</td>
144
+ <td class="tg-baqh">✔</td>
145
+ <td class="tg-baqh">✔</td>
146
+ <td class="tg-baqh">✔</td>
147
+ <td class="tg-baqh">✔</td>
148
+ </tr>
149
+ <tr>
150
+ <td class="tg-yw4l">REGEXP<br>column =~ "pattern"<br></td>
151
+ <td class="tg-baqh">✔</td>
152
+ <td class="tg-baqh">✔</td>
153
+ <td class="tg-3oug">require pcre.so</td>
154
+ <td class="tg-j6lv">REGEXP_LIKE()</td>
155
+ <td class="tg-j6lv">LIKE()<br></td>
156
+ <td class="tg-baqh">✔</td>
157
+ </tr>
158
+ <tr>
159
+ <td class="tg-yw4l">NOT_REGEXP<br>column != "pattern"</td>
160
+ <td class="tg-baqh">✔</td>
161
+ <td class="tg-baqh">✔<br></td>
162
+ <td class="tg-3oug">require pcre.so</td>
163
+ <td class="tg-j6lv">NOT REGEXP_LIKE()</td>
164
+ <td class="tg-j6lv">NOT LIKE()</td>
165
+ <td class="tg-baqh">✔</td>
166
+ </tr>
167
+ <tr>
168
+ <td class="tg-yw4l">TRIM (leading)<br>column.trim("LEADING","M")</td>
169
+ <td class="tg-baqh">✔</td>
170
+ <td class="tg-j6lv">LTRIM()</td>
171
+ <td class="tg-j6lv">LTRIM()</td>
172
+ <td class="tg-baqh">✔</td>
173
+ <td class="tg-baqh">✔</td>
174
+ <td class="tg-j6lv">LTRIM()</td>
175
+ </tr>
176
+ <tr>
177
+ <td class="tg-yw4l">TRIM (trailing)<br>column.trim("TRAILING","g")</td>
178
+ <td class="tg-baqh">✔</td>
179
+ <td class="tg-j6lv">RTRIM()</td>
180
+ <td class="tg-j6lv">RTRIM()</td>
181
+ <td class="tg-baqh">✔</td>
182
+ <td class="tg-baqh">✔</td>
183
+ <td class="tg-j6lv">Rtrim()</td>
184
+ </tr>
185
+ <tr>
186
+ <td class="tg-yw4l">TRIM (both)<br>column.trim("BOTH","e")</td>
187
+ <td class="tg-baqh">✔</td>
188
+ <td class="tg-j6lv">TRIM()<br></td>
189
+ <td class="tg-j6lv">TRIM()</td>
190
+ <td class="tg-baqh">✔</td>
191
+ <td class="tg-baqh">✔</td>
192
+ <td class="tg-j6lv">TRIM()</td>
193
+ </tr>
194
+ <tr>
195
+ <td class="tg-4rp9" rowspan="6"><br><br><br><br><br><br><br>Date <br>functions<br></td>
196
+ <td class="tg-yw4l">DATEADD<br>column + 2.year<br></td>
197
+ <td class="tg-j6lv">DATE_ADD()<br></td>
198
+ <td class="tg-baqh">✔</td>
199
+ <td class="tg-baqh">✔</td>
200
+ <td class="tg-baqh">✔</td>
201
+ <td class="tg-baqh">✔</td>
202
+ <td class="tg-j6lv">+</td>
203
+ </tr>
204
+ <tr>
205
+ <td class="tg-yw4l">DATEDIFF<br>column - date<br></td>
206
+ <td class="tg-j6lv">DATEDIFF()<br></td>
207
+ <td class="tg-baqh">✔</td>
208
+ <td class="tg-j6lv">JULIANDAY() - JULIANDAY()</td>
209
+ <td class="tg-j6lv"> -</td>
210
+ <td class="tg-baqh">✔</td>
211
+ <td class="tg-j6lv">DAY()</td>
212
+ </tr>
213
+ <tr>
214
+ <td class="tg-yw4l">DAY<br>column.day<br></td>
215
+ <td class="tg-baqh">✔</td>
216
+ <td class="tg-baqh">✔</td>
217
+ <td class="tg-j6lv">STRFTIME()</td>
218
+ <td class="tg-baqh">✔</td>
219
+ <td class="tg-baqh">✔</td>
220
+ <td class="tg-baqh">✔</td>
221
+ </tr>
222
+ <tr>
223
+ <td class="tg-yw4l">MONTH<br>column.month<br></td>
224
+ <td class="tg-baqh">✔</td>
225
+ <td class="tg-baqh">✔</td>
226
+ <td class="tg-j6lv">STRFTIME()</td>
227
+ <td class="tg-baqh">✔</td>
228
+ <td class="tg-baqh">✔</td>
229
+ <td class="tg-baqh">✔</td>
230
+ </tr>
231
+ <tr>
232
+ <td class="tg-yw4l">WEEK<br>column.week</td>
233
+ <td class="tg-baqh">✔</td>
234
+ <td class="tg-baqh">✔</td>
235
+ <td class="tg-j6lv">STRFTIME()</td>
236
+ <td class="tg-baqh">✔</td>
237
+ <td class="tg-baqh">✔</td>
238
+ <td class="tg-baqh">✔</td>
239
+ </tr>
240
+ <tr>
241
+ <td class="tg-yw4l">YEAR<br>column.year</td>
242
+ <td class="tg-baqh">✔</td>
243
+ <td class="tg-baqh">✔</td>
244
+ <td class="tg-j6lv">STRFTIME()</td>
245
+ <td class="tg-baqh">✔</td>
246
+ <td class="tg-baqh">✔</td>
247
+ <td class="tg-baqh">✔</td>
248
+ </tr>
249
+ <tr>
250
+ <td class="tg-72dn" rowspan="8"><br><br><br><br><br><br>Comparators<br>functions<br></td>
251
+ <td class="tg-yw4l">COALESCE<br>column.coalesce(var)</td>
252
+ <td class="tg-baqh">✔</td>
253
+ <td class="tg-baqh">✔</td>
254
+ <td class="tg-baqh">✔</td>
255
+ <td class="tg-baqh">✔</td>
256
+ <td class="tg-baqh">✔</td>
257
+ <td class="tg-baqh">✔</td>
258
+ </tr>
259
+ <tr>
260
+ <td class="tg-yw4l">ISNULL<br>column.isnull(var)</td>
261
+ <td class="tg-j6lv">IFNULL()<br></td>
262
+ <td class="tg-baqh">✔</td>
263
+ <td class="tg-baqh">✔</td>
264
+ <td class="tg-j6lv">NVC()</td>
265
+ <td class="tg-baqh">✔</td>
266
+ <td class="tg-baqh">✔</td>
267
+ </tr>
268
+ <tr>
269
+ <td class="tg-yw4l">==<br>column == integer<br></td>
270
+ <td class="tg-baqh">✔</td>
271
+ <td class="tg-baqh">✔</td>
272
+ <td class="tg-baqh">✔</td>
273
+ <td class="tg-baqh">✔</td>
274
+ <td class="tg-baqh">✔</td>
275
+ <td class="tg-baqh">✔</td>
276
+ </tr>
277
+ <tr>
278
+ <td class="tg-yw4l">!=<br>column != integer<br></td>
279
+ <td class="tg-baqh">✔</td>
280
+ <td class="tg-baqh">✔</td>
281
+ <td class="tg-baqh">✔</td>
282
+ <td class="tg-baqh">✔</td>
283
+ <td class="tg-baqh">✔</td>
284
+ <td class="tg-baqh">✔</td>
285
+ </tr>
286
+ <tr>
287
+ <td class="tg-yw4l">&gt;<br>column &gt; integer<br></td>
288
+ <td class="tg-baqh">✔</td>
289
+ <td class="tg-baqh">✔</td>
290
+ <td class="tg-baqh">✔</td>
291
+ <td class="tg-baqh">✔</td>
292
+ <td class="tg-baqh">✔</td>
293
+ <td class="tg-baqh">✔</td>
294
+ </tr>
295
+ <tr>
296
+ <td class="tg-yw4l">&gt;=<br>column &gt;= integer</td>
297
+ <td class="tg-baqh">✔</td>
298
+ <td class="tg-baqh">✔</td>
299
+ <td class="tg-baqh">✔</td>
300
+ <td class="tg-baqh">✔</td>
301
+ <td class="tg-baqh">✔</td>
302
+ <td class="tg-baqh">✔</td>
303
+ </tr>
304
+ <tr>
305
+ <td class="tg-yw4l">&lt; <br>column &lt; integer</td>
306
+ <td class="tg-baqh">✔</td>
307
+ <td class="tg-baqh">✔</td>
308
+ <td class="tg-baqh">✔</td>
309
+ <td class="tg-baqh">✔</td>
310
+ <td class="tg-baqh">✔</td>
311
+ <td class="tg-baqh">✔</td>
312
+ </tr>
313
+ <tr>
314
+ <td class="tg-yw4l">&lt;=<br>column &lt;= integer</td>
315
+ <td class="tg-baqh">✔</td>
316
+ <td class="tg-baqh">✔</td>
317
+ <td class="tg-baqh">✔</td>
318
+ <td class="tg-baqh">✔</td>
319
+ <td class="tg-baqh">✔</td>
320
+ <td class="tg-baqh">✔</td>
321
+ </tr>
322
+ <tr>
323
+ <td class="tg-9hbo" rowspan="2"><br><br>Boolean <br>functions<br></td>
324
+ <td class="tg-yw4l">OR ( ⋁ )<br>column.eq(var) ⋁ column.eq(var)</td>
325
+ <td class="tg-baqh">✔</td>
326
+ <td class="tg-baqh">✔</td>
327
+ <td class="tg-baqh">✔</td>
328
+ <td class="tg-baqh">✔</td>
329
+ <td class="tg-baqh">✔</td>
330
+ <td class="tg-baqh">✔</td>
331
+ </tr>
332
+ <tr>
333
+ <td class="tg-yw4l">AND ( ⋀ )<br>column.eq(var) ⋀ column.eq(var)</td>
334
+ <td class="tg-baqh">✔</td>
335
+ <td class="tg-baqh">✔</td>
336
+ <td class="tg-baqh">✔</td>
337
+ <td class="tg-baqh">✔</td>
338
+ <td class="tg-baqh">✔</td>
339
+ <td class="tg-baqh">✔</td>
340
+ </tr>
341
+ </table>
342
+ </table>
343
+ </body>
344
+ </html>