fix: contain generated files and assets and harden SQL rendering

This commit is contained in:
2026-10-12 20:59:46 +02:00
parent 2fa48335d3
commit dd97413b8e
68 changed files with 2328 additions and 798 deletions
+4 -17
View File
@@ -3,20 +3,12 @@ package assetloader
import (
"context"
"fmt"
"os"
"git.warky.dev/wdevs/relspecgo/pkg/sqllex"
"path/filepath"
"regexp"
"strings"
"github.com/jackc/pgx/v5"
)
// namedPlaceholder matches :identifier patterns (but not ::cast syntax).
var namedPlaceholder = regexp.MustCompile(`:([a-zA-Z_][a-zA-Z0-9_]*)`)
// pgCastMarker temporarily replaces :: to protect PostgreSQL cast syntax.
const pgCastMarker = "\x00PGCAST\x00"
// BuildQuery converts a SQL call that uses :name named placeholders into a
// pgx-compatible positional-parameter query ($1, $2, …) and returns the
// corresponding argument slice.
@@ -30,13 +22,11 @@ const pgCastMarker = "\x00PGCAST\x00"
// placeholder (not built-in and not in staticParams) returns an error.
// PostgreSQL cast syntax (::type) is left untouched.
func BuildQuery(call string, fileBytes []byte, filename string, staticParams map[string]string) (query string, args []any, err error) {
// Protect :: casts before running the placeholder regex.
protected := strings.ReplaceAll(call, "::", pgCastMarker)
paramIndex := map[string]int{} // name → 1-based position
var firstErr error
query = namedPlaceholder.ReplaceAllStringFunc(protected, func(match string) string {
query = sqllex.Walk(call, func(match string) string {
if firstErr != nil {
return match
}
@@ -70,15 +60,12 @@ func BuildQuery(call string, fileBytes []byte, filename string, staticParams map
paramIndex[name] = idx
args = append(args, val)
return fmt.Sprintf("$%d", idx)
})
}, nil)
if firstErr != nil {
return "", nil, firstErr
}
// Restore :: casts.
query = strings.ReplaceAll(query, pgCastMarker, "::")
return query, args, nil
}
@@ -86,7 +73,7 @@ func BuildQuery(call string, fileBytes []byte, filename string, staticParams map
// absolute path set by ScanDir) and executes the configured SQL call via conn.
// The file's raw bytes are bound as a []byte parameter — no encoding or escaping.
func ExecuteItem(ctx context.Context, conn *pgx.Conn, item Item) error {
data, err := os.ReadFile(item.Entry.File)
data, err := readItemAsset(item)
if err != nil {
return fmt.Errorf("reading asset file %s: %w", item.Entry.File, err)
}