Remove QueryJson statements method to avoid potential misuse.
This commit is contained in:
parent
12c96116d0
commit
950b33191e
13 changed files with 125 additions and 143 deletions
1
internal/3rdparty/snaker/snaker_test.go
vendored
1
internal/3rdparty/snaker/snaker_test.go
vendored
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
func TestSnakeToCamel(t *testing.T) {
|
func TestSnakeToCamel(t *testing.T) {
|
||||||
require.Equal(t, SnakeToCamel(""), "")
|
require.Equal(t, SnakeToCamel(""), "")
|
||||||
|
require.Equal(t, SnakeToCamel("_", false), "")
|
||||||
require.Equal(t, SnakeToCamel("potato_"), "Potato")
|
require.Equal(t, SnakeToCamel("potato_"), "Potato")
|
||||||
require.Equal(t, SnakeToCamel("potato_", false), "potato")
|
require.Equal(t, SnakeToCamel("potato_", false), "potato")
|
||||||
require.Equal(t, SnakeToCamel("Potato_", false), "potato")
|
require.Equal(t, SnakeToCamel("Potato_", false), "potato")
|
||||||
|
|
|
||||||
|
|
@ -20,31 +20,20 @@ type Statement interface {
|
||||||
// Do not use it in production, as it may lead to security risks such as SQL injection.
|
// Do not use it in production, as it may lead to security risks such as SQL injection.
|
||||||
DebugSql() (query string)
|
DebugSql() (query string)
|
||||||
|
|
||||||
// Query executes statement on the provided database connection or transaction (db),
|
// Query delegates call to QueryContext using context.Background() as parameter.
|
||||||
// storing the retrieved row results in the given destination.
|
|
||||||
// Destination must be a pointer to either a struct or a slice.
|
|
||||||
// If the destination is a pointer to a struct and the query returns no rows, Query returns qrm.ErrNoRows.
|
|
||||||
Query(db qrm.Queryable, destination interface{}) error
|
Query(db qrm.Queryable, destination interface{}) error
|
||||||
|
|
||||||
// QueryContext executes statement with a context over database connection/transaction db,
|
// QueryContext executes the statement with the provided context over a database connection or transaction (`db`),
|
||||||
// storing the retrieved row results in the given destination.
|
// and stores the retrieved row results in the given destination.
|
||||||
// Destination must be a pointer to either a struct or a slice.
|
//
|
||||||
// If the destination is a pointer to a struct and the query returns no rows, Query returns qrm.ErrNoRows.
|
// For statements of type SELECT, INSERT, UPDATE, or DELETE, the destination must be a pointer to either a struct or a slice.
|
||||||
|
// For SELECT_JSON_ARR statements, the destination must be a pointer to a slice of structs or a pointer to []map[string]any.
|
||||||
|
// For SELECT_JSON_OBJ statements, the destination must be a pointer to a struct or a pointer to map[string]any.
|
||||||
|
//
|
||||||
|
// If the destination is a pointer to a struct and the query returns no rows, QueryContext returns qrm.ErrNoRows.
|
||||||
QueryContext(ctx context.Context, db qrm.Queryable, destination interface{}) error
|
QueryContext(ctx context.Context, db qrm.Queryable, destination interface{}) error
|
||||||
|
|
||||||
// QueryJSON executes the given statement within the provided context on the database connection/transaction (db)
|
// Exec delegates call to ExecContext using context.Background() as parameter.
|
||||||
// and unmarshals the JSON result into the destination.
|
|
||||||
// If the statement is created as SELECT_JSON_ARR, the destination must be a pointer to a slice of structs or a
|
|
||||||
// pointer to []map[string]any.
|
|
||||||
// If the statement is created as SELECT_JSON_OBJ, the destination must be a pointer to a struct or a pointer to
|
|
||||||
// map[string]any.
|
|
||||||
// QueryJSON can also be used by other SQL statements that generate JSON on the server. The only requirement is
|
|
||||||
// that the query must return exactly one row with a single column; otherwise, an error is returned.
|
|
||||||
// If the destination is a pointer to a struct (or []map[string]any) and the query result set is empty, the method
|
|
||||||
// returns qrm.ErrNoRows.
|
|
||||||
QueryJSON(ctx context.Context, db qrm.Queryable, destination interface{}) error
|
|
||||||
|
|
||||||
// Exec executes statement over db connection/transaction without returning any rows.
|
|
||||||
Exec(db qrm.Executable) (sql.Result, error)
|
Exec(db qrm.Executable) (sql.Result, error)
|
||||||
|
|
||||||
// ExecContext executes statement with context over db connection/transaction without returning any rows.
|
// ExecContext executes statement with context over db connection/transaction without returning any rows.
|
||||||
|
|
@ -116,16 +105,14 @@ func (s *statementInterfaceImpl) Query(db qrm.Queryable, destination interface{}
|
||||||
|
|
||||||
func (s *statementInterfaceImpl) QueryContext(ctx context.Context, db qrm.Queryable, destination interface{}) error {
|
func (s *statementInterfaceImpl) QueryContext(ctx context.Context, db qrm.Queryable, destination interface{}) error {
|
||||||
return s.query(ctx, func(query string, args []interface{}) (int64, error) {
|
return s.query(ctx, func(query string, args []interface{}) (int64, error) {
|
||||||
return qrm.Query(ctx, db, query, args, destination)
|
switch s.statementType {
|
||||||
})
|
case SelectJsonObjStatementType:
|
||||||
}
|
|
||||||
|
|
||||||
func (s *statementInterfaceImpl) QueryJSON(ctx context.Context, db qrm.Queryable, destination interface{}) error {
|
|
||||||
return s.query(ctx, func(query string, args []interface{}) (int64, error) {
|
|
||||||
if s.statementType == SelectJsonObjStatementType {
|
|
||||||
return qrm.QueryJsonObj(ctx, db, query, args, destination)
|
return qrm.QueryJsonObj(ctx, db, query, args, destination)
|
||||||
}
|
case SelectJsonArrStatementType:
|
||||||
return qrm.QueryJsonArr(ctx, db, query, args, destination)
|
return qrm.QueryJsonArr(ctx, db, query, args, destination)
|
||||||
|
default:
|
||||||
|
return qrm.Query(ctx, db, query, args, destination)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -272,16 +272,6 @@ func AssertQueryPanicErr(t *testing.T, stmt jet.Statement, db qrm.DB, dest inter
|
||||||
_ = stmt.Query(db, dest)
|
_ = stmt.Query(db, dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssertQueryJsonPanicErr check if statement QueryJSON execution panics with error errString
|
|
||||||
func AssertQueryJsonPanicErr(t *testing.T, stmt jet.Statement, db qrm.DB, dest interface{}, errString string) {
|
|
||||||
defer func() {
|
|
||||||
r := recover()
|
|
||||||
require.Equal(t, r, errString)
|
|
||||||
}()
|
|
||||||
|
|
||||||
_ = stmt.QueryJSON(context.Background(), db, dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssertFileContent check if file content at filePath contains expectedContent text.
|
// AssertFileContent check if file content at filePath contains expectedContent text.
|
||||||
func AssertFileContent(t *testing.T, filePath string, expectedContent string) {
|
func AssertFileContent(t *testing.T, filePath string, expectedContent string) {
|
||||||
enumFileData, err := os.ReadFile(filePath) // #nosec G304
|
enumFileData, err := os.ReadFile(filePath) // #nosec G304
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ func queryJson(ctx context.Context, db Queryable, query string, args []interface
|
||||||
err = json.Unmarshal(jsonData, &destPtr)
|
err = json.Unmarshal(jsonData, &destPtr)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 1, err
|
return 1, fmt.Errorf("jet: invalid json, %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rows.Next() {
|
if rows.Next() {
|
||||||
|
|
@ -407,7 +407,7 @@ func mapRowToStruct(
|
||||||
err := json.Unmarshal(value, fieldInterface)
|
err := json.Unmarshal(value, fieldInterface)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return updated, qrmAssignError(scannedValue, field, err)
|
return updated, qrmAssignError(scannedValue, field, fmt.Errorf("invalid json, %w", err))
|
||||||
}
|
}
|
||||||
default: // simple type
|
default: // simple type
|
||||||
err := assign(scannedValue, fieldValue)
|
err := assign(scannedValue, fieldValue)
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ FROM test_sample.all_types;
|
||||||
|
|
||||||
var dest []model.AllTypes
|
var dest []model.AllTypes
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// fix float rounding lost before comparison
|
// fix float rounding lost before comparison
|
||||||
|
|
@ -1329,7 +1329,7 @@ FROM (
|
||||||
|
|
||||||
var destJson []model.AllTypes
|
var destJson []model.AllTypes
|
||||||
|
|
||||||
err := stmtJson.QueryJSON(ctx, db, &destJson)
|
err := stmtJson.QueryContext(ctx, db, &destJson)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("using AllColumns()", func(t *testing.T) {
|
t.Run("using AllColumns()", func(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ func testDVDsJoinEverythingJSON(t require.TestingT) {
|
||||||
|
|
||||||
var dest allInfo
|
var dest allInfo
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
//testutils.SaveJSONFile(dest, "./testdata/results/mysql/dvds_join_everything2.json")
|
//testutils.SaveJSONFile(dest, "./testdata/results/mysql/dvds_join_everything2.json")
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ WHERE actor.actor_id = ?;
|
||||||
|
|
||||||
var dest model.Actor
|
var dest model.Actor
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.Query(db, &dest)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
testutils.AssertDeepEqual(t, dest, actor2)
|
testutils.AssertDeepEqual(t, dest, actor2)
|
||||||
|
|
@ -51,7 +51,7 @@ func TestSelectJsonObj_NestedObj(t *testing.T) {
|
||||||
FROM(FilmActor.INNER_JOIN(Film, Film.FilmID.EQ(FilmActor.FilmID))).
|
FROM(FilmActor.INNER_JOIN(Film, Film.FilmID.EQ(FilmActor.FilmID))).
|
||||||
WHERE(Actor.ActorID.EQ(FilmActor.ActorID)).
|
WHERE(Actor.ActorID.EQ(FilmActor.ActorID)).
|
||||||
ORDER_BY(Film.Length.DESC()).
|
ORDER_BY(Film.Length.DESC()).
|
||||||
LIMIT(1).AS("LongestFilm"),
|
LIMIT(1).OFFSET(3).AS("LongestFilm"),
|
||||||
).FROM(
|
).FROM(
|
||||||
Actor,
|
Actor,
|
||||||
).WHERE(
|
).WHERE(
|
||||||
|
|
@ -85,6 +85,7 @@ SELECT JSON_OBJECT(
|
||||||
WHERE actor.actor_id = film_actor.actor_id
|
WHERE actor.actor_id = film_actor.actor_id
|
||||||
ORDER BY film.length DESC
|
ORDER BY film.length DESC
|
||||||
LIMIT ?
|
LIMIT ?
|
||||||
|
OFFSET ?
|
||||||
)
|
)
|
||||||
) AS "json"
|
) AS "json"
|
||||||
FROM dvds.actor
|
FROM dvds.actor
|
||||||
|
|
@ -97,7 +98,7 @@ WHERE actor.actor_id = ?;
|
||||||
LongestFilm model.Film
|
LongestFilm model.Film
|
||||||
}
|
}
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
testutils.AssertJSON(t, dest, `
|
testutils.AssertJSON(t, dest, `
|
||||||
{
|
{
|
||||||
|
|
@ -106,18 +107,18 @@ WHERE actor.actor_id = ?;
|
||||||
"LastName": "WAHLBERG",
|
"LastName": "WAHLBERG",
|
||||||
"LastUpdate": "2006-02-15T04:34:33Z",
|
"LastUpdate": "2006-02-15T04:34:33Z",
|
||||||
"LongestFilm": {
|
"LongestFilm": {
|
||||||
"FilmID": 958,
|
"FilmID": 754,
|
||||||
"Title": "WARDROBE PHANTOM",
|
"Title": "RUSHMORE MERMAID",
|
||||||
"Description": "A Action-Packed Display of a Mad Cow And a Astronaut who must Kill a Car in Ancient India",
|
"Description": "A Boring Story of a Woman And a Moose who must Reach a Husband in A Shark Tank",
|
||||||
"ReleaseYear": 2006,
|
"ReleaseYear": 2006,
|
||||||
"LanguageID": 1,
|
"LanguageID": 1,
|
||||||
"OriginalLanguageID": null,
|
"OriginalLanguageID": null,
|
||||||
"RentalDuration": 6,
|
"RentalDuration": 6,
|
||||||
"RentalRate": 2.99,
|
"RentalRate": 2.99,
|
||||||
"Length": 178,
|
"Length": 150,
|
||||||
"ReplacementCost": 19.99,
|
"ReplacementCost": 17.99,
|
||||||
"Rating": "G",
|
"Rating": "PG-13",
|
||||||
"SpecialFeatures": "Trailers,Commentaries",
|
"SpecialFeatures": "Trailers,Commentaries,Deleted Scenes",
|
||||||
"LastUpdate": "2006-02-15T05:03:42Z"
|
"LastUpdate": "2006-02-15T05:03:42Z"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -143,7 +144,7 @@ ORDER BY actor.actor_id;
|
||||||
|
|
||||||
var dest []model.Actor
|
var dest []model.Actor
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.Query(db, &dest)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
testutils.AssertJSONFile(t, dest, "./testdata/results/mysql/all_actors.json")
|
testutils.AssertJSONFile(t, dest, "./testdata/results/mysql/all_actors.json")
|
||||||
|
|
@ -215,7 +216,7 @@ ORDER BY actor.actor_id;
|
||||||
Films []model.Film
|
Films []model.Film
|
||||||
}
|
}
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
testutils.AssertJSON(t, dest, `
|
testutils.AssertJSON(t, dest, `
|
||||||
|
|
@ -404,7 +405,7 @@ FROM (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
testutils.AssertJSONFile(t, dest, "./testdata/results/mysql/customer_payment_sum.json")
|
testutils.AssertJSONFile(t, dest, "./testdata/results/mysql/customer_payment_sum.json")
|
||||||
|
|
@ -420,7 +421,7 @@ func TestSelectJsonObject_EmptyResult(t *testing.T) {
|
||||||
|
|
||||||
var dest model.Actor
|
var dest model.Actor
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
require.ErrorIs(t, err, qrm.ErrNoRows)
|
require.ErrorIs(t, err, qrm.ErrNoRows)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -431,7 +432,7 @@ func TestSelectJsonObject_EmptyResult(t *testing.T) {
|
||||||
|
|
||||||
var dest []model.Actor
|
var dest []model.Actor
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Empty(t, dest)
|
require.Empty(t, dest)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ FROM (
|
||||||
|
|
||||||
var dest []model.AllTypes
|
var dest []model.AllTypes
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// fix inconsistencies between postgres and cockroachdb.
|
// fix inconsistencies between postgres and cockroachdb.
|
||||||
|
|
@ -864,7 +864,7 @@ FROM (
|
||||||
|
|
||||||
var destSelectJson testDest
|
var destSelectJson testDest
|
||||||
|
|
||||||
err := stmtJson.QueryJSON(ctx, db, &destSelectJson)
|
err := stmtJson.QueryContext(ctx, db, &destSelectJson)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testutils.PrintJson(destSelectJson)
|
testutils.PrintJson(destSelectJson)
|
||||||
|
|
||||||
|
|
@ -1427,7 +1427,7 @@ SELECT $1::time without time zone AS "time",
|
||||||
Date time.Time
|
Date time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
err := stmtJson.QueryJSON(ctx, db, &jsonDest)
|
err := stmtJson.QueryContext(ctx, db, &jsonDest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1823,7 +1823,7 @@ FROM (
|
||||||
|
|
||||||
var destJson []model.AllTypes
|
var destJson []model.AllTypes
|
||||||
|
|
||||||
err := stmtJson.QueryJSON(ctx, db, &destJson)
|
err := stmtJson.QueryContext(ctx, db, &destJson)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("using AllColumns()", func(t *testing.T) {
|
t.Run("using AllColumns()", func(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,7 @@ func testJoinEverythingJSON(t require.TestingT) {
|
||||||
|
|
||||||
var dest AllArtistDetails
|
var dest AllArtistDetails
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, len(dest), 275)
|
require.Equal(t, len(dest), 275)
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ func testNorthwindJoinEverythingJson(t require.TestingT) {
|
||||||
|
|
||||||
var dest Dest
|
var dest Dest
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
//testutils.SaveJSONFile(dest, "./testdata/results/postgres/northwind-all2.json")
|
//testutils.SaveJSONFile(dest, "./testdata/results/postgres/northwind-all2.json")
|
||||||
|
|
|
||||||
|
|
@ -300,7 +300,7 @@ func TestUUIDComplex(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := jsonQuery.QueryJSON(ctx, db, &dest)
|
err := jsonQuery.QueryContext(ctx, db, &dest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
testutils.AssertJSON(t, dest, expectedSliceOfStructsLeftJoin)
|
testutils.AssertJSON(t, dest, expectedSliceOfStructsLeftJoin)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -196,7 +196,7 @@ ORDER BY customer.customer_id ASC;
|
||||||
|
|
||||||
var dest []model.Customer
|
var dest []model.Customer
|
||||||
|
|
||||||
err := stmt.QueryJSON(ctx, db, &dest)
|
err := stmt.QueryContext(ctx, db, &dest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
testutils.AssertDeepEqual(t, customers, dest)
|
testutils.AssertDeepEqual(t, customers, dest)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue