Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion generator/postgres/postgres_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func GenerateDB(db *sql.DB, schema, destDir string, templates ...template.Templa

err = template.ProcessSchema(destDir, schemaMetadata, generatorTemplate)
if err != nil {
return fmt.Errorf("failed to generate schema %s: %d", schemaMetadata.Name, err)
return fmt.Errorf("failed to generate schema %s: %w", schemaMetadata.Name, err)
}

return nil
Expand Down
3 changes: 2 additions & 1 deletion internal/jet/sql_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ func (s *SQLBuilder) WriteString(str string) {

// WriteJsonObjKey serializes json object key
func (s *SQLBuilder) WriteJsonObjKey(key string) {
s.WriteString(fmt.Sprintf(`'%s', `, key))
s.WriteString(stringQuote(key))
s.WriteString(", ")
}

// WriteIdentifier adds identifier to output SQL
Expand Down
8 changes: 8 additions & 0 deletions internal/jet/sql_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ func TestArgToString(t *testing.T) {
}()
}

func TestWriteJsonObjKeyEscapesStringLiteral(t *testing.T) {
s := &SQLBuilder{Dialect: defaultDialect}

s.WriteJsonObjKey("author's name")

require.Equal(t, "'author''s name', ", s.Buff.String())
}

func TestFallTrough(t *testing.T) {
require.Equal(t, FallTrough([]SerializeOption{ShortName}), []SerializeOption{ShortName})
require.Equal(t, FallTrough([]SerializeOption{SkipNewLine}), []SerializeOption(nil))
Expand Down
12 changes: 5 additions & 7 deletions qrm/qrm.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,12 @@ func queryJson(ctx context.Context, db Queryable, query string, args []interface
return 1, err
}

if jsonData == nil {
return 1, nil
}

err = GlobalConfig.JsonUnmarshalFunc(jsonData, &destPtr)
if jsonData != nil {
err = GlobalConfig.JsonUnmarshalFunc(jsonData, &destPtr)

if err != nil {
return 1, fmt.Errorf("jet: invalid json, %w", err)
if err != nil {
return 1, fmt.Errorf("jet: invalid json, %w", err)
}
}

if rows.Next() {
Expand Down
2 changes: 1 addition & 1 deletion stmtcache/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (t *Tx) QueryContext(ctx context.Context, query string, args ...interface{}
return nil, err
}

return prepStmt.Query(args...)
return prepStmt.QueryContext(ctx, args...)
}

// Prepare delegates call to PrepareContext using context.Background as a parameter.
Expand Down
44 changes: 44 additions & 0 deletions tests/mysql/select_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,3 +505,47 @@ func TestSelectJson_ProjectionNotAliased(t *testing.T) {
}, "jet: expression need to be aliased when used as SELECT JSON projection.")
})
}

func TestSelectJsonObject_EscapesJsonKeys(t *testing.T) {
stmt := SELECT_JSON_OBJ(
String("value").AS("author"),
String("value").AS("author's name"),
String("value").AS("author''s name"),
String("value").AS("author \"name\""),
String("value").AS(`C:\tmp\file`),
String("value").AS("hello\nworld"),
String("value").AS("a'b\\\\c\\nd\\r\\x00e\\x1af"),
String("value").AS("žika 😀"),
)

testutils.AssertDebugStatementSql(t, stmt, `
SELECT JSON_OBJECT(
'author', 'value',
'author''s name', 'value',
'author''''s name', 'value',
'author "name"', 'value',
'C:\tmp\file', 'value',
'hello
world', 'value',
'a''b\\c\nd\r\x00e\x1af', 'value',
'žika 😀', 'value'
) AS "json";
`)

var dest map[string]any

err := stmt.QueryContext(ctx, db, &dest)
require.NoError(t, err)
testutils.AssertJSON(t, dest, `
{
"C:\tmpfile": "value",
"a'b\\c\nd\rx00ex1af": "value",
"author": "value",
"author \"name\"": "value",
"author''s name": "value",
"author's name": "value",
"hello\nworld": "value",
"žika 😀": "value"
}
`)
}
52 changes: 52 additions & 0 deletions tests/postgres/select_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -914,3 +914,55 @@ func TestSelectJson_InvalidJson(t *testing.T) {
err := stmt.QueryContext(ctx, db, &dest)
require.ErrorContains(t, err, "invalid json")
}

func TestSelectJsonObject_EscapesJsonKeys(t *testing.T) {
stmt := SELECT_JSON_OBJ(
String("value").AS("author"),
String("value").AS("author's name"),
String("value").AS("author''s name"),
String("value").AS(`C:\tmp\file`),
String("value").AS("hello\nworld"),
String("value").AS("a'b\\\\c\\nd\\r\\x00e\\x1af"),
String("value").AS("žika 😀"),
)

testutils.AssertDebugStatementSql(t, stmt, `
SELECT row_to_json(records) AS "json"
FROM (
SELECT 'value'::text AS "author",
'value'::text AS "author's name",
'value'::text AS "author''s name",
'value'::text AS "C:\tmp\file",
'value'::text AS "hello
world",
'value'::text AS "a'b\\c\nd\r\x00e\x1af",
'value'::text AS "žika 😀"
) AS records;
`)

var dest map[string]any

err := stmt.QueryContext(ctx, db, &dest)
require.NoError(t, err)
testutils.AssertJSON(t, dest, `
{
"C:\\tmp\\file": "value",
"a'b\\\\c\\nd\\r\\x00e\\x1af": "value",
"author": "value",
"author''s name": "value",
"author's name": "value",
"hello\nworld": "value",
"žika 😀": "value"
}
`)
}

func TestSelectJsonObject_NullMoreThanOneRow(t *testing.T) {
var dest map[string]any

_, err := qrm.QueryJsonObj(ctx, db, `
SELECT NULL::json AS "json"
UNION ALL
SELECT NULL::json AS "json"`, nil, &dest)
require.ErrorContains(t, err, "jet: query returned more then one row")
}
Loading