-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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 errorThis 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"); ENDMetadata
Metadata
Assignees
Labels
No labels