quote-sql 0.0.3 → 0.0.5
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/README.md +15 -3
- data/lib/quote_sql/error.rb +47 -0
- data/lib/quote_sql/formater.rb +7 -5
- data/lib/quote_sql/quoter.rb +173 -124
- data/lib/quote_sql/test.rb +193 -142
- data/lib/quote_sql/version.rb +3 -0
- data/lib/quote_sql.rb +58 -137
- metadata +20 -5
- data/lib/quote_sql/deprecated.rb +0 -162
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb47e85b4c7c4e1f945748295390c9e1bd49b7e0ba5291e0f7310058f6f91ddc
|
4
|
+
data.tar.gz: 0f5bde1afc31eb573bb3e24727b530bf5909048284114d45c56c1b24a63e97aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6596b9bb50ee373030e401dcb9d0067ae31857b6467fdd7b0341e21b3dcbe8fb0e78714ec24f56615618bbf965849307474a4030978e6c98d2d728166e235151
|
7
|
+
data.tar.gz: f38366de3e2227835fd11f512a9c9d2a99d130d896a17f6b0a58788dd8ed7ebd13f46682992b762e2d50f09716c3bd5654d525dc4b03f350d3a52cc6b19b322e
|
data/README.md
CHANGED
@@ -9,13 +9,15 @@ I created this library while coding for different projects, and had lots of Here
|
|
9
9
|
|
10
10
|
My strategy is to segment SQL Queries in readable junks, which can be individually tested and then combine their sql to the final query.
|
11
11
|
|
12
|
-
QuoteSql is used in production, but is still bleeding edge - and there is not a fully sync between doc and code.
|
13
|
-
|
14
12
|
If you think QuoteSql is interesting, let's chat!
|
15
13
|
Also if you have problems using it, just drop me a note.
|
16
14
|
|
17
15
|
Best Martin
|
18
16
|
|
17
|
+
## Caveats & Notes
|
18
|
+
- QuoteSql is used in production, but is still bleeding edge - and there is not a fully sync between doc and code.
|
19
|
+
- Just for my examples and in the docs, I'm using for Yajl for JSON parsing, and changed in my environments the standard parse output to *symbolized keys*.
|
20
|
+
|
19
21
|
## Examples
|
20
22
|
### Simple quoting
|
21
23
|
`QuoteSql.new("SELECT %field").quote(field: "abc").to_sql`
|
@@ -119,6 +121,12 @@ with optional array dimension
|
|
119
121
|
- +String+ value will become the expression, the key the AS {result: "SUM(*)"} => SUM(*) AS result
|
120
122
|
- +Proc+ are executed with the +QuoteSQL::Quoter+ object as parameter and added as raw SQL
|
121
123
|
|
124
|
+
## Executing
|
125
|
+
### Getting the results
|
126
|
+
### Binds
|
127
|
+
`v = {a: 1, b: "foo", c: true};QuoteSQL(%q{Select * From %x_json}, x_json: 1, x_casts: {a: "int", b: "text", c: "boolean"}).result(v.to_json)`
|
128
|
+
=> Select * From json_to_recordset($1) AS "x"("a" int,"b" text,"c" boolean) => [{a: 1, b: "foo", c: true}]
|
129
|
+
|
122
130
|
## Shortcuts and functions
|
123
131
|
- `QuoteSQL("select %abc", abc: 1)` == `QuoteSql.new("select %abc").quote(abc: 1)`
|
124
132
|
- when you have in your initializer `String.include QuoteSql::Extension` you can do e.g. `"select %abc".quote_sql(abc: 1)`
|
@@ -127,7 +135,11 @@ with optional array dimension
|
|
127
135
|
## Debug and dump
|
128
136
|
If you have pg_format installed you can get the resulting query inspected:
|
129
137
|
`QuoteSql.new("select %abc").quote(abc: 1).dsql`
|
130
|
-
|
138
|
+
|
139
|
+
# Test
|
140
|
+
Minimal tests you can run by
|
141
|
+
`QuoteSql.test.all`
|
142
|
+
You can find them in /lib/quote_sql/test.rb
|
131
143
|
|
132
144
|
## Installing
|
133
145
|
`gem install quote-sql`
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class QuoteSql
|
2
|
+
class Error < ::RuntimeError
|
3
|
+
def initialize(quote_sql, errors)
|
4
|
+
@object = quote_sql
|
5
|
+
@errors = errors
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :object, :errors
|
9
|
+
|
10
|
+
def original
|
11
|
+
@object.original.dsql
|
12
|
+
end
|
13
|
+
|
14
|
+
def sql
|
15
|
+
@object.sql.dsql
|
16
|
+
end
|
17
|
+
|
18
|
+
def tables
|
19
|
+
@object.tables.inspect
|
20
|
+
end
|
21
|
+
|
22
|
+
def columns
|
23
|
+
@object.columns.inspect
|
24
|
+
end
|
25
|
+
|
26
|
+
def quotes
|
27
|
+
@object.quotes.inspect
|
28
|
+
end
|
29
|
+
|
30
|
+
def message
|
31
|
+
|
32
|
+
errors = @object.errors.map do |quote, error|
|
33
|
+
error => {exc:, backtrace:, **transformations}
|
34
|
+
|
35
|
+
"#{quote}: #{exc.class} #{exc.message} #{transformations.inspect}\n#{backtrace.join("\n")}"
|
36
|
+
end
|
37
|
+
<<~ERROR
|
38
|
+
Original: #{original}
|
39
|
+
Tables:
|
40
|
+
Quotes: #{quotes}
|
41
|
+
Processed: #{sql}
|
42
|
+
#{errors.join("\n\n")}
|
43
|
+
#{'*' * 40}
|
44
|
+
ERROR
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/quote_sql/formater.rb
CHANGED
@@ -9,11 +9,13 @@ class QuoteSql
|
|
9
9
|
|
10
10
|
def to_formatted_sql
|
11
11
|
sql = respond_to?(:to_sql) ? to_sql : to_s
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
Niceql::Prettifier.prettify_sql(sql)
|
13
|
+
|
14
|
+
# IO.popen(PG_FORMAT_BIN, "r+", err: "/dev/null") do |f|
|
15
|
+
# f.write(sql)
|
16
|
+
# f.close_write
|
17
|
+
# f.read
|
18
|
+
# end
|
17
19
|
rescue
|
18
20
|
sql
|
19
21
|
end
|
data/lib/quote_sql/quoter.rb
CHANGED
@@ -3,35 +3,98 @@ class QuoteSql
|
|
3
3
|
def initialize(qsql, key, quotable)
|
4
4
|
@qsql = qsql
|
5
5
|
@key, @quotable = key, quotable
|
6
|
+
@name = key.sub(/_[^_]+$/, '') if key["_"]
|
6
7
|
end
|
7
8
|
|
9
|
+
attr_reader :key, :quotable, :name
|
10
|
+
|
8
11
|
def quotes
|
9
12
|
@qsql.quotes
|
10
13
|
end
|
11
14
|
|
12
|
-
|
15
|
+
def table(name = nil)
|
16
|
+
@qsql.table(name || self.name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def ident_table(i = nil)
|
20
|
+
Raw.sql(Array(self.table(name)).compact[0..i].map do |table|
|
21
|
+
if table.respond_to? :table_name
|
22
|
+
QuoteSql.quote_column_name table.table_name
|
23
|
+
elsif table.present?
|
24
|
+
QuoteSql.quote_column_name table
|
25
|
+
end
|
26
|
+
end.join(","))
|
27
|
+
end
|
28
|
+
|
29
|
+
def columns(name = nil)
|
30
|
+
@qsql.columns(name || self.name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def casts(name = nil)
|
34
|
+
@qsql.casts(name || self.name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def ident_columns(name = nil)
|
38
|
+
item = columns(name || self.name)
|
39
|
+
unless item
|
40
|
+
unless item = casts(name || self.name)&.keys
|
41
|
+
if (table = self.table(name || self.name))&.respond_to? :column_names
|
42
|
+
item = table.column_names
|
43
|
+
else
|
44
|
+
raise ArgumntError, "No columns, casts or table given for #{name}" unless table&.respond_to? :column_names
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
if item.is_a?(Array)
|
49
|
+
if item.all? { _1.respond_to?(:name) }
|
50
|
+
item = item.map(&:name)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
_ident(item)
|
54
|
+
end
|
55
|
+
|
56
|
+
def _quote_ident(item)
|
57
|
+
Raw.sql case item.class.to_s
|
58
|
+
when "QuoteSql::Raw", "Arel::Nodes::SqlLiteral" then item
|
59
|
+
when "Hash" then json_hash_ident(item)
|
60
|
+
when "Array" then json_array_ident(item)
|
61
|
+
when "Proc" then item.call(self)
|
62
|
+
when "Integer" then "$#{item}"
|
63
|
+
when "Symbol" then [ident_table(0).presence, _quote_ident(item.to_s)].compact.join(".")
|
64
|
+
when "String" then item.scan(/(?:^|")?([^."]+)/).flatten.map { QuoteSql.quote_column_name _1 }.join(".")
|
65
|
+
else raise ArgumentError, "just Hash, Array, Arel::Nodes::SqlLiteral, QuoteSql::Raw, String, Symbol, Proc, Integer, or responding to #to_sql"
|
66
|
+
end
|
67
|
+
end
|
13
68
|
|
14
|
-
def
|
15
|
-
|
69
|
+
def _ident(item = @quotable)
|
70
|
+
return Raw.sql(item) if item.respond_to?(:to_sql)
|
71
|
+
rv = case item.class.to_s
|
72
|
+
when "Array"
|
73
|
+
item.map { _1.is_a?(Hash) ? _ident(_1) : _quote_ident(_1) }.join(",")
|
74
|
+
when "Hash"
|
75
|
+
item.map { "#{_quote_ident(_2)} AS \"#{_1}\"" }.join(",")
|
76
|
+
else
|
77
|
+
_quote_ident(item)
|
78
|
+
# _quote_column_name(item)
|
79
|
+
end
|
80
|
+
Raw.sql rv
|
16
81
|
end
|
17
82
|
|
18
83
|
def to_sql
|
19
84
|
return @quotable.call(self) if @quotable.is_a? Proc
|
20
85
|
case key.to_s
|
21
86
|
when /(?:^|(.*)_)table$/i
|
22
|
-
|
23
|
-
when /(?:^|(.*)_)columns
|
24
|
-
|
25
|
-
when /(?:^|(.*)_)(
|
26
|
-
|
27
|
-
when /(?:^|(.*)_)(column_name?s?)$/i
|
28
|
-
ident_name
|
29
|
-
when /(?:^|(.*)_)(ident|args)$/i
|
30
|
-
ident_name
|
87
|
+
ident_table
|
88
|
+
when /(?:^|(.*)_)columns$/i
|
89
|
+
ident_columns
|
90
|
+
when /(?:^|(.*)_)(ident)$/i
|
91
|
+
_ident
|
31
92
|
when /(?:^|(.*)_)constraints?$/i
|
32
|
-
quotable
|
93
|
+
quotable
|
33
94
|
when /(?:^|(.*)_)(raw|sql)$/i
|
34
|
-
quotable
|
95
|
+
quotable
|
96
|
+
when /^(.+)_json$/i
|
97
|
+
data_json
|
35
98
|
when /^(.+)_values$/i
|
36
99
|
data_values
|
37
100
|
when /values$/i
|
@@ -41,20 +104,34 @@ class QuoteSql
|
|
41
104
|
end
|
42
105
|
end
|
43
106
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
107
|
+
###############
|
108
|
+
|
109
|
+
private def value(values)
|
110
|
+
# case values.class.to_s
|
111
|
+
# when "QuoteSql::Raw", "Arel::Nodes::SqlLiteral" then rv = values
|
112
|
+
# when "Array"
|
113
|
+
# when "Hash"
|
114
|
+
# columns = self.columns(name)&.flat_map { _1.is_a?(Hash) ? _1.values : _1 }
|
115
|
+
# if columns.nil?
|
116
|
+
# values = values.values
|
117
|
+
# elsif columns.all? { _1.is_a? Symbol }
|
118
|
+
# raise ArgumentError, "Columns just Symbols"
|
119
|
+
# else
|
120
|
+
# values = columns.map do |column|
|
121
|
+
# if values.key?(column&.to_sym) or !defaults
|
122
|
+
# values[column.to_sym]
|
123
|
+
# elsif column[/^(created|updated)_at$/]
|
124
|
+
# :current_timestamp
|
125
|
+
# else
|
126
|
+
# :default
|
127
|
+
# end
|
128
|
+
# end
|
129
|
+
# end
|
130
|
+
# else
|
131
|
+
# raise ArgumentError, "value just Array, Hash, QuoteSql::Raw, Arel::Nodes::SqlLiteral"
|
132
|
+
# end
|
133
|
+
|
134
|
+
rv ||= values.map do |i|
|
58
135
|
case i
|
59
136
|
when :default, :current_timestamp
|
60
137
|
next i.to_s.upcase
|
@@ -62,13 +139,26 @@ class QuoteSql
|
|
62
139
|
i = i.to_json
|
63
140
|
end
|
64
141
|
_quote(i)
|
65
|
-
end
|
142
|
+
end
|
143
|
+
Raw.sql "(#{rv.join(",")})"
|
144
|
+
end
|
66
145
|
|
146
|
+
def data_json(item = @quotable)
|
147
|
+
casts = self.casts(name)
|
148
|
+
columns = self.columns(name) || casts&.keys
|
149
|
+
column_cast = columns&.map { "#{QuoteSql.quote_column_name(_1)} #{casts&.dig(_1) || "TEXT"}" }
|
150
|
+
if item.is_a? Integer
|
151
|
+
rv = "$#{item}"
|
152
|
+
else
|
153
|
+
item = [item].flatten.compact.as_json.map { _1.slice(*columns.map(&:to_s)) }
|
154
|
+
rv = "'#{item.to_json.gsub(/'/, "''")}'"
|
155
|
+
end
|
156
|
+
Raw.sql "json_to_recordset(#{rv}) AS #{QuoteSql.quote_column_name name}(#{column_cast.join(',')})"
|
67
157
|
end
|
68
158
|
|
69
159
|
def data_values(item = @quotable)
|
70
160
|
item = Array(item).compact
|
71
|
-
column_names =
|
161
|
+
column_names = columns(name)
|
72
162
|
if column_names.is_a? Hash
|
73
163
|
types = column_names.values.map { "::#{_1.upcase}" if _1 }
|
74
164
|
column_names = column_names.keys
|
@@ -80,7 +170,7 @@ class QuoteSql
|
|
80
170
|
if item.all? { _1.is_a?(Array) }
|
81
171
|
length, overflow = item.map { _1.length }.uniq
|
82
172
|
raise ArgumentError, "all values need to have the same length" if overflow
|
83
|
-
column_names ||= (1..length).map{"column#{_1}"}
|
173
|
+
column_names ||= (1..length).map { "column#{_1}" }
|
84
174
|
raise ArgumentError, "#{name}_columns and value lengths need to be the same" if column_names.length != length
|
85
175
|
values = item.map { value(_1) }
|
86
176
|
else
|
@@ -88,18 +178,17 @@ class QuoteSql
|
|
88
178
|
end
|
89
179
|
if types.present?
|
90
180
|
value = values[0][1..-2].split(/\s*,\s*/)
|
91
|
-
types.each_with_index { value[_2] << _1 || ""}
|
181
|
+
types.each_with_index { value[_2] << _1 || "" }
|
92
182
|
values[0] = "(" + value.join(",") + ")"
|
93
183
|
end
|
94
184
|
# values[0] { _1 << types[_1] || ""}
|
95
|
-
"(VALUES #{values.join(",")}) AS #{
|
185
|
+
Raw.sql "(VALUES #{values.join(",")}) AS #{_ident name} (#{_ident column_names})"
|
96
186
|
end
|
97
187
|
|
98
|
-
|
99
188
|
def insert_values(item = @quotable)
|
100
189
|
case item
|
101
190
|
when Arel::Nodes::SqlLiteral
|
102
|
-
item =
|
191
|
+
item = Raw.sql("(#{item})") unless item[/^\s*\(/] and item[/\)\s*$/]
|
103
192
|
return item
|
104
193
|
when Array
|
105
194
|
item.compact!
|
@@ -129,9 +218,9 @@ class QuoteSql
|
|
129
218
|
raise ArgumentError, "Either all type Hash or Array"
|
130
219
|
end
|
131
220
|
if column_names.present?
|
132
|
-
"(#{
|
221
|
+
Raw.sql "(#{_ident column_names}) VALUES #{values.join(",")}"
|
133
222
|
else
|
134
|
-
"VALUES #{values.join(",")}"
|
223
|
+
Raw.sql "VALUES #{values.join(",")}"
|
135
224
|
end
|
136
225
|
when Hash
|
137
226
|
value([item])
|
@@ -151,51 +240,31 @@ class QuoteSql
|
|
151
240
|
private def _quote(item = @quotable, cast = self.cast)
|
152
241
|
rv = QuoteSql.quote(item)
|
153
242
|
if cast
|
154
|
-
rv << "::#{cast}"
|
243
|
+
rv << "::#{cast.upcase}"
|
155
244
|
rv << "[]" * rv.depth if rv[/^ARRAY/]
|
156
245
|
end
|
157
|
-
rv
|
246
|
+
Raw.sql rv
|
158
247
|
end
|
159
248
|
|
160
|
-
private def _quote_column_name(name
|
161
|
-
name
|
162
|
-
rv = QuoteSql.quote_column_name(name)
|
163
|
-
return rv unless column.present?
|
164
|
-
rv + "." + QuoteSql.quote_column_name(column)
|
249
|
+
private def _quote_column_name(name)
|
250
|
+
Raw.sql name.scan(/(?:^|")?([^."]+)/).map { QuoteSql.quote_column_name _1 }.join(".")
|
165
251
|
end
|
166
252
|
|
167
253
|
def quote(item = @quotable)
|
168
|
-
case item
|
169
|
-
when Arel::Nodes::SqlLiteral
|
170
|
-
return item
|
171
|
-
when Array
|
254
|
+
case item.class.to_s
|
255
|
+
when "Arel::Nodes::SqlLiteral", "QuoteSql::Raw"
|
256
|
+
return Raw.sql(item)
|
257
|
+
when "Array"
|
172
258
|
return _quote(item.to_json) if json?
|
173
259
|
_quote(item)
|
174
|
-
when Hash
|
175
|
-
|
176
|
-
item.map do |as, item|
|
177
|
-
"#{_quote(item)} AS #{as}"
|
178
|
-
end.join(",")
|
260
|
+
when "Hash"
|
261
|
+
_quote(item.to_json, :jsonb)
|
179
262
|
else
|
180
|
-
return item.to_sql if item.respond_to? :to_sql
|
263
|
+
return Raw.sql item.to_sql if item.respond_to? :to_sql
|
181
264
|
_quote(item)
|
182
265
|
end
|
183
266
|
end
|
184
267
|
|
185
|
-
def columns(item = @quotable)
|
186
|
-
if item.respond_to?(:column_names)
|
187
|
-
item = item.column_names
|
188
|
-
elsif item.class.respond_to?(:column_names)
|
189
|
-
item = item.class.column_names
|
190
|
-
elsif item.is_a?(Array)
|
191
|
-
if item.all?{ _1.respond_to?(:name) }
|
192
|
-
item = item.map(&:name)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
@qsql.column_names ||= item
|
196
|
-
ident_name(item)
|
197
|
-
end
|
198
|
-
|
199
268
|
def column_names(item = @quotable)
|
200
269
|
if item.respond_to?(:column_names)
|
201
270
|
item = item.column_names
|
@@ -205,70 +274,50 @@ class QuoteSql
|
|
205
274
|
item = item.map(&:name)
|
206
275
|
end
|
207
276
|
@qsql.column_names ||= item
|
208
|
-
|
277
|
+
_ident(item)
|
209
278
|
end
|
210
279
|
|
211
|
-
def
|
212
|
-
|
213
|
-
rv = "jsonb_build_object(" + h.map { "'#{_1}',#{_2}" }.join(",") + ")"
|
214
|
-
return rv unless compact
|
215
|
-
"jsonb_strip_nulls(#{rv})"
|
280
|
+
def json_array_values(h)
|
281
|
+
Raw.sql "'#{h.to_json.gsub(/'/, "''")}'::JSONB"
|
216
282
|
end
|
217
283
|
|
218
|
-
def
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
case item
|
223
|
-
when Hash
|
224
|
-
ident_name(item)
|
225
|
-
when String, Symbol
|
226
|
-
_quote_column_name(item)
|
227
|
-
when Proc
|
228
|
-
item.call(self)
|
229
|
-
end
|
230
|
-
end.join(",")
|
231
|
-
when Hash
|
232
|
-
item.map do |k,v|
|
233
|
-
case v
|
234
|
-
when Symbol
|
235
|
-
_quote_column_name(k, v)
|
236
|
-
when String
|
237
|
-
"#{v} AS #{k}"
|
238
|
-
when Proc
|
239
|
-
item.call(self)
|
240
|
-
when Hash
|
241
|
-
"#{json_build_object(v)} AS #{k}"
|
242
|
-
else
|
243
|
-
raise ArgumentError
|
244
|
-
end
|
245
|
-
end.join(",")
|
246
|
-
else
|
247
|
-
_quote_column_name(item)
|
248
|
-
end
|
284
|
+
def json_hash_values(h)
|
285
|
+
compact = h.delete(nil) == false
|
286
|
+
rv = json_array_values(h)
|
287
|
+
Raw.sql(compact ? "jsonb_strip_nulls(#{rv})" : rv)
|
249
288
|
end
|
250
289
|
|
251
|
-
def
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
item = item.class.table_name
|
256
|
-
end
|
257
|
-
table_name(item || @qsql.table_name)
|
290
|
+
def json_hash_ident(h)
|
291
|
+
compact = h.delete(nil) == false
|
292
|
+
rv = "jsonb_build_object(" + h.map { "'#{_1.to_s.gsub(/'/, "''")}', #{_ident(_2)}" }.join(",") + ")"
|
293
|
+
Raw.sql(compact ? "jsonb_strip_nulls(#{rv})" : rv)
|
258
294
|
end
|
259
295
|
|
260
|
-
def
|
261
|
-
|
262
|
-
when Array
|
263
|
-
item.map do |item|
|
264
|
-
item.is_a?(Hash) ? table_name(item) : _quote_column_name(item)
|
265
|
-
end.join(",")
|
266
|
-
when Hash
|
267
|
-
raise NotImplementedError, "table name is a Hash"
|
268
|
-
# perhaps as ...
|
269
|
-
else
|
270
|
-
_quote_column_name(item)
|
271
|
-
end
|
296
|
+
def json_array_ident(h)
|
297
|
+
Raw.sql "jsonb_build_array(#{h.map { _ident(_2) }.join(",")})"
|
272
298
|
end
|
299
|
+
|
300
|
+
# def table(item = @quotable)
|
301
|
+
# @qsql.table_name ||= if item.respond_to?(:table_name)
|
302
|
+
# item = item.table_name
|
303
|
+
# elsif item.class.respond_to?(:table_name)
|
304
|
+
# item = item.class.table_name
|
305
|
+
# end
|
306
|
+
# table_name(item || @qsql.table_name)
|
307
|
+
# end
|
308
|
+
#
|
309
|
+
# def table_name(item = @quotable)
|
310
|
+
# case item
|
311
|
+
# when Array
|
312
|
+
# item.map do |item|
|
313
|
+
# item.is_a?(Hash) ? table_name(item) : _quote_column_name(item)
|
314
|
+
# end.join(",")
|
315
|
+
# when Hash
|
316
|
+
# raise NotImplementedError, "table name is a Hash"
|
317
|
+
# # perhaps as ...
|
318
|
+
# else
|
319
|
+
# _quote_column_name(item)
|
320
|
+
# end
|
321
|
+
# end
|
273
322
|
end
|
274
323
|
end
|