sqlite3 eval中的tcl var替换

时间:2018-02-11 10:49:03

标签: sqlite tcl

我有一个文件,里面装满了我要解析的sqlite语句。我以前使用C接口这样做了,但现在我遇到了Tcl接口问题。

sqlite3 cspdb ":memory:"
set s [read [set f [open csp_sql.txt]]]
set ms [string map {"\n" "\0"} $s]
puts $ms
cspdb eval {$ms}

我得到的错误是:

  

“near”$ ms“:执行cspdb eval {$ ms}时出现语法错误”

将puts $ ms的输出直接粘贴到eval括号中时,它工作正常。我也试过“{$ ms}”并且只是简单的$ ms,但结果是一样的;语法错误。

我可能会一起为问题选择另一种解决方案,但它确实错误地解释了为什么它不起作用......

这是文件的样子:

  BEGIN TRANSACTION;
    CREATE TABLE Symbol (
      Label TEXT PRIMARY KEY,
      Type TEXT DEFAULT('no_type')
    );

    CREATE TABLE Process (
      Name INTEGER PRIMARY KEY,
      Type TEXT DEFAULT('no_type')
    );

    CREATE TABLE Named_Process (
      Label TEXT UNIQUE,
      Definition INTEGER UNIQUE,
      FOREIGN KEY(Label) REFERENCES Symbol (Label),
      FOREIGN KEY(Definition) REFERENCES Definition(Name)
    );

    CREATE TABLE Definition (
      Name INTEGER UNIQUE,
      Definition INTEGER,
      FOREIGN KEY(Name) REFERENCES Process(Name),
      FOREIGN KEY(Definition) REFERENCES Process(Name)
    );

    CREATE TABLE Reference (
      Name INTEGER UNIQUE,
      Reference TEXT,
      FOREIGN KEY(Name) REFERENCES Process(Name),
      FOREIGN KEY(Reference) REFERENCES Definition(Name)
    );

    CREATE TABLE Event (
      Label TEXT PRIMARY KEY,
      Type TEXT DEFAULT('no_type')
    );

    CREATE TABLE Environment (
      Label TEXT UNIQUE,
      FOREIGN KEY (Label) REFERENCES Event (Label)
    );

    CREATE TABLE Prefix (
      Name INTEGER UNIQUE,
      P INTEGER,
      Event TEXT,
      FOREIGN KEY (Name) REFERENCES Process (Name),
      FOREIGN KEY (P) REFERENCES Process (Name),
      FOREIGN KEY (Event) REFERENCES Event (Label)
    );

    CREATE TABLE Choice (
      Name INTEGER UNIQUE,
      P INTEGER,
      Q INTEGER,
      FOREIGN KEY(Name) REFERENCES Process(Name),
      FOREIGN KEY(P) REFERENCES Process(Name),
      FOREIGN KEY(Q) REFERENCES Process(Name)
    );

    /* Language defined processes */
    /* SKIP */
    INSERT INTO Symbol(Label,Type) VALUES('SKIP','named_process');
    INSERT INTO Named_Process(Label) VALUES('SKIP');
    INSERT INTO Process(type) VALUES('definition');
    UPDATE Named_Process SET Definition=last_insert_rowid() WHERE Label='SKIP';
    INSERT INTO Definition(Name,Definition) VALUES(last_insert_rowid(),last_insert_rowid());

  END TRANSACTION;

(不太确定删除换行符是必要的......)

3 个答案:

答案 0 :(得分:4)

如果您从该文件中读取的字符串是SQL,则应该能够执行此操作:

sqlite3 cspdb ":memory:"

set f [open "csp_sql.txt"]
set sql [read $f]
close $f

cspdb eval $sql

相比之下,文字字符串$ms不是有效的SQL语句或查询,在语法上用括号包围SQL语句也不合法(这是"{$ms}"最终做的事情;外部" ... "使内部只是一堆字符。)

我不知道你为什么要把新行翻译成NUL,但那真的不太可能是个好主意。批量导入数据(可能包含NUL)应该以不同的方式完成。

答案 1 :(得分:1)

Sqlite创建的eval子命令确实限制了变量替换,但仅限于需要字符串值的地方。

尝试

cspdb eval $ms

让Tcl解释器在将SQL语句发送到eval之前替换它们。

答案 2 :(得分:0)

证明newline-to-null是导致替换失败的罪魁祸首。最终工作代码:

sqlite3 cspdb ":memory:"
cspdb eval [read [set f [open csp_sql.txt]]]

newline-to-null完全出现的原因是在尝试调试时使字符串匹配我使用多行字符串文字的原始工作C代码,其中使用了换行符。除了," \ 0"不是"消失"字符...