aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dialect.go30
-rw-r--r--internal/dialect.go41
-rw-r--r--internal/mock/mock.go (renamed from internal/mock/driver.go)0
-rw-r--r--oblast.go19
-rw-r--r--plan.go (renamed from internal/plan.go)84
-rw-r--r--plan_test.go (renamed from internal/plan_test.go)43
-rw-r--r--select.go8
7 files changed, 101 insertions, 124 deletions
diff --git a/dialect.go b/dialect.go
index acbb160..a2827e2 100644
--- a/dialect.go
+++ b/dialect.go
@@ -3,7 +3,10 @@
package oblast
-import "go.xyrillian.de/oblast/internal"
+import (
+ "strconv"
+ "strings"
+)
// Dialect accounts for differences between different SQL dialects
// that are relevant to query generation within Oblast.
@@ -38,10 +41,31 @@ type Dialect interface {
// PostgresDialect is the dialect of PostgreSQL databases.
func PostgresDialect() Dialect {
- return internal.PostgresDialect{}
+ return postgresDialect{}
+}
+
+type postgresDialect struct{}
+
+func (postgresDialect) Placeholder(i int) string { return "$" + strconv.Itoa(i+1) }
+func (postgresDialect) QuoteIdentifier(name string) string { return `"` + name + `"` }
+func (postgresDialect) UsesLastInsertID() bool { return false }
+
+func (p postgresDialect) InsertSuffixForAutoColumns(columns []string) string {
+ quotedColumns := make([]string, len(columns))
+ for idx, name := range columns {
+ quotedColumns[idx] = p.QuoteIdentifier(name)
+ }
+ return ` RETURNING ` + strings.Join(quotedColumns, ", ")
}
// SqliteDialect is the dialect of SQLite databases.
func SqliteDialect() Dialect {
- return internal.SqliteDialect{}
+ return sqliteDialect{}
}
+
+type sqliteDialect struct{}
+
+func (sqliteDialect) Placeholder(_ int) string { return "?" }
+func (sqliteDialect) QuoteIdentifier(name string) string { return `"` + name + `"` }
+func (sqliteDialect) UsesLastInsertID() bool { return true }
+func (sqliteDialect) InsertSuffixForAutoColumns(columns []string) string { return "" }
diff --git a/internal/dialect.go b/internal/dialect.go
deleted file mode 100644
index e6db5b8..0000000
--- a/internal/dialect.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net>
-// SPDX-License-Identifier: Apache-2.0
-
-package internal
-
-import (
- "strconv"
- "strings"
-)
-
-// Dialect is a copy of the interface of the same name in package oblast.
-// We cannot refer to that interface within this package because that would constitute a cyclic dependency.
-type Dialect interface {
- Placeholder(i int) string
- QuoteIdentifier(name string) string
- UsesLastInsertID() bool
- InsertSuffixForAutoColumns(columns []string) string
-}
-
-// PostgresDialect is the dialect of PostgreSQL databases.
-type PostgresDialect struct{}
-
-func (PostgresDialect) Placeholder(i int) string { return "$" + strconv.Itoa(i+1) }
-func (PostgresDialect) QuoteIdentifier(name string) string { return `"` + name + `"` }
-func (PostgresDialect) UsesLastInsertID() bool { return false }
-
-func (p PostgresDialect) InsertSuffixForAutoColumns(columns []string) string {
- quotedColumns := make([]string, len(columns))
- for idx, name := range columns {
- quotedColumns[idx] = p.QuoteIdentifier(name)
- }
- return ` RETURNING ` + strings.Join(quotedColumns, ", ")
-}
-
-// SqliteDialect is the dialect of SQLite databases.
-type SqliteDialect struct{}
-
-func (SqliteDialect) Placeholder(_ int) string { return "?" }
-func (SqliteDialect) QuoteIdentifier(name string) string { return `"` + name + `"` }
-func (SqliteDialect) UsesLastInsertID() bool { return true }
-func (SqliteDialect) InsertSuffixForAutoColumns(columns []string) string { return "" }
diff --git a/internal/mock/driver.go b/internal/mock/mock.go
index d3358c4..d3358c4 100644
--- a/internal/mock/driver.go
+++ b/internal/mock/mock.go
diff --git a/oblast.go b/oblast.go
index 15f840a..7b40146 100644
--- a/oblast.go
+++ b/oblast.go
@@ -42,24 +42,23 @@ package oblast // import "go.xyrillian.de/oblast"
import (
"database/sql"
+ "fmt"
"reflect"
-
- "go.xyrillian.de/oblast/internal"
)
// PlanOption is an option that can be given to NewStore() to influence query planning for a certain type of record.
-type PlanOption func(*internal.PlanOpts)
+type PlanOption func(*planOpts)
// TableNameIs is a PlanOption for record types that correspond to exactly one database table (as opposed to a join of multiple tables).
// This option is required to enable any of the methods of [Store] that use partially or fully auto-generated query strings.
func TableNameIs(name string) PlanOption {
- return func(opts *internal.PlanOpts) { opts.TableName = name }
+ return func(opts *planOpts) { opts.TableName = name }
}
// PrimaryKeyIs is a PlanOption for record types that correspond to a database table with a primary key.
// This option is required to enable use of the [Store.Update] and [Store.Delete] methods.
func PrimaryKeyIs(columnNames ...string) PlanOption {
- return func(opts *internal.PlanOpts) { opts.PrimaryKeyColumnNames = columnNames }
+ return func(opts *planOpts) { opts.PrimaryKeyColumnNames = columnNames }
}
// Handle is an interface for functions providing direct DB access.
@@ -83,7 +82,7 @@ var (
// and can also be used to execute autogenerated queries if the respective [PlanOption] values were provided during [NewStore].
type Store[R any] struct {
dialect Dialect
- plan internal.Plan
+ plan plan
}
// NewStore initializes a store for record type R.
@@ -110,11 +109,15 @@ type Store[R any] struct {
// Besides the declaration of a column name, the following extra tags are understood (as a comma-separated list following the column name):
// - "auto": During [Store.Insert], do not store this field's value. Instead, the database will auto-generate a value, which will be read back into the record.
func NewStore[R any](dialect Dialect, opts ...PlanOption) (Store[R], error) {
- var popts internal.PlanOpts
+ var popts planOpts
for _, opt := range opts {
opt(&popts)
}
- plan, err := internal.BuildPlan(reflect.TypeFor[R](), dialect, popts)
+ plan, err := buildPlan(reflect.TypeFor[R](), dialect, popts)
+ if err != nil {
+ var zero R
+ return Store[R]{}, fmt.Errorf("cannot use type %T for queries: %w", zero, err)
+ }
return Store[R]{dialect, plan}, err
}
diff --git a/internal/plan.go b/plan.go
index b57b8dd..da9f9b5 100644
--- a/internal/plan.go
+++ b/plan.go
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net>
// SPDX-License-Identifier: Apache-2.0
-package internal
+package oblast
import (
"errors"
@@ -11,9 +11,9 @@ import (
"strings"
)
-// Plan holds all information that we can derive from reflecting on a given type.
+// plan holds all information that we can derive from reflecting on a given type.
// The queries held within are only valid within the context of a given SQL dialect.
-type Plan struct {
+type plan struct {
TypeName string // for use in error messages
TableName string // from info.TableNameIs marker (if any)
AllColumnNames []string // in order of struct fields
@@ -28,15 +28,15 @@ type Plan struct {
FillIDWithSetInt bool
// Planned queries.
- Select PlannedQuery // only `SELECT ... FROM ... WHERE `; user supplies the rest during Select{,One}Where()
- Insert PlannedQuery
- Update PlannedQuery
- Delete PlannedQuery
+ Select plannedQuery // only `SELECT ... FROM ... WHERE `; user supplies the rest during Select{,One}Where()
+ Insert plannedQuery
+ Update plannedQuery
+ Delete plannedQuery
}
-// PlannedQuery appears in type Plan.
-type PlannedQuery struct {
- // Empty if the respective query type is not supported by this Plan for lack of the required marker types.
+// plannedQuery appears in type plan.
+type plannedQuery struct {
+ // Empty if the respective query type is not supported by this plan for lack of the required marker types.
Query string
// Arguments for reflect.Value.FieldByIndex() in the correct order for the query arguments of the above query.
ArgumentIndexes [][]int
@@ -44,27 +44,19 @@ type PlannedQuery struct {
ScanIndexes [][]int
}
-// PlanOpts holds additional arguments to BuildPlan().
-type PlanOpts struct {
+// planOpts holds additional arguments to buildPlan().
+type planOpts struct {
TableName string
PrimaryKeyColumnNames []string
}
-// BuildPlan creates a new plan for the given struct type.
-func BuildPlan(t reflect.Type, dialect Dialect, opts PlanOpts) (Plan, error) {
- p, err := buildPlan(t, dialect, opts)
- if err != nil {
- return Plan{}, fmt.Errorf("cannot use type %s.%s for queries: %w", t.PkgPath(), t.Name(), err)
- }
- return p, nil
-}
-
-func buildPlan(t reflect.Type, dialect Dialect, opts PlanOpts) (Plan, error) {
+// buildPlan creates a new plan for the given struct type.
+func buildPlan(t reflect.Type, dialect Dialect, opts planOpts) (plan, error) {
if t.Kind() != reflect.Struct {
- return Plan{}, fmt.Errorf("expected struct type, but got kind %s", t.Kind().String())
+ return plan{}, fmt.Errorf("expected struct type, but got kind %s", t.Kind().String())
}
- var p = Plan{
+ var p = plan{
TypeName: t.Name(),
TableName: opts.TableName,
PrimaryKeyColumnNames: opts.PrimaryKeyColumnNames,
@@ -92,7 +84,7 @@ func buildPlan(t reflect.Type, dialect Dialect, opts PlanOpts) (Plan, error) {
columnName = field.Name
}
if otherIndex := p.IndexByColumnName[columnName]; otherIndex != nil {
- return Plan{}, fmt.Errorf(
+ return plan{}, fmt.Errorf(
"duplicate tag `db:%q` on field index %v, but also on field index %v",
columnName, otherIndex, field.Index,
)
@@ -105,7 +97,7 @@ func buildPlan(t reflect.Type, dialect Dialect, opts PlanOpts) (Plan, error) {
case "auto":
p.AutoColumnNames = append(p.AutoColumnNames, columnName)
default:
- return Plan{}, fmt.Errorf("unknown tag `db:%q` on field index %v", ","+tag, field.Index)
+ return plan{}, fmt.Errorf("unknown tag `db:%q` on field index %v", ","+tag, field.Index)
}
}
}
@@ -113,14 +105,14 @@ func buildPlan(t reflect.Type, dialect Dialect, opts PlanOpts) (Plan, error) {
// validation: defining a primary key only makes sense for records that map onto a single table
if len(p.PrimaryKeyColumnNames) > 0 && p.TableName == "" {
- return Plan{}, errors.New("cannot declare a primary key without also providing the TableNameIs option")
+ return plan{}, errors.New("cannot declare a primary key without also providing the TableNameIs option")
}
// validation: oblast.PrimaryKeyInfo must refer to columns that exist
for _, columnName := range p.PrimaryKeyColumnNames {
_, ok := p.IndexByColumnName[columnName]
if !ok {
- return Plan{}, fmt.Errorf("no field has tag `db:%q`, but a field of this name was declared in the primary key", columnName)
+ return plan{}, fmt.Errorf("no field has tag `db:%q`, but a field of this name was declared in the primary key", columnName)
}
}
@@ -138,13 +130,13 @@ func buildPlan(t reflect.Type, dialect Dialect, opts PlanOpts) (Plan, error) {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
p.FillIDWithSetUint = true
default:
- return Plan{}, fmt.Errorf(
+ return plan{}, fmt.Errorf(
"column is marked as auto-filled (%s), but this SQL dialect only supports auto-filling struct fields with integer types",
strings.Join(p.AutoColumnNames, ", "),
)
}
default:
- return Plan{}, fmt.Errorf(
+ return plan{}, fmt.Errorf(
"multiple columns are marked as auto-filled (%s), but this SQL dialect only supports at most one per table",
strings.Join(p.AutoColumnNames, ", "),
)
@@ -160,7 +152,7 @@ func buildPlan(t reflect.Type, dialect Dialect, opts PlanOpts) (Plan, error) {
return p, nil
}
-func (p Plan) getNonAutoColumnNames() []string {
+func (p plan) getNonAutoColumnNames() []string {
result := make([]string, 0, len(p.AllColumnNames)-len(p.AutoColumnNames))
for _, columnName := range p.AllColumnNames {
if !slices.Contains(p.AutoColumnNames, columnName) {
@@ -170,7 +162,7 @@ func (p Plan) getNonAutoColumnNames() []string {
return result
}
-func (p Plan) getNonPrimaryKeyColumnNames() []string {
+func (p plan) getNonPrimaryKeyColumnNames() []string {
result := make([]string, 0, len(p.AllColumnNames)-len(p.PrimaryKeyColumnNames))
for _, columnName := range p.AllColumnNames {
if !slices.Contains(p.PrimaryKeyColumnNames, columnName) {
@@ -180,9 +172,9 @@ func (p Plan) getNonPrimaryKeyColumnNames() []string {
return result
}
-func (p Plan) buildSelectQueryIfPossible(dialect Dialect) PlannedQuery {
+func (p plan) buildSelectQueryIfPossible(dialect Dialect) plannedQuery {
if p.TableName == "" {
- return PlannedQuery{Query: ""}
+ return plannedQuery{Query: ""}
}
var (
@@ -199,16 +191,16 @@ func (p Plan) buildSelectQueryIfPossible(dialect Dialect) PlannedQuery {
strings.Join(quotedColumnNames, ", "),
dialect.QuoteIdentifier(p.TableName),
)
- return PlannedQuery{query, nil, scanIndexes}
+ return plannedQuery{query, nil, scanIndexes}
}
-func (p Plan) buildInsertQueryIfPossible(dialect Dialect) PlannedQuery {
+func (p plan) buildInsertQueryIfPossible(dialect Dialect) plannedQuery {
if p.TableName == "" || len(p.AllColumnNames) == 0 {
- return PlannedQuery{Query: ""}
+ return plannedQuery{Query: ""}
}
nonAutoColumnNames := p.getNonAutoColumnNames()
if len(nonAutoColumnNames) == 0 {
- return PlannedQuery{Query: ""}
+ return plannedQuery{Query: ""}
}
var (
@@ -240,16 +232,16 @@ func (p Plan) buildInsertQueryIfPossible(dialect Dialect) PlannedQuery {
if len(p.AutoColumnNames) > 0 {
query += dialect.InsertSuffixForAutoColumns(p.AutoColumnNames)
}
- return PlannedQuery{query, argumentIndexes, scanIndexes}
+ return plannedQuery{query, argumentIndexes, scanIndexes}
}
-func (p Plan) buildUpdateQueryIfPossible(dialect Dialect) PlannedQuery {
+func (p plan) buildUpdateQueryIfPossible(dialect Dialect) plannedQuery {
if p.TableName == "" || len(p.PrimaryKeyColumnNames) == 0 {
- return PlannedQuery{Query: ""}
+ return plannedQuery{Query: ""}
}
nonPrimaryKeyColumnNames := p.getNonPrimaryKeyColumnNames()
if len(nonPrimaryKeyColumnNames) == 0 {
- return PlannedQuery{Query: ""}
+ return plannedQuery{Query: ""}
}
var (
@@ -276,12 +268,12 @@ func (p Plan) buildUpdateQueryIfPossible(dialect Dialect) PlannedQuery {
strings.Join(setClauses, ", "),
strings.Join(whereClauses, " AND "),
)
- return PlannedQuery{query, slices.Concat(setArgumentIndexes, whereArgumentIndexes), nil}
+ return plannedQuery{query, slices.Concat(setArgumentIndexes, whereArgumentIndexes), nil}
}
-func (p Plan) buildDeleteQueryIfPossible(dialect Dialect) PlannedQuery {
+func (p plan) buildDeleteQueryIfPossible(dialect Dialect) plannedQuery {
if p.TableName == "" || len(p.PrimaryKeyColumnNames) == 0 {
- return PlannedQuery{Query: ""}
+ return plannedQuery{Query: ""}
}
var (
@@ -298,5 +290,5 @@ func (p Plan) buildDeleteQueryIfPossible(dialect Dialect) PlannedQuery {
dialect.QuoteIdentifier(p.TableName),
strings.Join(clauses, " AND "),
)
- return PlannedQuery{query, argumentIndexes, nil}
+ return plannedQuery{query, argumentIndexes, nil}
}
diff --git a/internal/plan_test.go b/plan_test.go
index e692556..1095016 100644
--- a/internal/plan_test.go
+++ b/plan_test.go
@@ -1,14 +1,15 @@
// SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net>
// SPDX-License-Identifier: Apache-2.0
-package internal_test
+package oblast
+
+// ^ NOTE: This is testing internal types and thus must reside in the same package.
import (
"reflect"
"testing"
"time"
- "go.xyrillian.de/oblast/internal"
"go.xyrillian.de/oblast/internal/assert"
)
@@ -37,7 +38,7 @@ func TestPlanFieldTraversal(t *testing.T) {
// 5. traverses into "Timestamps" and includes its fields as well
// 6. traverses into "yetMoreTimestamps" as well (despite the extra pointer and the type being private)
// 7. recognizes "id" as an autofilled column
- plan, err := internal.BuildPlan(reflect.TypeFor[Log](), internal.PostgresDialect{}, internal.PlanOpts{
+ plan, err := buildPlan(reflect.TypeFor[Log](), PostgresDialect(), planOpts{
TableName: "log_entries",
PrimaryKeyColumnNames: []string{"id"},
})
@@ -65,13 +66,13 @@ func TestQueryConstructionBasic(t *testing.T) {
Description string
CreatedAt time.Time
}
- opts := internal.PlanOpts{
+ opts := planOpts{
TableName: "basic_records",
PrimaryKeyColumnNames: []string{"ID"},
}
t.Run("PostgresDialect", func(t *testing.T) {
- plan, err := internal.BuildPlan(reflect.TypeFor[record](), internal.PostgresDialect{}, opts)
+ plan, err := buildPlan(reflect.TypeFor[record](), PostgresDialect(), opts)
if err != nil {
t.Error(err)
}
@@ -90,7 +91,7 @@ func TestQueryConstructionBasic(t *testing.T) {
})
t.Run("SqliteDialect", func(t *testing.T) {
- plan, err := internal.BuildPlan(reflect.TypeFor[record](), internal.SqliteDialect{}, opts)
+ plan, err := buildPlan(reflect.TypeFor[record](), SqliteDialect(), opts)
if err != nil {
t.Error(err)
}
@@ -114,12 +115,12 @@ func TestQueryConstructionWithoutPrimaryKey(t *testing.T) {
FooID int64 `db:"foo_id"`
BarID int64 `db:"bar_id"`
}
- opts := internal.PlanOpts{
+ opts := planOpts{
TableName: "foo_bar_relations",
}
t.Run("PostgresDialect", func(t *testing.T) {
- plan, err := internal.BuildPlan(reflect.TypeFor[relation](), internal.PostgresDialect{}, opts)
+ plan, err := buildPlan(reflect.TypeFor[relation](), PostgresDialect(), opts)
if err != nil {
t.Error(err)
}
@@ -138,7 +139,7 @@ func TestQueryConstructionWithoutPrimaryKey(t *testing.T) {
})
t.Run("SqliteDialect", func(t *testing.T) {
- plan, err := internal.BuildPlan(reflect.TypeFor[relation](), internal.SqliteDialect{}, opts)
+ plan, err := buildPlan(reflect.TypeFor[relation](), SqliteDialect(), opts)
if err != nil {
t.Error(err)
}
@@ -162,11 +163,11 @@ func TestQueryConstructionImpossble(t *testing.T) {
Foo int
Bar string
}
- opts := internal.PlanOpts{}
+ opts := planOpts{}
- testWith := func(dialect internal.Dialect) func(*testing.T) {
+ testWith := func(dialect Dialect) func(*testing.T) {
return func(t *testing.T) {
- plan, err := internal.BuildPlan(reflect.TypeFor[unstructuredData](), dialect, opts)
+ plan, err := buildPlan(reflect.TypeFor[unstructuredData](), dialect, opts)
if err != nil {
t.Error(err)
}
@@ -186,8 +187,8 @@ func TestQueryConstructionImpossble(t *testing.T) {
}
}
- t.Run("PostgresDialect", testWith(internal.PostgresDialect{}))
- t.Run("SqliteDialect", testWith(internal.SqliteDialect{}))
+ t.Run("PostgresDialect", testWith(PostgresDialect()))
+ t.Run("SqliteDialect", testWith(SqliteDialect()))
}
func TestQueryConstructionWithMultiplePrimaryKeyColumns(t *testing.T) {
@@ -196,13 +197,13 @@ func TestQueryConstructionWithMultiplePrimaryKeyColumns(t *testing.T) {
Name string `db:"name"`
CreatedAt time.Time `db:"created_at"`
}
- opts := internal.PlanOpts{
+ opts := planOpts{
TableName: "complex_records",
PrimaryKeyColumnNames: []string{"group_id", "name"},
}
t.Run("PostgresDialect", func(t *testing.T) {
- plan, err := internal.BuildPlan(reflect.TypeFor[record](), internal.PostgresDialect{}, opts)
+ plan, err := buildPlan(reflect.TypeFor[record](), PostgresDialect(), opts)
if err != nil {
t.Error(err)
}
@@ -221,7 +222,7 @@ func TestQueryConstructionWithMultiplePrimaryKeyColumns(t *testing.T) {
})
t.Run("SqliteDialect", func(t *testing.T) {
- plan, err := internal.BuildPlan(reflect.TypeFor[record](), internal.SqliteDialect{}, opts)
+ plan, err := buildPlan(reflect.TypeFor[record](), SqliteDialect(), opts)
if err != nil {
t.Error(err)
}
@@ -246,13 +247,13 @@ func TestQueryConstructionWithMultipleAutoColumns(t *testing.T) {
Name string `db:"name"`
CreatedAt time.Time `db:"created_at,auto"`
}
- opts := internal.PlanOpts{
+ opts := planOpts{
TableName: "autogenerated_records",
PrimaryKeyColumnNames: []string{"id"},
}
t.Run("PostgresDialect", func(t *testing.T) {
- plan, err := internal.BuildPlan(reflect.TypeFor[record](), internal.PostgresDialect{}, opts)
+ plan, err := buildPlan(reflect.TypeFor[record](), PostgresDialect(), opts)
if err != nil {
t.Error(err)
}
@@ -271,7 +272,7 @@ func TestQueryConstructionWithMultipleAutoColumns(t *testing.T) {
})
t.Run("SqliteDialect", func(t *testing.T) {
- _, err := internal.BuildPlan(reflect.TypeFor[record](), internal.SqliteDialect{}, opts)
- assert.Equal(t, err.Error(), `cannot use type go.xyrillian.de/oblast/internal_test.record for queries: multiple columns are marked as auto-filled (id, created_at), but this SQL dialect only supports at most one per table`)
+ _, err := NewStore[record](SqliteDialect())
+ assert.Equal(t, err.Error(), `cannot use type oblast.record for queries: multiple columns are marked as auto-filled (id, created_at), but this SQL dialect only supports at most one per table`)
})
}
diff --git a/select.go b/select.go
index e6eccb1..8aed249 100644
--- a/select.go
+++ b/select.go
@@ -8,8 +8,6 @@ import (
"errors"
"fmt"
"reflect"
-
- "go.xyrillian.de/oblast/internal"
)
// Select executes the provided SQL query and fills an instance of the record type R for each row in the result set,
@@ -79,7 +77,7 @@ func (s Store[R]) SelectWhere(db Handle, partialQuery string, args ...any) (resu
return result, nil
}
-func startSelectQuery(db Handle, plan internal.Plan, query string, args ...any) (returnedRows *sql.Rows, indexes [][]int, returnedError error) {
+func startSelectQuery(db Handle, plan plan, query string, args ...any) (returnedRows *sql.Rows, indexes [][]int, returnedError error) {
rows, err := db.Query(query, args...)
if err != nil {
return nil, nil, fmt.Errorf("during Query(): %w", err)
@@ -112,7 +110,7 @@ func startSelectQuery(db Handle, plan internal.Plan, query string, args ...any)
return rows, indexes, nil
}
-func startSelectWhereQuery(db Handle, plan internal.Plan, partialQuery string, args ...any) (rows *sql.Rows, indexes [][]int, err error) {
+func startSelectWhereQuery(db Handle, plan plan, partialQuery string, args ...any) (rows *sql.Rows, indexes [][]int, err error) {
if plan.Select.Query == "" {
return nil, nil, errors.New("cannot execute SelectWhere() because query could not be autogenerated")
}
@@ -175,7 +173,7 @@ func (s Store[R]) SelectOneWhere(db Handle, partialQuery string, args ...any) (r
return
}
-func selectOneWhere(db Handle, plan internal.Plan, v reflect.Value, partialQuery string, args []any) error {
+func selectOneWhere(db Handle, plan plan, v reflect.Value, partialQuery string, args []any) error {
if plan.Select.Query == "" {
return errors.New("cannot execute SelectOneWhere() because query could not be autogenerated")
}