]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Full-coverage testing and documentation for the ANALYZE command. The
authordrh <drh@noemail.net>
Sat, 23 Jul 2005 02:17:03 +0000 (02:17 +0000)
committerdrh <drh@noemail.net>
Sat, 23 Jul 2005 02:17:03 +0000 (02:17 +0000)
results of analysis are still not loaded or used, however. (CVS 2561)

FossilOrigin-Name: bd7583a5d63412785a9c5de54d25b509da241605

main.mk
manifest
manifest.uuid
src/analyze.c
src/sqlite.h.in
src/tclsqlite.c
test/analyze.test [new file with mode: 0644]
test/auth.test
www/lang.tcl

diff --git a/main.mk b/main.mk
index 3c73fb0bec31cfea4669e8db861c40f62a50fe29..2925e1a38deaef0fba83f599df6aacea2ab60e4b 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -133,7 +133,8 @@ TESTSRC = \
   $(TOP)/src/utf.c \
   $(TOP)/src/util.c \
   $(TOP)/src/vdbe.c \
-  $(TOP)/src/md5.c
+  $(TOP)/src/md5.c \
+  $(TOP)/src/where.c
 
 # Header files used by all library source files.
 #
index 5929b7aea5395b82ab8de0da4ea3ed7d45505d36..9bed028a6f06444483807256ff7e994d443e4ea7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C First\scode\sfor\sthe\sANALYZE\scommand.\s\sMostly\suntested.\s\sThe\sanalysis\sis\nnot\sloaded\sinto\sthe\ssymbol\stables\sand\sis\snot\sused\sby\sthe\soptimizer.\s(CVS\s2560)
-D 2005-07-23T00:41:49
+C Full-coverage\stesting\sand\sdocumentation\sfor\sthe\sANALYZE\scommand.\s\sThe\nresults\sof\sanalysis\sare\sstill\snot\sloaded\sor\sused,\showever.\s(CVS\s2561)
+D 2005-07-23T02:17:03
 F Makefile.in 22ea9c0fe748f591712d8fe3c6d972c6c173a165
 F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -16,7 +16,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
 F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
 F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
-F main.mk b2d38013a10e1c6a821e3d117294bf785deecf97
+F main.mk c6712c0b26305f2da026d722caf3d9f8b6e187ea
 F mkdll.sh 5ec23622515d5bf8969404e80cfb5e220ddf0512
 F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
 F mkopcodeh.awk 7563ad235670e864ead95cf672be3fe081450ae0
@@ -28,7 +28,7 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
 F sqlite3.def c413e514217736884254739a105c8c942fdf0c2f
 F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
 F src/alter.c 03041f2464e22532601254f87cb49997fa21dcdf
-F src/analyze.c 0eb48929dd1caa21438b067c507b0ee55ce17047
+F src/analyze.c b849c23866b7da98373f7b380f40b2a5f371e962
 F src/attach.c 3615dbe960cbee4aa5ea300b8a213dad36527b0f
 F src/auth.c 18c5a0befe20f3a58a41e3ddd78f372faeeefe1f
 F src/btree.c ec55bd70052cdd0958f3a0e79ad58d93561acb20
@@ -63,10 +63,10 @@ F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
 F src/random.c 90adff4e73a3b249eb4f1fc2a6ff9cf78c7233a4
 F src/select.c c611471052773b94af771693686bd5bcdbbb0dba
 F src/shell.c 25b3217d7c64e6497225439d261a253a23efff26
-F src/sqlite.h.in 838382ed6b48d392366a55e07f49d9d71263e1fe
+F src/sqlite.h.in 7ccf2f61de2a0dca515e73708e561362e6c3d1e3
 F src/sqliteInt.h 2925510c0233bb24c550fc5912fcdf0dd3a4421d
 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
-F src/tclsqlite.c cccaf6b78c290d824cf8ea089b8b27377e545830
+F src/tclsqlite.c ef3276d0967cc0042bedcc1a7f09e0eb95cd3a8c
 F src/test1.c 722c1444b5774705eb6eb11163343fc94ffe17f7
 F src/test2.c 716c1809dba8e5be6093703e9cada99d627542dc
 F src/test3.c 683e1e3819152ffd35da2f201e507228921148d0
@@ -91,10 +91,11 @@ F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
 F test/alter.test 9d6837a3d946b73df692b7cef2a7644d2e2f6bc6
 F test/alter2.test 60ba0a7057dc71ad630a1cc7c487104346849d50
 F test/alter3.test d4eecd8dbd008d0e66f1c201fa6dc2edca853c38
+F test/analyze.test a34554a015e9fdc478ae1660188feb0de4e43c2e
 F test/attach.test f320e98bcca68d100cab7666a0c9a93ac5f236bd
 F test/attach2.test 3396c012a39ddf7ba6b528d80bd79554168aa115
 F test/attach3.test 63013383adc4380af69779f34f4af19bd49f7cbe
-F test/auth.test 5129bfe268133092ad2928b8644ef97fa4602b2e
+F test/auth.test 6a51c57219e246bdfd4454b3f7bd4136b44ad95c
 F test/autoinc.test 2aba7dc87438d221e2f2ea0e3e7d5fb6812edf6d
 F test/autovacuum.test cf2719b17659f7a011202ad05905654cedf26023
 F test/autovacuum_crash.test 05a63b8805b20cfba7ace82856ce4ccdda075a31
@@ -269,7 +270,7 @@ F www/faq.tcl 49f31a703f74c71ce66da646aaf18b07a5042672
 F www/fileformat.tcl 900c95b9633abc3dcfc384d9ddd8eb4876793059
 F www/formatchng.tcl 053ddb73646701353a5b1c9ca6274d5900739b45
 F www/index.tcl 9527f4eed69739cf5f81b3d75e0478d1c84d0a8a
-F www/lang.tcl e0b9c55bf17a502b8f6f7731e5420278965b81a2
+F www/lang.tcl d55f580cff3f384ae82d29b1201babddf991f510
 F www/lockingv3.tcl f59b19d6c8920a931f096699d6faaf61c05db55f
 F www/mingw.tcl d96b451568c5d28545fefe0c80bee3431c73f69c
 F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf
@@ -286,7 +287,7 @@ F www/tclsqlite.tcl 425be741b8ae664f55cb1ef2371aab0a75109cf9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
 F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
-P 1a573619f558d1d67775d17aabb9d704f82ad1a8
-R a3fdedefcb771a47f367010f865883f0
+P a4886b114d2ccb3841d3d219f6b97f67745b13c2
+R 65a6648aca434084253023a9ade3ab6b
 U drh
-Z d92cfb5ebecb44f8fc7d777743031b10
+Z 5c397aa099a763af87ffe475ca34fcef
index 4da8744596631f309d73c64f5ea7675bd5333acb..e2842dd2e204b1f01762f5e668e891382144dab8 100644 (file)
@@ -1 +1 @@
-a4886b114d2ccb3841d3d219f6b97f67745b13c2
\ No newline at end of file
+bd7583a5d63412785a9c5de54d25b509da241605
\ No newline at end of file
index 76c1348992689379bdb18f99d171430207f930e4..a3f8e84c836d782e4abd6ff4e3cad125d0e2444a 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code associated with the ANALYZE command.
 **
-** @(#) $Id: analyze.c,v 1.2 2005/07/23 00:41:49 drh Exp $
+** @(#) $Id: analyze.c,v 1.3 2005/07/23 02:17:03 drh Exp $
 */
 #ifndef SQLITE_OMIT_ANALYZE
 #include "sqliteInt.h"
@@ -64,7 +64,7 @@ static void openStatTable(
   /* Open the sqlite_stat1 table for writing.
   */
   sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
-  sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, 0);
+  sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage);
   sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3);
 }
 
@@ -92,6 +92,14 @@ static void analyzeOneTable(
     /* Do no analysis for tables with fewer than 2 indices */
     return;
   }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+  if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
+      pParse->db->aDb[pTab->iDb].zName ) ){
+    return;
+  }
+#endif
+
   iIdxCur = pParse->nTab;
   for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
     /* Open a cursor to the index to be analyzed
@@ -130,9 +138,9 @@ static void analyzeOneTable(
 
     /* Do the analysis.
     */
-    sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, 0);
-    topOfLoop = sqlite3VdbeCurrentAddr(v);
     endOfLoop = sqlite3VdbeMakeLabel(v);
+    sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, endOfLoop);
+    topOfLoop = sqlite3VdbeCurrentAddr(v);
     sqlite3VdbeAddOp(v, OP_MemIncr, iMem, 0);
     for(i=0; i<nCol; i++){
       sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
@@ -263,20 +271,19 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
       if( i==1 ) continue;  /* Do not analyze the TEMP database */
       analyzeDatabase(pParse, i);
     }
-  }else if( pName2==0 ){
+  }else if( pName2==0 || pName2->n==0 ){
     /* Form 2:  Analyze the database or table named */
     iDb = sqlite3FindDb(db, pName1);
     if( iDb>=0 ){
       analyzeDatabase(pParse, iDb);
-      return;
-    }
-    z = sqlite3NameFromToken(pName1);
-    pTab = sqlite3LocateTable(pParse, z, 0);
-    sqliteFree(z);
-    if( pTab ){
-      analyzeTable(pParse, pTab);
+    }else{
+      z = sqlite3NameFromToken(pName1);
+      pTab = sqlite3LocateTable(pParse, z, 0);
+      sqliteFree(z);
+      if( pTab ){
+        analyzeTable(pParse, pTab);
+      }
     }
-    return;
   }else{
     /* Form 3: Analyze the fully qualified table name */
     iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
index 7457268c3b6e41befc23a86ad9f1e7e0b02cdab9..9590fd8bfccce7a093b3d3f43164499a92d37951 100644 (file)
@@ -12,7 +12,7 @@
 ** This header file defines the interface that the SQLite library
 ** presents to client programs.
 **
-** @(#) $Id: sqlite.h.in,v 1.137 2005/07/09 02:39:40 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.138 2005/07/23 02:17:03 drh Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -452,6 +452,7 @@ int sqlite3_set_authorizer(
 #define SQLITE_DETACH               25   /* Database Name   NULL            */
 #define SQLITE_ALTER_TABLE          26   /* Database Name   Table Name      */
 #define SQLITE_REINDEX              27   /* Index Name      NULL            */
+#define SQLITE_ANALYZE              28   /* Table Name      NULL            */
 
 
 /*
index 64a2a3b8ec143862a9084641014d2c9c2cd62b6e..bc98e348df40962b34861e34c333a22b18b25cf7 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** A TCL Interface to SQLite
 **
-** $Id: tclsqlite.c,v 1.127 2005/06/26 17:55:34 drh Exp $
+** $Id: tclsqlite.c,v 1.128 2005/07/23 02:17:03 drh Exp $
 */
 #ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */
 
@@ -472,6 +472,7 @@ static int auth_callback(
     case SQLITE_DETACH            : zCode="SQLITE_DETACH"; break;
     case SQLITE_ALTER_TABLE       : zCode="SQLITE_ALTER_TABLE"; break;
     case SQLITE_REINDEX           : zCode="SQLITE_REINDEX"; break;
+    case SQLITE_ANALYZE           : zCode="SQLITE_ANALYZE"; break;
     default                       : zCode="????"; break;
   }
   Tcl_DStringInit(&str);
diff --git a/test/analyze.test b/test/analyze.test
new file mode 100644 (file)
index 0000000..a9f0118
--- /dev/null
@@ -0,0 +1,190 @@
+# 2005 July 22
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+# This file implements tests for the ANALYZE command.
+#
+# $Id: analyze.test,v 1.1 2005/07/23 02:17:03 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# There is nothing to test if ANALYZE is disable for this build.
+#
+ifcapable {!analyze} {
+  finish_test
+  return
+}
+
+# Basic sanity checks.
+#
+do_test analyze-1.1 {
+  catchsql {
+    ANALYZE no_such_table
+  }
+} {1 {no such table: no_such_table}}
+do_test analyze-1.2 {
+  execsql {
+    SELECT count(*) FROM sqlite_master WHERE name='sqlite_stat1'
+  }
+} {0}
+do_test analyze-1.3 {
+  catchsql {
+    ANALYZE no_such_db.no_such_table
+  }
+} {1 {unknown database no_such_db}}
+do_test analyze-1.4 {
+  execsql {
+    SELECT count(*) FROM sqlite_master WHERE name='sqlite_stat1'
+  }
+} {0}
+do_test analyze-1.5 {
+  catchsql {
+    ANALYZE
+  }
+} {0 {}}
+do_test analyze-1.6 {
+  execsql {
+    SELECT count(*) FROM sqlite_master WHERE name='sqlite_stat1'
+  }
+} {1}
+do_test analyze-1.7 {
+  execsql {
+    SELECT * FROM sqlite_stat1
+  }
+} {}
+do_test analyze-1.8 {
+  catchsql {
+    ANALYZE main
+  }
+} {0 {}}
+do_test analyze-1.9 {
+  execsql {
+    SELECT * FROM sqlite_stat1
+  }
+} {}
+do_test analyze-1.10 {
+  catchsql {
+    CREATE TABLE t1(a,b);
+    ANALYZE main.t1;
+  }
+} {0 {}}
+do_test analyze-1.11 {
+  execsql {
+    SELECT * FROM sqlite_stat1
+  }
+} {}
+do_test analyze-1.12 {
+  catchsql {
+    ANALYZE t1;
+  }
+} {0 {}}
+do_test analyze-1.13 {
+  execsql {
+    SELECT * FROM sqlite_stat1
+  }
+} {}
+
+# Create some indices that can be analyzed.  But do not yet add
+# data.  Without data in the tables, no analysis is done.
+#
+do_test analyze-2.1 {
+  execsql {
+    CREATE INDEX t1i1 ON t1(a);
+    ANALYZE main.t1;
+    SELECT * FROM sqlite_stat1 ORDER BY idx;
+  }
+} {}
+do_test analyze-2.2 {
+  execsql {
+    CREATE INDEX t1i2 ON t1(b);
+    ANALYZE t1;
+    SELECT * FROM sqlite_stat1 ORDER BY idx;
+  }
+} {}
+do_test analyze-2.3 {
+  execsql {
+    CREATE INDEX t1i3 ON t1(a,b);
+    ANALYZE main;
+    SELECT * FROM sqlite_stat1 ORDER BY idx;
+  }
+} {}
+
+# Start adding data to the table.  Verify that the analysis
+# is done correctly.
+#
+do_test analyze-3.1 {
+  execsql {
+    INSERT INTO t1 VALUES(1,2);
+    INSERT INTO t1 VALUES(1,3);
+    ANALYZE main.t1;
+    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
+  }
+} {t1i1 2 t1i2 1 t1i3 {2 1}}
+do_test analyze-3.2 {
+  execsql {
+    INSERT INTO t1 VALUES(1,4);
+    INSERT INTO t1 VALUES(1,5);
+    ANALYZE t1;
+    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
+  }
+} {t1i1 4 t1i2 1 t1i3 {4 1}}
+do_test analyze-3.3 {
+  execsql {
+    INSERT INTO t1 VALUES(2,5);
+    ANALYZE main;
+    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
+  }
+} {t1i1 3 t1i2 2 t1i3 {3 1}}
+do_test analyze-3.4 {
+  execsql {
+    CREATE TABLE t2 AS SELECT * FROM t1;
+    CREATE INDEX t2i1 ON t2(a);
+    CREATE INDEX t2i2 ON t2(b);
+    CREATE INDEX t2i3 ON t2(a,b);
+    ANALYZE;
+    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
+  }
+} {t1i1 3 t1i2 2 t1i3 {3 1} t2i1 3 t2i2 2 t2i3 {3 1}}
+do_test analyze-3.5 {
+  execsql {
+    DROP INDEX t2i3;
+    ANALYZE t1;
+    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
+  }
+} {t1i1 3 t1i2 2 t1i3 {3 1} t2i1 3 t2i2 2 t2i3 {3 1}}
+do_test analyze-3.6 {
+  execsql {
+    ANALYZE t2;
+    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
+  }
+} {t1i1 3 t1i2 2 t1i3 {3 1} t2i1 3 t2i2 2}
+do_test analyze-3.7 {
+  execsql {
+    DROP INDEX t2i2;
+    ANALYZE t2;
+    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
+  }
+} {t1i1 3 t1i2 2 t1i3 {3 1}}
+do_test analyze-3.8 {
+  execsql {
+    CREATE TABLE t3 AS SELECT a, b, rowid AS c, 'hi' AS d FROM t1;
+    CREATE INDEX t3i1 ON t3(a);
+    CREATE INDEX t3i2 ON t3(a,b,c,d);
+    CREATE INDEX t3i3 ON t3(d,b,c,a);
+    DROP TABLE t1;
+    DROP TABLE t2;
+    ANALYZE;
+    SELECT idx, stat FROM sqlite_stat1 ORDER BY idx;
+  }
+} {t3i1 3 t3i2 {3 1 1 1} t3i3 {5 2 1 1}}
+
+
+finish_test
index 1bd32cb65b78acff77edec31f836bb74c42011d4..cc43b2daebbf19057023204fe54cb62a9e1fe7f2 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this script is testing the ATTACH and DETACH commands
 # and related functionality.
 #
-# $Id: auth.test,v 1.27 2005/03/29 03:11:00 danielk1977 Exp $
+# $Id: auth.test,v 1.28 2005/07/23 02:17:03 drh Exp $
 #
 
 set testdir [file dirname $argv0]
@@ -1951,6 +1951,49 @@ ifcapable tempdb {
 
 } ;# ifcapable reindex 
 
+ifcapable analyze {
+  proc auth {code args} {
+    if {$code=="SQLITE_ANALYZE"} {
+      set ::authargs [concat $::authargs $args]
+    }
+    return SQLITE_OK
+  }
+  do_test auth-1.294 {
+    set ::authargs {}
+    execsql {
+      CREATE TABLE t4(a,b,c);
+      CREATE INDEX t4i1 ON t4(a);
+      CREATE INDEX t4i2 ON t4(b,a,c);
+      INSERT INTO t4 VALUES(1,2,3);
+      ANALYZE;
+    }
+    set ::authargs
+  } {t4 {} main {}}
+  do_test auth-1.295 {
+    execsql {
+      SELECT count(*) FROM sqlite_stat1;
+    }
+  } 2
+  proc auth {code args} {
+    if {$code=="SQLITE_ANALYZE"} {
+      set ::authargs [concat $::authargs $args]
+      return SQLITE_DENY
+    }
+    return SQLITE_OK
+  }
+  do_test auth-1.296 {
+    set ::authargs {}
+    catchsql {
+      ANALYZE;
+    }
+  } {1 {not authorized}}
+  do_test auth-1.297 {
+    execsql {
+      SELECT count(*) FROM sqlite_stat1;
+    }
+  } 2
+} ;# ifcapable analyze
+
 do_test auth-2.1 {
   proc auth {code arg1 arg2 arg3 arg4} {
     if {$code=="SQLITE_READ" && $arg1=="t3" && $arg2=="x"} {
index c54c46af6235b52dce31d646cc09ee835be11bd2..8e4fe79c86947979f357639516f0a265820e2085 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this Tcl script to generate the lang-*.html files.
 #
-set rcsid {$Id: lang.tcl,v 1.94 2005/07/22 23:56:50 drh Exp $}
+set rcsid {$Id: lang.tcl,v 1.95 2005/07/23 02:17:03 drh Exp $}
 source common.tcl
 
 if {[llength $argv]>0} {
@@ -76,6 +76,7 @@ foreach {section} [lsort -index 0 -dictionary {
   {{DETACH DATABASE} detach}
   {REINDEX reindex}
   {{ALTER TABLE} altertable}
+  {{ANALYZE} analyze}
 }] {
   foreach {s_title s_tag} $section {}
   puts "<li><a href=\"[slink $s_tag]\">$s_title</a></li>"
@@ -187,6 +188,35 @@ be readable by SQLite version 3.1.3 and earlier until the database
 is <a href="lang_vacuum.html">VACUUM</a>ed.</p>
 }
 
+Section {ANALYZE} analyze
+
+Syntax {sql-statement} {
+  ANALYZE
+}
+Syntax {sql-statement} {
+  ANALYZE <database-name>
+}
+Syntax {sql-statement} {
+  ANALYZE [<database-name> .] <table-name>
+}
+
+puts {
+<p>The ANALYZE command gathers statistics about indices and stores them
+in a special tables in the database where the query optimizer can use
+them to help make better index choices.
+If no arguments are given, all indices in all attached databases are
+analyzed.  If a database name is given as the argument, all indices
+in that one database are analyzed.  If the argument is a table name,
+then only indices associated with that one table are analyzed.</p>
+
+<p>The initial implementation stores all statistics in a single
+table named <b>sqlite_stat1</b>.  Future enhancements may create
+additional tables with the same name pattern except with the "1"
+changed to a different digit.  The <b>sqlite_stat1</b> table cannot
+be DROPped, but it all the content can be DELETEd which as the
+same effect.</p>
+}
+
 Section {ATTACH DATABASE} attach
 
 Syntax {sql-statement} {
@@ -1484,8 +1514,7 @@ Syntax {sql-statement} {
 
 puts {
 <p>The REINDEX command is used to delete and recreate indices from scratch.
-This is primarily useful when the definition of a collation sequence has 
-changed.
+This is useful when the definition of a collation sequence has changed.
 </p>
 
 <p>In the first form, all indices in all attached databases that use the