diff --git a/exp/bitwise_test.go b/exp/bitwise_test.go index 419728ff..7cf2cc83 100644 --- a/exp/bitwise_test.go +++ b/exp/bitwise_test.go @@ -32,12 +32,12 @@ func (bes *bitwiseExpressionSuite) TestAs() { func (bes *bitwiseExpressionSuite) TestAsc() { be := exp.NewBitwiseExpression(exp.BitwiseAndOp, exp.NewIdentifierExpression("", "", "col"), 1) - bes.Equal(exp.NewOrderedExpression(be, exp.AscDir, exp.NoNullsSortType), be.Asc()) + bes.Equal(exp.NewOrderedExpression(be, exp.AscDir, exp.NoNullsSortType, exp.NoCollation), be.Asc()) } func (bes *bitwiseExpressionSuite) TestDesc() { be := exp.NewBitwiseExpression(exp.BitwiseOrOp, exp.NewIdentifierExpression("", "", "col"), 1) - bes.Equal(exp.NewOrderedExpression(be, exp.DescSortDir, exp.NoNullsSortType), be.Desc()) + bes.Equal(exp.NewOrderedExpression(be, exp.DescSortDir, exp.NoNullsSortType, exp.NoCollation), be.Desc()) } func (bes *bitwiseExpressionSuite) TestAllOthers() { diff --git a/exp/case_test.go b/exp/case_test.go index 86c6add4..7093cefa 100644 --- a/exp/case_test.go +++ b/exp/case_test.go @@ -59,12 +59,12 @@ func (ces *caseExpressionSuite) TestElse() { func (ces *caseExpressionSuite) TestAsc() { ce := exp.NewCaseExpression() - ces.Equal(exp.NewOrderedExpression(ce, exp.AscDir, exp.NoNullsSortType), ce.Asc()) + ces.Equal(exp.NewOrderedExpression(ce, exp.AscDir, exp.NoNullsSortType, exp.NoCollation), ce.Asc()) } func (ces *caseExpressionSuite) TestDesc() { ce := exp.NewCaseExpression() - ces.Equal(exp.NewOrderedExpression(ce, exp.DescSortDir, exp.NoNullsSortType), ce.Desc()) + ces.Equal(exp.NewOrderedExpression(ce, exp.DescSortDir, exp.NoNullsSortType, exp.NoCollation), ce.Desc()) } type caseWhenSuite struct { diff --git a/exp/cast_test.go b/exp/cast_test.go index 14b5dfdf..6391cf00 100644 --- a/exp/cast_test.go +++ b/exp/cast_test.go @@ -50,8 +50,8 @@ func (ces *castExpressionSuite) TestAllOthers() { {Ex: ce.Gte(1), Expected: exp.NewBooleanExpression(exp.GteOp, ce, 1)}, {Ex: ce.Lt(1), Expected: exp.NewBooleanExpression(exp.LtOp, ce, 1)}, {Ex: ce.Lte(1), Expected: exp.NewBooleanExpression(exp.LteOp, ce, 1)}, - {Ex: ce.Asc(), Expected: exp.NewOrderedExpression(ce, exp.AscDir, exp.NoNullsSortType)}, - {Ex: ce.Desc(), Expected: exp.NewOrderedExpression(ce, exp.DescSortDir, exp.NoNullsSortType)}, + {Ex: ce.Asc(), Expected: exp.NewOrderedExpression(ce, exp.AscDir, exp.NoNullsSortType, exp.NoCollation)}, + {Ex: ce.Desc(), Expected: exp.NewOrderedExpression(ce, exp.DescSortDir, exp.NoNullsSortType, exp.NoCollation)}, {Ex: ce.Between(rv), Expected: exp.NewRangeExpression(exp.BetweenOp, ce, rv)}, {Ex: ce.NotBetween(rv), Expected: exp.NewRangeExpression(exp.NotBetweenOp, ce, rv)}, {Ex: ce.Like(pattern), Expected: exp.NewBooleanExpression(exp.LikeOp, ce, pattern)}, diff --git a/exp/exp.go b/exp/exp.go index 240a96a6..662f486f 100644 --- a/exp/exp.go +++ b/exp/exp.go @@ -395,6 +395,8 @@ type ( Args() []interface{} } + Collation string + NullSortType int SortDirection int // An expression for specifying sort order and options @@ -410,6 +412,10 @@ type ( NullsFirst() OrderedExpression // Returns a new OrderedExpression with NullSortType set to NULLS_LAST NullsLast() OrderedExpression + // Returns the OrderedExpression with Collation set to Collation + Collate(Collation) OrderedExpression + // If the expression has a Collation + HasCollation() (bool, Collation) } RangeOperation int @@ -547,6 +553,7 @@ const ( AscDir SortDirection = iota // DESC DescSortDir + NoCollation = "" // BETWEEN BetweenOp RangeOperation = iota diff --git a/exp/func_test.go b/exp/func_test.go index 54c76073..a74066c2 100644 --- a/exp/func_test.go +++ b/exp/func_test.go @@ -71,8 +71,8 @@ func (sfes *sqlFunctionExpressionSuite) TestAllOthers() { {Ex: fn.IsNotTrue(), Expected: exp.NewBooleanExpression(exp.IsNotOp, fn, true)}, {Ex: fn.IsFalse(), Expected: exp.NewBooleanExpression(exp.IsOp, fn, false)}, {Ex: fn.IsNotFalse(), Expected: exp.NewBooleanExpression(exp.IsNotOp, fn, false)}, - {Ex: fn.Desc(), Expected: exp.NewOrderedExpression(fn, exp.DescSortDir, exp.NoNullsSortType)}, - {Ex: fn.Asc(), Expected: exp.NewOrderedExpression(fn, exp.AscDir, exp.NoNullsSortType)}, + {Ex: fn.Desc(), Expected: exp.NewOrderedExpression(fn, exp.DescSortDir, exp.NoNullsSortType, exp.NoCollation)}, + {Ex: fn.Asc(), Expected: exp.NewOrderedExpression(fn, exp.AscDir, exp.NoNullsSortType, exp.NoCollation)}, } for _, tc := range testCases { diff --git a/exp/ident_test.go b/exp/ident_test.go index d74d83ed..c3eb57e4 100644 --- a/exp/ident_test.go +++ b/exp/ident_test.go @@ -210,8 +210,8 @@ func (ies *identifierExpressionSuite) TestAllOthers() { {Ex: ident.Gte(1), Expected: exp.NewBooleanExpression(exp.GteOp, ident, 1)}, {Ex: ident.Lt(1), Expected: exp.NewBooleanExpression(exp.LtOp, ident, 1)}, {Ex: ident.Lte(1), Expected: exp.NewBooleanExpression(exp.LteOp, ident, 1)}, - {Ex: ident.Asc(), Expected: exp.NewOrderedExpression(ident, exp.AscDir, exp.NoNullsSortType)}, - {Ex: ident.Desc(), Expected: exp.NewOrderedExpression(ident, exp.DescSortDir, exp.NoNullsSortType)}, + {Ex: ident.Asc(), Expected: exp.NewOrderedExpression(ident, exp.AscDir, exp.NoNullsSortType, exp.NoCollation)}, + {Ex: ident.Desc(), Expected: exp.NewOrderedExpression(ident, exp.DescSortDir, exp.NoNullsSortType, exp.NoCollation)}, {Ex: ident.Between(rv), Expected: exp.NewRangeExpression(exp.BetweenOp, ident, rv)}, {Ex: ident.NotBetween(rv), Expected: exp.NewRangeExpression(exp.NotBetweenOp, ident, rv)}, {Ex: ident.Like(pattern), Expected: exp.NewBooleanExpression(exp.LikeOp, ident, pattern)}, diff --git a/exp/literal_test.go b/exp/literal_test.go index 42f00a8c..00f93e0e 100644 --- a/exp/literal_test.go +++ b/exp/literal_test.go @@ -51,8 +51,8 @@ func (les *literalExpressionSuite) TestAllOthers() { {Ex: le.Gte(1), Expected: exp.NewBooleanExpression(exp.GteOp, le, 1)}, {Ex: le.Lt(1), Expected: exp.NewBooleanExpression(exp.LtOp, le, 1)}, {Ex: le.Lte(1), Expected: exp.NewBooleanExpression(exp.LteOp, le, 1)}, - {Ex: le.Asc(), Expected: exp.NewOrderedExpression(le, exp.AscDir, exp.NoNullsSortType)}, - {Ex: le.Desc(), Expected: exp.NewOrderedExpression(le, exp.DescSortDir, exp.NoNullsSortType)}, + {Ex: le.Asc(), Expected: exp.NewOrderedExpression(le, exp.AscDir, exp.NoNullsSortType, exp.NoCollation)}, + {Ex: le.Desc(), Expected: exp.NewOrderedExpression(le, exp.DescSortDir, exp.NoNullsSortType, exp.NoCollation)}, {Ex: le.Between(rv), Expected: exp.NewRangeExpression(exp.BetweenOp, le, rv)}, {Ex: le.NotBetween(rv), Expected: exp.NewRangeExpression(exp.NotBetweenOp, le, rv)}, {Ex: le.Like(pattern), Expected: exp.NewBooleanExpression(exp.LikeOp, le, pattern)}, diff --git a/exp/order.go b/exp/order.go index 640f1f66..205cf5df 100644 --- a/exp/order.go +++ b/exp/order.go @@ -5,26 +5,27 @@ type ( sortExpression Expression direction SortDirection nullSortType NullSortType + collation Collation } ) // used internally to create a new SORT_ASC OrderedExpression func asc(exp Expression) OrderedExpression { - return NewOrderedExpression(exp, AscDir, NoNullsSortType) + return NewOrderedExpression(exp, AscDir, NoNullsSortType, NoCollation) } // used internally to create a new SORT_DESC OrderedExpression func desc(exp Expression) OrderedExpression { - return NewOrderedExpression(exp, DescSortDir, NoNullsSortType) + return NewOrderedExpression(exp, DescSortDir, NoNullsSortType, NoCollation) } // used internally to create a new SORT_ASC OrderedExpression -func NewOrderedExpression(exp Expression, direction SortDirection, sortType NullSortType) OrderedExpression { - return orderedExpression{sortExpression: exp, direction: direction, nullSortType: sortType} +func NewOrderedExpression(exp Expression, direction SortDirection, sortType NullSortType, collation Collation) OrderedExpression { + return orderedExpression{sortExpression: exp, direction: direction, nullSortType: sortType, collation: collation} } func (oe orderedExpression) Clone() Expression { - return NewOrderedExpression(oe.sortExpression, oe.direction, oe.nullSortType) + return NewOrderedExpression(oe.sortExpression, oe.direction, oe.nullSortType, oe.collation) } func (oe orderedExpression) Expression() Expression { @@ -44,9 +45,17 @@ func (oe orderedExpression) NullSortType() NullSortType { } func (oe orderedExpression) NullsFirst() OrderedExpression { - return NewOrderedExpression(oe.sortExpression, oe.direction, NullsFirstSortType) + return NewOrderedExpression(oe.sortExpression, oe.direction, NullsFirstSortType, oe.collation) } func (oe orderedExpression) NullsLast() OrderedExpression { - return NewOrderedExpression(oe.sortExpression, oe.direction, NullsLastSortType) + return NewOrderedExpression(oe.sortExpression, oe.direction, NullsLastSortType, oe.collation) +} + +func (oe orderedExpression) HasCollation() (bool, Collation) { + return oe.collation != NoCollation, oe.collation +} + +func (oe orderedExpression) Collate(c Collation) OrderedExpression { + return NewOrderedExpression(oe.sortExpression, oe.direction, oe.nullSortType, c) } diff --git a/exp/window_func_test.go b/exp/window_func_test.go index 0ab6efc9..26f8c88d 100644 --- a/exp/window_func_test.go +++ b/exp/window_func_test.go @@ -97,8 +97,8 @@ func (swfet *sqlWindowFunctionExpressionTest) TestAllOthers() { {Ex: wf.IsNotTrue(), Expected: exp.NewBooleanExpression(exp.IsNotOp, wf, true)}, {Ex: wf.IsFalse(), Expected: exp.NewBooleanExpression(exp.IsOp, wf, false)}, {Ex: wf.IsNotFalse(), Expected: exp.NewBooleanExpression(exp.IsNotOp, wf, false)}, - {Ex: wf.Desc(), Expected: exp.NewOrderedExpression(wf, exp.DescSortDir, exp.NoNullsSortType)}, - {Ex: wf.Asc(), Expected: exp.NewOrderedExpression(wf, exp.AscDir, exp.NoNullsSortType)}, + {Ex: wf.Desc(), Expected: exp.NewOrderedExpression(wf, exp.DescSortDir, exp.NoNullsSortType, exp.NoCollation)}, + {Ex: wf.Asc(), Expected: exp.NewOrderedExpression(wf, exp.AscDir, exp.NoNullsSortType, exp.NoCollation)}, } for _, tc := range testCases { diff --git a/expressions_example_test.go b/expressions_example_test.go index 222701ee..b8540995 100644 --- a/expressions_example_test.go +++ b/expressions_example_test.go @@ -186,6 +186,9 @@ func ExampleC_ordering() { sql, args, _ = goqu.From("test").Order(goqu.C("a").Desc().NullsLast()).ToSQL() fmt.Println(sql, args) + sql, args, _ = goqu.From("test").Order(goqu.C("a").Asc().NullsFirst().Collate("en_GB")).ToSQL() + fmt.Println(sql, args) + // Output: // SELECT * FROM "test" ORDER BY "a" ASC [] // SELECT * FROM "test" ORDER BY "a" ASC NULLS FIRST [] @@ -193,6 +196,7 @@ func ExampleC_ordering() { // SELECT * FROM "test" ORDER BY "a" DESC [] // SELECT * FROM "test" ORDER BY "a" DESC NULLS FIRST [] // SELECT * FROM "test" ORDER BY "a" DESC NULLS LAST [] + // SELECT * FROM "test" ORDER BY "a" COLLATE en_GB ASC NULLS FIRST [] } func ExampleC_cast() { diff --git a/sqlgen/common_sql_generator_test.go b/sqlgen/common_sql_generator_test.go index 26f12b49..bf0c4419 100644 --- a/sqlgen/common_sql_generator_test.go +++ b/sqlgen/common_sql_generator_test.go @@ -210,6 +210,7 @@ func (csgs *commonSQLGeneratorSuite) TestOrderSQL() { opts.OrderByFragment = []byte(" order by ") opts.AscFragment = []byte(" asc") opts.DescFragment = []byte(" desc") + opts.CollateFragment = []byte(" collate") opts.NullsFirstFragment = []byte(" nulls first") opts.NullsLastFragment = []byte(" nulls last") csgCustom := sqlgen.NewCommonSQLGenerator("test", opts) @@ -223,6 +224,14 @@ func (csgs *commonSQLGeneratorSuite) TestOrderSQL() { odnf := ident.Desc().NullsFirst() odnl := ident.Desc().NullsLast() + oac := ident.Asc().Collate("en_GB") + oanfc := ident.Asc().NullsFirst().Collate("en_GB") + oanlc := ident.Asc().NullsLast().Collate("en_GB") + + odc := ident.Desc().Collate("en_GB") + odnfc := ident.Desc().NullsFirst().Collate("en_GB") + odnlc := ident.Desc().NullsLast().Collate("en_GB") + csgs.assertCases( commonSQLTestCase{gen: orderGen(csg), sql: ``}, commonSQLTestCase{gen: orderGen(csg), sql: ``, isPrepared: true, args: emptyArgs}, @@ -245,8 +254,26 @@ func (csgs *commonSQLGeneratorSuite) TestOrderSQL() { commonSQLTestCase{gen: orderGen(csg, odnl), sql: ` ORDER BY "a" DESC NULLS LAST`}, commonSQLTestCase{gen: orderGen(csg, odnl), sql: ` ORDER BY "a" DESC NULLS LAST`, isPrepared: true, args: emptyArgs}, - commonSQLTestCase{gen: orderGen(csg, oa, od), sql: ` ORDER BY "a" ASC, "a" DESC`}, - commonSQLTestCase{gen: orderGen(csg, oa, od), sql: ` ORDER BY "a" ASC, "a" DESC`, isPrepared: true, args: emptyArgs}, + commonSQLTestCase{gen: orderGen(csg, oac), sql: ` ORDER BY "a" COLLATE en_GB ASC`}, + commonSQLTestCase{gen: orderGen(csg, oac), sql: ` ORDER BY "a" COLLATE en_GB ASC`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csg, oanfc), sql: ` ORDER BY "a" COLLATE en_GB ASC NULLS FIRST`}, + commonSQLTestCase{gen: orderGen(csg, oanfc), sql: ` ORDER BY "a" COLLATE en_GB ASC NULLS FIRST`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csg, oanlc), sql: ` ORDER BY "a" COLLATE en_GB ASC NULLS LAST`}, + commonSQLTestCase{gen: orderGen(csg, oanlc), sql: ` ORDER BY "a" COLLATE en_GB ASC NULLS LAST`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csg, odc), sql: ` ORDER BY "a" COLLATE en_GB DESC`}, + commonSQLTestCase{gen: orderGen(csg, odc), sql: ` ORDER BY "a" COLLATE en_GB DESC`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csg, odnfc), sql: ` ORDER BY "a" COLLATE en_GB DESC NULLS FIRST`}, + commonSQLTestCase{gen: orderGen(csg, odnfc), sql: ` ORDER BY "a" COLLATE en_GB DESC NULLS FIRST`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csg, odnlc), sql: ` ORDER BY "a" COLLATE en_GB DESC NULLS LAST`}, + commonSQLTestCase{gen: orderGen(csg, odnlc), sql: ` ORDER BY "a" COLLATE en_GB DESC NULLS LAST`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csg, oa, od, oanfc), sql: ` ORDER BY "a" ASC, "a" DESC, "a" COLLATE en_GB ASC NULLS FIRST`}, + commonSQLTestCase{gen: orderGen(csg, oa, od, oanfc), sql: ` ORDER BY "a" ASC, "a" DESC, "a" COLLATE en_GB ASC NULLS FIRST`, isPrepared: true, args: emptyArgs}, commonSQLTestCase{gen: orderGen(csgCustom), sql: ``}, commonSQLTestCase{gen: orderGen(csgCustom), sql: ``, isPrepared: true, args: emptyArgs}, @@ -269,8 +296,26 @@ func (csgs *commonSQLGeneratorSuite) TestOrderSQL() { commonSQLTestCase{gen: orderGen(csgCustom, odnl), sql: ` order by "a" desc nulls last`}, commonSQLTestCase{gen: orderGen(csgCustom, odnl), sql: ` order by "a" desc nulls last`, isPrepared: true, args: emptyArgs}, - commonSQLTestCase{gen: orderGen(csgCustom, oa, od), sql: ` order by "a" asc, "a" desc`}, - commonSQLTestCase{gen: orderGen(csgCustom, oa, od), sql: ` order by "a" asc, "a" desc`, isPrepared: true, args: emptyArgs}, + commonSQLTestCase{gen: orderGen(csgCustom, oac), sql: ` order by "a" collate en_GB asc`}, + commonSQLTestCase{gen: orderGen(csgCustom, oac), sql: ` order by "a" collate en_GB asc`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csgCustom, oanfc), sql: ` order by "a" collate en_GB asc nulls first`}, + commonSQLTestCase{gen: orderGen(csgCustom, oanfc), sql: ` order by "a" collate en_GB asc nulls first`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csgCustom, oanlc), sql: ` order by "a" collate en_GB asc nulls last`}, + commonSQLTestCase{gen: orderGen(csgCustom, oanlc), sql: ` order by "a" collate en_GB asc nulls last`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csgCustom, odc), sql: ` order by "a" collate en_GB desc`}, + commonSQLTestCase{gen: orderGen(csgCustom, odc), sql: ` order by "a" collate en_GB desc`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csgCustom, odnfc), sql: ` order by "a" collate en_GB desc nulls first`}, + commonSQLTestCase{gen: orderGen(csgCustom, odnfc), sql: ` order by "a" collate en_GB desc nulls first`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csgCustom, odnlc), sql: ` order by "a" collate en_GB desc nulls last`}, + commonSQLTestCase{gen: orderGen(csgCustom, odnlc), sql: ` order by "a" collate en_GB desc nulls last`, isPrepared: true, args: emptyArgs}, + + commonSQLTestCase{gen: orderGen(csgCustom, oa, od, oanfc), sql: ` order by "a" asc, "a" desc, "a" collate en_GB asc nulls first`}, + commonSQLTestCase{gen: orderGen(csgCustom, oa, od, oanfc), sql: ` order by "a" asc, "a" desc, "a" collate en_GB asc nulls first`, isPrepared: true, args: emptyArgs}, ) } diff --git a/sqlgen/expression_sql_generator.go b/sqlgen/expression_sql_generator.go index 94fc10f9..50ee0736 100644 --- a/sqlgen/expression_sql_generator.go +++ b/sqlgen/expression_sql_generator.go @@ -2,6 +2,7 @@ package sqlgen import ( "database/sql/driver" + "fmt" "reflect" "strconv" "time" @@ -471,6 +472,10 @@ func (esg *expressionSQLGenerator) rangeExpressionSQL(b sb.SQLBuilder, operator // Generates SQL for an OrderedExpression (e.g. I("a").Asc() -> "a" ASC) func (esg *expressionSQLGenerator) orderedExpressionSQL(b sb.SQLBuilder, order exp.OrderedExpression) { esg.Generate(b, order.SortExpression()) + hasCollation, collation := order.HasCollation() + if hasCollation { + b.Write([]byte(fmt.Sprintf("%s %s", esg.dialectOptions.CollateFragment, collation))) + } if order.IsAsc() { b.Write(esg.dialectOptions.AscFragment) } else { diff --git a/sqlgen/expression_sql_generator_test.go b/sqlgen/expression_sql_generator_test.go index ed75e12f..5cd3ce29 100644 --- a/sqlgen/expression_sql_generator_test.go +++ b/sqlgen/expression_sql_generator_test.go @@ -725,6 +725,14 @@ func (esgs *expressionSQLGeneratorSuite) TestGenerate_OrderedExpression() { descNf := exp.NewIdentifierExpression("", "", "a").Desc().NullsFirst() descNl := exp.NewIdentifierExpression("", "", "a").Desc().NullsLast() + ascC := exp.NewIdentifierExpression("", "", "a").Asc().Collate("en_GB") + ascNfC := exp.NewIdentifierExpression("", "", "a").Asc().NullsFirst().Collate("en_GB") + ascNlC := exp.NewIdentifierExpression("", "", "a").Asc().NullsLast().Collate("en_GB") + + descC := exp.NewIdentifierExpression("", "", "a").Desc().Collate("en_GB") + descNfC := exp.NewIdentifierExpression("", "", "a").Desc().NullsFirst().Collate("en_GB") + descNlC := exp.NewIdentifierExpression("", "", "a").Desc().NullsLast().Collate("en_GB") + esgs.assertCases( sqlgen.NewExpressionSQLGenerator("test", sqlgen.DefaultDialectOptions()), expressionTestCase{val: asc, sql: `"a" ASC`}, @@ -744,6 +752,24 @@ func (esgs *expressionSQLGeneratorSuite) TestGenerate_OrderedExpression() { expressionTestCase{val: descNl, sql: `"a" DESC NULLS LAST`}, expressionTestCase{val: descNl, sql: `"a" DESC NULLS LAST`, isPrepared: true}, + + expressionTestCase{val: ascC, sql: `"a" COLLATE en_GB ASC`}, + expressionTestCase{val: ascC, sql: `"a" COLLATE en_GB ASC`, isPrepared: true}, + + expressionTestCase{val: ascNfC, sql: `"a" COLLATE en_GB ASC NULLS FIRST`}, + expressionTestCase{val: ascNfC, sql: `"a" COLLATE en_GB ASC NULLS FIRST`, isPrepared: true}, + + expressionTestCase{val: ascNlC, sql: `"a" COLLATE en_GB ASC NULLS LAST`}, + expressionTestCase{val: ascNlC, sql: `"a" COLLATE en_GB ASC NULLS LAST`, isPrepared: true}, + + expressionTestCase{val: descC, sql: `"a" COLLATE en_GB DESC`}, + expressionTestCase{val: descC, sql: `"a" COLLATE en_GB DESC`, isPrepared: true}, + + expressionTestCase{val: descNfC, sql: `"a" COLLATE en_GB DESC NULLS FIRST`}, + expressionTestCase{val: descNfC, sql: `"a" COLLATE en_GB DESC NULLS FIRST`, isPrepared: true}, + + expressionTestCase{val: descNlC, sql: `"a" COLLATE en_GB DESC NULLS LAST`}, + expressionTestCase{val: descNlC, sql: `"a" COLLATE en_GB DESC NULLS LAST`, isPrepared: true}, ) } diff --git a/sqlgen/sql_dialect_options.go b/sqlgen/sql_dialect_options.go index 3d9a981b..3e8b7fe5 100644 --- a/sqlgen/sql_dialect_options.go +++ b/sqlgen/sql_dialect_options.go @@ -147,6 +147,8 @@ type ( NullsFirstFragment []byte // The NULLS LAST fragment when specifying column order (DEFAULT=[]byte(" NULLS LAST")) NullsLastFragment []byte + // The COLLATE fragment when specifying collation (DEFAULT=[]byte(" COLLATE")) + CollateFragment []byte // The AND keyword used when joining ExpressionLists (DEFAULT=[]byte(" AND ")) AndFragment []byte // The OR keyword used when joining ExpressionLists (DEFAULT=[]byte(" OR ")) @@ -469,6 +471,7 @@ func DefaultDialectOptions() *SQLDialectOptions { AsFragment: []byte(" AS "), AscFragment: []byte(" ASC"), DescFragment: []byte(" DESC"), + CollateFragment: []byte(" COLLATE"), NullsFirstFragment: []byte(" NULLS FIRST"), NullsLastFragment: []byte(" NULLS LAST"), AndFragment: []byte(" AND "),