diff --git a/HISTORY.md b/HISTORY.md index 55329f44..3168298f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,7 @@ +## v8.2.1 + +* [FIX] Return an error when an empty identifier is encountered [#115](https://github.com/doug-martin/goqu/issues/118) + ## v8.2.0 * [FIX] Fix reflection errors related to nil pointers and unexported fields [#118](https://github.com/doug-martin/goqu/issues/118) diff --git a/exp/exp.go b/exp/exp.go index 3bd69160..e150cd22 100644 --- a/exp/exp.go +++ b/exp/exp.go @@ -262,6 +262,9 @@ type ( // Returns a new IdentifierExpression with the column set to * // I("my_table").All() //"my_table".* All() IdentifierExpression + + // Returns true if schema table and identifier are all zero values. + IsEmpty() bool } InsertExpression interface { Expression diff --git a/exp/ident.go b/exp/ident.go index 2c4534d5..d0b9a7af 100644 --- a/exp/ident.go +++ b/exp/ident.go @@ -21,7 +21,7 @@ func ParseIdentifier(ident string) IdentifierExpression { return NewIdentifierExpression("", "", ident) } -func NewIdentifierExpression(schema, table, col string) IdentifierExpression { +func NewIdentifierExpression(schema, table string, col interface{}) IdentifierExpression { return identifier{}.Schema(schema).Table(table).Col(col) } @@ -77,6 +77,21 @@ func (i identifier) Expression() Expression { return i } // Qualifies the epression with a * literal (e.g. "table".*) func (i identifier) All() IdentifierExpression { return i.Col("*") } +func (i identifier) IsEmpty() bool { + isEmpty := i.schema == "" && i.table == "" + if isEmpty { + switch t := i.col.(type) { + case nil: + return true + case string: + return t == "" + default: + return false + } + } + return isEmpty +} + // Gets the column identifier func (i identifier) GetCol() interface{} { return i.col } diff --git a/issues_test.go b/issues_test.go index 564d9e19..11039d73 100644 --- a/issues_test.go +++ b/issues_test.go @@ -1,6 +1,7 @@ package goqu_test import ( + "strings" "sync" "testing" "time" @@ -14,6 +15,10 @@ type githubIssuesSuite struct { suite.Suite } +func (gis *githubIssuesSuite) AfterTest(suiteName, testName string) { + goqu.SetColumnRenameFunction(strings.ToLower) +} + // Test for https://github.com/doug-martin/goqu/issues/49 func (gis *githubIssuesSuite) TestIssue49() { t := gis.T() @@ -36,6 +41,20 @@ func (gis *githubIssuesSuite) TestIssue49() { assert.Equal(t, `SELECT * FROM "table"`, sql) } +// Test for https://github.com/doug-martin/goqu/issues/115 +func (gis *githubIssuesSuite) TestIssue115() { + + type TestStruct struct { + Field string + } + goqu.SetColumnRenameFunction(func(col string) string { + return "" + }) + + _, _, err := goqu.Insert("test").Rows(TestStruct{Field: "hello"}).ToSQL() + gis.EqualError(err, `goqu: a empty identifier was encountered, please specify a "schema", "table" or "column"`) +} + // Test for https://github.com/doug-martin/goqu/issues/118 func (gis *githubIssuesSuite) TestIssue118_withEmbeddedStructWithoutExportedFields() { // struct is in a custom package diff --git a/sql_dialect.go b/sql_dialect.go index 5cfee69d..fb051b99 100644 --- a/sql_dialect.go +++ b/sql_dialect.go @@ -51,6 +51,7 @@ var ( errNoSourceForTruncate = errors.New("no source found when generating truncate sql") errReturnNotSupported = errors.New("adapter does not support RETURNING clause") errNoSetValuesForUpdate = errors.New("no set values found when generating UPDATE sql") + errEmptyIdentifier = errors.New(`a empty identifier was encountered, please specify a "schema", "table" or "column"`) ) func notSupportedFragmentErr(sqlType string, f SQLFragmentType) error { @@ -898,6 +899,10 @@ func (d *sqlDialect) appendableExpressionSQL(b sb.SQLBuilder, a exp.AppendableEx // Quotes an identifier (e.g. "col", "table"."col" func (d *sqlDialect) quoteIdentifier(b sb.SQLBuilder, ident exp.IdentifierExpression) { + if ident.IsEmpty() { + b.SetError(errEmptyIdentifier) + return + } schema, table, col := ident.GetSchema(), ident.GetTable(), ident.GetCol() if schema != d.dialectOptions.EmptyString { b.WriteRunes(d.dialectOptions.QuoteRune). diff --git a/sql_dialect_test.go b/sql_dialect_test.go index 8afe4476..0df9a43f 100644 --- a/sql_dialect_test.go +++ b/sql_dialect_test.go @@ -1867,6 +1867,12 @@ func (dts *dialectTestSuite) TestLiteral_IdentifierExpression() { d := sqlDialect{dialect: "test", dialectOptions: DefaultDialectOptions()} b := sb.NewSQLBuilder(false) + d.Literal(b.Clear(), exp.NewIdentifierExpression("", "", "")) + dts.assertErrorSQL(b, `goqu: a empty identifier was encountered, please specify a "schema", "table" or "column"`) + + d.Literal(b.Clear(), exp.NewIdentifierExpression("", "", nil)) + dts.assertErrorSQL(b, `goqu: a empty identifier was encountered, please specify a "schema", "table" or "column"`) + d.Literal(b.Clear(), exp.NewIdentifierExpression("", "", "col")) dts.assertNotPreparedSQL(b, `"col"`)