如何在SQL编译期间查找哪些SQLite pragma生效?

时间:2017-05-12 13:58:33

标签: sqlite

根据the docs

  

某些编译指示在SQL编译阶段生效,而不是执行阶段。这意味着如果使用C语言sqlite3_prepare(),sqlite3_step(),sqlite3_finalize()API(或包装器接口中的类似API),pragma可以在sqlite3_prepare()调用期间运行,而不是在sqlite3_step()调用期间作为普通SQL运行陈述呢。或者pragma可能在sqlite3_step()期间运行,就像普通的SQL语句一样。 pragma在sqlite3_prepare()或sqlite3_step()期间是否运行取决于pragma和SQLite的特定版本。

最后声明中的信息未在特定编译指示的文档中给出。假设我仍然有兴趣找到它,大概我要看源头。但到底在哪里?

1 个答案:

答案 0 :(得分:1)

解析时执行implemented by the underlying VFS的所有编译指示。 (但是在VFS中没有实现任何预定义的编译指示。)

否则,找出的最简单方法是在生成的look pragma中virtual machine instructions。 一些pragma在VDBE代码中没有做任何事情,这意味着它们在解析时完全执行(并且EXPLAIN不会阻止它):

> EXPLAIN PRAGMA page_size = 16384;
addr  opcode         p1    p2    p3    p4             p5  comment      
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     1     0                    00  Start at 1   
1     Halt           0     0     0                    00               

但请注意,未知的pragma只是被忽略了:

> EXPLAIN PRAGMA give_me_lots_of_money;
addr  opcode         p1    p2    p3    p4             p5  comment      
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     1     0                    00  Start at 1   
1     Halt           0     0     0                    00               

许多只返回值的pragma在解析时生成具有当前值的代码:

> EXPLAIN PRAGMA page_size;
addr  opcode         p1    p2    p3    p4             p5  comment      
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     1     0                    00  Start at 1   
1     Int64          0     1     0     16384          00  r[1]=16384   
2     ResultRow      1     1     0                    00  output=r[1]  
3     Halt           0     0     0                    00               

但是一些pragma在执行时会查找值:

> EXPLAIN PRAGMA user_version;
addr  opcode         p1    p2    p3    p4             p5  comment      
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     1     0                    00  Start at 1   
1     Transaction    0     0     0                    00               
2     ReadCookie     0     1     6                    00               
3     ResultRow      1     1     0                    00  output=r[1]  
4     Halt           0     0     0                    00               

可以使用VDBE代码实现一些编译指示:

> EXPLAIN PRAGMA foreign_key_check;
addr  opcode         p1    p2    p3    p4             p5  comment      
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     15    0                    00  Start at 15  
1     OpenRead       0     2     0     2              00  root=2 iDb=0; MyTable
2     String8        0     3     0     MyTable        00  r[3]='MyTable'
3     OpenRead       1     3     0     k(2,,)         00  root=3 iDb=0 
4     Rewind         0     14    0                    00               
5       Column         0     1     8                    00  r[8]=MyTable.Parent
6       IsNull         8     13    0                    00  if r[8]==NULL goto 13
7       MakeRecord     8     1     7     A              00  r[7]=mkrec(r[8])
8       Found          1     13    7     0              00  key=r[7]     
9       Rowid          0     4     0                    00  r[4]=rowid   
10      String8        0     5     0     MyTable        00  r[5]='MyTable'
11      Integer        0     6     0                    00  r[6]=0       
12      ResultRow      3     4     0                    00  output=r[3..6]
13    Next           0     5     0                    00               
14    Halt           0     0     0                    00               
15    Transaction    0     0     3     0              01  usesStmtJournal=0
16    Goto           0     1     0                    00               

pragma(例如,default_cache_size)在解析和执行时都执行;这通常适用于记录在数据库文件中的值(此类写入只能在事务中完成)。

所以最安全的方法是查看sqlite3Pragma文件中的src/pragma.c函数。