| ︙ | | |
423
424
425
426
427
428
429
430
431
432
433
434
435
436
|
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
z = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
utf8_printf(iotrace, "%s", z);
sqlite3_free(z);
}
#endif
/*
** Output string zUtf to stream pOut as w characters. If w is negative,
** then right-justify the text. W is the width in UTF-8 characters, not
** in bytes. This is different from the %*.*s specification in printf
** since with %*.*s the width is measured in bytes, not characters.
*/
static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
int i;
int n;
int aw = w<0 ? -w : w;
char zBuf[1000];
if( aw>sizeof(zBuf)/3 ) aw = sizeof(zBuf)/3;
for(i=n=0; zUtf[i]; i++){
if( (zUtf[i]&0xc0)!=0x80 ){
n++;
if( n==aw ){
do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
break;
}
}
}
if( n>=aw ){
utf8_printf(pOut, "%.*s", i, zUtf);
}else if( w<0 ){
utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
}else{
utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
}
}
/*
** Determines if a string is a number of not.
*/
static int isNumber(const char *z, int *realnum){
if( *z=='-' || *z=='+' ) z++;
if( !IsDigit(*z) ){
|
| ︙ | | |
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
|
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
-
+
+
|
static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
int i;
char *zBlob = (char *)pBlob;
raw_printf(out,"X'");
for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
raw_printf(out,"'");
}
/*
** Find a string that is not found anywhere in z[]. Return a pointer
** to that string.
**
** Try to use zA and zB first. If both of those are already found in z[]
** then make up some string and store it in the buffer zBuf.
*/
static const char *unused_string(
const char *z, /* Result must not appear anywhere in z */
const char *zA, const char *zB, /* Try these first */
char *zBuf /* Space to store a generated string */
){
unsigned i = 0;
if( strstr(z, zA)==0 ) return zA;
if( strstr(z, zB)==0 ) return zB;
do{
sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
}while( strstr(z,zBuf)!=0 );
return zBuf;
}
/*
** Output the given string as a quoted string using SQL quoting conventions.
**
** See also: output_quoted_escaped_string()
*/
static void output_quoted_string(FILE *out, const char *z){
int i;
char c;
setBinaryMode(out, 1);
for(i=0; (c = z[i])!=0 && c!='\''; i++){}
if( c==0 ){
utf8_printf(out,"'%s'",z);
}else{
raw_printf(out, "'");
while( *z ){
for(i=0; (c = z[i])!=0 && c!='\''; i++){}
if( c=='\'' ) i++;
if( i ){
utf8_printf(out, "%.*s", i, z);
z += i;
}
if( c=='\'' ){
raw_printf(out, "'");
continue;
}
if( c==0 ){
break;
}
z++;
}
raw_printf(out, "'");
}
setTextMode(out, 1);
}
/*
** Output the given string as a quoted string using SQL quoting conventions.
** The "\n" and "\r" characters are converted to char(10) and char(13)
** to prevent them from being transformed by end-of-line translators.
** Additionallly , escape the "\n" and "\r" characters so that they do not
** get corrupted by end-of-line translation facilities in some operating
** systems.
**
** This is like output_quoted_string() but with the addition of the \r\n
** escape mechanism.
*/
static void output_quoted_string(FILE *out, const char *z){
static void output_quoted_escaped_string(FILE *out, const char *z){
int i;
char c;
setBinaryMode(out, 1);
for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
if( c==0 ){
utf8_printf(out,"'%s'",z);
}else{
const char *zNL = 0;
const char *zCR = 0;
int inQuote = 0;
int bStarted = 0;
int nNL = 0;
int nCR = 0;
char zBuf1[20], zBuf2[20];
for(i=0; z[i]; i++){
if( z[i]=='\n' ) nNL++;
if( z[i]=='\r' ) nCR++;
}
if( nNL ){
raw_printf(out, "replace(");
zNL = unused_string(z, "\\n", "\\012", zBuf1);
}
if( nCR ){
raw_printf(out, "replace(");
zCR = unused_string(z, "\\r", "\\015", zBuf2);
}
raw_printf(out, "'");
while( *z ){
for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
if( c=='\'' ) i++;
if( i ){
if( !inQuote ){
if( bStarted ) raw_printf(out, "||");
raw_printf(out, "'");
inQuote = 1;
}
utf8_printf(out, "%.*s", i, z);
z += i;
bStarted = 1;
}
if( c=='\'' ){
raw_printf(out, "'");
continue;
}
if( inQuote ){
raw_printf(out, "'");
inQuote = 0;
}
if( c==0 ){
break;
}
z++;
for(i=0; (c = z[i])=='\r' || c=='\n'; i++){
if( bStarted ) raw_printf(out, "||");
raw_printf(out, "char(%d)", c);
if( c=='\n' ){
raw_printf(out, "%s", zNL);
continue;
}
raw_printf(out, "%s", zCR);
bStarted = 1;
}
z += i;
}
raw_printf(out, "'");
if( nCR ){
raw_printf(out, ",'%s',char(13))", zCR);
}
if( nNL ){
if( inQuote ) raw_printf(out, "'");
raw_printf(out, ",'%s',char(10))", zNL);
}
}
setTextMode(out, 1);
}
/*
** Output the given string as a quoted according to C or TCL quoting rules.
*/
|
| ︙ | | |
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
|
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
|
-
-
-
+
+
-
-
-
-
|
n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue);
if( w<n ) w = n;
}
if( i<ArraySize(p->actualWidth) ){
p->actualWidth[i] = w;
}
if( showHdr ){
if( w<0 ){
utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i],
i==nArg-1 ? rowSep : " ");
utf8_width_print(p->out, w, azCol[i]);
utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
}else{
utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i],
i==nArg-1 ? rowSep : " ");
}
}
}
if( showHdr ){
for(i=0; i<nArg; i++){
int w;
if( i<ArraySize(p->actualWidth) ){
w = p->actualWidth[i];
|
| ︙ | | |
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
|
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
|
-
-
-
-
+
+
-
-
-
-
-
|
}
if( i==1 && p->aiIndent && p->pStmt ){
if( p->iIndent<p->nIndent ){
utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
}
p->iIndent++;
}
if( w<0 ){
utf8_printf(p->out,"%*.*s%s",-w,-w,
azArg[i] ? azArg[i] : p->nullValue,
i==nArg-1 ? rowSep : " ");
utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
}else{
utf8_printf(p->out,"%-*.*s%s",w,w,
azArg[i] ? azArg[i] : p->nullValue,
i==nArg-1 ? rowSep : " ");
}
}
break;
}
case MODE_Semi: { /* .schema and .fullschema output */
printSchemaLine(p->out, azArg[0], ";\n");
break;
}
|
| ︙ | | |
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
|
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
|
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
+
-
+
-
-
+
-
-
+
|
output_csv(p, azArg[i], i<nArg-1);
}
utf8_printf(p->out, "%s", p->rowSeparator);
}
setTextMode(p->out, 1);
break;
}
case MODE_Quote:
case MODE_Insert: {
if( azArg==0 ) break;
if( p->cMode==MODE_Insert ){
utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
if( p->showHeader ){
raw_printf(p->out,"(");
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
utf8_printf(p->out, "%s%s", zSep, azCol[i]);
utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
if( p->showHeader ){
raw_printf(p->out,"(");
for(i=0; i<nArg; i++){
if( i>0 ) raw_printf(p->out, ",");
if( quoteChar(azCol[i]) ){
char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
utf8_printf(p->out, "%s", z);
sqlite3_free(z);
}else{
raw_printf(p->out, "%s", azCol[i]);
}
}
raw_printf(p->out,")");
}
raw_printf(p->out," VALUES(");
}else if( p->cnt==0 && p->showHeader ){
raw_printf(p->out,")");
}
p->cnt++;
for(i=0; i<nArg; i++){
raw_printf(p->out, i>0 ? "," : " VALUES(");
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
utf8_printf(p->out,"NULL");
}else if( aiType && aiType[i]==SQLITE_TEXT ){
output_quoted_escaped_string(p->out, azArg[i]);
}else if( aiType && aiType[i]==SQLITE_INTEGER ){
utf8_printf(p->out,"%s", azArg[i]);
}else if( aiType && aiType[i]==SQLITE_FLOAT ){
char z[50];
double r = sqlite3_column_double(p->pStmt, i);
sqlite3_snprintf(50,z,"%!.20g", r);
raw_printf(p->out, "%s", z);
}else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
const void *pBlob = sqlite3_column_blob(p->pStmt, i);
int nBlob = sqlite3_column_bytes(p->pStmt, i);
output_hex_blob(p->out, pBlob, nBlob);
}else if( isNumber(azArg[i], 0) ){
utf8_printf(p->out,"%s", azArg[i]);
}else{
output_quoted_escaped_string(p->out, azArg[i]);
}
}
raw_printf(p->out,");\n");
break;
}
case MODE_Quote: {
if( azArg==0 ) break;
if( p->cnt==0 && p->showHeader ){
for(i=0; i<nArg; i++){
if( i>0 ) raw_printf(p->out, ",");
output_quoted_string(p->out, azCol[i]);
}
raw_printf(p->out,"\n");
}
p->cnt++;
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
if( i>0 ) raw_printf(p->out, ",");
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
utf8_printf(p->out,"%sNULL",zSep);
utf8_printf(p->out,"NULL");
}else if( aiType && aiType[i]==SQLITE_TEXT ){
if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
output_quoted_string(p->out, azArg[i]);
}else if( aiType && aiType[i]==SQLITE_INTEGER ){
utf8_printf(p->out,"%s%s",zSep, azArg[i]);
utf8_printf(p->out,"%s", azArg[i]);
}else if( aiType && aiType[i]==SQLITE_FLOAT ){
char z[50];
double r = sqlite3_column_double(p->pStmt, i);
sqlite3_snprintf(50,z,"%!.20g", r);
raw_printf(p->out, "%s%s", zSep, z);
raw_printf(p->out, "%s", z);
}else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
const void *pBlob = sqlite3_column_blob(p->pStmt, i);
int nBlob = sqlite3_column_bytes(p->pStmt, i);
if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
output_hex_blob(p->out, pBlob, nBlob);
}else if( isNumber(azArg[i], 0) ){
utf8_printf(p->out,"%s%s",zSep, azArg[i]);
utf8_printf(p->out,"%s", azArg[i]);
}else{
if( zSep[0] ) utf8_printf(p->out,"%s",zSep);
output_quoted_string(p->out, azArg[i]);
}
}
raw_printf(p->out,p->cMode==MODE_Quote?"\n":");\n");
raw_printf(p->out,"\n");
break;
}
case MODE_Ascii: {
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
|
| ︙ | | |
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
|
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
|
-
+
+
-
+
-
-
-
+
+
-
+
+
|
**
** These six values are used by the C logic below to generate the report.
*/
const char *zSql =
"SELECT "
" 'EXPLAIN QUERY PLAN SELECT rowid FROM ' || quote(s.name) || ' WHERE '"
" || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
" || fkey_collate_clause(f.[table], f.[to], s.name, f.[from]),' AND ')"
" || fkey_collate_clause("
" f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
", "
" 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
" || group_concat('*=?', ' AND ') || ')'"
", "
" s.name || '(' || group_concat(f.[from], ', ') || ')'"
", "
" f.[table] || '(' || group_concat(COALESCE(f.[to], "
" f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
" (SELECT name FROM pragma_table_info(f.[table]) WHERE pk=seq+1)"
" )) || ')'"
", "
" 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
" || ' ON ' || quote(s.name) || '('"
" || group_concat(quote(f.[from]) ||"
" fkey_collate_clause(f.[table], f.[to], s.name, f.[from]), ', ')"
" fkey_collate_clause("
" f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
" || ');'"
", "
" f.[table] "
"FROM sqlite_master AS s, pragma_foreign_key_list(s.name) AS f "
"LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
"GROUP BY s.name, f.id "
"ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
;
const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
for(i=2; i<nArg; i++){
int n = (int)strlen(azArg[i]);
if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
bVerbose = 1;
}
else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
|
| ︙ | | |
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
|
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
|
+
-
+
+
+
|
const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
if( rc!=SQLITE_OK ) break;
if( SQLITE_ROW==sqlite3_step(pExplain) ){
const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
res = (
res = (0==sqlite3_strglob(zGlob, zPlan));
0==sqlite3_strglob(zGlob, zPlan)
|| 0==sqlite3_strglob(zGlobIPK, zPlan)
);
}
rc = sqlite3_finalize(pExplain);
if( rc!=SQLITE_OK ) break;
if( res<0 ){
raw_printf(stderr, "Error: internal error");
break;
|
| ︙ | | |
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
|
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
|
+
|
if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){
rc = shell_dbinfo_command(p, nArg, azArg);
}else
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
const char *zLike = 0;
int i;
int savedShowHeader = p->showHeader;
ShellClearFlag(p, SHFLG_PreserveRowid);
for(i=1; i<nArg; i++){
if( azArg[i][0]=='-' ){
const char *z = azArg[i]+1;
if( z[0]=='-' ) z++;
if( strcmp(z,"preserve-rowids")==0 ){
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
| ︙ | | |
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
|
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
|
+
|
open_db(p, 0);
/* When playing back a "dump", the content might appear in an order
** which causes immediate foreign key constraints to be violated.
** So disable foreign-key constraint enforcement to prevent problems. */
raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
raw_printf(p->out, "BEGIN TRANSACTION;\n");
p->writableSchema = 0;
p->showHeader = 0;
/* Set writable_schema=ON since doing so forces SQLite to initialize
** as much of the schema as it can even if the sqlite_master table is
** corrupt. */
sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
p->nErr = 0;
if( zLike==0 ){
run_schema_dump_query(p,
|
| ︙ | | |
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
|
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
|
+
|
if( p->writableSchema ){
raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
p->writableSchema = 0;
}
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
p->showHeader = savedShowHeader;
}else
if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
if( nArg==2 ){
setOrClearFlag(p, SHFLG_Echo, azArg[1]);
}else{
raw_printf(stderr, "Usage: .echo on|off\n");
|
| ︙ | | |