02.11.2025

This commit is contained in:
2025-11-02 19:55:58 +03:00
parent 49371e3eca
commit 9c204a9554
4 changed files with 50 additions and 28 deletions

View File

@@ -1,9 +1,9 @@
package batcher
import (
"strings"
"errors"
"strconv"
"strings"
"btchrr/models"
)
@@ -80,25 +80,33 @@ func (b *Batcher) BuildBatchQuery(singleQuery string, batchSize int, batchedItem
switch placeholder {
case "?":
for i :=0; i < numOfBatches; i++ {
batchQuery, err := b.buildSqliteQuery(singleQuery, batchedItems[i])
for i := 0; i < numOfBatches; i++ {
batchQuery, err := b.buildSqliteQuery(singleQuery)
if err != nil {
return []models.BatchedQuery{}, err
}
batchQuery.Items = batchedItems[i]
batchedQueries = append(batchedQueries, batchQuery)
}
return
case "$":
for i :=0; i < numOfBatches; i++ {
batchQuery, err := b.buildPostgresQuery(singleQuery, batchedItems[i])
for i := 0; i < numOfBatches; i++ {
batchQuery, err := b.buildPostgresQuery(singleQuery)
if err != nil {
return []models.BatchedQuery{}, err
}
batchQuery.Items = batchedItems[i]
batchedQueries = append(batchedQueries, batchQuery)
}
return
case ":":
batchedQueries, err = b.buildQueryWithNamedPlaceholders(singleQuery)
if err != nil {
return []models.BatchedQuery{}, err
}
return
default:
return b.buildQueryWithNamedPlaceholders(singleQuery, placeholder, batchedItems)
return []models.BatchedQuery{}, errors.New("unknown placeholder")
}
}
@@ -112,11 +120,12 @@ func (b *Batcher) detectPlaceholders(query string) (string, error) {
return "", models.ErrCannotDetectPlaceholder
}
func (b *Batcher) buildSqliteQuery(singleQuery string, batchedItems []any) (batchedQueries models.BatchedQuery, err error) {
// buildSqliteQuery - builds a batch query with sqlite placeholders
func (b *Batcher) buildSqliteQuery(singleQuery string) (batchedQuery models.BatchedQuery, err error) {
// INSERT INTO users VALUES (?, ?);
idx := strings.Index(strings.ToLower(singleQuery), "values")
if idx == -1 {
return "", errors.New("no values found in query")
return models.BatchedQuery{}, errors.New("no values found in query")
}
prefix := singleQuery[:idx+6] // +6 - values
@@ -124,23 +133,23 @@ func (b *Batcher) buildSqliteQuery(singleQuery string, batchedItems []any) (batc
numOfInserts := strings.Count(valuesPart, "?")
if numOfInserts == 0 {
return "", errors.New("no placeholders found in query")
return models.BatchedQuery{}, errors.New("no placeholders found in query")
}
singleItemValues := "(" + strings.Repeat("?, ", numOfInserts - 1) + "?)"
singleItemValues := "(" + strings.Repeat("?, ", numOfInserts-1) + "?)"
//INSERT INTO users (name, age) VALUES (?, ?), (?, ?), (?, ?);
newValues := strings.Repeat(singleItemValues + ", ", b.batchSize - 1) + singleItemValues
newQuery := prefix + " " + newValues + ";"
newValues := strings.Repeat(singleItemValues+", ", b.batchSize-1) + singleItemValues
batchedQuery.Query = prefix + " " + newValues + ";"
return models.BatchedQuery(newQuery), nil
return
}
func (b *Batcher) buildPostgresQuery(singleQuery string, batchedItems []any) (batchedQueries models.BatchedQuery, err error) {
// buildPostgresQuery - builds a batch query with postgres placeholders
func (b *Batcher) buildPostgresQuery(singleQuery string) (batchedQuery models.BatchedQuery, err error) {
// INSERT INTO users VALUES ($1, $2);
idx := strings.Index(strings.ToLower(singleQuery), "values")
if idx == -1 {
return "", errors.New("no values found in query")
return models.BatchedQuery{}, errors.New("no values found in query")
}
prefix := singleQuery[:idx+6] // +6 - values
@@ -148,13 +157,13 @@ func (b *Batcher) buildPostgresQuery(singleQuery string, batchedItems []any) (ba
numOfInserts := strings.Count(valuesPart, "$")
if numOfInserts == 0 {
return "", errors.New("no placeholders found in query")
return models.BatchedQuery{}, errors.New("no placeholders found in query")
}
//INSERT INTO users VALUES ($1, $2), ($3, $4), ($5, $6);
placeholderNum := 1
query := ""
for i := 0; i < b.batchSize ; i++ {
for i := 0; i < b.batchSize; i++ {
if i > 0 {
query += ", "
}
@@ -166,11 +175,22 @@ func (b *Batcher) buildPostgresQuery(singleQuery string, batchedItems []any) (ba
query += ")"
}
query = prefix + " " + query + ";"
batchedQuery.Query = prefix + " " + query + ";"
return models.BatchedQuery(query), nil
return
}
func (b *Batcher) buildQueryWithNamedPlaceholders(singleQuery string, placeholder string, batchedItems [][]any) (batchedQueries []models.BatchedQuery, err error) {
return []models.BatchedQuery{}, errors.New("not implemented")
// buildQueryWithNamedPlaceholders - builds a batch query with named placeholders
func (b *Batcher) buildQueryWithNamedPlaceholders(singleQuery string) (batchedQuery models.BatchedQuery, err error) {
// INSERT INTO users (name, age) VALUES (:name, :age);
idx := strings.Index(strings.ToLower(singleQuery), "values")
if idx == -1 {
return models.BatchedQuery{}, errors.New("no values found in query")
}
prefix := singleQuery[:idx+6] // +6 - values
valuesPart := singleQuery[idx+6:]
return
}

View File

@@ -52,7 +52,7 @@ func NewBtchrr(batchSize int, db *sql.DB) (*Btchrr, error) {
}
// Exec - accepts a query for single item, items and executes it in batches
func (b *Btchrr) Exec(ctx context.Context, query string, items []any) (sql.Result, error) {
func (b *Btchrr) ExecWitchContext(ctx context.Context, query string, items []any) (sql.Result, error) {
err := b.executor.CheckQuery(query)
if err != nil {
return nil, err

View File

@@ -16,16 +16,15 @@ func NewSQLAdapter(db *sql.DB) *DBAdapter {
}
func (a *DBAdapter) Exec(ctx context.Context, batchedQuery models.BatchedQuery) (sql.Result, error) {
res, err := a.db.ExecContext(ctx, string(batchedQuery))
res, err := a.db.ExecContext(ctx, batchedQuery.Query, batchedQuery.Items...)
return res, err
}
// CheckQuery - checks if the query is valid
func (a *DBAdapter) CheckQuery(query string) error {
stmt, err := a.db.Prepare(query)
stmt, err := a.db.Prepare(query)
if err != nil {
return err
return err
}
stmt.Close()
return nil

View File

@@ -9,4 +9,7 @@ var (
)
// BatchedQuery - single batch query
type BatchedQuery string
type BatchedQuery struct {
Query string
Items []any
}