Skip to content

Commit 59a557c

Browse files
committed
Fixing issues with escaping single characters
1 parent 4aba43b commit 59a557c

File tree

3 files changed

+11
-10
lines changed

3 files changed

+11
-10
lines changed

stmt/parse.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ func readVarName(r []rune, i, end int, q rune) (int, rune) {
177177
// A command is defined as the first non-blank text after \, followed by
178178
// parameters up to either the next \ or a control character (for example, \n):
179179
func readCommand(r []rune, i, end int) (int, int) {
180-
command:
181180
// find end of command
181+
c, next := rune(0), rune(0)
182+
command:
182183
for ; i < end; i++ {
183-
next := grab(r, i+1, end)
184-
switch {
184+
switch next = grab(r, i+1, end); {
185185
case next == 0:
186186
return end, end
187187
case next == '\\' || unicode.IsControl(next):
@@ -196,8 +196,7 @@ command:
196196
params:
197197
// find end of params
198198
for ; i < end; i++ {
199-
c, next := r[i], grab(r, i+1, end)
200-
switch {
199+
switch c, next = r[i], grab(r, i+1, end); {
201200
case next == 0:
202201
return cmd, end
203202
case quote == 0 && (c == '\'' || c == '"' || c == '`'):

stmt/parse_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ func TestSubstituteVar(t *testing.T) {
537537
for i, test := range tests {
538538
t.Run(strconv.Itoa(i), func(t *testing.T) {
539539
z := []rune(test.s)
540-
y, l := substituteVar(z, test.v, test.sub)
540+
y, l := test.v.Substitute(z, test.sub, true)
541541
if sl := len([]rune(test.sub)); test.v.Len != sl {
542542
t.Errorf("expected v.Len to be %d, got: %d", sl, test.v.Len)
543543
}

stmt/stmt.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func (b *Stmt) RawString() string {
7171
i, s, z := 0, string(b.Buf), new(bytes.Buffer)
7272
// deinterpolate vars
7373
for _, v := range b.Vars {
74-
if !v.Defined {
74+
if !v.Defined && v.Quote != '\\' {
7575
continue
7676
}
7777
if len(s) > i {
@@ -222,8 +222,6 @@ parse:
222222
case b.quote != 0 || b.multilineComment || b.balanceCount != 0:
223223
// skip escaped backslash, semicolon, colon
224224
case c == '\\' && (next == '\\' || next == ';' || next == ':'):
225-
// FIXME: the below works, but it may not make sense to keep this enabled.
226-
// FIXME: also, the behavior is slightly different than psql
227225
v := &Var{
228226
I: i,
229227
End: i + 2,
@@ -234,6 +232,7 @@ parse:
234232
if b.r, b.rlen = v.Substitute(b.r, string(next), false); b.Len != 0 {
235233
v.I += b.Len + 1
236234
}
235+
i++
237236
// start of command
238237
case c == '\\':
239238
// parse command and params end positions
@@ -373,7 +372,10 @@ func (v *Var) String() string {
373372

374373
// Substitute substitutes part of r, with s.
375374
func (v *Var) Substitute(r []rune, s string, ok bool) ([]rune, int) {
376-
if v.Quote == '?' {
375+
switch v.Quote {
376+
case '\\':
377+
s = "\\" + s
378+
case '?':
377379
s = trueFalse(ok)
378380
}
379381
sr, rcap := []rune(s), cap(r)

0 commit comments

Comments
 (0)