Skip to content

Commit 7b16e43

Browse files
committed
Add support for SELECT_JSON statements.
1 parent 7047de4 commit 7b16e43

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2732
-307
lines changed

.circleci/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
build_and_tests:
99
docker:
1010
# specify the version
11-
- image: cimg/go:1.22.8
11+
- image: cimg/go:1.23.6
1212

1313
# Please keep the version in sync with test/docker-compose.yaml
1414
- image: cimg/postgres:14.10
@@ -29,7 +29,7 @@ jobs:
2929
MYSQL_TCP_PORT: 50902
3030

3131
# Please keep the version in sync with test/docker-compose.yaml
32-
- image: circleci/mariadb:10.3
32+
- image: circleci/mariadb:11.7
3333
command: [ '--default-authentication-plugin=mysql_native_password', '--port=50903' ]
3434
environment:
3535
MYSQL_ROOT_PASSWORD: jet

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,5 +579,5 @@ To run the tests, additional dependencies are required:
579579

580580
## License
581581

582-
Copyright 2019-2024 Goran Bjelanovic
582+
Copyright 2019-2025 Goran Bjelanovic
583583
Licensed under the Apache License, Version 2.0.

cmd/jet/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
package main
22

3-
const version = "v2.11.1"
3+
const version = "v2.12.0"

internal/3rdparty/snaker/snaker.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,23 @@ func snakeToCamel(s string, upperCase bool) string {
4040

4141
if upperCase || i > 0 {
4242
result += camelizeWord(word, len(words) > 1)
43-
} else {
44-
result += word
43+
} else { // lowerCase and i == 0
44+
result += toLowerFirstLetter(word)
4545
}
4646
}
4747

4848
return result
4949
}
5050

51+
func toLowerFirstLetter(s string) string {
52+
if s == "" {
53+
return s
54+
}
55+
runes := []rune(s)
56+
runes[0] = unicode.ToLower(runes[0])
57+
return string(runes)
58+
}
59+
5160
func camelizeWord(word string, force bool) string {
5261
runes := []rune(word)
5362

internal/3rdparty/snaker/snaker_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
func TestSnakeToCamel(t *testing.T) {
99
require.Equal(t, SnakeToCamel(""), "")
1010
require.Equal(t, SnakeToCamel("potato_"), "Potato")
11+
require.Equal(t, SnakeToCamel("potato_", false), "potato")
12+
require.Equal(t, SnakeToCamel("Potato_", false), "potato")
1113
require.Equal(t, SnakeToCamel("this_has_to_be_uppercased"), "ThisHasToBeUppercased")
1214
require.Equal(t, SnakeToCamel("this_is_an_id"), "ThisIsAnID")
1315
require.Equal(t, SnakeToCamel("this_is_an_identifier"), "ThisIsAnIdentifier")

internal/jet/alias.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,8 @@ func (a *alias) serializeForProjection(statement StatementType, out *SQLBuilder)
3030
out.WriteString("AS")
3131
out.WriteAlias(a.alias)
3232
}
33+
34+
func (a *alias) serializeForJsonObj(statement StatementType, out *SQLBuilder) {
35+
out.WriteJsonObjKey(a.alias)
36+
a.expression.serialize(statement, out)
37+
}

internal/jet/clause.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ func (s *ClauseSelect) Projections() ProjectionList {
5252

5353
// Serialize serializes clause into SQLBuilder
5454
func (s *ClauseSelect) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
55+
if len(s.ProjectionList) == 0 {
56+
panic("jet: SELECT clause has to have at least one projection")
57+
}
58+
5559
out.NewLine()
5660
out.WriteString("SELECT")
5761
s.OptimizerHints.Serialize(statementType, out, options...)
@@ -66,10 +70,6 @@ func (s *ClauseSelect) Serialize(statementType StatementType, out *SQLBuilder, o
6670
out.WriteByte(')')
6771
}
6872

69-
if len(s.ProjectionList) == 0 {
70-
panic("jet: SELECT clause has to have at least one projection")
71-
}
72-
7373
out.WriteProjections(statementType, s.ProjectionList)
7474
}
7575

internal/jet/column.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
package jet
44

5+
import (
6+
"github.com/go-jet/jet/v2/internal/3rdparty/snaker"
7+
)
8+
59
// Column is common column interface for all types of columns.
610
type Column interface {
711
Name() string
@@ -97,7 +101,17 @@ func (c ColumnExpressionImpl) serializeForProjection(statement StatementType, ou
97101
c.serialize(statement, out)
98102

99103
out.WriteString("AS")
100-
out.WriteAlias(c.defaultAlias())
104+
105+
if statement.IsSelectJSON() {
106+
out.WriteAlias(snaker.SnakeToCamel(c.name, false))
107+
} else {
108+
out.WriteAlias(c.defaultAlias())
109+
}
110+
}
111+
112+
func (c ColumnExpressionImpl) serializeForJsonObj(statement StatementType, out *SQLBuilder) {
113+
out.WriteJsonObjKey(snaker.SnakeToCamel(c.name, false))
114+
c.serialize(statement, out)
101115
}
102116

103117
func (c ColumnExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {

internal/jet/column_list.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ func (cl ColumnList) serializeForProjection(statement StatementType, out *SQLBui
7878
SerializeProjectionList(statement, projections, out)
7979
}
8080

81+
func (cl ColumnList) serializeForJsonObj(statement StatementType, out *SQLBuilder) {
82+
projections := ColumnListToProjectionList(cl)
83+
84+
SerializeProjectionListJsonObj(statement, projections, out)
85+
}
86+
8187
// dummy column interface implementation
8288

8389
// Name is placeholder for ColumnList to implement Column interface

internal/jet/expression.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package jet
22

33
import "fmt"
44

5-
// Expression is common interface for all expressions.
5+
// Expression is a common interface for all expressions.
66
// Can be Bool, Int, Float, String, Date, Time, Timez, Timestamp or Timestampz expressions.
77
type Expression interface {
88
Serializer
@@ -89,9 +89,16 @@ func (e *ExpressionInterfaceImpl) serializeForGroupBy(statement StatementType, o
8989
}
9090

9191
func (e *ExpressionInterfaceImpl) serializeForProjection(statement StatementType, out *SQLBuilder) {
92+
if statement.IsSelectJSON() {
93+
panic("jet: expression need to be aliased when used as SELECT JSON projection.")
94+
}
9295
e.Parent.serialize(statement, out, NoWrap)
9396
}
9497

98+
func (e *ExpressionInterfaceImpl) serializeForJsonObj(statement StatementType, out *SQLBuilder) {
99+
panic("jet: expression need to be aliased when used as SELECT JSON projection.")
100+
}
101+
95102
func (e *ExpressionInterfaceImpl) serializeForOrderBy(statement StatementType, out *SQLBuilder) {
96103
e.Parent.serialize(statement, out, NoWrap)
97104
}

0 commit comments

Comments
 (0)