Open
Description
I'm running into a parsing error when executing a CREATE TRIGGER
statement including a DELETE FROM ... AS ...
clause inside the trigger body.
I'm using v1.14.28 of this module.
_, err := db.Exec(`
CREATE TABLE host (host TEXT);
CREATE TABLE dsn (id INTEGER, host TEXT);
CREATE TRIGGER test_trigger AFTER DELETE ON dsn
BEGIN
DELETE FROM host AS h
WHERE h.host = OLD.host
AND h.host NOT IN (
SELECT DISTINCT d2.host
FROM dsn AS d2
WHERE d2.id != OLD.id
AND d2.host = OLD.host
);
END;
`)
returns
near "AS": syntax error
This SQL is valid as of SQLite 3.33.0, which introduced support for DELETE FROM ... AS alias
. This is using SQLite v3.49.1. The same SQL executes without issue using tools like DBeaver.
I can work around this by removing the alias and referencing the table name directly, i.e.
DELETE FROM host
WHERE host.host = OLD.host
AND host.host NOT IN (...)
I'm also able to successfully parse this using rqlite/sql.
Could this be a bug or parser limitation in the handling of Exec()
for DDL/trigger bodies?
For testing/reproduction, here is the code that works in rqlite/sql (and whose output runs in DBeaver) but fails in this module:
package main
import (
"fmt"
"strings"
"github.com/rqlite/sql"
)
func main() {
query := `
CREATE TRIGGER IF NOT EXISTS tr_log_dsn_removal AFTER DELETE
ON dsn
FOR EACH ROW
BEGIN
INSERT INTO audit (id, nm, data, source_id, source_table)
VALUES (
lower(hex(randomblob(16))),
'DSN_REMOVED',
json_object(
'id', OLD.id,
'name', OLD.nm
),
OLD.id,
'dsn'
);
DELETE FROM host h
WHERE h.host = OLD.host
AND h.host NOT IN (
SELECT distinct d2.host
FROM dsn d2
WHERE d2.id != OLD.id AND d2.host = OLD.host
);
END
;`
parser := sql.NewParser(strings.NewReader(query))
for {
stmt, err := parser.ParseStatement()
if err != nil {
if err.Error() == "EOF" {
break
}
panic(err)
}
fmt.Printf("-- Reconstructed statement as: \n%s\n", stmt.String())
}
}
Output:
-- Reconstructed statement as:
CREATE TRIGGER IF NOT EXISTS "tr_log_dsn_removal" AFTER DELETE ON "dsn" FOR EACH ROW BEGIN INSERT INTO "audit" ("id", "nm", "data", "source_id", "source_table") VALUES (lower(hex(randomblob(16))), 'DSN_REMOVED', json_object('id', "OLD"."id", 'name', "OLD"."nm"), "OLD"."id", 'dsn'); DELETE FROM "host" AS "h" WHERE "h"."host" = "OLD"."host" AND "h"."host" NOT IN (SELECT DISTINCT "d2"."host" FROM "dsn" AS "d2" WHERE "d2"."id" != "OLD"."id" AND "d2"."host" = "OLD"."host"); END
Metadata
Metadata
Assignees
Labels
No labels