be more strict about identifier printing

When stringifying a query, we would print the identifier bare most
of the time. This caused issues when stringifying an identifier
that contained elements of syntax. For example, querying for the
value "in-bytes" would fail because the mapper would serialize it to
in-bytes and would parse it as an expression. Same problem occured
when using keywords as identifier names, such as select or in.

Fixes #3547
pull/3560/head
Daniel Morsing 2015-08-05 17:40:42 +01:00
parent affd0b1ca2
commit fc4246d7f5
4 changed files with 15 additions and 26 deletions

View File

@ -1992,26 +1992,6 @@ func (f *Field) Name() string {
func (f *Field) String() string {
str := f.Expr.String()
switch f.Expr.(type) {
case *VarRef:
quoted := false
// Escape any double-quotes in the field
if strings.Contains(str, `"`) {
str = strings.Replace(str, `"`, `\"`, -1)
quoted = true
}
// Escape any single-quotes in the field
if strings.Contains(str, `'`) {
quoted = true
}
// Double-quote field names with spaces or that were previously escaped
if strings.Contains(str, " ") || quoted {
str = fmt.Sprintf("\"%s\"", str)
}
}
if f.Alias == "" {
return str
}
@ -2132,7 +2112,9 @@ type VarRef struct {
}
// String returns a string representation of the variable reference.
func (r *VarRef) String() string { return r.Val }
func (r *VarRef) String() string {
return QuoteIdent(r.Val)
}
// Call represents a function call.
type Call struct {

View File

@ -44,35 +44,35 @@ func TestSelectStatement_Substatement(t *testing.T) {
{
stmt: `SELECT sum(aa.value) + sum(bb.value) FROM aa, bb`,
expr: &influxql.VarRef{Val: "aa.value"},
sub: `SELECT aa.value FROM aa`,
sub: `SELECT "aa.value" FROM aa`,
},
// 2. Simple merge
{
stmt: `SELECT sum(aa.value) + sum(bb.value) FROM aa, bb`,
expr: &influxql.VarRef{Val: "bb.value"},
sub: `SELECT bb.value FROM bb`,
sub: `SELECT "bb.value" FROM bb`,
},
// 3. Join with condition
{
stmt: `SELECT sum(aa.value) + sum(bb.value) FROM aa, bb WHERE aa.host = 'servera' AND bb.host = 'serverb'`,
expr: &influxql.VarRef{Val: "bb.value"},
sub: `SELECT bb.value FROM bb WHERE bb.host = 'serverb'`,
sub: `SELECT "bb.value" FROM bb WHERE "bb.host" = 'serverb'`,
},
// 4. Join with complex condition
{
stmt: `SELECT sum(aa.value) + sum(bb.value) FROM aa, bb WHERE aa.host = 'servera' AND (bb.host = 'serverb' OR bb.host = 'serverc') AND 1 = 2`,
expr: &influxql.VarRef{Val: "bb.value"},
sub: `SELECT bb.value FROM bb WHERE (bb.host = 'serverb' OR bb.host = 'serverc') AND 1.000 = 2.000`,
sub: `SELECT "bb.value" FROM bb WHERE ("bb.host" = 'serverb' OR "bb.host" = 'serverc') AND 1.000 = 2.000`,
},
// 5. 4 with different condition order
{
stmt: `SELECT sum(aa.value) + sum(bb.value) FROM aa, bb WHERE ((bb.host = 'serverb' OR bb.host = 'serverc') AND aa.host = 'servera') AND 1 = 2`,
expr: &influxql.VarRef{Val: "bb.value"},
sub: `SELECT bb.value FROM bb WHERE ((bb.host = 'serverb' OR bb.host = 'serverc')) AND 1.000 = 2.000`,
sub: `SELECT "bb.value" FROM bb WHERE (("bb.host" = 'serverb' OR "bb.host" = 'serverc')) AND 1.000 = 2.000`,
},
}

View File

@ -2217,6 +2217,11 @@ func QuoteIdent(segments ...string) string {
// IdentNeedsQuotes returns true if the ident string given would require quotes.
func IdentNeedsQuotes(ident string) bool {
// check if this identifier is a keyword
tok := Lookup(ident)
if tok != IDENT {
return true
}
for i, r := range ident {
if i == 0 && !isIdentFirstChar(r) {
return true

View File

@ -1664,6 +1664,8 @@ func TestQuoteIdent(t *testing.T) {
s string
}{
{[]string{``}, ``},
{[]string{`select`}, `"select"`},
{[]string{`in-bytes`}, `"in-bytes"`},
{[]string{`foo`, `bar`}, `"foo".bar`},
{[]string{`foo`, ``, `bar`}, `"foo"..bar`},
{[]string{`foo bar`, `baz`}, `"foo bar".baz`},