twowaysql 0.2.0
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.
- data/History.txt +3 -0
- data/License.txt +13 -0
- data/Manifest.txt +38 -0
- data/README.txt +382 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +73 -0
- data/config/requirements.rb +15 -0
- data/issues/issue-25efcfc383f3b0f6c0e2730ae7c2975bb2b3de26.yaml +18 -0
- data/issues/issue-39023ea09e17e2d64bcef03aa59cdfe38b78ad5b.yaml +26 -0
- data/issues/issue-4bc308d55ae91f266e656162a4147d356de1166c.yaml +24 -0
- data/issues/issue-897995fa10377eabdf597e8e7692f17087c76923.yaml +26 -0
- data/issues/issue-bd38c1cdc965d73dd629a81db2de1bcdcf4b10b8.yaml +26 -0
- data/issues/issue-f2b773020b54f839c03d899b38b5113c8fd991df.yaml +18 -0
- data/issues/issue-f39b907d01d7fa93df8c7a9de2e1b5e27727ee0a.yaml +18 -0
- data/issues/issue-f64d73ed4f9854f1ded77e6496dbf59cfb3770a7.yaml +18 -0
- data/issues/project.yaml +16 -0
- data/lib/twowaysql/node.rb +239 -0
- data/lib/twowaysql/parser.rb +489 -0
- data/lib/twowaysql/parser.y +226 -0
- data/lib/twowaysql/template.rb +75 -0
- data/lib/twowaysql/version.rb +9 -0
- data/lib/twowaysql.rb +6 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/spec/large_sql_spec.rb +142 -0
- data/spec/learning_regex_spec.rb +234 -0
- data/spec/spec.opts +0 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/twowaysql_spec.rb +736 -0
- data/tasks/deployment.rake +53 -0
- data/tasks/ditz.rake +8 -0
- data/tasks/environment.rake +7 -0
- data/tasks/racc.rake +23 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- metadata +104 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
--- !ditz.rubyforge.org,2008-03-06/issue
|
2
|
+
title: Handle Embedded variable comment at Scanner/Grammer level
|
3
|
+
desc: Handle Embedded variable comment at Scanner/Grammer level. Currently it is handled at Node object level, so Scanner does not know the Substitution comment is Bind variable comment or Embedded variable comment. However Node should not be responsible for that, Scanner/Grammer should do.
|
4
|
+
type: :task
|
5
|
+
component: twowaysql
|
6
|
+
release:
|
7
|
+
reporter: takuto <takuto.wada@gmail.com>
|
8
|
+
status: :unstarted
|
9
|
+
disposition:
|
10
|
+
creation_time: 2008-09-04 19:53:35.026331 Z
|
11
|
+
references: []
|
12
|
+
|
13
|
+
id: f39b907d01d7fa93df8c7a9de2e1b5e27727ee0a
|
14
|
+
log_events:
|
15
|
+
- - 2008-09-04 19:53:37.545312 Z
|
16
|
+
- takuto <takuto.wada@gmail.com>
|
17
|
+
- created
|
18
|
+
- ""
|
@@ -0,0 +1,18 @@
|
|
1
|
+
--- !ditz.rubyforge.org,2008-03-06/issue
|
2
|
+
title: preserve actual comment content
|
3
|
+
desc: preserve actual comment content
|
4
|
+
type: :feature
|
5
|
+
component: twowaysql
|
6
|
+
release:
|
7
|
+
reporter: takuto <takuto.wada@gmail.com>
|
8
|
+
status: :unstarted
|
9
|
+
disposition:
|
10
|
+
creation_time: 2008-09-03 08:33:12.940300 Z
|
11
|
+
references: []
|
12
|
+
|
13
|
+
id: f64d73ed4f9854f1ded77e6496dbf59cfb3770a7
|
14
|
+
log_events:
|
15
|
+
- - 2008-09-03 08:33:34.448031 Z
|
16
|
+
- takuto <takuto.wada@gmail.com>
|
17
|
+
- created
|
18
|
+
- preserve actual comment content if :preserve_comment is on.
|
data/issues/project.yaml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
--- !ditz.rubyforge.org,2008-03-06/project
|
2
|
+
name: twowaysql
|
3
|
+
version: "0.4"
|
4
|
+
components:
|
5
|
+
- !ditz.rubyforge.org,2008-03-06/component
|
6
|
+
name: twowaysql
|
7
|
+
releases:
|
8
|
+
- !ditz.rubyforge.org,2008-03-06/release
|
9
|
+
name: 0.2 release
|
10
|
+
status: :unreleased
|
11
|
+
release_time:
|
12
|
+
log_events:
|
13
|
+
- - 2008-09-03 08:30:15.096853 Z
|
14
|
+
- takuto <takuto.wada@gmail.com>
|
15
|
+
- created
|
16
|
+
- first published version.
|
@@ -0,0 +1,239 @@
|
|
1
|
+
unless String.method_defined?(:start_with?)
|
2
|
+
class String #:nodoc:
|
3
|
+
def start_with?(prefix)
|
4
|
+
prefix = prefix.to_s
|
5
|
+
self[0, prefix.length] == prefix
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
module TwoWaySQL
|
12
|
+
|
13
|
+
class Context
|
14
|
+
|
15
|
+
def initialize(data)
|
16
|
+
@data = data
|
17
|
+
@enabled = true
|
18
|
+
@bound_variables = []
|
19
|
+
@sql_fragments = []
|
20
|
+
end
|
21
|
+
attr_reader :bound_variables
|
22
|
+
attr_reader :sql_fragments
|
23
|
+
attr_reader :data
|
24
|
+
|
25
|
+
def sql(separator="")
|
26
|
+
@sql_fragments.join(separator)
|
27
|
+
end
|
28
|
+
|
29
|
+
def fork_child
|
30
|
+
child = Context.new(@data)
|
31
|
+
child.disable!
|
32
|
+
child
|
33
|
+
end
|
34
|
+
|
35
|
+
def join_child(child_ctx)
|
36
|
+
@sql_fragments.concat(child_ctx.sql_fragments)
|
37
|
+
@bound_variables.concat(child_ctx.bound_variables)
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_sql(sql_fragment)
|
41
|
+
@sql_fragments << sql_fragment
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_value(value)
|
45
|
+
@sql_fragments << '?'
|
46
|
+
@bound_variables << value
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_values(values)
|
50
|
+
@sql_fragments << Array.new(values.size, '?').join(', ')
|
51
|
+
@bound_variables.concat(values)
|
52
|
+
end
|
53
|
+
|
54
|
+
def enabled?
|
55
|
+
@enabled
|
56
|
+
end
|
57
|
+
|
58
|
+
def enable!
|
59
|
+
@enabled = true
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
def disable!
|
64
|
+
@enabled = false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
class Node
|
71
|
+
protected
|
72
|
+
def exec_list(nodes, ctx)
|
73
|
+
v = nil
|
74
|
+
nodes.each do |i|
|
75
|
+
v = i.accept(ctx)
|
76
|
+
end
|
77
|
+
v
|
78
|
+
end
|
79
|
+
|
80
|
+
def do_eval(ctx, exp)
|
81
|
+
safe_eval(ctx.data, exp)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
def safe_eval(ctx, exp)
|
86
|
+
within_safe_level(4) { eval(exp) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def within_safe_level(level)
|
90
|
+
result = nil
|
91
|
+
Thread.start {
|
92
|
+
$SAFE = level
|
93
|
+
result = yield
|
94
|
+
}.join
|
95
|
+
result
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
class RootNode < Node
|
101
|
+
def initialize(tree)
|
102
|
+
@tree = tree
|
103
|
+
end
|
104
|
+
def accept(ctx)
|
105
|
+
exec_list(@tree, ctx)
|
106
|
+
end
|
107
|
+
def children
|
108
|
+
@tree
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
class IfNode < Node
|
114
|
+
def initialize(cond, tstmt, fstmt)
|
115
|
+
@condition = cond
|
116
|
+
@tstmt = tstmt
|
117
|
+
@fstmt = fstmt
|
118
|
+
end
|
119
|
+
def accept(ctx)
|
120
|
+
if do_eval(ctx, @condition)
|
121
|
+
exec_list(@tstmt, ctx)
|
122
|
+
ctx.enable!
|
123
|
+
elsif @fstmt
|
124
|
+
exec_list(@fstmt, ctx)
|
125
|
+
ctx.enable!
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
class BeginNode < Node
|
132
|
+
def initialize(tree)
|
133
|
+
@tree = tree
|
134
|
+
end
|
135
|
+
def accept(ctx)
|
136
|
+
child_ctx = ctx.fork_child
|
137
|
+
exec_list(@tree, child_ctx)
|
138
|
+
if child_ctx.enabled?
|
139
|
+
ctx.join_child(child_ctx)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
class SubStatementNode < Node
|
146
|
+
def initialize(prefix, tree)
|
147
|
+
@prefix = prefix
|
148
|
+
@tree = tree
|
149
|
+
end
|
150
|
+
def accept(ctx)
|
151
|
+
ctx.add_sql(@prefix) if ctx.enabled?
|
152
|
+
exec_list(@tree, ctx)
|
153
|
+
end
|
154
|
+
def each
|
155
|
+
yield self
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
class SubstitutionNode < Node
|
161
|
+
def initialize(exp)
|
162
|
+
@exp = exp
|
163
|
+
end
|
164
|
+
def accept(ctx)
|
165
|
+
if @exp.start_with?('$')
|
166
|
+
embed_value(ctx)
|
167
|
+
else
|
168
|
+
substitute(ctx)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
def substitute(ctx)
|
172
|
+
ctx.add_value(do_eval(ctx, @exp))
|
173
|
+
end
|
174
|
+
def embed_value(ctx)
|
175
|
+
result = do_eval(ctx, @exp[1..-1])
|
176
|
+
ctx.add_sql(result) unless result.nil?
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
class QuestionNode < Node
|
182
|
+
def initialize(num)
|
183
|
+
@num = num
|
184
|
+
end
|
185
|
+
def accept(ctx)
|
186
|
+
ctx.add_value(ctx.data[@num])
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
class ParenSubstitutionNode < Node
|
192
|
+
def initialize(exp)
|
193
|
+
@exp = exp
|
194
|
+
end
|
195
|
+
def accept(ctx)
|
196
|
+
result = do_eval(ctx, @exp)
|
197
|
+
return if result.nil?
|
198
|
+
if result.respond_to?('to_ary')
|
199
|
+
bind_values(ctx, result.to_ary)
|
200
|
+
else
|
201
|
+
ctx.add_value(result)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
def bind_values(ctx, ary)
|
205
|
+
return if ary.empty?
|
206
|
+
ctx.add_sql("(")
|
207
|
+
ctx.add_values(ary)
|
208
|
+
ctx.add_sql(")")
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
class LiteralNode < Node
|
214
|
+
def initialize(val)
|
215
|
+
@val = val
|
216
|
+
end
|
217
|
+
def accept(ctx)
|
218
|
+
ctx.add_sql(@val)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
class CommentNode < Node
|
224
|
+
def initialize(val)
|
225
|
+
@val = val
|
226
|
+
end
|
227
|
+
def accept(ctx)
|
228
|
+
# nothing to do
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
class EolNode < Node
|
234
|
+
def accept(ctx)
|
235
|
+
ctx.add_sql("\n")
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|