]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the "index_xinfo" pragma. Add new columns to the "index_info" and
authordrh <drh@noemail.net>
Sat, 31 Jan 2015 02:00:01 +0000 (02:00 +0000)
committerdrh <drh@noemail.net>
Sat, 31 Jan 2015 02:00:01 +0000 (02:00 +0000)
"index_list" pragmas.

FossilOrigin-Name: 30f51d7b3b292191e8351223242e708bb7f3dfa6

manifest
manifest.uuid
src/pragma.c
test/pragma.test
tool/mkpragmatab.tcl

index f8fe7806e281fbd6b3d82ba9453bf5ea83b2ac82..effa8658b49435c46ff44e933eb1cd882b15e55c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Change\sSQLITE_TESTCTRL_INITMODE\sto\sSQLITE_TESTCTRL_IMPOSTER.\s\sRevise\sthe\sorder\nof\sparameters.\s\sGive\sit\sthe\sability\sto\sreset\sthe\sschema\sparse\stable\sso\sthat\nimposter\stables\scan\sbe\serased.
-D 2015-01-30T20:59:27.457
+C Add\sthe\s"index_xinfo"\spragma.\s\sAdd\snew\scolumns\sto\sthe\s"index_info"\sand\n"index_list"\spragmas.
+D 2015-01-31T02:00:01.018
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5407a688f4d77a05c18a8142be8ae5a2829dd610
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -223,7 +223,7 @@ F src/parse.y c5d0d964f9ac023e8154cad512e54b0b6058e086
 F src/pcache.c d210cf90d04365a74f85d21374dded65af67b0cb
 F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
 F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf
-F src/pragma.c ba149bbbc90783f84815636c509ced8eac11bbcf
+F src/pragma.c f4d0326361cc875ecd9c92100c5b17363a6a671a
 F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9
 F src/printf.c 05edc41450d0eb2c05ef7db113bf32742ae65325
 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
@@ -630,7 +630,7 @@ F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
 F test/hexlit.test f9ecde8145bfc2341573473256c74ae37a200497
 F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
-F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 w test/initmode.test
+F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
 F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
@@ -786,7 +786,7 @@ F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
 F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
 F test/permutations.test f9cc1dd987986c9d4949211c7a4ed55ec9aecba1
-F test/pragma.test aa16dedfe01c02c8895169012f7dfde9c163f0d5
+F test/pragma.test 66776f48f533c7248d04c1473deb3ebb792daacd
 F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
 F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
@@ -1202,7 +1202,7 @@ F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
 F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
 F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
-F tool/mkpragmatab.tcl 07a5124cf2dbafa1b375eefcf8ac4227028b0f8b
+F tool/mkpragmatab.tcl 4a3b465f0a800d22ca419daad34389c6a44858c2
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
 F tool/mksqlite3c-noext.tcl 9ef48e1748dce7b844f67e2450ff9dfeb0fb4ab5
 F tool/mksqlite3c.tcl cfde806851c413db7689b9cb74a4eeb92539c601
@@ -1238,7 +1238,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 98e029134dc1300d3ecb48b41b5107ec69ba85db
-R ae5f14ccaf584de0786e4614152020d2
+P 42d5601739c90434e5adfda8fa99ef7b903877db
+R 6dd4b55c378d1f90a678654a5a3c72aa
+T *branch * index_xinfo
+T *sym-index_xinfo *
+T -sym-trunk *
 U drh
-Z c23d2e36f9e88e779a131b19c0ee1b9b
+Z 111ada8400958c014924f86391246d25
index 9eba1b1a5401baf9e1a85d06af0e3170ac218928..6dcf9f25fb5939a64407f120b7543ce98e7c6b42 100644 (file)
@@ -1 +1 @@
-42d5601739c90434e5adfda8fa99ef7b903877db
\ No newline at end of file
+30f51d7b3b292191e8351223242e708bb7f3dfa6
\ No newline at end of file
index 34830e33a6700907dad8d335848e6fee17f76d94..d1aaa4c91360d0ae161ff65c105982d7473e805d 100644 (file)
@@ -261,6 +261,10 @@ static const struct sPragmaNames {
     /* ePragTyp:  */ PragTyp_INDEX_LIST,
     /* ePragFlag: */ PragFlag_NeedSchema,
     /* iArg:      */ 0 },
+  { /* zName:     */ "index_xinfo",
+    /* ePragTyp:  */ PragTyp_INDEX_INFO,
+    /* ePragFlag: */ PragFlag_NeedSchema,
+    /* iArg:      */ 1 },
 #endif
 #if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
   { /* zName:     */ "integrity_check",
@@ -477,7 +481,7 @@ static const struct sPragmaNames {
     /* iArg:      */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
 #endif
 };
-/* Number of pragmas: 58 on by default, 71 total. */
+/* Number of pragmas: 59 on by default, 72 total. */
 /* End of the automatically generated pragma table.
 ***************************************************************************/
 
@@ -732,6 +736,7 @@ void sqlite3Pragma(
   sqlite3 *db = pParse->db;    /* The database connection */
   Db *pDb;                     /* The specific database being pragmaed */
   Vdbe *v = sqlite3GetVdbe(pParse);  /* Prepared statement */
+  const struct sPragmaNames *pPragma;
 
   if( v==0 ) return;
   sqlite3VdbeRunOnlyOnce(v);
@@ -809,14 +814,15 @@ void sqlite3Pragma(
     }
   }
   if( lwr>upr ) goto pragma_out;
+  pPragma = &aPragmaNames[mid];
 
   /* Make sure the database schema is loaded if the pragma requires that */
-  if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){
+  if( (pPragma->mPragFlag & PragFlag_NeedSchema)!=0 ){
     if( sqlite3ReadSchema(pParse) ) goto pragma_out;
   }
 
   /* Jump to the appropriate pragma handler */
-  switch( aPragmaNames[mid].ePragTyp ){
+  switch( pPragma->ePragTyp ){
   
 #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
   /*
@@ -1395,10 +1401,9 @@ void sqlite3Pragma(
 #ifndef SQLITE_OMIT_FLAG_PRAGMAS
   case PragTyp_FLAG: {
     if( zRight==0 ){
-      returnSingleInt(pParse, aPragmaNames[mid].zName,
-                     (db->flags & aPragmaNames[mid].iArg)!=0 );
+      returnSingleInt(pParse, pPragma->zName, (db->flags & pPragma->iArg)!=0 );
     }else{
-      int mask = aPragmaNames[mid].iArg;    /* Mask of bits to set or clear. */
+      int mask = pPragma->iArg;    /* Mask of bits to set or clear. */
       if( db->autoCommit==0 ){
         /* Foreign key support may not be enabled or disabled while not
         ** in auto-commit mode.  */
@@ -1527,20 +1532,30 @@ void sqlite3Pragma(
     pIdx = sqlite3FindIndex(db, zRight, zDb);
     if( pIdx ){
       int i;
+      int mx = pPragma->iArg ? pIdx->nColumn : pIdx->nKeyCol;
       pTab = pIdx->pTable;
-      sqlite3VdbeSetNumCols(v, 3);
-      pParse->nMem = 3;
+      sqlite3VdbeSetNumCols(v, 6);
+      pParse->nMem = 6;
       sqlite3CodeVerifySchema(pParse, iDb);
       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
-      for(i=0; i<pIdx->nKeyCol; i++){
+      sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "desc", SQLITE_STATIC);
+      sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "coll", SQLITE_STATIC);
+      sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "key", SQLITE_STATIC);
+      for(i=0; i<mx; i++){
         i16 cnum = pIdx->aiColumn[i];
         sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
         sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
-        assert( pTab->nCol>cnum );
-        sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
-        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
+        if( cnum<0 ){
+          sqlite3VdbeAddOp2(v, OP_Null, 0, 3);
+        }else{
+          sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
+        }
+        sqlite3VdbeAddOp2(v, OP_Integer, pIdx->aSortOrder[i], 4);
+        sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, pIdx->azColl[i], 0);
+        sqlite3VdbeAddOp2(v, OP_Integer, i<pIdx->nKeyCol, 6);
+        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
       }
     }
   }
@@ -1553,17 +1568,22 @@ void sqlite3Pragma(
     pTab = sqlite3FindTable(db, zRight, zDb);
     if( pTab ){
       v = sqlite3GetVdbe(pParse);
-      sqlite3VdbeSetNumCols(v, 3);
-      pParse->nMem = 3;
+      sqlite3VdbeSetNumCols(v, 5);
+      pParse->nMem = 5;
       sqlite3CodeVerifySchema(pParse, iDb);
       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
+      sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "origin", SQLITE_STATIC);
+      sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "partial", SQLITE_STATIC);
       for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
+        const char *azOrigin[] = { "c", "u", "pk" };
         sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
         sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
         sqlite3VdbeAddOp2(v, OP_Integer, IsUniqueIndex(pIdx), 3);
-        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
+        sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, azOrigin[pIdx->idxType], 0);
+        sqlite3VdbeAddOp2(v, OP_Integer, pIdx->pPartIdxWhere!=0, 5);
+        sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
       }
     }
   }
@@ -2133,9 +2153,9 @@ void sqlite3Pragma(
   ** applications for any purpose.
   */
   case PragTyp_HEADER_VALUE: {
-    int iCookie = aPragmaNames[mid].iArg;  /* Which cookie to read or write */
+    int iCookie = pPragma->iArg;  /* Which cookie to read or write */
     sqlite3VdbeUsesBtree(v, iDb);
-    if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){
+    if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){
       /* Write the specified cookie value */
       static const VdbeOpList setCookie[] = {
         { OP_Transaction,    0,  1,  0},    /* 0 */
@@ -2255,7 +2275,7 @@ void sqlite3Pragma(
   ** disables the timeout.
   */
   /*case PragTyp_BUSY_TIMEOUT*/ default: {
-    assert( aPragmaNames[mid].ePragTyp==PragTyp_BUSY_TIMEOUT );
+    assert( pPragma->ePragTyp==PragTyp_BUSY_TIMEOUT );
     if( zRight ){
       sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
     }
index 09b9b6c14f53c84c90efef6cbc8b7cad87a848d8..1628cbaecf0275efaa026520d3b7d90b3f803b9d 100644 (file)
@@ -51,6 +51,30 @@ ifcapable !pragma {
   return
 }
 
+# Capture the output of a pragma in a TEMP table.
+#
+proc capture_pragma {db tabname sql} {
+  $db eval "DROP TABLE IF EXISTS temp.$tabname"
+  set once 1
+  $db eval $sql x {
+    if {$once} {
+      set once 0
+      set ins "INSERT INTO $tabname VALUES"
+      set crtab "CREATE TEMP TABLE $tabname "
+      set sep "("
+      foreach col $x(*) {
+        append ins ${sep}\$x($col)
+        append crtab ${sep}\"$col\"
+        set sep ,
+      }
+      append ins )
+      append crtab )
+      $db eval $crtab
+    }
+    $db eval $ins
+  }
+}
+
 # Delete the preexisting database to avoid the special setup
 # that the "all.test" script does.
 #
@@ -620,9 +644,10 @@ ifcapable {foreignkey} {
     }
   } {}
   do_test pragma-6.4 {
-    execsql {
+    capture_pragma db out {
       pragma index_list(t3);
     }
+    db eval {SELECT seq, "name", "unique" FROM out ORDER BY seq}
   } {0 sqlite_autoindex_t3_1 1}
 }
 ifcapable {!foreignkey} {
@@ -631,8 +656,11 @@ ifcapable {!foreignkey} {
 do_test pragma-6.5.1 {
   execsql {
     CREATE INDEX t3i1 ON t3(a,b);
+  }
+  capture_pragma db out {
     pragma index_info(t3i1);
   }
+  db eval {SELECT seqno, cid, name FROM out ORDER BY seqno}
 } {0 0 a 1 1 b}
 do_test pragma-6.5.2 {
   execsql {
@@ -676,8 +704,10 @@ do_test pragma-6.7 {
       four REAL DEFAULT X'abcdef',
       five DEFAULT CURRENT_TIME
     );
-    PRAGMA table_info(test_table);
   }
+  capture_pragma db out {PRAGMA table_info(test_table)}
+  db eval {SELECT cid, "name", type, "notnull", dflt_value, pk FROM out
+            ORDER BY cid}
 } [concat \
   {0 one INT 1 -1 0} \
   {1 two text 0 {} 0} \
@@ -693,10 +723,9 @@ do_test pragma-7.1.1 {
   # Make sure a pragma knows to read the schema if it needs to
   db close
   sqlite3 db test.db
-  execsql {
-    pragma index_list(t3);
-  }
-} {0 t3i1 0 1 sqlite_autoindex_t3_1 1}
+  capture_pragma db out "PRAGMA index_list(t3)"
+  db eval {SELECT name, "origin" FROM out ORDER BY name DESC}
+} {t3i1 c sqlite_autoindex_t3_1 u}
 do_test pragma-7.1.2 {
   execsql {
     pragma index_list(t3_bogus);
@@ -1705,19 +1734,25 @@ do_test 23.1 {
   }
   db2 eval {SELECT name FROM sqlite_master}
 } {t1 i1 i2 t2}
-do_test 23.2 {
+do_test 23.2a {
   db eval {
     DROP INDEX i2;
     CREATE INDEX i2 ON t1(c,d,b);
   }
-  db2 eval {PRAGMA index_info(i2)}
-} {0 2 c 1 3 d 2 1 b}
+  capture_pragma db2 out {PRAGMA index_info(i2)}
+  db2 eval {SELECT cid, name, "desc", coll, "key", '|' FROM out ORDER BY seqno}
+} {2 c 0 BINARY 1 | 3 d 0 BINARY 1 | 1 b 0 BINARY 1 |}
+do_test 23.2b {
+  capture_pragma db2 out {PRAGMA index_xinfo(i2)}
+  db2 eval {SELECT cid, name, "desc", coll, "key", '|' FROM out ORDER BY seqno}
+} {2 c 0 BINARY 1 | 3 d 0 BINARY 1 | 1 b 0 BINARY 1 | -1 {} 0 BINARY 0 |}
 do_test 23.3 {
   db eval {
     CREATE INDEX i3 ON t1(d,b,c);
   }
-  db2 eval {PRAGMA index_list(t1)}
-} {0 i3 0 1 i2 0 2 i1 0}
+  capture_pragma db2 out {PRAGMA index_list(t1)}
+  db2 eval {SELECT name, "unique", origin FROM out ORDER BY seq}
+} {i3 0 c i2 0 c i1 0 c}
 do_test 23.4 {
   db eval {
     ALTER TABLE t1 ADD COLUMN e;
index 21503d16eeccf8a062fa5407fcd215e37d4153d5..c842208de513fdfe341b77e396e145b04ca800a9 100644 (file)
@@ -205,6 +205,14 @@ set pragma_def {
   IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
 
   NAME: index_info
+  TYPE: INDEX_INFO
+  ARG:  0
+  FLAG: NeedSchema
+  IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+
+  NAME: index_xinfo
+  TYPE: INDEX_INFO
+  ARG:  1
   FLAG: NeedSchema
   IF:   !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)