added postgreSQL placeholders support

This commit is contained in:
2025-10-13 00:07:06 +03:00
parent b104ff31b6
commit 49371e3eca

View File

@@ -3,6 +3,7 @@ package batcher
import ( import (
"strings" "strings"
"errors" "errors"
"strconv"
"btchrr/models" "btchrr/models"
) )
@@ -23,7 +24,7 @@ func NewBatcher(batchSize int) (*Batcher, error) {
batchSize: batchSize, batchSize: batchSize,
placeholders: make(map[string]struct{}), placeholders: make(map[string]struct{}),
} }
for _, ph := range []string{"?", "$", ":", ":"} { for _, ph := range []string{"?", "$", ":"} {
b.placeholders[ph] = struct{}{} b.placeholders[ph] = struct{}{}
} }
return b, nil return b, nil
@@ -36,7 +37,7 @@ func (b *Batcher) BuildBatches(singleQuery string, items []any) ([]models.Batche
return []models.BatchedQuery{}, err return []models.BatchedQuery{}, err
} }
batches, err := b.BuildBatchQuery(singleQuery, b.batchSize, batchedItems) batches, err := b.BuildBatchQuery(singleQuery, b.batchSize, batchedItems, len(batchedItems))
if err != nil { if err != nil {
return []models.BatchedQuery{}, err return []models.BatchedQuery{}, err
} }
@@ -71,7 +72,7 @@ func (b *Batcher) batchItems(items []any) ([][]any, error) {
} }
// BuildBatchQuery - builds a batch query from a single query // BuildBatchQuery - builds a batch query from a single query
func (b *Batcher) BuildBatchQuery(singleQuery string, batchSize int, batchedItems [][]any) (batchedQueries []models.BatchedQuery, err error) { func (b *Batcher) BuildBatchQuery(singleQuery string, batchSize int, batchedItems [][]any, numOfBatches int) (batchedQueries []models.BatchedQuery, err error) {
placeholder, err := b.detectPlaceholders(singleQuery) placeholder, err := b.detectPlaceholders(singleQuery)
if err != nil { if err != nil {
return []models.BatchedQuery{}, err return []models.BatchedQuery{}, err
@@ -79,9 +80,23 @@ func (b *Batcher) BuildBatchQuery(singleQuery string, batchSize int, batchedItem
switch placeholder { switch placeholder {
case "?": case "?":
return b.buildSqliteQuery(singleQuery, batchedItems) for i :=0; i < numOfBatches; i++ {
batchQuery, err := b.buildSqliteQuery(singleQuery, batchedItems[i])
if err != nil {
return []models.BatchedQuery{}, err
}
batchedQueries = append(batchedQueries, batchQuery)
}
return
case "$": case "$":
return b.buildPostgresQuery(singleQuery, batchedItems) for i :=0; i < numOfBatches; i++ {
batchQuery, err := b.buildPostgresQuery(singleQuery, batchedItems[i])
if err != nil {
return []models.BatchedQuery{}, err
}
batchedQueries = append(batchedQueries, batchQuery)
}
return
default: default:
return b.buildQueryWithNamedPlaceholders(singleQuery, placeholder, batchedItems) return b.buildQueryWithNamedPlaceholders(singleQuery, placeholder, batchedItems)
} }
@@ -97,7 +112,7 @@ func (b *Batcher) detectPlaceholders(query string) (string, error) {
return "", models.ErrCannotDetectPlaceholder return "", models.ErrCannotDetectPlaceholder
} }
func (b *Batcher) buildSqliteQuery(singleQuery string, batchedItems [][]any) (batchedQueries models.BatchedQuery, err error) { func (b *Batcher) buildSqliteQuery(singleQuery string, batchedItems []any) (batchedQueries models.BatchedQuery, err error) {
// INSERT INTO users VALUES (?, ?); // INSERT INTO users VALUES (?, ?);
idx := strings.Index(strings.ToLower(singleQuery), "values") idx := strings.Index(strings.ToLower(singleQuery), "values")
if idx == -1 { if idx == -1 {
@@ -121,8 +136,39 @@ func (b *Batcher) buildSqliteQuery(singleQuery string, batchedItems [][]any) (ba
return models.BatchedQuery(newQuery), nil return models.BatchedQuery(newQuery), nil
} }
func (b *Batcher) buildPostgresQuery(singleQuery string, batchedItems [][]any) (batchedQueries []models.BatchedQuery, err error) { func (b *Batcher) buildPostgresQuery(singleQuery string, batchedItems []any) (batchedQueries models.BatchedQuery, err error) {
return []models.BatchedQuery{}, errors.New("not implemented") // INSERT INTO users VALUES ($1, $2);
idx := strings.Index(strings.ToLower(singleQuery), "values")
if idx == -1 {
return "", errors.New("no values found in query")
}
prefix := singleQuery[:idx+6] // +6 - values
valuesPart := singleQuery[idx+6:]
numOfInserts := strings.Count(valuesPart, "$")
if numOfInserts == 0 {
return "", 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++ {
if i > 0 {
query += ", "
}
query += "("
for j := 0; j < numOfInserts; j++ {
query += "$" + strconv.Itoa(placeholderNum) + ", "
placeholderNum++
}
query += ")"
}
query = prefix + " " + query + ";"
return models.BatchedQuery(query), nil
} }
func (b *Batcher) buildQueryWithNamedPlaceholders(singleQuery string, placeholder string, batchedItems [][]any) (batchedQueries []models.BatchedQuery, err error) { func (b *Batcher) buildQueryWithNamedPlaceholders(singleQuery string, placeholder string, batchedItems [][]any) (batchedQueries []models.BatchedQuery, err error) {