Как найти, какие прагмы SQLite вступают в силу во время компиляции SQL?

62
7

Согласно документам,

Некоторые прагмы вступают в силу во время этапа компиляции SQL, а не этапа выполнения. Это означает, что при использовании C-language sqlite3_prepare(), sqlite3_step(), sqlite3_finalize() API (или аналогичного в интерфейсе обертки), прагма может выполняться во время вызова sqlite3_prepare(), а не во время вызова sqlite3_step(), как обычный SQL заявления делают. Или прагма может работать во время sqlite3_step(), как и обычные инструкции SQL. Независимо от того, работает ли прагма во время sqlite3_prepare() или sqlite3_step(), зависит от прагмы и от конкретной версии SQLite.

Информация в последнем заявлении не приводится в документации для конкретных прагм. Предполагая, что я, тем не менее, заинтересован в том, чтобы найти его, по-видимому, я должен посмотреть на источник. Но где именно?

спросил(а) 2021-01-19T20:06:37+03:00 2 месяца, 3 недели назад
1
Решение
61

Все прагмы, которые реализуются базовой VFS, выполняются при разборе. (Но ни одна из предопределенных прагм не реализована в VFS.)

В противном случае, самый простой способ узнать - посмотреть на созданные виртуальные машинные инструкции прагмы. Некоторые прагмы ничего не делают в коде 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

Но обратите внимание, что неизвестные прагмы просто игнорируются:


> 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

Многие прагмы, которые просто возвращают значение, генерируют код с текущим значением во время разбора:


> 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

Но некоторые прагмы ищут ценность, когда они исполняются:


> 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

Существуют прагмы (например, default_cache_size), которые выполняются как в процессе анализа, так и во время выполнения; это обычно для значений, которые записываются в файл базы данных (такие записи могут выполняться только внутри транзакции).

Таким образом, самым безопасным способом является просмотр функции sqlite3Pragma в файле src/pragma.c.

ответил(а) 2021-01-19T20:06:37+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема