Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SQL identifiers in this migrator are always static allowlisted names or
|
||||
// programmer-supplied column paths — never end-user free text. Still quote
|
||||
// and validate before interpolating into DDL/DML to fail closed on mistakes.
|
||||
|
||||
var sqlIdentSegment = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`)
|
||||
|
||||
func quoteMySQLIdent(ident string) (string, error) {
|
||||
if !sqlIdentSegment.MatchString(ident) {
|
||||
return "", fmt.Errorf("invalid MySQL identifier %q", ident)
|
||||
}
|
||||
return "`" + strings.ReplaceAll(ident, "`", "``") + "`", nil
|
||||
}
|
||||
|
||||
// quoteMySQLIdentPath quotes dotted paths such as company_id or cf.company_id.
|
||||
func quoteMySQLIdentPath(path string) (string, error) {
|
||||
path = strings.TrimSpace(path)
|
||||
if path == "" {
|
||||
return "", fmt.Errorf("empty MySQL identifier path")
|
||||
}
|
||||
parts := strings.Split(path, ".")
|
||||
out := make([]string, len(parts))
|
||||
for i, part := range parts {
|
||||
q, err := quoteMySQLIdent(part)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
out[i] = q
|
||||
}
|
||||
return strings.Join(out, "."), nil
|
||||
}
|
||||
|
||||
func mustQuoteMySQLIdent(ident string) string {
|
||||
q, err := quoteMySQLIdent(ident)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func quotePGIdent(ident string) (string, error) {
|
||||
if !sqlIdentSegment.MatchString(ident) {
|
||||
return "", fmt.Errorf("invalid Postgres identifier %q", ident)
|
||||
}
|
||||
return `"` + strings.ReplaceAll(ident, `"`, `""`) + `"`, nil
|
||||
}
|
||||
Reference in New Issue
Block a user