wasCSharpSQLite – Blame information for rev

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System;
2 using System.Diagnostics;
3 using System.Text;
4  
5 using i64 = System.Int64;
6 using u8 = System.Byte;
7  
8 using Pgno = System.UInt32;
9 using sqlite3_int64 = System.Int64;
10 using System.Globalization;
11  
12 namespace Community.CsharpSqlite
13 {
14 public partial class Sqlite3
15 {
16 /*
17 ** 2003 April 6
18 **
19 ** The author disclaims copyright to this source code. In place of
20 ** a legal notice, here is a blessing:
21 **
22 ** May you do good and not evil.
23 ** May you find forgiveness for yourself and forgive others.
24 ** May you share freely, never taking more than you give.
25 **
26 *************************************************************************
27 ** This file contains code used to implement the PRAGMA command.
28 *************************************************************************
29 ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
30 ** C#-SQLite is an independent reimplementation of the SQLite software library
31 **
32 ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2
33 **
34 *************************************************************************
35 */
36 //#include "sqliteInt.h"
37  
38 /*
39 ** Interpret the given string as a safety level. Return 0 for OFF,
40 ** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
41 ** unrecognized string argument.
42 **
43 ** Note that the values returned are one less that the values that
44 ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done
45 ** to support legacy SQL code. The safety level used to be boolean
46 ** and older scripts may have used numbers 0 for OFF and 1 for ON.
47 */
48 static u8 getSafetyLevel( string z )
49 {
50 // /* 123456789 123456789 */
51 string zText = "onoffalseyestruefull";
52 int[] iOffset = new int[] { 0, 1, 2, 4, 9, 12, 16 };
53 int[] iLength = new int[] { 2, 2, 3, 5, 3, 4, 4 };
54 u8[] iValue = new u8[] { 1, 0, 0, 0, 1, 1, 2 };
55 int i, n;
56 if ( sqlite3Isdigit( z[0] ) )
57 {
58 return (u8)sqlite3Atoi( z );
59 }
60 n = sqlite3Strlen30( z );
61 for ( i = 0; i < ArraySize( iLength ); i++ )
62 {
63 if ( iLength[i] == n && sqlite3StrNICmp( zText.Substring( iOffset[i] ), z, n ) == 0 )
64 {
65 return iValue[i];
66 }
67 }
68 return 1;
69 }
70  
71 /*
72 ** Interpret the given string as a boolean value.
73 */
74 static u8 sqlite3GetBoolean(string z){
75 return (u8)( getSafetyLevel( z ) & 1 );//return getSafetyLevel(z)&1;
76 }
77  
78 /* The sqlite3GetBoolean() function is used by other modules but the
79 ** remainder of this file is specific to PRAGMA processing. So omit
80 ** the rest of the file if PRAGMAs are omitted from the build.
81 */
82 #if !(SQLITE_OMIT_PRAGMA)
83  
84 /*
85 ** Interpret the given string as a locking mode value.
86 */
87 static int getLockingMode( string z )
88 {
89 if ( z != null )
90 {
91 if ( z.Equals( "exclusive" ,StringComparison.OrdinalIgnoreCase ) )
92 return PAGER_LOCKINGMODE_EXCLUSIVE;
93 if ( z.Equals( "normal" ,StringComparison.OrdinalIgnoreCase ) )
94 return PAGER_LOCKINGMODE_NORMAL;
95 }
96 return PAGER_LOCKINGMODE_QUERY;
97 }
98  
99 #if !SQLITE_OMIT_AUTOVACUUM
100 /*
101 ** Interpret the given string as an auto-vacuum mode value.
102 **
103 ** The following strings, "none", "full" and "incremental" are
104 ** acceptable, as are their numeric equivalents: 0, 1 and 2 respectively.
105 */
106 static u8 getAutoVacuum( string z )
107 {
108 int i;
109 if ( z.Equals( "none" ,StringComparison.OrdinalIgnoreCase ) )
110 return BTREE_AUTOVACUUM_NONE;
111 if ( z.Equals( "full" ,StringComparison.OrdinalIgnoreCase ) )
112 return BTREE_AUTOVACUUM_FULL;
113 if ( z.Equals( "incremental" ,StringComparison.OrdinalIgnoreCase ) )
114 return BTREE_AUTOVACUUM_INCR;
115 i = atoi( z );
116 return (u8)( ( i >= 0 && i <= 2 ) ? i : 0 );
117 }
118 #endif // * if !SQLITE_OMIT_AUTOVACUUM */
119  
120 #if !SQLITE_OMIT_PAGER_PRAGMAS
121 /*
122 ** Interpret the given string as a temp db location. Return 1 for file
123 ** backed temporary databases, 2 for the Red-Black tree in memory database
124 ** and 0 to use the compile-time default.
125 */
126 static int getTempStore( string z )
127 {
128 if ( z[0] >= '0' && z[0] <= '2' )
129 {
130 return z[0] - '0';
131 }
132 else if ( z.Equals( "file" ,StringComparison.OrdinalIgnoreCase ) )
133 {
134 return 1;
135 }
136 else if ( z.Equals( "memory" ,StringComparison.OrdinalIgnoreCase ) )
137 {
138 return 2;
139 }
140 else
141 {
142 return 0;
143 }
144 }
145 #endif // * SQLITE_PAGER_PRAGMAS */
146  
147 #if !SQLITE_OMIT_PAGER_PRAGMAS
148 /*
149 ** Invalidate temp storage, either when the temp storage is changed
150 ** from default, or when 'file' and the temp_store_directory has changed
151 */
152 static int invalidateTempStorage( Parse pParse )
153 {
154 sqlite3 db = pParse.db;
155 if ( db.aDb[1].pBt != null )
156 {
157 if ( 0 == db.autoCommit || sqlite3BtreeIsInReadTrans( db.aDb[1].pBt ) )
158 {
159 sqlite3ErrorMsg( pParse, "temporary storage cannot be changed " +
160 "from within a transaction" );
161 return SQLITE_ERROR;
162 }
163 sqlite3BtreeClose( ref db.aDb[1].pBt );
164 db.aDb[1].pBt = null;
165 sqlite3ResetInternalSchema( db, -1 );
166 }
167 return SQLITE_OK;
168 }
169 #endif // * SQLITE_PAGER_PRAGMAS */
170  
171 #if !SQLITE_OMIT_PAGER_PRAGMAS
172 /*
173 ** If the TEMP database is open, close it and mark the database schema
174 ** as needing reloading. This must be done when using the SQLITE_TEMP_STORE
175 ** or DEFAULT_TEMP_STORE pragmas.
176 */
177 static int changeTempStorage( Parse pParse, string zStorageType )
178 {
179 int ts = getTempStore( zStorageType );
180 sqlite3 db = pParse.db;
181 if ( db.temp_store == ts )
182 return SQLITE_OK;
183 if ( invalidateTempStorage( pParse ) != SQLITE_OK )
184 {
185 return SQLITE_ERROR;
186 }
187 db.temp_store = (u8)ts;
188 return SQLITE_OK;
189 }
190 #endif // * SQLITE_PAGER_PRAGMAS */
191  
192 /*
193 ** Generate code to return a single integer value.
194 */
195 static void returnSingleInt( Parse pParse, string zLabel, i64 value )
196 {
197 Vdbe v = sqlite3GetVdbe( pParse );
198 int mem = ++pParse.nMem;
199 //i64* pI64 = sqlite3DbMallocRaw( pParse->db, sizeof( value ) );
200 //if ( pI64 )
201 //{
202 // memcpy( pI64, &value, sizeof( value ) );
203 //}
204 //sqlite3VdbeAddOp4( v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64 );
205 sqlite3VdbeAddOp4( v, OP_Int64, 0, mem, 0, value, P4_INT64 );
206 sqlite3VdbeSetNumCols( v, 1 );
207 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC );
208 sqlite3VdbeAddOp2( v, OP_ResultRow, mem, 1 );
209 }
210  
211 #if !SQLITE_OMIT_FLAG_PRAGMAS
212 /*
213 ** Check to see if zRight and zLeft refer to a pragma that queries
214 ** or changes one of the flags in db.flags. Return 1 if so and 0 if not.
215 ** Also, implement the pragma.
216 */
217 struct sPragmaType
218 {
219 public string zName; /* Name of the pragma */
220 public int mask; /* Mask for the db.flags value */
221 public sPragmaType( string zName, int mask )
222 {
223 this.zName = zName;
224 this.mask = mask;
225 }
226 }
227 static int flagPragma( Parse pParse, string zLeft, string zRight )
228 {
229 sPragmaType[] aPragma = new sPragmaType[]{
230 new sPragmaType( "full_column_names", SQLITE_FullColNames ),
231 new sPragmaType( "short_column_names", SQLITE_ShortColNames ),
232 new sPragmaType( "count_changes", SQLITE_CountRows ),
233 new sPragmaType( "empty_result_callbacks", SQLITE_NullCallback ),
234 new sPragmaType( "legacy_file_format", SQLITE_LegacyFileFmt ),
235 new sPragmaType( "fullfsync", SQLITE_FullFSync ),
236 new sPragmaType( "checkpoint_fullfsync", SQLITE_CkptFullFSync ),
237 new sPragmaType( "reverse_unordered_selects", SQLITE_ReverseOrder),
238 #if !SQLITE_OMIT_AUTOMATIC_INDEX
239 new sPragmaType( "automatic_index", SQLITE_AutoIndex ),
240 #endif
241 #if SQLITE_DEBUG
242 new sPragmaType( "sql_trace", SQLITE_SqlTrace ),
243 new sPragmaType( "vdbe_listing", SQLITE_VdbeListing ),
244 new sPragmaType( "vdbe_trace", SQLITE_VdbeTrace ),
245 #endif
246 #if !SQLITE_OMIT_CHECK
247 new sPragmaType( "ignore_check_constraints", SQLITE_IgnoreChecks ),
248 #endif
249 /* The following is VERY experimental */
250 new sPragmaType( "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode ),
251 new sPragmaType( "omit_readlock", SQLITE_NoReadlock ),
252  
253 /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
254 ** flag if there are any active statements. */
255 new sPragmaType( "read_uncommitted", SQLITE_ReadUncommitted ),
256 new sPragmaType( "recursive_triggers", SQLITE_RecTriggers ),
257  
258 /* This flag may only be set if both foreign-key and trigger support
259 ** are present in the build. */
260 #if !(SQLITE_OMIT_FOREIGN_KEY) && !(SQLITE_OMIT_TRIGGER)
261 new sPragmaType( "foreign_keys", SQLITE_ForeignKeys ),
262 #endif
263 };
264 int i;
265 sPragmaType p;
266 for ( i = 0; i < ArraySize( aPragma ); i++ )//, p++)
267 {
268 p = aPragma[i];
269 if ( zLeft.Equals( p.zName ,StringComparison.OrdinalIgnoreCase ) )
270 {
271 sqlite3 db = pParse.db;
272 Vdbe v;
273 v = sqlite3GetVdbe( pParse );
274 Debug.Assert( v != null ); /* Already allocated by sqlite3Pragma() */
275 if ( ALWAYS( v ) )
276 {
277 if ( null == zRight )
278 {
279 returnSingleInt( pParse, p.zName, ( ( db.flags & p.mask ) != 0 ) ? 1 : 0 );
280 }
281 else
282 {
283 int mask = p.mask; /* Mask of bits to set or clear. */
284 if ( db.autoCommit == 0 )
285 {
286 /* Foreign key support may not be enabled or disabled while not
287 ** in auto-commit mode. */
288 mask &= ~( SQLITE_ForeignKeys );
289 }
290 if ( sqlite3GetBoolean( zRight ) != 0 )
291 {
292 db.flags |= mask;
293 }
294 else
295 {
296 db.flags &= ~mask;
297 }
298  
299 /* Many of the flag-pragmas modify the code generated by the SQL
300 ** compiler (eg. count_changes). So add an opcode to expire all
301 ** compiled SQL statements after modifying a pragma value.
302 */
303 sqlite3VdbeAddOp2( v, OP_Expire, 0, 0 );
304 }
305 }
306  
307 return 1;
308 }
309 }
310 return 0;
311 }
312 #endif // * SQLITE_OMIT_FLAG_PRAGMAS */
313  
314 /*
315 ** Return a human-readable name for a constraint resolution action.
316 */
317 #if !SQLITE_OMIT_FOREIGN_KEY
318 static string actionName( int action )
319 {
320 string zName;
321 switch ( action )
322 {
323 case OE_SetNull:
324 zName = "SET NULL";
325 break;
326 case OE_SetDflt:
327 zName = "SET DEFAULT";
328 break;
329 case OE_Cascade:
330 zName = "CASCADE";
331 break;
332 case OE_Restrict:
333 zName = "RESTRICT";
334 break;
335 default:
336 zName = "NO ACTION";
337 Debug.Assert( action == OE_None );
338 break;
339 }
340 return zName;
341 }
342 #endif
343  
344 /*
345 ** Parameter eMode must be one of the PAGER_JOURNALMODE_XXX constants
346 ** defined in pager.h. This function returns the associated lowercase
347 ** journal-mode name.
348 */
349 static string sqlite3JournalModename( int eMode )
350 {
351 string[] azModeName = {
352 "delete", "persist", "off", "truncate", "memory"
353 #if !SQLITE_OMIT_WAL
354 , "wal"
355 #endif
356 };
357 Debug.Assert( PAGER_JOURNALMODE_DELETE == 0 );
358 Debug.Assert( PAGER_JOURNALMODE_PERSIST == 1 );
359 Debug.Assert( PAGER_JOURNALMODE_OFF == 2 );
360 Debug.Assert( PAGER_JOURNALMODE_TRUNCATE == 3 );
361 Debug.Assert( PAGER_JOURNALMODE_MEMORY == 4 );
362 Debug.Assert( PAGER_JOURNALMODE_WAL == 5 );
363 Debug.Assert( eMode >= 0 && eMode <= ArraySize( azModeName ) );
364  
365 if ( eMode == ArraySize( azModeName ) )
366 return null;
367 return azModeName[eMode];
368 }
369  
370 /*
371 ** Process a pragma statement.
372 **
373 ** Pragmas are of this form:
374 **
375 ** PRAGMA [database.]id [= value]
376 **
377 ** The identifier might also be a string. The value is a string, and
378 ** identifier, or a number. If minusFlag is true, then the value is
379 ** a number that was preceded by a minus sign.
380 **
381 ** If the left side is "database.id" then pId1 is the database name
382 ** and pId2 is the id. If the left side is just "id" then pId1 is the
383 ** id and pId2 is any empty string.
384 */
385 class EncName
386 {
387 public string zName;
388 public u8 enc;
389  
390 public EncName( string zName, u8 enc )
391 {
392 this.zName = zName;
393 this.enc = enc;
394 }
395 };
396  
397 static EncName[] encnames = new EncName[] {
398 new EncName( "UTF8", SQLITE_UTF8 ),
399 new EncName( "UTF-8", SQLITE_UTF8 ),/* Must be element [1] */
400 new EncName( "UTF-16le (not supported)", SQLITE_UTF16LE ),/* Must be element [2] */
401 new EncName( "UTF-16be (not supported)", SQLITE_UTF16BE ), /* Must be element [3] */
402 new EncName( "UTF16le (not supported)", SQLITE_UTF16LE ),
403 new EncName( "UTF16be (not supported)", SQLITE_UTF16BE ),
404 new EncName( "UTF-16 (not supported)", 0 ), /* SQLITE_UTF16NATIVE */
405 new EncName( "UTF16", 0 ), /* SQLITE_UTF16NATIVE */
406 new EncName( null, 0 )
407 };
408  
409 // OVERLOADS, so I don't need to rewrite parse.c
410 static void sqlite3Pragma( Parse pParse, Token pId1, Token pId2, int null_4, int minusFlag )
411 {
412 sqlite3Pragma( pParse, pId1, pId2, null, minusFlag );
413 }
414 static void sqlite3Pragma(
415 Parse pParse,
416 Token pId1, /* First part of [database.]id field */
417 Token pId2, /* Second part of [database.]id field, or NULL */
418 Token pValue, /* Token for <value>, or NULL */
419 int minusFlag /* True if a '-' sign preceded <value> */
420 )
421 {
422 string zLeft = null; /* Nul-terminated UTF-8 string <id> */
423 string zRight = null; /* Nul-terminated UTF-8 string <value>, or NULL */
424 string zDb = null; /* The database name */
425 Token pId = new Token();/* Pointer to <id> token */
426 int iDb; /* Database index for <database> */
427 sqlite3 db = pParse.db;
428 Db pDb;
429 Vdbe v = pParse.pVdbe = sqlite3VdbeCreate( db );
430 if ( v == null )
431 return;
432 sqlite3VdbeRunOnlyOnce( v );
433 pParse.nMem = 2;
434  
435 /* Interpret the [database.] part of the pragma statement. iDb is the
436 ** index of the database this pragma is being applied to in db.aDb[]. */
437 iDb = sqlite3TwoPartName( pParse, pId1, pId2, ref pId );
438 if ( iDb < 0 )
439 return;
440 pDb = db.aDb[iDb];
441  
442 /* If the temp database has been explicitly named as part of the
443 ** pragma, make sure it is open.
444 */
445 if ( iDb == 1 && sqlite3OpenTempDatabase( pParse ) != 0 )
446 {
447 return;
448 }
449  
450 zLeft = sqlite3NameFromToken( db, pId );
451 if ( zLeft.Length == 0 )
452 return;
453 if ( minusFlag != 0 )
454 {
455 zRight = ( pValue == null ) ? string.Empty : sqlite3MPrintf( db, "-%T", pValue );
456 }
457 else
458 {
459 zRight = sqlite3NameFromToken( db, pValue );
460 }
461  
462 Debug.Assert( pId2 != null );
463 zDb = pId2.n > 0 ? pDb.zName : null;
464 #if !SQLITE_OMIT_AUTHORIZATION
465 if ( sqlite3AuthCheck( pParse, SQLITE_PRAGMA, zLeft, zRight, zDb ) )
466 {
467 goto pragma_out;
468 }
469 #endif
470 #if !SQLITE_OMIT_PAGER_PRAGMAS
471 /*
472 ** PRAGMA [database.]default_cache_size
473 ** PRAGMA [database.]default_cache_size=N
474 **
475 ** The first form reports the current persistent setting for the
476 ** page cache size. The value returned is the maximum number of
477 ** pages in the page cache. The second form sets both the current
478 ** page cache size value and the persistent page cache size value
479 ** stored in the database file.
480 **
481 ** Older versions of SQLite would set the default cache size to a
482 ** negative number to indicate synchronous=OFF. These days, synchronous
483 ** is always on by default regardless of the sign of the default cache
484 ** size. But continue to take the absolute value of the default cache
485 ** size of historical compatibility.
486 */
487 if ( zLeft.Equals( "default_cache_size" ,StringComparison.OrdinalIgnoreCase ) )
488 {
489 VdbeOpList[] getCacheSize = new VdbeOpList[]{
490 new VdbeOpList( OP_Transaction, 0, 0, 0), /* 0 */
491 new VdbeOpList( OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE), /* 1 */
492 new VdbeOpList( OP_IfPos, 1, 7, 0),
493 new VdbeOpList( OP_Integer, 0, 2, 0),
494 new VdbeOpList( OP_Subtract, 1, 2, 1),
495 new VdbeOpList( OP_IfPos, 1, 7, 0),
496 new VdbeOpList( OP_Integer, 0, 1, 0), /* 6 */
497 new VdbeOpList( OP_ResultRow, 1, 1, 0),
498 };
499 int addr;
500 if ( sqlite3ReadSchema( pParse ) != 0 )
501 goto pragma_out;
502 sqlite3VdbeUsesBtree( v, iDb );
503 if ( null == zRight )
504 {
505 sqlite3VdbeSetNumCols( v, 1 );
506 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC );
507 pParse.nMem += 2;
508 addr = sqlite3VdbeAddOpList( v, getCacheSize.Length, getCacheSize );
509 sqlite3VdbeChangeP1( v, addr, iDb );
510 sqlite3VdbeChangeP1( v, addr + 1, iDb );
511 sqlite3VdbeChangeP1( v, addr + 6, SQLITE_DEFAULT_CACHE_SIZE );
512 }
513 else
514 {
515 int size = sqlite3AbsInt32(sqlite3Atoi( zRight ));
516 sqlite3BeginWriteOperation( pParse, 0, iDb );
517 sqlite3VdbeAddOp2( v, OP_Integer, size, 1 );
518 sqlite3VdbeAddOp3( v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1 );
519 Debug.Assert( sqlite3SchemaMutexHeld( db, iDb, null ) );
520 pDb.pSchema.cache_size = size;
521 sqlite3BtreeSetCacheSize( pDb.pBt, pDb.pSchema.cache_size );
522 }
523 }
524 else
525  
526 /*
527 ** PRAGMA [database.]page_size
528 ** PRAGMA [database.]page_size=N
529 **
530 ** The first form reports the current setting for the
531 ** database page size in bytes. The second form sets the
532 ** database page size value. The value can only be set if
533 ** the database has not yet been created.
534 */
535 if ( zLeft.Equals( "page_size" ,StringComparison.OrdinalIgnoreCase ) )
536 {
537 Btree pBt = pDb.pBt;
538 Debug.Assert( pBt != null );
539 if ( null == zRight )
540 {
541 int size = ALWAYS( pBt ) ? sqlite3BtreeGetPageSize( pBt ) : 0;
542 returnSingleInt( pParse, "page_size", size );
543 }
544 else
545 {
546 /* Malloc may fail when setting the page-size, as there is an internal
547 ** buffer that the pager module resizes using sqlite3_realloc().
548 */
549 db.nextPagesize = sqlite3Atoi( zRight );
550 if ( SQLITE_NOMEM == sqlite3BtreeSetPageSize( pBt, db.nextPagesize, -1, 0 ) )
551 {
552 //// db.mallocFailed = 1;
553 }
554 }
555 }
556 else
557  
558 /*
559 ** PRAGMA [database.]secure_delete
560 ** PRAGMA [database.]secure_delete=ON/OFF
561 **
562 ** The first form reports the current setting for the
563 ** secure_delete flag. The second form changes the secure_delete
564 ** flag setting and reports thenew value.
565 */
566 if ( zLeft.Equals( "secure_delete" ,StringComparison.OrdinalIgnoreCase ) )
567 {
568 Btree pBt = pDb.pBt;
569 int b = -1;
570 Debug.Assert( pBt != null );
571 if ( zRight != null )
572 {
573 b = sqlite3GetBoolean( zRight );
574 }
575 if ( pId2.n == 0 && b >= 0 )
576 {
577 int ii;
578 for ( ii = 0; ii < db.nDb; ii++ )
579 {
580 sqlite3BtreeSecureDelete( db.aDb[ii].pBt, b );
581 }
582 }
583 b = sqlite3BtreeSecureDelete( pBt, b );
584 returnSingleInt( pParse, "secure_delete", b );
585 }
586 else
587 /*
588 ** PRAGMA [database.]max_page_count
589 ** PRAGMA [database.]max_page_count=N
590 **
591 ** The first form reports the current setting for the
592 ** maximum number of pages in the database file. The
593 ** second form attempts to change this setting. Both
594 ** forms return the current setting.
595 **
596 ** PRAGMA [database.]page_count
597 **
598 ** Return the number of pages in the specified database.
599 */
600 if ( zLeft.Equals( "page_count" ,StringComparison.OrdinalIgnoreCase )
601 || zLeft.Equals( "max_page_count" ,StringComparison.OrdinalIgnoreCase )
602 )
603 {
604 int iReg;
605 if ( sqlite3ReadSchema( pParse ) != 0 )
606 goto pragma_out;
607 sqlite3CodeVerifySchema( pParse, iDb );
608 iReg = ++pParse.nMem;
609 if ( zLeft[0] == 'p' )
610 {
611 sqlite3VdbeAddOp2( v, OP_Pagecount, iDb, iReg );
612 }
613 else
614 {
615 sqlite3VdbeAddOp3( v, OP_MaxPgcnt, iDb, iReg, sqlite3Atoi( zRight ) );
616 }
617 sqlite3VdbeAddOp2( v, OP_ResultRow, iReg, 1 );
618 sqlite3VdbeSetNumCols( v, 1 );
619 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT );
620 }
621 else
622  
623 /*
624 ** PRAGMA [database.]page_count
625 **
626 ** Return the number of pages in the specified database.
627 */
628 if ( zLeft == "page_count" )
629 {
630 Vdbe _v;
631 int iReg;
632 _v = sqlite3GetVdbe( pParse );
633 if ( _v == null || sqlite3ReadSchema( pParse ) != 0 )
634 goto pragma_out;
635 sqlite3CodeVerifySchema( pParse, iDb );
636 iReg = ++pParse.nMem;
637 sqlite3VdbeAddOp2( _v, OP_Pagecount, iDb, iReg );
638 sqlite3VdbeAddOp2( _v, OP_ResultRow, iReg, 1 );
639 sqlite3VdbeSetNumCols( _v, 1 );
640 sqlite3VdbeSetColName( _v, 0, COLNAME_NAME, "page_count", SQLITE_STATIC );
641 }
642 else
643  
644 /*
645 ** PRAGMA [database.]locking_mode
646 ** PRAGMA [database.]locking_mode = (normal|exclusive)
647 */
648 if ( zLeft.Equals( "locking_mode" ,StringComparison.OrdinalIgnoreCase ) )
649 {
650 string zRet = "normal";
651 int eMode = getLockingMode( zRight );
652  
653 if ( pId2.n == 0 && eMode == PAGER_LOCKINGMODE_QUERY )
654 {
655 /* Simple "PRAGMA locking_mode;" statement. This is a query for
656 ** the current default locking mode (which may be different to
657 ** the locking-mode of the main database).
658 */
659 eMode = db.dfltLockMode;
660 }
661 else
662 {
663 Pager pPager;
664 if ( pId2.n == 0 )
665 {
666 /* This indicates that no database name was specified as part
667 ** of the PRAGMA command. In this case the locking-mode must be
668 ** set on all attached databases, as well as the main db file.
669 **
670 ** Also, the sqlite3.dfltLockMode variable is set so that
671 ** any subsequently attached databases also use the specified
672 ** locking mode.
673 */
674 int ii;
675 Debug.Assert( pDb == db.aDb[0] );
676 for ( ii = 2; ii < db.nDb; ii++ )
677 {
678 pPager = sqlite3BtreePager( db.aDb[ii].pBt );
679 sqlite3PagerLockingMode( pPager, eMode );
680 }
681 db.dfltLockMode = (u8)eMode;
682 }
683 pPager = sqlite3BtreePager( pDb.pBt );
684 eMode = sqlite3PagerLockingMode( pPager, eMode ) ? 1 : 0;
685 }
686  
687 Debug.Assert( eMode == PAGER_LOCKINGMODE_NORMAL || eMode == PAGER_LOCKINGMODE_EXCLUSIVE );
688 if ( eMode == PAGER_LOCKINGMODE_EXCLUSIVE )
689 {
690 zRet = "exclusive";
691 }
692 sqlite3VdbeSetNumCols( v, 1 );
693 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "locking_mode", SQLITE_STATIC );
694 sqlite3VdbeAddOp4( v, OP_String8, 0, 1, 0, zRet, 0 );
695 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 1 );
696 }
697 else
698 /*
699 ** PRAGMA [database.]journal_mode
700 ** PRAGMA [database.]journal_mode =
701 ** (delete|persist|off|truncate|memory|wal|off)
702 */
703 if ( zLeft == "journal_mode" )
704 {
705 int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
706 int ii; /* Loop counter */
707  
708 /* Force the schema to be loaded on all databases. This cases all
709 ** database files to be opened and the journal_modes set. */
710 if ( sqlite3ReadSchema( pParse ) != 0 )
711 {
712 goto pragma_out;
713 }
714  
715 sqlite3VdbeSetNumCols( v, 1 );
716 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC );
717 if ( null == zRight )
718 {
719 /* If there is no "=MODE" part of the pragma, do a query for the
720 ** current mode */
721 eMode = PAGER_JOURNALMODE_QUERY;
722 }
723 else
724 {
725 string zMode;
726 int n = sqlite3Strlen30( zRight );
727 for ( eMode = 0; ( zMode = sqlite3JournalModename( eMode ) ) != null; eMode++ )
728 {
729 if ( sqlite3StrNICmp( zRight, zMode, n ) == 0 )
730 break;
731 }
732 if ( null == zMode )
733 {
734 /* If the "=MODE" part does not match any known journal mode,
735 ** then do a query */
736 eMode = PAGER_JOURNALMODE_QUERY;
737 }
738 }
739 if ( eMode == PAGER_JOURNALMODE_QUERY && pId2.n == 0 )
740 {
741 /* Convert "PRAGMA journal_mode" into "PRAGMA main.journal_mode" */
742 iDb = 0;
743 pId2.n = 1;
744 }
745 for ( ii = db.nDb - 1; ii >= 0; ii-- )
746 {
747 if ( db.aDb[ii].pBt != null && ( ii == iDb || pId2.n == 0 ) )
748 {
749 sqlite3VdbeUsesBtree( v, ii );
750 sqlite3VdbeAddOp3( v, OP_JournalMode, ii, 1, eMode );
751 }
752 }
753 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 1 );
754 }
755 else
756  
757 /*
758 ** PRAGMA [database.]journal_size_limit
759 ** PRAGMA [database.]journal_size_limit=N
760 **
761 ** Get or set the size limit on rollback journal files.
762 */
763 if ( zLeft.Equals( "journal_size_limit" ,StringComparison.OrdinalIgnoreCase ) )
764 {
765 Pager pPager = sqlite3BtreePager( pDb.pBt );
766 i64 iLimit = -2;
767 if ( !string.IsNullOrEmpty( zRight ) )
768 {
769 sqlite3Atoi64( zRight, ref iLimit, 1000000, SQLITE_UTF8 );
770 if ( iLimit < -1 )
771 iLimit = -1;
772 }
773 iLimit = sqlite3PagerJournalSizeLimit( pPager, iLimit );
774 returnSingleInt( pParse, "journal_size_limit", iLimit );
775 }
776 else
777  
778 #endif // * SQLITE_OMIT_PAGER_PRAGMAS */
779  
780 /*
781 ** PRAGMA [database.]auto_vacuum
782 ** PRAGMA [database.]auto_vacuum=N
783 **
784 ** Get or set the value of the database 'auto-vacuum' parameter.
785 ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL
786 */
787 #if !SQLITE_OMIT_AUTOVACUUM
788 if ( zLeft.Equals( "auto_vacuum" ,StringComparison.OrdinalIgnoreCase ) )
789 {
790 Btree pBt = pDb.pBt;
791 Debug.Assert( pBt != null );
792 if ( sqlite3ReadSchema( pParse ) != 0 )
793 {
794 goto pragma_out;
795 }
796 if ( null == zRight )
797 {
798 int auto_vacuum;
799 if ( ALWAYS( pBt ) )
800 {
801 auto_vacuum = sqlite3BtreeGetAutoVacuum( pBt );
802 }
803 else
804 {
805 auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM;
806 }
807 returnSingleInt( pParse, "auto_vacuum", auto_vacuum );
808 }
809 else
810 {
811 int eAuto = getAutoVacuum( zRight );
812 Debug.Assert( eAuto >= 0 && eAuto <= 2 );
813 db.nextAutovac = (u8)eAuto;
814 if ( ALWAYS( eAuto >= 0 ) )
815 {
816 /* Call SetAutoVacuum() to set initialize the internal auto and
817 ** incr-vacuum flags. This is required in case this connection
818 ** creates the database file. It is important that it is created
819 ** as an auto-vacuum capable db.
820 */
821 int rc = sqlite3BtreeSetAutoVacuum( pBt, eAuto );
822 if ( rc == SQLITE_OK && ( eAuto == 1 || eAuto == 2 ) )
823 {
824 /* When setting the auto_vacuum mode to either "full" or
825 ** "incremental", write the value of meta[6] in the database
826 ** file. Before writing to meta[6], check that meta[3] indicates
827 ** that this really is an auto-vacuum capable database.
828 */
829 VdbeOpList[] setMeta6 = new VdbeOpList[] {
830 new VdbeOpList( OP_Transaction, 0, 1, 0), /* 0 */
831 new VdbeOpList( OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE), /* 1 */
832 new VdbeOpList( OP_If, 1, 0, 0), /* 2 */
833 new VdbeOpList( OP_Halt, SQLITE_OK, OE_Abort, 0), /* 3 */
834 new VdbeOpList( OP_Integer, 0, 1, 0), /* 4 */
835 new VdbeOpList( OP_SetCookie, 0, BTREE_INCR_VACUUM, 1), /* 5 */
836 };
837 int iAddr;
838 iAddr = sqlite3VdbeAddOpList( v, ArraySize( setMeta6 ), setMeta6 );
839 sqlite3VdbeChangeP1( v, iAddr, iDb );
840 sqlite3VdbeChangeP1( v, iAddr + 1, iDb );
841 sqlite3VdbeChangeP2( v, iAddr + 2, iAddr + 4 );
842 sqlite3VdbeChangeP1( v, iAddr + 4, eAuto - 1 );
843 sqlite3VdbeChangeP1( v, iAddr + 5, iDb );
844 sqlite3VdbeUsesBtree( v, iDb );
845 }
846 }
847 }
848 }
849 else
850 #endif
851  
852 /*
853 ** PRAGMA [database.]incremental_vacuum(N)
854 **
855 ** Do N steps of incremental vacuuming on a database.
856 */
857 #if !SQLITE_OMIT_AUTOVACUUM
858 if ( zLeft.Equals( "incremental_vacuum" ,StringComparison.OrdinalIgnoreCase ) )
859 {
860 int iLimit = 0, addr;
861 if ( sqlite3ReadSchema( pParse ) != 0 )
862 {
863 goto pragma_out;
864 }
865 if ( zRight == null || !sqlite3GetInt32( zRight, ref iLimit ) || iLimit <= 0 )
866 {
867 iLimit = 0x7fffffff;
868 }
869 sqlite3BeginWriteOperation( pParse, 0, iDb );
870 sqlite3VdbeAddOp2( v, OP_Integer, iLimit, 1 );
871 addr = sqlite3VdbeAddOp1( v, OP_IncrVacuum, iDb );
872 sqlite3VdbeAddOp1( v, OP_ResultRow, 1 );
873 sqlite3VdbeAddOp2( v, OP_AddImm, 1, -1 );
874 sqlite3VdbeAddOp2( v, OP_IfPos, 1, addr );
875 sqlite3VdbeJumpHere( v, addr );
876 }
877 else
878 #endif
879  
880 #if !SQLITE_OMIT_PAGER_PRAGMAS
881 /*
882 ** PRAGMA [database.]cache_size
883 ** PRAGMA [database.]cache_size=N
884 **
885 ** The first form reports the current local setting for the
886 ** page cache size. The local setting can be different from
887 ** the persistent cache size value that is stored in the database
888 ** file itself. The value returned is the maximum number of
889 ** pages in the page cache. The second form sets the local
890 ** page cache size value. It does not change the persistent
891 ** cache size stored on the disk so the cache size will revert
892 ** to its default value when the database is closed and reopened.
893 ** N should be a positive integer.
894 */
895 if ( zLeft.Equals( "cache_size" ,StringComparison.OrdinalIgnoreCase ) )
896 {
897 if ( sqlite3ReadSchema( pParse ) != 0 )
898 goto pragma_out;
899 Debug.Assert( sqlite3SchemaMutexHeld( db, iDb, null ) );
900 if ( null == zRight )
901 {
902 returnSingleInt( pParse, "cache_size", pDb.pSchema.cache_size );
903 }
904 else
905 {
906 int size = sqlite3AbsInt32(sqlite3Atoi( zRight ));
907 pDb.pSchema.cache_size = size;
908 sqlite3BtreeSetCacheSize( pDb.pBt, pDb.pSchema.cache_size );
909 }
910 }
911 else
912  
913 /*
914 ** PRAGMA temp_store
915 ** PRAGMA temp_store = "default"|"memory"|"file"
916 **
917 ** Return or set the local value of the temp_store flag. Changing
918 ** the local value does not make changes to the disk file and the default
919 ** value will be restored the next time the database is opened.
920 **
921 ** Note that it is possible for the library compile-time options to
922 ** override this setting
923 */
924 if ( zLeft.Equals( "temp_store" ,StringComparison.OrdinalIgnoreCase ) )
925 {
926 if ( zRight == null )
927 {
928 returnSingleInt( pParse, "temp_store", db.temp_store );
929 }
930 else
931 {
932 changeTempStorage( pParse, zRight );
933 }
934 }
935 else
936  
937 /*
938 ** PRAGMA temp_store_directory
939 ** PRAGMA temp_store_directory = ""|"directory_name"
940 **
941 ** Return or set the local value of the temp_store_directory flag. Changing
942 ** the value sets a specific directory to be used for temporary files.
943 ** Setting to a null string reverts to the default temporary directory search.
944 ** If temporary directory is changed, then invalidateTempStorage.
945 **
946 */
947 if ( zLeft.Equals( "temp_store_directory" ,StringComparison.OrdinalIgnoreCase ) )
948 {
949 if ( null == zRight )
950 {
951 if ( sqlite3_temp_directory.Length > 0 )
952 {
953 sqlite3VdbeSetNumCols( v, 1 );
954 sqlite3VdbeSetColName( v, 0, COLNAME_NAME,
955 "temp_store_directory", SQLITE_STATIC );
956 sqlite3VdbeAddOp4( v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0 );
957 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 1 );
958 }
959 }
960 else
961 {
962 #if !SQLITE_OMIT_WSD
963 if ( zRight.Length > 0 )
964 {
965 int rc;
966 int res = 0;
967 rc = sqlite3OsAccess( db.pVfs, zRight, SQLITE_ACCESS_READWRITE, ref res );
968 if ( rc != SQLITE_OK || res == 0 )
969 {
970 sqlite3ErrorMsg( pParse, "not a writable directory" );
971 goto pragma_out;
972 }
973 }
974 if ( SQLITE_TEMP_STORE == 0
975 || ( SQLITE_TEMP_STORE == 1 && db.temp_store <= 1 )
976 || ( SQLITE_TEMP_STORE == 2 && db.temp_store == 1 )
977 )
978 {
979 invalidateTempStorage( pParse );
980 }
981 //sqlite3_free( ref sqlite3_temp_directory );
982 if ( zRight.Length > 0 )
983 {
984 sqlite3_temp_directory = zRight;//sqlite3_mprintf("%s", zRight);
985 }
986 else
987 {
988 sqlite3_temp_directory = string.Empty;
989 }
990 #endif //* SQLITE_OMIT_WSD */
991 }
992 }
993 else
994  
995 #if !(SQLITE_ENABLE_LOCKING_STYLE)
996 # if (__APPLE__)
997 //# define SQLITE_ENABLE_LOCKING_STYLE 1
998 # else
999 //# define SQLITE_ENABLE_LOCKING_STYLE 0
1000 # endif
1001 #endif
1002 #if SQLITE_ENABLE_LOCKING_STYLE
1003 /*
1004 ** PRAGMA [database.]lock_proxy_file
1005 ** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path"
1006 **
1007 ** Return or set the value of the lock_proxy_file flag. Changing
1008 ** the value sets a specific file to be used for database access locks.
1009 **
1010 */
1011 if ( zLeft.Equals( "lock_proxy_file" ,StringComparison.OrdinalIgnoreCase ) )
1012 {
1013 if ( zRight != string.Empty)
1014 {
1015 Pager pPager = sqlite3BtreePager( pDb.pBt );
1016 int proxy_file_path = 0;
1017 sqlite3_file pFile = sqlite3PagerFile( pPager );
1018 sqlite3OsFileControl( pFile, SQLITE_GET_LOCKPROXYFILE,
1019 ref proxy_file_path );
1020  
1021 if ( proxy_file_path!=0 )
1022 {
1023 sqlite3VdbeSetNumCols( v, 1 );
1024 sqlite3VdbeSetColName( v, 0, COLNAME_NAME,
1025 "lock_proxy_file", SQLITE_STATIC );
1026 sqlite3VdbeAddOp4( v, OP_String8, 0, 1, 0, proxy_file_path, 0 );
1027 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 1 );
1028 }
1029 }
1030 else
1031 {
1032 Pager pPager = sqlite3BtreePager( pDb.pBt );
1033 sqlite3_file pFile = sqlite3PagerFile( pPager );
1034 int res;
1035 int iDummy = 0;
1036 if ( zRight[0]!=0 )
1037 {
1038 iDummy = zRight[0];
1039 res = sqlite3OsFileControl( pFile, SQLITE_SET_LOCKPROXYFILE,
1040 ref iDummy );
1041 }
1042 else
1043 {
1044 res = sqlite3OsFileControl( pFile, SQLITE_SET_LOCKPROXYFILE,
1045 ref iDummy );
1046 }
1047 if ( res != SQLITE_OK )
1048 {
1049 sqlite3ErrorMsg( pParse, "failed to set lock proxy file" );
1050 goto pragma_out;
1051 }
1052 }
1053 }
1054 else
1055 #endif //* SQLITE_ENABLE_LOCKING_STYLE */
1056  
1057 /*
1058 ** PRAGMA [database.]synchronous
1059 ** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL
1060 **
1061 ** Return or set the local value of the synchronous flag. Changing
1062 ** the local value does not make changes to the disk file and the
1063 ** default value will be restored the next time the database is
1064 ** opened.
1065 */
1066 if ( zLeft.Equals( "synchronous" ,StringComparison.OrdinalIgnoreCase ) )
1067 {
1068 if ( sqlite3ReadSchema( pParse ) != 0 )
1069 goto pragma_out;
1070 if ( null == zRight )
1071 {
1072 returnSingleInt( pParse, "synchronous", pDb.safety_level - 1 );
1073 }
1074 else
1075 {
1076 if ( 0 == db.autoCommit )
1077 {
1078 sqlite3ErrorMsg( pParse,
1079 "Safety level may not be changed inside a transaction" );
1080 }
1081 else
1082 {
1083 pDb.safety_level = (byte)( getSafetyLevel( zRight ) + 1 );
1084 }
1085 }
1086 }
1087 else
1088 #endif // * SQLITE_OMIT_PAGER_PRAGMAS */
1089  
1090 #if !SQLITE_OMIT_FLAG_PRAGMAS
1091 if ( flagPragma( pParse, zLeft, zRight ) != 0 )
1092 {
1093 /* The flagPragma() subroutine also generates any necessary code
1094 ** there is nothing more to do here */
1095 }
1096 else
1097 #endif // * SQLITE_OMIT_FLAG_PRAGMAS */
1098  
1099 #if !SQLITE_OMIT_SCHEMA_PRAGMAS
1100 /*
1101 ** PRAGMA table_info(<table>)
1102 **
1103 ** Return a single row for each column of the named table. The columns of
1104 ** the returned data set are:
1105 **
1106 ** cid: Column id (numbered from left to right, starting at 0)
1107 ** name: Column name
1108 ** type: Column declaration type.
1109 ** notnull: True if 'NOT NULL' is part of column declaration
1110 ** dflt_value: The default value for the column, if any.
1111 */
1112 if ( zLeft.Equals( "table_info" ,StringComparison.OrdinalIgnoreCase ) && zRight != null )
1113 {
1114 Table pTab;
1115 if ( sqlite3ReadSchema( pParse ) != 0 )
1116 goto pragma_out;
1117 pTab = sqlite3FindTable( db, zRight, zDb );
1118 if ( pTab != null )
1119 {
1120 int i;
1121 int nHidden = 0;
1122 Column pCol;
1123 sqlite3VdbeSetNumCols( v, 6 );
1124 pParse.nMem = 6;
1125 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "cid", SQLITE_STATIC );
1126 sqlite3VdbeSetColName( v, 1, COLNAME_NAME, "name", SQLITE_STATIC );
1127 sqlite3VdbeSetColName( v, 2, COLNAME_NAME, "type", SQLITE_STATIC );
1128 sqlite3VdbeSetColName( v, 3, COLNAME_NAME, "notnull", SQLITE_STATIC );
1129 sqlite3VdbeSetColName( v, 4, COLNAME_NAME, "dflt_value", SQLITE_STATIC );
1130 sqlite3VdbeSetColName( v, 5, COLNAME_NAME, "pk", SQLITE_STATIC );
1131 sqlite3ViewGetColumnNames( pParse, pTab );
1132 for ( i = 0; i < pTab.nCol; i++ )//, pCol++)
1133 {
1134 pCol = pTab.aCol[i];
1135 if ( IsHiddenColumn( pCol ) )
1136 {
1137 nHidden++;
1138 continue;
1139 }
1140 sqlite3VdbeAddOp2( v, OP_Integer, i - nHidden, 1 );
1141 sqlite3VdbeAddOp4( v, OP_String8, 0, 2, 0, pCol.zName, 0 );
1142 sqlite3VdbeAddOp4( v, OP_String8, 0, 3, 0, pCol.zType ?? string.Empty, 0 );
1143 sqlite3VdbeAddOp2( v, OP_Integer, ( pCol.notNull != 0 ? 1 : 0 ), 4 );
1144 if ( pCol.zDflt != null )
1145 {
1146 sqlite3VdbeAddOp4( v, OP_String8, 0, 5, 0, pCol.zDflt, 0 );
1147 }
1148 else
1149 {
1150 sqlite3VdbeAddOp2( v, OP_Null, 0, 5 );
1151 }
1152 sqlite3VdbeAddOp2( v, OP_Integer, pCol.isPrimKey != 0 ? 1 : 0, 6 );
1153 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 6 );
1154 }
1155 }
1156 }
1157 else
1158  
1159 if ( zLeft.Equals( "index_info" ,StringComparison.OrdinalIgnoreCase ) && zRight != null )
1160 {
1161 Index pIdx;
1162 Table pTab;
1163 if ( sqlite3ReadSchema( pParse ) != 0 )
1164 goto pragma_out;
1165 pIdx = sqlite3FindIndex( db, zRight, zDb );
1166 if ( pIdx != null )
1167 {
1168 int i;
1169 pTab = pIdx.pTable;
1170 sqlite3VdbeSetNumCols( v, 3 );
1171 pParse.nMem = 3;
1172 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC );
1173 sqlite3VdbeSetColName( v, 1, COLNAME_NAME, "cid", SQLITE_STATIC );
1174 sqlite3VdbeSetColName( v, 2, COLNAME_NAME, "name", SQLITE_STATIC );
1175 for ( i = 0; i < pIdx.nColumn; i++ )
1176 {
1177 int cnum = pIdx.aiColumn[i];
1178 sqlite3VdbeAddOp2( v, OP_Integer, i, 1 );
1179 sqlite3VdbeAddOp2( v, OP_Integer, cnum, 2 );
1180 Debug.Assert( pTab.nCol > cnum );
1181 sqlite3VdbeAddOp4( v, OP_String8, 0, 3, 0, pTab.aCol[cnum].zName, 0 );
1182 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 3 );
1183 }
1184 }
1185 }
1186 else
1187  
1188 if ( zLeft.Equals( "index_list" ,StringComparison.OrdinalIgnoreCase ) && zRight != null )
1189 {
1190 Index pIdx;
1191 Table pTab;
1192 if ( sqlite3ReadSchema( pParse ) != 0 )
1193 goto pragma_out;
1194 pTab = sqlite3FindTable( db, zRight, zDb );
1195 if ( pTab != null )
1196 {
1197 v = sqlite3GetVdbe( pParse );
1198 pIdx = pTab.pIndex;
1199 if ( pIdx != null )
1200 {
1201 int i = 0;
1202 sqlite3VdbeSetNumCols( v, 3 );
1203 pParse.nMem = 3;
1204 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "seq", SQLITE_STATIC );
1205 sqlite3VdbeSetColName( v, 1, COLNAME_NAME, "name", SQLITE_STATIC );
1206 sqlite3VdbeSetColName( v, 2, COLNAME_NAME, "unique", SQLITE_STATIC );
1207 while ( pIdx != null )
1208 {
1209 sqlite3VdbeAddOp2( v, OP_Integer, i, 1 );
1210 sqlite3VdbeAddOp4( v, OP_String8, 0, 2, 0, pIdx.zName, 0 );
1211 sqlite3VdbeAddOp2( v, OP_Integer, ( pIdx.onError != OE_None ) ? 1 : 0, 3 );
1212 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 3 );
1213 ++i;
1214 pIdx = pIdx.pNext;
1215 }
1216 }
1217 }
1218 }
1219 else
1220  
1221 if ( zLeft.Equals( "database_list" ,StringComparison.OrdinalIgnoreCase ) )
1222 {
1223 int i;
1224 if ( sqlite3ReadSchema( pParse ) != 0 )
1225 goto pragma_out;
1226 sqlite3VdbeSetNumCols( v, 3 );
1227 pParse.nMem = 3;
1228 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "seq", SQLITE_STATIC );
1229 sqlite3VdbeSetColName( v, 1, COLNAME_NAME, "name", SQLITE_STATIC );
1230 sqlite3VdbeSetColName( v, 2, COLNAME_NAME, "file", SQLITE_STATIC );
1231 for ( i = 0; i < db.nDb; i++ )
1232 {
1233 if ( db.aDb[i].pBt == null )
1234 continue;
1235 Debug.Assert( db.aDb[i].zName != null );
1236 sqlite3VdbeAddOp2( v, OP_Integer, i, 1 );
1237 sqlite3VdbeAddOp4( v, OP_String8, 0, 2, 0, db.aDb[i].zName, 0 );
1238 sqlite3VdbeAddOp4( v, OP_String8, 0, 3, 0,
1239 sqlite3BtreeGetFilename( db.aDb[i].pBt ), 0 );
1240 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 3 );
1241 }
1242 }
1243 else
1244  
1245 if ( zLeft.Equals( "collation_list" ,StringComparison.OrdinalIgnoreCase ) )
1246 {
1247 int i = 0;
1248 HashElem p;
1249 sqlite3VdbeSetNumCols( v, 2 );
1250 pParse.nMem = 2;
1251 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "seq", SQLITE_STATIC );
1252 sqlite3VdbeSetColName( v, 1, COLNAME_NAME, "name", SQLITE_STATIC );
1253 for ( p = db.aCollSeq.first; p != null; p = p.next )//( p = sqliteHashFirst( db.aCollSeq ) ; p; p = sqliteHashNext( p ) )
1254 {
1255 CollSeq pColl = ( (CollSeq[])p.data )[0];// sqliteHashData( p );
1256 sqlite3VdbeAddOp2( v, OP_Integer, i++, 1 );
1257 sqlite3VdbeAddOp4( v, OP_String8, 0, 2, 0, pColl.zName, 0 );
1258 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 2 );
1259 }
1260 }
1261 else
1262 #endif // * SQLITE_OMIT_SCHEMA_PRAGMAS */
1263  
1264 #if !SQLITE_OMIT_FOREIGN_KEY
1265 if ( zLeft.Equals( "foreign_key_list" ,StringComparison.OrdinalIgnoreCase ) && zRight != null )
1266 {
1267 FKey pFK;
1268 Table pTab;
1269 if ( sqlite3ReadSchema( pParse ) != 0 )
1270 goto pragma_out;
1271 pTab = sqlite3FindTable( db, zRight, zDb );
1272 if ( pTab != null )
1273 {
1274 v = sqlite3GetVdbe( pParse );
1275 pFK = pTab.pFKey;
1276 if ( pFK != null )
1277 {
1278 int i = 0;
1279 sqlite3VdbeSetNumCols( v, 8 );
1280 pParse.nMem = 8;
1281 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "id", SQLITE_STATIC );
1282 sqlite3VdbeSetColName( v, 1, COLNAME_NAME, "seq", SQLITE_STATIC );
1283 sqlite3VdbeSetColName( v, 2, COLNAME_NAME, "table", SQLITE_STATIC );
1284 sqlite3VdbeSetColName( v, 3, COLNAME_NAME, "from", SQLITE_STATIC );
1285 sqlite3VdbeSetColName( v, 4, COLNAME_NAME, "to", SQLITE_STATIC );
1286 sqlite3VdbeSetColName( v, 5, COLNAME_NAME, "on_update", SQLITE_STATIC );
1287 sqlite3VdbeSetColName( v, 6, COLNAME_NAME, "on_delete", SQLITE_STATIC );
1288 sqlite3VdbeSetColName( v, 7, COLNAME_NAME, "match", SQLITE_STATIC );
1289 while ( pFK != null )
1290 {
1291 int j;
1292 for ( j = 0; j < pFK.nCol; j++ )
1293 {
1294 string zCol = pFK.aCol[j].zCol;
1295 string zOnDelete = actionName( pFK.aAction[0] );
1296 string zOnUpdate = actionName( pFK.aAction[1] );
1297 sqlite3VdbeAddOp2( v, OP_Integer, i, 1 );
1298 sqlite3VdbeAddOp2( v, OP_Integer, j, 2 );
1299 sqlite3VdbeAddOp4( v, OP_String8, 0, 3, 0, pFK.zTo, 0 );
1300 sqlite3VdbeAddOp4( v, OP_String8, 0, 4, 0,
1301 pTab.aCol[pFK.aCol[j].iFrom].zName, 0 );
1302 sqlite3VdbeAddOp4( v, zCol != null ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0 );
1303 sqlite3VdbeAddOp4( v, OP_String8, 0, 6, 0, zOnUpdate, 0 );
1304 sqlite3VdbeAddOp4( v, OP_String8, 0, 7, 0, zOnDelete, 0 );
1305 sqlite3VdbeAddOp4( v, OP_String8, 0, 8, 0, "NONE", 0 );
1306 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 8 );
1307 }
1308 ++i;
1309 pFK = pFK.pNextFrom;
1310 }
1311 }
1312 }
1313 }
1314 else
1315 #endif // * !SQLITE_OMIT_FOREIGN_KEY) */
1316  
1317 #if !NDEBUG
1318 if ( zLeft.Equals( "parser_trace" ,StringComparison.OrdinalIgnoreCase ) )
1319 {
1320 if ( zRight != null )
1321 {
1322 if ( sqlite3GetBoolean( zRight ) != 0 )
1323 {
1324 sqlite3ParserTrace( Console.Out, "parser: " );
1325 }
1326 else
1327 {
1328 sqlite3ParserTrace( null, string.Empty );
1329 }
1330 }
1331 }
1332 else
1333 #endif
1334  
1335 /* Reinstall the LIKE and GLOB functions. The variant of LIKE
1336 ** used will be case sensitive or not depending on the RHS.
1337 */
1338 if ( zLeft.Equals( "case_sensitive_like" ,StringComparison.OrdinalIgnoreCase ) )
1339 {
1340 if ( zRight != null )
1341 {
1342 sqlite3RegisterLikeFunctions( db, sqlite3GetBoolean( zRight ) );
1343 }
1344 }
1345 else
1346  
1347 #if !SQLITE_INTEGRITY_CHECK_ERROR_MAX
1348 //const int SQLITE_INTEGRITY_CHECK_ERROR_MAX = 100;
1349 #endif
1350  
1351 #if !SQLITE_OMIT_INTEGRITY_CHECK
1352 /* Pragma "quick_check" is an experimental reduced version of
1353 ** integrity_check designed to detect most database corruption
1354 ** without most of the overhead of a full integrity-check.
1355 */
1356 if ( zLeft.Equals( "integrity_check" ,StringComparison.OrdinalIgnoreCase )
1357 || zLeft.Equals( "quick_check" ,StringComparison.OrdinalIgnoreCase )
1358 )
1359 {
1360 const int SQLITE_INTEGRITY_CHECK_ERROR_MAX = 100;
1361 int i, j, addr, mxErr;
1362  
1363 /* Code that appears at the end of the integrity check. If no error
1364 ** messages have been generated, refput OK. Otherwise output the
1365 ** error message
1366 */
1367 VdbeOpList[] endCode = new VdbeOpList[] {
1368 new VdbeOpList( OP_AddImm, 1, 0, 0), /* 0 */
1369 new VdbeOpList( OP_IfNeg, 1, 0, 0), /* 1 */
1370 new VdbeOpList( OP_String8, 0, 3, 0), /* 2 */
1371 new VdbeOpList( OP_ResultRow, 3, 1, 0),
1372 };
1373  
1374 bool isQuick = ( zLeft[0] == 'q' );
1375  
1376 /* Initialize the VDBE program */
1377 if ( sqlite3ReadSchema( pParse ) != 0 )
1378 goto pragma_out;
1379 pParse.nMem = 6;
1380 sqlite3VdbeSetNumCols( v, 1 );
1381 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC );
1382  
1383 /* Set the maximum error count */
1384 mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
1385 if ( zRight != null )
1386 {
1387 sqlite3GetInt32( zRight, ref mxErr );
1388 if ( mxErr <= 0 )
1389 {
1390 mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
1391 }
1392 }
1393 sqlite3VdbeAddOp2( v, OP_Integer, mxErr, 1 ); /* reg[1] holds errors left */
1394  
1395 /* Do an integrity check on each database file */
1396 for ( i = 0; i < db.nDb; i++ )
1397 {
1398 HashElem x;
1399 Hash pTbls;
1400 int cnt = 0;
1401  
1402 if ( OMIT_TEMPDB != 0 && i == 1 )
1403 continue;
1404  
1405 sqlite3CodeVerifySchema( pParse, i );
1406 addr = sqlite3VdbeAddOp1( v, OP_IfPos, 1 ); /* Halt if out of errors */
1407 sqlite3VdbeAddOp2( v, OP_Halt, 0, 0 );
1408 sqlite3VdbeJumpHere( v, addr );
1409  
1410 /* Do an integrity check of the B-Tree
1411 **
1412 ** Begin by filling registers 2, 3, ... with the root pages numbers
1413 ** for all tables and indices in the database.
1414 */
1415 Debug.Assert( sqlite3SchemaMutexHeld( db, iDb, null ) );
1416 pTbls = db.aDb[i].pSchema.tblHash;
1417 for ( x = pTbls.first; x != null; x = x.next )
1418 {// for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
1419 Table pTab = (Table)x.data;// sqliteHashData( x );
1420 Index pIdx;
1421 sqlite3VdbeAddOp2( v, OP_Integer, pTab.tnum, 2 + cnt );
1422 cnt++;
1423 for ( pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext )
1424 {
1425 sqlite3VdbeAddOp2( v, OP_Integer, pIdx.tnum, 2 + cnt );
1426 cnt++;
1427 }
1428 }
1429  
1430 /* Make sure sufficient number of registers have been allocated */
1431 if ( pParse.nMem < cnt + 4 )
1432 {
1433 pParse.nMem = cnt + 4;
1434 }
1435  
1436 /* Do the b-tree integrity checks */
1437 sqlite3VdbeAddOp3( v, OP_IntegrityCk, 2, cnt, 1 );
1438 sqlite3VdbeChangeP5( v, (u8)i );
1439 addr = sqlite3VdbeAddOp1( v, OP_IsNull, 2 );
1440 sqlite3VdbeAddOp4( v, OP_String8, 0, 3, 0,
1441 sqlite3MPrintf( db, "*** in database %s ***\n", db.aDb[i].zName ),
1442 P4_DYNAMIC );
1443 sqlite3VdbeAddOp3( v, OP_Move, 2, 4, 1 );
1444 sqlite3VdbeAddOp3( v, OP_Concat, 4, 3, 2 );
1445 sqlite3VdbeAddOp2( v, OP_ResultRow, 2, 1 );
1446 sqlite3VdbeJumpHere( v, addr );
1447  
1448 /* Make sure all the indices are constructed correctly.
1449 */
1450 for ( x = pTbls.first; x != null && !isQuick; x = x.next )
1451 {
1452 ;// for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
1453 Table pTab = (Table)x.data;// sqliteHashData( x );
1454 Index pIdx;
1455 int loopTop;
1456  
1457 if ( pTab.pIndex == null )
1458 continue;
1459 addr = sqlite3VdbeAddOp1( v, OP_IfPos, 1 ); /* Stop if out of errors */
1460 sqlite3VdbeAddOp2( v, OP_Halt, 0, 0 );
1461 sqlite3VdbeJumpHere( v, addr );
1462 sqlite3OpenTableAndIndices( pParse, pTab, 1, OP_OpenRead );
1463 sqlite3VdbeAddOp2( v, OP_Integer, 0, 2 ); /* reg(2) will count entries */
1464 loopTop = sqlite3VdbeAddOp2( v, OP_Rewind, 1, 0 );
1465 sqlite3VdbeAddOp2( v, OP_AddImm, 2, 1 ); /* increment entry count */
1466 for ( j = 0, pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext, j++ )
1467 {
1468 int jmp2;
1469 int r1;
1470 VdbeOpList[] idxErr = new VdbeOpList[] {
1471 new VdbeOpList( OP_AddImm, 1, -1, 0),
1472 new VdbeOpList( OP_String8, 0, 3, 0), /* 1 */
1473 new VdbeOpList( OP_Rowid, 1, 4, 0),
1474 new VdbeOpList( OP_String8, 0, 5, 0), /* 3 */
1475 new VdbeOpList( OP_String8, 0, 6, 0), /* 4 */
1476 new VdbeOpList( OP_Concat, 4, 3, 3),
1477 new VdbeOpList( OP_Concat, 5, 3, 3),
1478 new VdbeOpList( OP_Concat, 6, 3, 3),
1479 new VdbeOpList( OP_ResultRow, 3, 1, 0),
1480 new VdbeOpList( OP_IfPos, 1, 0, 0), /* 9 */
1481 new VdbeOpList( OP_Halt, 0, 0, 0),
1482 };
1483 r1 = sqlite3GenerateIndexKey( pParse, pIdx, 1, 3, false );
1484 jmp2 = sqlite3VdbeAddOp4Int( v, OP_Found, j + 2, 0, r1, pIdx.nColumn + 1 );
1485 addr = sqlite3VdbeAddOpList( v, ArraySize( idxErr ), idxErr );
1486 sqlite3VdbeChangeP4( v, addr + 1, "rowid ", SQLITE_STATIC );
1487 sqlite3VdbeChangeP4( v, addr + 3, " missing from index ", SQLITE_STATIC );
1488 sqlite3VdbeChangeP4( v, addr + 4, pIdx.zName, P4_TRANSIENT );
1489 sqlite3VdbeJumpHere( v, addr + 9 );
1490 sqlite3VdbeJumpHere( v, jmp2 );
1491 }
1492 sqlite3VdbeAddOp2( v, OP_Next, 1, loopTop + 1 );
1493 sqlite3VdbeJumpHere( v, loopTop );
1494 for ( j = 0, pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext, j++ )
1495 {
1496 VdbeOpList[] cntIdx = new VdbeOpList[] {
1497 new VdbeOpList( OP_Integer, 0, 3, 0),
1498 new VdbeOpList( OP_Rewind, 0, 0, 0), /* 1 */
1499 new VdbeOpList( OP_AddImm, 3, 1, 0),
1500 new VdbeOpList( OP_Next, 0, 0, 0), /* 3 */
1501 new VdbeOpList( OP_Eq, 2, 0, 3), /* 4 */
1502 new VdbeOpList( OP_AddImm, 1, -1, 0),
1503 new VdbeOpList( OP_String8, 0, 2, 0), /* 6 */
1504 new VdbeOpList( OP_String8, 0, 3, 0), /* 7 */
1505 new VdbeOpList( OP_Concat, 3, 2, 2),
1506 new VdbeOpList( OP_ResultRow, 2, 1, 0),
1507 };
1508 addr = sqlite3VdbeAddOp1( v, OP_IfPos, 1 );
1509 sqlite3VdbeAddOp2( v, OP_Halt, 0, 0 );
1510 sqlite3VdbeJumpHere( v, addr );
1511 addr = sqlite3VdbeAddOpList( v, ArraySize( cntIdx ), cntIdx );
1512 sqlite3VdbeChangeP1( v, addr + 1, j + 2 );
1513 sqlite3VdbeChangeP2( v, addr + 1, addr + 4 );
1514 sqlite3VdbeChangeP1( v, addr + 3, j + 2 );
1515 sqlite3VdbeChangeP2( v, addr + 3, addr + 2 );
1516 sqlite3VdbeJumpHere( v, addr + 4 );
1517 sqlite3VdbeChangeP4( v, addr + 6,
1518 "wrong # of entries in index ", P4_STATIC );
1519 sqlite3VdbeChangeP4( v, addr + 7, pIdx.zName, P4_TRANSIENT );
1520 }
1521 }
1522 }
1523 addr = sqlite3VdbeAddOpList( v, ArraySize( endCode ), endCode );
1524 sqlite3VdbeChangeP2( v, addr, -mxErr );
1525 sqlite3VdbeJumpHere( v, addr + 1 );
1526 sqlite3VdbeChangeP4( v, addr + 2, "ok", P4_STATIC );
1527 }
1528 else
1529 #endif // * SQLITE_OMIT_INTEGRITY_CHECK */
1530  
1531 /*
1532 ** PRAGMA encoding
1533 ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be"
1534 **
1535 ** In its first form, this pragma returns the encoding of the main
1536 ** database. If the database is not initialized, it is initialized now.
1537 **
1538 ** The second form of this pragma is a no-op if the main database file
1539 ** has not already been initialized. In this case it sets the default
1540 ** encoding that will be used for the main database file if a new file
1541 ** is created. If an existing main database file is opened, then the
1542 ** default text encoding for the existing database is used.
1543 **
1544 ** In all cases new databases created using the ATTACH command are
1545 ** created to use the same default text encoding as the main database. If
1546 ** the main database has not been initialized and/or created when ATTACH
1547 ** is executed, this is done before the ATTACH operation.
1548 **
1549 ** In the second form this pragma sets the text encoding to be used in
1550 ** new database files created using this database handle. It is only
1551 ** useful if invoked immediately after the main database i
1552 */
1553 if ( zLeft.Equals( "encoding" ,StringComparison.OrdinalIgnoreCase ) )
1554 {
1555 int iEnc;
1556 if ( null == zRight )
1557 { /* "PRAGMA encoding" */
1558 if ( sqlite3ReadSchema( pParse ) != 0 )
1559 {
1560 pParse.nErr = 0;
1561 pParse.zErrMsg = null;
1562 pParse.rc = 0;// reset errors goto pragma_out;
1563 }
1564 sqlite3VdbeSetNumCols( v, 1 );
1565 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "encoding", SQLITE_STATIC );
1566 sqlite3VdbeAddOp2( v, OP_String8, 0, 1 );
1567 Debug.Assert( encnames[SQLITE_UTF8].enc == SQLITE_UTF8 );
1568 Debug.Assert( encnames[SQLITE_UTF16LE].enc == SQLITE_UTF16LE );
1569 Debug.Assert( encnames[SQLITE_UTF16BE].enc == SQLITE_UTF16BE );
1570 sqlite3VdbeChangeP4( v, -1, encnames[ENC( pParse.db )].zName, P4_STATIC );
1571 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 1 );
1572 }
1573 #if !SQLITE_OMIT_UTF16
1574 else
1575 { /* "PRAGMA encoding = XXX" */
1576 /* Only change the value of sqlite.enc if the database handle is not
1577 ** initialized. If the main database exists, the new sqlite.enc value
1578 ** will be overwritten when the schema is next loaded. If it does not
1579 ** already exists, it will be created to use the new encoding value.
1580 */
1581 if (
1582 //!(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
1583 //DbHasProperty(db, 0, DB_Empty)
1584 ( db.flags & DB_SchemaLoaded ) != DB_SchemaLoaded || ( db.flags & DB_Empty ) == DB_Empty
1585 )
1586 {
1587 for ( iEnc = 0 ; encnames[iEnc].zName != null ; iEnc++ )
1588 {
1589 if ( zRight.Equals( encnames[iEnc].zName ,StringComparison.OrdinalIgnoreCase ) )
1590 {
1591 pParse.db.aDbStatic[0].pSchema.enc = encnames[iEnc].enc != 0 ? encnames[iEnc].enc : SQLITE_UTF16NATIVE;
1592 break;
1593 }
1594 }
1595 if ( encnames[iEnc].zName == null )
1596 {
1597 sqlite3ErrorMsg( pParse, "unsupported encoding: %s", zRight );
1598 }
1599 }
1600 }
1601 #endif
1602 }
1603 else
1604  
1605 #if !SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
1606 /*
1607 ** PRAGMA [database.]schema_version
1608 ** PRAGMA [database.]schema_version = <integer>
1609 **
1610 ** PRAGMA [database.]user_version
1611 ** PRAGMA [database.]user_version = <integer>
1612 **
1613 ** The pragma's schema_version and user_version are used to set or get
1614 ** the value of the schema-version and user-version, respectively. Both
1615 ** the schema-version and the user-version are 32-bit signed integers
1616 ** stored in the database header.
1617 **
1618 ** The schema-cookie is usually only manipulated internally by SQLite. It
1619 ** is incremented by SQLite whenever the database schema is modified (by
1620 ** creating or dropping a table or index). The schema version is used by
1621 ** SQLite each time a query is executed to ensure that the internal cache
1622 ** of the schema used when compiling the SQL query matches the schema of
1623 ** the database against which the compiled query is actually executed.
1624 ** Subverting this mechanism by using "PRAGMA schema_version" to modify
1625 ** the schema-version is potentially dangerous and may lead to program
1626 ** crashes or database corruption. Use with caution!
1627 **
1628 ** The user-version is not used internally by SQLite. It may be used by
1629 ** applications for any purpose.
1630 */
1631 if ( zLeft.Equals( "schema_version" ,StringComparison.OrdinalIgnoreCase )
1632 || zLeft.Equals( "user_version" ,StringComparison.OrdinalIgnoreCase )
1633 || zLeft.Equals( "freelist_count" ,StringComparison.OrdinalIgnoreCase )
1634 )
1635 {
1636 int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
1637 sqlite3VdbeUsesBtree( v, iDb );
1638 switch ( zLeft[0] )
1639 {
1640 case 'f':
1641 case 'F':
1642 iCookie = BTREE_FREE_PAGE_COUNT;
1643 break;
1644 case 's':
1645 case 'S':
1646 iCookie = BTREE_SCHEMA_VERSION;
1647 break;
1648 default:
1649 iCookie = BTREE_USER_VERSION;
1650 break;
1651 }
1652  
1653 if ( zRight != null && iCookie != BTREE_FREE_PAGE_COUNT )
1654 {
1655 /* Write the specified cookie value */
1656 VdbeOpList[] setCookie = new VdbeOpList[] {
1657 new VdbeOpList( OP_Transaction, 0, 1, 0), /* 0 */
1658 new VdbeOpList( OP_Integer, 0, 1, 0), /* 1 */
1659 new VdbeOpList( OP_SetCookie, 0, 0, 1), /* 2 */
1660 };
1661 int addr = sqlite3VdbeAddOpList( v, ArraySize( setCookie ), setCookie );
1662 sqlite3VdbeChangeP1( v, addr, iDb );
1663 sqlite3VdbeChangeP1( v, addr + 1, sqlite3Atoi( zRight ) );
1664 sqlite3VdbeChangeP1( v, addr + 2, iDb );
1665 sqlite3VdbeChangeP2( v, addr + 2, iCookie );
1666 }
1667 else
1668 {
1669 /* Read the specified cookie value */
1670 VdbeOpList[] readCookie = new VdbeOpList[] {
1671 new VdbeOpList( OP_Transaction, 0, 0, 0), /* 0 */
1672 new VdbeOpList( OP_ReadCookie, 0, 1, 0), /* 1 */
1673 new VdbeOpList( OP_ResultRow, 1, 1, 0)
1674 };
1675 int addr = sqlite3VdbeAddOpList( v, readCookie.Length, readCookie );// ArraySize(readCookie), readCookie);
1676 sqlite3VdbeChangeP1( v, addr, iDb );
1677 sqlite3VdbeChangeP1( v, addr + 1, iDb );
1678 sqlite3VdbeChangeP3( v, addr + 1, iCookie );
1679 sqlite3VdbeSetNumCols( v, 1 );
1680 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT );
1681 }
1682 }
1683 else if ( zLeft.Equals( "reload_schema" ,StringComparison.OrdinalIgnoreCase ) )
1684 {
1685 /* force schema reloading*/
1686 sqlite3ResetInternalSchema( db, -1 );
1687 }
1688 else if ( zLeft.Equals( "file_format" ,StringComparison.OrdinalIgnoreCase ) )
1689 {
1690 pDb.pSchema.file_format = (u8)atoi( zRight );
1691 sqlite3ResetInternalSchema( db, -1 );
1692 }
1693 else
1694 #endif // * SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
1695  
1696 #if !SQLITE_OMIT_COMPILEOPTION_DIAGS
1697 /*
1698 ** PRAGMA compile_options
1699 **
1700 ** Return the names of all compile-time options used in this build,
1701 ** one option per row.
1702 */
1703 if ( zLeft.Equals( "compile_options" ,StringComparison.OrdinalIgnoreCase ) )
1704 {
1705 int i = 0;
1706 string zOpt;
1707 sqlite3VdbeSetNumCols( v, 1 );
1708 pParse.nMem = 1;
1709 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC );
1710 while ( ( zOpt = sqlite3_compileoption_get( i++ ) ) != null )
1711 {
1712 sqlite3VdbeAddOp4( v, OP_String8, 0, 1, 0, zOpt, 0 );
1713 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 1 );
1714 }
1715 }
1716 else
1717 #endif //* SQLITE_OMIT_COMPILEOPTION_DIAGS */
1718  
1719  
1720 #if !SQLITE_OMIT_WAL
1721 /*
1722 ** PRAGMA [database.]wal_checkpoint = passive|full|restart
1723 **
1724 ** Checkpoint the database.
1725 */
1726 if( sqlite3StrICmp(zLeft, "wal_checkpoint")==0 ){
1727 int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
1728 int eMode = SQLITE_CHECKPOINT_PASSIVE;
1729 if( zRight ){
1730 if( sqlite3StrICmp(zRight, "full")==0 ){
1731 eMode = SQLITE_CHECKPOINT_FULL;
1732 }else if( sqlite3StrICmp(zRight, "restart")==0 ){
1733 eMode = SQLITE_CHECKPOINT_RESTART;
1734 }
1735 }
1736 if( sqlite3ReadSchema(pParse) ) goto pragma_out;
1737 sqlite3VdbeSetNumCols(v, 3);
1738 pParse->nMem = 3;
1739 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
1740 sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC);
1741 sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC);
1742  
1743 sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1);
1744 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
1745 }else
1746  
1747 /*
1748 ** PRAGMA wal_autocheckpoint
1749 ** PRAGMA wal_autocheckpoint = N
1750 **
1751 ** Configure a database connection to automatically checkpoint a database
1752 ** after accumulating N frames in the log. Or query for the current value
1753 ** of N.
1754 */
1755 if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){
1756 if( zRight ){
1757 sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight));
1758 }
1759 returnSingleInt(pParse, "wal_autocheckpoint",
1760 db->xWalCallback==sqlite3WalDefaultHook ?
1761 SQLITE_PTR_TO_INT(db->pWalArg) : 0);
1762 }else
1763 #endif
1764  
1765 #if SQLITE_DEBUG || SQLITE_TEST
1766 /*
1767 ** Report the current state of file logs for all databases
1768 */
1769 if ( zLeft.Equals( "lock_status" ,StringComparison.OrdinalIgnoreCase ) )
1770 {
1771 string[] azLockName = {
1772 "unlocked", "shared", "reserved", "pending", "exclusive"
1773 };
1774 int i;
1775 sqlite3VdbeSetNumCols( v, 2 );
1776 pParse.nMem = 2;
1777 sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "database", SQLITE_STATIC );
1778 sqlite3VdbeSetColName( v, 1, COLNAME_NAME, "status", SQLITE_STATIC );
1779 for ( i = 0; i < db.nDb; i++ )
1780 {
1781 Btree pBt;
1782 string zState = "unknown";
1783 sqlite3_int64 j = 0;
1784 if ( db.aDb[i].zName == null )
1785 continue;
1786 sqlite3VdbeAddOp4( v, OP_String8, 0, 1, 0, db.aDb[i].zName, P4_STATIC );
1787 pBt = db.aDb[i].pBt;
1788 if ( pBt == null || sqlite3BtreePager( pBt ) == null )
1789 {
1790 zState = "closed";
1791 }
1792 else if ( sqlite3_file_control( db, i != 0 ? db.aDb[i].zName : null,
1793 SQLITE_FCNTL_LOCKSTATE, ref j ) == SQLITE_OK )
1794 {
1795 zState = azLockName[j];
1796 }
1797 sqlite3VdbeAddOp4( v, OP_String8, 0, 2, 0, zState, P4_STATIC );
1798 sqlite3VdbeAddOp2( v, OP_ResultRow, 1, 2 );
1799 }
1800 }
1801 else
1802 #endif
1803  
1804 #if SQLITE_HAS_CODEC
1805 // needed to support key/rekey/hexrekey with pragma cmds
1806 if ( zLeft.Equals( "key" ,StringComparison.OrdinalIgnoreCase ) && !string.IsNullOrEmpty( zRight ) )
1807 {
1808 sqlite3_key( db, zRight, sqlite3Strlen30( zRight ) );
1809 }
1810 else
1811 if ( zLeft.Equals( "rekey" ,StringComparison.OrdinalIgnoreCase ) && !string.IsNullOrEmpty( zRight ) )
1812 {
1813 sqlite3_rekey( db, zRight, sqlite3Strlen30( zRight ) );
1814 }
1815 else
1816 if ( !string.IsNullOrEmpty( zRight ) && ( zLeft.Equals( "hexkey" ,StringComparison.OrdinalIgnoreCase ) ||
1817 zLeft.Equals( "hexrekey" ,StringComparison.OrdinalIgnoreCase ) ) )
1818 {
1819 StringBuilder zKey = new StringBuilder( 40 );
1820 zRight.ToLower( new CultureInfo( "en-us" ) );
1821 // expected '0x0102030405060708090a0b0c0d0e0f10'
1822 if ( zRight.Length != 34 )
1823 return;
1824  
1825 for ( int i = 2; i < zRight.Length; i += 2 )
1826 {
1827 int h1 = zRight[i];
1828 int h2 = zRight[i + 1];
1829 h1 += 9 * ( 1 & ( h1 >> 6 ) );
1830 h2 += 9 * ( 1 & ( h2 >> 6 ) );
1831 zKey.Append( Convert.ToChar( ( h2 & 0x0f ) | ( ( h1 & 0xf ) << 4 ) ) );
1832 }
1833 if ( ( zLeft[3] & 0xf ) == 0xb )
1834 {
1835 sqlite3_key( db, zKey.ToString(), zKey.Length );
1836 }
1837 else
1838 {
1839 sqlite3_rekey( db, zKey.ToString(), zKey.Length );
1840 }
1841 }
1842 else
1843 #endif
1844 #if SQLITE_HAS_CODEC || SQLITE_ENABLE_CEROD
1845 if ( zLeft.Equals( "activate_extensions" ,StringComparison.OrdinalIgnoreCase ) )
1846 {
1847 #if SQLITE_HAS_CODEC
1848 if ( !string.IsNullOrEmpty( zRight ) && zRight.Length > 4 && sqlite3StrNICmp( zRight, "see-", 4 ) == 0 )
1849 {
1850 sqlite3_activate_see( zRight.Substring( 4 ) );
1851 }
1852 #endif
1853 #if SQLITE_ENABLE_CEROD
1854 if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
1855 sqlite3_activate_cerod(&zRight[6]);
1856 }
1857 #endif
1858 }
1859 else
1860 #endif
1861 { /* Empty ELSE clause */
1862 }
1863  
1864 /*
1865 ** Reset the safety level, in case the fullfsync flag or synchronous
1866 ** setting changed.
1867 */
1868 #if !SQLITE_OMIT_PAGER_PRAGMAS
1869 if ( db.autoCommit != 0 )
1870 {
1871 sqlite3BtreeSetSafetyLevel( pDb.pBt, pDb.safety_level,
1872 ( ( db.flags & SQLITE_FullFSync ) != 0 ) ? 1 : 0,
1873 ( ( db.flags & SQLITE_CkptFullFSync ) != 0 ) ? 1 : 0 );
1874 }
1875 #endif
1876 pragma_out:
1877 sqlite3DbFree( db, ref zLeft );
1878 sqlite3DbFree( db, ref zRight );
1879 ;
1880 }
1881  
1882 #endif // * SQLITE_OMIT_PRAGMA
1883 }
1884 }