aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyze.c12
-rw-r--r--src/shell.c49
-rw-r--r--src/sqlite.h.in12
-rw-r--r--src/sqliteInt.h3
-rw-r--r--src/where.c15
5 files changed, 75 insertions, 16 deletions
diff --git a/src/analyze.c b/src/analyze.c
index c614350ae..3a6823c10 100644
--- a/src/analyze.c
+++ b/src/analyze.c
@@ -1432,10 +1432,13 @@ static void decodeIntArray(
if( sqlite3_strglob("unordered*", z)==0 ){
pIndex->bUnordered = 1;
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
- int v32 = 0;
- sqlite3GetInt32(z+3, &v32);
- pIndex->szIdxRow = sqlite3LogEst(v32);
+ pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
}
+#ifdef SQLITE_ENABLE_COSTMULT
+ else if( sqlite3_strglob("costmult=[0-9]*",z)==0 ){
+ pIndex->pTable->costMult = sqlite3LogEst(sqlite3Atoi(z+9));
+ }
+#endif
while( z[0]!=0 && z[0]!=' ' ) z++;
while( z[0]==' ' ) z++;
}
@@ -1484,6 +1487,9 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
}else{
Index fakeIdx;
fakeIdx.szIdxRow = pTable->szTabRow;
+#ifdef SQLITE_ENABLE_COSTMULT
+ fakeIdx.pTable = pTable;
+#endif
decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
pTable->szTabRow = fakeIdx.szIdxRow;
}
diff --git a/src/shell.c b/src/shell.c
index 97167dc87..ea92b07e3 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -64,6 +64,7 @@
#if defined(_WIN32) || defined(WIN32)
# include <io.h>
+# include <fcntl.h>
#define isatty(h) _isatty(h)
#ifndef access
# define access(f,m) _access((f),(m))
@@ -458,6 +459,7 @@ struct callback_data {
int showHeader; /* True to show column names in List or Column mode */
char *zDestTable; /* Name of destination table when MODE_Insert */
char separator[20]; /* Separator character for MODE_List */
+ char newline[20]; /* Record separator in MODE_Csv */
int colWidth[100]; /* Requested width of each column when in column mode*/
int actualWidth[100]; /* Actual width of each column */
char nullvalue[20]; /* The text to print when a NULL comes back from
@@ -659,7 +661,8 @@ static const char needCsvQuote[] = {
/*
** Output a single term of CSV. Actually, p->separator is used for
** the separator, which may or may not be a comma. p->nullvalue is
-** the null value. Strings are quoted if necessary.
+** the null value. Strings are quoted if necessary. The separator
+** is only issued if bSep is true.
*/
static void output_csv(struct callback_data *p, const char *z, int bSep){
FILE *out = p->out;
@@ -855,17 +858,26 @@ static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int
break;
}
case MODE_Csv: {
+#if defined(WIN32) || defined(_WIN32)
+ fflush(p->out);
+ _setmode(_fileno(p->out), _O_BINARY);
+#endif
if( p->cnt++==0 && p->showHeader ){
for(i=0; i<nArg; i++){
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
}
- fprintf(p->out,"\n");
+ fprintf(p->out,"%s",p->newline);
}
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- output_csv(p, azArg[i], i<nArg-1);
+ if( azArg>0 ){
+ for(i=0; i<nArg; i++){
+ output_csv(p, azArg[i], i<nArg-1);
+ }
+ fprintf(p->out,"%s",p->newline);
}
- fprintf(p->out,"\n");
+#if defined(WIN32) || defined(_WIN32)
+ fflush(p->out);
+ _setmode(_fileno(p->out), _O_TEXT);
+#endif
break;
}
case MODE_Insert: {
@@ -1619,7 +1631,8 @@ static char zHelp[] =
".schema ?TABLE? Show the CREATE statements\n"
" If TABLE specified, only show tables matching\n"
" LIKE pattern TABLE.\n"
- ".separator STRING Change separator used by output mode and .import\n"
+ ".separator STRING ?NL? Change separator used by output mode and .import\n"
+ " NL is the end-of-line mark for CSV\n"
".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
".show Show the current values for various settings\n"
".stats on|off Turn stats on or off\n"
@@ -2751,6 +2764,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
p->mode = MODE_Csv;
sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
+ sqlite3_snprintf(sizeof(p->newline), p->newline, "\r\n");
}else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
p->mode = MODE_List;
sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
@@ -3029,13 +3043,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
#endif
if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
- if( nArg==2 ){
- sqlite3_snprintf(sizeof(p->separator), p->separator,
- "%.*s", (int)sizeof(p->separator)-1, azArg[1]);
- }else{
- fprintf(stderr, "Usage: .separator STRING\n");
+ if( nArg<2 || nArg>3 ){
+ fprintf(stderr, "Usage: .separator SEPARATOR ?NEWLINE?\n");
rc = 1;
}
+ if( nArg>=2 ){
+ sqlite3_snprintf(sizeof(p->separator), p->separator, azArg[1]);
+ }
+ if( nArg>=3 ){
+ sqlite3_snprintf(sizeof(p->newline), p->newline, azArg[2]);
+ }
}else
if( c=='s'
@@ -3076,6 +3093,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
strlen30(p->outfile) ? p->outfile : "stdout");
fprintf(p->out,"%9.9s: ", "separator");
output_c_string(p->out, p->separator);
+ fprintf(p->out," ");
+ output_c_string(p->out, p->newline);
fprintf(p->out, "\n");
fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
fprintf(p->out,"%9.9s: ","width");
@@ -3692,6 +3711,7 @@ static const char zOptions[] =
#ifdef SQLITE_ENABLE_MULTIPLEX
" -multiplex enable the multiplexor VFS\n"
#endif
+ " -newline SEP set newline character(s) for CSV\n"
" -nullvalue TEXT set text string for NULL values. Default ''\n"
" -separator SEP set output field separator. Default: '|'\n"
" -stats print memory stats before each finalize\n"
@@ -3721,6 +3741,7 @@ static void main_init(struct callback_data *data) {
memset(data, 0, sizeof(*data));
data->mode = MODE_List;
memcpy(data->separator,"|", 2);
+ memcpy(data->newline,"\r\n", 3);
data->showHeader = 0;
sqlite3_config(SQLITE_CONFIG_URI, 1);
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
@@ -3813,6 +3834,7 @@ int main(int argc, char **argv){
if( z[1]=='-' ) z++;
if( strcmp(z,"-separator")==0
|| strcmp(z,"-nullvalue")==0
+ || strcmp(z,"-newline")==0
|| strcmp(z,"-cmd")==0
){
(void)cmdline_option_value(argc, argv, ++i);
@@ -3922,6 +3944,9 @@ int main(int argc, char **argv){
}else if( strcmp(z,"-separator")==0 ){
sqlite3_snprintf(sizeof(data.separator), data.separator,
"%s",cmdline_option_value(argc,argv,++i));
+ }else if( strcmp(z,"-newline")==0 ){
+ sqlite3_snprintf(sizeof(data.newline), data.newline,
+ "%s",cmdline_option_value(argc,argv,++i));
}else if( strcmp(z,"-nullvalue")==0 ){
sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
"%s",cmdline_option_value(argc,argv,++i));
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 93cde7834..67113dc41 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -4711,6 +4711,13 @@ int sqlite3_sleep(int);
** is a NULL pointer, then SQLite performs a search for an appropriate
** temporary file directory.
**
+** Applications are strongly discouraged from using this global variable.
+** It is required to set a temporary folder on Windows Runtime (WinRT).
+** But for all other platforms, it is highly recommended that applications
+** neither read nor write this variable. This global variable is a relic
+** that exists for backwards compatibility of legacy applications and should
+** be avoided in new projects.
+**
** It is not safe to read or modify this variable in more than one
** thread at a time. It is not safe to read or modify this variable
** if a [database connection] is being used at the same time in a separate
@@ -4729,6 +4736,11 @@ int sqlite3_sleep(int);
** Hence, if this variable is modified directly, either it should be
** made NULL or made to point to memory obtained from [sqlite3_malloc]
** or else the use of the [temp_store_directory pragma] should be avoided.
+** Except when requested by the [temp_store_directory pragma], SQLite
+** does not free the memory that sqlite3_temp_directory points to. If
+** the application wants that memory to be freed, it must do
+** so itself, taking care to only do so after all [database connection]
+** objects have been destroyed.
**
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index ca075307e..7a5d225b8 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1477,6 +1477,9 @@ struct Table {
i16 nCol; /* Number of columns in this table */
u16 nRef; /* Number of pointers to this Table */
LogEst szTabRow; /* Estimated size of each table row in bytes */
+#ifdef SQLITE_ENABLE_COSTMULT
+ LogEst costMult; /* Cost multiplier for using this table */
+#endif
u8 tabFlags; /* Mask of TF_* values */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
#ifndef SQLITE_OMIT_ALTERTABLE
diff --git a/src/where.c b/src/where.c
index ff18d5d4e..3901dd468 100644
--- a/src/where.c
+++ b/src/where.c
@@ -4231,6 +4231,16 @@ static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){
}
/*
+** Adjust the cost C by the costMult facter T. This only occurs if
+** compiled with -DSQLITE_ENABLE_COSTMULT
+*/
+#ifdef SQLITE_ENABLE_COSTMULT
+# define ApplyCostMultiplier(C,T) C += T
+#else
+# define ApplyCostMultiplier(C,T)
+#endif
+
+/*
** We have so far matched pBuilder->pNew->u.btree.nEq terms of the
** index pIndex. Try to match one more.
**
@@ -4457,6 +4467,7 @@ static int whereLoopAddBtreeIndex(
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut + 16);
}
+ ApplyCostMultiplier(pNew->rRun, pProbe->pTable->costMult);
nOutUnadjusted = pNew->nOut;
pNew->rRun += nInMul + nIn;
@@ -4671,6 +4682,7 @@ static int whereLoopAddBtree(
** approximately 7*N*log2(N) where N is the number of rows in
** the table being indexed. */
pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
+ ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
/* TUNING: Each index lookup yields 20 rows in the table. This
** is more than the usual guess of 10 rows, since we have no way
** of knowning how selective the index will ultimately be. It would
@@ -4712,6 +4724,7 @@ static int whereLoopAddBtree(
pNew->iSortIdx = b ? iSortIdx : 0;
/* TUNING: Cost of full table scan is (N*3.0). */
pNew->rRun = rSize + 16;
+ ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew);
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
@@ -4747,7 +4760,7 @@ static int whereLoopAddBtree(
if( m!=0 ){
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
}
-
+ ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew);
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;