sqlconstructor 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|