feat: implement QueryFromObject method for mssql and postgres wrappers; enhance query building with limits and geometry support
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
dbdialects "git.ksdemosapps.com/kylesoda/go-migrate/internal/app/db-wrapper/db-dialects"
|
dbdialects "git.ksdemosapps.com/kylesoda/go-migrate/internal/app/db-wrapper/db-dialects"
|
||||||
mssql "github.com/microsoft/go-mssqldb"
|
mssql "github.com/microsoft/go-mssqldb"
|
||||||
@@ -175,3 +176,72 @@ func (mw *mssqlDbWrapper) SaveMassive(ctx context.Context, schema string, table
|
|||||||
|
|
||||||
return rowsAffected, nil
|
return rowsAffected, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mw *mssqlDbWrapper) QueryFromObject(ctx context.Context, q ExtractionQuery) (RowsResult, error) {
|
||||||
|
var sbQuery strings.Builder
|
||||||
|
|
||||||
|
sbQuery.WriteString("SELECT ")
|
||||||
|
|
||||||
|
if len(q.columns) == 0 {
|
||||||
|
sbQuery.WriteString("*")
|
||||||
|
} else {
|
||||||
|
for i, col := range q.columns {
|
||||||
|
fmt.Fprintf(&sbQuery, "[%s]", col.Name())
|
||||||
|
|
||||||
|
switch col.Type() {
|
||||||
|
case "GEOMETRY":
|
||||||
|
fmt.Fprintf(&sbQuery, ".STAsBinary() AS [%s]", col.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
if i < len(q.columns)-1 {
|
||||||
|
sbQuery.WriteString(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(&sbQuery, " FROM [%s].[%s]", q.Schema, q.Table)
|
||||||
|
|
||||||
|
if q.LowerLimit.IsValid || q.UpperLimit.IsValid {
|
||||||
|
sbQuery.WriteString(" WHERE ")
|
||||||
|
|
||||||
|
if q.LowerLimit.IsValid {
|
||||||
|
fmt.Fprintf(&sbQuery, "[%s]", q.PrimaryKey)
|
||||||
|
if q.LowerLimit.IsInclusive {
|
||||||
|
sbQuery.WriteString(" >=")
|
||||||
|
} else {
|
||||||
|
sbQuery.WriteString(" >")
|
||||||
|
}
|
||||||
|
sbQuery.WriteString(" @min")
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.LowerLimit.IsValid && q.UpperLimit.IsValid {
|
||||||
|
sbQuery.WriteString(" AND ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.UpperLimit.IsValid {
|
||||||
|
fmt.Fprintf(&sbQuery, "[%s]", q.PrimaryKey)
|
||||||
|
if q.UpperLimit.IsInclusive {
|
||||||
|
sbQuery.WriteString(" <=")
|
||||||
|
} else {
|
||||||
|
sbQuery.WriteString(" <")
|
||||||
|
}
|
||||||
|
sbQuery.WriteString(" @max")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(&sbQuery, " ORDER BY [%s] ASC", q.PrimaryKey)
|
||||||
|
|
||||||
|
queryString := sbQuery.String()
|
||||||
|
|
||||||
|
var queryArgs []any
|
||||||
|
|
||||||
|
if q.LowerLimit.IsValid {
|
||||||
|
queryArgs = append(queryArgs, sql.Named("min", q.LowerLimit.Value))
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.UpperLimit.IsValid {
|
||||||
|
queryArgs = append(queryArgs, sql.Named("max", q.UpperLimit.Value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return mw.Query(ctx, queryString, queryArgs...)
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package dbwrapper
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
dbdialects "git.ksdemosapps.com/kylesoda/go-migrate/internal/app/db-wrapper/db-dialects"
|
dbdialects "git.ksdemosapps.com/kylesoda/go-migrate/internal/app/db-wrapper/db-dialects"
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
@@ -127,3 +129,75 @@ func (pw *postgresDbWrapper) SaveMassive(ctx context.Context, schema string, tab
|
|||||||
|
|
||||||
return affectedRows, nil
|
return affectedRows, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pw *postgresDbWrapper) QueryFromObject(ctx context.Context, q ExtractionQuery) (RowsResult, error) {
|
||||||
|
var sbQuery strings.Builder
|
||||||
|
|
||||||
|
sbQuery.WriteString("SELECT ")
|
||||||
|
|
||||||
|
if len(q.columns) == 0 {
|
||||||
|
sbQuery.WriteString("*")
|
||||||
|
} else {
|
||||||
|
for i, col := range q.columns {
|
||||||
|
switch col.Type() {
|
||||||
|
case "GEOMETRY":
|
||||||
|
fmt.Fprintf(&sbQuery, `ST_AsEWKB("%s") AS "%s"`, col.Name(), col.Name())
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(&sbQuery, `"%s"`, col.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
if i < len(q.columns)-1 {
|
||||||
|
sbQuery.WriteString(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(&sbQuery, ` FROM "%s"."%s"`, q.Schema, q.Table)
|
||||||
|
|
||||||
|
if q.LowerLimit.IsValid || q.UpperLimit.IsValid {
|
||||||
|
sbQuery.WriteString(" WHERE ")
|
||||||
|
paramIdx := 1
|
||||||
|
|
||||||
|
if q.LowerLimit.IsValid {
|
||||||
|
fmt.Fprintf(&sbQuery, `"%s"`, q.PrimaryKey)
|
||||||
|
if q.LowerLimit.IsInclusive {
|
||||||
|
sbQuery.WriteString(" >=")
|
||||||
|
} else {
|
||||||
|
sbQuery.WriteString(" >")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&sbQuery, " $%d", paramIdx)
|
||||||
|
paramIdx++
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.LowerLimit.IsValid && q.UpperLimit.IsValid {
|
||||||
|
sbQuery.WriteString(" AND ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.UpperLimit.IsValid {
|
||||||
|
fmt.Fprintf(&sbQuery, `"%s"`, q.PrimaryKey)
|
||||||
|
if q.UpperLimit.IsInclusive {
|
||||||
|
sbQuery.WriteString(" <=")
|
||||||
|
} else {
|
||||||
|
sbQuery.WriteString(" <")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&sbQuery, " $%d", paramIdx)
|
||||||
|
paramIdx++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(&sbQuery, ` ORDER BY "%s" ASC`, q.PrimaryKey)
|
||||||
|
|
||||||
|
queryString := sbQuery.String()
|
||||||
|
|
||||||
|
var queryArgs []any
|
||||||
|
|
||||||
|
if q.LowerLimit.IsValid {
|
||||||
|
queryArgs = append(queryArgs, q.LowerLimit.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.UpperLimit.IsValid {
|
||||||
|
queryArgs = append(queryArgs, q.UpperLimit.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pw.Query(ctx, queryString, queryArgs...)
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package dbwrapper
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"git.ksdemosapps.com/kylesoda/go-migrate/internal/app/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
var MethodNotSupported error = errors.New("Method not supported by driver... yet :P")
|
var MethodNotSupported error = errors.New("Method not supported by driver... yet :P")
|
||||||
@@ -24,6 +26,21 @@ type RowResult interface {
|
|||||||
Scan(dest ...any) error
|
Scan(dest ...any) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExtractorQueryLimit struct {
|
||||||
|
IsValid bool
|
||||||
|
IsInclusive bool
|
||||||
|
Value int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtractionQuery struct {
|
||||||
|
Schema string
|
||||||
|
Table string
|
||||||
|
PrimaryKey string
|
||||||
|
columns []models.ColumnType
|
||||||
|
LowerLimit ExtractorQueryLimit
|
||||||
|
UpperLimit ExtractorQueryLimit
|
||||||
|
}
|
||||||
|
|
||||||
type DbWrapper interface {
|
type DbWrapper interface {
|
||||||
Close() error
|
Close() error
|
||||||
Connect(ctx context.Context, dbUrl string) error
|
Connect(ctx context.Context, dbUrl string) error
|
||||||
@@ -32,4 +49,5 @@ type DbWrapper interface {
|
|||||||
Query(ctx context.Context, query string, args ...any) (RowsResult, error)
|
Query(ctx context.Context, query string, args ...any) (RowsResult, error)
|
||||||
QueryRow(ctx context.Context, query string, args ...any) RowResult
|
QueryRow(ctx context.Context, query string, args ...any) RowResult
|
||||||
SaveMassive(ctx context.Context, schema string, table string, columnNames []string, rows [][]any) (int64, error)
|
SaveMassive(ctx context.Context, schema string, table string, columnNames []string, rows [][]any) (int64, error)
|
||||||
|
QueryFromObject(ctx context.Context, query ExtractionQuery) (RowsResult, error)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user