sqlconstructor 0.1
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 +15 -0
- data/LICENSE.md +16 -0
- data/README.md +161 -0
- data/Rakefile +11 -0
- data/doc/Object.html +267 -0
- data/doc/Rakefile.html +150 -0
- data/doc/SQLAliasedList.html +717 -0
- data/doc/SQLColumn.html +326 -0
- data/doc/SQLCondList.html +318 -0
- data/doc/SQLConditional.html +1082 -0
- data/doc/SQLConditional/BasicCond.html +325 -0
- data/doc/SQLConstructor.html +763 -0
- data/doc/SQLConstructor/BasicDelete.html +383 -0
- data/doc/SQLConstructor/BasicDelete_mysql.html +368 -0
- data/doc/SQLConstructor/BasicInsert.html +339 -0
- data/doc/SQLConstructor/BasicInsert_mysql.html +325 -0
- data/doc/SQLConstructor/BasicJoin.html +408 -0
- data/doc/SQLConstructor/BasicJoin_mysql.html +439 -0
- data/doc/SQLConstructor/BasicSelect.html +554 -0
- data/doc/SQLConstructor/BasicSelect_example.html +288 -0
- data/doc/SQLConstructor/BasicSelect_mysql.html +466 -0
- data/doc/SQLConstructor/BasicUnion.html +396 -0
- data/doc/SQLConstructor/BasicUpdate.html +409 -0
- data/doc/SQLConstructor/BasicUpdate_mysql.html +310 -0
- data/doc/SQLConstructor/GenericQuery.html +797 -0
- data/doc/SQLConstructor/QAttr.html +398 -0
- data/doc/SQLConstructorTest.html +603 -0
- data/doc/SQLExporter.html +382 -0
- data/doc/SQLExporter/Exporter_generic.html +413 -0
- data/doc/SQLExporter/Exporter_mysql.html +395 -0
- data/doc/SQLObject.html +525 -0
- data/doc/SQLValList.html +322 -0
- data/doc/SQLValue.html +375 -0
- data/doc/created.rid +12 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +356 -0
- data/doc/js/darkfish.js +118 -0
- data/doc/js/jquery.js +32 -0
- data/doc/js/quicksearch.js +114 -0
- data/doc/js/thickbox-compressed.js +10 -0
- data/doc/lib/dialects/example-constructor_rb.html +52 -0
- data/doc/lib/dialects/mysql-constructor_rb.html +52 -0
- data/doc/lib/dialects/mysql-exporter_rb.html +54 -0
- data/doc/lib/sqlconditional_rb.html +64 -0
- data/doc/lib/sqlconstructor_rb.html +52 -0
- data/doc/lib/sqlerrors_rb.html +54 -0
- data/doc/lib/sqlexporter_rb.html +55 -0
- data/doc/lib/sqlobject_rb.html +54 -0
- data/doc/rdoc.css +763 -0
- data/doc/test/queries_rb.html +56 -0
- data/doc/test_rb.html +52 -0
- data/lib/dialects/example-constructor.rb +45 -0
- data/lib/dialects/mysql-constructor.rb +247 -0
- data/lib/dialects/mysql-exporter.rb +108 -0
- data/lib/sqlconditional.rb +196 -0
- data/lib/sqlconstructor.rb +708 -0
- data/lib/sqlerrors.rb +15 -0
- data/lib/sqlexporter.rb +125 -0
- data/lib/sqlobject.rb +284 -0
- data/test/queries.rb +92 -0
- metadata +121 -0
data/lib/sqlerrors.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
##################################################################################
|
3
|
+
# List of error messages
|
4
|
+
##################################################################################
|
5
|
+
|
6
|
+
ERR_INVALID_COL_NAME = "Invalid column name."
|
7
|
+
ERR_INVALID_RULES = "No valid syntax rules found for dialect"
|
8
|
+
ERR_NUMERIC_VALUE_EXPECTED = "Numeric argument value expected."
|
9
|
+
ERR_UNKNOWN_DIALECT = "Unimplemented SQL dialect specified"
|
10
|
+
ERR_UNKNOWN_METHOD = "Unknown method called"
|
11
|
+
ERR_UNKNOWN_OPERATOR_TYPE = "Unknown conditional operator type."
|
12
|
+
ERR_VALUES_NUM_MISMATCH = "Number of values provided mismatches the number of requested columns."
|
13
|
+
ERR_WHERE_INVALID_ARGS = "Hash expected in .where() arguments."
|
14
|
+
ERR_WHERE_LIKE_INVALID_ARGS = "Hash with scalar values expected in .where() arguments."
|
15
|
+
ERR_NAME_NOT_FOUND = "Could not find named clause by the name"
|
data/lib/sqlexporter.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
|
2
|
+
##############################################################################################
|
3
|
+
# This class implements the interface for exprting SQLConstructor objects to strings.
|
4
|
+
##############################################################################################
|
5
|
+
class SQLExporter
|
6
|
+
|
7
|
+
attr_accessor :dialect, :tidy
|
8
|
+
attr_reader :separator
|
9
|
+
|
10
|
+
# defaults to 'mysql'
|
11
|
+
DEFAULT_DIALECT = 'mysql'
|
12
|
+
|
13
|
+
#############################################################################
|
14
|
+
# Class constructor. Called with two optional arguments - dialect and tidy.
|
15
|
+
# Dialect determines the translator class (e.g., Exporter_mysql,
|
16
|
+
# Exporter_informix etc). Tidy determines whether the output should be
|
17
|
+
# formatted and human-readable.
|
18
|
+
#############################################################################
|
19
|
+
def initialize ( dialect = DEFAULT_DIALECT, tidy = false )
|
20
|
+
dialect ||= DEFAULT_DIALECT
|
21
|
+
dialect_class = "Exporter_" + dialect.to_s
|
22
|
+
begin
|
23
|
+
@translator = SQLExporter.const_get( dialect_class ).new( tidy )
|
24
|
+
rescue
|
25
|
+
raise NameError, ERR_UNKNOWN_DIALECT + ": " + dialect.to_s
|
26
|
+
end
|
27
|
+
@dialect, @tidy = dialect, tidy
|
28
|
+
@separator = @translator.separator
|
29
|
+
end
|
30
|
+
|
31
|
+
#############################################################################
|
32
|
+
# The main method to export the obj to string. Calls the @translator's
|
33
|
+
# export method.
|
34
|
+
#############################################################################
|
35
|
+
def export ( obj )
|
36
|
+
string = @translator.export obj
|
37
|
+
string = @separator + "(" + string + ")" if obj.inline
|
38
|
+
return string
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
#########################################################################################
|
43
|
+
# The exporter class of a 'generic' sql dialect. This should be the parent for
|
44
|
+
# all dialect-specific exporter classes.
|
45
|
+
#########################################################################################
|
46
|
+
class Exporter_generic
|
47
|
+
|
48
|
+
attr_reader :separator
|
49
|
+
|
50
|
+
#############################################################################
|
51
|
+
# Class constructor.
|
52
|
+
#############################################################################
|
53
|
+
def initialize ( tidy )
|
54
|
+
@tidy = tidy
|
55
|
+
@separator = @tidy ? "\n" : " "
|
56
|
+
end
|
57
|
+
|
58
|
+
#############################################################################
|
59
|
+
# exports a string with a query from object.
|
60
|
+
# this method should be called from a child class with defined constant
|
61
|
+
# arrays [select|delete|update|insert]_syntax. methods defined in the array
|
62
|
+
# are called in the specified order for the object obj.
|
63
|
+
#############################################################################
|
64
|
+
def export ( obj )
|
65
|
+
rules_const_name = obj.class.name.sub( /^.+?::Basic([^_]+).+/, '\1' ).upcase + "_SYNTAX"
|
66
|
+
begin
|
67
|
+
rules = self.class.const_get( rules_const_name.to_sym )
|
68
|
+
rescue NameError
|
69
|
+
raise NameError, ERR_INVALID_RULES + " '" + self.send( :dialect ) + "'"
|
70
|
+
end
|
71
|
+
string = ""
|
72
|
+
rules.each do |rule|
|
73
|
+
if rule.is_a? String
|
74
|
+
string += rule + @separator
|
75
|
+
elsif rule.is_a? Symbol
|
76
|
+
res = self.send( rule, obj ).to_s
|
77
|
+
string += res
|
78
|
+
string += @separator if ! res.empty?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
return string
|
82
|
+
end
|
83
|
+
|
84
|
+
#############################################################################
|
85
|
+
# Generic representation of the JOIN clause
|
86
|
+
#############################################################################
|
87
|
+
def gen_joins ( obj )
|
88
|
+
arr_joins = [ ]
|
89
|
+
if obj.gen_joins
|
90
|
+
arr_joins = obj.gen_joins.map { |join| join.to_s }
|
91
|
+
end
|
92
|
+
return arr_joins.join( @separator )
|
93
|
+
end
|
94
|
+
|
95
|
+
#############################################################################
|
96
|
+
# Construct an expression string for an object's attribute defined in
|
97
|
+
# in the METHODS constant array.
|
98
|
+
#############################################################################
|
99
|
+
def method_missing ( method, *args )
|
100
|
+
obj = args[0]
|
101
|
+
return '' if ! obj.is_a? SQLObject
|
102
|
+
result = ""
|
103
|
+
_attr = obj.send method
|
104
|
+
if _attr.is_a? Array
|
105
|
+
result += _attr.join @separator
|
106
|
+
elsif _attr
|
107
|
+
result += _attr.to_s
|
108
|
+
end
|
109
|
+
|
110
|
+
return result
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
##################################################################################################
|
118
|
+
##################################################################################################
|
119
|
+
# Include dialect-specific classes from ./dialects/exporter/ :
|
120
|
+
# This should be done after SQLExporter is defined.
|
121
|
+
##################################################################################################
|
122
|
+
##################################################################################################
|
123
|
+
|
124
|
+
Dir[ DIALECTS_PATH + "/*-exporter.rb"].each { |file| require file }
|
125
|
+
|
data/lib/sqlobject.rb
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
|
2
|
+
###############################################################################################
|
3
|
+
### Main class for all objects. All other entities should inherit this class.
|
4
|
+
###############################################################################################
|
5
|
+
class SQLObject
|
6
|
+
|
7
|
+
attr_accessor :alias, :separator, :name, :inline
|
8
|
+
|
9
|
+
##########################################################################
|
10
|
+
# Do we really need a constructor here?
|
11
|
+
##########################################################################
|
12
|
+
def initialize
|
13
|
+
@string = nil
|
14
|
+
@alias = nil
|
15
|
+
@name = nil
|
16
|
+
@inline = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
##########################################################################
|
20
|
+
# Set object's name for further named processing
|
21
|
+
##########################################################################
|
22
|
+
def _name ( name )
|
23
|
+
@name = name.to_s
|
24
|
+
return self
|
25
|
+
end
|
26
|
+
|
27
|
+
##########################################################################
|
28
|
+
# Store string representation in @string after the first call
|
29
|
+
##########################################################################
|
30
|
+
def to_s
|
31
|
+
return @string if @string
|
32
|
+
@string = self.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
##########################################################################
|
36
|
+
# attr_reader for @string, actually an alias to to_s().
|
37
|
+
##########################################################################
|
38
|
+
def _string
|
39
|
+
to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
##########################################################################
|
43
|
+
# attr_writer for @string
|
44
|
+
##########################################################################
|
45
|
+
def _string= ( val )
|
46
|
+
@string = val
|
47
|
+
end
|
48
|
+
|
49
|
+
##########################################################################
|
50
|
+
# Convert values to the corresponding internal data types
|
51
|
+
##########################################################################
|
52
|
+
def self.get ( *list )
|
53
|
+
list.map! do |expr|
|
54
|
+
if expr.is_a? SQLObject
|
55
|
+
# inline queries go in parens:
|
56
|
+
if expr.class == SQLConstructor || expr.is_a?( SQLConstructor::GenericQuery )
|
57
|
+
expr.inline = true
|
58
|
+
end
|
59
|
+
expr
|
60
|
+
elsif expr.is_a? Array or expr.is_a? Range
|
61
|
+
SQLValList.new *expr.to_a
|
62
|
+
elsif expr.is_a? Hash
|
63
|
+
SQLAliasedList.new expr
|
64
|
+
elsif expr.is_a? Symbol
|
65
|
+
SQLColumn.new( expr )
|
66
|
+
else
|
67
|
+
SQLValue.new( expr )
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Return array or scalar, depending on the number of function arguments
|
72
|
+
list.length == 1 ? list[0] : list
|
73
|
+
end
|
74
|
+
|
75
|
+
# ##########################################################################
|
76
|
+
# # Convert a hash of { obj => alias, ... } to an array of SQLObjects
|
77
|
+
# # with defined @alias attribute.
|
78
|
+
# ##########################################################################
|
79
|
+
# def self.getWithAliases( *list )
|
80
|
+
# new_list = [ ]
|
81
|
+
# # If list is a hash of objects with aliases:
|
82
|
+
# if list.length == 1 && list[0].is_a?( Hash )
|
83
|
+
# list.each do |src, _alias|
|
84
|
+
# obj = SQLObject.get src
|
85
|
+
# obj.alias = _alias
|
86
|
+
# new_list << obj
|
87
|
+
# end
|
88
|
+
# # If list is an array of objects:
|
89
|
+
# else
|
90
|
+
# new_list = list.map { |src| SQLObject.get src }
|
91
|
+
# end
|
92
|
+
# return new_list
|
93
|
+
# end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
###############################################################################################
|
99
|
+
### Class representing SQL columns
|
100
|
+
###############################################################################################
|
101
|
+
class SQLColumn < SQLObject
|
102
|
+
|
103
|
+
def initialize ( col = nil )
|
104
|
+
@name = col.is_a?( SQLColumn ) ? col.name : col #_prepareName( col )
|
105
|
+
end
|
106
|
+
|
107
|
+
##########################################################################
|
108
|
+
def to_s
|
109
|
+
@name.to_s
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
##########################################################################
|
115
|
+
# Prepare column name (remove all non-alphanumeric/underscore characters)
|
116
|
+
##########################################################################
|
117
|
+
def _prepareName ( name )
|
118
|
+
name.to_s.gsub /[\W]/, ''
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
###############################################################################################
|
125
|
+
### Class representing SQL scalar values
|
126
|
+
###############################################################################################
|
127
|
+
class SQLValue < SQLObject
|
128
|
+
|
129
|
+
def initialize ( val = nil )
|
130
|
+
@value = val.is_a?( SQLValue ) ? val.value : _escape( val )
|
131
|
+
end
|
132
|
+
|
133
|
+
##########################################################################
|
134
|
+
def to_s
|
135
|
+
@value
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
##########################################################################
|
141
|
+
# DERIVED FROM https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
|
142
|
+
##########################################################################
|
143
|
+
def _escape ( val )
|
144
|
+
case val
|
145
|
+
when String then "'#{_quoteString(val.to_s)}'"
|
146
|
+
when true then 'TRUE'
|
147
|
+
when false then 'FALSE'
|
148
|
+
when nil then "NULL"
|
149
|
+
when Numeric, Time then val.to_s
|
150
|
+
when Symbol then "'#{_quoteString(val.to_s)}'"
|
151
|
+
when Class then "'#{val.to_s}'"
|
152
|
+
else
|
153
|
+
"'#{quoteString( val.to_s )}'"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
##########################################################################
|
158
|
+
# FROM https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
|
159
|
+
# Quotes a string, escaping any ' (single quote) and \ (backslash)
|
160
|
+
# characters.
|
161
|
+
##########################################################################
|
162
|
+
def _quoteString ( str )
|
163
|
+
str.gsub( /\\/, '\&\&' ).gsub( /'/, "''" ) # ' (for ruby-mode)
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
###############################################################################################
|
170
|
+
### Class container - a list of SQLValue scalars
|
171
|
+
###############################################################################################
|
172
|
+
class SQLValList < SQLObject
|
173
|
+
def initialize ( *list )
|
174
|
+
@list = list.map { |item| SQLObject.get item }
|
175
|
+
end
|
176
|
+
|
177
|
+
def << ( list )
|
178
|
+
list.map! { |item| SQLObject.get item }
|
179
|
+
@list += list
|
180
|
+
end
|
181
|
+
|
182
|
+
def to_s
|
183
|
+
return @string if @string
|
184
|
+
@string = "(" + @list.join( "," ) + ")"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
###############################################################################################
|
190
|
+
### Class container - a list of SQLObjects with aliases
|
191
|
+
###############################################################################################
|
192
|
+
class SQLAliasedList < SQLObject
|
193
|
+
attr_writer :no_commas
|
194
|
+
|
195
|
+
def initialize ( *list )
|
196
|
+
@list = _getList *list
|
197
|
+
end
|
198
|
+
|
199
|
+
def << ( *list )
|
200
|
+
@list += _getList *list
|
201
|
+
return self
|
202
|
+
end
|
203
|
+
|
204
|
+
def push ( *list )
|
205
|
+
@list += _getList( *list )
|
206
|
+
end
|
207
|
+
|
208
|
+
def length
|
209
|
+
@list.length
|
210
|
+
end
|
211
|
+
|
212
|
+
def each ( &block )
|
213
|
+
@list.each &block
|
214
|
+
end
|
215
|
+
|
216
|
+
def delete_if ( &block )
|
217
|
+
@list.delete_if &block
|
218
|
+
end
|
219
|
+
|
220
|
+
def [] (i)
|
221
|
+
@list[i]
|
222
|
+
end
|
223
|
+
|
224
|
+
def find ( &block )
|
225
|
+
@list.find &block
|
226
|
+
end
|
227
|
+
|
228
|
+
def select ( &block )
|
229
|
+
@list.each &block
|
230
|
+
end
|
231
|
+
|
232
|
+
def each_with_index ( &block )
|
233
|
+
@list.each_with_index &block
|
234
|
+
end
|
235
|
+
|
236
|
+
def to_s
|
237
|
+
return @string if @string
|
238
|
+
arr = @list.map { |obj| obj.to_s + ( obj.alias ? " " + obj.alias.to_s : "" ) }
|
239
|
+
list_separator = @no_commas ? "" : ","
|
240
|
+
@string = arr.join list_separator
|
241
|
+
end
|
242
|
+
|
243
|
+
private
|
244
|
+
|
245
|
+
def _getList ( *list )
|
246
|
+
new_list = [ ]
|
247
|
+
# If list is a hash of objects with aliases:
|
248
|
+
if list.length == 1 && list[0].is_a?( Hash )
|
249
|
+
new_list += _hash2array list[0]
|
250
|
+
# If list is an array of objects:
|
251
|
+
else
|
252
|
+
new_list = list.map { |src| SQLObject.get src }
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def _hash2array ( hash )
|
257
|
+
list = [ ]
|
258
|
+
hash.each do |item, _alias|
|
259
|
+
obj = SQLObject.get item
|
260
|
+
obj.alias = _alias
|
261
|
+
list << obj
|
262
|
+
end
|
263
|
+
return list
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
###############################################################################################
|
270
|
+
###
|
271
|
+
###############################################################################################
|
272
|
+
class SQLCondList < SQLObject
|
273
|
+
def initialize ( hash = { } )
|
274
|
+
@hash = Hash[ hash.map{ |k,v| [ SQLObject.get( k ), SQLObject.get( v ) ] } ]
|
275
|
+
end
|
276
|
+
|
277
|
+
def << ( new_hash )
|
278
|
+
@hash.merge! new_hash
|
279
|
+
end
|
280
|
+
|
281
|
+
def to_s
|
282
|
+
@hash.map{ |k,v| k.to_s + "=" + v.to_s }.join( "," )
|
283
|
+
end
|
284
|
+
end
|
data/test/queries.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'sqlconstructor'
|
3
|
+
|
4
|
+
class SQLConstructorTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_select1
|
7
|
+
assert_equal "SELECT\n col1,col2\nFROM table1\nJOIN table3 USE INDEX (col1)\nON \n(col1 = ccc1)\nJOIN table4,table5\nON \n(col2 = ccc2 AND col3 = 5)\nWHERE \n(col1 = 123 AND col2 IN ('value1','value2','@\#$%^') AND \n(c1 = 5 AND c2 < 6 OR (c1 = 3 AND c2 IN (1,2,3,4,5) AND s1 = 'somestring')))\nLIMIT 100\nUNION\nSELECT\n baz\nFROM table2\nUNION\nSELECT\n fooz\nFROM table5\nLIMIT 20\n\n",
|
8
|
+
select1
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_select2
|
12
|
+
assert_equal "SELECT\n t.id,t.tag,c.title category\nFROM tags2Articles t2a\nINNER JOIN tags t\nON \n(t.id = t2a.idTag)\nINNER JOIN categories c\nON \n(t.tagCategory = c.id)\nINNER JOIN \n(SELECT\n a.id\nFROM articles a\nJOIN tags2articles ta\nON \n(a.id = ta.idArticle)\nJOIN tags tsub\nON \n(ta.idTag = tsub.id)\nWHERE \n(tsub.id IN (12,13,16))\nGROUP BY a.id\nHAVING \n(COUNT(DISTINCT tsub.id) = 3)\n) asub\nON \n(t2a.idArticle = asub.id)\n",
|
13
|
+
select2
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_insert1
|
17
|
+
assert_equal "INSERT\nINTO table2\n SELECT\n name,CONCAT('blah=',ID)\nFROM table1\n\n",
|
18
|
+
insert1
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_delete1
|
22
|
+
assert_equal "DELETE\nFROM keywords\nWHERE \n(keyword_id IN \n(SELECT\n id\nFROM \n(SELECT\n k.keyword id\nFROM keywords k\nWHERE \n(k.keyword_type = 'CAMPAIGN' AND k.keyword != 'Airtel' AND k.keyword != 'Nokia' AND k.keyword != 'Micromax' AND k.keyword NOT IN \n(SELECT\nDISTINCT\n keyword_id\nFROM customer_analysis\n))\nORDER BY k.keyword_id\n) a\n))\n",
|
23
|
+
delete1
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_update1
|
27
|
+
assert_equal "UPDATE\n guest g\nSET link_id=\n(SELECT\n MAX(h.host_id)\nFROM guest_data d\nINNER JOIN host_data h\nON \n(d.guest_nm = hhost_nm)\nWHERE \n(d.guest_id = g.guest_id)\nGROUP BY h.venue_nm\nHAVING \n(COUNT(*) = 1)\n)\nWHERE \n(g.guest_id IN \n(SELECT\n d.guest_id\nFROM guest_data d\nINNER JOIN host_data h\nON \n(d.guest_nm = hhost_nm)\nGROUP BY h.venue_nm\nHAVING \n(COUNT(*) = 1)\n))\n",
|
28
|
+
update1
|
29
|
+
end
|
30
|
+
|
31
|
+
def select1
|
32
|
+
sql = SQLConstructor.new( :tidy => true, :dialect => 'mysql' )
|
33
|
+
sql.select(:col1,:col2).from(:table1).where.eq(:col1, 123).and.in(:col2,["value1","value2","@#\$%^"])
|
34
|
+
sql.limit( 100 )
|
35
|
+
sql.union._name("u1").select(:baz).from(:table2)
|
36
|
+
c2 = SQLConditional.new.eq(:c1,3).and.in(:c2,[1,2,3,4,5]).and.eq(:s1,'somestring')
|
37
|
+
c1 = SQLConditional.new.eq(:c1,5).and.lt(:c2,6).or.is(c2)
|
38
|
+
sql.where.and.is(c1)
|
39
|
+
sql.join( :table3 )._name('j1').on.eq( :col1, :ccc1 ).use_index( :col1 )
|
40
|
+
sql.join( :table4,:table5 )._name('j2').on.eq( :col2, :ccc2).and.eq( :col3, 5 )
|
41
|
+
sql.union._name("u2").select(:fooz).from(:table5).limit( 20 )
|
42
|
+
sql.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
def select2
|
46
|
+
sql = SQLConstructor.new( :tidy => true, :dialect => 'mysql' )
|
47
|
+
sql.select( :"t.id",:"t.tag",:"c.title" => :category ).from( :tags2Articles => :t2a )
|
48
|
+
sql.inner_join( :tags => :t ).on.eq(:"t.id", :"t2a.idTag" )
|
49
|
+
sql.inner_join( :categories => :c ).on.eq( :"t.tagCategory", :"c.id" )
|
50
|
+
inner_sql = SQLConstructor.new( :tidy => true, :dialect => 'mysql' )
|
51
|
+
inner_sql.select( :"a.id" ).from( :articles => :a )
|
52
|
+
inner_sql.join( :tags2articles => :ta ).on.eq( :"a.id", :"ta.idArticle" )
|
53
|
+
inner_sql.join( :tags => :tsub ).on.eq( :"ta.idTag", :"tsub.id" )
|
54
|
+
inner_sql.where.in( :"tsub.id", [12,13,16] ).group_by( :"a.id" ).
|
55
|
+
having.eq( :"COUNT(DISTINCT tsub.id)", 3 )
|
56
|
+
sql.inner_join( inner_sql => 'asub' ).on.eq( :"t2a.idArticle", :"asub.id" )
|
57
|
+
sql.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
def insert1
|
61
|
+
sql = SQLConstructor.new( :tidy => true, :dialect => 'mysql' )
|
62
|
+
sql.insert.into(:table2).select(:name, :"CONCAT('blah=',ID)").from(:table1)
|
63
|
+
sql.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
def delete1
|
67
|
+
sql = SQLConstructor.new( :tidy => true, :dialect => 'mysql' )
|
68
|
+
inner_sel3 = SQLConstructor.new( :tidy => true, :dialect => 'mysql' ).select( :keyword_id ).distinct.from( :customer_analysis )
|
69
|
+
inner_sel2 = SQLConstructor.new( :tidy => true, :dialect => 'mysql' ).select( :"k.keyword" => :id ).from( :keywords => :k ).
|
70
|
+
where.eq( :"k.keyword_type", "CAMPAIGN" ).and.ne( :"k.keyword", "Airtel" ).
|
71
|
+
and.ne( :"k.keyword", "Nokia" ).and.ne( :"k.keyword", "Micromax" ).
|
72
|
+
and.not_in( :"k.keyword", inner_sel3 ).order_by( :"k.keyword_id" )
|
73
|
+
inner_sel1 = SQLConstructor.new( :tidy => true, :dialect => 'mysql' ).select( :id ).from( inner_sel2 => :a )
|
74
|
+
sql.delete.from( :keywords ).where.in( :keyword_id, inner_sel1 )
|
75
|
+
sql.to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
def update1
|
79
|
+
sql = SQLConstructor.new( :tidy => true, :dialect => 'mysql' )
|
80
|
+
in_sel1 = SQLConstructor.new( :tidy => true )
|
81
|
+
in_sel1.select( :"MAX(h.host_id)" ).from( :guest_data => :d ).
|
82
|
+
inner_join( :host_data => :h ).on.eq( :"d.guest_nm", :hhost_nm ).where.
|
83
|
+
eq( :"d.guest_id", :"g.guest_id" ).group_by( :"h.venue_nm" ).having.eq( :"COUNT(*)", 1 )
|
84
|
+
in_sel2 = SQLConstructor.new( :dialect => 'mysql', :tidy => true )
|
85
|
+
in_sel2.select( :"d.guest_id" ).from( :guest_data => :d ).
|
86
|
+
inner_join( :host_data => :h ).on.eq( :"d.guest_nm", :hhost_nm ).
|
87
|
+
group_by( :"h.venue_nm" ).having.eq( :"COUNT(*)", 1 )
|
88
|
+
sql.update( :guest => :g ).set( :link_id => in_sel1).where.in( :"g.guest_id", in_sel2 )
|
89
|
+
sql.to_s
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|