diff --git a/internal/compiler/resolve.go b/internal/compiler/resolve.go index 2cb93fabc3..4624c5a45d 100644 --- a/internal/compiler/resolve.go +++ b/internal/compiler/resolve.go @@ -600,6 +600,16 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar, default: slog.Debug("unsupported reference type", "type", fmt.Sprintf("%T", n)) + defaultP := named.NewInferredParam(ref.name, false) + p, isNamed := params.FetchMerge(ref.ref.Number, defaultP) + a = append(a, Parameter{ + Number: ref.ref.Number, + Column: &Column{ + Name: p.Name(), + DataType: "any", + IsNamedParam: isNamed, + }, + }) } } return a, nil diff --git a/internal/endtoend/testdata/coalesce_params/issue.md b/internal/endtoend/testdata/coalesce_params/issue.md new file mode 100644 index 0000000000..ad6db4167a --- /dev/null +++ b/internal/endtoend/testdata/coalesce_params/issue.md @@ -0,0 +1,2 @@ +https://github.com/sqlc-dev/sqlc/issues/2748 +https://github.com/sqlc-dev/sqlc/issues/2786 diff --git a/internal/endtoend/testdata/coalesce_params/mysql/go/db.go b/internal/endtoend/testdata/coalesce_params/mysql/go/db.go new file mode 100644 index 0000000000..a457fb76b2 --- /dev/null +++ b/internal/endtoend/testdata/coalesce_params/mysql/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/coalesce_params/mysql/go/models.go b/internal/endtoend/testdata/coalesce_params/mysql/go/models.go new file mode 100644 index 0000000000..b2fc5363fd --- /dev/null +++ b/internal/endtoend/testdata/coalesce_params/mysql/go/models.go @@ -0,0 +1,87 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 + +package querytest + +import ( + "database/sql" + "database/sql/driver" + "fmt" + "time" +) + +type CalendarMaincalendar string + +const ( + CalendarMaincalendarTrue CalendarMaincalendar = "true" + CalendarMaincalendarFalse CalendarMaincalendar = "false" +) + +func (e *CalendarMaincalendar) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = CalendarMaincalendar(s) + case string: + *e = CalendarMaincalendar(s) + default: + return fmt.Errorf("unsupported scan type for CalendarMaincalendar: %T", src) + } + return nil +} + +type NullCalendarMaincalendar struct { + CalendarMaincalendar CalendarMaincalendar + Valid bool // Valid is true if CalendarMaincalendar is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullCalendarMaincalendar) Scan(value interface{}) error { + if value == nil { + ns.CalendarMaincalendar, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.CalendarMaincalendar.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullCalendarMaincalendar) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.CalendarMaincalendar), nil +} + +type Author struct { + ID int64 + Address string + Name string + Bio string +} + +type Calendar struct { + ID uint64 + Relation uint64 + Calendarname []byte + Title []byte + Description []byte + Timezone string + Uniquekey string + Idkey string + Maincalendar CalendarMaincalendar + Createdate time.Time + Modifydate time.Time +} + +type Event struct { + ID uint64 + Relation uint64 + Calendarreference uint64 + Uniquekey string + Eventname []byte + Description []byte + Location string + Timezone string + Idkey sql.NullString +} diff --git a/internal/endtoend/testdata/coalesce_params/mysql/go/query.sql.go b/internal/endtoend/testdata/coalesce_params/mysql/go/query.sql.go new file mode 100644 index 0000000000..833f917be5 --- /dev/null +++ b/internal/endtoend/testdata/coalesce_params/mysql/go/query.sql.go @@ -0,0 +1,57 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.22.0 +// source: query.sql + +package querytest + +import ( + "context" +) + +const addAuthor = `-- name: AddAuthor :execlastid +INSERT INTO authors ( + address, + name, + bio +) VALUES ( + ?, + COALESCE(?, ""), + COALESCE(?, "") +) +` + +type AddAuthorParams struct { + Address string + CalName interface{} + CalDescription interface{} +} + +func (q *Queries) AddAuthor(ctx context.Context, arg AddAuthorParams) (int64, error) { + result, err := q.db.ExecContext(ctx, addAuthor, arg.Address, arg.CalName, arg.CalDescription) + if err != nil { + return 0, err + } + return result.LastInsertId() +} + +const addEvent = `-- name: AddEvent :execlastid +INSERT INTO ` + "`" + `Event` + "`" + ` ( + Timezone +) VALUES ( + (CASE WHEN ? = "calendar" THEN (SELECT cal.Timezone FROM Calendar cal WHERE cal.IdKey = ?) ELSE ? END) +) +` + +type AddEventParams struct { + Timezone interface{} + CalendarIdKey string +} + +func (q *Queries) AddEvent(ctx context.Context, arg AddEventParams) (int64, error) { + result, err := q.db.ExecContext(ctx, addEvent, arg.Timezone, arg.CalendarIdKey, arg.Timezone) + if err != nil { + return 0, err + } + return result.LastInsertId() +} diff --git a/internal/endtoend/testdata/coalesce_params/mysql/query.sql b/internal/endtoend/testdata/coalesce_params/mysql/query.sql new file mode 100644 index 0000000000..f6df77d55d --- /dev/null +++ b/internal/endtoend/testdata/coalesce_params/mysql/query.sql @@ -0,0 +1,17 @@ +-- name: AddEvent :execlastid +INSERT INTO `Event` ( + Timezone +) VALUES ( + (CASE WHEN sqlc.arg("Timezone") = "calendar" THEN (SELECT cal.Timezone FROM Calendar cal WHERE cal.IdKey = sqlc.arg("calendarIdKey")) ELSE sqlc.arg("Timezone") END) +); + +-- name: AddAuthor :execlastid +INSERT INTO authors ( + address, + name, + bio +) VALUES ( + ?, + COALESCE(sqlc.narg("calName"), ""), + COALESCE(sqlc.narg("calDescription"), "") +); diff --git a/internal/endtoend/testdata/coalesce_params/mysql/schema.sql b/internal/endtoend/testdata/coalesce_params/mysql/schema.sql new file mode 100644 index 0000000000..a0d41cbe74 --- /dev/null +++ b/internal/endtoend/testdata/coalesce_params/mysql/schema.sql @@ -0,0 +1,43 @@ +CREATE TABLE `Calendar` ( + `Id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `Relation` bigint(20) unsigned NOT NULL, + `CalendarName` longblob NOT NULL, + `Title` longblob NOT NULL, + `Description` longblob NOT NULL, + `Timezone` varchar(50) NOT NULL, + `UniqueKey` varchar(50) NOT NULL, + `IdKey` varchar(50) NOT NULL, + `MainCalendar` enum('true','false') NOT NULL DEFAULT 'false', + `CreateDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `ModifyDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`Id`), + KEY `Relation` (`Relation`), + KEY `UniqueKey` (`UniqueKey`), + KEY `IdKey` (`IdKey`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; + + +CREATE TABLE `Event` ( + `Id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `Relation` bigint(20) unsigned NOT NULL, + `CalendarReference` bigint(20) unsigned NOT NULL, + `UniqueKey` varchar(50) NOT NULL, + `EventName` longblob NOT NULL, + `Description` longblob NOT NULL, + `Location` varchar(500) NOT NULL, + `Timezone` varchar(50) NOT NULL, + `IdKey` varchar(48) DEFAULT NULL, + PRIMARY KEY (`Id`), + KEY `Relation` (`Relation`), + KEY `CalendarReference` (`CalendarReference`), + KEY `UniqueKey` (`UniqueKey`), + KEY `IdKey` (`IdKey`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4; + + +CREATE TABLE authors ( + id BIGINT AUTO_INCREMENT NOT NULL, + address VARCHAR(200) NOT NULL, + name VARCHAR(20) NOT NULL, + bio LONGTEXT NOT NULL +); diff --git a/internal/endtoend/testdata/coalesce_params/mysql/sqlc.yaml b/internal/endtoend/testdata/coalesce_params/mysql/sqlc.yaml new file mode 100644 index 0000000000..b843ef55e3 --- /dev/null +++ b/internal/endtoend/testdata/coalesce_params/mysql/sqlc.yaml @@ -0,0 +1,9 @@ +version: "2" +sql: + - engine: "mysql" + schema: "schema.sql" + queries: "query.sql" + gen: + go: + package: "querytest" + out: "go"