Fossil SCM
Merge updates from trunk.
Commit
a6647539f6f7f589a03b65251204ab73e6ca3d63
Parent
fc7e8d01d459ea8…
62 files changed
+1
-1
+1
-1
+1
+2
-2
+6
-10
+6
-2
+5
-1
+5
-1
+267
-87
+9
-3
+2
-2
+31
-24
+2
-4
+53
-17
+1
-1
+1
-1
+1
-1
+2
-2
+3
-1
+21
-1
+3
-1
+3
-1
+21
-3
+1
-1
+2
-2
+55
+1
+47
-1
+6
+12
-7
+1
+844
-470
+844
-470
+4
-4
+4
-4
+1
-1
+18
-4
+7
-2
+7
-2
+11
-32
+528
+10
-5
+7
-3
+3
-3
+1
-1
+23
+16
-4
+25
-1
+25
-1
+25
-1
+25
-1
+20
+3
+3
+398
-204
+29
-28
+3
-4
+1
-1
+1
-1
+2
-2
+3
-3
+1
-1
~
src/add.c
~
src/bisect.c
~
src/cgi.c
~
src/checkin.c
~
src/cson_amalgamation.c
~
src/cson_amalgamation.h
~
src/db.c
~
src/db.c
~
src/diff.c
~
src/diffcmd.c
~
src/doc.c
~
src/file.c
~
src/http_socket.c
~
src/info.c
~
src/json_diff.c
~
src/json_timeline.c
~
src/json_wiki.c
~
src/login.c
~
src/main.c
~
src/main.mk
~
src/makemake.tcl
~
src/makemake.tcl
~
src/manifest.c
~
src/merge.c
~
src/merge3.c
~
src/regexp.c
~
src/report.c
~
src/setup.c
~
src/shell.c
~
src/skins.c
~
src/sqlcmd.c
~
src/sqlite3.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/sqlite3.h
~
src/stat.c
~
src/style.c
~
src/th_main.c
~
src/th_main.c
~
src/timeline.c
~
src/unicode.c
~
src/update.c
~
src/user.c
~
src/utf8.c
~
src/wiki.c
~
test/diff-test-1.wiki
~
win/Makefile.dmc
~
win/Makefile.mingw
~
win/Makefile.mingw
~
win/Makefile.mingw.mistachkin
~
win/Makefile.mingw.mistachkin
~
win/Makefile.msc
~
win/fossil.rc
~
win/fossil.rc
~
win/include/dirent.h
~
www/build.wiki
~
www/checkin_names.wiki
~
www/contribute.wiki
~
www/index.wiki
~
www/mkindex.tcl
~
www/permutedindex.wiki
~
www/quickstart.wiki
+1
-1
| --- src/add.c | ||
| +++ src/add.c | ||
| @@ -140,11 +140,11 @@ | ||
| 140 | 140 | const char *zPath, /* Tree-name of file to add. */ |
| 141 | 141 | int vid, /* Add to this VFILE */ |
| 142 | 142 | int caseSensitive /* True if filenames are case sensitive */ |
| 143 | 143 | ){ |
| 144 | 144 | const char *zCollate = caseSensitive ? "binary" : "nocase"; |
| 145 | - if( !file_is_simple_pathname(zPath) ){ | |
| 145 | + if( !file_is_simple_pathname(zPath, 1) ){ | |
| 146 | 146 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 147 | 147 | return 0; |
| 148 | 148 | } |
| 149 | 149 | if( db_exists("SELECT 1 FROM vfile" |
| 150 | 150 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){ |
| 151 | 151 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -140,11 +140,11 @@ | |
| 140 | const char *zPath, /* Tree-name of file to add. */ |
| 141 | int vid, /* Add to this VFILE */ |
| 142 | int caseSensitive /* True if filenames are case sensitive */ |
| 143 | ){ |
| 144 | const char *zCollate = caseSensitive ? "binary" : "nocase"; |
| 145 | if( !file_is_simple_pathname(zPath) ){ |
| 146 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 147 | return 0; |
| 148 | } |
| 149 | if( db_exists("SELECT 1 FROM vfile" |
| 150 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){ |
| 151 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -140,11 +140,11 @@ | |
| 140 | const char *zPath, /* Tree-name of file to add. */ |
| 141 | int vid, /* Add to this VFILE */ |
| 142 | int caseSensitive /* True if filenames are case sensitive */ |
| 143 | ){ |
| 144 | const char *zCollate = caseSensitive ? "binary" : "nocase"; |
| 145 | if( !file_is_simple_pathname(zPath, 1) ){ |
| 146 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 147 | return 0; |
| 148 | } |
| 149 | if( db_exists("SELECT 1 FROM vfile" |
| 150 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){ |
| 151 |
+1
-1
| --- src/bisect.c | ||
| +++ src/bisect.c | ||
| @@ -123,11 +123,11 @@ | ||
| 123 | 123 | for(p=path_last(), n=0; p; p=p->pFrom, n++){ |
| 124 | 124 | if( p->isHidden && (nHidden || (p->pFrom && p->pFrom->isHidden)) ){ |
| 125 | 125 | nHidden++; |
| 126 | 126 | continue; |
| 127 | 127 | }else if( nHidden ){ |
| 128 | - fossil_print(" ... eliding %d check-ins\n", nHidden); | |
| 128 | + fossil_print(" ... %d other check-ins omitted\n", nHidden); | |
| 129 | 129 | nHidden = 0; |
| 130 | 130 | } |
| 131 | 131 | db_bind_int(&s, ":rid", p->rid); |
| 132 | 132 | if( db_step(&s)==SQLITE_ROW ){ |
| 133 | 133 | const char *zUuid = db_column_text(&s, 0); |
| 134 | 134 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -123,11 +123,11 @@ | |
| 123 | for(p=path_last(), n=0; p; p=p->pFrom, n++){ |
| 124 | if( p->isHidden && (nHidden || (p->pFrom && p->pFrom->isHidden)) ){ |
| 125 | nHidden++; |
| 126 | continue; |
| 127 | }else if( nHidden ){ |
| 128 | fossil_print(" ... eliding %d check-ins\n", nHidden); |
| 129 | nHidden = 0; |
| 130 | } |
| 131 | db_bind_int(&s, ":rid", p->rid); |
| 132 | if( db_step(&s)==SQLITE_ROW ){ |
| 133 | const char *zUuid = db_column_text(&s, 0); |
| 134 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -123,11 +123,11 @@ | |
| 123 | for(p=path_last(), n=0; p; p=p->pFrom, n++){ |
| 124 | if( p->isHidden && (nHidden || (p->pFrom && p->pFrom->isHidden)) ){ |
| 125 | nHidden++; |
| 126 | continue; |
| 127 | }else if( nHidden ){ |
| 128 | fossil_print(" ... %d other check-ins omitted\n", nHidden); |
| 129 | nHidden = 0; |
| 130 | } |
| 131 | db_bind_int(&s, ":rid", p->rid); |
| 132 | if( db_step(&s)==SQLITE_ROW ){ |
| 133 | const char *zUuid = db_column_text(&s, 0); |
| 134 |
+1
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -21,10 +21,11 @@ | ||
| 21 | 21 | ** formatting function and its cousins, and routines to encode and |
| 22 | 22 | ** decode strings in HTML or HTTP. |
| 23 | 23 | */ |
| 24 | 24 | #include "config.h" |
| 25 | 25 | #ifdef _WIN32 |
| 26 | +# include <winsock2.h> | |
| 26 | 27 | # include <ws2tcpip.h> |
| 27 | 28 | #else |
| 28 | 29 | # include <sys/socket.h> |
| 29 | 30 | # include <netinet/in.h> |
| 30 | 31 | # include <arpa/inet.h> |
| 31 | 32 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -21,10 +21,11 @@ | |
| 21 | ** formatting function and its cousins, and routines to encode and |
| 22 | ** decode strings in HTML or HTTP. |
| 23 | */ |
| 24 | #include "config.h" |
| 25 | #ifdef _WIN32 |
| 26 | # include <ws2tcpip.h> |
| 27 | #else |
| 28 | # include <sys/socket.h> |
| 29 | # include <netinet/in.h> |
| 30 | # include <arpa/inet.h> |
| 31 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -21,10 +21,11 @@ | |
| 21 | ** formatting function and its cousins, and routines to encode and |
| 22 | ** decode strings in HTML or HTTP. |
| 23 | */ |
| 24 | #include "config.h" |
| 25 | #ifdef _WIN32 |
| 26 | # include <winsock2.h> |
| 27 | # include <ws2tcpip.h> |
| 28 | #else |
| 29 | # include <sys/socket.h> |
| 30 | # include <netinet/in.h> |
| 31 | # include <arpa/inet.h> |
| 32 |
+2
-2
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -316,11 +316,11 @@ | ||
| 316 | 316 | ** unless overridden by the --abs-paths or --rel-paths options. |
| 317 | 317 | ** |
| 318 | 318 | ** Options: |
| 319 | 319 | ** --abs-paths Display absolute pathnames. |
| 320 | 320 | ** --dotfiles include files beginning with a dot (".") |
| 321 | -** --ignore <CSG> ignore files matching patterns from the | |
| 321 | +** --ignore <CSG> ignore files matching patterns from the argument | |
| 322 | 322 | ** --rel-paths Display pathnames relative to the current working |
| 323 | 323 | ** directory. |
| 324 | 324 | ** |
| 325 | 325 | ** See also: changes, clean, status |
| 326 | 326 | */ |
| @@ -1144,11 +1144,11 @@ | ||
| 1144 | 1144 | } |
| 1145 | 1145 | |
| 1146 | 1146 | /* So that older versions of Fossil (that do not understand delta- |
| 1147 | 1147 | ** manifest) can continue to use this repository, do not create a new |
| 1148 | 1148 | ** delta-manifest unless this repository already contains one or more |
| 1149 | - ** delta-manifets, or unless the delta-manifest is explicitly requested | |
| 1149 | + ** delta-manifests, or unless the delta-manifest is explicitly requested | |
| 1150 | 1150 | ** by the --delta option. |
| 1151 | 1151 | */ |
| 1152 | 1152 | if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){ |
| 1153 | 1153 | forceBaseline = 1; |
| 1154 | 1154 | } |
| 1155 | 1155 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -316,11 +316,11 @@ | |
| 316 | ** unless overridden by the --abs-paths or --rel-paths options. |
| 317 | ** |
| 318 | ** Options: |
| 319 | ** --abs-paths Display absolute pathnames. |
| 320 | ** --dotfiles include files beginning with a dot (".") |
| 321 | ** --ignore <CSG> ignore files matching patterns from the |
| 322 | ** --rel-paths Display pathnames relative to the current working |
| 323 | ** directory. |
| 324 | ** |
| 325 | ** See also: changes, clean, status |
| 326 | */ |
| @@ -1144,11 +1144,11 @@ | |
| 1144 | } |
| 1145 | |
| 1146 | /* So that older versions of Fossil (that do not understand delta- |
| 1147 | ** manifest) can continue to use this repository, do not create a new |
| 1148 | ** delta-manifest unless this repository already contains one or more |
| 1149 | ** delta-manifets, or unless the delta-manifest is explicitly requested |
| 1150 | ** by the --delta option. |
| 1151 | */ |
| 1152 | if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){ |
| 1153 | forceBaseline = 1; |
| 1154 | } |
| 1155 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -316,11 +316,11 @@ | |
| 316 | ** unless overridden by the --abs-paths or --rel-paths options. |
| 317 | ** |
| 318 | ** Options: |
| 319 | ** --abs-paths Display absolute pathnames. |
| 320 | ** --dotfiles include files beginning with a dot (".") |
| 321 | ** --ignore <CSG> ignore files matching patterns from the argument |
| 322 | ** --rel-paths Display pathnames relative to the current working |
| 323 | ** directory. |
| 324 | ** |
| 325 | ** See also: changes, clean, status |
| 326 | */ |
| @@ -1144,11 +1144,11 @@ | |
| 1144 | } |
| 1145 | |
| 1146 | /* So that older versions of Fossil (that do not understand delta- |
| 1147 | ** manifest) can continue to use this repository, do not create a new |
| 1148 | ** delta-manifest unless this repository already contains one or more |
| 1149 | ** delta-manifests, or unless the delta-manifest is explicitly requested |
| 1150 | ** by the --delta option. |
| 1151 | */ |
| 1152 | if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){ |
| 1153 | forceBaseline = 1; |
| 1154 | } |
| 1155 |
+6
-10
| --- src/cson_amalgamation.c | ||
| +++ src/cson_amalgamation.c | ||
| @@ -1422,11 +1422,10 @@ | ||
| 1422 | 1422 | extern "C" { |
| 1423 | 1423 | #endif |
| 1424 | 1424 | |
| 1425 | 1425 | |
| 1426 | 1426 | |
| 1427 | - | |
| 1428 | 1427 | /** |
| 1429 | 1428 | This type holds the "vtbl" for type-specific operations when |
| 1430 | 1429 | working with cson_value objects. |
| 1431 | 1430 | |
| 1432 | 1431 | All cson_values of a given logical type share a pointer to a single |
| @@ -1524,13 +1523,11 @@ | ||
| 1524 | 1523 | */ |
| 1525 | 1524 | #define cson_value_empty_m { &cson_value_api_empty/*api*/, NULL/*value*/, 0/*refcount*/ } |
| 1526 | 1525 | /** |
| 1527 | 1526 | Empty-initialized cson_value object. |
| 1528 | 1527 | */ |
| 1529 | -extern const cson_value cson_value_empty; | |
| 1530 | - | |
| 1531 | -const cson_value cson_value_empty = cson_value_empty_m; | |
| 1528 | +static const cson_value cson_value_empty = cson_value_empty_m; | |
| 1532 | 1529 | const cson_parse_opt cson_parse_opt_empty = cson_parse_opt_empty_m; |
| 1533 | 1530 | const cson_output_opt cson_output_opt_empty = cson_output_opt_empty_m; |
| 1534 | 1531 | const cson_object_iterator cson_object_iterator_empty = cson_object_iterator_empty_m; |
| 1535 | 1532 | const cson_buffer cson_buffer_empty = cson_buffer_empty_m; |
| 1536 | 1533 | const cson_parse_info cson_parse_info_empty = cson_parse_info_empty_m; |
| @@ -1661,11 +1658,11 @@ | ||
| 1661 | 1658 | { |
| 1662 | 1659 | if((m >= (void const *)&CSON_EMPTY_HOLDER) |
| 1663 | 1660 | && ( m < (void const *)(&CSON_EMPTY_HOLDER+1))) |
| 1664 | 1661 | return 1; |
| 1665 | 1662 | else return |
| 1666 | - ((m > (void const *)&CSON_SPECIAL_VALUES[0]) | |
| 1663 | + ((m >= (void const *)&CSON_SPECIAL_VALUES[0]) | |
| 1667 | 1664 | && ( m < (void const *)&CSON_SPECIAL_VALUES[CSON_INTERNAL_VALUES_LENGTH]) ) |
| 1668 | 1665 | ? 1 |
| 1669 | 1666 | : 0; |
| 1670 | 1667 | } |
| 1671 | 1668 | |
| @@ -1711,13 +1708,13 @@ | ||
| 1711 | 1708 | malloc/free funcs because fossil's lack of header files |
| 1712 | 1709 | means we would have to #include "main.c" here to |
| 1713 | 1710 | get the declarations. |
| 1714 | 1711 | */ |
| 1715 | 1712 | #if defined(CSON_FOSSIL_MODE) |
| 1716 | -void *fossil_malloc(size_t n); | |
| 1717 | -void fossil_free(void *p); | |
| 1718 | -void *fossil_realloc(void *p, size_t n); | |
| 1713 | +extern void *fossil_malloc(size_t n); | |
| 1714 | +extern void fossil_free(void *p); | |
| 1715 | +extern void *fossil_realloc(void *p, size_t n); | |
| 1719 | 1716 | # define CSON_MALLOC_IMPL fossil_malloc |
| 1720 | 1717 | # define CSON_FREE_IMPL fossil_free |
| 1721 | 1718 | # define CSON_REALLOC_IMPL fossil_realloc |
| 1722 | 1719 | #endif |
| 1723 | 1720 | |
| @@ -4380,11 +4377,11 @@ | ||
| 4380 | 4377 | arg MUST be a (cson_buffer*). This function appends n bytes at |
| 4381 | 4378 | position arg->used, expanding the buffer as necessary. |
| 4382 | 4379 | */ |
| 4383 | 4380 | static int cson_data_dest_cson_buffer( void * arg, void const * data_, unsigned int n ) |
| 4384 | 4381 | { |
| 4385 | - if( ! arg || (n<0) ) return cson_rc.ArgError; | |
| 4382 | + if( !arg ) return cson_rc.ArgError; | |
| 4386 | 4383 | else if( ! n ) return 0; |
| 4387 | 4384 | else |
| 4388 | 4385 | { |
| 4389 | 4386 | cson_buffer * sb = (cson_buffer*)arg; |
| 4390 | 4387 | char const * data = (char const *)data_; |
| @@ -4500,11 +4497,10 @@ | ||
| 4500 | 4497 | cson_value * cv = NULL; |
| 4501 | 4498 | cson_object const * curObj = obj; |
| 4502 | 4499 | enum { BufSize = 128 }; |
| 4503 | 4500 | char buf[BufSize]; |
| 4504 | 4501 | memset( buf, 0, BufSize ); |
| 4505 | - rc = cson_rc.RangeError; | |
| 4506 | 4502 | |
| 4507 | 4503 | while( cson_next_token( &beg, sep, &end ) ) |
| 4508 | 4504 | { |
| 4509 | 4505 | if( beg == end ) break; |
| 4510 | 4506 | else |
| 4511 | 4507 |
| --- src/cson_amalgamation.c | |
| +++ src/cson_amalgamation.c | |
| @@ -1422,11 +1422,10 @@ | |
| 1422 | extern "C" { |
| 1423 | #endif |
| 1424 | |
| 1425 | |
| 1426 | |
| 1427 | |
| 1428 | /** |
| 1429 | This type holds the "vtbl" for type-specific operations when |
| 1430 | working with cson_value objects. |
| 1431 | |
| 1432 | All cson_values of a given logical type share a pointer to a single |
| @@ -1524,13 +1523,11 @@ | |
| 1524 | */ |
| 1525 | #define cson_value_empty_m { &cson_value_api_empty/*api*/, NULL/*value*/, 0/*refcount*/ } |
| 1526 | /** |
| 1527 | Empty-initialized cson_value object. |
| 1528 | */ |
| 1529 | extern const cson_value cson_value_empty; |
| 1530 | |
| 1531 | const cson_value cson_value_empty = cson_value_empty_m; |
| 1532 | const cson_parse_opt cson_parse_opt_empty = cson_parse_opt_empty_m; |
| 1533 | const cson_output_opt cson_output_opt_empty = cson_output_opt_empty_m; |
| 1534 | const cson_object_iterator cson_object_iterator_empty = cson_object_iterator_empty_m; |
| 1535 | const cson_buffer cson_buffer_empty = cson_buffer_empty_m; |
| 1536 | const cson_parse_info cson_parse_info_empty = cson_parse_info_empty_m; |
| @@ -1661,11 +1658,11 @@ | |
| 1661 | { |
| 1662 | if((m >= (void const *)&CSON_EMPTY_HOLDER) |
| 1663 | && ( m < (void const *)(&CSON_EMPTY_HOLDER+1))) |
| 1664 | return 1; |
| 1665 | else return |
| 1666 | ((m > (void const *)&CSON_SPECIAL_VALUES[0]) |
| 1667 | && ( m < (void const *)&CSON_SPECIAL_VALUES[CSON_INTERNAL_VALUES_LENGTH]) ) |
| 1668 | ? 1 |
| 1669 | : 0; |
| 1670 | } |
| 1671 | |
| @@ -1711,13 +1708,13 @@ | |
| 1711 | malloc/free funcs because fossil's lack of header files |
| 1712 | means we would have to #include "main.c" here to |
| 1713 | get the declarations. |
| 1714 | */ |
| 1715 | #if defined(CSON_FOSSIL_MODE) |
| 1716 | void *fossil_malloc(size_t n); |
| 1717 | void fossil_free(void *p); |
| 1718 | void *fossil_realloc(void *p, size_t n); |
| 1719 | # define CSON_MALLOC_IMPL fossil_malloc |
| 1720 | # define CSON_FREE_IMPL fossil_free |
| 1721 | # define CSON_REALLOC_IMPL fossil_realloc |
| 1722 | #endif |
| 1723 | |
| @@ -4380,11 +4377,11 @@ | |
| 4380 | arg MUST be a (cson_buffer*). This function appends n bytes at |
| 4381 | position arg->used, expanding the buffer as necessary. |
| 4382 | */ |
| 4383 | static int cson_data_dest_cson_buffer( void * arg, void const * data_, unsigned int n ) |
| 4384 | { |
| 4385 | if( ! arg || (n<0) ) return cson_rc.ArgError; |
| 4386 | else if( ! n ) return 0; |
| 4387 | else |
| 4388 | { |
| 4389 | cson_buffer * sb = (cson_buffer*)arg; |
| 4390 | char const * data = (char const *)data_; |
| @@ -4500,11 +4497,10 @@ | |
| 4500 | cson_value * cv = NULL; |
| 4501 | cson_object const * curObj = obj; |
| 4502 | enum { BufSize = 128 }; |
| 4503 | char buf[BufSize]; |
| 4504 | memset( buf, 0, BufSize ); |
| 4505 | rc = cson_rc.RangeError; |
| 4506 | |
| 4507 | while( cson_next_token( &beg, sep, &end ) ) |
| 4508 | { |
| 4509 | if( beg == end ) break; |
| 4510 | else |
| 4511 |
| --- src/cson_amalgamation.c | |
| +++ src/cson_amalgamation.c | |
| @@ -1422,11 +1422,10 @@ | |
| 1422 | extern "C" { |
| 1423 | #endif |
| 1424 | |
| 1425 | |
| 1426 | |
| 1427 | /** |
| 1428 | This type holds the "vtbl" for type-specific operations when |
| 1429 | working with cson_value objects. |
| 1430 | |
| 1431 | All cson_values of a given logical type share a pointer to a single |
| @@ -1524,13 +1523,11 @@ | |
| 1523 | */ |
| 1524 | #define cson_value_empty_m { &cson_value_api_empty/*api*/, NULL/*value*/, 0/*refcount*/ } |
| 1525 | /** |
| 1526 | Empty-initialized cson_value object. |
| 1527 | */ |
| 1528 | static const cson_value cson_value_empty = cson_value_empty_m; |
| 1529 | const cson_parse_opt cson_parse_opt_empty = cson_parse_opt_empty_m; |
| 1530 | const cson_output_opt cson_output_opt_empty = cson_output_opt_empty_m; |
| 1531 | const cson_object_iterator cson_object_iterator_empty = cson_object_iterator_empty_m; |
| 1532 | const cson_buffer cson_buffer_empty = cson_buffer_empty_m; |
| 1533 | const cson_parse_info cson_parse_info_empty = cson_parse_info_empty_m; |
| @@ -1661,11 +1658,11 @@ | |
| 1658 | { |
| 1659 | if((m >= (void const *)&CSON_EMPTY_HOLDER) |
| 1660 | && ( m < (void const *)(&CSON_EMPTY_HOLDER+1))) |
| 1661 | return 1; |
| 1662 | else return |
| 1663 | ((m >= (void const *)&CSON_SPECIAL_VALUES[0]) |
| 1664 | && ( m < (void const *)&CSON_SPECIAL_VALUES[CSON_INTERNAL_VALUES_LENGTH]) ) |
| 1665 | ? 1 |
| 1666 | : 0; |
| 1667 | } |
| 1668 | |
| @@ -1711,13 +1708,13 @@ | |
| 1708 | malloc/free funcs because fossil's lack of header files |
| 1709 | means we would have to #include "main.c" here to |
| 1710 | get the declarations. |
| 1711 | */ |
| 1712 | #if defined(CSON_FOSSIL_MODE) |
| 1713 | extern void *fossil_malloc(size_t n); |
| 1714 | extern void fossil_free(void *p); |
| 1715 | extern void *fossil_realloc(void *p, size_t n); |
| 1716 | # define CSON_MALLOC_IMPL fossil_malloc |
| 1717 | # define CSON_FREE_IMPL fossil_free |
| 1718 | # define CSON_REALLOC_IMPL fossil_realloc |
| 1719 | #endif |
| 1720 | |
| @@ -4380,11 +4377,11 @@ | |
| 4377 | arg MUST be a (cson_buffer*). This function appends n bytes at |
| 4378 | position arg->used, expanding the buffer as necessary. |
| 4379 | */ |
| 4380 | static int cson_data_dest_cson_buffer( void * arg, void const * data_, unsigned int n ) |
| 4381 | { |
| 4382 | if( !arg ) return cson_rc.ArgError; |
| 4383 | else if( ! n ) return 0; |
| 4384 | else |
| 4385 | { |
| 4386 | cson_buffer * sb = (cson_buffer*)arg; |
| 4387 | char const * data = (char const *)data_; |
| @@ -4500,11 +4497,10 @@ | |
| 4497 | cson_value * cv = NULL; |
| 4498 | cson_object const * curObj = obj; |
| 4499 | enum { BufSize = 128 }; |
| 4500 | char buf[BufSize]; |
| 4501 | memset( buf, 0, BufSize ); |
| 4502 | |
| 4503 | while( cson_next_token( &beg, sep, &end ) ) |
| 4504 | { |
| 4505 | if( beg == end ) break; |
| 4506 | else |
| 4507 |
+6
-2
| --- src/cson_amalgamation.h | ||
| +++ src/cson_amalgamation.h | ||
| @@ -1236,11 +1236,14 @@ | ||
| 1236 | 1236 | eventually either free the value using cson_value_free() or |
| 1237 | 1237 | inserting it into a container (array or object), which transfers |
| 1238 | 1238 | ownership to the container. See the cson_value class documentation |
| 1239 | 1239 | for more details. |
| 1240 | 1240 | |
| 1241 | - Returns NULL on allocation error. | |
| 1241 | + Semantically speaking this function Returns NULL on allocation | |
| 1242 | + error, but the implementation never actually allocates for this | |
| 1243 | + case. Nonetheless, it must be treated as if it were an allocated | |
| 1244 | + value. | |
| 1242 | 1245 | */ |
| 1243 | 1246 | cson_value * cson_value_new_bool( char v ); |
| 1244 | 1247 | |
| 1245 | 1248 | |
| 1246 | 1249 | /** |
| @@ -1927,11 +1930,12 @@ | ||
| 1927 | 1930 | modified. |
| 1928 | 1931 | |
| 1929 | 1932 | buf->mem is owned by buf and must eventually be freed by passing an |
| 1930 | 1933 | n value of 0 to this function. |
| 1931 | 1934 | |
| 1932 | - buf->used is never modified by this function. | |
| 1935 | + buf->used is never modified by this function unless n is 0, in which case | |
| 1936 | + it is reset. | |
| 1933 | 1937 | */ |
| 1934 | 1938 | int cson_buffer_reserve( cson_buffer * buf, cson_size_t n ); |
| 1935 | 1939 | |
| 1936 | 1940 | /** |
| 1937 | 1941 | Fills all bytes of the given buffer with the given character. |
| 1938 | 1942 |
| --- src/cson_amalgamation.h | |
| +++ src/cson_amalgamation.h | |
| @@ -1236,11 +1236,14 @@ | |
| 1236 | eventually either free the value using cson_value_free() or |
| 1237 | inserting it into a container (array or object), which transfers |
| 1238 | ownership to the container. See the cson_value class documentation |
| 1239 | for more details. |
| 1240 | |
| 1241 | Returns NULL on allocation error. |
| 1242 | */ |
| 1243 | cson_value * cson_value_new_bool( char v ); |
| 1244 | |
| 1245 | |
| 1246 | /** |
| @@ -1927,11 +1930,12 @@ | |
| 1927 | modified. |
| 1928 | |
| 1929 | buf->mem is owned by buf and must eventually be freed by passing an |
| 1930 | n value of 0 to this function. |
| 1931 | |
| 1932 | buf->used is never modified by this function. |
| 1933 | */ |
| 1934 | int cson_buffer_reserve( cson_buffer * buf, cson_size_t n ); |
| 1935 | |
| 1936 | /** |
| 1937 | Fills all bytes of the given buffer with the given character. |
| 1938 |
| --- src/cson_amalgamation.h | |
| +++ src/cson_amalgamation.h | |
| @@ -1236,11 +1236,14 @@ | |
| 1236 | eventually either free the value using cson_value_free() or |
| 1237 | inserting it into a container (array or object), which transfers |
| 1238 | ownership to the container. See the cson_value class documentation |
| 1239 | for more details. |
| 1240 | |
| 1241 | Semantically speaking this function Returns NULL on allocation |
| 1242 | error, but the implementation never actually allocates for this |
| 1243 | case. Nonetheless, it must be treated as if it were an allocated |
| 1244 | value. |
| 1245 | */ |
| 1246 | cson_value * cson_value_new_bool( char v ); |
| 1247 | |
| 1248 | |
| 1249 | /** |
| @@ -1927,11 +1930,12 @@ | |
| 1930 | modified. |
| 1931 | |
| 1932 | buf->mem is owned by buf and must eventually be freed by passing an |
| 1933 | n value of 0 to this function. |
| 1934 | |
| 1935 | buf->used is never modified by this function unless n is 0, in which case |
| 1936 | it is reset. |
| 1937 | */ |
| 1938 | int cson_buffer_reserve( cson_buffer * buf, cson_size_t n ); |
| 1939 | |
| 1940 | /** |
| 1941 | Fills all bytes of the given buffer with the given character. |
| 1942 |
M
src/db.c
+5
-1
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1604,11 +1604,11 @@ | ||
| 1604 | 1604 | |
| 1605 | 1605 | /* |
| 1606 | 1606 | ** This function registers auxiliary functions when the SQLite |
| 1607 | 1607 | ** database connection is first established. |
| 1608 | 1608 | */ |
| 1609 | -LOCAL void db_connection_init(void){ | |
| 1609 | +void db_connection_init(void){ | |
| 1610 | 1610 | sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0); |
| 1611 | 1611 | sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0); |
| 1612 | 1612 | sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1613 | 1613 | sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1614 | 1614 | sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0); |
| @@ -1619,10 +1619,11 @@ | ||
| 1619 | 1619 | g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0 |
| 1620 | 1620 | ); |
| 1621 | 1621 | if( g.fSqlTrace ){ |
| 1622 | 1622 | sqlite3_trace(g.db, db_sql_trace, 0); |
| 1623 | 1623 | } |
| 1624 | + re_add_sql_func(g.db); | |
| 1624 | 1625 | } |
| 1625 | 1626 | |
| 1626 | 1627 | /* |
| 1627 | 1628 | ** Return true if the string zVal represents "true" (or "false"). |
| 1628 | 1629 | */ |
| @@ -2116,10 +2117,13 @@ | ||
| 2116 | 2117 | ** file named .fossil-settings/PROPERTY in the checked out files, if that |
| 2117 | 2118 | ** file exists. |
| 2118 | 2119 | ** |
| 2119 | 2120 | ** The "unset" command clears a property setting. |
| 2120 | 2121 | ** |
| 2122 | +** | |
| 2123 | +** access-log If enabled, record successful and failed login attempts | |
| 2124 | +** in the "accesslog" table. Default: off | |
| 2121 | 2125 | ** |
| 2122 | 2126 | ** allow-symlinks If enabled, don't follow symlinks, and instead treat |
| 2123 | 2127 | ** (versionable) them as symlinks on Unix. Has no effect on Windows |
| 2124 | 2128 | ** (existing links in repository created on Unix become |
| 2125 | 2129 | ** plain-text files with link destination path inside). |
| 2126 | 2130 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1604,11 +1604,11 @@ | |
| 1604 | |
| 1605 | /* |
| 1606 | ** This function registers auxiliary functions when the SQLite |
| 1607 | ** database connection is first established. |
| 1608 | */ |
| 1609 | LOCAL void db_connection_init(void){ |
| 1610 | sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0); |
| 1611 | sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0); |
| 1612 | sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1613 | sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1614 | sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0); |
| @@ -1619,10 +1619,11 @@ | |
| 1619 | g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0 |
| 1620 | ); |
| 1621 | if( g.fSqlTrace ){ |
| 1622 | sqlite3_trace(g.db, db_sql_trace, 0); |
| 1623 | } |
| 1624 | } |
| 1625 | |
| 1626 | /* |
| 1627 | ** Return true if the string zVal represents "true" (or "false"). |
| 1628 | */ |
| @@ -2116,10 +2117,13 @@ | |
| 2116 | ** file named .fossil-settings/PROPERTY in the checked out files, if that |
| 2117 | ** file exists. |
| 2118 | ** |
| 2119 | ** The "unset" command clears a property setting. |
| 2120 | ** |
| 2121 | ** |
| 2122 | ** allow-symlinks If enabled, don't follow symlinks, and instead treat |
| 2123 | ** (versionable) them as symlinks on Unix. Has no effect on Windows |
| 2124 | ** (existing links in repository created on Unix become |
| 2125 | ** plain-text files with link destination path inside). |
| 2126 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1604,11 +1604,11 @@ | |
| 1604 | |
| 1605 | /* |
| 1606 | ** This function registers auxiliary functions when the SQLite |
| 1607 | ** database connection is first established. |
| 1608 | */ |
| 1609 | void db_connection_init(void){ |
| 1610 | sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0); |
| 1611 | sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0); |
| 1612 | sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1613 | sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1614 | sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0); |
| @@ -1619,10 +1619,11 @@ | |
| 1619 | g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0 |
| 1620 | ); |
| 1621 | if( g.fSqlTrace ){ |
| 1622 | sqlite3_trace(g.db, db_sql_trace, 0); |
| 1623 | } |
| 1624 | re_add_sql_func(g.db); |
| 1625 | } |
| 1626 | |
| 1627 | /* |
| 1628 | ** Return true if the string zVal represents "true" (or "false"). |
| 1629 | */ |
| @@ -2116,10 +2117,13 @@ | |
| 2117 | ** file named .fossil-settings/PROPERTY in the checked out files, if that |
| 2118 | ** file exists. |
| 2119 | ** |
| 2120 | ** The "unset" command clears a property setting. |
| 2121 | ** |
| 2122 | ** |
| 2123 | ** access-log If enabled, record successful and failed login attempts |
| 2124 | ** in the "accesslog" table. Default: off |
| 2125 | ** |
| 2126 | ** allow-symlinks If enabled, don't follow symlinks, and instead treat |
| 2127 | ** (versionable) them as symlinks on Unix. Has no effect on Windows |
| 2128 | ** (existing links in repository created on Unix become |
| 2129 | ** plain-text files with link destination path inside). |
| 2130 |
M
src/db.c
+5
-1
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1604,11 +1604,11 @@ | ||
| 1604 | 1604 | |
| 1605 | 1605 | /* |
| 1606 | 1606 | ** This function registers auxiliary functions when the SQLite |
| 1607 | 1607 | ** database connection is first established. |
| 1608 | 1608 | */ |
| 1609 | -LOCAL void db_connection_init(void){ | |
| 1609 | +void db_connection_init(void){ | |
| 1610 | 1610 | sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0); |
| 1611 | 1611 | sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0); |
| 1612 | 1612 | sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1613 | 1613 | sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1614 | 1614 | sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0); |
| @@ -1619,10 +1619,11 @@ | ||
| 1619 | 1619 | g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0 |
| 1620 | 1620 | ); |
| 1621 | 1621 | if( g.fSqlTrace ){ |
| 1622 | 1622 | sqlite3_trace(g.db, db_sql_trace, 0); |
| 1623 | 1623 | } |
| 1624 | + re_add_sql_func(g.db); | |
| 1624 | 1625 | } |
| 1625 | 1626 | |
| 1626 | 1627 | /* |
| 1627 | 1628 | ** Return true if the string zVal represents "true" (or "false"). |
| 1628 | 1629 | */ |
| @@ -2116,10 +2117,13 @@ | ||
| 2116 | 2117 | ** file named .fossil-settings/PROPERTY in the checked out files, if that |
| 2117 | 2118 | ** file exists. |
| 2118 | 2119 | ** |
| 2119 | 2120 | ** The "unset" command clears a property setting. |
| 2120 | 2121 | ** |
| 2122 | +** | |
| 2123 | +** access-log If enabled, record successful and failed login attempts | |
| 2124 | +** in the "accesslog" table. Default: off | |
| 2121 | 2125 | ** |
| 2122 | 2126 | ** allow-symlinks If enabled, don't follow symlinks, and instead treat |
| 2123 | 2127 | ** (versionable) them as symlinks on Unix. Has no effect on Windows |
| 2124 | 2128 | ** (existing links in repository created on Unix become |
| 2125 | 2129 | ** plain-text files with link destination path inside). |
| 2126 | 2130 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1604,11 +1604,11 @@ | |
| 1604 | |
| 1605 | /* |
| 1606 | ** This function registers auxiliary functions when the SQLite |
| 1607 | ** database connection is first established. |
| 1608 | */ |
| 1609 | LOCAL void db_connection_init(void){ |
| 1610 | sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0); |
| 1611 | sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0); |
| 1612 | sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1613 | sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1614 | sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0); |
| @@ -1619,10 +1619,11 @@ | |
| 1619 | g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0 |
| 1620 | ); |
| 1621 | if( g.fSqlTrace ){ |
| 1622 | sqlite3_trace(g.db, db_sql_trace, 0); |
| 1623 | } |
| 1624 | } |
| 1625 | |
| 1626 | /* |
| 1627 | ** Return true if the string zVal represents "true" (or "false"). |
| 1628 | */ |
| @@ -2116,10 +2117,13 @@ | |
| 2116 | ** file named .fossil-settings/PROPERTY in the checked out files, if that |
| 2117 | ** file exists. |
| 2118 | ** |
| 2119 | ** The "unset" command clears a property setting. |
| 2120 | ** |
| 2121 | ** |
| 2122 | ** allow-symlinks If enabled, don't follow symlinks, and instead treat |
| 2123 | ** (versionable) them as symlinks on Unix. Has no effect on Windows |
| 2124 | ** (existing links in repository created on Unix become |
| 2125 | ** plain-text files with link destination path inside). |
| 2126 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1604,11 +1604,11 @@ | |
| 1604 | |
| 1605 | /* |
| 1606 | ** This function registers auxiliary functions when the SQLite |
| 1607 | ** database connection is first established. |
| 1608 | */ |
| 1609 | void db_connection_init(void){ |
| 1610 | sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0); |
| 1611 | sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0); |
| 1612 | sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1613 | sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0); |
| 1614 | sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0); |
| @@ -1619,10 +1619,11 @@ | |
| 1619 | g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0 |
| 1620 | ); |
| 1621 | if( g.fSqlTrace ){ |
| 1622 | sqlite3_trace(g.db, db_sql_trace, 0); |
| 1623 | } |
| 1624 | re_add_sql_func(g.db); |
| 1625 | } |
| 1626 | |
| 1627 | /* |
| 1628 | ** Return true if the string zVal represents "true" (or "false"). |
| 1629 | */ |
| @@ -2116,10 +2117,13 @@ | |
| 2117 | ** file named .fossil-settings/PROPERTY in the checked out files, if that |
| 2118 | ** file exists. |
| 2119 | ** |
| 2120 | ** The "unset" command clears a property setting. |
| 2121 | ** |
| 2122 | ** |
| 2123 | ** access-log If enabled, record successful and failed login attempts |
| 2124 | ** in the "accesslog" table. Default: off |
| 2125 | ** |
| 2126 | ** allow-symlinks If enabled, don't follow symlinks, and instead treat |
| 2127 | ** (versionable) them as symlinks on Unix. Has no effect on Windows |
| 2128 | ** (existing links in repository created on Unix become |
| 2129 | ** plain-text files with link destination path inside). |
| 2130 |
+267
-87
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -23,11 +23,12 @@ | ||
| 23 | 23 | #include <assert.h> |
| 24 | 24 | |
| 25 | 25 | |
| 26 | 26 | #if INTERFACE |
| 27 | 27 | /* |
| 28 | -** Allowed flag parameters to the text_diff() and html_sbsdiff() functions: | |
| 28 | +** Flag parameters to the text_diff() routine used to control the formatting | |
| 29 | +** of the diff output. | |
| 29 | 30 | */ |
| 30 | 31 | #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */ |
| 31 | 32 | #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */ |
| 32 | 33 | #define DIFF_IGNORE_EOLWS ((u64)0x01000000) /* Ignore end-of-line whitespace */ |
| 33 | 34 | #define DIFF_SIDEBYSIDE ((u64)0x02000000) /* Generate a side-by-side diff */ |
| @@ -37,10 +38,11 @@ | ||
| 37 | 38 | #define DIFF_HTML ((u64)0x10000000) /* Render for HTML */ |
| 38 | 39 | #define DIFF_LINENO ((u64)0x20000000) /* Show line numbers */ |
| 39 | 40 | #define DIFF_WS_WARNING ((u64)0x40000000) /* Warn about whitespace */ |
| 40 | 41 | #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */ |
| 41 | 42 | #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */ |
| 43 | +#define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */ | |
| 42 | 44 | |
| 43 | 45 | /* |
| 44 | 46 | ** These error messages are shared in multiple locations. They are defined |
| 45 | 47 | ** here for consistency. |
| 46 | 48 | */ |
| @@ -52,11 +54,11 @@ | ||
| 52 | 54 | |
| 53 | 55 | #define looks_like_binary(blob) (looks_like_utf8((blob)) == 0) |
| 54 | 56 | #endif /* INTERFACE */ |
| 55 | 57 | |
| 56 | 58 | /* |
| 57 | -** Maximum length of a line in a text file, in bytes. (8192) | |
| 59 | +** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes) | |
| 58 | 60 | */ |
| 59 | 61 | #define LENGTH_MASK_SZ 13 |
| 60 | 62 | #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1) |
| 61 | 63 | |
| 62 | 64 | /* |
| @@ -116,10 +118,13 @@ | ||
| 116 | 118 | ** more. If trailing whitespace is ignored, the "patch" command gets |
| 117 | 119 | ** confused by the diff output. Ticket [a9f7b23c2e376af5b0e5b] |
| 118 | 120 | ** |
| 119 | 121 | ** Return 0 if the file is binary or contains a line that is |
| 120 | 122 | ** too long. |
| 123 | +** | |
| 124 | +** Profiling show that in most cases this routine consumes the bulk of | |
| 125 | +** the CPU time on a diff. | |
| 121 | 126 | */ |
| 122 | 127 | static DLine *break_into_lines(const char *z, int n, int *pnLine, int ignoreWS){ |
| 123 | 128 | int nLine, i, j, k, x; |
| 124 | 129 | unsigned int h, h2; |
| 125 | 130 | DLine *a; |
| @@ -407,34 +412,50 @@ | ||
| 407 | 412 | ** Return true if two DLine elements are identical. |
| 408 | 413 | */ |
| 409 | 414 | static int same_dline(DLine *pA, DLine *pB){ |
| 410 | 415 | return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0; |
| 411 | 416 | } |
| 417 | + | |
| 418 | +/* | |
| 419 | +** Return true if the regular expression *pRe matches any of the | |
| 420 | +** N dlines | |
| 421 | +*/ | |
| 422 | +static int re_dline_match( | |
| 423 | + ReCompiled *pRe, /* The regular expression to be matched */ | |
| 424 | + DLine *aDLine, /* First of N DLines to compare against */ | |
| 425 | + int N /* Number of DLines to check */ | |
| 426 | +){ | |
| 427 | + while( N-- ){ | |
| 428 | + if( re_match(pRe, (const unsigned char *)aDLine->z, LENGTH(aDLine)) ){ | |
| 429 | + return 1; | |
| 430 | + } | |
| 431 | + aDLine++; | |
| 432 | + } | |
| 433 | + return 0; | |
| 434 | +} | |
| 412 | 435 | |
| 413 | 436 | /* |
| 414 | 437 | ** Append a single line of context-diff output to pOut. |
| 415 | 438 | */ |
| 416 | 439 | static void appendDiffLine( |
| 417 | 440 | Blob *pOut, /* Where to write the line of output */ |
| 418 | 441 | char cPrefix, /* One of " ", "+", or "-" */ |
| 419 | 442 | DLine *pLine, /* The line to be output */ |
| 420 | - int html /* True if generating HTML. False for plain text */ | |
| 443 | + int html, /* True if generating HTML. False for plain text */ | |
| 444 | + ReCompiled *pRe /* Colorize only if line matches this Regex */ | |
| 421 | 445 | ){ |
| 422 | - int i; | |
| 423 | 446 | blob_append(pOut, &cPrefix, 1); |
| 424 | 447 | if( html ){ |
| 425 | 448 | char *zHtml; |
| 426 | - if( cPrefix=='+' ){ | |
| 449 | + if( pRe && re_dline_match(pRe, pLine, 1)==0 ){ | |
| 450 | + cPrefix = ' '; | |
| 451 | + }else if( cPrefix=='+' ){ | |
| 427 | 452 | blob_append(pOut, "<span class=\"diffadd\">", -1); |
| 428 | 453 | }else if( cPrefix=='-' ){ |
| 429 | 454 | blob_append(pOut, "<span class=\"diffrm\">", -1); |
| 430 | 455 | } |
| 431 | 456 | zHtml = htmlize(pLine->z, (pLine->h & LENGTH_MASK)); |
| 432 | - for(i=0; i<strlen(zHtml); i++){ | |
| 433 | - char c = zHtml[i]; | |
| 434 | - if( c=='\t' || c=='\r' || c=='\f' ) zHtml[i] = ' '; | |
| 435 | - } | |
| 436 | 457 | blob_append(pOut, zHtml, -1); |
| 437 | 458 | fossil_free(zHtml); |
| 438 | 459 | if( cPrefix!=' ' ){ |
| 439 | 460 | blob_append(pOut, "</span>", -1); |
| 440 | 461 | } |
| @@ -444,11 +465,11 @@ | ||
| 444 | 465 | blob_append(pOut, "\n", 1); |
| 445 | 466 | } |
| 446 | 467 | |
| 447 | 468 | /* |
| 448 | 469 | ** Add two line numbers to the beginning of an output line for a context |
| 449 | -** diff. One or of the other of the two numbers might be zero, which means | |
| 470 | +** diff. One or the other of the two numbers might be zero, which means | |
| 450 | 471 | ** to leave that number field blank. The "html" parameter means to format |
| 451 | 472 | ** the output for HTML. |
| 452 | 473 | */ |
| 453 | 474 | static void appendDiffLineno(Blob *pOut, int lnA, int lnB, int html){ |
| 454 | 475 | if( html ) blob_append(pOut, "<span class=\"diffln\">", -1); |
| @@ -463,21 +484,19 @@ | ||
| 463 | 484 | blob_append(pOut, " ", 8); |
| 464 | 485 | } |
| 465 | 486 | if( html ) blob_append(pOut, "</span>", -1); |
| 466 | 487 | } |
| 467 | 488 | |
| 468 | - | |
| 469 | 489 | /* |
| 470 | 490 | ** Given a raw diff p[] in which the p->aEdit[] array has been filled |
| 471 | 491 | ** in, compute a context diff into pOut. |
| 472 | 492 | */ |
| 473 | 493 | static void contextDiff( |
| 474 | 494 | DContext *p, /* The difference */ |
| 475 | 495 | Blob *pOut, /* Output a context diff to here */ |
| 476 | - int nContext, /* Number of lines of context */ | |
| 477 | - int showLn, /* Show line numbers */ | |
| 478 | - int html /* Render as HTML */ | |
| 496 | + ReCompiled *pRe, /* Only show changes that match this regex */ | |
| 497 | + u64 diffFlags /* Flags controlling the diff format */ | |
| 479 | 498 | ){ |
| 480 | 499 | DLine *A; /* Left side of the diff */ |
| 481 | 500 | DLine *B; /* Right side of the diff */ |
| 482 | 501 | int a = 0; /* Index of next line in A[] */ |
| 483 | 502 | int b = 0; /* Index of next line in B[] */ |
| @@ -488,11 +507,18 @@ | ||
| 488 | 507 | int na, nb; /* Number of lines shown from A and B */ |
| 489 | 508 | int i, j; /* Loop counters */ |
| 490 | 509 | int m; /* Number of lines to output */ |
| 491 | 510 | int skip; /* Number of lines to skip */ |
| 492 | 511 | int nChunk = 0; /* Number of diff chunks seen so far */ |
| 512 | + int nContext; /* Number of lines of context */ | |
| 513 | + int showLn; /* Show line numbers */ | |
| 514 | + int html; /* Render as HTML */ | |
| 515 | + int showDivider = 0; /* True to show the divider between diff blocks */ | |
| 493 | 516 | |
| 517 | + nContext = diff_context_lines(diffFlags); | |
| 518 | + showLn = (diffFlags & DIFF_LINENO)!=0; | |
| 519 | + html = (diffFlags & DIFF_HTML)!=0; | |
| 494 | 520 | A = p->aFrom; |
| 495 | 521 | B = p->aTo; |
| 496 | 522 | R = p->aEdit; |
| 497 | 523 | mxr = p->nEdit; |
| 498 | 524 | while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } |
| @@ -499,10 +525,35 @@ | ||
| 499 | 525 | for(r=0; r<mxr; r += 3*nr){ |
| 500 | 526 | /* Figure out how many triples to show in a single block */ |
| 501 | 527 | for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} |
| 502 | 528 | /* printf("r=%d nr=%d\n", r, nr); */ |
| 503 | 529 | |
| 530 | + /* If there is a regex, skip this block (generate no diff output) | |
| 531 | + ** if the regex matches or does not match both insert and delete. | |
| 532 | + ** Only display the block if one side matches but the other side does | |
| 533 | + ** not. | |
| 534 | + */ | |
| 535 | + if( pRe ){ | |
| 536 | + int hideBlock = 1; | |
| 537 | + int xa = a, xb = b; | |
| 538 | + for(i=0; hideBlock && i<nr; i++){ | |
| 539 | + int c1, c2; | |
| 540 | + xa += R[r+i*3]; | |
| 541 | + xb += R[r+i*3]; | |
| 542 | + c1 = re_dline_match(pRe, &A[xa], R[r+i*3+1]); | |
| 543 | + c2 = re_dline_match(pRe, &B[xb], R[r+i*3+2]); | |
| 544 | + hideBlock = c1==c2; | |
| 545 | + xa += R[r+i*3+1]; | |
| 546 | + xb += R[r+i*3+2]; | |
| 547 | + } | |
| 548 | + if( hideBlock ){ | |
| 549 | + a = xa; | |
| 550 | + b = xb; | |
| 551 | + continue; | |
| 552 | + } | |
| 553 | + } | |
| 554 | + | |
| 504 | 555 | /* For the current block comprising nr triples, figure out |
| 505 | 556 | ** how many lines of A and B are to be displayed |
| 506 | 557 | */ |
| 507 | 558 | if( R[r]>nContext ){ |
| 508 | 559 | na = nb = nContext; |
| @@ -526,17 +577,18 @@ | ||
| 526 | 577 | na += R[r+i*3]; |
| 527 | 578 | nb += R[r+i*3]; |
| 528 | 579 | } |
| 529 | 580 | |
| 530 | 581 | /* Show the header for this block, or if we are doing a modified |
| 531 | - ** context diff that contains line numbers, show the separate from | |
| 582 | + ** context diff that contains line numbers, show the separator from | |
| 532 | 583 | ** the previous block. |
| 533 | 584 | */ |
| 534 | 585 | nChunk++; |
| 535 | 586 | if( showLn ){ |
| 536 | - if( r==0 ){ | |
| 587 | + if( !showDivider ){ | |
| 537 | 588 | /* Do not show a top divider */ |
| 589 | + showDivider = 1; | |
| 538 | 590 | }else if( html ){ |
| 539 | 591 | blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.'); |
| 540 | 592 | blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk); |
| 541 | 593 | }else{ |
| 542 | 594 | blob_appendf(pOut, "%.80c\n", '.'); |
| @@ -559,34 +611,36 @@ | ||
| 559 | 611 | a += skip; |
| 560 | 612 | b += skip; |
| 561 | 613 | m = R[r] - skip; |
| 562 | 614 | for(j=0; j<m; j++){ |
| 563 | 615 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); |
| 564 | - appendDiffLine(pOut, ' ', &A[a+j], html); | |
| 616 | + appendDiffLine(pOut, ' ', &A[a+j], html, 0); | |
| 565 | 617 | } |
| 566 | 618 | a += m; |
| 567 | 619 | b += m; |
| 568 | 620 | |
| 569 | 621 | /* Show the differences */ |
| 570 | 622 | for(i=0; i<nr; i++){ |
| 571 | 623 | m = R[r+i*3+1]; |
| 572 | 624 | for(j=0; j<m; j++){ |
| 625 | + char cMark = '-'; | |
| 573 | 626 | if( showLn ) appendDiffLineno(pOut, a+j+1, 0, html); |
| 574 | - appendDiffLine(pOut, '-', &A[a+j], html); | |
| 627 | + if( pRe && re_dline_match(pRe, &A[a+j], 1)==0 ) cMark = ' '; | |
| 628 | + appendDiffLine(pOut, '-', &A[a+j], html, pRe); | |
| 575 | 629 | } |
| 576 | 630 | a += m; |
| 577 | 631 | m = R[r+i*3+2]; |
| 578 | 632 | for(j=0; j<m; j++){ |
| 579 | 633 | if( showLn ) appendDiffLineno(pOut, 0, b+j+1, html); |
| 580 | - appendDiffLine(pOut, '+', &B[b+j], html); | |
| 634 | + appendDiffLine(pOut, '+', &B[b+j], html, pRe); | |
| 581 | 635 | } |
| 582 | 636 | b += m; |
| 583 | 637 | if( i<nr-1 ){ |
| 584 | 638 | m = R[r+i*3+3]; |
| 585 | 639 | for(j=0; j<m; j++){ |
| 586 | 640 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); |
| 587 | - appendDiffLine(pOut, ' ', &B[b+j], html); | |
| 641 | + appendDiffLine(pOut, ' ', &B[b+j], html, 0); | |
| 588 | 642 | } |
| 589 | 643 | b += m; |
| 590 | 644 | a += m; |
| 591 | 645 | } |
| 592 | 646 | } |
| @@ -595,11 +649,11 @@ | ||
| 595 | 649 | assert( nr==i ); |
| 596 | 650 | m = R[r+nr*3]; |
| 597 | 651 | if( m>nContext ) m = nContext; |
| 598 | 652 | for(j=0; j<m; j++){ |
| 599 | 653 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); |
| 600 | - appendDiffLine(pOut, ' ', &B[b+j], html); | |
| 654 | + appendDiffLine(pOut, ' ', &B[b+j], html, 0); | |
| 601 | 655 | } |
| 602 | 656 | } |
| 603 | 657 | } |
| 604 | 658 | |
| 605 | 659 | /* |
| @@ -615,10 +669,11 @@ | ||
| 615 | 669 | const char *zStart; /* A <span> tag */ |
| 616 | 670 | int iEnd; /* Write </span> prior to character iEnd */ |
| 617 | 671 | int iStart2; /* Write zStart2 prior to character iStart2 */ |
| 618 | 672 | const char *zStart2; /* A <span> tag */ |
| 619 | 673 | int iEnd2; /* Write </span> prior to character iEnd2 */ |
| 674 | + ReCompiled *pRe; /* Only colorize matching lines, if not NULL */ | |
| 620 | 675 | }; |
| 621 | 676 | |
| 622 | 677 | /* |
| 623 | 678 | ** Flags for sbsWriteText() |
| 624 | 679 | */ |
| @@ -640,13 +695,17 @@ | ||
| 640 | 695 | int k; /* Cursor position */ |
| 641 | 696 | int needEndSpan = 0; |
| 642 | 697 | const char *zIn = pLine->z; |
| 643 | 698 | char *z = &p->zLine[p->n]; |
| 644 | 699 | int w = p->width; |
| 700 | + int colorize = p->escHtml; | |
| 701 | + if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){ | |
| 702 | + colorize = 0; | |
| 703 | + } | |
| 645 | 704 | for(i=j=k=0; k<w && i<n; i++, k++){ |
| 646 | 705 | char c = zIn[i]; |
| 647 | - if( p->escHtml ){ | |
| 706 | + if( colorize ){ | |
| 648 | 707 | if( i==p->iStart ){ |
| 649 | 708 | int x = strlen(p->zStart); |
| 650 | 709 | memcpy(z+j, p->zStart, x); |
| 651 | 710 | j += x; |
| 652 | 711 | needEndSpan = 1; |
| @@ -797,10 +856,41 @@ | ||
| 797 | 856 | } |
| 798 | 857 | } |
| 799 | 858 | } |
| 800 | 859 | return rc; |
| 801 | 860 | } |
| 861 | + | |
| 862 | +/* | |
| 863 | +** Try to shift iStart as far as possible to the left. | |
| 864 | +*/ | |
| 865 | +static void sbsShiftLeft(SbsLine *p, const char *z){ | |
| 866 | + int i, j; | |
| 867 | + while( (i=p->iStart)>0 && z[i-1]==z[i] ){ | |
| 868 | + for(j=i+1; j<p->iEnd && z[j-1]==z[j]; j++){} | |
| 869 | + if( j<p->iEnd ) break; | |
| 870 | + p->iStart--; | |
| 871 | + p->iEnd--; | |
| 872 | + } | |
| 873 | +} | |
| 874 | + | |
| 875 | +/* | |
| 876 | +** Simplify iStart and iStart2: | |
| 877 | +** | |
| 878 | +** * If iStart is a null-change then move iStart2 into iStart | |
| 879 | +** * Make sure any null-changes are in canonoical form. | |
| 880 | +*/ | |
| 881 | +static void sbsSimplifyLine(SbsLine *p){ | |
| 882 | + if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0; | |
| 883 | + if( p->iStart==p->iEnd ){ | |
| 884 | + p->iStart = p->iStart2; | |
| 885 | + p->iEnd = p->iEnd2; | |
| 886 | + p->zStart = p->zStart2; | |
| 887 | + p->iStart2 = 0; | |
| 888 | + p->iEnd2 = 0; | |
| 889 | + } | |
| 890 | + if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1; | |
| 891 | +} | |
| 802 | 892 | |
| 803 | 893 | /* |
| 804 | 894 | ** Write out lines that have been edited. Adjust the highlight to cover |
| 805 | 895 | ** only those parts of the line that actually changed. |
| 806 | 896 | */ |
| @@ -891,41 +981,35 @@ | ||
| 891 | 981 | && textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS) |
| 892 | 982 | ){ |
| 893 | 983 | sbsWriteLineno(p, lnLeft); |
| 894 | 984 | p->iStart = nPrefix; |
| 895 | 985 | p->iEnd = nPrefix + aLCS[0]; |
| 896 | - p->zStart = aLCS[2]==0 ? zClassRm : zClassChng; | |
| 986 | + if( aLCS[2]==0 ){ | |
| 987 | + sbsShiftLeft(p, pLeft->z); | |
| 988 | + p->zStart = zClassRm; | |
| 989 | + }else{ | |
| 990 | + p->zStart = zClassChng; | |
| 991 | + } | |
| 897 | 992 | p->iStart2 = nPrefix + aLCS[1]; |
| 898 | 993 | p->iEnd2 = nLeft - nSuffix; |
| 899 | 994 | p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng; |
| 900 | - if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0; | |
| 901 | - if( p->iStart==p->iEnd ){ | |
| 902 | - p->iStart = p->iStart2; | |
| 903 | - p->iEnd = p->iEnd2; | |
| 904 | - p->zStart = p->zStart2; | |
| 905 | - p->iStart2 = 0; | |
| 906 | - p->iEnd2 = 0; | |
| 907 | - } | |
| 908 | - if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1; | |
| 995 | + sbsSimplifyLine(p); | |
| 909 | 996 | sbsWriteText(p, pLeft, SBS_PAD); |
| 910 | 997 | sbsWrite(p, " | ", 3); |
| 911 | 998 | sbsWriteLineno(p, lnRight); |
| 912 | 999 | p->iStart = nPrefix; |
| 913 | 1000 | p->iEnd = nPrefix + aLCS[2]; |
| 914 | - p->zStart = aLCS[0]==0 ? zClassAdd : zClassChng; | |
| 1001 | + if( aLCS[0]==0 ){ | |
| 1002 | + sbsShiftLeft(p, pRight->z); | |
| 1003 | + p->zStart = zClassAdd; | |
| 1004 | + }else{ | |
| 1005 | + p->zStart = zClassChng; | |
| 1006 | + } | |
| 915 | 1007 | p->iStart2 = nPrefix + aLCS[3]; |
| 916 | 1008 | p->iEnd2 = nRight - nSuffix; |
| 917 | 1009 | p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng; |
| 918 | - if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0; | |
| 919 | - if( p->iStart==p->iEnd ){ | |
| 920 | - p->iStart = p->iStart2; | |
| 921 | - p->iEnd = p->iEnd2; | |
| 922 | - p->zStart = p->zStart2; | |
| 923 | - p->iStart2 = 0; | |
| 924 | - p->iEnd2 = 0; | |
| 925 | - } | |
| 926 | - if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1; | |
| 1010 | + sbsSimplifyLine(p); | |
| 927 | 1011 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 928 | 1012 | return; |
| 929 | 1013 | } |
| 930 | 1014 | |
| 931 | 1015 | /* If all else fails, show a single big change between left and right */ |
| @@ -1018,13 +1102,16 @@ | ||
| 1018 | 1102 | ** |
| 1019 | 1103 | ** The return value is a buffer of unsigned characters, obtained from |
| 1020 | 1104 | ** fossil_malloc(). (The caller needs to free the return value using |
| 1021 | 1105 | ** fossil_free().) Entries in the returned array have values as follows: |
| 1022 | 1106 | ** |
| 1023 | -** 1. Delete the next line of pLeft. | |
| 1024 | -** 2. The next line of pLeft changes into the next line of pRight. | |
| 1025 | -** 3. Insert the next line of pRight. | |
| 1107 | +** 1. Delete the next line of pLeft. | |
| 1108 | +** 2. Insert the next line of pRight. | |
| 1109 | +** 3. The next line of pLeft changes into the next line of pRight. | |
| 1110 | +** 4. Delete one line from pLeft and add one line to pRight. | |
| 1111 | +** | |
| 1112 | +** Values larger than three indicate better matches. | |
| 1026 | 1113 | ** |
| 1027 | 1114 | ** The length of the returned array will be just large enough to cause |
| 1028 | 1115 | ** all elements of pLeft and pRight to be consumed. |
| 1029 | 1116 | ** |
| 1030 | 1117 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by |
| @@ -1039,27 +1126,32 @@ | ||
| 1039 | 1126 | ){ |
| 1040 | 1127 | int i, j, k; /* Loop counters */ |
| 1041 | 1128 | int *a; /* One row of the Wagner matrix */ |
| 1042 | 1129 | int *pToFree; /* Space that needs to be freed */ |
| 1043 | 1130 | unsigned char *aM; /* Wagner result matrix */ |
| 1131 | + int nMatch, iMatch; /* Number of matching lines and match score */ | |
| 1132 | + int mnLen; /* MIN(nLeft, nRight) */ | |
| 1133 | + int mxLen; /* MAX(nLeft, nRight) */ | |
| 1044 | 1134 | int aBuf[100]; /* Stack space for a[] if nRight not to big */ |
| 1045 | 1135 | |
| 1046 | 1136 | aM = fossil_malloc( (nLeft+1)*(nRight+1) ); |
| 1047 | 1137 | if( nLeft==0 ){ |
| 1048 | - memset(aM, 3, nRight); | |
| 1138 | + memset(aM, 2, nRight); | |
| 1049 | 1139 | return aM; |
| 1050 | 1140 | } |
| 1051 | 1141 | if( nRight==0 ){ |
| 1052 | 1142 | memset(aM, 1, nLeft); |
| 1053 | 1143 | return aM; |
| 1054 | 1144 | } |
| 1055 | 1145 | |
| 1056 | 1146 | /* This algorithm is O(N**2). So if N is too big, bail out with a |
| 1057 | 1147 | ** simple (but stupid and ugly) result that doesn't take too long. */ |
| 1148 | + mnLen = nLeft<nRight ? nLeft : nRight; | |
| 1058 | 1149 | if( nLeft*nRight>100000 ){ |
| 1059 | - memset(aM, 3, nRight); | |
| 1060 | - memset(aM+nRight, 1, nLeft); | |
| 1150 | + memset(aM, 4, mnLen); | |
| 1151 | + if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen); | |
| 1152 | + if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen); | |
| 1061 | 1153 | return aM; |
| 1062 | 1154 | } |
| 1063 | 1155 | |
| 1064 | 1156 | if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){ |
| 1065 | 1157 | pToFree = 0; |
| @@ -1068,30 +1160,30 @@ | ||
| 1068 | 1160 | a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) ); |
| 1069 | 1161 | } |
| 1070 | 1162 | |
| 1071 | 1163 | /* Compute the best alignment */ |
| 1072 | 1164 | for(i=0; i<=nRight; i++){ |
| 1073 | - aM[i] = 3; | |
| 1165 | + aM[i] = 2; | |
| 1074 | 1166 | a[i] = i*50; |
| 1075 | 1167 | } |
| 1076 | 1168 | aM[0] = 0; |
| 1077 | 1169 | for(j=1; j<=nLeft; j++){ |
| 1078 | 1170 | int p = a[0]; |
| 1079 | 1171 | a[0] = p+50; |
| 1080 | 1172 | aM[j*(nRight+1)] = 1; |
| 1081 | 1173 | for(i=1; i<=nRight; i++){ |
| 1082 | 1174 | int m = a[i-1]+50; |
| 1083 | - int d = 3; | |
| 1175 | + int d = 2; | |
| 1084 | 1176 | if( m>a[i]+50 ){ |
| 1085 | 1177 | m = a[i]+50; |
| 1086 | 1178 | d = 1; |
| 1087 | 1179 | } |
| 1088 | 1180 | if( m>p ){ |
| 1089 | 1181 | int score = match_dline(&aLeft[j-1], &aRight[i-1]); |
| 1090 | - if( (score<66 || (i<j+1 && i>j-1)) && m>p+score ){ | |
| 1182 | + if( (score<=63 || (i<j+1 && i>j-1)) && m>p+score ){ | |
| 1091 | 1183 | m = p+score; |
| 1092 | - d = 2; | |
| 1184 | + d = 3 | score*4; | |
| 1093 | 1185 | } |
| 1094 | 1186 | } |
| 1095 | 1187 | p = a[i]; |
| 1096 | 1188 | a[i] = m; |
| 1097 | 1189 | aM[j*(nRight+1)+i] = d; |
| @@ -1100,28 +1192,50 @@ | ||
| 1100 | 1192 | |
| 1101 | 1193 | /* Compute the lowest-cost path back through the matrix */ |
| 1102 | 1194 | i = nRight; |
| 1103 | 1195 | j = nLeft; |
| 1104 | 1196 | k = (nRight+1)*(nLeft+1)-1; |
| 1197 | + nMatch = iMatch = 0; | |
| 1105 | 1198 | while( i+j>0 ){ |
| 1106 | - unsigned char c = aM[k--]; | |
| 1107 | - if( c==2 ){ | |
| 1199 | + unsigned char c = aM[k]; | |
| 1200 | + if( c>=3 ){ | |
| 1108 | 1201 | assert( i>0 && j>0 ); |
| 1109 | 1202 | i--; |
| 1110 | 1203 | j--; |
| 1111 | - }else if( c==3 ){ | |
| 1204 | + nMatch++; | |
| 1205 | + iMatch += (c>>2); | |
| 1206 | + aM[k] = 3; | |
| 1207 | + }else if( c==2 ){ | |
| 1112 | 1208 | assert( i>0 ); |
| 1113 | 1209 | i--; |
| 1114 | 1210 | }else{ |
| 1115 | 1211 | assert( j>0 ); |
| 1116 | 1212 | j--; |
| 1117 | 1213 | } |
| 1214 | + k--; | |
| 1118 | 1215 | aM[k] = aM[j*(nRight+1)+i]; |
| 1119 | 1216 | } |
| 1120 | 1217 | k++; |
| 1121 | 1218 | i = (nRight+1)*(nLeft+1) - k; |
| 1122 | 1219 | memmove(aM, &aM[k], i); |
| 1220 | + | |
| 1221 | + /* If: | |
| 1222 | + ** (1) the alignment is more than 25% longer than the longest side, and | |
| 1223 | + ** (2) the average match cost exceeds 15 | |
| 1224 | + ** Then this is probably an alignment that will be difficult for humans | |
| 1225 | + ** to read. So instead, just show all of the right side inserted followed | |
| 1226 | + ** by all of the left side deleted. | |
| 1227 | + ** | |
| 1228 | + ** The coefficients for conditions (1) and (2) above are determined by | |
| 1229 | + ** experimentation. | |
| 1230 | + */ | |
| 1231 | + mxLen = nLeft>nRight ? nLeft : nRight; | |
| 1232 | + if( i*4>mxLen*5 && (nMatch==0 || iMatch/nMatch>15) ){ | |
| 1233 | + memset(aM, 4, mnLen); | |
| 1234 | + if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen); | |
| 1235 | + if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen); | |
| 1236 | + } | |
| 1123 | 1237 | |
| 1124 | 1238 | /* Return the result */ |
| 1125 | 1239 | fossil_free(pToFree); |
| 1126 | 1240 | return aM; |
| 1127 | 1241 | } |
| @@ -1141,13 +1255,12 @@ | ||
| 1141 | 1255 | ** in, compute a side-by-side diff into pOut. |
| 1142 | 1256 | */ |
| 1143 | 1257 | static void sbsDiff( |
| 1144 | 1258 | DContext *p, /* The computed diff */ |
| 1145 | 1259 | Blob *pOut, /* Write the results here */ |
| 1146 | - int nContext, /* Number of lines of context around each change */ | |
| 1147 | - int width, /* Width of each column of output */ | |
| 1148 | - int escHtml /* True to generate HTML output */ | |
| 1260 | + ReCompiled *pRe, /* Only show changes that match this regex */ | |
| 1261 | + u64 diffFlags /* Flags controlling the diff */ | |
| 1149 | 1262 | ){ |
| 1150 | 1263 | DLine *A; /* Left side of the diff */ |
| 1151 | 1264 | DLine *B; /* Right side of the diff */ |
| 1152 | 1265 | int a = 0; /* Index of next line in A[] */ |
| 1153 | 1266 | int b = 0; /* Index of next line in B[] */ |
| @@ -1159,16 +1272,20 @@ | ||
| 1159 | 1272 | int i, j; /* Loop counters */ |
| 1160 | 1273 | int m, ma, mb;/* Number of lines to output */ |
| 1161 | 1274 | int skip; /* Number of lines to skip */ |
| 1162 | 1275 | int nChunk = 0; /* Number of chunks of diff output seen so far */ |
| 1163 | 1276 | SbsLine s; /* Output line buffer */ |
| 1277 | + int nContext; /* Lines of context above and below each change */ | |
| 1278 | + int showDivider = 0; /* True to show the divider */ | |
| 1164 | 1279 | |
| 1165 | 1280 | memset(&s, 0, sizeof(s)); |
| 1166 | - s.zLine = fossil_malloc( 15*width + 200 ); | |
| 1281 | + s.width = diff_width(diffFlags); | |
| 1282 | + s.zLine = fossil_malloc( 15*s.width + 200 ); | |
| 1167 | 1283 | if( s.zLine==0 ) return; |
| 1168 | - s.width = width; | |
| 1169 | - s.escHtml = escHtml; | |
| 1284 | + nContext = diff_context_lines(diffFlags); | |
| 1285 | + s.escHtml = (diffFlags & DIFF_HTML)!=0; | |
| 1286 | + s.pRe = pRe; | |
| 1170 | 1287 | s.iStart = -1; |
| 1171 | 1288 | s.iStart2 = 0; |
| 1172 | 1289 | s.iEnd = -1; |
| 1173 | 1290 | A = p->aFrom; |
| 1174 | 1291 | B = p->aTo; |
| @@ -1177,10 +1294,35 @@ | ||
| 1177 | 1294 | while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } |
| 1178 | 1295 | for(r=0; r<mxr; r += 3*nr){ |
| 1179 | 1296 | /* Figure out how many triples to show in a single block */ |
| 1180 | 1297 | for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} |
| 1181 | 1298 | /* printf("r=%d nr=%d\n", r, nr); */ |
| 1299 | + | |
| 1300 | + /* If there is a regex, skip this block (generate no diff output) | |
| 1301 | + ** if the regex matches or does not match both insert and delete. | |
| 1302 | + ** Only display the block if one side matches but the other side does | |
| 1303 | + ** not. | |
| 1304 | + */ | |
| 1305 | + if( pRe ){ | |
| 1306 | + int hideBlock = 1; | |
| 1307 | + int xa = a, xb = b; | |
| 1308 | + for(i=0; hideBlock && i<nr; i++){ | |
| 1309 | + int c1, c2; | |
| 1310 | + xa += R[r+i*3]; | |
| 1311 | + xb += R[r+i*3]; | |
| 1312 | + c1 = re_dline_match(pRe, &A[xa], R[r+i*3+1]); | |
| 1313 | + c2 = re_dline_match(pRe, &B[xb], R[r+i*3+2]); | |
| 1314 | + hideBlock = c1==c2; | |
| 1315 | + xa += R[r+i*3+1]; | |
| 1316 | + xb += R[r+i*3+2]; | |
| 1317 | + } | |
| 1318 | + if( hideBlock ){ | |
| 1319 | + a = xa; | |
| 1320 | + b = xb; | |
| 1321 | + continue; | |
| 1322 | + } | |
| 1323 | + } | |
| 1182 | 1324 | |
| 1183 | 1325 | /* For the current block comprising nr triples, figure out |
| 1184 | 1326 | ** how many lines of A and B are to be displayed |
| 1185 | 1327 | */ |
| 1186 | 1328 | if( R[r]>nContext ){ |
| @@ -1205,20 +1347,21 @@ | ||
| 1205 | 1347 | na += R[r+i*3]; |
| 1206 | 1348 | nb += R[r+i*3]; |
| 1207 | 1349 | } |
| 1208 | 1350 | |
| 1209 | 1351 | /* Draw the separator between blocks */ |
| 1210 | - if( r>0 ){ | |
| 1211 | - if( escHtml ){ | |
| 1352 | + if( showDivider ){ | |
| 1353 | + if( s.escHtml ){ | |
| 1212 | 1354 | blob_appendf(pOut, "<span class=\"diffhr\">%.*c</span>\n", |
| 1213 | - width*2+16, '.'); | |
| 1355 | + s.width*2+16, '.'); | |
| 1214 | 1356 | }else{ |
| 1215 | - blob_appendf(pOut, "%.*c\n", width*2+16, '.'); | |
| 1357 | + blob_appendf(pOut, "%.*c\n", s.width*2+16, '.'); | |
| 1216 | 1358 | } |
| 1217 | 1359 | } |
| 1360 | + showDivider = 1; | |
| 1218 | 1361 | nChunk++; |
| 1219 | - if( escHtml ){ | |
| 1362 | + if( s.escHtml ){ | |
| 1220 | 1363 | blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk); |
| 1221 | 1364 | } |
| 1222 | 1365 | |
| 1223 | 1366 | /* Show the initial common area */ |
| 1224 | 1367 | a += skip; |
| @@ -1254,38 +1397,41 @@ | ||
| 1254 | 1397 | } |
| 1255 | 1398 | |
| 1256 | 1399 | alignment = sbsAlignment(&A[a], ma, &B[b], mb); |
| 1257 | 1400 | for(j=0; ma+mb>0; j++){ |
| 1258 | 1401 | if( alignment[j]==1 ){ |
| 1402 | + /* Delete one line from the left */ | |
| 1259 | 1403 | s.n = 0; |
| 1260 | 1404 | sbsWriteLineno(&s, a); |
| 1261 | 1405 | s.iStart = 0; |
| 1262 | 1406 | s.zStart = "<span class=\"diffrm\">"; |
| 1263 | 1407 | s.iEnd = s.width; |
| 1264 | 1408 | sbsWriteText(&s, &A[a], SBS_PAD); |
| 1265 | - if( escHtml ){ | |
| 1409 | + if( s.escHtml ){ | |
| 1266 | 1410 | sbsWrite(&s, " <\n", 6); |
| 1267 | 1411 | }else{ |
| 1268 | 1412 | sbsWrite(&s, " <\n", 3); |
| 1269 | 1413 | } |
| 1270 | 1414 | blob_append(pOut, s.zLine, s.n); |
| 1271 | 1415 | assert( ma>0 ); |
| 1272 | 1416 | ma--; |
| 1273 | 1417 | a++; |
| 1274 | - }else if( alignment[j]==2 ){ | |
| 1418 | + }else if( alignment[j]==3 ){ | |
| 1419 | + /* The left line is changed into the right line */ | |
| 1275 | 1420 | s.n = 0; |
| 1276 | 1421 | sbsWriteLineChange(&s, &A[a], a, &B[b], b); |
| 1277 | 1422 | blob_append(pOut, s.zLine, s.n); |
| 1278 | 1423 | assert( ma>0 && mb>0 ); |
| 1279 | 1424 | ma--; |
| 1280 | 1425 | mb--; |
| 1281 | 1426 | a++; |
| 1282 | 1427 | b++; |
| 1283 | - }else{ | |
| 1428 | + }else if( alignment[j]==2 ){ | |
| 1429 | + /* Insert one line on the right */ | |
| 1284 | 1430 | s.n = 0; |
| 1285 | - sbsWriteSpace(&s, width + 7); | |
| 1286 | - if( escHtml ){ | |
| 1431 | + sbsWriteSpace(&s, s.width + 7); | |
| 1432 | + if( s.escHtml ){ | |
| 1287 | 1433 | sbsWrite(&s, " > ", 6); |
| 1288 | 1434 | }else{ |
| 1289 | 1435 | sbsWrite(&s, " > ", 3); |
| 1290 | 1436 | } |
| 1291 | 1437 | sbsWriteLineno(&s, b); |
| @@ -1295,11 +1441,31 @@ | ||
| 1295 | 1441 | sbsWriteText(&s, &B[b], SBS_NEWLINE); |
| 1296 | 1442 | blob_append(pOut, s.zLine, s.n); |
| 1297 | 1443 | assert( mb>0 ); |
| 1298 | 1444 | mb--; |
| 1299 | 1445 | b++; |
| 1446 | + }else{ | |
| 1447 | + /* Delete from the left and insert on the right */ | |
| 1448 | + s.n = 0; | |
| 1449 | + sbsWriteLineno(&s, a); | |
| 1450 | + s.iStart = 0; | |
| 1451 | + s.zStart = "<span class=\"diffrm\">"; | |
| 1452 | + s.iEnd = s.width; | |
| 1453 | + sbsWriteText(&s, &A[a], SBS_PAD); | |
| 1454 | + sbsWrite(&s, " | ", 3); | |
| 1455 | + sbsWriteLineno(&s, b); | |
| 1456 | + s.iStart = 0; | |
| 1457 | + s.zStart = "<span class=\"diffadd\">"; | |
| 1458 | + s.iEnd = s.width; | |
| 1459 | + sbsWriteText(&s, &B[b], SBS_NEWLINE); | |
| 1460 | + blob_append(pOut, s.zLine, s.n); | |
| 1461 | + ma--; | |
| 1462 | + mb--; | |
| 1463 | + a++; | |
| 1464 | + b++; | |
| 1300 | 1465 | } |
| 1466 | + | |
| 1301 | 1467 | } |
| 1302 | 1468 | fossil_free(alignment); |
| 1303 | 1469 | if( i<nr-1 ){ |
| 1304 | 1470 | m = R[r+i*3+3]; |
| 1305 | 1471 | for(j=0; j<m; j++){ |
| @@ -1723,11 +1889,11 @@ | ||
| 1723 | 1889 | ** Extract the number of lines of context from diffFlags. Supply an |
| 1724 | 1890 | ** appropriate default if no context width is specified. |
| 1725 | 1891 | */ |
| 1726 | 1892 | int diff_context_lines(u64 diffFlags){ |
| 1727 | 1893 | int n = diffFlags & DIFF_CONTEXT_MASK; |
| 1728 | - if( n==0 ) n = 5; | |
| 1894 | + if( n==0 && (diffFlags & DIFF_CONTEXT_EX)==0 ) n = 5; | |
| 1729 | 1895 | return n; |
| 1730 | 1896 | } |
| 1731 | 1897 | |
| 1732 | 1898 | /* |
| 1733 | 1899 | ** Extract the width of columns for side-by-side diff. Supply an |
| @@ -1755,22 +1921,21 @@ | ||
| 1755 | 1921 | */ |
| 1756 | 1922 | int *text_diff( |
| 1757 | 1923 | Blob *pA_Blob, /* FROM file */ |
| 1758 | 1924 | Blob *pB_Blob, /* TO file */ |
| 1759 | 1925 | Blob *pOut, /* Write diff here if not NULL */ |
| 1926 | + ReCompiled *pRe, /* Only output changes where this Regexp matches */ | |
| 1760 | 1927 | u64 diffFlags /* DIFF_* flags defined above */ |
| 1761 | 1928 | ){ |
| 1762 | 1929 | int ignoreEolWs; /* Ignore whitespace at the end of lines */ |
| 1763 | - int nContext; /* Amount of context to display */ | |
| 1764 | 1930 | DContext c; |
| 1765 | 1931 | |
| 1766 | 1932 | if( diffFlags & DIFF_INVERT ){ |
| 1767 | 1933 | Blob *pTemp = pA_Blob; |
| 1768 | 1934 | pA_Blob = pB_Blob; |
| 1769 | 1935 | pB_Blob = pTemp; |
| 1770 | 1936 | } |
| 1771 | - nContext = diff_context_lines(diffFlags); | |
| 1772 | 1937 | ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0; |
| 1773 | 1938 | |
| 1774 | 1939 | /* Prepare the input files */ |
| 1775 | 1940 | memset(&c, 0, sizeof(c)); |
| 1776 | 1941 | c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob), |
| @@ -1790,17 +1955,14 @@ | ||
| 1790 | 1955 | diff_all(&c); |
| 1791 | 1956 | if( (diffFlags & DIFF_NOOPT)==0 ) diff_optimize(&c); |
| 1792 | 1957 | |
| 1793 | 1958 | if( pOut ){ |
| 1794 | 1959 | /* Compute a context or side-by-side diff into pOut */ |
| 1795 | - int escHtml = (diffFlags & DIFF_HTML)!=0; | |
| 1796 | 1960 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 1797 | - int width = diff_width(diffFlags); | |
| 1798 | - sbsDiff(&c, pOut, nContext, width, escHtml); | |
| 1961 | + sbsDiff(&c, pOut, pRe, diffFlags); | |
| 1799 | 1962 | }else{ |
| 1800 | - int showLn = (diffFlags & DIFF_LINENO)!=0; | |
| 1801 | - contextDiff(&c, pOut, nContext, showLn, escHtml); | |
| 1963 | + contextDiff(&c, pOut, pRe, diffFlags); | |
| 1802 | 1964 | } |
| 1803 | 1965 | fossil_free(c.aFrom); |
| 1804 | 1966 | fossil_free(c.aTo); |
| 1805 | 1967 | fossil_free(c.aEdit); |
| 1806 | 1968 | return 0; |
| @@ -1826,19 +1988,19 @@ | ||
| 1826 | 1988 | ** --noopt Disable optimization DIFF_NOOPT |
| 1827 | 1989 | ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE |
| 1828 | 1990 | ** --unified Unified diff. ~DIFF_SIDEBYSIDE |
| 1829 | 1991 | ** --width|-W N N character lines. DIFF_WIDTH_MASK |
| 1830 | 1992 | */ |
| 1831 | -int diff_options(void){ | |
| 1993 | +u64 diff_options(void){ | |
| 1832 | 1994 | u64 diffFlags = 0; |
| 1833 | 1995 | const char *z; |
| 1834 | 1996 | int f; |
| 1835 | 1997 | if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 1836 | 1998 | if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE; |
| 1837 | - if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){ | |
| 1999 | + if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){ | |
| 1838 | 2000 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 1839 | - diffFlags |= f; | |
| 2001 | + diffFlags |= f + DIFF_CONTEXT_EX; | |
| 1840 | 2002 | } |
| 1841 | 2003 | if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ |
| 1842 | 2004 | f *= DIFF_CONTEXT_MASK+1; |
| 1843 | 2005 | if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; |
| 1844 | 2006 | diffFlags |= f; |
| @@ -1863,34 +2025,52 @@ | ||
| 1863 | 2025 | if( g.argc<4 ) usage("FILE1 FILE2 ..."); |
| 1864 | 2026 | blob_read_from_file(&a, g.argv[2]); |
| 1865 | 2027 | for(i=3; i<g.argc; i++){ |
| 1866 | 2028 | if( i>3 ) fossil_print("-------------------------------\n"); |
| 1867 | 2029 | blob_read_from_file(&b, g.argv[i]); |
| 1868 | - R = text_diff(&a, &b, 0, diffFlags); | |
| 2030 | + R = text_diff(&a, &b, 0, 0, diffFlags); | |
| 1869 | 2031 | for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){ |
| 1870 | 2032 | fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]); |
| 1871 | 2033 | } |
| 1872 | 2034 | /* free(R); */ |
| 1873 | 2035 | blob_reset(&b); |
| 1874 | 2036 | } |
| 1875 | 2037 | } |
| 1876 | 2038 | |
| 1877 | 2039 | /* |
| 1878 | -** COMMAND: test-udiff | |
| 2040 | +** COMMAND: test-diff | |
| 2041 | +** | |
| 2042 | +** Usage: %fossil [options] FILE1 FILE2 | |
| 1879 | 2043 | ** |
| 1880 | 2044 | ** Print the difference between two files. The usual diff options apply. |
| 1881 | 2045 | */ |
| 1882 | -void test_udiff_cmd(void){ | |
| 2046 | +void test_diff_cmd(void){ | |
| 1883 | 2047 | Blob a, b, out; |
| 1884 | - u64 diffFlag = diff_options(); | |
| 2048 | + u64 diffFlag; | |
| 2049 | + const char *zRe; /* Regex filter for diff output */ | |
| 2050 | + ReCompiled *pRe = 0; /* Regex filter for diff output */ | |
| 1885 | 2051 | |
| 2052 | + if( find_option("tk",0,0)!=0 ){ | |
| 2053 | + diff_tk("test-diff", 2); | |
| 2054 | + return; | |
| 2055 | + } | |
| 2056 | + find_option("i",0,0); | |
| 2057 | + zRe = find_option("regexp","e",1); | |
| 2058 | + if( zRe ){ | |
| 2059 | + const char *zErr = re_compile(&pRe, zRe, 0); | |
| 2060 | + if( zErr ) fossil_fatal("regex error: %s", zErr); | |
| 2061 | + } | |
| 2062 | + diffFlag = diff_options(); | |
| 2063 | + verify_all_options(); | |
| 1886 | 2064 | if( g.argc!=4 ) usage("FILE1 FILE2"); |
| 2065 | + diff_print_filenames(g.argv[2], g.argv[3], diffFlag); | |
| 1887 | 2066 | blob_read_from_file(&a, g.argv[2]); |
| 1888 | 2067 | blob_read_from_file(&b, g.argv[3]); |
| 1889 | 2068 | blob_zero(&out); |
| 1890 | - text_diff(&a, &b, &out, diffFlag); | |
| 2069 | + text_diff(&a, &b, &out, pRe, diffFlag); | |
| 1891 | 2070 | blob_write_to_file(&out, "-"); |
| 2071 | + re_free(pRe); | |
| 1892 | 2072 | } |
| 1893 | 2073 | |
| 1894 | 2074 | /************************************************************************** |
| 1895 | 2075 | ** The basic difference engine is above. What follows is the annotation |
| 1896 | 2076 | ** engine. Both are in the same file since they share many components. |
| 1897 | 2077 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -23,11 +23,12 @@ | |
| 23 | #include <assert.h> |
| 24 | |
| 25 | |
| 26 | #if INTERFACE |
| 27 | /* |
| 28 | ** Allowed flag parameters to the text_diff() and html_sbsdiff() functions: |
| 29 | */ |
| 30 | #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */ |
| 31 | #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */ |
| 32 | #define DIFF_IGNORE_EOLWS ((u64)0x01000000) /* Ignore end-of-line whitespace */ |
| 33 | #define DIFF_SIDEBYSIDE ((u64)0x02000000) /* Generate a side-by-side diff */ |
| @@ -37,10 +38,11 @@ | |
| 37 | #define DIFF_HTML ((u64)0x10000000) /* Render for HTML */ |
| 38 | #define DIFF_LINENO ((u64)0x20000000) /* Show line numbers */ |
| 39 | #define DIFF_WS_WARNING ((u64)0x40000000) /* Warn about whitespace */ |
| 40 | #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */ |
| 41 | #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */ |
| 42 | |
| 43 | /* |
| 44 | ** These error messages are shared in multiple locations. They are defined |
| 45 | ** here for consistency. |
| 46 | */ |
| @@ -52,11 +54,11 @@ | |
| 52 | |
| 53 | #define looks_like_binary(blob) (looks_like_utf8((blob)) == 0) |
| 54 | #endif /* INTERFACE */ |
| 55 | |
| 56 | /* |
| 57 | ** Maximum length of a line in a text file, in bytes. (8192) |
| 58 | */ |
| 59 | #define LENGTH_MASK_SZ 13 |
| 60 | #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1) |
| 61 | |
| 62 | /* |
| @@ -116,10 +118,13 @@ | |
| 116 | ** more. If trailing whitespace is ignored, the "patch" command gets |
| 117 | ** confused by the diff output. Ticket [a9f7b23c2e376af5b0e5b] |
| 118 | ** |
| 119 | ** Return 0 if the file is binary or contains a line that is |
| 120 | ** too long. |
| 121 | */ |
| 122 | static DLine *break_into_lines(const char *z, int n, int *pnLine, int ignoreWS){ |
| 123 | int nLine, i, j, k, x; |
| 124 | unsigned int h, h2; |
| 125 | DLine *a; |
| @@ -407,34 +412,50 @@ | |
| 407 | ** Return true if two DLine elements are identical. |
| 408 | */ |
| 409 | static int same_dline(DLine *pA, DLine *pB){ |
| 410 | return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0; |
| 411 | } |
| 412 | |
| 413 | /* |
| 414 | ** Append a single line of context-diff output to pOut. |
| 415 | */ |
| 416 | static void appendDiffLine( |
| 417 | Blob *pOut, /* Where to write the line of output */ |
| 418 | char cPrefix, /* One of " ", "+", or "-" */ |
| 419 | DLine *pLine, /* The line to be output */ |
| 420 | int html /* True if generating HTML. False for plain text */ |
| 421 | ){ |
| 422 | int i; |
| 423 | blob_append(pOut, &cPrefix, 1); |
| 424 | if( html ){ |
| 425 | char *zHtml; |
| 426 | if( cPrefix=='+' ){ |
| 427 | blob_append(pOut, "<span class=\"diffadd\">", -1); |
| 428 | }else if( cPrefix=='-' ){ |
| 429 | blob_append(pOut, "<span class=\"diffrm\">", -1); |
| 430 | } |
| 431 | zHtml = htmlize(pLine->z, (pLine->h & LENGTH_MASK)); |
| 432 | for(i=0; i<strlen(zHtml); i++){ |
| 433 | char c = zHtml[i]; |
| 434 | if( c=='\t' || c=='\r' || c=='\f' ) zHtml[i] = ' '; |
| 435 | } |
| 436 | blob_append(pOut, zHtml, -1); |
| 437 | fossil_free(zHtml); |
| 438 | if( cPrefix!=' ' ){ |
| 439 | blob_append(pOut, "</span>", -1); |
| 440 | } |
| @@ -444,11 +465,11 @@ | |
| 444 | blob_append(pOut, "\n", 1); |
| 445 | } |
| 446 | |
| 447 | /* |
| 448 | ** Add two line numbers to the beginning of an output line for a context |
| 449 | ** diff. One or of the other of the two numbers might be zero, which means |
| 450 | ** to leave that number field blank. The "html" parameter means to format |
| 451 | ** the output for HTML. |
| 452 | */ |
| 453 | static void appendDiffLineno(Blob *pOut, int lnA, int lnB, int html){ |
| 454 | if( html ) blob_append(pOut, "<span class=\"diffln\">", -1); |
| @@ -463,21 +484,19 @@ | |
| 463 | blob_append(pOut, " ", 8); |
| 464 | } |
| 465 | if( html ) blob_append(pOut, "</span>", -1); |
| 466 | } |
| 467 | |
| 468 | |
| 469 | /* |
| 470 | ** Given a raw diff p[] in which the p->aEdit[] array has been filled |
| 471 | ** in, compute a context diff into pOut. |
| 472 | */ |
| 473 | static void contextDiff( |
| 474 | DContext *p, /* The difference */ |
| 475 | Blob *pOut, /* Output a context diff to here */ |
| 476 | int nContext, /* Number of lines of context */ |
| 477 | int showLn, /* Show line numbers */ |
| 478 | int html /* Render as HTML */ |
| 479 | ){ |
| 480 | DLine *A; /* Left side of the diff */ |
| 481 | DLine *B; /* Right side of the diff */ |
| 482 | int a = 0; /* Index of next line in A[] */ |
| 483 | int b = 0; /* Index of next line in B[] */ |
| @@ -488,11 +507,18 @@ | |
| 488 | int na, nb; /* Number of lines shown from A and B */ |
| 489 | int i, j; /* Loop counters */ |
| 490 | int m; /* Number of lines to output */ |
| 491 | int skip; /* Number of lines to skip */ |
| 492 | int nChunk = 0; /* Number of diff chunks seen so far */ |
| 493 | |
| 494 | A = p->aFrom; |
| 495 | B = p->aTo; |
| 496 | R = p->aEdit; |
| 497 | mxr = p->nEdit; |
| 498 | while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } |
| @@ -499,10 +525,35 @@ | |
| 499 | for(r=0; r<mxr; r += 3*nr){ |
| 500 | /* Figure out how many triples to show in a single block */ |
| 501 | for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} |
| 502 | /* printf("r=%d nr=%d\n", r, nr); */ |
| 503 | |
| 504 | /* For the current block comprising nr triples, figure out |
| 505 | ** how many lines of A and B are to be displayed |
| 506 | */ |
| 507 | if( R[r]>nContext ){ |
| 508 | na = nb = nContext; |
| @@ -526,17 +577,18 @@ | |
| 526 | na += R[r+i*3]; |
| 527 | nb += R[r+i*3]; |
| 528 | } |
| 529 | |
| 530 | /* Show the header for this block, or if we are doing a modified |
| 531 | ** context diff that contains line numbers, show the separate from |
| 532 | ** the previous block. |
| 533 | */ |
| 534 | nChunk++; |
| 535 | if( showLn ){ |
| 536 | if( r==0 ){ |
| 537 | /* Do not show a top divider */ |
| 538 | }else if( html ){ |
| 539 | blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.'); |
| 540 | blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk); |
| 541 | }else{ |
| 542 | blob_appendf(pOut, "%.80c\n", '.'); |
| @@ -559,34 +611,36 @@ | |
| 559 | a += skip; |
| 560 | b += skip; |
| 561 | m = R[r] - skip; |
| 562 | for(j=0; j<m; j++){ |
| 563 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); |
| 564 | appendDiffLine(pOut, ' ', &A[a+j], html); |
| 565 | } |
| 566 | a += m; |
| 567 | b += m; |
| 568 | |
| 569 | /* Show the differences */ |
| 570 | for(i=0; i<nr; i++){ |
| 571 | m = R[r+i*3+1]; |
| 572 | for(j=0; j<m; j++){ |
| 573 | if( showLn ) appendDiffLineno(pOut, a+j+1, 0, html); |
| 574 | appendDiffLine(pOut, '-', &A[a+j], html); |
| 575 | } |
| 576 | a += m; |
| 577 | m = R[r+i*3+2]; |
| 578 | for(j=0; j<m; j++){ |
| 579 | if( showLn ) appendDiffLineno(pOut, 0, b+j+1, html); |
| 580 | appendDiffLine(pOut, '+', &B[b+j], html); |
| 581 | } |
| 582 | b += m; |
| 583 | if( i<nr-1 ){ |
| 584 | m = R[r+i*3+3]; |
| 585 | for(j=0; j<m; j++){ |
| 586 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); |
| 587 | appendDiffLine(pOut, ' ', &B[b+j], html); |
| 588 | } |
| 589 | b += m; |
| 590 | a += m; |
| 591 | } |
| 592 | } |
| @@ -595,11 +649,11 @@ | |
| 595 | assert( nr==i ); |
| 596 | m = R[r+nr*3]; |
| 597 | if( m>nContext ) m = nContext; |
| 598 | for(j=0; j<m; j++){ |
| 599 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); |
| 600 | appendDiffLine(pOut, ' ', &B[b+j], html); |
| 601 | } |
| 602 | } |
| 603 | } |
| 604 | |
| 605 | /* |
| @@ -615,10 +669,11 @@ | |
| 615 | const char *zStart; /* A <span> tag */ |
| 616 | int iEnd; /* Write </span> prior to character iEnd */ |
| 617 | int iStart2; /* Write zStart2 prior to character iStart2 */ |
| 618 | const char *zStart2; /* A <span> tag */ |
| 619 | int iEnd2; /* Write </span> prior to character iEnd2 */ |
| 620 | }; |
| 621 | |
| 622 | /* |
| 623 | ** Flags for sbsWriteText() |
| 624 | */ |
| @@ -640,13 +695,17 @@ | |
| 640 | int k; /* Cursor position */ |
| 641 | int needEndSpan = 0; |
| 642 | const char *zIn = pLine->z; |
| 643 | char *z = &p->zLine[p->n]; |
| 644 | int w = p->width; |
| 645 | for(i=j=k=0; k<w && i<n; i++, k++){ |
| 646 | char c = zIn[i]; |
| 647 | if( p->escHtml ){ |
| 648 | if( i==p->iStart ){ |
| 649 | int x = strlen(p->zStart); |
| 650 | memcpy(z+j, p->zStart, x); |
| 651 | j += x; |
| 652 | needEndSpan = 1; |
| @@ -797,10 +856,41 @@ | |
| 797 | } |
| 798 | } |
| 799 | } |
| 800 | return rc; |
| 801 | } |
| 802 | |
| 803 | /* |
| 804 | ** Write out lines that have been edited. Adjust the highlight to cover |
| 805 | ** only those parts of the line that actually changed. |
| 806 | */ |
| @@ -891,41 +981,35 @@ | |
| 891 | && textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS) |
| 892 | ){ |
| 893 | sbsWriteLineno(p, lnLeft); |
| 894 | p->iStart = nPrefix; |
| 895 | p->iEnd = nPrefix + aLCS[0]; |
| 896 | p->zStart = aLCS[2]==0 ? zClassRm : zClassChng; |
| 897 | p->iStart2 = nPrefix + aLCS[1]; |
| 898 | p->iEnd2 = nLeft - nSuffix; |
| 899 | p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng; |
| 900 | if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0; |
| 901 | if( p->iStart==p->iEnd ){ |
| 902 | p->iStart = p->iStart2; |
| 903 | p->iEnd = p->iEnd2; |
| 904 | p->zStart = p->zStart2; |
| 905 | p->iStart2 = 0; |
| 906 | p->iEnd2 = 0; |
| 907 | } |
| 908 | if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1; |
| 909 | sbsWriteText(p, pLeft, SBS_PAD); |
| 910 | sbsWrite(p, " | ", 3); |
| 911 | sbsWriteLineno(p, lnRight); |
| 912 | p->iStart = nPrefix; |
| 913 | p->iEnd = nPrefix + aLCS[2]; |
| 914 | p->zStart = aLCS[0]==0 ? zClassAdd : zClassChng; |
| 915 | p->iStart2 = nPrefix + aLCS[3]; |
| 916 | p->iEnd2 = nRight - nSuffix; |
| 917 | p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng; |
| 918 | if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0; |
| 919 | if( p->iStart==p->iEnd ){ |
| 920 | p->iStart = p->iStart2; |
| 921 | p->iEnd = p->iEnd2; |
| 922 | p->zStart = p->zStart2; |
| 923 | p->iStart2 = 0; |
| 924 | p->iEnd2 = 0; |
| 925 | } |
| 926 | if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1; |
| 927 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 928 | return; |
| 929 | } |
| 930 | |
| 931 | /* If all else fails, show a single big change between left and right */ |
| @@ -1018,13 +1102,16 @@ | |
| 1018 | ** |
| 1019 | ** The return value is a buffer of unsigned characters, obtained from |
| 1020 | ** fossil_malloc(). (The caller needs to free the return value using |
| 1021 | ** fossil_free().) Entries in the returned array have values as follows: |
| 1022 | ** |
| 1023 | ** 1. Delete the next line of pLeft. |
| 1024 | ** 2. The next line of pLeft changes into the next line of pRight. |
| 1025 | ** 3. Insert the next line of pRight. |
| 1026 | ** |
| 1027 | ** The length of the returned array will be just large enough to cause |
| 1028 | ** all elements of pLeft and pRight to be consumed. |
| 1029 | ** |
| 1030 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by |
| @@ -1039,27 +1126,32 @@ | |
| 1039 | ){ |
| 1040 | int i, j, k; /* Loop counters */ |
| 1041 | int *a; /* One row of the Wagner matrix */ |
| 1042 | int *pToFree; /* Space that needs to be freed */ |
| 1043 | unsigned char *aM; /* Wagner result matrix */ |
| 1044 | int aBuf[100]; /* Stack space for a[] if nRight not to big */ |
| 1045 | |
| 1046 | aM = fossil_malloc( (nLeft+1)*(nRight+1) ); |
| 1047 | if( nLeft==0 ){ |
| 1048 | memset(aM, 3, nRight); |
| 1049 | return aM; |
| 1050 | } |
| 1051 | if( nRight==0 ){ |
| 1052 | memset(aM, 1, nLeft); |
| 1053 | return aM; |
| 1054 | } |
| 1055 | |
| 1056 | /* This algorithm is O(N**2). So if N is too big, bail out with a |
| 1057 | ** simple (but stupid and ugly) result that doesn't take too long. */ |
| 1058 | if( nLeft*nRight>100000 ){ |
| 1059 | memset(aM, 3, nRight); |
| 1060 | memset(aM+nRight, 1, nLeft); |
| 1061 | return aM; |
| 1062 | } |
| 1063 | |
| 1064 | if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){ |
| 1065 | pToFree = 0; |
| @@ -1068,30 +1160,30 @@ | |
| 1068 | a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) ); |
| 1069 | } |
| 1070 | |
| 1071 | /* Compute the best alignment */ |
| 1072 | for(i=0; i<=nRight; i++){ |
| 1073 | aM[i] = 3; |
| 1074 | a[i] = i*50; |
| 1075 | } |
| 1076 | aM[0] = 0; |
| 1077 | for(j=1; j<=nLeft; j++){ |
| 1078 | int p = a[0]; |
| 1079 | a[0] = p+50; |
| 1080 | aM[j*(nRight+1)] = 1; |
| 1081 | for(i=1; i<=nRight; i++){ |
| 1082 | int m = a[i-1]+50; |
| 1083 | int d = 3; |
| 1084 | if( m>a[i]+50 ){ |
| 1085 | m = a[i]+50; |
| 1086 | d = 1; |
| 1087 | } |
| 1088 | if( m>p ){ |
| 1089 | int score = match_dline(&aLeft[j-1], &aRight[i-1]); |
| 1090 | if( (score<66 || (i<j+1 && i>j-1)) && m>p+score ){ |
| 1091 | m = p+score; |
| 1092 | d = 2; |
| 1093 | } |
| 1094 | } |
| 1095 | p = a[i]; |
| 1096 | a[i] = m; |
| 1097 | aM[j*(nRight+1)+i] = d; |
| @@ -1100,28 +1192,50 @@ | |
| 1100 | |
| 1101 | /* Compute the lowest-cost path back through the matrix */ |
| 1102 | i = nRight; |
| 1103 | j = nLeft; |
| 1104 | k = (nRight+1)*(nLeft+1)-1; |
| 1105 | while( i+j>0 ){ |
| 1106 | unsigned char c = aM[k--]; |
| 1107 | if( c==2 ){ |
| 1108 | assert( i>0 && j>0 ); |
| 1109 | i--; |
| 1110 | j--; |
| 1111 | }else if( c==3 ){ |
| 1112 | assert( i>0 ); |
| 1113 | i--; |
| 1114 | }else{ |
| 1115 | assert( j>0 ); |
| 1116 | j--; |
| 1117 | } |
| 1118 | aM[k] = aM[j*(nRight+1)+i]; |
| 1119 | } |
| 1120 | k++; |
| 1121 | i = (nRight+1)*(nLeft+1) - k; |
| 1122 | memmove(aM, &aM[k], i); |
| 1123 | |
| 1124 | /* Return the result */ |
| 1125 | fossil_free(pToFree); |
| 1126 | return aM; |
| 1127 | } |
| @@ -1141,13 +1255,12 @@ | |
| 1141 | ** in, compute a side-by-side diff into pOut. |
| 1142 | */ |
| 1143 | static void sbsDiff( |
| 1144 | DContext *p, /* The computed diff */ |
| 1145 | Blob *pOut, /* Write the results here */ |
| 1146 | int nContext, /* Number of lines of context around each change */ |
| 1147 | int width, /* Width of each column of output */ |
| 1148 | int escHtml /* True to generate HTML output */ |
| 1149 | ){ |
| 1150 | DLine *A; /* Left side of the diff */ |
| 1151 | DLine *B; /* Right side of the diff */ |
| 1152 | int a = 0; /* Index of next line in A[] */ |
| 1153 | int b = 0; /* Index of next line in B[] */ |
| @@ -1159,16 +1272,20 @@ | |
| 1159 | int i, j; /* Loop counters */ |
| 1160 | int m, ma, mb;/* Number of lines to output */ |
| 1161 | int skip; /* Number of lines to skip */ |
| 1162 | int nChunk = 0; /* Number of chunks of diff output seen so far */ |
| 1163 | SbsLine s; /* Output line buffer */ |
| 1164 | |
| 1165 | memset(&s, 0, sizeof(s)); |
| 1166 | s.zLine = fossil_malloc( 15*width + 200 ); |
| 1167 | if( s.zLine==0 ) return; |
| 1168 | s.width = width; |
| 1169 | s.escHtml = escHtml; |
| 1170 | s.iStart = -1; |
| 1171 | s.iStart2 = 0; |
| 1172 | s.iEnd = -1; |
| 1173 | A = p->aFrom; |
| 1174 | B = p->aTo; |
| @@ -1177,10 +1294,35 @@ | |
| 1177 | while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } |
| 1178 | for(r=0; r<mxr; r += 3*nr){ |
| 1179 | /* Figure out how many triples to show in a single block */ |
| 1180 | for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} |
| 1181 | /* printf("r=%d nr=%d\n", r, nr); */ |
| 1182 | |
| 1183 | /* For the current block comprising nr triples, figure out |
| 1184 | ** how many lines of A and B are to be displayed |
| 1185 | */ |
| 1186 | if( R[r]>nContext ){ |
| @@ -1205,20 +1347,21 @@ | |
| 1205 | na += R[r+i*3]; |
| 1206 | nb += R[r+i*3]; |
| 1207 | } |
| 1208 | |
| 1209 | /* Draw the separator between blocks */ |
| 1210 | if( r>0 ){ |
| 1211 | if( escHtml ){ |
| 1212 | blob_appendf(pOut, "<span class=\"diffhr\">%.*c</span>\n", |
| 1213 | width*2+16, '.'); |
| 1214 | }else{ |
| 1215 | blob_appendf(pOut, "%.*c\n", width*2+16, '.'); |
| 1216 | } |
| 1217 | } |
| 1218 | nChunk++; |
| 1219 | if( escHtml ){ |
| 1220 | blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk); |
| 1221 | } |
| 1222 | |
| 1223 | /* Show the initial common area */ |
| 1224 | a += skip; |
| @@ -1254,38 +1397,41 @@ | |
| 1254 | } |
| 1255 | |
| 1256 | alignment = sbsAlignment(&A[a], ma, &B[b], mb); |
| 1257 | for(j=0; ma+mb>0; j++){ |
| 1258 | if( alignment[j]==1 ){ |
| 1259 | s.n = 0; |
| 1260 | sbsWriteLineno(&s, a); |
| 1261 | s.iStart = 0; |
| 1262 | s.zStart = "<span class=\"diffrm\">"; |
| 1263 | s.iEnd = s.width; |
| 1264 | sbsWriteText(&s, &A[a], SBS_PAD); |
| 1265 | if( escHtml ){ |
| 1266 | sbsWrite(&s, " <\n", 6); |
| 1267 | }else{ |
| 1268 | sbsWrite(&s, " <\n", 3); |
| 1269 | } |
| 1270 | blob_append(pOut, s.zLine, s.n); |
| 1271 | assert( ma>0 ); |
| 1272 | ma--; |
| 1273 | a++; |
| 1274 | }else if( alignment[j]==2 ){ |
| 1275 | s.n = 0; |
| 1276 | sbsWriteLineChange(&s, &A[a], a, &B[b], b); |
| 1277 | blob_append(pOut, s.zLine, s.n); |
| 1278 | assert( ma>0 && mb>0 ); |
| 1279 | ma--; |
| 1280 | mb--; |
| 1281 | a++; |
| 1282 | b++; |
| 1283 | }else{ |
| 1284 | s.n = 0; |
| 1285 | sbsWriteSpace(&s, width + 7); |
| 1286 | if( escHtml ){ |
| 1287 | sbsWrite(&s, " > ", 6); |
| 1288 | }else{ |
| 1289 | sbsWrite(&s, " > ", 3); |
| 1290 | } |
| 1291 | sbsWriteLineno(&s, b); |
| @@ -1295,11 +1441,31 @@ | |
| 1295 | sbsWriteText(&s, &B[b], SBS_NEWLINE); |
| 1296 | blob_append(pOut, s.zLine, s.n); |
| 1297 | assert( mb>0 ); |
| 1298 | mb--; |
| 1299 | b++; |
| 1300 | } |
| 1301 | } |
| 1302 | fossil_free(alignment); |
| 1303 | if( i<nr-1 ){ |
| 1304 | m = R[r+i*3+3]; |
| 1305 | for(j=0; j<m; j++){ |
| @@ -1723,11 +1889,11 @@ | |
| 1723 | ** Extract the number of lines of context from diffFlags. Supply an |
| 1724 | ** appropriate default if no context width is specified. |
| 1725 | */ |
| 1726 | int diff_context_lines(u64 diffFlags){ |
| 1727 | int n = diffFlags & DIFF_CONTEXT_MASK; |
| 1728 | if( n==0 ) n = 5; |
| 1729 | return n; |
| 1730 | } |
| 1731 | |
| 1732 | /* |
| 1733 | ** Extract the width of columns for side-by-side diff. Supply an |
| @@ -1755,22 +1921,21 @@ | |
| 1755 | */ |
| 1756 | int *text_diff( |
| 1757 | Blob *pA_Blob, /* FROM file */ |
| 1758 | Blob *pB_Blob, /* TO file */ |
| 1759 | Blob *pOut, /* Write diff here if not NULL */ |
| 1760 | u64 diffFlags /* DIFF_* flags defined above */ |
| 1761 | ){ |
| 1762 | int ignoreEolWs; /* Ignore whitespace at the end of lines */ |
| 1763 | int nContext; /* Amount of context to display */ |
| 1764 | DContext c; |
| 1765 | |
| 1766 | if( diffFlags & DIFF_INVERT ){ |
| 1767 | Blob *pTemp = pA_Blob; |
| 1768 | pA_Blob = pB_Blob; |
| 1769 | pB_Blob = pTemp; |
| 1770 | } |
| 1771 | nContext = diff_context_lines(diffFlags); |
| 1772 | ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0; |
| 1773 | |
| 1774 | /* Prepare the input files */ |
| 1775 | memset(&c, 0, sizeof(c)); |
| 1776 | c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob), |
| @@ -1790,17 +1955,14 @@ | |
| 1790 | diff_all(&c); |
| 1791 | if( (diffFlags & DIFF_NOOPT)==0 ) diff_optimize(&c); |
| 1792 | |
| 1793 | if( pOut ){ |
| 1794 | /* Compute a context or side-by-side diff into pOut */ |
| 1795 | int escHtml = (diffFlags & DIFF_HTML)!=0; |
| 1796 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 1797 | int width = diff_width(diffFlags); |
| 1798 | sbsDiff(&c, pOut, nContext, width, escHtml); |
| 1799 | }else{ |
| 1800 | int showLn = (diffFlags & DIFF_LINENO)!=0; |
| 1801 | contextDiff(&c, pOut, nContext, showLn, escHtml); |
| 1802 | } |
| 1803 | fossil_free(c.aFrom); |
| 1804 | fossil_free(c.aTo); |
| 1805 | fossil_free(c.aEdit); |
| 1806 | return 0; |
| @@ -1826,19 +1988,19 @@ | |
| 1826 | ** --noopt Disable optimization DIFF_NOOPT |
| 1827 | ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE |
| 1828 | ** --unified Unified diff. ~DIFF_SIDEBYSIDE |
| 1829 | ** --width|-W N N character lines. DIFF_WIDTH_MASK |
| 1830 | */ |
| 1831 | int diff_options(void){ |
| 1832 | u64 diffFlags = 0; |
| 1833 | const char *z; |
| 1834 | int f; |
| 1835 | if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 1836 | if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE; |
| 1837 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){ |
| 1838 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 1839 | diffFlags |= f; |
| 1840 | } |
| 1841 | if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ |
| 1842 | f *= DIFF_CONTEXT_MASK+1; |
| 1843 | if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; |
| 1844 | diffFlags |= f; |
| @@ -1863,34 +2025,52 @@ | |
| 1863 | if( g.argc<4 ) usage("FILE1 FILE2 ..."); |
| 1864 | blob_read_from_file(&a, g.argv[2]); |
| 1865 | for(i=3; i<g.argc; i++){ |
| 1866 | if( i>3 ) fossil_print("-------------------------------\n"); |
| 1867 | blob_read_from_file(&b, g.argv[i]); |
| 1868 | R = text_diff(&a, &b, 0, diffFlags); |
| 1869 | for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){ |
| 1870 | fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]); |
| 1871 | } |
| 1872 | /* free(R); */ |
| 1873 | blob_reset(&b); |
| 1874 | } |
| 1875 | } |
| 1876 | |
| 1877 | /* |
| 1878 | ** COMMAND: test-udiff |
| 1879 | ** |
| 1880 | ** Print the difference between two files. The usual diff options apply. |
| 1881 | */ |
| 1882 | void test_udiff_cmd(void){ |
| 1883 | Blob a, b, out; |
| 1884 | u64 diffFlag = diff_options(); |
| 1885 | |
| 1886 | if( g.argc!=4 ) usage("FILE1 FILE2"); |
| 1887 | blob_read_from_file(&a, g.argv[2]); |
| 1888 | blob_read_from_file(&b, g.argv[3]); |
| 1889 | blob_zero(&out); |
| 1890 | text_diff(&a, &b, &out, diffFlag); |
| 1891 | blob_write_to_file(&out, "-"); |
| 1892 | } |
| 1893 | |
| 1894 | /************************************************************************** |
| 1895 | ** The basic difference engine is above. What follows is the annotation |
| 1896 | ** engine. Both are in the same file since they share many components. |
| 1897 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -23,11 +23,12 @@ | |
| 23 | #include <assert.h> |
| 24 | |
| 25 | |
| 26 | #if INTERFACE |
| 27 | /* |
| 28 | ** Flag parameters to the text_diff() routine used to control the formatting |
| 29 | ** of the diff output. |
| 30 | */ |
| 31 | #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */ |
| 32 | #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */ |
| 33 | #define DIFF_IGNORE_EOLWS ((u64)0x01000000) /* Ignore end-of-line whitespace */ |
| 34 | #define DIFF_SIDEBYSIDE ((u64)0x02000000) /* Generate a side-by-side diff */ |
| @@ -37,10 +38,11 @@ | |
| 38 | #define DIFF_HTML ((u64)0x10000000) /* Render for HTML */ |
| 39 | #define DIFF_LINENO ((u64)0x20000000) /* Show line numbers */ |
| 40 | #define DIFF_WS_WARNING ((u64)0x40000000) /* Warn about whitespace */ |
| 41 | #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */ |
| 42 | #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */ |
| 43 | #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */ |
| 44 | |
| 45 | /* |
| 46 | ** These error messages are shared in multiple locations. They are defined |
| 47 | ** here for consistency. |
| 48 | */ |
| @@ -52,11 +54,11 @@ | |
| 54 | |
| 55 | #define looks_like_binary(blob) (looks_like_utf8((blob)) == 0) |
| 56 | #endif /* INTERFACE */ |
| 57 | |
| 58 | /* |
| 59 | ** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes) |
| 60 | */ |
| 61 | #define LENGTH_MASK_SZ 13 |
| 62 | #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1) |
| 63 | |
| 64 | /* |
| @@ -116,10 +118,13 @@ | |
| 118 | ** more. If trailing whitespace is ignored, the "patch" command gets |
| 119 | ** confused by the diff output. Ticket [a9f7b23c2e376af5b0e5b] |
| 120 | ** |
| 121 | ** Return 0 if the file is binary or contains a line that is |
| 122 | ** too long. |
| 123 | ** |
| 124 | ** Profiling show that in most cases this routine consumes the bulk of |
| 125 | ** the CPU time on a diff. |
| 126 | */ |
| 127 | static DLine *break_into_lines(const char *z, int n, int *pnLine, int ignoreWS){ |
| 128 | int nLine, i, j, k, x; |
| 129 | unsigned int h, h2; |
| 130 | DLine *a; |
| @@ -407,34 +412,50 @@ | |
| 412 | ** Return true if two DLine elements are identical. |
| 413 | */ |
| 414 | static int same_dline(DLine *pA, DLine *pB){ |
| 415 | return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0; |
| 416 | } |
| 417 | |
| 418 | /* |
| 419 | ** Return true if the regular expression *pRe matches any of the |
| 420 | ** N dlines |
| 421 | */ |
| 422 | static int re_dline_match( |
| 423 | ReCompiled *pRe, /* The regular expression to be matched */ |
| 424 | DLine *aDLine, /* First of N DLines to compare against */ |
| 425 | int N /* Number of DLines to check */ |
| 426 | ){ |
| 427 | while( N-- ){ |
| 428 | if( re_match(pRe, (const unsigned char *)aDLine->z, LENGTH(aDLine)) ){ |
| 429 | return 1; |
| 430 | } |
| 431 | aDLine++; |
| 432 | } |
| 433 | return 0; |
| 434 | } |
| 435 | |
| 436 | /* |
| 437 | ** Append a single line of context-diff output to pOut. |
| 438 | */ |
| 439 | static void appendDiffLine( |
| 440 | Blob *pOut, /* Where to write the line of output */ |
| 441 | char cPrefix, /* One of " ", "+", or "-" */ |
| 442 | DLine *pLine, /* The line to be output */ |
| 443 | int html, /* True if generating HTML. False for plain text */ |
| 444 | ReCompiled *pRe /* Colorize only if line matches this Regex */ |
| 445 | ){ |
| 446 | blob_append(pOut, &cPrefix, 1); |
| 447 | if( html ){ |
| 448 | char *zHtml; |
| 449 | if( pRe && re_dline_match(pRe, pLine, 1)==0 ){ |
| 450 | cPrefix = ' '; |
| 451 | }else if( cPrefix=='+' ){ |
| 452 | blob_append(pOut, "<span class=\"diffadd\">", -1); |
| 453 | }else if( cPrefix=='-' ){ |
| 454 | blob_append(pOut, "<span class=\"diffrm\">", -1); |
| 455 | } |
| 456 | zHtml = htmlize(pLine->z, (pLine->h & LENGTH_MASK)); |
| 457 | blob_append(pOut, zHtml, -1); |
| 458 | fossil_free(zHtml); |
| 459 | if( cPrefix!=' ' ){ |
| 460 | blob_append(pOut, "</span>", -1); |
| 461 | } |
| @@ -444,11 +465,11 @@ | |
| 465 | blob_append(pOut, "\n", 1); |
| 466 | } |
| 467 | |
| 468 | /* |
| 469 | ** Add two line numbers to the beginning of an output line for a context |
| 470 | ** diff. One or the other of the two numbers might be zero, which means |
| 471 | ** to leave that number field blank. The "html" parameter means to format |
| 472 | ** the output for HTML. |
| 473 | */ |
| 474 | static void appendDiffLineno(Blob *pOut, int lnA, int lnB, int html){ |
| 475 | if( html ) blob_append(pOut, "<span class=\"diffln\">", -1); |
| @@ -463,21 +484,19 @@ | |
| 484 | blob_append(pOut, " ", 8); |
| 485 | } |
| 486 | if( html ) blob_append(pOut, "</span>", -1); |
| 487 | } |
| 488 | |
| 489 | /* |
| 490 | ** Given a raw diff p[] in which the p->aEdit[] array has been filled |
| 491 | ** in, compute a context diff into pOut. |
| 492 | */ |
| 493 | static void contextDiff( |
| 494 | DContext *p, /* The difference */ |
| 495 | Blob *pOut, /* Output a context diff to here */ |
| 496 | ReCompiled *pRe, /* Only show changes that match this regex */ |
| 497 | u64 diffFlags /* Flags controlling the diff format */ |
| 498 | ){ |
| 499 | DLine *A; /* Left side of the diff */ |
| 500 | DLine *B; /* Right side of the diff */ |
| 501 | int a = 0; /* Index of next line in A[] */ |
| 502 | int b = 0; /* Index of next line in B[] */ |
| @@ -488,11 +507,18 @@ | |
| 507 | int na, nb; /* Number of lines shown from A and B */ |
| 508 | int i, j; /* Loop counters */ |
| 509 | int m; /* Number of lines to output */ |
| 510 | int skip; /* Number of lines to skip */ |
| 511 | int nChunk = 0; /* Number of diff chunks seen so far */ |
| 512 | int nContext; /* Number of lines of context */ |
| 513 | int showLn; /* Show line numbers */ |
| 514 | int html; /* Render as HTML */ |
| 515 | int showDivider = 0; /* True to show the divider between diff blocks */ |
| 516 | |
| 517 | nContext = diff_context_lines(diffFlags); |
| 518 | showLn = (diffFlags & DIFF_LINENO)!=0; |
| 519 | html = (diffFlags & DIFF_HTML)!=0; |
| 520 | A = p->aFrom; |
| 521 | B = p->aTo; |
| 522 | R = p->aEdit; |
| 523 | mxr = p->nEdit; |
| 524 | while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } |
| @@ -499,10 +525,35 @@ | |
| 525 | for(r=0; r<mxr; r += 3*nr){ |
| 526 | /* Figure out how many triples to show in a single block */ |
| 527 | for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} |
| 528 | /* printf("r=%d nr=%d\n", r, nr); */ |
| 529 | |
| 530 | /* If there is a regex, skip this block (generate no diff output) |
| 531 | ** if the regex matches or does not match both insert and delete. |
| 532 | ** Only display the block if one side matches but the other side does |
| 533 | ** not. |
| 534 | */ |
| 535 | if( pRe ){ |
| 536 | int hideBlock = 1; |
| 537 | int xa = a, xb = b; |
| 538 | for(i=0; hideBlock && i<nr; i++){ |
| 539 | int c1, c2; |
| 540 | xa += R[r+i*3]; |
| 541 | xb += R[r+i*3]; |
| 542 | c1 = re_dline_match(pRe, &A[xa], R[r+i*3+1]); |
| 543 | c2 = re_dline_match(pRe, &B[xb], R[r+i*3+2]); |
| 544 | hideBlock = c1==c2; |
| 545 | xa += R[r+i*3+1]; |
| 546 | xb += R[r+i*3+2]; |
| 547 | } |
| 548 | if( hideBlock ){ |
| 549 | a = xa; |
| 550 | b = xb; |
| 551 | continue; |
| 552 | } |
| 553 | } |
| 554 | |
| 555 | /* For the current block comprising nr triples, figure out |
| 556 | ** how many lines of A and B are to be displayed |
| 557 | */ |
| 558 | if( R[r]>nContext ){ |
| 559 | na = nb = nContext; |
| @@ -526,17 +577,18 @@ | |
| 577 | na += R[r+i*3]; |
| 578 | nb += R[r+i*3]; |
| 579 | } |
| 580 | |
| 581 | /* Show the header for this block, or if we are doing a modified |
| 582 | ** context diff that contains line numbers, show the separator from |
| 583 | ** the previous block. |
| 584 | */ |
| 585 | nChunk++; |
| 586 | if( showLn ){ |
| 587 | if( !showDivider ){ |
| 588 | /* Do not show a top divider */ |
| 589 | showDivider = 1; |
| 590 | }else if( html ){ |
| 591 | blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.'); |
| 592 | blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk); |
| 593 | }else{ |
| 594 | blob_appendf(pOut, "%.80c\n", '.'); |
| @@ -559,34 +611,36 @@ | |
| 611 | a += skip; |
| 612 | b += skip; |
| 613 | m = R[r] - skip; |
| 614 | for(j=0; j<m; j++){ |
| 615 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); |
| 616 | appendDiffLine(pOut, ' ', &A[a+j], html, 0); |
| 617 | } |
| 618 | a += m; |
| 619 | b += m; |
| 620 | |
| 621 | /* Show the differences */ |
| 622 | for(i=0; i<nr; i++){ |
| 623 | m = R[r+i*3+1]; |
| 624 | for(j=0; j<m; j++){ |
| 625 | char cMark = '-'; |
| 626 | if( showLn ) appendDiffLineno(pOut, a+j+1, 0, html); |
| 627 | if( pRe && re_dline_match(pRe, &A[a+j], 1)==0 ) cMark = ' '; |
| 628 | appendDiffLine(pOut, '-', &A[a+j], html, pRe); |
| 629 | } |
| 630 | a += m; |
| 631 | m = R[r+i*3+2]; |
| 632 | for(j=0; j<m; j++){ |
| 633 | if( showLn ) appendDiffLineno(pOut, 0, b+j+1, html); |
| 634 | appendDiffLine(pOut, '+', &B[b+j], html, pRe); |
| 635 | } |
| 636 | b += m; |
| 637 | if( i<nr-1 ){ |
| 638 | m = R[r+i*3+3]; |
| 639 | for(j=0; j<m; j++){ |
| 640 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); |
| 641 | appendDiffLine(pOut, ' ', &B[b+j], html, 0); |
| 642 | } |
| 643 | b += m; |
| 644 | a += m; |
| 645 | } |
| 646 | } |
| @@ -595,11 +649,11 @@ | |
| 649 | assert( nr==i ); |
| 650 | m = R[r+nr*3]; |
| 651 | if( m>nContext ) m = nContext; |
| 652 | for(j=0; j<m; j++){ |
| 653 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); |
| 654 | appendDiffLine(pOut, ' ', &B[b+j], html, 0); |
| 655 | } |
| 656 | } |
| 657 | } |
| 658 | |
| 659 | /* |
| @@ -615,10 +669,11 @@ | |
| 669 | const char *zStart; /* A <span> tag */ |
| 670 | int iEnd; /* Write </span> prior to character iEnd */ |
| 671 | int iStart2; /* Write zStart2 prior to character iStart2 */ |
| 672 | const char *zStart2; /* A <span> tag */ |
| 673 | int iEnd2; /* Write </span> prior to character iEnd2 */ |
| 674 | ReCompiled *pRe; /* Only colorize matching lines, if not NULL */ |
| 675 | }; |
| 676 | |
| 677 | /* |
| 678 | ** Flags for sbsWriteText() |
| 679 | */ |
| @@ -640,13 +695,17 @@ | |
| 695 | int k; /* Cursor position */ |
| 696 | int needEndSpan = 0; |
| 697 | const char *zIn = pLine->z; |
| 698 | char *z = &p->zLine[p->n]; |
| 699 | int w = p->width; |
| 700 | int colorize = p->escHtml; |
| 701 | if( colorize && p->pRe && re_dline_match(p->pRe, pLine, 1)==0 ){ |
| 702 | colorize = 0; |
| 703 | } |
| 704 | for(i=j=k=0; k<w && i<n; i++, k++){ |
| 705 | char c = zIn[i]; |
| 706 | if( colorize ){ |
| 707 | if( i==p->iStart ){ |
| 708 | int x = strlen(p->zStart); |
| 709 | memcpy(z+j, p->zStart, x); |
| 710 | j += x; |
| 711 | needEndSpan = 1; |
| @@ -797,10 +856,41 @@ | |
| 856 | } |
| 857 | } |
| 858 | } |
| 859 | return rc; |
| 860 | } |
| 861 | |
| 862 | /* |
| 863 | ** Try to shift iStart as far as possible to the left. |
| 864 | */ |
| 865 | static void sbsShiftLeft(SbsLine *p, const char *z){ |
| 866 | int i, j; |
| 867 | while( (i=p->iStart)>0 && z[i-1]==z[i] ){ |
| 868 | for(j=i+1; j<p->iEnd && z[j-1]==z[j]; j++){} |
| 869 | if( j<p->iEnd ) break; |
| 870 | p->iStart--; |
| 871 | p->iEnd--; |
| 872 | } |
| 873 | } |
| 874 | |
| 875 | /* |
| 876 | ** Simplify iStart and iStart2: |
| 877 | ** |
| 878 | ** * If iStart is a null-change then move iStart2 into iStart |
| 879 | ** * Make sure any null-changes are in canonoical form. |
| 880 | */ |
| 881 | static void sbsSimplifyLine(SbsLine *p){ |
| 882 | if( p->iStart2==p->iEnd2 ) p->iStart2 = p->iEnd2 = 0; |
| 883 | if( p->iStart==p->iEnd ){ |
| 884 | p->iStart = p->iStart2; |
| 885 | p->iEnd = p->iEnd2; |
| 886 | p->zStart = p->zStart2; |
| 887 | p->iStart2 = 0; |
| 888 | p->iEnd2 = 0; |
| 889 | } |
| 890 | if( p->iStart==p->iEnd ) p->iStart = p->iEnd = -1; |
| 891 | } |
| 892 | |
| 893 | /* |
| 894 | ** Write out lines that have been edited. Adjust the highlight to cover |
| 895 | ** only those parts of the line that actually changed. |
| 896 | */ |
| @@ -891,41 +981,35 @@ | |
| 981 | && textLCS(&zLeft[nPrefix], nLeftDiff, &zRight[nPrefix], nRightDiff, aLCS) |
| 982 | ){ |
| 983 | sbsWriteLineno(p, lnLeft); |
| 984 | p->iStart = nPrefix; |
| 985 | p->iEnd = nPrefix + aLCS[0]; |
| 986 | if( aLCS[2]==0 ){ |
| 987 | sbsShiftLeft(p, pLeft->z); |
| 988 | p->zStart = zClassRm; |
| 989 | }else{ |
| 990 | p->zStart = zClassChng; |
| 991 | } |
| 992 | p->iStart2 = nPrefix + aLCS[1]; |
| 993 | p->iEnd2 = nLeft - nSuffix; |
| 994 | p->zStart2 = aLCS[3]==nRightDiff ? zClassRm : zClassChng; |
| 995 | sbsSimplifyLine(p); |
| 996 | sbsWriteText(p, pLeft, SBS_PAD); |
| 997 | sbsWrite(p, " | ", 3); |
| 998 | sbsWriteLineno(p, lnRight); |
| 999 | p->iStart = nPrefix; |
| 1000 | p->iEnd = nPrefix + aLCS[2]; |
| 1001 | if( aLCS[0]==0 ){ |
| 1002 | sbsShiftLeft(p, pRight->z); |
| 1003 | p->zStart = zClassAdd; |
| 1004 | }else{ |
| 1005 | p->zStart = zClassChng; |
| 1006 | } |
| 1007 | p->iStart2 = nPrefix + aLCS[3]; |
| 1008 | p->iEnd2 = nRight - nSuffix; |
| 1009 | p->zStart2 = aLCS[1]==nLeftDiff ? zClassAdd : zClassChng; |
| 1010 | sbsSimplifyLine(p); |
| 1011 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 1012 | return; |
| 1013 | } |
| 1014 | |
| 1015 | /* If all else fails, show a single big change between left and right */ |
| @@ -1018,13 +1102,16 @@ | |
| 1102 | ** |
| 1103 | ** The return value is a buffer of unsigned characters, obtained from |
| 1104 | ** fossil_malloc(). (The caller needs to free the return value using |
| 1105 | ** fossil_free().) Entries in the returned array have values as follows: |
| 1106 | ** |
| 1107 | ** 1. Delete the next line of pLeft. |
| 1108 | ** 2. Insert the next line of pRight. |
| 1109 | ** 3. The next line of pLeft changes into the next line of pRight. |
| 1110 | ** 4. Delete one line from pLeft and add one line to pRight. |
| 1111 | ** |
| 1112 | ** Values larger than three indicate better matches. |
| 1113 | ** |
| 1114 | ** The length of the returned array will be just large enough to cause |
| 1115 | ** all elements of pLeft and pRight to be consumed. |
| 1116 | ** |
| 1117 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by |
| @@ -1039,27 +1126,32 @@ | |
| 1126 | ){ |
| 1127 | int i, j, k; /* Loop counters */ |
| 1128 | int *a; /* One row of the Wagner matrix */ |
| 1129 | int *pToFree; /* Space that needs to be freed */ |
| 1130 | unsigned char *aM; /* Wagner result matrix */ |
| 1131 | int nMatch, iMatch; /* Number of matching lines and match score */ |
| 1132 | int mnLen; /* MIN(nLeft, nRight) */ |
| 1133 | int mxLen; /* MAX(nLeft, nRight) */ |
| 1134 | int aBuf[100]; /* Stack space for a[] if nRight not to big */ |
| 1135 | |
| 1136 | aM = fossil_malloc( (nLeft+1)*(nRight+1) ); |
| 1137 | if( nLeft==0 ){ |
| 1138 | memset(aM, 2, nRight); |
| 1139 | return aM; |
| 1140 | } |
| 1141 | if( nRight==0 ){ |
| 1142 | memset(aM, 1, nLeft); |
| 1143 | return aM; |
| 1144 | } |
| 1145 | |
| 1146 | /* This algorithm is O(N**2). So if N is too big, bail out with a |
| 1147 | ** simple (but stupid and ugly) result that doesn't take too long. */ |
| 1148 | mnLen = nLeft<nRight ? nLeft : nRight; |
| 1149 | if( nLeft*nRight>100000 ){ |
| 1150 | memset(aM, 4, mnLen); |
| 1151 | if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen); |
| 1152 | if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen); |
| 1153 | return aM; |
| 1154 | } |
| 1155 | |
| 1156 | if( nRight < (sizeof(aBuf)/sizeof(aBuf[0]))-1 ){ |
| 1157 | pToFree = 0; |
| @@ -1068,30 +1160,30 @@ | |
| 1160 | a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) ); |
| 1161 | } |
| 1162 | |
| 1163 | /* Compute the best alignment */ |
| 1164 | for(i=0; i<=nRight; i++){ |
| 1165 | aM[i] = 2; |
| 1166 | a[i] = i*50; |
| 1167 | } |
| 1168 | aM[0] = 0; |
| 1169 | for(j=1; j<=nLeft; j++){ |
| 1170 | int p = a[0]; |
| 1171 | a[0] = p+50; |
| 1172 | aM[j*(nRight+1)] = 1; |
| 1173 | for(i=1; i<=nRight; i++){ |
| 1174 | int m = a[i-1]+50; |
| 1175 | int d = 2; |
| 1176 | if( m>a[i]+50 ){ |
| 1177 | m = a[i]+50; |
| 1178 | d = 1; |
| 1179 | } |
| 1180 | if( m>p ){ |
| 1181 | int score = match_dline(&aLeft[j-1], &aRight[i-1]); |
| 1182 | if( (score<=63 || (i<j+1 && i>j-1)) && m>p+score ){ |
| 1183 | m = p+score; |
| 1184 | d = 3 | score*4; |
| 1185 | } |
| 1186 | } |
| 1187 | p = a[i]; |
| 1188 | a[i] = m; |
| 1189 | aM[j*(nRight+1)+i] = d; |
| @@ -1100,28 +1192,50 @@ | |
| 1192 | |
| 1193 | /* Compute the lowest-cost path back through the matrix */ |
| 1194 | i = nRight; |
| 1195 | j = nLeft; |
| 1196 | k = (nRight+1)*(nLeft+1)-1; |
| 1197 | nMatch = iMatch = 0; |
| 1198 | while( i+j>0 ){ |
| 1199 | unsigned char c = aM[k]; |
| 1200 | if( c>=3 ){ |
| 1201 | assert( i>0 && j>0 ); |
| 1202 | i--; |
| 1203 | j--; |
| 1204 | nMatch++; |
| 1205 | iMatch += (c>>2); |
| 1206 | aM[k] = 3; |
| 1207 | }else if( c==2 ){ |
| 1208 | assert( i>0 ); |
| 1209 | i--; |
| 1210 | }else{ |
| 1211 | assert( j>0 ); |
| 1212 | j--; |
| 1213 | } |
| 1214 | k--; |
| 1215 | aM[k] = aM[j*(nRight+1)+i]; |
| 1216 | } |
| 1217 | k++; |
| 1218 | i = (nRight+1)*(nLeft+1) - k; |
| 1219 | memmove(aM, &aM[k], i); |
| 1220 | |
| 1221 | /* If: |
| 1222 | ** (1) the alignment is more than 25% longer than the longest side, and |
| 1223 | ** (2) the average match cost exceeds 15 |
| 1224 | ** Then this is probably an alignment that will be difficult for humans |
| 1225 | ** to read. So instead, just show all of the right side inserted followed |
| 1226 | ** by all of the left side deleted. |
| 1227 | ** |
| 1228 | ** The coefficients for conditions (1) and (2) above are determined by |
| 1229 | ** experimentation. |
| 1230 | */ |
| 1231 | mxLen = nLeft>nRight ? nLeft : nRight; |
| 1232 | if( i*4>mxLen*5 && (nMatch==0 || iMatch/nMatch>15) ){ |
| 1233 | memset(aM, 4, mnLen); |
| 1234 | if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen); |
| 1235 | if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen); |
| 1236 | } |
| 1237 | |
| 1238 | /* Return the result */ |
| 1239 | fossil_free(pToFree); |
| 1240 | return aM; |
| 1241 | } |
| @@ -1141,13 +1255,12 @@ | |
| 1255 | ** in, compute a side-by-side diff into pOut. |
| 1256 | */ |
| 1257 | static void sbsDiff( |
| 1258 | DContext *p, /* The computed diff */ |
| 1259 | Blob *pOut, /* Write the results here */ |
| 1260 | ReCompiled *pRe, /* Only show changes that match this regex */ |
| 1261 | u64 diffFlags /* Flags controlling the diff */ |
| 1262 | ){ |
| 1263 | DLine *A; /* Left side of the diff */ |
| 1264 | DLine *B; /* Right side of the diff */ |
| 1265 | int a = 0; /* Index of next line in A[] */ |
| 1266 | int b = 0; /* Index of next line in B[] */ |
| @@ -1159,16 +1272,20 @@ | |
| 1272 | int i, j; /* Loop counters */ |
| 1273 | int m, ma, mb;/* Number of lines to output */ |
| 1274 | int skip; /* Number of lines to skip */ |
| 1275 | int nChunk = 0; /* Number of chunks of diff output seen so far */ |
| 1276 | SbsLine s; /* Output line buffer */ |
| 1277 | int nContext; /* Lines of context above and below each change */ |
| 1278 | int showDivider = 0; /* True to show the divider */ |
| 1279 | |
| 1280 | memset(&s, 0, sizeof(s)); |
| 1281 | s.width = diff_width(diffFlags); |
| 1282 | s.zLine = fossil_malloc( 15*s.width + 200 ); |
| 1283 | if( s.zLine==0 ) return; |
| 1284 | nContext = diff_context_lines(diffFlags); |
| 1285 | s.escHtml = (diffFlags & DIFF_HTML)!=0; |
| 1286 | s.pRe = pRe; |
| 1287 | s.iStart = -1; |
| 1288 | s.iStart2 = 0; |
| 1289 | s.iEnd = -1; |
| 1290 | A = p->aFrom; |
| 1291 | B = p->aTo; |
| @@ -1177,10 +1294,35 @@ | |
| 1294 | while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } |
| 1295 | for(r=0; r<mxr; r += 3*nr){ |
| 1296 | /* Figure out how many triples to show in a single block */ |
| 1297 | for(nr=1; R[r+nr*3]>0 && R[r+nr*3]<nContext*2; nr++){} |
| 1298 | /* printf("r=%d nr=%d\n", r, nr); */ |
| 1299 | |
| 1300 | /* If there is a regex, skip this block (generate no diff output) |
| 1301 | ** if the regex matches or does not match both insert and delete. |
| 1302 | ** Only display the block if one side matches but the other side does |
| 1303 | ** not. |
| 1304 | */ |
| 1305 | if( pRe ){ |
| 1306 | int hideBlock = 1; |
| 1307 | int xa = a, xb = b; |
| 1308 | for(i=0; hideBlock && i<nr; i++){ |
| 1309 | int c1, c2; |
| 1310 | xa += R[r+i*3]; |
| 1311 | xb += R[r+i*3]; |
| 1312 | c1 = re_dline_match(pRe, &A[xa], R[r+i*3+1]); |
| 1313 | c2 = re_dline_match(pRe, &B[xb], R[r+i*3+2]); |
| 1314 | hideBlock = c1==c2; |
| 1315 | xa += R[r+i*3+1]; |
| 1316 | xb += R[r+i*3+2]; |
| 1317 | } |
| 1318 | if( hideBlock ){ |
| 1319 | a = xa; |
| 1320 | b = xb; |
| 1321 | continue; |
| 1322 | } |
| 1323 | } |
| 1324 | |
| 1325 | /* For the current block comprising nr triples, figure out |
| 1326 | ** how many lines of A and B are to be displayed |
| 1327 | */ |
| 1328 | if( R[r]>nContext ){ |
| @@ -1205,20 +1347,21 @@ | |
| 1347 | na += R[r+i*3]; |
| 1348 | nb += R[r+i*3]; |
| 1349 | } |
| 1350 | |
| 1351 | /* Draw the separator between blocks */ |
| 1352 | if( showDivider ){ |
| 1353 | if( s.escHtml ){ |
| 1354 | blob_appendf(pOut, "<span class=\"diffhr\">%.*c</span>\n", |
| 1355 | s.width*2+16, '.'); |
| 1356 | }else{ |
| 1357 | blob_appendf(pOut, "%.*c\n", s.width*2+16, '.'); |
| 1358 | } |
| 1359 | } |
| 1360 | showDivider = 1; |
| 1361 | nChunk++; |
| 1362 | if( s.escHtml ){ |
| 1363 | blob_appendf(pOut, "<a name=\"chunk%d\"></a>\n", nChunk); |
| 1364 | } |
| 1365 | |
| 1366 | /* Show the initial common area */ |
| 1367 | a += skip; |
| @@ -1254,38 +1397,41 @@ | |
| 1397 | } |
| 1398 | |
| 1399 | alignment = sbsAlignment(&A[a], ma, &B[b], mb); |
| 1400 | for(j=0; ma+mb>0; j++){ |
| 1401 | if( alignment[j]==1 ){ |
| 1402 | /* Delete one line from the left */ |
| 1403 | s.n = 0; |
| 1404 | sbsWriteLineno(&s, a); |
| 1405 | s.iStart = 0; |
| 1406 | s.zStart = "<span class=\"diffrm\">"; |
| 1407 | s.iEnd = s.width; |
| 1408 | sbsWriteText(&s, &A[a], SBS_PAD); |
| 1409 | if( s.escHtml ){ |
| 1410 | sbsWrite(&s, " <\n", 6); |
| 1411 | }else{ |
| 1412 | sbsWrite(&s, " <\n", 3); |
| 1413 | } |
| 1414 | blob_append(pOut, s.zLine, s.n); |
| 1415 | assert( ma>0 ); |
| 1416 | ma--; |
| 1417 | a++; |
| 1418 | }else if( alignment[j]==3 ){ |
| 1419 | /* The left line is changed into the right line */ |
| 1420 | s.n = 0; |
| 1421 | sbsWriteLineChange(&s, &A[a], a, &B[b], b); |
| 1422 | blob_append(pOut, s.zLine, s.n); |
| 1423 | assert( ma>0 && mb>0 ); |
| 1424 | ma--; |
| 1425 | mb--; |
| 1426 | a++; |
| 1427 | b++; |
| 1428 | }else if( alignment[j]==2 ){ |
| 1429 | /* Insert one line on the right */ |
| 1430 | s.n = 0; |
| 1431 | sbsWriteSpace(&s, s.width + 7); |
| 1432 | if( s.escHtml ){ |
| 1433 | sbsWrite(&s, " > ", 6); |
| 1434 | }else{ |
| 1435 | sbsWrite(&s, " > ", 3); |
| 1436 | } |
| 1437 | sbsWriteLineno(&s, b); |
| @@ -1295,11 +1441,31 @@ | |
| 1441 | sbsWriteText(&s, &B[b], SBS_NEWLINE); |
| 1442 | blob_append(pOut, s.zLine, s.n); |
| 1443 | assert( mb>0 ); |
| 1444 | mb--; |
| 1445 | b++; |
| 1446 | }else{ |
| 1447 | /* Delete from the left and insert on the right */ |
| 1448 | s.n = 0; |
| 1449 | sbsWriteLineno(&s, a); |
| 1450 | s.iStart = 0; |
| 1451 | s.zStart = "<span class=\"diffrm\">"; |
| 1452 | s.iEnd = s.width; |
| 1453 | sbsWriteText(&s, &A[a], SBS_PAD); |
| 1454 | sbsWrite(&s, " | ", 3); |
| 1455 | sbsWriteLineno(&s, b); |
| 1456 | s.iStart = 0; |
| 1457 | s.zStart = "<span class=\"diffadd\">"; |
| 1458 | s.iEnd = s.width; |
| 1459 | sbsWriteText(&s, &B[b], SBS_NEWLINE); |
| 1460 | blob_append(pOut, s.zLine, s.n); |
| 1461 | ma--; |
| 1462 | mb--; |
| 1463 | a++; |
| 1464 | b++; |
| 1465 | } |
| 1466 | |
| 1467 | } |
| 1468 | fossil_free(alignment); |
| 1469 | if( i<nr-1 ){ |
| 1470 | m = R[r+i*3+3]; |
| 1471 | for(j=0; j<m; j++){ |
| @@ -1723,11 +1889,11 @@ | |
| 1889 | ** Extract the number of lines of context from diffFlags. Supply an |
| 1890 | ** appropriate default if no context width is specified. |
| 1891 | */ |
| 1892 | int diff_context_lines(u64 diffFlags){ |
| 1893 | int n = diffFlags & DIFF_CONTEXT_MASK; |
| 1894 | if( n==0 && (diffFlags & DIFF_CONTEXT_EX)==0 ) n = 5; |
| 1895 | return n; |
| 1896 | } |
| 1897 | |
| 1898 | /* |
| 1899 | ** Extract the width of columns for side-by-side diff. Supply an |
| @@ -1755,22 +1921,21 @@ | |
| 1921 | */ |
| 1922 | int *text_diff( |
| 1923 | Blob *pA_Blob, /* FROM file */ |
| 1924 | Blob *pB_Blob, /* TO file */ |
| 1925 | Blob *pOut, /* Write diff here if not NULL */ |
| 1926 | ReCompiled *pRe, /* Only output changes where this Regexp matches */ |
| 1927 | u64 diffFlags /* DIFF_* flags defined above */ |
| 1928 | ){ |
| 1929 | int ignoreEolWs; /* Ignore whitespace at the end of lines */ |
| 1930 | DContext c; |
| 1931 | |
| 1932 | if( diffFlags & DIFF_INVERT ){ |
| 1933 | Blob *pTemp = pA_Blob; |
| 1934 | pA_Blob = pB_Blob; |
| 1935 | pB_Blob = pTemp; |
| 1936 | } |
| 1937 | ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0; |
| 1938 | |
| 1939 | /* Prepare the input files */ |
| 1940 | memset(&c, 0, sizeof(c)); |
| 1941 | c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob), |
| @@ -1790,17 +1955,14 @@ | |
| 1955 | diff_all(&c); |
| 1956 | if( (diffFlags & DIFF_NOOPT)==0 ) diff_optimize(&c); |
| 1957 | |
| 1958 | if( pOut ){ |
| 1959 | /* Compute a context or side-by-side diff into pOut */ |
| 1960 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 1961 | sbsDiff(&c, pOut, pRe, diffFlags); |
| 1962 | }else{ |
| 1963 | contextDiff(&c, pOut, pRe, diffFlags); |
| 1964 | } |
| 1965 | fossil_free(c.aFrom); |
| 1966 | fossil_free(c.aTo); |
| 1967 | fossil_free(c.aEdit); |
| 1968 | return 0; |
| @@ -1826,19 +1988,19 @@ | |
| 1988 | ** --noopt Disable optimization DIFF_NOOPT |
| 1989 | ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE |
| 1990 | ** --unified Unified diff. ~DIFF_SIDEBYSIDE |
| 1991 | ** --width|-W N N character lines. DIFF_WIDTH_MASK |
| 1992 | */ |
| 1993 | u64 diff_options(void){ |
| 1994 | u64 diffFlags = 0; |
| 1995 | const char *z; |
| 1996 | int f; |
| 1997 | if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; |
| 1998 | if( find_option("unified",0,0)!=0 ) diffFlags &= ~DIFF_SIDEBYSIDE; |
| 1999 | if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>=0 ){ |
| 2000 | if( f > DIFF_CONTEXT_MASK ) f = DIFF_CONTEXT_MASK; |
| 2001 | diffFlags |= f + DIFF_CONTEXT_EX; |
| 2002 | } |
| 2003 | if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ |
| 2004 | f *= DIFF_CONTEXT_MASK+1; |
| 2005 | if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; |
| 2006 | diffFlags |= f; |
| @@ -1863,34 +2025,52 @@ | |
| 2025 | if( g.argc<4 ) usage("FILE1 FILE2 ..."); |
| 2026 | blob_read_from_file(&a, g.argv[2]); |
| 2027 | for(i=3; i<g.argc; i++){ |
| 2028 | if( i>3 ) fossil_print("-------------------------------\n"); |
| 2029 | blob_read_from_file(&b, g.argv[i]); |
| 2030 | R = text_diff(&a, &b, 0, 0, diffFlags); |
| 2031 | for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){ |
| 2032 | fossil_print(" copy %4d delete %4d insert %4d\n", R[r], R[r+1], R[r+2]); |
| 2033 | } |
| 2034 | /* free(R); */ |
| 2035 | blob_reset(&b); |
| 2036 | } |
| 2037 | } |
| 2038 | |
| 2039 | /* |
| 2040 | ** COMMAND: test-diff |
| 2041 | ** |
| 2042 | ** Usage: %fossil [options] FILE1 FILE2 |
| 2043 | ** |
| 2044 | ** Print the difference between two files. The usual diff options apply. |
| 2045 | */ |
| 2046 | void test_diff_cmd(void){ |
| 2047 | Blob a, b, out; |
| 2048 | u64 diffFlag; |
| 2049 | const char *zRe; /* Regex filter for diff output */ |
| 2050 | ReCompiled *pRe = 0; /* Regex filter for diff output */ |
| 2051 | |
| 2052 | if( find_option("tk",0,0)!=0 ){ |
| 2053 | diff_tk("test-diff", 2); |
| 2054 | return; |
| 2055 | } |
| 2056 | find_option("i",0,0); |
| 2057 | zRe = find_option("regexp","e",1); |
| 2058 | if( zRe ){ |
| 2059 | const char *zErr = re_compile(&pRe, zRe, 0); |
| 2060 | if( zErr ) fossil_fatal("regex error: %s", zErr); |
| 2061 | } |
| 2062 | diffFlag = diff_options(); |
| 2063 | verify_all_options(); |
| 2064 | if( g.argc!=4 ) usage("FILE1 FILE2"); |
| 2065 | diff_print_filenames(g.argv[2], g.argv[3], diffFlag); |
| 2066 | blob_read_from_file(&a, g.argv[2]); |
| 2067 | blob_read_from_file(&b, g.argv[3]); |
| 2068 | blob_zero(&out); |
| 2069 | text_diff(&a, &b, &out, pRe, diffFlag); |
| 2070 | blob_write_to_file(&out, "-"); |
| 2071 | re_free(pRe); |
| 2072 | } |
| 2073 | |
| 2074 | /************************************************************************** |
| 2075 | ** The basic difference engine is above. What follows is the annotation |
| 2076 | ** engine. Both are in the same file since they share many components. |
| 2077 |
+9
-3
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -109,11 +109,11 @@ | ||
| 109 | 109 | if( blob_compare(pFile1, &file2) ){ |
| 110 | 110 | fossil_print("CHANGED %s\n", zName); |
| 111 | 111 | } |
| 112 | 112 | }else{ |
| 113 | 113 | blob_zero(&out); |
| 114 | - text_diff(pFile1, &file2, &out, diffFlags); | |
| 114 | + text_diff(pFile1, &file2, &out, 0, diffFlags); | |
| 115 | 115 | if( blob_size(&out) ){ |
| 116 | 116 | diff_print_filenames(zName, zName2, diffFlags); |
| 117 | 117 | fossil_print("%s\n", blob_str(&out)); |
| 118 | 118 | } |
| 119 | 119 | blob_reset(&out); |
| @@ -210,11 +210,11 @@ | ||
| 210 | 210 | if( diffFlags & DIFF_BRIEF ) return; |
| 211 | 211 | if( zDiffCmd==0 ){ |
| 212 | 212 | Blob out; /* Diff output text */ |
| 213 | 213 | |
| 214 | 214 | blob_zero(&out); |
| 215 | - text_diff(pFile1, pFile2, &out, diffFlags); | |
| 215 | + text_diff(pFile1, pFile2, &out, 0, diffFlags); | |
| 216 | 216 | diff_print_filenames(zName, zName, diffFlags); |
| 217 | 217 | fossil_print("%s\n", blob_str(&out)); |
| 218 | 218 | |
| 219 | 219 | /* Release memory resources */ |
| 220 | 220 | blob_reset(&out); |
| @@ -659,12 +659,18 @@ | ||
| 659 | 659 | char *zCmd; |
| 660 | 660 | blob_zero(&script); |
| 661 | 661 | blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i", |
| 662 | 662 | g.nameOfExe, zSubCmd); |
| 663 | 663 | for(i=firstArg; i<g.argc; i++){ |
| 664 | + const char *z = g.argv[i]; | |
| 665 | + if( z[0]=='-' ){ | |
| 666 | + if( strglob("*-html",z) ) continue; | |
| 667 | + if( strglob("*-y",z) ) continue; | |
| 668 | + if( strglob("*-i",z) ) continue; | |
| 669 | + } | |
| 664 | 670 | blob_append(&script, " ", 1); |
| 665 | - shell_escape(&script, g.argv[i]); | |
| 671 | + shell_escape(&script, z); | |
| 666 | 672 | } |
| 667 | 673 | blob_appendf(&script, "}\n%s", zDiffScript); |
| 668 | 674 | zTempFile = write_blob_to_temp_file(&script); |
| 669 | 675 | zCmd = mprintf("tclsh \"%s\"", zTempFile); |
| 670 | 676 | fossil_system(zCmd); |
| 671 | 677 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -109,11 +109,11 @@ | |
| 109 | if( blob_compare(pFile1, &file2) ){ |
| 110 | fossil_print("CHANGED %s\n", zName); |
| 111 | } |
| 112 | }else{ |
| 113 | blob_zero(&out); |
| 114 | text_diff(pFile1, &file2, &out, diffFlags); |
| 115 | if( blob_size(&out) ){ |
| 116 | diff_print_filenames(zName, zName2, diffFlags); |
| 117 | fossil_print("%s\n", blob_str(&out)); |
| 118 | } |
| 119 | blob_reset(&out); |
| @@ -210,11 +210,11 @@ | |
| 210 | if( diffFlags & DIFF_BRIEF ) return; |
| 211 | if( zDiffCmd==0 ){ |
| 212 | Blob out; /* Diff output text */ |
| 213 | |
| 214 | blob_zero(&out); |
| 215 | text_diff(pFile1, pFile2, &out, diffFlags); |
| 216 | diff_print_filenames(zName, zName, diffFlags); |
| 217 | fossil_print("%s\n", blob_str(&out)); |
| 218 | |
| 219 | /* Release memory resources */ |
| 220 | blob_reset(&out); |
| @@ -659,12 +659,18 @@ | |
| 659 | char *zCmd; |
| 660 | blob_zero(&script); |
| 661 | blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i", |
| 662 | g.nameOfExe, zSubCmd); |
| 663 | for(i=firstArg; i<g.argc; i++){ |
| 664 | blob_append(&script, " ", 1); |
| 665 | shell_escape(&script, g.argv[i]); |
| 666 | } |
| 667 | blob_appendf(&script, "}\n%s", zDiffScript); |
| 668 | zTempFile = write_blob_to_temp_file(&script); |
| 669 | zCmd = mprintf("tclsh \"%s\"", zTempFile); |
| 670 | fossil_system(zCmd); |
| 671 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -109,11 +109,11 @@ | |
| 109 | if( blob_compare(pFile1, &file2) ){ |
| 110 | fossil_print("CHANGED %s\n", zName); |
| 111 | } |
| 112 | }else{ |
| 113 | blob_zero(&out); |
| 114 | text_diff(pFile1, &file2, &out, 0, diffFlags); |
| 115 | if( blob_size(&out) ){ |
| 116 | diff_print_filenames(zName, zName2, diffFlags); |
| 117 | fossil_print("%s\n", blob_str(&out)); |
| 118 | } |
| 119 | blob_reset(&out); |
| @@ -210,11 +210,11 @@ | |
| 210 | if( diffFlags & DIFF_BRIEF ) return; |
| 211 | if( zDiffCmd==0 ){ |
| 212 | Blob out; /* Diff output text */ |
| 213 | |
| 214 | blob_zero(&out); |
| 215 | text_diff(pFile1, pFile2, &out, 0, diffFlags); |
| 216 | diff_print_filenames(zName, zName, diffFlags); |
| 217 | fossil_print("%s\n", blob_str(&out)); |
| 218 | |
| 219 | /* Release memory resources */ |
| 220 | blob_reset(&out); |
| @@ -659,12 +659,18 @@ | |
| 659 | char *zCmd; |
| 660 | blob_zero(&script); |
| 661 | blob_appendf(&script, "set cmd {| \"%/\" %s --html -y -i", |
| 662 | g.nameOfExe, zSubCmd); |
| 663 | for(i=firstArg; i<g.argc; i++){ |
| 664 | const char *z = g.argv[i]; |
| 665 | if( z[0]=='-' ){ |
| 666 | if( strglob("*-html",z) ) continue; |
| 667 | if( strglob("*-y",z) ) continue; |
| 668 | if( strglob("*-i",z) ) continue; |
| 669 | } |
| 670 | blob_append(&script, " ", 1); |
| 671 | shell_escape(&script, z); |
| 672 | } |
| 673 | blob_appendf(&script, "}\n%s", zDiffScript); |
| 674 | zTempFile = write_blob_to_temp_file(&script); |
| 675 | zCmd = mprintf("tclsh \"%s\"", zTempFile); |
| 676 | fossil_system(zCmd); |
| 677 |
+2
-2
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -380,15 +380,15 @@ | ||
| 380 | 380 | g.zPath = mprintf("%s/%s", g.zPath, zName); |
| 381 | 381 | memcpy(zBaseline, zName, i); |
| 382 | 382 | zBaseline[i] = 0; |
| 383 | 383 | zName += i; |
| 384 | 384 | while( zName[0]=='/' ){ zName++; } |
| 385 | - if( !file_is_simple_pathname(zName) ){ | |
| 385 | + if( !file_is_simple_pathname(zName, 1) ){ | |
| 386 | 386 | int n = strlen(zName); |
| 387 | 387 | if( n>0 && zName[n-1]=='/' ){ |
| 388 | 388 | zName = mprintf("%sindex.html", zName); |
| 389 | - if( !file_is_simple_pathname(zName) ){ | |
| 389 | + if( !file_is_simple_pathname(zName, 1) ){ | |
| 390 | 390 | goto doc_not_found; |
| 391 | 391 | } |
| 392 | 392 | }else{ |
| 393 | 393 | goto doc_not_found; |
| 394 | 394 | } |
| 395 | 395 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -380,15 +380,15 @@ | |
| 380 | g.zPath = mprintf("%s/%s", g.zPath, zName); |
| 381 | memcpy(zBaseline, zName, i); |
| 382 | zBaseline[i] = 0; |
| 383 | zName += i; |
| 384 | while( zName[0]=='/' ){ zName++; } |
| 385 | if( !file_is_simple_pathname(zName) ){ |
| 386 | int n = strlen(zName); |
| 387 | if( n>0 && zName[n-1]=='/' ){ |
| 388 | zName = mprintf("%sindex.html", zName); |
| 389 | if( !file_is_simple_pathname(zName) ){ |
| 390 | goto doc_not_found; |
| 391 | } |
| 392 | }else{ |
| 393 | goto doc_not_found; |
| 394 | } |
| 395 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -380,15 +380,15 @@ | |
| 380 | g.zPath = mprintf("%s/%s", g.zPath, zName); |
| 381 | memcpy(zBaseline, zName, i); |
| 382 | zBaseline[i] = 0; |
| 383 | zName += i; |
| 384 | while( zName[0]=='/' ){ zName++; } |
| 385 | if( !file_is_simple_pathname(zName, 1) ){ |
| 386 | int n = strlen(zName); |
| 387 | if( n>0 && zName[n-1]=='/' ){ |
| 388 | zName = mprintf("%sindex.html", zName); |
| 389 | if( !file_is_simple_pathname(zName, 1) ){ |
| 390 | goto doc_not_found; |
| 391 | } |
| 392 | }else{ |
| 393 | goto doc_not_found; |
| 394 | } |
| 395 |
+31
-24
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -487,43 +487,50 @@ | ||
| 487 | 487 | ** * Does not contain any path element named "." or ".." |
| 488 | 488 | ** * Does not contain any of these characters in the path: "\" |
| 489 | 489 | ** * Does not end with "/". |
| 490 | 490 | ** * Does not contain two or more "/" characters in a row. |
| 491 | 491 | ** * Contains at least one character |
| 492 | +** | |
| 493 | +** Invalid UTF8 characters result in a false return if bStrictUtf8 is | |
| 494 | +** true. If bStrictUtf8 is false, invalid UTF8 characters are silently | |
| 495 | +** ignored. | |
| 492 | 496 | */ |
| 493 | -int file_is_simple_pathname(const char *z){ | |
| 497 | +int file_is_simple_pathname(const char *z, int bStrictUtf8){ | |
| 494 | 498 | int i; |
| 495 | 499 | char c = z[0]; |
| 500 | + char maskNonAscii = bStrictUtf8 ? 0x80 : 0x00; | |
| 496 | 501 | if( c=='/' || c==0 ) return 0; |
| 497 | 502 | if( c=='.' ){ |
| 498 | 503 | if( z[1]=='/' || z[1]==0 ) return 0; |
| 499 | 504 | if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0; |
| 500 | 505 | } |
| 501 | 506 | for(i=0; (c=z[i])!=0; i++){ |
| 502 | - if( (c & 0xf0) == 0xf0 ) { | |
| 503 | - /* Unicode characters > U+FFFF are not supported. | |
| 504 | - * Windows XP and earlier cannot handle them. | |
| 505 | - */ | |
| 506 | - return 0; | |
| 507 | - } | |
| 508 | - if( (c & 0xf0) == 0xe0 ) { | |
| 509 | - /* This is a 3-byte UTF-8 character */ | |
| 510 | - if ( (c & 0xfe) == 0xee ){ | |
| 511 | - /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */ | |
| 512 | - if ( (c & 1) && ((z[i+1] & 0xff) >= 0xa4) ){ | |
| 513 | - /* But exclude U+F900 - U+FFFF (0xef followed by byte >= 0xa4), | |
| 514 | - * which contain valid characters. */ | |
| 515 | - continue; | |
| 516 | - } | |
| 517 | - /* Unicode character in the range U+E000 - U+F8FF are for | |
| 518 | - * private use, they shouldn't occur in filenames. */ | |
| 519 | - return 0; | |
| 520 | - } | |
| 521 | - if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){ | |
| 522 | - /* Unicode character in the range U+D800 - U+DFFF are for | |
| 523 | - * surrogate pairs, they shouldn't occur in filenames. */ | |
| 524 | - return 0; | |
| 507 | + if( c & maskNonAscii ){ | |
| 508 | + if( (c & 0xf0) == 0xf0 ) { | |
| 509 | + /* Unicode characters > U+FFFF are not supported. | |
| 510 | + * Windows XP and earlier cannot handle them. | |
| 511 | + */ | |
| 512 | + return 0; | |
| 513 | + } | |
| 514 | + if( (c & 0xf0) == 0xe0 ) { | |
| 515 | + /* This is a 3-byte UTF-8 character */ | |
| 516 | + if ( (c & 0xfe) == 0xee ){ | |
| 517 | + /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */ | |
| 518 | + if ( (c & 1) && ((z[i+1] & 0xff) >= 0xa4) ){ | |
| 519 | + /* But exclude U+F900 - U+FFFF (0xef followed by byte >= 0xa4), | |
| 520 | + * which contain valid characters. */ | |
| 521 | + continue; | |
| 522 | + } | |
| 523 | + /* Unicode character in the range U+E000 - U+F8FF are for | |
| 524 | + * private use, they shouldn't occur in filenames. */ | |
| 525 | + return 0; | |
| 526 | + } | |
| 527 | + if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){ | |
| 528 | + /* Unicode character in the range U+D800 - U+DFFF are for | |
| 529 | + * surrogate pairs, they shouldn't occur in filenames. */ | |
| 530 | + return 0; | |
| 531 | + } | |
| 525 | 532 | } |
| 526 | 533 | } |
| 527 | 534 | if( c=='\\' ){ |
| 528 | 535 | return 0; |
| 529 | 536 | } |
| 530 | 537 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -487,43 +487,50 @@ | |
| 487 | ** * Does not contain any path element named "." or ".." |
| 488 | ** * Does not contain any of these characters in the path: "\" |
| 489 | ** * Does not end with "/". |
| 490 | ** * Does not contain two or more "/" characters in a row. |
| 491 | ** * Contains at least one character |
| 492 | */ |
| 493 | int file_is_simple_pathname(const char *z){ |
| 494 | int i; |
| 495 | char c = z[0]; |
| 496 | if( c=='/' || c==0 ) return 0; |
| 497 | if( c=='.' ){ |
| 498 | if( z[1]=='/' || z[1]==0 ) return 0; |
| 499 | if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0; |
| 500 | } |
| 501 | for(i=0; (c=z[i])!=0; i++){ |
| 502 | if( (c & 0xf0) == 0xf0 ) { |
| 503 | /* Unicode characters > U+FFFF are not supported. |
| 504 | * Windows XP and earlier cannot handle them. |
| 505 | */ |
| 506 | return 0; |
| 507 | } |
| 508 | if( (c & 0xf0) == 0xe0 ) { |
| 509 | /* This is a 3-byte UTF-8 character */ |
| 510 | if ( (c & 0xfe) == 0xee ){ |
| 511 | /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */ |
| 512 | if ( (c & 1) && ((z[i+1] & 0xff) >= 0xa4) ){ |
| 513 | /* But exclude U+F900 - U+FFFF (0xef followed by byte >= 0xa4), |
| 514 | * which contain valid characters. */ |
| 515 | continue; |
| 516 | } |
| 517 | /* Unicode character in the range U+E000 - U+F8FF are for |
| 518 | * private use, they shouldn't occur in filenames. */ |
| 519 | return 0; |
| 520 | } |
| 521 | if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){ |
| 522 | /* Unicode character in the range U+D800 - U+DFFF are for |
| 523 | * surrogate pairs, they shouldn't occur in filenames. */ |
| 524 | return 0; |
| 525 | } |
| 526 | } |
| 527 | if( c=='\\' ){ |
| 528 | return 0; |
| 529 | } |
| 530 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -487,43 +487,50 @@ | |
| 487 | ** * Does not contain any path element named "." or ".." |
| 488 | ** * Does not contain any of these characters in the path: "\" |
| 489 | ** * Does not end with "/". |
| 490 | ** * Does not contain two or more "/" characters in a row. |
| 491 | ** * Contains at least one character |
| 492 | ** |
| 493 | ** Invalid UTF8 characters result in a false return if bStrictUtf8 is |
| 494 | ** true. If bStrictUtf8 is false, invalid UTF8 characters are silently |
| 495 | ** ignored. |
| 496 | */ |
| 497 | int file_is_simple_pathname(const char *z, int bStrictUtf8){ |
| 498 | int i; |
| 499 | char c = z[0]; |
| 500 | char maskNonAscii = bStrictUtf8 ? 0x80 : 0x00; |
| 501 | if( c=='/' || c==0 ) return 0; |
| 502 | if( c=='.' ){ |
| 503 | if( z[1]=='/' || z[1]==0 ) return 0; |
| 504 | if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0; |
| 505 | } |
| 506 | for(i=0; (c=z[i])!=0; i++){ |
| 507 | if( c & maskNonAscii ){ |
| 508 | if( (c & 0xf0) == 0xf0 ) { |
| 509 | /* Unicode characters > U+FFFF are not supported. |
| 510 | * Windows XP and earlier cannot handle them. |
| 511 | */ |
| 512 | return 0; |
| 513 | } |
| 514 | if( (c & 0xf0) == 0xe0 ) { |
| 515 | /* This is a 3-byte UTF-8 character */ |
| 516 | if ( (c & 0xfe) == 0xee ){ |
| 517 | /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */ |
| 518 | if ( (c & 1) && ((z[i+1] & 0xff) >= 0xa4) ){ |
| 519 | /* But exclude U+F900 - U+FFFF (0xef followed by byte >= 0xa4), |
| 520 | * which contain valid characters. */ |
| 521 | continue; |
| 522 | } |
| 523 | /* Unicode character in the range U+E000 - U+F8FF are for |
| 524 | * private use, they shouldn't occur in filenames. */ |
| 525 | return 0; |
| 526 | } |
| 527 | if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){ |
| 528 | /* Unicode character in the range U+D800 - U+DFFF are for |
| 529 | * surrogate pairs, they shouldn't occur in filenames. */ |
| 530 | return 0; |
| 531 | } |
| 532 | } |
| 533 | } |
| 534 | if( c=='\\' ){ |
| 535 | return 0; |
| 536 | } |
| 537 |
+2
-4
| --- src/http_socket.c | ||
| +++ src/http_socket.c | ||
| @@ -27,14 +27,12 @@ | ||
| 27 | 27 | */ |
| 28 | 28 | |
| 29 | 29 | #include "config.h" |
| 30 | 30 | #include "http_socket.h" |
| 31 | 31 | #if defined(_WIN32) |
| 32 | -# if defined(__MINGW32__) | |
| 33 | -# include <ws2tcpip.h> | |
| 34 | -# endif | |
| 35 | -# include <windows.h> | |
| 32 | +# include <winsock2.h> | |
| 33 | +# include <ws2tcpip.h> | |
| 36 | 34 | #else |
| 37 | 35 | # include <netinet/in.h> |
| 38 | 36 | # include <arpa/inet.h> |
| 39 | 37 | # include <sys/socket.h> |
| 40 | 38 | # include <netdb.h> |
| 41 | 39 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -27,14 +27,12 @@ | |
| 27 | */ |
| 28 | |
| 29 | #include "config.h" |
| 30 | #include "http_socket.h" |
| 31 | #if defined(_WIN32) |
| 32 | # if defined(__MINGW32__) |
| 33 | # include <ws2tcpip.h> |
| 34 | # endif |
| 35 | # include <windows.h> |
| 36 | #else |
| 37 | # include <netinet/in.h> |
| 38 | # include <arpa/inet.h> |
| 39 | # include <sys/socket.h> |
| 40 | # include <netdb.h> |
| 41 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -27,14 +27,12 @@ | |
| 27 | */ |
| 28 | |
| 29 | #include "config.h" |
| 30 | #include "http_socket.h" |
| 31 | #if defined(_WIN32) |
| 32 | # include <winsock2.h> |
| 33 | # include <ws2tcpip.h> |
| 34 | #else |
| 35 | # include <netinet/in.h> |
| 36 | # include <arpa/inet.h> |
| 37 | # include <sys/socket.h> |
| 38 | # include <netdb.h> |
| 39 |
+53
-17
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -287,13 +287,18 @@ | ||
| 287 | 287 | } |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | 290 | |
| 291 | 291 | /* |
| 292 | -** Append the difference between two RIDs to the output | |
| 292 | +** Append the difference between artifacts to the output | |
| 293 | 293 | */ |
| 294 | -static void append_diff(const char *zFrom, const char *zTo, u64 diffFlags){ | |
| 294 | +static void append_diff( | |
| 295 | + const char *zFrom, /* Diff from this artifact */ | |
| 296 | + const char *zTo, /* ... to this artifact */ | |
| 297 | + u64 diffFlags, /* Diff formatting flags */ | |
| 298 | + ReCompiled *pRe /* Only show change matching this regex */ | |
| 299 | +){ | |
| 295 | 300 | int fromid; |
| 296 | 301 | int toid; |
| 297 | 302 | Blob from, to, out; |
| 298 | 303 | if( zFrom ){ |
| 299 | 304 | fromid = uuid_to_rid(zFrom, 0); |
| @@ -307,16 +312,16 @@ | ||
| 307 | 312 | }else{ |
| 308 | 313 | blob_zero(&to); |
| 309 | 314 | } |
| 310 | 315 | blob_zero(&out); |
| 311 | 316 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 312 | - text_diff(&from, &to, &out, diffFlags | DIFF_HTML); | |
| 317 | + text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML); | |
| 313 | 318 | @ <div class="sbsdiff"> |
| 314 | 319 | @ %s(blob_str(&out)) |
| 315 | 320 | @ </div> |
| 316 | 321 | }else{ |
| 317 | - text_diff(&from, &to, &out, diffFlags | DIFF_LINENO | DIFF_HTML); | |
| 322 | + text_diff(&from, &to, &out, pRe, diffFlags | DIFF_LINENO | DIFF_HTML); | |
| 318 | 323 | @ <div class="udiff"> |
| 319 | 324 | @ %s(blob_str(&out)) |
| 320 | 325 | @ </div> |
| 321 | 326 | } |
| 322 | 327 | blob_reset(&from); |
| @@ -333,10 +338,11 @@ | ||
| 333 | 338 | const char *zName, /* Name of the file that has changed */ |
| 334 | 339 | const char *zOld, /* blob.uuid before change. NULL for added files */ |
| 335 | 340 | const char *zNew, /* blob.uuid after change. NULL for deletes */ |
| 336 | 341 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 337 | 342 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 343 | + ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ | |
| 338 | 344 | int mperm /* executable or symlink permission for zNew */ |
| 339 | 345 | ){ |
| 340 | 346 | if( !g.perm.Hyperlink ){ |
| 341 | 347 | if( zNew==0 ){ |
| 342 | 348 | @ <p>Deleted %h(zName)</p> |
| @@ -350,21 +356,21 @@ | ||
| 350 | 356 | }else{ |
| 351 | 357 | @ <p>Changes to %h(zName)</p> |
| 352 | 358 | } |
| 353 | 359 | if( diffFlags ){ |
| 354 | 360 | @ <pre style="white-space:pre;"> |
| 355 | - append_diff(zOld, zNew, diffFlags); | |
| 361 | + append_diff(zOld, zNew, diffFlags, pRe); | |
| 356 | 362 | @ </pre> |
| 357 | 363 | } |
| 358 | 364 | }else{ |
| 359 | 365 | if( zOld && zNew ){ |
| 360 | 366 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 361 | 367 | @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 362 | 368 | @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a> |
| 363 | 369 | @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a> |
| 364 | 370 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 365 | - @ <p>Name change from | |
| 371 | + @ <p>Name change | |
| 366 | 372 | @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> |
| 367 | 373 | @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. |
| 368 | 374 | }else{ |
| 369 | 375 | @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for |
| 370 | 376 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| @@ -376,11 +382,11 @@ | ||
| 376 | 382 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 377 | 383 | @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> |
| 378 | 384 | } |
| 379 | 385 | if( diffFlags ){ |
| 380 | 386 | @ <pre style="white-space:pre;"> |
| 381 | - append_diff(zOld, zNew, diffFlags); | |
| 387 | + append_diff(zOld, zNew, diffFlags, pRe); | |
| 382 | 388 | @ </pre> |
| 383 | 389 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 384 | 390 | @ |
| 385 | 391 | @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a> |
| 386 | 392 | } |
| @@ -444,10 +450,12 @@ | ||
| 444 | 450 | int sideBySide; /* True for side-by-side diffs */ |
| 445 | 451 | u64 diffFlags; /* Flag parameter for text_diff() */ |
| 446 | 452 | const char *zName; /* Name of the checkin to be displayed */ |
| 447 | 453 | const char *zUuid; /* UUID of zName */ |
| 448 | 454 | const char *zParent; /* UUID of the parent checkin (if any) */ |
| 455 | + const char *zRe; /* regex parameter */ | |
| 456 | + ReCompiled *pRe = 0; /* regex */ | |
| 449 | 457 | |
| 450 | 458 | login_check_credentials(); |
| 451 | 459 | if( !g.perm.Read ){ login_needed(); return; } |
| 452 | 460 | zName = P("name"); |
| 453 | 461 | rid = name_to_rid_www("name"); |
| @@ -455,10 +463,12 @@ | ||
| 455 | 463 | style_header("Check-in Information Error"); |
| 456 | 464 | @ No such object: %h(g.argv[2]) |
| 457 | 465 | style_footer(); |
| 458 | 466 | return; |
| 459 | 467 | } |
| 468 | + zRe = P("regex"); | |
| 469 | + if( zRe ) re_compile(&pRe, zRe, 0); | |
| 460 | 470 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 461 | 471 | zParent = db_text(0, |
| 462 | 472 | "SELECT uuid FROM plink, blob" |
| 463 | 473 | " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim", |
| 464 | 474 | rid |
| @@ -479,13 +489,13 @@ | ||
| 479 | 489 | char *zEUser, *zEComment; |
| 480 | 490 | const char *zUser; |
| 481 | 491 | const char *zComment; |
| 482 | 492 | const char *zDate; |
| 483 | 493 | const char *zOrigDate; |
| 494 | +#if 0 | |
| 484 | 495 | char *zThisBranch; |
| 485 | 496 | double thisMtime; |
| 486 | -#if 0 | |
| 487 | 497 | int seenDiffTitle = 0; |
| 488 | 498 | #endif |
| 489 | 499 | |
| 490 | 500 | style_header(zTitle); |
| 491 | 501 | login_anonymous_available(); |
| @@ -498,11 +508,13 @@ | ||
| 498 | 508 | TAG_COMMENT, rid); |
| 499 | 509 | zUser = db_column_text(&q, 2); |
| 500 | 510 | zComment = db_column_text(&q, 3); |
| 501 | 511 | zDate = db_column_text(&q,1); |
| 502 | 512 | zOrigDate = db_column_text(&q, 4); |
| 513 | +#if 0 | |
| 503 | 514 | thisMtime = db_column_double(&q, 5); |
| 515 | +#endif | |
| 504 | 516 | @ <div class="section">Overview</div> |
| 505 | 517 | @ <table class="label-value"> |
| 506 | 518 | @ <tr><th>SHA1 Hash:</th><td>%s(zUuid) |
| 507 | 519 | if( g.perm.Setup ){ |
| 508 | 520 | @ (Record ID: %d(rid)) |
| @@ -567,17 +579,17 @@ | ||
| 567 | 579 | const char *zTagName = db_column_text(&q, 0); |
| 568 | 580 | @ | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a> |
| 569 | 581 | } |
| 570 | 582 | db_finalize(&q); |
| 571 | 583 | |
| 584 | +#if 0 | |
| 572 | 585 | /* Select a few other branches to diff against */ |
| 573 | 586 | zThisBranch = db_text("trunk", "SELECT value FROM tagxref" |
| 574 | 587 | " WHERE tagid=%d AND tagtype>0" |
| 575 | 588 | " AND rid=%d", |
| 576 | 589 | TAG_BRANCH, rid); |
| 577 | 590 | |
| 578 | -#if 0 | |
| 579 | 591 | /* Find nearby leaves to offer to diff against */ |
| 580 | 592 | db_prepare(&q, |
| 581 | 593 | "SELECT tagxref.value, blob.uuid, min(%.17g-event.mtime)" |
| 582 | 594 | " FROM leaf, event, tagxref, blob" |
| 583 | 595 | " WHERE event.mtime BETWEEN %.17g AND %.17g" |
| @@ -690,29 +702,35 @@ | ||
| 690 | 702 | @ show side-by-side diffs</a> |
| 691 | 703 | } |
| 692 | 704 | } |
| 693 | 705 | @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid)) |
| 694 | 706 | @ patch</a></div> |
| 707 | + if( pRe ){ | |
| 708 | + @ <p><b>Only differences that match regular expression "%h(zRe)" | |
| 709 | + @ are shown.</b></p> | |
| 710 | + } | |
| 695 | 711 | db_prepare(&q, |
| 696 | 712 | "SELECT name," |
| 697 | 713 | " mperm," |
| 698 | 714 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 699 | 715 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," |
| 700 | 716 | " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)" |
| 701 | 717 | " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" |
| 702 | 718 | " WHERE mlink.mid=%d" |
| 719 | + " AND (mlink.fid>0" | |
| 720 | + " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))" | |
| 703 | 721 | " ORDER BY name /*sort*/", |
| 704 | - rid | |
| 722 | + rid, rid | |
| 705 | 723 | ); |
| 706 | 724 | diffFlags = construct_diff_flags(showDiff, sideBySide); |
| 707 | 725 | while( db_step(&q)==SQLITE_ROW ){ |
| 708 | 726 | const char *zName = db_column_text(&q,0); |
| 709 | 727 | int mperm = db_column_int(&q, 1); |
| 710 | 728 | const char *zOld = db_column_text(&q,2); |
| 711 | 729 | const char *zNew = db_column_text(&q,3); |
| 712 | 730 | const char *zOldName = db_column_text(&q, 4); |
| 713 | - append_file_change_line(zName, zOld, zNew, zOldName, diffFlags, mperm); | |
| 731 | + append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm); | |
| 714 | 732 | } |
| 715 | 733 | db_finalize(&q); |
| 716 | 734 | } |
| 717 | 735 | style_footer(); |
| 718 | 736 | } |
| @@ -931,15 +949,19 @@ | ||
| 931 | 949 | Manifest *pFrom, *pTo; |
| 932 | 950 | ManifestFile *pFileFrom, *pFileTo; |
| 933 | 951 | const char *zBranch; |
| 934 | 952 | const char *zFrom; |
| 935 | 953 | const char *zTo; |
| 954 | + const char *zRe; | |
| 955 | + ReCompiled *pRe = 0; | |
| 936 | 956 | |
| 937 | 957 | login_check_credentials(); |
| 938 | 958 | if( !g.perm.Read ){ login_needed(); return; } |
| 939 | 959 | login_anonymous_available(); |
| 940 | 960 | |
| 961 | + zRe = P("regex"); | |
| 962 | + if( zRe ) re_compile(&pRe, zRe, 0); | |
| 941 | 963 | zBranch = P("branch"); |
| 942 | 964 | if( zBranch && zBranch[0] ){ |
| 943 | 965 | cgi_replace_parameter("from", mprintf("root:%s", zBranch)); |
| 944 | 966 | cgi_replace_parameter("to", zBranch); |
| 945 | 967 | } |
| @@ -967,11 +989,16 @@ | ||
| 967 | 989 | style_header("Check-in Differences"); |
| 968 | 990 | @ <h2>Difference From:</h2><blockquote> |
| 969 | 991 | checkin_description(ridFrom); |
| 970 | 992 | @ </blockquote><h2>To:</h2><blockquote> |
| 971 | 993 | checkin_description(ridTo); |
| 972 | - @ </blockquote><hr /><p> | |
| 994 | + @ </blockquote> | |
| 995 | + if( pRe ){ | |
| 996 | + @ <p><b>Only differences that match regular expression "%h(zRe)" | |
| 997 | + @ are shown.</b></p> | |
| 998 | + } | |
| 999 | + @<hr /><p> | |
| 973 | 1000 | |
| 974 | 1001 | manifest_file_rewind(pFrom); |
| 975 | 1002 | pFileFrom = manifest_file_next(pFrom, 0); |
| 976 | 1003 | manifest_file_rewind(pTo); |
| 977 | 1004 | pFileTo = manifest_file_next(pTo, 0); |
| @@ -985,25 +1012,25 @@ | ||
| 985 | 1012 | }else{ |
| 986 | 1013 | cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName); |
| 987 | 1014 | } |
| 988 | 1015 | if( cmp<0 ){ |
| 989 | 1016 | append_file_change_line(pFileFrom->zName, |
| 990 | - pFileFrom->zUuid, 0, 0, diffFlags, 0); | |
| 1017 | + pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0); | |
| 991 | 1018 | pFileFrom = manifest_file_next(pFrom, 0); |
| 992 | 1019 | }else if( cmp>0 ){ |
| 993 | 1020 | append_file_change_line(pFileTo->zName, |
| 994 | - 0, pFileTo->zUuid, 0, diffFlags, | |
| 1021 | + 0, pFileTo->zUuid, 0, diffFlags, pRe, | |
| 995 | 1022 | manifest_file_mperm(pFileTo)); |
| 996 | 1023 | pFileTo = manifest_file_next(pTo, 0); |
| 997 | 1024 | }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){ |
| 998 | 1025 | /* No changes */ |
| 999 | 1026 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1000 | 1027 | pFileTo = manifest_file_next(pTo, 0); |
| 1001 | 1028 | }else{ |
| 1002 | 1029 | append_file_change_line(pFileFrom->zName, |
| 1003 | 1030 | pFileFrom->zUuid, |
| 1004 | - pFileTo->zUuid, 0, diffFlags, | |
| 1031 | + pFileTo->zUuid, 0, diffFlags, pRe, | |
| 1005 | 1032 | manifest_file_mperm(pFileTo)); |
| 1006 | 1033 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1007 | 1034 | pFileTo = manifest_file_next(pTo, 0); |
| 1008 | 1035 | } |
| 1009 | 1036 | } |
| @@ -1252,11 +1279,11 @@ | ||
| 1252 | 1279 | } |
| 1253 | 1280 | |
| 1254 | 1281 | |
| 1255 | 1282 | /* |
| 1256 | 1283 | ** WEBPAGE: fdiff |
| 1257 | -** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN | |
| 1284 | +** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX | |
| 1258 | 1285 | ** |
| 1259 | 1286 | ** Two arguments, v1 and v2, identify the files to be diffed. Show the |
| 1260 | 1287 | ** difference between the two artifacts. Show diff side by side unless sbs |
| 1261 | 1288 | ** is 0. Generate plaintext if "patch" is present. |
| 1262 | 1289 | */ |
| @@ -1265,12 +1292,15 @@ | ||
| 1265 | 1292 | int isPatch; |
| 1266 | 1293 | int sideBySide; |
| 1267 | 1294 | Blob c1, c2, diff, *pOut; |
| 1268 | 1295 | char *zV1; |
| 1269 | 1296 | char *zV2; |
| 1297 | + const char *zRe; | |
| 1298 | + ReCompiled *pRe = 0; | |
| 1270 | 1299 | u64 diffFlags; |
| 1271 | 1300 | const char *zStyle = "sbsdiff"; |
| 1301 | + const char *zReErr = 0; | |
| 1272 | 1302 | |
| 1273 | 1303 | login_check_credentials(); |
| 1274 | 1304 | if( !g.perm.Read ){ login_needed(); return; } |
| 1275 | 1305 | v1 = name_to_rid_www("v1"); |
| 1276 | 1306 | v2 = name_to_rid_www("v2"); |
| @@ -1292,13 +1322,15 @@ | ||
| 1292 | 1322 | }else{ |
| 1293 | 1323 | diffFlags |= DIFF_LINENO; |
| 1294 | 1324 | zStyle = "udiff"; |
| 1295 | 1325 | } |
| 1296 | 1326 | } |
| 1327 | + zRe = P("regex"); | |
| 1328 | + if( zRe ) zReErr = re_compile(&pRe, zRe, 0); | |
| 1297 | 1329 | content_get(v1, &c1); |
| 1298 | 1330 | content_get(v2, &c2); |
| 1299 | - text_diff(&c1, &c2, pOut, diffFlags); | |
| 1331 | + text_diff(&c1, &c2, pOut, pRe, diffFlags); | |
| 1300 | 1332 | blob_reset(&c1); |
| 1301 | 1333 | blob_reset(&c2); |
| 1302 | 1334 | if( !isPatch ){ |
| 1303 | 1335 | style_header("Diff"); |
| 1304 | 1336 | style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", |
| @@ -1322,10 +1354,14 @@ | ||
| 1322 | 1354 | @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> |
| 1323 | 1355 | object_description(v1, 0, 0); |
| 1324 | 1356 | @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> |
| 1325 | 1357 | object_description(v2, 0, 0); |
| 1326 | 1358 | } |
| 1359 | + if( pRe ){ | |
| 1360 | + @ <b>Only differences that match regular expression "%h(zRe)" | |
| 1361 | + @ are shown.</b> | |
| 1362 | + } | |
| 1327 | 1363 | @ <hr /> |
| 1328 | 1364 | @ <div class="%s(zStyle)"> |
| 1329 | 1365 | @ %s(blob_str(&diff)) |
| 1330 | 1366 | @ </div> |
| 1331 | 1367 | blob_reset(&diff); |
| 1332 | 1368 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -287,13 +287,18 @@ | |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | |
| 291 | /* |
| 292 | ** Append the difference between two RIDs to the output |
| 293 | */ |
| 294 | static void append_diff(const char *zFrom, const char *zTo, u64 diffFlags){ |
| 295 | int fromid; |
| 296 | int toid; |
| 297 | Blob from, to, out; |
| 298 | if( zFrom ){ |
| 299 | fromid = uuid_to_rid(zFrom, 0); |
| @@ -307,16 +312,16 @@ | |
| 307 | }else{ |
| 308 | blob_zero(&to); |
| 309 | } |
| 310 | blob_zero(&out); |
| 311 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 312 | text_diff(&from, &to, &out, diffFlags | DIFF_HTML); |
| 313 | @ <div class="sbsdiff"> |
| 314 | @ %s(blob_str(&out)) |
| 315 | @ </div> |
| 316 | }else{ |
| 317 | text_diff(&from, &to, &out, diffFlags | DIFF_LINENO | DIFF_HTML); |
| 318 | @ <div class="udiff"> |
| 319 | @ %s(blob_str(&out)) |
| 320 | @ </div> |
| 321 | } |
| 322 | blob_reset(&from); |
| @@ -333,10 +338,11 @@ | |
| 333 | const char *zName, /* Name of the file that has changed */ |
| 334 | const char *zOld, /* blob.uuid before change. NULL for added files */ |
| 335 | const char *zNew, /* blob.uuid after change. NULL for deletes */ |
| 336 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 337 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 338 | int mperm /* executable or symlink permission for zNew */ |
| 339 | ){ |
| 340 | if( !g.perm.Hyperlink ){ |
| 341 | if( zNew==0 ){ |
| 342 | @ <p>Deleted %h(zName)</p> |
| @@ -350,21 +356,21 @@ | |
| 350 | }else{ |
| 351 | @ <p>Changes to %h(zName)</p> |
| 352 | } |
| 353 | if( diffFlags ){ |
| 354 | @ <pre style="white-space:pre;"> |
| 355 | append_diff(zOld, zNew, diffFlags); |
| 356 | @ </pre> |
| 357 | } |
| 358 | }else{ |
| 359 | if( zOld && zNew ){ |
| 360 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 361 | @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 362 | @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a> |
| 363 | @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a> |
| 364 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 365 | @ <p>Name change from |
| 366 | @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> |
| 367 | @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. |
| 368 | }else{ |
| 369 | @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for |
| 370 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| @@ -376,11 +382,11 @@ | |
| 376 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 377 | @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> |
| 378 | } |
| 379 | if( diffFlags ){ |
| 380 | @ <pre style="white-space:pre;"> |
| 381 | append_diff(zOld, zNew, diffFlags); |
| 382 | @ </pre> |
| 383 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 384 | @ |
| 385 | @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a> |
| 386 | } |
| @@ -444,10 +450,12 @@ | |
| 444 | int sideBySide; /* True for side-by-side diffs */ |
| 445 | u64 diffFlags; /* Flag parameter for text_diff() */ |
| 446 | const char *zName; /* Name of the checkin to be displayed */ |
| 447 | const char *zUuid; /* UUID of zName */ |
| 448 | const char *zParent; /* UUID of the parent checkin (if any) */ |
| 449 | |
| 450 | login_check_credentials(); |
| 451 | if( !g.perm.Read ){ login_needed(); return; } |
| 452 | zName = P("name"); |
| 453 | rid = name_to_rid_www("name"); |
| @@ -455,10 +463,12 @@ | |
| 455 | style_header("Check-in Information Error"); |
| 456 | @ No such object: %h(g.argv[2]) |
| 457 | style_footer(); |
| 458 | return; |
| 459 | } |
| 460 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 461 | zParent = db_text(0, |
| 462 | "SELECT uuid FROM plink, blob" |
| 463 | " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim", |
| 464 | rid |
| @@ -479,13 +489,13 @@ | |
| 479 | char *zEUser, *zEComment; |
| 480 | const char *zUser; |
| 481 | const char *zComment; |
| 482 | const char *zDate; |
| 483 | const char *zOrigDate; |
| 484 | char *zThisBranch; |
| 485 | double thisMtime; |
| 486 | #if 0 |
| 487 | int seenDiffTitle = 0; |
| 488 | #endif |
| 489 | |
| 490 | style_header(zTitle); |
| 491 | login_anonymous_available(); |
| @@ -498,11 +508,13 @@ | |
| 498 | TAG_COMMENT, rid); |
| 499 | zUser = db_column_text(&q, 2); |
| 500 | zComment = db_column_text(&q, 3); |
| 501 | zDate = db_column_text(&q,1); |
| 502 | zOrigDate = db_column_text(&q, 4); |
| 503 | thisMtime = db_column_double(&q, 5); |
| 504 | @ <div class="section">Overview</div> |
| 505 | @ <table class="label-value"> |
| 506 | @ <tr><th>SHA1 Hash:</th><td>%s(zUuid) |
| 507 | if( g.perm.Setup ){ |
| 508 | @ (Record ID: %d(rid)) |
| @@ -567,17 +579,17 @@ | |
| 567 | const char *zTagName = db_column_text(&q, 0); |
| 568 | @ | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a> |
| 569 | } |
| 570 | db_finalize(&q); |
| 571 | |
| 572 | /* Select a few other branches to diff against */ |
| 573 | zThisBranch = db_text("trunk", "SELECT value FROM tagxref" |
| 574 | " WHERE tagid=%d AND tagtype>0" |
| 575 | " AND rid=%d", |
| 576 | TAG_BRANCH, rid); |
| 577 | |
| 578 | #if 0 |
| 579 | /* Find nearby leaves to offer to diff against */ |
| 580 | db_prepare(&q, |
| 581 | "SELECT tagxref.value, blob.uuid, min(%.17g-event.mtime)" |
| 582 | " FROM leaf, event, tagxref, blob" |
| 583 | " WHERE event.mtime BETWEEN %.17g AND %.17g" |
| @@ -690,29 +702,35 @@ | |
| 690 | @ show side-by-side diffs</a> |
| 691 | } |
| 692 | } |
| 693 | @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid)) |
| 694 | @ patch</a></div> |
| 695 | db_prepare(&q, |
| 696 | "SELECT name," |
| 697 | " mperm," |
| 698 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 699 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," |
| 700 | " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)" |
| 701 | " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" |
| 702 | " WHERE mlink.mid=%d" |
| 703 | " ORDER BY name /*sort*/", |
| 704 | rid |
| 705 | ); |
| 706 | diffFlags = construct_diff_flags(showDiff, sideBySide); |
| 707 | while( db_step(&q)==SQLITE_ROW ){ |
| 708 | const char *zName = db_column_text(&q,0); |
| 709 | int mperm = db_column_int(&q, 1); |
| 710 | const char *zOld = db_column_text(&q,2); |
| 711 | const char *zNew = db_column_text(&q,3); |
| 712 | const char *zOldName = db_column_text(&q, 4); |
| 713 | append_file_change_line(zName, zOld, zNew, zOldName, diffFlags, mperm); |
| 714 | } |
| 715 | db_finalize(&q); |
| 716 | } |
| 717 | style_footer(); |
| 718 | } |
| @@ -931,15 +949,19 @@ | |
| 931 | Manifest *pFrom, *pTo; |
| 932 | ManifestFile *pFileFrom, *pFileTo; |
| 933 | const char *zBranch; |
| 934 | const char *zFrom; |
| 935 | const char *zTo; |
| 936 | |
| 937 | login_check_credentials(); |
| 938 | if( !g.perm.Read ){ login_needed(); return; } |
| 939 | login_anonymous_available(); |
| 940 | |
| 941 | zBranch = P("branch"); |
| 942 | if( zBranch && zBranch[0] ){ |
| 943 | cgi_replace_parameter("from", mprintf("root:%s", zBranch)); |
| 944 | cgi_replace_parameter("to", zBranch); |
| 945 | } |
| @@ -967,11 +989,16 @@ | |
| 967 | style_header("Check-in Differences"); |
| 968 | @ <h2>Difference From:</h2><blockquote> |
| 969 | checkin_description(ridFrom); |
| 970 | @ </blockquote><h2>To:</h2><blockquote> |
| 971 | checkin_description(ridTo); |
| 972 | @ </blockquote><hr /><p> |
| 973 | |
| 974 | manifest_file_rewind(pFrom); |
| 975 | pFileFrom = manifest_file_next(pFrom, 0); |
| 976 | manifest_file_rewind(pTo); |
| 977 | pFileTo = manifest_file_next(pTo, 0); |
| @@ -985,25 +1012,25 @@ | |
| 985 | }else{ |
| 986 | cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName); |
| 987 | } |
| 988 | if( cmp<0 ){ |
| 989 | append_file_change_line(pFileFrom->zName, |
| 990 | pFileFrom->zUuid, 0, 0, diffFlags, 0); |
| 991 | pFileFrom = manifest_file_next(pFrom, 0); |
| 992 | }else if( cmp>0 ){ |
| 993 | append_file_change_line(pFileTo->zName, |
| 994 | 0, pFileTo->zUuid, 0, diffFlags, |
| 995 | manifest_file_mperm(pFileTo)); |
| 996 | pFileTo = manifest_file_next(pTo, 0); |
| 997 | }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){ |
| 998 | /* No changes */ |
| 999 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1000 | pFileTo = manifest_file_next(pTo, 0); |
| 1001 | }else{ |
| 1002 | append_file_change_line(pFileFrom->zName, |
| 1003 | pFileFrom->zUuid, |
| 1004 | pFileTo->zUuid, 0, diffFlags, |
| 1005 | manifest_file_mperm(pFileTo)); |
| 1006 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1007 | pFileTo = manifest_file_next(pTo, 0); |
| 1008 | } |
| 1009 | } |
| @@ -1252,11 +1279,11 @@ | |
| 1252 | } |
| 1253 | |
| 1254 | |
| 1255 | /* |
| 1256 | ** WEBPAGE: fdiff |
| 1257 | ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN |
| 1258 | ** |
| 1259 | ** Two arguments, v1 and v2, identify the files to be diffed. Show the |
| 1260 | ** difference between the two artifacts. Show diff side by side unless sbs |
| 1261 | ** is 0. Generate plaintext if "patch" is present. |
| 1262 | */ |
| @@ -1265,12 +1292,15 @@ | |
| 1265 | int isPatch; |
| 1266 | int sideBySide; |
| 1267 | Blob c1, c2, diff, *pOut; |
| 1268 | char *zV1; |
| 1269 | char *zV2; |
| 1270 | u64 diffFlags; |
| 1271 | const char *zStyle = "sbsdiff"; |
| 1272 | |
| 1273 | login_check_credentials(); |
| 1274 | if( !g.perm.Read ){ login_needed(); return; } |
| 1275 | v1 = name_to_rid_www("v1"); |
| 1276 | v2 = name_to_rid_www("v2"); |
| @@ -1292,13 +1322,15 @@ | |
| 1292 | }else{ |
| 1293 | diffFlags |= DIFF_LINENO; |
| 1294 | zStyle = "udiff"; |
| 1295 | } |
| 1296 | } |
| 1297 | content_get(v1, &c1); |
| 1298 | content_get(v2, &c2); |
| 1299 | text_diff(&c1, &c2, pOut, diffFlags); |
| 1300 | blob_reset(&c1); |
| 1301 | blob_reset(&c2); |
| 1302 | if( !isPatch ){ |
| 1303 | style_header("Diff"); |
| 1304 | style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", |
| @@ -1322,10 +1354,14 @@ | |
| 1322 | @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> |
| 1323 | object_description(v1, 0, 0); |
| 1324 | @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> |
| 1325 | object_description(v2, 0, 0); |
| 1326 | } |
| 1327 | @ <hr /> |
| 1328 | @ <div class="%s(zStyle)"> |
| 1329 | @ %s(blob_str(&diff)) |
| 1330 | @ </div> |
| 1331 | blob_reset(&diff); |
| 1332 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -287,13 +287,18 @@ | |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | |
| 291 | /* |
| 292 | ** Append the difference between artifacts to the output |
| 293 | */ |
| 294 | static void append_diff( |
| 295 | const char *zFrom, /* Diff from this artifact */ |
| 296 | const char *zTo, /* ... to this artifact */ |
| 297 | u64 diffFlags, /* Diff formatting flags */ |
| 298 | ReCompiled *pRe /* Only show change matching this regex */ |
| 299 | ){ |
| 300 | int fromid; |
| 301 | int toid; |
| 302 | Blob from, to, out; |
| 303 | if( zFrom ){ |
| 304 | fromid = uuid_to_rid(zFrom, 0); |
| @@ -307,16 +312,16 @@ | |
| 312 | }else{ |
| 313 | blob_zero(&to); |
| 314 | } |
| 315 | blob_zero(&out); |
| 316 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 317 | text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML); |
| 318 | @ <div class="sbsdiff"> |
| 319 | @ %s(blob_str(&out)) |
| 320 | @ </div> |
| 321 | }else{ |
| 322 | text_diff(&from, &to, &out, pRe, diffFlags | DIFF_LINENO | DIFF_HTML); |
| 323 | @ <div class="udiff"> |
| 324 | @ %s(blob_str(&out)) |
| 325 | @ </div> |
| 326 | } |
| 327 | blob_reset(&from); |
| @@ -333,10 +338,11 @@ | |
| 338 | const char *zName, /* Name of the file that has changed */ |
| 339 | const char *zOld, /* blob.uuid before change. NULL for added files */ |
| 340 | const char *zNew, /* blob.uuid after change. NULL for deletes */ |
| 341 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 342 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 343 | ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ |
| 344 | int mperm /* executable or symlink permission for zNew */ |
| 345 | ){ |
| 346 | if( !g.perm.Hyperlink ){ |
| 347 | if( zNew==0 ){ |
| 348 | @ <p>Deleted %h(zName)</p> |
| @@ -350,21 +356,21 @@ | |
| 356 | }else{ |
| 357 | @ <p>Changes to %h(zName)</p> |
| 358 | } |
| 359 | if( diffFlags ){ |
| 360 | @ <pre style="white-space:pre;"> |
| 361 | append_diff(zOld, zNew, diffFlags, pRe); |
| 362 | @ </pre> |
| 363 | } |
| 364 | }else{ |
| 365 | if( zOld && zNew ){ |
| 366 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 367 | @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 368 | @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a> |
| 369 | @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a> |
| 370 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 371 | @ <p>Name change |
| 372 | @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> |
| 373 | @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. |
| 374 | }else{ |
| 375 | @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for |
| 376 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| @@ -376,11 +382,11 @@ | |
| 382 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 383 | @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> |
| 384 | } |
| 385 | if( diffFlags ){ |
| 386 | @ <pre style="white-space:pre;"> |
| 387 | append_diff(zOld, zNew, diffFlags, pRe); |
| 388 | @ </pre> |
| 389 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 390 | @ |
| 391 | @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a> |
| 392 | } |
| @@ -444,10 +450,12 @@ | |
| 450 | int sideBySide; /* True for side-by-side diffs */ |
| 451 | u64 diffFlags; /* Flag parameter for text_diff() */ |
| 452 | const char *zName; /* Name of the checkin to be displayed */ |
| 453 | const char *zUuid; /* UUID of zName */ |
| 454 | const char *zParent; /* UUID of the parent checkin (if any) */ |
| 455 | const char *zRe; /* regex parameter */ |
| 456 | ReCompiled *pRe = 0; /* regex */ |
| 457 | |
| 458 | login_check_credentials(); |
| 459 | if( !g.perm.Read ){ login_needed(); return; } |
| 460 | zName = P("name"); |
| 461 | rid = name_to_rid_www("name"); |
| @@ -455,10 +463,12 @@ | |
| 463 | style_header("Check-in Information Error"); |
| 464 | @ No such object: %h(g.argv[2]) |
| 465 | style_footer(); |
| 466 | return; |
| 467 | } |
| 468 | zRe = P("regex"); |
| 469 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 470 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 471 | zParent = db_text(0, |
| 472 | "SELECT uuid FROM plink, blob" |
| 473 | " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim", |
| 474 | rid |
| @@ -479,13 +489,13 @@ | |
| 489 | char *zEUser, *zEComment; |
| 490 | const char *zUser; |
| 491 | const char *zComment; |
| 492 | const char *zDate; |
| 493 | const char *zOrigDate; |
| 494 | #if 0 |
| 495 | char *zThisBranch; |
| 496 | double thisMtime; |
| 497 | int seenDiffTitle = 0; |
| 498 | #endif |
| 499 | |
| 500 | style_header(zTitle); |
| 501 | login_anonymous_available(); |
| @@ -498,11 +508,13 @@ | |
| 508 | TAG_COMMENT, rid); |
| 509 | zUser = db_column_text(&q, 2); |
| 510 | zComment = db_column_text(&q, 3); |
| 511 | zDate = db_column_text(&q,1); |
| 512 | zOrigDate = db_column_text(&q, 4); |
| 513 | #if 0 |
| 514 | thisMtime = db_column_double(&q, 5); |
| 515 | #endif |
| 516 | @ <div class="section">Overview</div> |
| 517 | @ <table class="label-value"> |
| 518 | @ <tr><th>SHA1 Hash:</th><td>%s(zUuid) |
| 519 | if( g.perm.Setup ){ |
| 520 | @ (Record ID: %d(rid)) |
| @@ -567,17 +579,17 @@ | |
| 579 | const char *zTagName = db_column_text(&q, 0); |
| 580 | @ | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a> |
| 581 | } |
| 582 | db_finalize(&q); |
| 583 | |
| 584 | #if 0 |
| 585 | /* Select a few other branches to diff against */ |
| 586 | zThisBranch = db_text("trunk", "SELECT value FROM tagxref" |
| 587 | " WHERE tagid=%d AND tagtype>0" |
| 588 | " AND rid=%d", |
| 589 | TAG_BRANCH, rid); |
| 590 | |
| 591 | /* Find nearby leaves to offer to diff against */ |
| 592 | db_prepare(&q, |
| 593 | "SELECT tagxref.value, blob.uuid, min(%.17g-event.mtime)" |
| 594 | " FROM leaf, event, tagxref, blob" |
| 595 | " WHERE event.mtime BETWEEN %.17g AND %.17g" |
| @@ -690,29 +702,35 @@ | |
| 702 | @ show side-by-side diffs</a> |
| 703 | } |
| 704 | } |
| 705 | @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid)) |
| 706 | @ patch</a></div> |
| 707 | if( pRe ){ |
| 708 | @ <p><b>Only differences that match regular expression "%h(zRe)" |
| 709 | @ are shown.</b></p> |
| 710 | } |
| 711 | db_prepare(&q, |
| 712 | "SELECT name," |
| 713 | " mperm," |
| 714 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 715 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," |
| 716 | " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)" |
| 717 | " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" |
| 718 | " WHERE mlink.mid=%d" |
| 719 | " AND (mlink.fid>0" |
| 720 | " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))" |
| 721 | " ORDER BY name /*sort*/", |
| 722 | rid, rid |
| 723 | ); |
| 724 | diffFlags = construct_diff_flags(showDiff, sideBySide); |
| 725 | while( db_step(&q)==SQLITE_ROW ){ |
| 726 | const char *zName = db_column_text(&q,0); |
| 727 | int mperm = db_column_int(&q, 1); |
| 728 | const char *zOld = db_column_text(&q,2); |
| 729 | const char *zNew = db_column_text(&q,3); |
| 730 | const char *zOldName = db_column_text(&q, 4); |
| 731 | append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm); |
| 732 | } |
| 733 | db_finalize(&q); |
| 734 | } |
| 735 | style_footer(); |
| 736 | } |
| @@ -931,15 +949,19 @@ | |
| 949 | Manifest *pFrom, *pTo; |
| 950 | ManifestFile *pFileFrom, *pFileTo; |
| 951 | const char *zBranch; |
| 952 | const char *zFrom; |
| 953 | const char *zTo; |
| 954 | const char *zRe; |
| 955 | ReCompiled *pRe = 0; |
| 956 | |
| 957 | login_check_credentials(); |
| 958 | if( !g.perm.Read ){ login_needed(); return; } |
| 959 | login_anonymous_available(); |
| 960 | |
| 961 | zRe = P("regex"); |
| 962 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 963 | zBranch = P("branch"); |
| 964 | if( zBranch && zBranch[0] ){ |
| 965 | cgi_replace_parameter("from", mprintf("root:%s", zBranch)); |
| 966 | cgi_replace_parameter("to", zBranch); |
| 967 | } |
| @@ -967,11 +989,16 @@ | |
| 989 | style_header("Check-in Differences"); |
| 990 | @ <h2>Difference From:</h2><blockquote> |
| 991 | checkin_description(ridFrom); |
| 992 | @ </blockquote><h2>To:</h2><blockquote> |
| 993 | checkin_description(ridTo); |
| 994 | @ </blockquote> |
| 995 | if( pRe ){ |
| 996 | @ <p><b>Only differences that match regular expression "%h(zRe)" |
| 997 | @ are shown.</b></p> |
| 998 | } |
| 999 | @<hr /><p> |
| 1000 | |
| 1001 | manifest_file_rewind(pFrom); |
| 1002 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1003 | manifest_file_rewind(pTo); |
| 1004 | pFileTo = manifest_file_next(pTo, 0); |
| @@ -985,25 +1012,25 @@ | |
| 1012 | }else{ |
| 1013 | cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName); |
| 1014 | } |
| 1015 | if( cmp<0 ){ |
| 1016 | append_file_change_line(pFileFrom->zName, |
| 1017 | pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0); |
| 1018 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1019 | }else if( cmp>0 ){ |
| 1020 | append_file_change_line(pFileTo->zName, |
| 1021 | 0, pFileTo->zUuid, 0, diffFlags, pRe, |
| 1022 | manifest_file_mperm(pFileTo)); |
| 1023 | pFileTo = manifest_file_next(pTo, 0); |
| 1024 | }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){ |
| 1025 | /* No changes */ |
| 1026 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1027 | pFileTo = manifest_file_next(pTo, 0); |
| 1028 | }else{ |
| 1029 | append_file_change_line(pFileFrom->zName, |
| 1030 | pFileFrom->zUuid, |
| 1031 | pFileTo->zUuid, 0, diffFlags, pRe, |
| 1032 | manifest_file_mperm(pFileTo)); |
| 1033 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1034 | pFileTo = manifest_file_next(pTo, 0); |
| 1035 | } |
| 1036 | } |
| @@ -1252,11 +1279,11 @@ | |
| 1279 | } |
| 1280 | |
| 1281 | |
| 1282 | /* |
| 1283 | ** WEBPAGE: fdiff |
| 1284 | ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX |
| 1285 | ** |
| 1286 | ** Two arguments, v1 and v2, identify the files to be diffed. Show the |
| 1287 | ** difference between the two artifacts. Show diff side by side unless sbs |
| 1288 | ** is 0. Generate plaintext if "patch" is present. |
| 1289 | */ |
| @@ -1265,12 +1292,15 @@ | |
| 1292 | int isPatch; |
| 1293 | int sideBySide; |
| 1294 | Blob c1, c2, diff, *pOut; |
| 1295 | char *zV1; |
| 1296 | char *zV2; |
| 1297 | const char *zRe; |
| 1298 | ReCompiled *pRe = 0; |
| 1299 | u64 diffFlags; |
| 1300 | const char *zStyle = "sbsdiff"; |
| 1301 | const char *zReErr = 0; |
| 1302 | |
| 1303 | login_check_credentials(); |
| 1304 | if( !g.perm.Read ){ login_needed(); return; } |
| 1305 | v1 = name_to_rid_www("v1"); |
| 1306 | v2 = name_to_rid_www("v2"); |
| @@ -1292,13 +1322,15 @@ | |
| 1322 | }else{ |
| 1323 | diffFlags |= DIFF_LINENO; |
| 1324 | zStyle = "udiff"; |
| 1325 | } |
| 1326 | } |
| 1327 | zRe = P("regex"); |
| 1328 | if( zRe ) zReErr = re_compile(&pRe, zRe, 0); |
| 1329 | content_get(v1, &c1); |
| 1330 | content_get(v2, &c2); |
| 1331 | text_diff(&c1, &c2, pOut, pRe, diffFlags); |
| 1332 | blob_reset(&c1); |
| 1333 | blob_reset(&c2); |
| 1334 | if( !isPatch ){ |
| 1335 | style_header("Diff"); |
| 1336 | style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", |
| @@ -1322,10 +1354,14 @@ | |
| 1354 | @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> |
| 1355 | object_description(v1, 0, 0); |
| 1356 | @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> |
| 1357 | object_description(v2, 0, 0); |
| 1358 | } |
| 1359 | if( pRe ){ |
| 1360 | @ <b>Only differences that match regular expression "%h(zRe)" |
| 1361 | @ are shown.</b> |
| 1362 | } |
| 1363 | @ <hr /> |
| 1364 | @ <div class="%s(zStyle)"> |
| 1365 | @ %s(blob_str(&diff)) |
| 1366 | @ </div> |
| 1367 | blob_reset(&diff); |
| 1368 |
+1
-1
| --- src/json_diff.c | ||
| +++ src/json_diff.c | ||
| @@ -58,11 +58,11 @@ | ||
| 58 | 58 | return NULL; |
| 59 | 59 | } |
| 60 | 60 | content_get(fromid, &from); |
| 61 | 61 | content_get(toid, &to); |
| 62 | 62 | blob_zero(&out); |
| 63 | - text_diff(&from, &to, &out, flags); | |
| 63 | + text_diff(&from, &to, &out, 0, flags); | |
| 64 | 64 | blob_reset(&from); |
| 65 | 65 | blob_reset(&to); |
| 66 | 66 | outLen = blob_size(&out); |
| 67 | 67 | if(outLen>=0){ |
| 68 | 68 | rc = cson_value_new_string(blob_buffer(&out), |
| 69 | 69 |
| --- src/json_diff.c | |
| +++ src/json_diff.c | |
| @@ -58,11 +58,11 @@ | |
| 58 | return NULL; |
| 59 | } |
| 60 | content_get(fromid, &from); |
| 61 | content_get(toid, &to); |
| 62 | blob_zero(&out); |
| 63 | text_diff(&from, &to, &out, flags); |
| 64 | blob_reset(&from); |
| 65 | blob_reset(&to); |
| 66 | outLen = blob_size(&out); |
| 67 | if(outLen>=0){ |
| 68 | rc = cson_value_new_string(blob_buffer(&out), |
| 69 |
| --- src/json_diff.c | |
| +++ src/json_diff.c | |
| @@ -58,11 +58,11 @@ | |
| 58 | return NULL; |
| 59 | } |
| 60 | content_get(fromid, &from); |
| 61 | content_get(toid, &to); |
| 62 | blob_zero(&out); |
| 63 | text_diff(&from, &to, &out, 0, flags); |
| 64 | blob_reset(&from); |
| 65 | blob_reset(&to); |
| 66 | outLen = blob_size(&out); |
| 67 | if(outLen>=0){ |
| 68 | rc = cson_value_new_string(blob_buffer(&out), |
| 69 |
+1
-1
| --- src/json_timeline.c | ||
| +++ src/json_timeline.c | ||
| @@ -90,11 +90,11 @@ | ||
| 90 | 90 | |
| 91 | 91 | /* |
| 92 | 92 | ** Return a pointer to a constant string that forms the basis |
| 93 | 93 | ** for a timeline query for the JSON interface. |
| 94 | 94 | */ |
| 95 | -const char const * json_timeline_query(void){ | |
| 95 | +char const * json_timeline_query(void){ | |
| 96 | 96 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 97 | 97 | static const char zBaseSql[] = |
| 98 | 98 | @ SELECT |
| 99 | 99 | @ NULL, |
| 100 | 100 | @ blob.rid, |
| 101 | 101 |
| --- src/json_timeline.c | |
| +++ src/json_timeline.c | |
| @@ -90,11 +90,11 @@ | |
| 90 | |
| 91 | /* |
| 92 | ** Return a pointer to a constant string that forms the basis |
| 93 | ** for a timeline query for the JSON interface. |
| 94 | */ |
| 95 | const char const * json_timeline_query(void){ |
| 96 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 97 | static const char zBaseSql[] = |
| 98 | @ SELECT |
| 99 | @ NULL, |
| 100 | @ blob.rid, |
| 101 |
| --- src/json_timeline.c | |
| +++ src/json_timeline.c | |
| @@ -90,11 +90,11 @@ | |
| 90 | |
| 91 | /* |
| 92 | ** Return a pointer to a constant string that forms the basis |
| 93 | ** for a timeline query for the JSON interface. |
| 94 | */ |
| 95 | char const * json_timeline_query(void){ |
| 96 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 97 | static const char zBaseSql[] = |
| 98 | @ SELECT |
| 99 | @ NULL, |
| 100 | @ blob.rid, |
| 101 |
+1
-1
| --- src/json_wiki.c | ||
| +++ src/json_wiki.c | ||
| @@ -543,11 +543,11 @@ | ||
| 543 | 543 | blob_init(&w1, pW1->zWiki, -1); |
| 544 | 544 | blob_zero(&w2); |
| 545 | 545 | blob_init(&w2, pW2->zWiki, -1); |
| 546 | 546 | blob_zero(&d); |
| 547 | 547 | diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE; |
| 548 | - text_diff(&w2, &w1, &d, diffFlags); | |
| 548 | + text_diff(&w2, &w1, &d, 0, diffFlags); | |
| 549 | 549 | blob_reset(&w1); |
| 550 | 550 | blob_reset(&w2); |
| 551 | 551 | |
| 552 | 552 | pay = cson_new_object(); |
| 553 | 553 | |
| 554 | 554 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -543,11 +543,11 @@ | |
| 543 | blob_init(&w1, pW1->zWiki, -1); |
| 544 | blob_zero(&w2); |
| 545 | blob_init(&w2, pW2->zWiki, -1); |
| 546 | blob_zero(&d); |
| 547 | diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE; |
| 548 | text_diff(&w2, &w1, &d, diffFlags); |
| 549 | blob_reset(&w1); |
| 550 | blob_reset(&w2); |
| 551 | |
| 552 | pay = cson_new_object(); |
| 553 | |
| 554 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -543,11 +543,11 @@ | |
| 543 | blob_init(&w1, pW1->zWiki, -1); |
| 544 | blob_zero(&w2); |
| 545 | blob_init(&w2, pW2->zWiki, -1); |
| 546 | blob_zero(&d); |
| 547 | diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE; |
| 548 | text_diff(&w2, &w1, &d, 0, diffFlags); |
| 549 | blob_reset(&w1); |
| 550 | blob_reset(&w2); |
| 551 | |
| 552 | pay = cson_new_object(); |
| 553 | |
| 554 |
+2
-2
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -397,11 +397,11 @@ | ||
| 397 | 397 | } |
| 398 | 398 | if( memcmp(zAgent, "Mozilla/", 8)==0 ){ |
| 399 | 399 | if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */ |
| 400 | 400 | if( strglob("*Firefox/[1-9]*", zAgent) ) return 1; |
| 401 | 401 | if( strglob("*Chrome/[1-9]*", zAgent) ) return 1; |
| 402 | - if( strglob("*(compatible;?MSIE?[1-9]*", zAgent) ) return 1; | |
| 402 | + if( strglob("*(compatible;?MSIE?[1789]*", zAgent) ) return 1; | |
| 403 | 403 | if( strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent) ) return 1; |
| 404 | 404 | return 0; |
| 405 | 405 | } |
| 406 | 406 | if( memcmp(zAgent, "Opera/", 6)==0 ) return 1; |
| 407 | 407 | if( memcmp(zAgent, "Safari/", 7)==0 ) return 1; |
| @@ -625,11 +625,11 @@ | ||
| 625 | 625 | @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>. |
| 626 | 626 | } |
| 627 | 627 | if( zAnonPw ){ |
| 628 | 628 | unsigned int uSeed = captcha_seed(); |
| 629 | 629 | char const *zDecoded = captcha_decode(uSeed); |
| 630 | - int bAutoCaptcha = db_get_boolean("auto-captcha", 1); | |
| 630 | + int bAutoCaptcha = db_get_boolean("auto-captcha", 0); | |
| 631 | 631 | char *zCaptcha = captcha_render(zDecoded); |
| 632 | 632 | |
| 633 | 633 | @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> |
| 634 | 634 | @ Visitors may enter <b>anonymous</b> as the user-ID with |
| 635 | 635 | @ the 8-character hexadecimal password shown below:</p> |
| 636 | 636 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -397,11 +397,11 @@ | |
| 397 | } |
| 398 | if( memcmp(zAgent, "Mozilla/", 8)==0 ){ |
| 399 | if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */ |
| 400 | if( strglob("*Firefox/[1-9]*", zAgent) ) return 1; |
| 401 | if( strglob("*Chrome/[1-9]*", zAgent) ) return 1; |
| 402 | if( strglob("*(compatible;?MSIE?[1-9]*", zAgent) ) return 1; |
| 403 | if( strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent) ) return 1; |
| 404 | return 0; |
| 405 | } |
| 406 | if( memcmp(zAgent, "Opera/", 6)==0 ) return 1; |
| 407 | if( memcmp(zAgent, "Safari/", 7)==0 ) return 1; |
| @@ -625,11 +625,11 @@ | |
| 625 | @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>. |
| 626 | } |
| 627 | if( zAnonPw ){ |
| 628 | unsigned int uSeed = captcha_seed(); |
| 629 | char const *zDecoded = captcha_decode(uSeed); |
| 630 | int bAutoCaptcha = db_get_boolean("auto-captcha", 1); |
| 631 | char *zCaptcha = captcha_render(zDecoded); |
| 632 | |
| 633 | @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> |
| 634 | @ Visitors may enter <b>anonymous</b> as the user-ID with |
| 635 | @ the 8-character hexadecimal password shown below:</p> |
| 636 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -397,11 +397,11 @@ | |
| 397 | } |
| 398 | if( memcmp(zAgent, "Mozilla/", 8)==0 ){ |
| 399 | if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */ |
| 400 | if( strglob("*Firefox/[1-9]*", zAgent) ) return 1; |
| 401 | if( strglob("*Chrome/[1-9]*", zAgent) ) return 1; |
| 402 | if( strglob("*(compatible;?MSIE?[1789]*", zAgent) ) return 1; |
| 403 | if( strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent) ) return 1; |
| 404 | return 0; |
| 405 | } |
| 406 | if( memcmp(zAgent, "Opera/", 6)==0 ) return 1; |
| 407 | if( memcmp(zAgent, "Safari/", 7)==0 ) return 1; |
| @@ -625,11 +625,11 @@ | |
| 625 | @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>. |
| 626 | } |
| 627 | if( zAnonPw ){ |
| 628 | unsigned int uSeed = captcha_seed(); |
| 629 | char const *zDecoded = captcha_decode(uSeed); |
| 630 | int bAutoCaptcha = db_get_boolean("auto-captcha", 0); |
| 631 | char *zCaptcha = captcha_render(zDecoded); |
| 632 | |
| 633 | @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> |
| 634 | @ Visitors may enter <b>anonymous</b> as the user-ID with |
| 635 | @ the 8-character hexadecimal password shown below:</p> |
| 636 |
+3
-1
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -892,11 +892,13 @@ | ||
| 892 | 892 | */ |
| 893 | 893 | void verify_all_options(void){ |
| 894 | 894 | int i; |
| 895 | 895 | for(i=1; i<g.argc; i++){ |
| 896 | 896 | if( g.argv[i][0]=='-' ){ |
| 897 | - fossil_fatal("unrecognized command-line option, or missing argument: %s", g.argv[i]); | |
| 897 | + fossil_fatal( | |
| 898 | + "unrecognized command-line option, or missing argument: %s", | |
| 899 | + g.argv[i]); | |
| 898 | 900 | } |
| 899 | 901 | } |
| 900 | 902 | } |
| 901 | 903 | |
| 902 | 904 | /* |
| 903 | 905 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -892,11 +892,13 @@ | |
| 892 | */ |
| 893 | void verify_all_options(void){ |
| 894 | int i; |
| 895 | for(i=1; i<g.argc; i++){ |
| 896 | if( g.argv[i][0]=='-' ){ |
| 897 | fossil_fatal("unrecognized command-line option, or missing argument: %s", g.argv[i]); |
| 898 | } |
| 899 | } |
| 900 | } |
| 901 | |
| 902 | /* |
| 903 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -892,11 +892,13 @@ | |
| 892 | */ |
| 893 | void verify_all_options(void){ |
| 894 | int i; |
| 895 | for(i=1; i<g.argc; i++){ |
| 896 | if( g.argv[i][0]=='-' ){ |
| 897 | fossil_fatal( |
| 898 | "unrecognized command-line option, or missing argument: %s", |
| 899 | g.argv[i]); |
| 900 | } |
| 901 | } |
| 902 | } |
| 903 | |
| 904 | /* |
| 905 |
+21
-1
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -81,10 +81,11 @@ | ||
| 81 | 81 | $(SRCDIR)/pivot.c \ |
| 82 | 82 | $(SRCDIR)/popen.c \ |
| 83 | 83 | $(SRCDIR)/pqueue.c \ |
| 84 | 84 | $(SRCDIR)/printf.c \ |
| 85 | 85 | $(SRCDIR)/rebuild.c \ |
| 86 | + $(SRCDIR)/regexp.c \ | |
| 86 | 87 | $(SRCDIR)/report.c \ |
| 87 | 88 | $(SRCDIR)/rss.c \ |
| 88 | 89 | $(SRCDIR)/schema.c \ |
| 89 | 90 | $(SRCDIR)/search.c \ |
| 90 | 91 | $(SRCDIR)/setup.c \ |
| @@ -101,10 +102,11 @@ | ||
| 101 | 102 | $(SRCDIR)/th_main.c \ |
| 102 | 103 | $(SRCDIR)/timeline.c \ |
| 103 | 104 | $(SRCDIR)/tkt.c \ |
| 104 | 105 | $(SRCDIR)/tktsetup.c \ |
| 105 | 106 | $(SRCDIR)/undo.c \ |
| 107 | + $(SRCDIR)/unicode.c \ | |
| 106 | 108 | $(SRCDIR)/update.c \ |
| 107 | 109 | $(SRCDIR)/url.c \ |
| 108 | 110 | $(SRCDIR)/user.c \ |
| 109 | 111 | $(SRCDIR)/utf8.c \ |
| 110 | 112 | $(SRCDIR)/verify.c \ |
| @@ -185,10 +187,11 @@ | ||
| 185 | 187 | $(OBJDIR)/pivot_.c \ |
| 186 | 188 | $(OBJDIR)/popen_.c \ |
| 187 | 189 | $(OBJDIR)/pqueue_.c \ |
| 188 | 190 | $(OBJDIR)/printf_.c \ |
| 189 | 191 | $(OBJDIR)/rebuild_.c \ |
| 192 | + $(OBJDIR)/regexp_.c \ | |
| 190 | 193 | $(OBJDIR)/report_.c \ |
| 191 | 194 | $(OBJDIR)/rss_.c \ |
| 192 | 195 | $(OBJDIR)/schema_.c \ |
| 193 | 196 | $(OBJDIR)/search_.c \ |
| 194 | 197 | $(OBJDIR)/setup_.c \ |
| @@ -205,10 +208,11 @@ | ||
| 205 | 208 | $(OBJDIR)/th_main_.c \ |
| 206 | 209 | $(OBJDIR)/timeline_.c \ |
| 207 | 210 | $(OBJDIR)/tkt_.c \ |
| 208 | 211 | $(OBJDIR)/tktsetup_.c \ |
| 209 | 212 | $(OBJDIR)/undo_.c \ |
| 213 | + $(OBJDIR)/unicode_.c \ | |
| 210 | 214 | $(OBJDIR)/update_.c \ |
| 211 | 215 | $(OBJDIR)/url_.c \ |
| 212 | 216 | $(OBJDIR)/user_.c \ |
| 213 | 217 | $(OBJDIR)/utf8_.c \ |
| 214 | 218 | $(OBJDIR)/verify_.c \ |
| @@ -289,10 +293,11 @@ | ||
| 289 | 293 | $(OBJDIR)/pivot.o \ |
| 290 | 294 | $(OBJDIR)/popen.o \ |
| 291 | 295 | $(OBJDIR)/pqueue.o \ |
| 292 | 296 | $(OBJDIR)/printf.o \ |
| 293 | 297 | $(OBJDIR)/rebuild.o \ |
| 298 | + $(OBJDIR)/regexp.o \ | |
| 294 | 299 | $(OBJDIR)/report.o \ |
| 295 | 300 | $(OBJDIR)/rss.o \ |
| 296 | 301 | $(OBJDIR)/schema.o \ |
| 297 | 302 | $(OBJDIR)/search.o \ |
| 298 | 303 | $(OBJDIR)/setup.o \ |
| @@ -309,10 +314,11 @@ | ||
| 309 | 314 | $(OBJDIR)/th_main.o \ |
| 310 | 315 | $(OBJDIR)/timeline.o \ |
| 311 | 316 | $(OBJDIR)/tkt.o \ |
| 312 | 317 | $(OBJDIR)/tktsetup.o \ |
| 313 | 318 | $(OBJDIR)/undo.o \ |
| 319 | + $(OBJDIR)/unicode.o \ | |
| 314 | 320 | $(OBJDIR)/update.o \ |
| 315 | 321 | $(OBJDIR)/url.o \ |
| 316 | 322 | $(OBJDIR)/user.o \ |
| 317 | 323 | $(OBJDIR)/utf8.o \ |
| 318 | 324 | $(OBJDIR)/verify.o \ |
| @@ -390,11 +396,11 @@ | ||
| 390 | 396 | |
| 391 | 397 | |
| 392 | 398 | $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex |
| 393 | 399 | $(OBJDIR)/mkindex $(TRANS_SRC) >$@ |
| 394 | 400 | $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h |
| 395 | - $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h | |
| 401 | + $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h | |
| 396 | 402 | touch $(OBJDIR)/headers |
| 397 | 403 | $(OBJDIR)/headers: Makefile |
| 398 | 404 | $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h |
| 399 | 405 | Makefile: |
| 400 | 406 | $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate |
| @@ -878,10 +884,17 @@ | ||
| 878 | 884 | |
| 879 | 885 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 880 | 886 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 881 | 887 | |
| 882 | 888 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 889 | +$(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate | |
| 890 | + $(OBJDIR)/translate $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c | |
| 891 | + | |
| 892 | +$(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h | |
| 893 | + $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c | |
| 894 | + | |
| 895 | +$(OBJDIR)/regexp.h: $(OBJDIR)/headers | |
| 883 | 896 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 884 | 897 | $(OBJDIR)/translate $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 885 | 898 | |
| 886 | 899 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| 887 | 900 | $(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c |
| @@ -1018,10 +1031,17 @@ | ||
| 1018 | 1031 | |
| 1019 | 1032 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1020 | 1033 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1021 | 1034 | |
| 1022 | 1035 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1036 | +$(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate | |
| 1037 | + $(OBJDIR)/translate $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c | |
| 1038 | + | |
| 1039 | +$(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h | |
| 1040 | + $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c | |
| 1041 | + | |
| 1042 | +$(OBJDIR)/unicode.h: $(OBJDIR)/headers | |
| 1023 | 1043 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1024 | 1044 | $(OBJDIR)/translate $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1025 | 1045 | |
| 1026 | 1046 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1027 | 1047 | $(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c |
| 1028 | 1048 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -81,10 +81,11 @@ | |
| 81 | $(SRCDIR)/pivot.c \ |
| 82 | $(SRCDIR)/popen.c \ |
| 83 | $(SRCDIR)/pqueue.c \ |
| 84 | $(SRCDIR)/printf.c \ |
| 85 | $(SRCDIR)/rebuild.c \ |
| 86 | $(SRCDIR)/report.c \ |
| 87 | $(SRCDIR)/rss.c \ |
| 88 | $(SRCDIR)/schema.c \ |
| 89 | $(SRCDIR)/search.c \ |
| 90 | $(SRCDIR)/setup.c \ |
| @@ -101,10 +102,11 @@ | |
| 101 | $(SRCDIR)/th_main.c \ |
| 102 | $(SRCDIR)/timeline.c \ |
| 103 | $(SRCDIR)/tkt.c \ |
| 104 | $(SRCDIR)/tktsetup.c \ |
| 105 | $(SRCDIR)/undo.c \ |
| 106 | $(SRCDIR)/update.c \ |
| 107 | $(SRCDIR)/url.c \ |
| 108 | $(SRCDIR)/user.c \ |
| 109 | $(SRCDIR)/utf8.c \ |
| 110 | $(SRCDIR)/verify.c \ |
| @@ -185,10 +187,11 @@ | |
| 185 | $(OBJDIR)/pivot_.c \ |
| 186 | $(OBJDIR)/popen_.c \ |
| 187 | $(OBJDIR)/pqueue_.c \ |
| 188 | $(OBJDIR)/printf_.c \ |
| 189 | $(OBJDIR)/rebuild_.c \ |
| 190 | $(OBJDIR)/report_.c \ |
| 191 | $(OBJDIR)/rss_.c \ |
| 192 | $(OBJDIR)/schema_.c \ |
| 193 | $(OBJDIR)/search_.c \ |
| 194 | $(OBJDIR)/setup_.c \ |
| @@ -205,10 +208,11 @@ | |
| 205 | $(OBJDIR)/th_main_.c \ |
| 206 | $(OBJDIR)/timeline_.c \ |
| 207 | $(OBJDIR)/tkt_.c \ |
| 208 | $(OBJDIR)/tktsetup_.c \ |
| 209 | $(OBJDIR)/undo_.c \ |
| 210 | $(OBJDIR)/update_.c \ |
| 211 | $(OBJDIR)/url_.c \ |
| 212 | $(OBJDIR)/user_.c \ |
| 213 | $(OBJDIR)/utf8_.c \ |
| 214 | $(OBJDIR)/verify_.c \ |
| @@ -289,10 +293,11 @@ | |
| 289 | $(OBJDIR)/pivot.o \ |
| 290 | $(OBJDIR)/popen.o \ |
| 291 | $(OBJDIR)/pqueue.o \ |
| 292 | $(OBJDIR)/printf.o \ |
| 293 | $(OBJDIR)/rebuild.o \ |
| 294 | $(OBJDIR)/report.o \ |
| 295 | $(OBJDIR)/rss.o \ |
| 296 | $(OBJDIR)/schema.o \ |
| 297 | $(OBJDIR)/search.o \ |
| 298 | $(OBJDIR)/setup.o \ |
| @@ -309,10 +314,11 @@ | |
| 309 | $(OBJDIR)/th_main.o \ |
| 310 | $(OBJDIR)/timeline.o \ |
| 311 | $(OBJDIR)/tkt.o \ |
| 312 | $(OBJDIR)/tktsetup.o \ |
| 313 | $(OBJDIR)/undo.o \ |
| 314 | $(OBJDIR)/update.o \ |
| 315 | $(OBJDIR)/url.o \ |
| 316 | $(OBJDIR)/user.o \ |
| 317 | $(OBJDIR)/utf8.o \ |
| 318 | $(OBJDIR)/verify.o \ |
| @@ -390,11 +396,11 @@ | |
| 390 | |
| 391 | |
| 392 | $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex |
| 393 | $(OBJDIR)/mkindex $(TRANS_SRC) >$@ |
| 394 | $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h |
| 395 | $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h |
| 396 | touch $(OBJDIR)/headers |
| 397 | $(OBJDIR)/headers: Makefile |
| 398 | $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h |
| 399 | Makefile: |
| 400 | $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate |
| @@ -878,10 +884,17 @@ | |
| 878 | |
| 879 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 880 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 881 | |
| 882 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 883 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 884 | $(OBJDIR)/translate $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 885 | |
| 886 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| 887 | $(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c |
| @@ -1018,10 +1031,17 @@ | |
| 1018 | |
| 1019 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1020 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1021 | |
| 1022 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1023 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1024 | $(OBJDIR)/translate $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1025 | |
| 1026 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1027 | $(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c |
| 1028 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -81,10 +81,11 @@ | |
| 81 | $(SRCDIR)/pivot.c \ |
| 82 | $(SRCDIR)/popen.c \ |
| 83 | $(SRCDIR)/pqueue.c \ |
| 84 | $(SRCDIR)/printf.c \ |
| 85 | $(SRCDIR)/rebuild.c \ |
| 86 | $(SRCDIR)/regexp.c \ |
| 87 | $(SRCDIR)/report.c \ |
| 88 | $(SRCDIR)/rss.c \ |
| 89 | $(SRCDIR)/schema.c \ |
| 90 | $(SRCDIR)/search.c \ |
| 91 | $(SRCDIR)/setup.c \ |
| @@ -101,10 +102,11 @@ | |
| 102 | $(SRCDIR)/th_main.c \ |
| 103 | $(SRCDIR)/timeline.c \ |
| 104 | $(SRCDIR)/tkt.c \ |
| 105 | $(SRCDIR)/tktsetup.c \ |
| 106 | $(SRCDIR)/undo.c \ |
| 107 | $(SRCDIR)/unicode.c \ |
| 108 | $(SRCDIR)/update.c \ |
| 109 | $(SRCDIR)/url.c \ |
| 110 | $(SRCDIR)/user.c \ |
| 111 | $(SRCDIR)/utf8.c \ |
| 112 | $(SRCDIR)/verify.c \ |
| @@ -185,10 +187,11 @@ | |
| 187 | $(OBJDIR)/pivot_.c \ |
| 188 | $(OBJDIR)/popen_.c \ |
| 189 | $(OBJDIR)/pqueue_.c \ |
| 190 | $(OBJDIR)/printf_.c \ |
| 191 | $(OBJDIR)/rebuild_.c \ |
| 192 | $(OBJDIR)/regexp_.c \ |
| 193 | $(OBJDIR)/report_.c \ |
| 194 | $(OBJDIR)/rss_.c \ |
| 195 | $(OBJDIR)/schema_.c \ |
| 196 | $(OBJDIR)/search_.c \ |
| 197 | $(OBJDIR)/setup_.c \ |
| @@ -205,10 +208,11 @@ | |
| 208 | $(OBJDIR)/th_main_.c \ |
| 209 | $(OBJDIR)/timeline_.c \ |
| 210 | $(OBJDIR)/tkt_.c \ |
| 211 | $(OBJDIR)/tktsetup_.c \ |
| 212 | $(OBJDIR)/undo_.c \ |
| 213 | $(OBJDIR)/unicode_.c \ |
| 214 | $(OBJDIR)/update_.c \ |
| 215 | $(OBJDIR)/url_.c \ |
| 216 | $(OBJDIR)/user_.c \ |
| 217 | $(OBJDIR)/utf8_.c \ |
| 218 | $(OBJDIR)/verify_.c \ |
| @@ -289,10 +293,11 @@ | |
| 293 | $(OBJDIR)/pivot.o \ |
| 294 | $(OBJDIR)/popen.o \ |
| 295 | $(OBJDIR)/pqueue.o \ |
| 296 | $(OBJDIR)/printf.o \ |
| 297 | $(OBJDIR)/rebuild.o \ |
| 298 | $(OBJDIR)/regexp.o \ |
| 299 | $(OBJDIR)/report.o \ |
| 300 | $(OBJDIR)/rss.o \ |
| 301 | $(OBJDIR)/schema.o \ |
| 302 | $(OBJDIR)/search.o \ |
| 303 | $(OBJDIR)/setup.o \ |
| @@ -309,10 +314,11 @@ | |
| 314 | $(OBJDIR)/th_main.o \ |
| 315 | $(OBJDIR)/timeline.o \ |
| 316 | $(OBJDIR)/tkt.o \ |
| 317 | $(OBJDIR)/tktsetup.o \ |
| 318 | $(OBJDIR)/undo.o \ |
| 319 | $(OBJDIR)/unicode.o \ |
| 320 | $(OBJDIR)/update.o \ |
| 321 | $(OBJDIR)/url.o \ |
| 322 | $(OBJDIR)/user.o \ |
| 323 | $(OBJDIR)/utf8.o \ |
| 324 | $(OBJDIR)/verify.o \ |
| @@ -390,11 +396,11 @@ | |
| 396 | |
| 397 | |
| 398 | $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex |
| 399 | $(OBJDIR)/mkindex $(TRANS_SRC) >$@ |
| 400 | $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h |
| 401 | $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h |
| 402 | touch $(OBJDIR)/headers |
| 403 | $(OBJDIR)/headers: Makefile |
| 404 | $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h |
| 405 | Makefile: |
| 406 | $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate |
| @@ -878,10 +884,17 @@ | |
| 884 | |
| 885 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 886 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 887 | |
| 888 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 889 | $(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate |
| 890 | $(OBJDIR)/translate $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c |
| 891 | |
| 892 | $(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h |
| 893 | $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c |
| 894 | |
| 895 | $(OBJDIR)/regexp.h: $(OBJDIR)/headers |
| 896 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 897 | $(OBJDIR)/translate $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 898 | |
| 899 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| 900 | $(XTCC) -o $(OBJDIR)/report.o -c $(OBJDIR)/report_.c |
| @@ -1018,10 +1031,17 @@ | |
| 1031 | |
| 1032 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1033 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1034 | |
| 1035 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1036 | $(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate |
| 1037 | $(OBJDIR)/translate $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c |
| 1038 | |
| 1039 | $(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h |
| 1040 | $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c |
| 1041 | |
| 1042 | $(OBJDIR)/unicode.h: $(OBJDIR)/headers |
| 1043 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1044 | $(OBJDIR)/translate $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1045 | |
| 1046 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1047 | $(XTCC) -o $(OBJDIR)/update.o -c $(OBJDIR)/update_.c |
| 1048 |
+3
-1
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -84,10 +84,11 @@ | ||
| 84 | 84 | pivot |
| 85 | 85 | popen |
| 86 | 86 | pqueue |
| 87 | 87 | printf |
| 88 | 88 | rebuild |
| 89 | + regexp | |
| 89 | 90 | report |
| 90 | 91 | rss |
| 91 | 92 | schema |
| 92 | 93 | search |
| 93 | 94 | setup |
| @@ -104,10 +105,11 @@ | ||
| 104 | 105 | th_main |
| 105 | 106 | timeline |
| 106 | 107 | tkt |
| 107 | 108 | tktsetup |
| 108 | 109 | undo |
| 110 | + unicode | |
| 109 | 111 | update |
| 110 | 112 | url |
| 111 | 113 | user |
| 112 | 114 | utf8 |
| 113 | 115 | verify |
| @@ -405,11 +407,11 @@ | ||
| 405 | 407 | |
| 406 | 408 | #### Check if the workaround for the MinGW command line handling needs to |
| 407 | 409 | # be enabled by default. |
| 408 | 410 | # |
| 409 | 411 | ifndef BROKEN_MINGW_CMDLINE |
| 410 | -ifeq ($(PREFIX),) | |
| 412 | +ifeq (,$(findstring w64-mingw32,$(PREFIX))) | |
| 411 | 413 | BROKEN_MINGW_CMDLINE = 1 |
| 412 | 414 | endif |
| 413 | 415 | endif |
| 414 | 416 | |
| 415 | 417 | #### The directories where the zlib include and library files are located. |
| 416 | 418 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -84,10 +84,11 @@ | |
| 84 | pivot |
| 85 | popen |
| 86 | pqueue |
| 87 | printf |
| 88 | rebuild |
| 89 | report |
| 90 | rss |
| 91 | schema |
| 92 | search |
| 93 | setup |
| @@ -104,10 +105,11 @@ | |
| 104 | th_main |
| 105 | timeline |
| 106 | tkt |
| 107 | tktsetup |
| 108 | undo |
| 109 | update |
| 110 | url |
| 111 | user |
| 112 | utf8 |
| 113 | verify |
| @@ -405,11 +407,11 @@ | |
| 405 | |
| 406 | #### Check if the workaround for the MinGW command line handling needs to |
| 407 | # be enabled by default. |
| 408 | # |
| 409 | ifndef BROKEN_MINGW_CMDLINE |
| 410 | ifeq ($(PREFIX),) |
| 411 | BROKEN_MINGW_CMDLINE = 1 |
| 412 | endif |
| 413 | endif |
| 414 | |
| 415 | #### The directories where the zlib include and library files are located. |
| 416 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -84,10 +84,11 @@ | |
| 84 | pivot |
| 85 | popen |
| 86 | pqueue |
| 87 | printf |
| 88 | rebuild |
| 89 | regexp |
| 90 | report |
| 91 | rss |
| 92 | schema |
| 93 | search |
| 94 | setup |
| @@ -104,10 +105,11 @@ | |
| 105 | th_main |
| 106 | timeline |
| 107 | tkt |
| 108 | tktsetup |
| 109 | undo |
| 110 | unicode |
| 111 | update |
| 112 | url |
| 113 | user |
| 114 | utf8 |
| 115 | verify |
| @@ -405,11 +407,11 @@ | |
| 407 | |
| 408 | #### Check if the workaround for the MinGW command line handling needs to |
| 409 | # be enabled by default. |
| 410 | # |
| 411 | ifndef BROKEN_MINGW_CMDLINE |
| 412 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 413 | BROKEN_MINGW_CMDLINE = 1 |
| 414 | endif |
| 415 | endif |
| 416 | |
| 417 | #### The directories where the zlib include and library files are located. |
| 418 |
+3
-1
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -84,10 +84,11 @@ | ||
| 84 | 84 | pivot |
| 85 | 85 | popen |
| 86 | 86 | pqueue |
| 87 | 87 | printf |
| 88 | 88 | rebuild |
| 89 | + regexp | |
| 89 | 90 | report |
| 90 | 91 | rss |
| 91 | 92 | schema |
| 92 | 93 | search |
| 93 | 94 | setup |
| @@ -104,10 +105,11 @@ | ||
| 104 | 105 | th_main |
| 105 | 106 | timeline |
| 106 | 107 | tkt |
| 107 | 108 | tktsetup |
| 108 | 109 | undo |
| 110 | + unicode | |
| 109 | 111 | update |
| 110 | 112 | url |
| 111 | 113 | user |
| 112 | 114 | utf8 |
| 113 | 115 | verify |
| @@ -405,11 +407,11 @@ | ||
| 405 | 407 | |
| 406 | 408 | #### Check if the workaround for the MinGW command line handling needs to |
| 407 | 409 | # be enabled by default. |
| 408 | 410 | # |
| 409 | 411 | ifndef BROKEN_MINGW_CMDLINE |
| 410 | -ifeq ($(PREFIX),) | |
| 412 | +ifeq (,$(findstring w64-mingw32,$(PREFIX))) | |
| 411 | 413 | BROKEN_MINGW_CMDLINE = 1 |
| 412 | 414 | endif |
| 413 | 415 | endif |
| 414 | 416 | |
| 415 | 417 | #### The directories where the zlib include and library files are located. |
| 416 | 418 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -84,10 +84,11 @@ | |
| 84 | pivot |
| 85 | popen |
| 86 | pqueue |
| 87 | printf |
| 88 | rebuild |
| 89 | report |
| 90 | rss |
| 91 | schema |
| 92 | search |
| 93 | setup |
| @@ -104,10 +105,11 @@ | |
| 104 | th_main |
| 105 | timeline |
| 106 | tkt |
| 107 | tktsetup |
| 108 | undo |
| 109 | update |
| 110 | url |
| 111 | user |
| 112 | utf8 |
| 113 | verify |
| @@ -405,11 +407,11 @@ | |
| 405 | |
| 406 | #### Check if the workaround for the MinGW command line handling needs to |
| 407 | # be enabled by default. |
| 408 | # |
| 409 | ifndef BROKEN_MINGW_CMDLINE |
| 410 | ifeq ($(PREFIX),) |
| 411 | BROKEN_MINGW_CMDLINE = 1 |
| 412 | endif |
| 413 | endif |
| 414 | |
| 415 | #### The directories where the zlib include and library files are located. |
| 416 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -84,10 +84,11 @@ | |
| 84 | pivot |
| 85 | popen |
| 86 | pqueue |
| 87 | printf |
| 88 | rebuild |
| 89 | regexp |
| 90 | report |
| 91 | rss |
| 92 | schema |
| 93 | search |
| 94 | setup |
| @@ -104,10 +105,11 @@ | |
| 105 | th_main |
| 106 | timeline |
| 107 | tkt |
| 108 | tktsetup |
| 109 | undo |
| 110 | unicode |
| 111 | update |
| 112 | url |
| 113 | user |
| 114 | utf8 |
| 115 | verify |
| @@ -405,11 +407,11 @@ | |
| 407 | |
| 408 | #### Check if the workaround for the MinGW command line handling needs to |
| 409 | # be enabled by default. |
| 410 | # |
| 411 | ifndef BROKEN_MINGW_CMDLINE |
| 412 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 413 | BROKEN_MINGW_CMDLINE = 1 |
| 414 | endif |
| 415 | endif |
| 416 | |
| 417 | #### The directories where the zlib include and library files are located. |
| 418 |
+21
-3
| --- src/manifest.c | ||
| +++ src/manifest.c | ||
| @@ -430,11 +430,11 @@ | ||
| 430 | 430 | zTarget = next_token(&x, &nTarget); |
| 431 | 431 | zSrc = next_token(&x, &nSrc); |
| 432 | 432 | if( zName==0 || zTarget==0 ) goto manifest_syntax_error; |
| 433 | 433 | if( p->zAttachName!=0 ) goto manifest_syntax_error; |
| 434 | 434 | defossilize(zName); |
| 435 | - if( !file_is_simple_pathname(zName) ){ | |
| 435 | + if( !file_is_simple_pathname(zName, 0) ){ | |
| 436 | 436 | SYNTAX("invalid filename on A-card"); |
| 437 | 437 | } |
| 438 | 438 | defossilize(zTarget); |
| 439 | 439 | if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE)) |
| 440 | 440 | && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){ |
| @@ -524,11 +524,11 @@ | ||
| 524 | 524 | case 'F': { |
| 525 | 525 | char *zName, *zPerm, *zPriorName; |
| 526 | 526 | zName = next_token(&x,0); |
| 527 | 527 | if( zName==0 ) SYNTAX("missing filename on F-card"); |
| 528 | 528 | defossilize(zName); |
| 529 | - if( !file_is_simple_pathname(zName) ){ | |
| 529 | + if( !file_is_simple_pathname(zName, 0) ){ | |
| 530 | 530 | SYNTAX("F-card filename is not a simple path"); |
| 531 | 531 | } |
| 532 | 532 | zUuid = next_token(&x, &sz); |
| 533 | 533 | if( p->zBaseline==0 || zUuid!=0 ){ |
| 534 | 534 | if( sz!=UUID_SIZE ) SYNTAX("F-card UUID is the wrong size"); |
| @@ -536,11 +536,11 @@ | ||
| 536 | 536 | } |
| 537 | 537 | zPerm = next_token(&x,0); |
| 538 | 538 | zPriorName = next_token(&x,0); |
| 539 | 539 | if( zPriorName ){ |
| 540 | 540 | defossilize(zPriorName); |
| 541 | - if( !file_is_simple_pathname(zPriorName) ){ | |
| 541 | + if( !file_is_simple_pathname(zPriorName, 0) ){ | |
| 542 | 542 | SYNTAX("F-card old filename is not a simple path"); |
| 543 | 543 | } |
| 544 | 544 | } |
| 545 | 545 | if( p->nFile>=p->nFileAlloc ){ |
| 546 | 546 | p->nFileAlloc = p->nFileAlloc*2 + 10; |
| @@ -1983,5 +1983,23 @@ | ||
| 1983 | 1983 | manifest_destroy(p); |
| 1984 | 1984 | } |
| 1985 | 1985 | assert( blob_is_reset(pContent) ); |
| 1986 | 1986 | return 1; |
| 1987 | 1987 | } |
| 1988 | + | |
| 1989 | +/* | |
| 1990 | +** COMMAND: test-crosslink | |
| 1991 | +** | |
| 1992 | +** Usage: %fossil test-crosslink RECORDID | |
| 1993 | +** | |
| 1994 | +** Run the manifest_crosslink() routine on the artifact with the given | |
| 1995 | +** record ID. This is typically done in the debugger. | |
| 1996 | +*/ | |
| 1997 | +void test_crosslink_cmd(void){ | |
| 1998 | + int rid; | |
| 1999 | + Blob content; | |
| 2000 | + db_find_and_open_repository(0, 0); | |
| 2001 | + if( g.argc!=3 ) usage("RECORDID"); | |
| 2002 | + rid = name_to_rid(g.argv[2]); | |
| 2003 | + content_get(rid, &content); | |
| 2004 | + manifest_crosslink(rid, &content); | |
| 2005 | +} | |
| 1988 | 2006 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -430,11 +430,11 @@ | |
| 430 | zTarget = next_token(&x, &nTarget); |
| 431 | zSrc = next_token(&x, &nSrc); |
| 432 | if( zName==0 || zTarget==0 ) goto manifest_syntax_error; |
| 433 | if( p->zAttachName!=0 ) goto manifest_syntax_error; |
| 434 | defossilize(zName); |
| 435 | if( !file_is_simple_pathname(zName) ){ |
| 436 | SYNTAX("invalid filename on A-card"); |
| 437 | } |
| 438 | defossilize(zTarget); |
| 439 | if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE)) |
| 440 | && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){ |
| @@ -524,11 +524,11 @@ | |
| 524 | case 'F': { |
| 525 | char *zName, *zPerm, *zPriorName; |
| 526 | zName = next_token(&x,0); |
| 527 | if( zName==0 ) SYNTAX("missing filename on F-card"); |
| 528 | defossilize(zName); |
| 529 | if( !file_is_simple_pathname(zName) ){ |
| 530 | SYNTAX("F-card filename is not a simple path"); |
| 531 | } |
| 532 | zUuid = next_token(&x, &sz); |
| 533 | if( p->zBaseline==0 || zUuid!=0 ){ |
| 534 | if( sz!=UUID_SIZE ) SYNTAX("F-card UUID is the wrong size"); |
| @@ -536,11 +536,11 @@ | |
| 536 | } |
| 537 | zPerm = next_token(&x,0); |
| 538 | zPriorName = next_token(&x,0); |
| 539 | if( zPriorName ){ |
| 540 | defossilize(zPriorName); |
| 541 | if( !file_is_simple_pathname(zPriorName) ){ |
| 542 | SYNTAX("F-card old filename is not a simple path"); |
| 543 | } |
| 544 | } |
| 545 | if( p->nFile>=p->nFileAlloc ){ |
| 546 | p->nFileAlloc = p->nFileAlloc*2 + 10; |
| @@ -1983,5 +1983,23 @@ | |
| 1983 | manifest_destroy(p); |
| 1984 | } |
| 1985 | assert( blob_is_reset(pContent) ); |
| 1986 | return 1; |
| 1987 | } |
| 1988 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -430,11 +430,11 @@ | |
| 430 | zTarget = next_token(&x, &nTarget); |
| 431 | zSrc = next_token(&x, &nSrc); |
| 432 | if( zName==0 || zTarget==0 ) goto manifest_syntax_error; |
| 433 | if( p->zAttachName!=0 ) goto manifest_syntax_error; |
| 434 | defossilize(zName); |
| 435 | if( !file_is_simple_pathname(zName, 0) ){ |
| 436 | SYNTAX("invalid filename on A-card"); |
| 437 | } |
| 438 | defossilize(zTarget); |
| 439 | if( (nTarget!=UUID_SIZE || !validate16(zTarget, UUID_SIZE)) |
| 440 | && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){ |
| @@ -524,11 +524,11 @@ | |
| 524 | case 'F': { |
| 525 | char *zName, *zPerm, *zPriorName; |
| 526 | zName = next_token(&x,0); |
| 527 | if( zName==0 ) SYNTAX("missing filename on F-card"); |
| 528 | defossilize(zName); |
| 529 | if( !file_is_simple_pathname(zName, 0) ){ |
| 530 | SYNTAX("F-card filename is not a simple path"); |
| 531 | } |
| 532 | zUuid = next_token(&x, &sz); |
| 533 | if( p->zBaseline==0 || zUuid!=0 ){ |
| 534 | if( sz!=UUID_SIZE ) SYNTAX("F-card UUID is the wrong size"); |
| @@ -536,11 +536,11 @@ | |
| 536 | } |
| 537 | zPerm = next_token(&x,0); |
| 538 | zPriorName = next_token(&x,0); |
| 539 | if( zPriorName ){ |
| 540 | defossilize(zPriorName); |
| 541 | if( !file_is_simple_pathname(zPriorName, 0) ){ |
| 542 | SYNTAX("F-card old filename is not a simple path"); |
| 543 | } |
| 544 | } |
| 545 | if( p->nFile>=p->nFileAlloc ){ |
| 546 | p->nFileAlloc = p->nFileAlloc*2 + 10; |
| @@ -1983,5 +1983,23 @@ | |
| 1983 | manifest_destroy(p); |
| 1984 | } |
| 1985 | assert( blob_is_reset(pContent) ); |
| 1986 | return 1; |
| 1987 | } |
| 1988 | |
| 1989 | /* |
| 1990 | ** COMMAND: test-crosslink |
| 1991 | ** |
| 1992 | ** Usage: %fossil test-crosslink RECORDID |
| 1993 | ** |
| 1994 | ** Run the manifest_crosslink() routine on the artifact with the given |
| 1995 | ** record ID. This is typically done in the debugger. |
| 1996 | */ |
| 1997 | void test_crosslink_cmd(void){ |
| 1998 | int rid; |
| 1999 | Blob content; |
| 2000 | db_find_and_open_repository(0, 0); |
| 2001 | if( g.argc!=3 ) usage("RECORDID"); |
| 2002 | rid = name_to_rid(g.argv[2]); |
| 2003 | content_get(rid, &content); |
| 2004 | manifest_crosslink(rid, &content); |
| 2005 | } |
| 2006 |
+1
-1
| --- src/merge.c | ||
| +++ src/merge.c | ||
| @@ -87,11 +87,11 @@ | ||
| 87 | 87 | ** option overrides the "binary-glob" setting. |
| 88 | 88 | ** |
| 89 | 89 | ** --nochange | -n Dryrun: do not actually make any changes; just |
| 90 | 90 | ** show what would have happened. |
| 91 | 91 | ** |
| 92 | -** --case-sensitive BOOL Overwrite the case-sensitive setting. If false, | |
| 92 | +** --case-sensitive BOOL Override the case-sensitive setting. If false, | |
| 93 | 93 | ** files whose names differ only in case are taken |
| 94 | 94 | ** to be the same file. |
| 95 | 95 | ** |
| 96 | 96 | ** --force | -f Force the merge even if it would be a no-op. |
| 97 | 97 | */ |
| 98 | 98 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -87,11 +87,11 @@ | |
| 87 | ** option overrides the "binary-glob" setting. |
| 88 | ** |
| 89 | ** --nochange | -n Dryrun: do not actually make any changes; just |
| 90 | ** show what would have happened. |
| 91 | ** |
| 92 | ** --case-sensitive BOOL Overwrite the case-sensitive setting. If false, |
| 93 | ** files whose names differ only in case are taken |
| 94 | ** to be the same file. |
| 95 | ** |
| 96 | ** --force | -f Force the merge even if it would be a no-op. |
| 97 | */ |
| 98 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -87,11 +87,11 @@ | |
| 87 | ** option overrides the "binary-glob" setting. |
| 88 | ** |
| 89 | ** --nochange | -n Dryrun: do not actually make any changes; just |
| 90 | ** show what would have happened. |
| 91 | ** |
| 92 | ** --case-sensitive BOOL Override the case-sensitive setting. If false, |
| 93 | ** files whose names differ only in case are taken |
| 94 | ** to be the same file. |
| 95 | ** |
| 96 | ** --force | -f Force the merge even if it would be a no-op. |
| 97 | */ |
| 98 |
+2
-2
| --- src/merge3.c | ||
| +++ src/merge3.c | ||
| @@ -175,12 +175,12 @@ | ||
| 175 | 175 | ** is the number of lines of text to copy directly from the pivot, |
| 176 | 176 | ** the second integer is the number of lines of text to omit from the |
| 177 | 177 | ** pivot, and the third integer is the number of lines of text that are |
| 178 | 178 | ** inserted. The edit array ends with a triple of 0,0,0. |
| 179 | 179 | */ |
| 180 | - aC1 = text_diff(pPivot, pV1, 0, 0); | |
| 181 | - aC2 = text_diff(pPivot, pV2, 0, 0); | |
| 180 | + aC1 = text_diff(pPivot, pV1, 0, 0, 0); | |
| 181 | + aC2 = text_diff(pPivot, pV2, 0, 0, 0); | |
| 182 | 182 | if( aC1==0 || aC2==0 ){ |
| 183 | 183 | free(aC1); |
| 184 | 184 | free(aC2); |
| 185 | 185 | return -1; |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | 188 | ADDED src/regexp.c |
| --- src/merge3.c | |
| +++ src/merge3.c | |
| @@ -175,12 +175,12 @@ | |
| 175 | ** is the number of lines of text to copy directly from the pivot, |
| 176 | ** the second integer is the number of lines of text to omit from the |
| 177 | ** pivot, and the third integer is the number of lines of text that are |
| 178 | ** inserted. The edit array ends with a triple of 0,0,0. |
| 179 | */ |
| 180 | aC1 = text_diff(pPivot, pV1, 0, 0); |
| 181 | aC2 = text_diff(pPivot, pV2, 0, 0); |
| 182 | if( aC1==0 || aC2==0 ){ |
| 183 | free(aC1); |
| 184 | free(aC2); |
| 185 | return -1; |
| 186 | } |
| 187 | |
| 188 | DDED src/regexp.c |
| --- src/merge3.c | |
| +++ src/merge3.c | |
| @@ -175,12 +175,12 @@ | |
| 175 | ** is the number of lines of text to copy directly from the pivot, |
| 176 | ** the second integer is the number of lines of text to omit from the |
| 177 | ** pivot, and the third integer is the number of lines of text that are |
| 178 | ** inserted. The edit array ends with a triple of 0,0,0. |
| 179 | */ |
| 180 | aC1 = text_diff(pPivot, pV1, 0, 0, 0); |
| 181 | aC2 = text_diff(pPivot, pV2, 0, 0, 0); |
| 182 | if( aC1==0 || aC2==0 ){ |
| 183 | free(aC1); |
| 184 | free(aC2); |
| 185 | return -1; |
| 186 | } |
| 187 | |
| 188 | DDED src/regexp.c |
+55
| --- a/src/regexp.c | ||
| +++ b/src/regexp.c | ||
| @@ -0,0 +1,55 @@ | ||
| 1 | +/* | |
| 2 | +** Co#ifndef SQL(sizeof(aSp* | |
| 3 | +** Co#ifndef SQLITE_MAX_REGEXP_REPEAT | |
| 4 | +# define SQLITE_MAX_REGEXP_REPEAT 999 | |
| 5 | +#endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA. | |
| 6 | +*/ | |
| 7 | +int re_maxlen(void){ | |
| 8 | + return 1000) : 1000; | |
| 9 | +}re_maxlen(), noCase) Co0); | |
| 10 | + /, 0 <= p,q <= 999* | |
| 11 | +** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax | |
| 12 | +** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1 | |
| 13 | +*/ | |
| 14 | +static void grepprintfREPEAT | |
| 15 | +# define SQLITE_MAX_REGEXP_REPEAT 999 | |
| 16 | +#endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA. | |
| 17 | +*/ | |
| 18 | +int re_maxlen(void){ | |
| 19 | + return 1000) : 1000; | |
| 20 | +}re_maxlen(), noCase) Co0); | |
| 21 | + /, 0 <= p,q <= 999* | |
| 22 | +** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax | |
| 23 | +** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1 | |
| 24 | +*/ | |
| 25 | +static void grepprintf har const | |
| 26 | + int argc, resqlite3char zInit[12]; | |
| 27 | +** Co#ifnde** Co#ifndef SQLITE_MAX_REGEXP_REPEAT | |
| 28 | +# define SQLITE_MAX_REGEXP_REPEAT 999 | |
| 29 | +#endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA. | |
| 30 | +*/ | |
| 31 | +int re_maxlen(void){ | |
| 32 | + return 1000) : 1000; | |
| 33 | +}re_maxlen(), noCase) Co0); | |
| 34 | + /, 0 <= p,q <= 999* | |
| 35 | +** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax | |
| 36 | +** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1 | |
| 37 | +*/ | |
| 38 | +static void grepprintfREPEAT | |
| 39 | +# define SQLITE_MAX_REGEXP_REPEAT 999 | |
| 40 | +#endifcharacter3CC_INC>0 &&ute a reasonable limit on X Where XXX is any number ofn the length of the REGEXP NF | |
| 41 | + return 1000) : 1000; | |
| 42 | +}re_maxlen(), noCase) Co0); | |
| 43 | + /, 0 <= p,q <= 999* | |
| 44 | +** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax | |
| 45 | +** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1 | |
| 46 | +*/ | |
| 47 | +static void grepprintf har const | |
| 48 | + int argc, resqlite3 strncmp(zIn+in.i, mem if( re_hex(zIn[1],&v) ){ | |
| 49 | + += 3v; | |
| 50 | + }5v = 0; | |
| 51 | +v = 0; | |
| 52 | + for(i=1; p->sIn.i<p->sIn.mx && re_hex(p->sIn.z[p->sIn.i+i], &v); i++){} | |
| 53 | + if( i>1 ){ | |
| 54 | +{ | |
| 55 | + return 1000) :/ |
| --- a/src/regexp.c | |
| +++ b/src/regexp.c | |
| @@ -0,0 +1,55 @@ | |
| --- a/src/regexp.c | |
| +++ b/src/regexp.c | |
| @@ -0,0 +1,55 @@ | |
| 1 | /* |
| 2 | ** Co#ifndef SQL(sizeof(aSp* |
| 3 | ** Co#ifndef SQLITE_MAX_REGEXP_REPEAT |
| 4 | # define SQLITE_MAX_REGEXP_REPEAT 999 |
| 5 | #endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA. |
| 6 | */ |
| 7 | int re_maxlen(void){ |
| 8 | return 1000) : 1000; |
| 9 | }re_maxlen(), noCase) Co0); |
| 10 | /, 0 <= p,q <= 999* |
| 11 | ** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax |
| 12 | ** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1 |
| 13 | */ |
| 14 | static void grepprintfREPEAT |
| 15 | # define SQLITE_MAX_REGEXP_REPEAT 999 |
| 16 | #endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA. |
| 17 | */ |
| 18 | int re_maxlen(void){ |
| 19 | return 1000) : 1000; |
| 20 | }re_maxlen(), noCase) Co0); |
| 21 | /, 0 <= p,q <= 999* |
| 22 | ** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax |
| 23 | ** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1 |
| 24 | */ |
| 25 | static void grepprintf har const |
| 26 | int argc, resqlite3char zInit[12]; |
| 27 | ** Co#ifnde** Co#ifndef SQLITE_MAX_REGEXP_REPEAT |
| 28 | # define SQLITE_MAX_REGEXP_REPEAT 999 |
| 29 | #endifcharacter3CC_INC>0 &&ute a reasonable limit on the length of the REGEXP NFA. |
| 30 | */ |
| 31 | int re_maxlen(void){ |
| 32 | return 1000) : 1000; |
| 33 | }re_maxlen(), noCase) Co0); |
| 34 | /, 0 <= p,q <= 999* |
| 35 | ** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax |
| 36 | ** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1 |
| 37 | */ |
| 38 | static void grepprintfREPEAT |
| 39 | # define SQLITE_MAX_REGEXP_REPEAT 999 |
| 40 | #endifcharacter3CC_INC>0 &&ute a reasonable limit on X Where XXX is any number ofn the length of the REGEXP NF |
| 41 | return 1000) : 1000; |
| 42 | }re_maxlen(), noCase) Co0); |
| 43 | /, 0 <= p,q <= 999* |
| 44 | ** To help prevent DoS attacks, the values of p and q in the "{p,q}" syntax |
| 45 | ** are limited to SQLITE_MAX_REGEXP_REPEAT, default 999 return 1; return 1 |
| 46 | */ |
| 47 | static void grepprintf har const |
| 48 | int argc, resqlite3 strncmp(zIn+in.i, mem if( re_hex(zIn[1],&v) ){ |
| 49 | += 3v; |
| 50 | }5v = 0; |
| 51 | v = 0; |
| 52 | for(i=1; p->sIn.i<p->sIn.mx && re_hex(p->sIn.z[p->sIn.i+i], &v); i++){} |
| 53 | if( i>1 ){ |
| 54 | { |
| 55 | return 1000) :/ |
+1
| --- src/report.c | ||
| +++ src/report.c | ||
| @@ -172,10 +172,11 @@ | ||
| 172 | 172 | break; |
| 173 | 173 | } |
| 174 | 174 | case SQLITE_READ: { |
| 175 | 175 | static const char *const azAllowed[] = { |
| 176 | 176 | "ticket", |
| 177 | + "ticketchng", | |
| 177 | 178 | "blob", |
| 178 | 179 | "filename", |
| 179 | 180 | "mlink", |
| 180 | 181 | "plink", |
| 181 | 182 | "event", |
| 182 | 183 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -172,10 +172,11 @@ | |
| 172 | break; |
| 173 | } |
| 174 | case SQLITE_READ: { |
| 175 | static const char *const azAllowed[] = { |
| 176 | "ticket", |
| 177 | "blob", |
| 178 | "filename", |
| 179 | "mlink", |
| 180 | "plink", |
| 181 | "event", |
| 182 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -172,10 +172,11 @@ | |
| 172 | break; |
| 173 | } |
| 174 | case SQLITE_READ: { |
| 175 | static const char *const azAllowed[] = { |
| 176 | "ticket", |
| 177 | "ticketchng", |
| 178 | "blob", |
| 179 | "filename", |
| 180 | "mlink", |
| 181 | "plink", |
| 182 | "event", |
| 183 |
+47
-1
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -94,11 +94,11 @@ | ||
| 94 | 94 | "Edit HTML text inserted at the top of every page"); |
| 95 | 95 | setup_menu_entry("Footer", "setup_footer", |
| 96 | 96 | "Edit HTML text inserted at the bottom of every page"); |
| 97 | 97 | setup_menu_entry("Moderation", "setup_modreq", |
| 98 | 98 | "Enable/Disable requiring moderator approval of Wiki and/or Ticket" |
| 99 | - "edits and attachments."); | |
| 99 | + " changes and attachments."); | |
| 100 | 100 | setup_menu_entry("Ad-Unit", "setup_adunit", |
| 101 | 101 | "Edit HTML text for an ad unit inserted after the menu bar"); |
| 102 | 102 | setup_menu_entry("Logo", "setup_logo", |
| 103 | 103 | "Change the logo and background images for the server"); |
| 104 | 104 | setup_menu_entry("Shunned", "shun", |
| @@ -109,10 +109,12 @@ | ||
| 109 | 109 | "A record of login attempts"); |
| 110 | 110 | setup_menu_entry("Stats", "stat", |
| 111 | 111 | "Display repository statistics"); |
| 112 | 112 | setup_menu_entry("SQL", "admin_sql", |
| 113 | 113 | "Enter raw SQL commands"); |
| 114 | + setup_menu_entry("TH1", "admin_th1", | |
| 115 | + "Enter raw TH1 commands"); | |
| 114 | 116 | @ </table> |
| 115 | 117 | |
| 116 | 118 | style_footer(); |
| 117 | 119 | } |
| 118 | 120 | |
| @@ -1759,8 +1761,52 @@ | ||
| 1759 | 1761 | @ </tr> |
| 1760 | 1762 | } |
| 1761 | 1763 | sqlite3_finalize(pStmt); |
| 1762 | 1764 | @ </table> |
| 1763 | 1765 | } |
| 1766 | + } | |
| 1767 | + style_footer(); | |
| 1768 | +} | |
| 1769 | + | |
| 1770 | + | |
| 1771 | +/* | |
| 1772 | +** WEBPAGE: admin_th1 | |
| 1773 | +** | |
| 1774 | +** Run raw TH1 commands using the web interface. If Tcl integration was | |
| 1775 | +** enabled at compile-time and the "tcl" setting is enabled, Tcl commands | |
| 1776 | +** may be run as well. | |
| 1777 | +*/ | |
| 1778 | +void th1_page(void){ | |
| 1779 | + const char *zQ = P("q"); | |
| 1780 | + int go = P("go")!=0; | |
| 1781 | + login_check_credentials(); | |
| 1782 | + if( !g.perm.Setup ){ | |
| 1783 | + login_needed(); | |
| 1784 | + } | |
| 1785 | + db_begin_transaction(); | |
| 1786 | + style_header("Raw TH1 Commands"); | |
| 1787 | + @ <p><b>Caution:</b> There are no restrictions on the TH1 that can be | |
| 1788 | + @ run by this page. If Tcl integration was enabled at compile-time and | |
| 1789 | + @ the "tcl" setting is enabled, Tcl commands may be run as well.</p> | |
| 1790 | + @ | |
| 1791 | + @ <form method="post" action="%s(g.zTop)/admin_th1"> | |
| 1792 | + login_insert_csrf_secret(); | |
| 1793 | + @ TH1:<br /> | |
| 1794 | + @ <textarea name="q" rows="5" cols="80">%h(zQ)</textarea><br /> | |
| 1795 | + @ <input type="submit" name="go" value="Run TH1"> | |
| 1796 | + @ </form> | |
| 1797 | + if( go ){ | |
| 1798 | + const char *zR; | |
| 1799 | + int rc; | |
| 1800 | + int n; | |
| 1801 | + @ <hr /> | |
| 1802 | + login_verify_csrf_secret(); | |
| 1803 | + rc = Th_Eval(g.interp, 0, zQ, -1); | |
| 1804 | + zR = Th_GetResult(g.interp, &n); | |
| 1805 | + if( rc==TH_OK ){ | |
| 1806 | + @ <pre class="th1result">%h(zR)</pre> | |
| 1807 | + }else{ | |
| 1808 | + @ <pre class="th1error">%h(zR)</pre> | |
| 1809 | + } | |
| 1764 | 1810 | } |
| 1765 | 1811 | style_footer(); |
| 1766 | 1812 | } |
| 1767 | 1813 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -94,11 +94,11 @@ | |
| 94 | "Edit HTML text inserted at the top of every page"); |
| 95 | setup_menu_entry("Footer", "setup_footer", |
| 96 | "Edit HTML text inserted at the bottom of every page"); |
| 97 | setup_menu_entry("Moderation", "setup_modreq", |
| 98 | "Enable/Disable requiring moderator approval of Wiki and/or Ticket" |
| 99 | "edits and attachments."); |
| 100 | setup_menu_entry("Ad-Unit", "setup_adunit", |
| 101 | "Edit HTML text for an ad unit inserted after the menu bar"); |
| 102 | setup_menu_entry("Logo", "setup_logo", |
| 103 | "Change the logo and background images for the server"); |
| 104 | setup_menu_entry("Shunned", "shun", |
| @@ -109,10 +109,12 @@ | |
| 109 | "A record of login attempts"); |
| 110 | setup_menu_entry("Stats", "stat", |
| 111 | "Display repository statistics"); |
| 112 | setup_menu_entry("SQL", "admin_sql", |
| 113 | "Enter raw SQL commands"); |
| 114 | @ </table> |
| 115 | |
| 116 | style_footer(); |
| 117 | } |
| 118 | |
| @@ -1759,8 +1761,52 @@ | |
| 1759 | @ </tr> |
| 1760 | } |
| 1761 | sqlite3_finalize(pStmt); |
| 1762 | @ </table> |
| 1763 | } |
| 1764 | } |
| 1765 | style_footer(); |
| 1766 | } |
| 1767 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -94,11 +94,11 @@ | |
| 94 | "Edit HTML text inserted at the top of every page"); |
| 95 | setup_menu_entry("Footer", "setup_footer", |
| 96 | "Edit HTML text inserted at the bottom of every page"); |
| 97 | setup_menu_entry("Moderation", "setup_modreq", |
| 98 | "Enable/Disable requiring moderator approval of Wiki and/or Ticket" |
| 99 | " changes and attachments."); |
| 100 | setup_menu_entry("Ad-Unit", "setup_adunit", |
| 101 | "Edit HTML text for an ad unit inserted after the menu bar"); |
| 102 | setup_menu_entry("Logo", "setup_logo", |
| 103 | "Change the logo and background images for the server"); |
| 104 | setup_menu_entry("Shunned", "shun", |
| @@ -109,10 +109,12 @@ | |
| 109 | "A record of login attempts"); |
| 110 | setup_menu_entry("Stats", "stat", |
| 111 | "Display repository statistics"); |
| 112 | setup_menu_entry("SQL", "admin_sql", |
| 113 | "Enter raw SQL commands"); |
| 114 | setup_menu_entry("TH1", "admin_th1", |
| 115 | "Enter raw TH1 commands"); |
| 116 | @ </table> |
| 117 | |
| 118 | style_footer(); |
| 119 | } |
| 120 | |
| @@ -1759,8 +1761,52 @@ | |
| 1761 | @ </tr> |
| 1762 | } |
| 1763 | sqlite3_finalize(pStmt); |
| 1764 | @ </table> |
| 1765 | } |
| 1766 | } |
| 1767 | style_footer(); |
| 1768 | } |
| 1769 | |
| 1770 | |
| 1771 | /* |
| 1772 | ** WEBPAGE: admin_th1 |
| 1773 | ** |
| 1774 | ** Run raw TH1 commands using the web interface. If Tcl integration was |
| 1775 | ** enabled at compile-time and the "tcl" setting is enabled, Tcl commands |
| 1776 | ** may be run as well. |
| 1777 | */ |
| 1778 | void th1_page(void){ |
| 1779 | const char *zQ = P("q"); |
| 1780 | int go = P("go")!=0; |
| 1781 | login_check_credentials(); |
| 1782 | if( !g.perm.Setup ){ |
| 1783 | login_needed(); |
| 1784 | } |
| 1785 | db_begin_transaction(); |
| 1786 | style_header("Raw TH1 Commands"); |
| 1787 | @ <p><b>Caution:</b> There are no restrictions on the TH1 that can be |
| 1788 | @ run by this page. If Tcl integration was enabled at compile-time and |
| 1789 | @ the "tcl" setting is enabled, Tcl commands may be run as well.</p> |
| 1790 | @ |
| 1791 | @ <form method="post" action="%s(g.zTop)/admin_th1"> |
| 1792 | login_insert_csrf_secret(); |
| 1793 | @ TH1:<br /> |
| 1794 | @ <textarea name="q" rows="5" cols="80">%h(zQ)</textarea><br /> |
| 1795 | @ <input type="submit" name="go" value="Run TH1"> |
| 1796 | @ </form> |
| 1797 | if( go ){ |
| 1798 | const char *zR; |
| 1799 | int rc; |
| 1800 | int n; |
| 1801 | @ <hr /> |
| 1802 | login_verify_csrf_secret(); |
| 1803 | rc = Th_Eval(g.interp, 0, zQ, -1); |
| 1804 | zR = Th_GetResult(g.interp, &n); |
| 1805 | if( rc==TH_OK ){ |
| 1806 | @ <pre class="th1result">%h(zR)</pre> |
| 1807 | }else{ |
| 1808 | @ <pre class="th1error">%h(zR)</pre> |
| 1809 | } |
| 1810 | } |
| 1811 | style_footer(); |
| 1812 | } |
| 1813 |
+6
| --- src/shell.c | ||
| +++ src/shell.c | ||
| @@ -1477,10 +1477,16 @@ | ||
| 1477 | 1477 | p->zDbFilename, sqlite3_errmsg(db)); |
| 1478 | 1478 | exit(1); |
| 1479 | 1479 | } |
| 1480 | 1480 | #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| 1481 | 1481 | sqlite3_enable_load_extension(p->db, 1); |
| 1482 | +#endif | |
| 1483 | +#ifdef SQLITE_ENABLE_REGEXP | |
| 1484 | + { | |
| 1485 | + extern int sqlite3_add_regexp_func(sqlite3*); | |
| 1486 | + sqlite3_add_regexp_func(db); | |
| 1487 | + } | |
| 1482 | 1488 | #endif |
| 1483 | 1489 | } |
| 1484 | 1490 | } |
| 1485 | 1491 | |
| 1486 | 1492 | /* |
| 1487 | 1493 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -1477,10 +1477,16 @@ | |
| 1477 | p->zDbFilename, sqlite3_errmsg(db)); |
| 1478 | exit(1); |
| 1479 | } |
| 1480 | #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| 1481 | sqlite3_enable_load_extension(p->db, 1); |
| 1482 | #endif |
| 1483 | } |
| 1484 | } |
| 1485 | |
| 1486 | /* |
| 1487 |
| --- src/shell.c | |
| +++ src/shell.c | |
| @@ -1477,10 +1477,16 @@ | |
| 1477 | p->zDbFilename, sqlite3_errmsg(db)); |
| 1478 | exit(1); |
| 1479 | } |
| 1480 | #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| 1481 | sqlite3_enable_load_extension(p->db, 1); |
| 1482 | #endif |
| 1483 | #ifdef SQLITE_ENABLE_REGEXP |
| 1484 | { |
| 1485 | extern int sqlite3_add_regexp_func(sqlite3*); |
| 1486 | sqlite3_add_regexp_func(db); |
| 1487 | } |
| 1488 | #endif |
| 1489 | } |
| 1490 | } |
| 1491 | |
| 1492 | /* |
| 1493 |
+12
-7
| --- src/skins.c | ||
| +++ src/skins.c | ||
| @@ -355,12 +355,13 @@ | ||
| 355 | 355 | @ div.footer a:visited { color: white; } |
| 356 | 356 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 357 | 357 | @ |
| 358 | 358 | @ /* <verbatim> blocks */ |
| 359 | 359 | @ pre.verbatim { |
| 360 | -@ background-color: #f5f5f5; | |
| 361 | -@ padding: 0.5em; | |
| 360 | +@ background-color: #f5f5f5; | |
| 361 | +@ padding: 0.5em; | |
| 362 | +@ white-space: pre-wrap; | |
| 362 | 363 | @ } |
| 363 | 364 | @ |
| 364 | 365 | @ /* The label/value pairs on (for example) the ci page */ |
| 365 | 366 | @ table.label-value th { |
| 366 | 367 | @ vertical-align: top; |
| @@ -595,12 +596,13 @@ | ||
| 595 | 596 | @ color: #555; |
| 596 | 597 | @ } |
| 597 | 598 | @ |
| 598 | 599 | @ /* <verbatim> blocks */ |
| 599 | 600 | @ pre.verbatim { |
| 600 | -@ background-color: #f5f5f5; | |
| 601 | -@ padding: 0.5em; | |
| 601 | +@ background-color: #f5f5f5; | |
| 602 | +@ padding: 0.5em; | |
| 603 | +@ white-space: pre-wrap; | |
| 602 | 604 | @ } |
| 603 | 605 | @ |
| 604 | 606 | @ /* The label/value pairs on (for example) the ci page */ |
| 605 | 607 | @ table.label-value th { |
| 606 | 608 | @ vertical-align: top; |
| @@ -1083,13 +1085,14 @@ | ||
| 1083 | 1085 | @ div.footer a:visited { color: white; } |
| 1084 | 1086 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 1085 | 1087 | @ |
| 1086 | 1088 | @ /* verbatim blocks */ |
| 1087 | 1089 | @ pre.verbatim { |
| 1088 | -@ background-color: #f5f5f5; | |
| 1089 | -@ padding: 0.5em; | |
| 1090 | -@} | |
| 1090 | +@ background-color: #f5f5f5; | |
| 1091 | +@ padding: 0.5em; | |
| 1092 | +@ white-space: pre-wrap; | |
| 1093 | +@ } | |
| 1091 | 1094 | @ |
| 1092 | 1095 | @ /* The label/value pairs on (for example) the ci page */ |
| 1093 | 1096 | @ table.label-value th { |
| 1094 | 1097 | @ vertical-align: top; |
| 1095 | 1098 | @ text-align: right; |
| @@ -1226,10 +1229,12 @@ | ||
| 1226 | 1229 | @ } |
| 1227 | 1230 | @ set version [getVersion $manifest_version] |
| 1228 | 1231 | @ set tclVersion [getTclVersion] |
| 1229 | 1232 | @ set fossilUrl http://www.fossil-scm.org |
| 1230 | 1233 | @ </th1> |
| 1234 | +@ This page was generated in about | |
| 1235 | +@ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by | |
| 1231 | 1236 | @ <a href="$fossilUrl/">Fossil</a> |
| 1232 | 1237 | @ version $release_version $tclVersion |
| 1233 | 1238 | @ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a> |
| 1234 | 1239 | @ <a href="$fossilUrl/fossil/timeline?c=$manifest_date&y=ci">$manifest_date</a> |
| 1235 | 1240 | @ </div> |
| 1236 | 1241 |
| --- src/skins.c | |
| +++ src/skins.c | |
| @@ -355,12 +355,13 @@ | |
| 355 | @ div.footer a:visited { color: white; } |
| 356 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 357 | @ |
| 358 | @ /* <verbatim> blocks */ |
| 359 | @ pre.verbatim { |
| 360 | @ background-color: #f5f5f5; |
| 361 | @ padding: 0.5em; |
| 362 | @ } |
| 363 | @ |
| 364 | @ /* The label/value pairs on (for example) the ci page */ |
| 365 | @ table.label-value th { |
| 366 | @ vertical-align: top; |
| @@ -595,12 +596,13 @@ | |
| 595 | @ color: #555; |
| 596 | @ } |
| 597 | @ |
| 598 | @ /* <verbatim> blocks */ |
| 599 | @ pre.verbatim { |
| 600 | @ background-color: #f5f5f5; |
| 601 | @ padding: 0.5em; |
| 602 | @ } |
| 603 | @ |
| 604 | @ /* The label/value pairs on (for example) the ci page */ |
| 605 | @ table.label-value th { |
| 606 | @ vertical-align: top; |
| @@ -1083,13 +1085,14 @@ | |
| 1083 | @ div.footer a:visited { color: white; } |
| 1084 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 1085 | @ |
| 1086 | @ /* verbatim blocks */ |
| 1087 | @ pre.verbatim { |
| 1088 | @ background-color: #f5f5f5; |
| 1089 | @ padding: 0.5em; |
| 1090 | @} |
| 1091 | @ |
| 1092 | @ /* The label/value pairs on (for example) the ci page */ |
| 1093 | @ table.label-value th { |
| 1094 | @ vertical-align: top; |
| 1095 | @ text-align: right; |
| @@ -1226,10 +1229,12 @@ | |
| 1226 | @ } |
| 1227 | @ set version [getVersion $manifest_version] |
| 1228 | @ set tclVersion [getTclVersion] |
| 1229 | @ set fossilUrl http://www.fossil-scm.org |
| 1230 | @ </th1> |
| 1231 | @ <a href="$fossilUrl/">Fossil</a> |
| 1232 | @ version $release_version $tclVersion |
| 1233 | @ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a> |
| 1234 | @ <a href="$fossilUrl/fossil/timeline?c=$manifest_date&y=ci">$manifest_date</a> |
| 1235 | @ </div> |
| 1236 |
| --- src/skins.c | |
| +++ src/skins.c | |
| @@ -355,12 +355,13 @@ | |
| 355 | @ div.footer a:visited { color: white; } |
| 356 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 357 | @ |
| 358 | @ /* <verbatim> blocks */ |
| 359 | @ pre.verbatim { |
| 360 | @ background-color: #f5f5f5; |
| 361 | @ padding: 0.5em; |
| 362 | @ white-space: pre-wrap; |
| 363 | @ } |
| 364 | @ |
| 365 | @ /* The label/value pairs on (for example) the ci page */ |
| 366 | @ table.label-value th { |
| 367 | @ vertical-align: top; |
| @@ -595,12 +596,13 @@ | |
| 596 | @ color: #555; |
| 597 | @ } |
| 598 | @ |
| 599 | @ /* <verbatim> blocks */ |
| 600 | @ pre.verbatim { |
| 601 | @ background-color: #f5f5f5; |
| 602 | @ padding: 0.5em; |
| 603 | @ white-space: pre-wrap; |
| 604 | @ } |
| 605 | @ |
| 606 | @ /* The label/value pairs on (for example) the ci page */ |
| 607 | @ table.label-value th { |
| 608 | @ vertical-align: top; |
| @@ -1083,13 +1085,14 @@ | |
| 1085 | @ div.footer a:visited { color: white; } |
| 1086 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 1087 | @ |
| 1088 | @ /* verbatim blocks */ |
| 1089 | @ pre.verbatim { |
| 1090 | @ background-color: #f5f5f5; |
| 1091 | @ padding: 0.5em; |
| 1092 | @ white-space: pre-wrap; |
| 1093 | @ } |
| 1094 | @ |
| 1095 | @ /* The label/value pairs on (for example) the ci page */ |
| 1096 | @ table.label-value th { |
| 1097 | @ vertical-align: top; |
| 1098 | @ text-align: right; |
| @@ -1226,10 +1229,12 @@ | |
| 1229 | @ } |
| 1230 | @ set version [getVersion $manifest_version] |
| 1231 | @ set tclVersion [getTclVersion] |
| 1232 | @ set fossilUrl http://www.fossil-scm.org |
| 1233 | @ </th1> |
| 1234 | @ This page was generated in about |
| 1235 | @ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by |
| 1236 | @ <a href="$fossilUrl/">Fossil</a> |
| 1237 | @ version $release_version $tclVersion |
| 1238 | @ <a href="$fossilUrl/index.html/info/$version">$manifest_version</a> |
| 1239 | @ <a href="$fossilUrl/fossil/timeline?c=$manifest_date&y=ci">$manifest_date</a> |
| 1240 | @ </div> |
| 1241 |
+1
| --- src/sqlcmd.c | ||
| +++ src/sqlcmd.c | ||
| @@ -118,10 +118,11 @@ | ||
| 118 | 118 | sqlcmd_content, 0, 0); |
| 119 | 119 | sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0, |
| 120 | 120 | sqlcmd_compress, 0, 0); |
| 121 | 121 | sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0, |
| 122 | 122 | sqlcmd_decompress, 0, 0); |
| 123 | + re_add_sql_func(db); | |
| 123 | 124 | g.repositoryOpen = 1; |
| 124 | 125 | g.db = db; |
| 125 | 126 | return SQLITE_OK; |
| 126 | 127 | } |
| 127 | 128 | |
| 128 | 129 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -118,10 +118,11 @@ | |
| 118 | sqlcmd_content, 0, 0); |
| 119 | sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0, |
| 120 | sqlcmd_compress, 0, 0); |
| 121 | sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0, |
| 122 | sqlcmd_decompress, 0, 0); |
| 123 | g.repositoryOpen = 1; |
| 124 | g.db = db; |
| 125 | return SQLITE_OK; |
| 126 | } |
| 127 | |
| 128 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -118,10 +118,11 @@ | |
| 118 | sqlcmd_content, 0, 0); |
| 119 | sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0, |
| 120 | sqlcmd_compress, 0, 0); |
| 121 | sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0, |
| 122 | sqlcmd_decompress, 0, 0); |
| 123 | re_add_sql_func(db); |
| 124 | g.repositoryOpen = 1; |
| 125 | g.db = db; |
| 126 | return SQLITE_OK; |
| 127 | } |
| 128 | |
| 129 |
+844
-470
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | -** version 3.7.15. By combining all the individual C code files into this | |
| 3 | +** version 3.7.16. By combining all the individual C code files into this | |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| @@ -671,13 +671,13 @@ | ||
| 671 | 671 | ** |
| 672 | 672 | ** See also: [sqlite3_libversion()], |
| 673 | 673 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 674 | 674 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 675 | 675 | */ |
| 676 | -#define SQLITE_VERSION "3.7.15" | |
| 677 | -#define SQLITE_VERSION_NUMBER 3007015 | |
| 678 | -#define SQLITE_SOURCE_ID "2012-10-16 23:08:28 f021559d8a23934e3bdccad5b55fc7a91d185f53" | |
| 676 | +#define SQLITE_VERSION "3.7.16" | |
| 677 | +#define SQLITE_VERSION_NUMBER 3007016 | |
| 678 | +#define SQLITE_SOURCE_ID "2012-12-08 06:46:05 e65db42c9fdc1d6f257c8db54a46ee4fc0d7aaf0" | |
| 679 | 679 | |
| 680 | 680 | /* |
| 681 | 681 | ** CAPI3REF: Run-Time Library Version Numbers |
| 682 | 682 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 683 | 683 | ** |
| @@ -2162,11 +2162,11 @@ | ||
| 2162 | 2162 | ** database connection is opened. By default, URI handling is globally |
| 2163 | 2163 | ** disabled. The default value may be changed by compiling with the |
| 2164 | 2164 | ** [SQLITE_USE_URI] symbol defined. |
| 2165 | 2165 | ** |
| 2166 | 2166 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 2167 | -** <dd> This option taks a single integer argument which is interpreted as | |
| 2167 | +** <dd> This option takes a single integer argument which is interpreted as | |
| 2168 | 2168 | ** a boolean in order to enable or disable the use of covering indices for |
| 2169 | 2169 | ** full table scans in the query optimizer. The default setting is determined |
| 2170 | 2170 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 2171 | 2171 | ** if that compile-time option is omitted. |
| 2172 | 2172 | ** The ability to disable the use of covering indices for full table scans |
| @@ -10573,24 +10573,24 @@ | ||
| 10573 | 10573 | ** and the value of Index.onError indicate the which conflict resolution |
| 10574 | 10574 | ** algorithm to employ whenever an attempt is made to insert a non-unique |
| 10575 | 10575 | ** element. |
| 10576 | 10576 | */ |
| 10577 | 10577 | struct Index { |
| 10578 | - char *zName; /* Name of this index */ | |
| 10579 | - int *aiColumn; /* Which columns are used by this index. 1st is 0 */ | |
| 10580 | - tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ | |
| 10581 | - Table *pTable; /* The SQL table being indexed */ | |
| 10582 | - char *zColAff; /* String defining the affinity of each column */ | |
| 10583 | - Index *pNext; /* The next index associated with the same table */ | |
| 10584 | - Schema *pSchema; /* Schema containing this index */ | |
| 10585 | - u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ | |
| 10586 | - char **azColl; /* Array of collation sequence names for index */ | |
| 10587 | - int nColumn; /* Number of columns in the table used by this index */ | |
| 10588 | - int tnum; /* Page containing root of this index in database file */ | |
| 10589 | - u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ | |
| 10590 | - u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ | |
| 10591 | - u8 bUnordered; /* Use this index for == or IN queries only */ | |
| 10578 | + char *zName; /* Name of this index */ | |
| 10579 | + int *aiColumn; /* Which columns are used by this index. 1st is 0 */ | |
| 10580 | + tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ | |
| 10581 | + Table *pTable; /* The SQL table being indexed */ | |
| 10582 | + char *zColAff; /* String defining the affinity of each column */ | |
| 10583 | + Index *pNext; /* The next index associated with the same table */ | |
| 10584 | + Schema *pSchema; /* Schema containing this index */ | |
| 10585 | + u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ | |
| 10586 | + char **azColl; /* Array of collation sequence names for index */ | |
| 10587 | + int tnum; /* DB Page containing root of this index */ | |
| 10588 | + u16 nColumn; /* Number of columns in table used by this index */ | |
| 10589 | + u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ | |
| 10590 | + unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ | |
| 10591 | + unsigned bUnordered:1; /* Use this index for == or IN queries only */ | |
| 10592 | 10592 | #ifdef SQLITE_ENABLE_STAT3 |
| 10593 | 10593 | int nSample; /* Number of elements in aSample[] */ |
| 10594 | 10594 | tRowcnt avgEq; /* Average nEq value for key values not in aSample */ |
| 10595 | 10595 | IndexSample *aSample; /* Samples of the left-most key */ |
| 10596 | 10596 | #endif |
| @@ -10767,11 +10767,10 @@ | ||
| 10767 | 10767 | Expr *pRight; /* Right subnode */ |
| 10768 | 10768 | union { |
| 10769 | 10769 | ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */ |
| 10770 | 10770 | Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */ |
| 10771 | 10771 | } x; |
| 10772 | - CollSeq *pColl; /* The collation type of the column or 0 */ | |
| 10773 | 10772 | |
| 10774 | 10773 | /* If the EP_Reduced flag is set in the Expr.flags mask, then no |
| 10775 | 10774 | ** space is allocated for the fields below this point. An attempt to |
| 10776 | 10775 | ** access them will result in a segfault or malfunction. |
| 10777 | 10776 | *********************************************************************/ |
| @@ -10803,11 +10802,11 @@ | ||
| 10803 | 10802 | #define EP_Error 0x0008 /* Expression contains one or more errors */ |
| 10804 | 10803 | #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ |
| 10805 | 10804 | #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ |
| 10806 | 10805 | #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ |
| 10807 | 10806 | #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ |
| 10808 | -#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ | |
| 10807 | +#define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */ | |
| 10809 | 10808 | #define EP_FixedDest 0x0200 /* Result needed in a specific register */ |
| 10810 | 10809 | #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */ |
| 10811 | 10810 | #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */ |
| 10812 | 10811 | #define EP_Hint 0x1000 /* Not used */ |
| 10813 | 10812 | #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ |
| @@ -10861,22 +10860,31 @@ | ||
| 10861 | 10860 | ** name. An expr/name combination can be used in several ways, such |
| 10862 | 10861 | ** as the list of "expr AS ID" fields following a "SELECT" or in the |
| 10863 | 10862 | ** list of "ID = expr" items in an UPDATE. A list of expressions can |
| 10864 | 10863 | ** also be used as the argument to a function, in which case the a.zName |
| 10865 | 10864 | ** field is not used. |
| 10865 | +** | |
| 10866 | +** By default the Expr.zSpan field holds a human-readable description of | |
| 10867 | +** the expression that is used in the generation of error messages and | |
| 10868 | +** column labels. In this case, Expr.zSpan is typically the text of a | |
| 10869 | +** column expression as it exists in a SELECT statement. However, if | |
| 10870 | +** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name | |
| 10871 | +** of the result column in the form: DATABASE.TABLE.COLUMN. This later | |
| 10872 | +** form is used for name resolution with nested FROM clauses. | |
| 10866 | 10873 | */ |
| 10867 | 10874 | struct ExprList { |
| 10868 | 10875 | int nExpr; /* Number of expressions on the list */ |
| 10869 | 10876 | int iECursor; /* VDBE Cursor associated with this ExprList */ |
| 10870 | 10877 | struct ExprList_item { /* For each expression in the list */ |
| 10871 | - Expr *pExpr; /* The list of expressions */ | |
| 10872 | - char *zName; /* Token associated with this expression */ | |
| 10873 | - char *zSpan; /* Original text of the expression */ | |
| 10874 | - u8 sortOrder; /* 1 for DESC or 0 for ASC */ | |
| 10875 | - u8 done; /* A flag to indicate when processing is finished */ | |
| 10876 | - u16 iOrderByCol; /* For ORDER BY, column number in result set */ | |
| 10877 | - u16 iAlias; /* Index into Parse.aAlias[] for zName */ | |
| 10878 | + Expr *pExpr; /* The list of expressions */ | |
| 10879 | + char *zName; /* Token associated with this expression */ | |
| 10880 | + char *zSpan; /* Original text of the expression */ | |
| 10881 | + u8 sortOrder; /* 1 for DESC or 0 for ASC */ | |
| 10882 | + unsigned done :1; /* A flag to indicate when processing is finished */ | |
| 10883 | + unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ | |
| 10884 | + u16 iOrderByCol; /* For ORDER BY, column number in result set */ | |
| 10885 | + u16 iAlias; /* Index into Parse.aAlias[] for zName */ | |
| 10878 | 10886 | } *a; /* Alloc a power of two greater or equal to nExpr */ |
| 10879 | 10887 | }; |
| 10880 | 10888 | |
| 10881 | 10889 | /* |
| 10882 | 10890 | ** An instance of this structure is used by the parser to record both |
| @@ -11192,10 +11200,11 @@ | ||
| 11192 | 11200 | #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ |
| 11193 | 11201 | #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ |
| 11194 | 11202 | #define SF_UseSorter 0x0040 /* Sort using a sorter */ |
| 11195 | 11203 | #define SF_Values 0x0080 /* Synthesized from VALUES clause */ |
| 11196 | 11204 | #define SF_Materialize 0x0100 /* Force materialization of views */ |
| 11205 | +#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ | |
| 11197 | 11206 | |
| 11198 | 11207 | |
| 11199 | 11208 | /* |
| 11200 | 11209 | ** The results of a select can be distributed in several ways. The |
| 11201 | 11210 | ** "SRT" prefix means "SELECT Result Type". |
| @@ -11420,10 +11429,11 @@ | ||
| 11420 | 11429 | #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ |
| 11421 | 11430 | #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ |
| 11422 | 11431 | #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ |
| 11423 | 11432 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ |
| 11424 | 11433 | #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ |
| 11434 | +#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ | |
| 11425 | 11435 | |
| 11426 | 11436 | /* |
| 11427 | 11437 | * Each trigger present in the database schema is stored as an instance of |
| 11428 | 11438 | * struct Trigger. |
| 11429 | 11439 | * |
| @@ -11904,11 +11914,11 @@ | ||
| 11904 | 11914 | SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, |
| 11905 | 11915 | Token*, int, int); |
| 11906 | 11916 | SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); |
| 11907 | 11917 | SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); |
| 11908 | 11918 | SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, |
| 11909 | - Expr*,ExprList*,int,Expr*,Expr*); | |
| 11919 | + Expr*,ExprList*,u16,Expr*,Expr*); | |
| 11910 | 11920 | SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); |
| 11911 | 11921 | SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); |
| 11912 | 11922 | SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); |
| 11913 | 11923 | SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); |
| 11914 | 11924 | #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) |
| @@ -12112,12 +12122,13 @@ | ||
| 12112 | 12122 | SQLITE_PRIVATE const char *sqlite3ErrStr(int); |
| 12113 | 12123 | SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); |
| 12114 | 12124 | SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); |
| 12115 | 12125 | SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); |
| 12116 | 12126 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); |
| 12117 | -SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*); | |
| 12118 | -SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*); | |
| 12127 | +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*); | |
| 12128 | +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); | |
| 12129 | +SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); | |
| 12119 | 12130 | SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); |
| 12120 | 12131 | SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); |
| 12121 | 12132 | SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); |
| 12122 | 12133 | SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); |
| 12123 | 12134 | SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); |
| @@ -12160,10 +12171,11 @@ | ||
| 12160 | 12171 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); |
| 12161 | 12172 | SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); |
| 12162 | 12173 | SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); |
| 12163 | 12174 | SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); |
| 12164 | 12175 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); |
| 12176 | +SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); | |
| 12165 | 12177 | SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); |
| 12166 | 12178 | SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); |
| 12167 | 12179 | SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); |
| 12168 | 12180 | SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); |
| 12169 | 12181 | SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); |
| @@ -12298,12 +12310,14 @@ | ||
| 12298 | 12310 | #define sqlite3FkOldmask(a,b) 0 |
| 12299 | 12311 | #define sqlite3FkRequired(a,b,c,d) 0 |
| 12300 | 12312 | #endif |
| 12301 | 12313 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 12302 | 12314 | SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); |
| 12315 | +SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); | |
| 12303 | 12316 | #else |
| 12304 | 12317 | #define sqlite3FkDelete(a,b) |
| 12318 | + #define sqlite3FkLocateIndex(a,b,c,d,e) | |
| 12305 | 12319 | #endif |
| 12306 | 12320 | |
| 12307 | 12321 | |
| 12308 | 12322 | /* |
| 12309 | 12323 | ** Available fault injectors. Should be numbered beginning with 0. |
| @@ -23307,15 +23321,11 @@ | ||
| 23307 | 23321 | { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, |
| 23308 | 23322 | #endif |
| 23309 | 23323 | #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ |
| 23310 | 23324 | aSyscall[13].pCurrent) |
| 23311 | 23325 | |
| 23312 | -#if SQLITE_ENABLE_LOCKING_STYLE | |
| 23313 | 23326 | { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, |
| 23314 | -#else | |
| 23315 | - { "fchmod", (sqlite3_syscall_ptr)0, 0 }, | |
| 23316 | -#endif | |
| 23317 | 23327 | #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) |
| 23318 | 23328 | |
| 23319 | 23329 | #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE |
| 23320 | 23330 | { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, |
| 23321 | 23331 | #else |
| @@ -23336,13 +23346,10 @@ | ||
| 23336 | 23346 | #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) |
| 23337 | 23347 | |
| 23338 | 23348 | { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, |
| 23339 | 23349 | #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) |
| 23340 | 23350 | |
| 23341 | - { "umask", (sqlite3_syscall_ptr)umask, 0 }, | |
| 23342 | -#define osUmask ((mode_t(*)(mode_t))aSyscall[21].pCurrent) | |
| 23343 | - | |
| 23344 | 23351 | }; /* End of the overrideable system calls */ |
| 23345 | 23352 | |
| 23346 | 23353 | /* |
| 23347 | 23354 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 23348 | 23355 | ** "unix" VFSes. Return SQLITE_OK opon successfully updating the |
| @@ -23443,31 +23450,29 @@ | ||
| 23443 | 23450 | ** process that is able to write to the database will also be able to |
| 23444 | 23451 | ** recover the hot journals. |
| 23445 | 23452 | */ |
| 23446 | 23453 | static int robust_open(const char *z, int f, mode_t m){ |
| 23447 | 23454 | int fd; |
| 23448 | - mode_t m2; | |
| 23449 | - mode_t origM = 0; | |
| 23450 | - if( m==0 ){ | |
| 23451 | - m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; | |
| 23452 | - }else{ | |
| 23453 | - m2 = m; | |
| 23454 | - origM = osUmask(0); | |
| 23455 | - } | |
| 23455 | + mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS; | |
| 23456 | 23456 | do{ |
| 23457 | 23457 | #if defined(O_CLOEXEC) |
| 23458 | 23458 | fd = osOpen(z,f|O_CLOEXEC,m2); |
| 23459 | 23459 | #else |
| 23460 | 23460 | fd = osOpen(z,f,m2); |
| 23461 | 23461 | #endif |
| 23462 | 23462 | }while( fd<0 && errno==EINTR ); |
| 23463 | - if( m ){ | |
| 23464 | - osUmask(origM); | |
| 23465 | - } | |
| 23463 | + if( fd>=0 ){ | |
| 23464 | + if( m!=0 ){ | |
| 23465 | + struct stat statbuf; | |
| 23466 | + if( osFstat(fd, &statbuf)==0 && (statbuf.st_mode&0777)!=m ){ | |
| 23467 | + osFchmod(fd, m); | |
| 23468 | + } | |
| 23469 | + } | |
| 23466 | 23470 | #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) |
| 23467 | - if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); | |
| 23471 | + osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); | |
| 23468 | 23472 | #endif |
| 23473 | + } | |
| 23469 | 23474 | return fd; |
| 23470 | 23475 | } |
| 23471 | 23476 | |
| 23472 | 23477 | /* |
| 23473 | 23478 | ** Helper functions to obtain and relinquish the global mutex. The |
| @@ -29889,11 +29894,11 @@ | ||
| 29889 | 29894 | }; |
| 29890 | 29895 | unsigned int i; /* Loop counter */ |
| 29891 | 29896 | |
| 29892 | 29897 | /* Double-check that the aSyscall[] array has been constructed |
| 29893 | 29898 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 29894 | - assert( ArraySize(aSyscall)==22 ); | |
| 29899 | + assert( ArraySize(aSyscall)==21 ); | |
| 29895 | 29900 | |
| 29896 | 29901 | /* Register all VFSes defined in the aVfs[] array */ |
| 29897 | 29902 | for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 29898 | 29903 | sqlite3_vfs_register(&aVfs[i], i==0); |
| 29899 | 29904 | } |
| @@ -56355,11 +56360,11 @@ | ||
| 56355 | 56360 | sqlite3BtreeLeave(p); |
| 56356 | 56361 | return 0; |
| 56357 | 56362 | } |
| 56358 | 56363 | i = PENDING_BYTE_PAGE(pBt); |
| 56359 | 56364 | if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); |
| 56360 | - sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); | |
| 56365 | + sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); | |
| 56361 | 56366 | sCheck.errMsg.useMalloc = 2; |
| 56362 | 56367 | |
| 56363 | 56368 | /* Check the integrity of the freelist |
| 56364 | 56369 | */ |
| 56365 | 56370 | checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), |
| @@ -56890,11 +56895,16 @@ | ||
| 56890 | 56895 | /* |
| 56891 | 56896 | ** Parameter zSrcData points to a buffer containing the data for |
| 56892 | 56897 | ** page iSrcPg from the source database. Copy this data into the |
| 56893 | 56898 | ** destination database. |
| 56894 | 56899 | */ |
| 56895 | -static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){ | |
| 56900 | +static int backupOnePage( | |
| 56901 | + sqlite3_backup *p, /* Backup handle */ | |
| 56902 | + Pgno iSrcPg, /* Source database page to backup */ | |
| 56903 | + const u8 *zSrcData, /* Source database page data */ | |
| 56904 | + int bUpdate /* True for an update, false otherwise */ | |
| 56905 | +){ | |
| 56896 | 56906 | Pager * const pDestPager = sqlite3BtreePager(p->pDest); |
| 56897 | 56907 | const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); |
| 56898 | 56908 | int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); |
| 56899 | 56909 | const int nCopy = MIN(nSrcPgsz, nDestPgsz); |
| 56900 | 56910 | const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; |
| @@ -56963,10 +56973,13 @@ | ||
| 56963 | 56973 | ** cached parse of the page). MemPage.isInit is marked |
| 56964 | 56974 | ** "MUST BE FIRST" for this purpose. |
| 56965 | 56975 | */ |
| 56966 | 56976 | memcpy(zOut, zIn, nCopy); |
| 56967 | 56977 | ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; |
| 56978 | + if( iOff==0 && bUpdate==0 ){ | |
| 56979 | + sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); | |
| 56980 | + } | |
| 56968 | 56981 | } |
| 56969 | 56982 | sqlite3PagerUnref(pDestPg); |
| 56970 | 56983 | } |
| 56971 | 56984 | |
| 56972 | 56985 | return rc; |
| @@ -57069,11 +57082,11 @@ | ||
| 57069 | 57082 | const Pgno iSrcPg = p->iNext; /* Source page number */ |
| 57070 | 57083 | if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ |
| 57071 | 57084 | DbPage *pSrcPg; /* Source page object */ |
| 57072 | 57085 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); |
| 57073 | 57086 | if( rc==SQLITE_OK ){ |
| 57074 | - rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg)); | |
| 57087 | + rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); | |
| 57075 | 57088 | sqlite3PagerUnref(pSrcPg); |
| 57076 | 57089 | } |
| 57077 | 57090 | } |
| 57078 | 57091 | p->iNext++; |
| 57079 | 57092 | } |
| @@ -57317,11 +57330,11 @@ | ||
| 57317 | 57330 | ** the new data into the backup. |
| 57318 | 57331 | */ |
| 57319 | 57332 | int rc; |
| 57320 | 57333 | assert( p->pDestDb ); |
| 57321 | 57334 | sqlite3_mutex_enter(p->pDestDb->mutex); |
| 57322 | - rc = backupOnePage(p, iPage, aData); | |
| 57335 | + rc = backupOnePage(p, iPage, aData, 1); | |
| 57323 | 57336 | sqlite3_mutex_leave(p->pDestDb->mutex); |
| 57324 | 57337 | assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); |
| 57325 | 57338 | if( rc!=SQLITE_OK ){ |
| 57326 | 57339 | p->rc = rc; |
| 57327 | 57340 | } |
| @@ -59434,26 +59447,22 @@ | ||
| 59434 | 59447 | assert( pKeyInfo->aSortOrder!=0 ); |
| 59435 | 59448 | sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); |
| 59436 | 59449 | i = sqlite3Strlen30(zTemp); |
| 59437 | 59450 | for(j=0; j<pKeyInfo->nField; j++){ |
| 59438 | 59451 | CollSeq *pColl = pKeyInfo->aColl[j]; |
| 59439 | - if( pColl ){ | |
| 59440 | - int n = sqlite3Strlen30(pColl->zName); | |
| 59441 | - if( i+n>nTemp-6 ){ | |
| 59442 | - memcpy(&zTemp[i],",...",4); | |
| 59443 | - break; | |
| 59444 | - } | |
| 59445 | - zTemp[i++] = ','; | |
| 59446 | - if( pKeyInfo->aSortOrder[j] ){ | |
| 59447 | - zTemp[i++] = '-'; | |
| 59448 | - } | |
| 59449 | - memcpy(&zTemp[i], pColl->zName,n+1); | |
| 59450 | - i += n; | |
| 59451 | - }else if( i+4<nTemp-6 ){ | |
| 59452 | - memcpy(&zTemp[i],",nil",4); | |
| 59453 | - i += 4; | |
| 59454 | - } | |
| 59452 | + const char *zColl = pColl ? pColl->zName : "nil"; | |
| 59453 | + int n = sqlite3Strlen30(zColl); | |
| 59454 | + if( i+n>nTemp-6 ){ | |
| 59455 | + memcpy(&zTemp[i],",...",4); | |
| 59456 | + break; | |
| 59457 | + } | |
| 59458 | + zTemp[i++] = ','; | |
| 59459 | + if( pKeyInfo->aSortOrder[j] ){ | |
| 59460 | + zTemp[i++] = '-'; | |
| 59461 | + } | |
| 59462 | + memcpy(&zTemp[i], zColl, n+1); | |
| 59463 | + i += n; | |
| 59455 | 59464 | } |
| 59456 | 59465 | zTemp[i++] = ')'; |
| 59457 | 59466 | zTemp[i] = 0; |
| 59458 | 59467 | assert( i<nTemp ); |
| 59459 | 59468 | break; |
| @@ -63839,11 +63848,13 @@ | ||
| 63839 | 63848 | #ifdef SQLITE_DEBUG |
| 63840 | 63849 | /* |
| 63841 | 63850 | ** Print the value of a register for tracing purposes: |
| 63842 | 63851 | */ |
| 63843 | 63852 | static void memTracePrint(FILE *out, Mem *p){ |
| 63844 | - if( p->flags & MEM_Null ){ | |
| 63853 | + if( p->flags & MEM_Invalid ){ | |
| 63854 | + fprintf(out, " undefined"); | |
| 63855 | + }else if( p->flags & MEM_Null ){ | |
| 63845 | 63856 | fprintf(out, " NULL"); |
| 63846 | 63857 | }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ |
| 63847 | 63858 | fprintf(out, " si:%lld", p->u.i); |
| 63848 | 63859 | }else if( p->flags & MEM_Int ){ |
| 63849 | 63860 | fprintf(out, " i:%lld", p->u.i); |
| @@ -64112,10 +64123,11 @@ | ||
| 64112 | 64123 | } af; |
| 64113 | 64124 | struct OP_Concat_stack_vars { |
| 64114 | 64125 | i64 nByte; |
| 64115 | 64126 | } ag; |
| 64116 | 64127 | struct OP_Remainder_stack_vars { |
| 64128 | + char bIntint; /* Started out as two integer operands */ | |
| 64117 | 64129 | int flags; /* Combined MEM_* flags from both inputs */ |
| 64118 | 64130 | i64 iA; /* Integer value of left operand */ |
| 64119 | 64131 | i64 iB; /* Integer value of right operand */ |
| 64120 | 64132 | double rA; /* Real value of left operand */ |
| 64121 | 64133 | double rB; /* Real value of right operand */ |
| @@ -65021,10 +65033,13 @@ | ||
| 65021 | 65033 | pOut = &aMem[pOp->p2]; |
| 65022 | 65034 | assert( pOut!=pIn1 ); |
| 65023 | 65035 | while( 1 ){ |
| 65024 | 65036 | sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); |
| 65025 | 65037 | Deephemeralize(pOut); |
| 65038 | +#ifdef SQLITE_DEBUG | |
| 65039 | + pOut->pScopyFrom = 0; | |
| 65040 | +#endif | |
| 65026 | 65041 | REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut); |
| 65027 | 65042 | if( (u.ae.n--)==0 ) break; |
| 65028 | 65043 | pOut++; |
| 65029 | 65044 | pIn1++; |
| 65030 | 65045 | } |
| @@ -65214,10 +65229,11 @@ | ||
| 65214 | 65229 | case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ |
| 65215 | 65230 | case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ |
| 65216 | 65231 | case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ |
| 65217 | 65232 | case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ |
| 65218 | 65233 | #if 0 /* local variables moved into u.ah */ |
| 65234 | + char bIntint; /* Started out as two integer operands */ | |
| 65219 | 65235 | int flags; /* Combined MEM_* flags from both inputs */ |
| 65220 | 65236 | i64 iA; /* Integer value of left operand */ |
| 65221 | 65237 | i64 iB; /* Integer value of right operand */ |
| 65222 | 65238 | double rA; /* Real value of left operand */ |
| 65223 | 65239 | double rB; /* Real value of right operand */ |
| @@ -65231,10 +65247,11 @@ | ||
| 65231 | 65247 | u.ah.flags = pIn1->flags | pIn2->flags; |
| 65232 | 65248 | if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; |
| 65233 | 65249 | if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ |
| 65234 | 65250 | u.ah.iA = pIn1->u.i; |
| 65235 | 65251 | u.ah.iB = pIn2->u.i; |
| 65252 | + u.ah.bIntint = 1; | |
| 65236 | 65253 | switch( pOp->opcode ){ |
| 65237 | 65254 | case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65238 | 65255 | case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65239 | 65256 | case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65240 | 65257 | case OP_Divide: { |
| @@ -65251,10 +65268,11 @@ | ||
| 65251 | 65268 | } |
| 65252 | 65269 | } |
| 65253 | 65270 | pOut->u.i = u.ah.iB; |
| 65254 | 65271 | MemSetTypeFlag(pOut, MEM_Int); |
| 65255 | 65272 | }else{ |
| 65273 | + u.ah.bIntint = 0; | |
| 65256 | 65274 | fp_math: |
| 65257 | 65275 | u.ah.rA = sqlite3VdbeRealValue(pIn1); |
| 65258 | 65276 | u.ah.rB = sqlite3VdbeRealValue(pIn2); |
| 65259 | 65277 | switch( pOp->opcode ){ |
| 65260 | 65278 | case OP_Add: u.ah.rB += u.ah.rA; break; |
| @@ -65282,11 +65300,11 @@ | ||
| 65282 | 65300 | if( sqlite3IsNaN(u.ah.rB) ){ |
| 65283 | 65301 | goto arithmetic_result_is_null; |
| 65284 | 65302 | } |
| 65285 | 65303 | pOut->r = u.ah.rB; |
| 65286 | 65304 | MemSetTypeFlag(pOut, MEM_Real); |
| 65287 | - if( (u.ah.flags & MEM_Real)==0 ){ | |
| 65305 | + if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){ | |
| 65288 | 65306 | sqlite3VdbeIntegerAffinity(pOut); |
| 65289 | 65307 | } |
| 65290 | 65308 | #endif |
| 65291 | 65309 | } |
| 65292 | 65310 | break; |
| @@ -65843,26 +65861,31 @@ | ||
| 65843 | 65861 | /* Opcode: Permutation * * * P4 * |
| 65844 | 65862 | ** |
| 65845 | 65863 | ** Set the permutation used by the OP_Compare operator to be the array |
| 65846 | 65864 | ** of integers in P4. |
| 65847 | 65865 | ** |
| 65848 | -** The permutation is only valid until the next OP_Permutation, OP_Compare, | |
| 65849 | -** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur | |
| 65850 | -** immediately prior to the OP_Compare. | |
| 65866 | +** The permutation is only valid until the next OP_Compare that has | |
| 65867 | +** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should | |
| 65868 | +** occur immediately prior to the OP_Compare. | |
| 65851 | 65869 | */ |
| 65852 | 65870 | case OP_Permutation: { |
| 65853 | 65871 | assert( pOp->p4type==P4_INTARRAY ); |
| 65854 | 65872 | assert( pOp->p4.ai ); |
| 65855 | 65873 | aPermute = pOp->p4.ai; |
| 65856 | 65874 | break; |
| 65857 | 65875 | } |
| 65858 | 65876 | |
| 65859 | -/* Opcode: Compare P1 P2 P3 P4 * | |
| 65877 | +/* Opcode: Compare P1 P2 P3 P4 P5 | |
| 65860 | 65878 | ** |
| 65861 | 65879 | ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this |
| 65862 | 65880 | ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of |
| 65863 | 65881 | ** the comparison for use by the next OP_Jump instruct. |
| 65882 | +** | |
| 65883 | +** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is | |
| 65884 | +** determined by the most recent OP_Permutation operator. If the | |
| 65885 | +** OPFLAG_PERMUTE bit is clear, then register are compared in sequential | |
| 65886 | +** order. | |
| 65864 | 65887 | ** |
| 65865 | 65888 | ** P4 is a KeyInfo structure that defines collating sequences and sort |
| 65866 | 65889 | ** orders for the comparison. The permutation applies to registers |
| 65867 | 65890 | ** only. The KeyInfo elements are used sequentially. |
| 65868 | 65891 | ** |
| @@ -65880,10 +65903,11 @@ | ||
| 65880 | 65903 | int idx; |
| 65881 | 65904 | CollSeq *pColl; /* Collating sequence to use on this term */ |
| 65882 | 65905 | int bRev; /* True for DESCENDING sort order */ |
| 65883 | 65906 | #endif /* local variables moved into u.al */ |
| 65884 | 65907 | |
| 65908 | + if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0; | |
| 65885 | 65909 | u.al.n = pOp->p3; |
| 65886 | 65910 | u.al.pKeyInfo = pOp->p4.pKeyInfo; |
| 65887 | 65911 | assert( u.al.n>0 ); |
| 65888 | 65912 | assert( u.al.pKeyInfo!=0 ); |
| 65889 | 65913 | u.al.p1 = pOp->p1; |
| @@ -66025,12 +66049,10 @@ | ||
| 66025 | 66049 | |
| 66026 | 66050 | /* Opcode: Once P1 P2 * * * |
| 66027 | 66051 | ** |
| 66028 | 66052 | ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, |
| 66029 | 66053 | ** set the flag and fall through to the next instruction. |
| 66030 | -** | |
| 66031 | -** See also: JumpOnce | |
| 66032 | 66054 | */ |
| 66033 | 66055 | case OP_Once: { /* jump */ |
| 66034 | 66056 | assert( pOp->p1<p->nOnceFlag ); |
| 66035 | 66057 | if( p->aOnceFlag[pOp->p1] ){ |
| 66036 | 66058 | pc = pOp->p2-1; |
| @@ -71902,10 +71924,18 @@ | ||
| 71902 | 71924 | p->pReal = pReal; |
| 71903 | 71925 | if( p->iSize>0 ){ |
| 71904 | 71926 | assert(p->iSize<=p->nBuf); |
| 71905 | 71927 | rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); |
| 71906 | 71928 | } |
| 71929 | + if( rc!=SQLITE_OK ){ | |
| 71930 | + /* If an error occurred while writing to the file, close it before | |
| 71931 | + ** returning. This way, SQLite uses the in-memory journal data to | |
| 71932 | + ** roll back changes made to the internal page-cache before this | |
| 71933 | + ** function was called. */ | |
| 71934 | + sqlite3OsClose(pReal); | |
| 71935 | + p->pReal = 0; | |
| 71936 | + } | |
| 71907 | 71937 | } |
| 71908 | 71938 | } |
| 71909 | 71939 | return rc; |
| 71910 | 71940 | } |
| 71911 | 71941 | |
| @@ -72565,10 +72595,19 @@ | ||
| 72565 | 72595 | ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 |
| 72566 | 72596 | ** |
| 72567 | 72597 | ** The result of random()%5 in the GROUP BY clause is probably different |
| 72568 | 72598 | ** from the result in the result-set. We might fix this someday. Or |
| 72569 | 72599 | ** then again, we might not... |
| 72600 | +** | |
| 72601 | +** If the reference is followed by a COLLATE operator, then make sure | |
| 72602 | +** the COLLATE operator is preserved. For example: | |
| 72603 | +** | |
| 72604 | +** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase; | |
| 72605 | +** | |
| 72606 | +** Should be transformed into: | |
| 72607 | +** | |
| 72608 | +** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; | |
| 72570 | 72609 | ** |
| 72571 | 72610 | ** The nSubquery parameter specifies how many levels of subquery the |
| 72572 | 72611 | ** alias is removed from the original expression. The usually value is |
| 72573 | 72612 | ** zero but it might be more if the alias is contained within a subquery |
| 72574 | 72613 | ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION |
| @@ -72589,45 +72628,40 @@ | ||
| 72589 | 72628 | assert( iCol>=0 && iCol<pEList->nExpr ); |
| 72590 | 72629 | pOrig = pEList->a[iCol].pExpr; |
| 72591 | 72630 | assert( pOrig!=0 ); |
| 72592 | 72631 | assert( pOrig->flags & EP_Resolved ); |
| 72593 | 72632 | db = pParse->db; |
| 72633 | + pDup = sqlite3ExprDup(db, pOrig, 0); | |
| 72634 | + if( pDup==0 ) return; | |
| 72594 | 72635 | if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ |
| 72595 | - pDup = sqlite3ExprDup(db, pOrig, 0); | |
| 72596 | 72636 | incrAggFunctionDepth(pDup, nSubquery); |
| 72597 | 72637 | pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); |
| 72598 | 72638 | if( pDup==0 ) return; |
| 72599 | 72639 | if( pEList->a[iCol].iAlias==0 ){ |
| 72600 | 72640 | pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); |
| 72601 | 72641 | } |
| 72602 | 72642 | pDup->iTable = pEList->a[iCol].iAlias; |
| 72603 | - }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){ | |
| 72604 | - pDup = sqlite3ExprDup(db, pOrig, 0); | |
| 72605 | - if( pDup==0 ) return; | |
| 72606 | - }else{ | |
| 72607 | - char *zToken = pOrig->u.zToken; | |
| 72608 | - assert( zToken!=0 ); | |
| 72609 | - pOrig->u.zToken = 0; | |
| 72610 | - pDup = sqlite3ExprDup(db, pOrig, 0); | |
| 72611 | - pOrig->u.zToken = zToken; | |
| 72612 | - if( pDup==0 ) return; | |
| 72613 | - assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 ); | |
| 72614 | - pDup->flags2 |= EP2_MallocedToken; | |
| 72615 | - pDup->u.zToken = sqlite3DbStrDup(db, zToken); | |
| 72616 | - } | |
| 72617 | - if( pExpr->flags & EP_ExpCollate ){ | |
| 72618 | - pDup->pColl = pExpr->pColl; | |
| 72619 | - pDup->flags |= EP_ExpCollate; | |
| 72643 | + } | |
| 72644 | + if( pExpr->op==TK_COLLATE ){ | |
| 72645 | + pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); | |
| 72620 | 72646 | } |
| 72621 | 72647 | |
| 72622 | 72648 | /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This |
| 72623 | 72649 | ** prevents ExprDelete() from deleting the Expr structure itself, |
| 72624 | 72650 | ** allowing it to be repopulated by the memcpy() on the following line. |
| 72651 | + ** The pExpr->u.zToken might point into memory that will be freed by the | |
| 72652 | + ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to | |
| 72653 | + ** make a copy of the token before doing the sqlite3DbFree(). | |
| 72625 | 72654 | */ |
| 72626 | 72655 | ExprSetProperty(pExpr, EP_Static); |
| 72627 | 72656 | sqlite3ExprDelete(db, pExpr); |
| 72628 | 72657 | memcpy(pExpr, pDup, sizeof(*pExpr)); |
| 72658 | + if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ | |
| 72659 | + assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); | |
| 72660 | + pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); | |
| 72661 | + pExpr->flags2 |= EP2_MallocedToken; | |
| 72662 | + } | |
| 72629 | 72663 | sqlite3DbFree(db, pDup); |
| 72630 | 72664 | } |
| 72631 | 72665 | |
| 72632 | 72666 | |
| 72633 | 72667 | /* |
| @@ -72644,10 +72678,39 @@ | ||
| 72644 | 72678 | } |
| 72645 | 72679 | } |
| 72646 | 72680 | return 0; |
| 72647 | 72681 | } |
| 72648 | 72682 | |
| 72683 | +/* | |
| 72684 | +** Subqueries stores the original database, table and column names for their | |
| 72685 | +** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN". | |
| 72686 | +** Check to see if the zSpan given to this routine matches the zDb, zTab, | |
| 72687 | +** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will | |
| 72688 | +** match anything. | |
| 72689 | +*/ | |
| 72690 | +SQLITE_PRIVATE int sqlite3MatchSpanName( | |
| 72691 | + const char *zSpan, | |
| 72692 | + const char *zCol, | |
| 72693 | + const char *zTab, | |
| 72694 | + const char *zDb | |
| 72695 | +){ | |
| 72696 | + int n; | |
| 72697 | + for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} | |
| 72698 | + if( zDb && sqlite3StrNICmp(zSpan, zDb, n)!=0 ){ | |
| 72699 | + return 0; | |
| 72700 | + } | |
| 72701 | + zSpan += n+1; | |
| 72702 | + for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} | |
| 72703 | + if( zTab && sqlite3StrNICmp(zSpan, zTab, n)!=0 ){ | |
| 72704 | + return 0; | |
| 72705 | + } | |
| 72706 | + zSpan += n+1; | |
| 72707 | + if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ | |
| 72708 | + return 0; | |
| 72709 | + } | |
| 72710 | + return 1; | |
| 72711 | +} | |
| 72649 | 72712 | |
| 72650 | 72713 | /* |
| 72651 | 72714 | ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up |
| 72652 | 72715 | ** that name in the set of source tables in pSrcList and make the pExpr |
| 72653 | 72716 | ** expression node refer back to that source column. The following changes |
| @@ -72699,44 +72762,63 @@ | ||
| 72699 | 72762 | |
| 72700 | 72763 | /* Initialize the node to no-match */ |
| 72701 | 72764 | pExpr->iTable = -1; |
| 72702 | 72765 | pExpr->pTab = 0; |
| 72703 | 72766 | ExprSetIrreducible(pExpr); |
| 72767 | + | |
| 72768 | + /* Translate the schema name in zDb into a pointer to the corresponding | |
| 72769 | + ** schema. If not found, pSchema will remain NULL and nothing will match | |
| 72770 | + ** resulting in an appropriate error message toward the end of this routine | |
| 72771 | + */ | |
| 72772 | + if( zDb ){ | |
| 72773 | + for(i=0; i<db->nDb; i++){ | |
| 72774 | + assert( db->aDb[i].zName ); | |
| 72775 | + if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){ | |
| 72776 | + pSchema = db->aDb[i].pSchema; | |
| 72777 | + break; | |
| 72778 | + } | |
| 72779 | + } | |
| 72780 | + } | |
| 72704 | 72781 | |
| 72705 | 72782 | /* Start at the inner-most context and move outward until a match is found */ |
| 72706 | 72783 | while( pNC && cnt==0 ){ |
| 72707 | 72784 | ExprList *pEList; |
| 72708 | 72785 | SrcList *pSrcList = pNC->pSrcList; |
| 72709 | 72786 | |
| 72710 | 72787 | if( pSrcList ){ |
| 72711 | 72788 | for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ |
| 72712 | 72789 | Table *pTab; |
| 72713 | - int iDb; | |
| 72714 | 72790 | Column *pCol; |
| 72715 | 72791 | |
| 72716 | 72792 | pTab = pItem->pTab; |
| 72717 | 72793 | assert( pTab!=0 && pTab->zName!=0 ); |
| 72718 | - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | |
| 72719 | 72794 | assert( pTab->nCol>0 ); |
| 72795 | + if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ | |
| 72796 | + ExprList *pEList = pItem->pSelect->pEList; | |
| 72797 | + int hit = 0; | |
| 72798 | + for(j=0; j<pEList->nExpr; j++){ | |
| 72799 | + if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){ | |
| 72800 | + cnt++; | |
| 72801 | + cntTab = 2; | |
| 72802 | + pMatch = pItem; | |
| 72803 | + pExpr->iColumn = j; | |
| 72804 | + hit = 1; | |
| 72805 | + } | |
| 72806 | + } | |
| 72807 | + if( hit || zTab==0 ) continue; | |
| 72808 | + } | |
| 72809 | + if( zDb && pTab->pSchema!=pSchema ){ | |
| 72810 | + continue; | |
| 72811 | + } | |
| 72720 | 72812 | if( zTab ){ |
| 72721 | - if( pItem->zAlias ){ | |
| 72722 | - char *zTabName = pItem->zAlias; | |
| 72723 | - if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; | |
| 72724 | - }else{ | |
| 72725 | - char *zTabName = pTab->zName; | |
| 72726 | - if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){ | |
| 72727 | - continue; | |
| 72728 | - } | |
| 72729 | - if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ | |
| 72730 | - continue; | |
| 72731 | - } | |
| 72813 | + const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; | |
| 72814 | + assert( zTabName!=0 ); | |
| 72815 | + if( sqlite3StrICmp(zTabName, zTab)!=0 ){ | |
| 72816 | + continue; | |
| 72732 | 72817 | } |
| 72733 | 72818 | } |
| 72734 | 72819 | if( 0==(cntTab++) ){ |
| 72735 | - pExpr->iTable = pItem->iCursor; | |
| 72736 | - pExpr->pTab = pTab; | |
| 72737 | - pSchema = pTab->pSchema; | |
| 72738 | 72820 | pMatch = pItem; |
| 72739 | 72821 | } |
| 72740 | 72822 | for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ |
| 72741 | 72823 | if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ |
| 72742 | 72824 | /* If there has been exactly one prior match and this match |
| @@ -72746,21 +72828,23 @@ | ||
| 72746 | 72828 | if( cnt==1 ){ |
| 72747 | 72829 | if( pItem->jointype & JT_NATURAL ) continue; |
| 72748 | 72830 | if( nameInUsingClause(pItem->pUsing, zCol) ) continue; |
| 72749 | 72831 | } |
| 72750 | 72832 | cnt++; |
| 72751 | - pExpr->iTable = pItem->iCursor; | |
| 72752 | - pExpr->pTab = pTab; | |
| 72753 | 72833 | pMatch = pItem; |
| 72754 | - pSchema = pTab->pSchema; | |
| 72755 | 72834 | /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ |
| 72756 | 72835 | pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; |
| 72757 | 72836 | break; |
| 72758 | 72837 | } |
| 72759 | 72838 | } |
| 72760 | 72839 | } |
| 72761 | - } | |
| 72840 | + if( pMatch ){ | |
| 72841 | + pExpr->iTable = pMatch->iCursor; | |
| 72842 | + pExpr->pTab = pMatch->pTab; | |
| 72843 | + pSchema = pExpr->pTab->pSchema; | |
| 72844 | + } | |
| 72845 | + } /* if( pSrcList ) */ | |
| 72762 | 72846 | |
| 72763 | 72847 | #ifndef SQLITE_OMIT_TRIGGER |
| 72764 | 72848 | /* If we have not already resolved the name, then maybe |
| 72765 | 72849 | ** it is a new.* or old.* trigger argument reference |
| 72766 | 72850 | */ |
| @@ -73055,42 +73139,43 @@ | ||
| 73055 | 73139 | int wrong_num_args = 0; /* True if wrong number of arguments */ |
| 73056 | 73140 | int is_agg = 0; /* True if is an aggregate function */ |
| 73057 | 73141 | int auth; /* Authorization to use the function */ |
| 73058 | 73142 | int nId; /* Number of characters in function name */ |
| 73059 | 73143 | const char *zId; /* The function name. */ |
| 73060 | - FuncDef *pDef; /* Information about the function */ | |
| 73061 | 73144 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 73062 | 73145 | |
| 73063 | 73146 | testcase( pExpr->op==TK_CONST_FUNC ); |
| 73064 | 73147 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 73065 | 73148 | zId = pExpr->u.zToken; |
| 73066 | 73149 | nId = sqlite3Strlen30(zId); |
| 73067 | - pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); | |
| 73068 | - if( pDef==0 ){ | |
| 73069 | - pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); | |
| 73070 | - if( pDef==0 ){ | |
| 73071 | - no_such_func = 1; | |
| 73072 | - }else{ | |
| 73073 | - wrong_num_args = 1; | |
| 73074 | - } | |
| 73075 | - }else{ | |
| 73076 | - is_agg = pDef->xFunc==0; | |
| 73077 | - } | |
| 73078 | -#ifndef SQLITE_OMIT_AUTHORIZATION | |
| 73079 | - if( pDef ){ | |
| 73080 | - auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); | |
| 73081 | - if( auth!=SQLITE_OK ){ | |
| 73082 | - if( auth==SQLITE_DENY ){ | |
| 73083 | - sqlite3ErrorMsg(pParse, "not authorized to use function: %s", | |
| 73084 | - pDef->zName); | |
| 73085 | - pNC->nErr++; | |
| 73086 | - } | |
| 73087 | - pExpr->op = TK_NULL; | |
| 73088 | - return WRC_Prune; | |
| 73089 | - } | |
| 73090 | - } | |
| 73091 | -#endif | |
| 73150 | + if( pParse->db->init.busy==0 ){ | |
| 73151 | + FuncDef *pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); | |
| 73152 | + if( pDef==0 ){ | |
| 73153 | + pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); | |
| 73154 | + if( pDef==0 ){ | |
| 73155 | + no_such_func = 1; | |
| 73156 | + }else{ | |
| 73157 | + wrong_num_args = 1; | |
| 73158 | + } | |
| 73159 | + }else{ | |
| 73160 | + is_agg = pDef->xFunc==0; | |
| 73161 | + } | |
| 73162 | +#ifndef SQLITE_OMIT_AUTHORIZATION | |
| 73163 | + if( pDef ){ | |
| 73164 | + auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); | |
| 73165 | + if( auth!=SQLITE_OK ){ | |
| 73166 | + if( auth==SQLITE_DENY ){ | |
| 73167 | + sqlite3ErrorMsg(pParse, "not authorized to use function: %s", | |
| 73168 | + pDef->zName); | |
| 73169 | + pNC->nErr++; | |
| 73170 | + } | |
| 73171 | + pExpr->op = TK_NULL; | |
| 73172 | + return WRC_Prune; | |
| 73173 | + } | |
| 73174 | + } | |
| 73175 | +#endif | |
| 73176 | + } | |
| 73092 | 73177 | if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ |
| 73093 | 73178 | sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); |
| 73094 | 73179 | pNC->nErr++; |
| 73095 | 73180 | is_agg = 0; |
| 73096 | 73181 | }else if( no_such_func ){ |
| @@ -73310,11 +73395,11 @@ | ||
| 73310 | 73395 | assert( pEList!=0 ); |
| 73311 | 73396 | for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ |
| 73312 | 73397 | int iCol = -1; |
| 73313 | 73398 | Expr *pE, *pDup; |
| 73314 | 73399 | if( pItem->done ) continue; |
| 73315 | - pE = pItem->pExpr; | |
| 73400 | + pE = sqlite3ExprSkipCollate(pItem->pExpr); | |
| 73316 | 73401 | if( sqlite3ExprIsInteger(pE, &iCol) ){ |
| 73317 | 73402 | if( iCol<=0 || iCol>pEList->nExpr ){ |
| 73318 | 73403 | resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); |
| 73319 | 73404 | return 1; |
| 73320 | 73405 | } |
| @@ -73328,18 +73413,24 @@ | ||
| 73328 | 73413 | } |
| 73329 | 73414 | sqlite3ExprDelete(db, pDup); |
| 73330 | 73415 | } |
| 73331 | 73416 | } |
| 73332 | 73417 | if( iCol>0 ){ |
| 73333 | - CollSeq *pColl = pE->pColl; | |
| 73334 | - int flags = pE->flags & EP_ExpCollate; | |
| 73418 | + /* Convert the ORDER BY term into an integer column number iCol, | |
| 73419 | + ** taking care to preserve the COLLATE clause if it exists */ | |
| 73420 | + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); | |
| 73421 | + if( pNew==0 ) return 1; | |
| 73422 | + pNew->flags |= EP_IntValue; | |
| 73423 | + pNew->u.iValue = iCol; | |
| 73424 | + if( pItem->pExpr==pE ){ | |
| 73425 | + pItem->pExpr = pNew; | |
| 73426 | + }else{ | |
| 73427 | + assert( pItem->pExpr->op==TK_COLLATE ); | |
| 73428 | + assert( pItem->pExpr->pLeft==pE ); | |
| 73429 | + pItem->pExpr->pLeft = pNew; | |
| 73430 | + } | |
| 73335 | 73431 | sqlite3ExprDelete(db, pE); |
| 73336 | - pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0); | |
| 73337 | - if( pE==0 ) return 1; | |
| 73338 | - pE->pColl = pColl; | |
| 73339 | - pE->flags |= EP_IntValue | flags; | |
| 73340 | - pE->u.iValue = iCol; | |
| 73341 | 73432 | pItem->iOrderByCol = (u16)iCol; |
| 73342 | 73433 | pItem->done = 1; |
| 73343 | 73434 | }else{ |
| 73344 | 73435 | moreToDo = 1; |
| 73345 | 73436 | } |
| @@ -73440,15 +73531,15 @@ | ||
| 73440 | 73531 | ** sqlite3ResolveOrderGroupBy() will convert the expression to a |
| 73441 | 73532 | ** copy of the iCol-th result-set expression. */ |
| 73442 | 73533 | pItem->iOrderByCol = (u16)iCol; |
| 73443 | 73534 | continue; |
| 73444 | 73535 | } |
| 73445 | - if( sqlite3ExprIsInteger(pE, &iCol) ){ | |
| 73536 | + if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){ | |
| 73446 | 73537 | /* The ORDER BY term is an integer constant. Again, set the column |
| 73447 | 73538 | ** number so that sqlite3ResolveOrderGroupBy() will convert the |
| 73448 | 73539 | ** order-by term to a copy of the result-set expression */ |
| 73449 | - if( iCol<1 ){ | |
| 73540 | + if( iCol<1 || iCol>0xffff ){ | |
| 73450 | 73541 | resolveOutOfRangeError(pParse, zType, i+1, nResult); |
| 73451 | 73542 | return 1; |
| 73452 | 73543 | } |
| 73453 | 73544 | pItem->iOrderByCol = (u16)iCol; |
| 73454 | 73545 | continue; |
| @@ -73521,27 +73612,10 @@ | ||
| 73521 | 73612 | if( sqlite3ResolveExprNames(&sNC, p->pLimit) || |
| 73522 | 73613 | sqlite3ResolveExprNames(&sNC, p->pOffset) ){ |
| 73523 | 73614 | return WRC_Abort; |
| 73524 | 73615 | } |
| 73525 | 73616 | |
| 73526 | - /* Set up the local name-context to pass to sqlite3ResolveExprNames() to | |
| 73527 | - ** resolve the result-set expression list. | |
| 73528 | - */ | |
| 73529 | - sNC.ncFlags = NC_AllowAgg; | |
| 73530 | - sNC.pSrcList = p->pSrc; | |
| 73531 | - sNC.pNext = pOuterNC; | |
| 73532 | - | |
| 73533 | - /* Resolve names in the result set. */ | |
| 73534 | - pEList = p->pEList; | |
| 73535 | - assert( pEList!=0 ); | |
| 73536 | - for(i=0; i<pEList->nExpr; i++){ | |
| 73537 | - Expr *pX = pEList->a[i].pExpr; | |
| 73538 | - if( sqlite3ResolveExprNames(&sNC, pX) ){ | |
| 73539 | - return WRC_Abort; | |
| 73540 | - } | |
| 73541 | - } | |
| 73542 | - | |
| 73543 | 73617 | /* Recursively resolve names in all subqueries |
| 73544 | 73618 | */ |
| 73545 | 73619 | for(i=0; i<p->pSrc->nSrc; i++){ |
| 73546 | 73620 | struct SrcList_item *pItem = &p->pSrc->a[i]; |
| 73547 | 73621 | if( pItem->pSelect ){ |
| @@ -73564,10 +73638,27 @@ | ||
| 73564 | 73638 | for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; |
| 73565 | 73639 | assert( pItem->isCorrelated==0 && nRef<=0 ); |
| 73566 | 73640 | pItem->isCorrelated = (nRef!=0); |
| 73567 | 73641 | } |
| 73568 | 73642 | } |
| 73643 | + | |
| 73644 | + /* Set up the local name-context to pass to sqlite3ResolveExprNames() to | |
| 73645 | + ** resolve the result-set expression list. | |
| 73646 | + */ | |
| 73647 | + sNC.ncFlags = NC_AllowAgg; | |
| 73648 | + sNC.pSrcList = p->pSrc; | |
| 73649 | + sNC.pNext = pOuterNC; | |
| 73650 | + | |
| 73651 | + /* Resolve names in the result set. */ | |
| 73652 | + pEList = p->pEList; | |
| 73653 | + assert( pEList!=0 ); | |
| 73654 | + for(i=0; i<pEList->nExpr; i++){ | |
| 73655 | + Expr *pX = pEList->a[i].pExpr; | |
| 73656 | + if( sqlite3ResolveExprNames(&sNC, pX) ){ | |
| 73657 | + return WRC_Abort; | |
| 73658 | + } | |
| 73659 | + } | |
| 73569 | 73660 | |
| 73570 | 73661 | /* If there are no aggregate functions in the result-set, and no GROUP BY |
| 73571 | 73662 | ** expression, do not allow aggregates in any of the other expressions. |
| 73572 | 73663 | */ |
| 73573 | 73664 | assert( (p->selFlags & SF_Aggregate)==0 ); |
| @@ -73798,11 +73889,13 @@ | ||
| 73798 | 73889 | ** SELECT * FROM t1 WHERE a; |
| 73799 | 73890 | ** SELECT a AS b FROM t1 WHERE b; |
| 73800 | 73891 | ** SELECT * FROM t1 WHERE (select a from t1); |
| 73801 | 73892 | */ |
| 73802 | 73893 | SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ |
| 73803 | - int op = pExpr->op; | |
| 73894 | + int op; | |
| 73895 | + pExpr = sqlite3ExprSkipCollate(pExpr); | |
| 73896 | + op = pExpr->op; | |
| 73804 | 73897 | if( op==TK_SELECT ){ |
| 73805 | 73898 | assert( pExpr->flags&EP_xIsSelect ); |
| 73806 | 73899 | return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); |
| 73807 | 73900 | } |
| 73808 | 73901 | #ifndef SQLITE_OMIT_CAST |
| @@ -73823,70 +73916,98 @@ | ||
| 73823 | 73916 | } |
| 73824 | 73917 | return pExpr->affinity; |
| 73825 | 73918 | } |
| 73826 | 73919 | |
| 73827 | 73920 | /* |
| 73828 | -** Set the explicit collating sequence for an expression to the | |
| 73829 | -** collating sequence supplied in the second argument. | |
| 73830 | -*/ | |
| 73831 | -SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){ | |
| 73832 | - if( pExpr && pColl ){ | |
| 73833 | - pExpr->pColl = pColl; | |
| 73834 | - pExpr->flags |= EP_ExpCollate; | |
| 73835 | - } | |
| 73836 | - return pExpr; | |
| 73837 | -} | |
| 73838 | - | |
| 73839 | -/* | |
| 73840 | -** Set the collating sequence for expression pExpr to be the collating | |
| 73841 | -** sequence named by pToken. Return a pointer to the revised expression. | |
| 73842 | -** The collating sequence is marked as "explicit" using the EP_ExpCollate | |
| 73843 | -** flag. An explicit collating sequence will override implicit | |
| 73844 | -** collating sequences. | |
| 73845 | -*/ | |
| 73846 | -SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){ | |
| 73847 | - char *zColl = 0; /* Dequoted name of collation sequence */ | |
| 73848 | - CollSeq *pColl; | |
| 73849 | - sqlite3 *db = pParse->db; | |
| 73850 | - zColl = sqlite3NameFromToken(db, pCollName); | |
| 73851 | - pColl = sqlite3LocateCollSeq(pParse, zColl); | |
| 73852 | - sqlite3ExprSetColl(pExpr, pColl); | |
| 73853 | - sqlite3DbFree(db, zColl); | |
| 73854 | - return pExpr; | |
| 73855 | -} | |
| 73856 | - | |
| 73857 | -/* | |
| 73858 | -** Return the default collation sequence for the expression pExpr. If | |
| 73859 | -** there is no default collation type, return 0. | |
| 73860 | -*/ | |
| 73861 | -SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ | |
| 73862 | - CollSeq *pColl = 0; | |
| 73863 | - Expr *p = pExpr; | |
| 73864 | - while( p ){ | |
| 73865 | - int op; | |
| 73866 | - pColl = p->pColl; | |
| 73867 | - if( pColl ) break; | |
| 73868 | - op = p->op; | |
| 73869 | - if( p->pTab!=0 && ( | |
| 73870 | - op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER | |
| 73871 | - )){ | |
| 73872 | - /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally | |
| 73873 | - ** a TK_COLUMN but was previously evaluated and cached in a register */ | |
| 73874 | - const char *zColl; | |
| 73875 | - int j = p->iColumn; | |
| 73876 | - if( j>=0 ){ | |
| 73877 | - sqlite3 *db = pParse->db; | |
| 73878 | - zColl = p->pTab->aCol[j].zColl; | |
| 73879 | - pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); | |
| 73880 | - pExpr->pColl = pColl; | |
| 73881 | - } | |
| 73882 | - break; | |
| 73883 | - } | |
| 73884 | - if( op!=TK_CAST && op!=TK_UPLUS ){ | |
| 73885 | - break; | |
| 73886 | - } | |
| 73887 | - p = p->pLeft; | |
| 73921 | +** Set the collating sequence for expression pExpr to be the collating | |
| 73922 | +** sequence named by pToken. Return a pointer to a new Expr node that | |
| 73923 | +** implements the COLLATE operator. | |
| 73924 | +** | |
| 73925 | +** If a memory allocation error occurs, that fact is recorded in pParse->db | |
| 73926 | +** and the pExpr parameter is returned unchanged. | |
| 73927 | +*/ | |
| 73928 | +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){ | |
| 73929 | + if( pCollName->n>0 ){ | |
| 73930 | + Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); | |
| 73931 | + if( pNew ){ | |
| 73932 | + pNew->pLeft = pExpr; | |
| 73933 | + pNew->flags |= EP_Collate; | |
| 73934 | + pExpr = pNew; | |
| 73935 | + } | |
| 73936 | + } | |
| 73937 | + return pExpr; | |
| 73938 | +} | |
| 73939 | +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ | |
| 73940 | + Token s; | |
| 73941 | + assert( zC!=0 ); | |
| 73942 | + s.z = zC; | |
| 73943 | + s.n = sqlite3Strlen30(s.z); | |
| 73944 | + return sqlite3ExprAddCollateToken(pParse, pExpr, &s); | |
| 73945 | +} | |
| 73946 | + | |
| 73947 | +/* | |
| 73948 | +** Skip over any TK_COLLATE and/or TK_AS operators at the root of | |
| 73949 | +** an expression. | |
| 73950 | +*/ | |
| 73951 | +SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ | |
| 73952 | + while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){ | |
| 73953 | + pExpr = pExpr->pLeft; | |
| 73954 | + } | |
| 73955 | + return pExpr; | |
| 73956 | +} | |
| 73957 | + | |
| 73958 | +/* | |
| 73959 | +** Return the collation sequence for the expression pExpr. If | |
| 73960 | +** there is no defined collating sequence, return NULL. | |
| 73961 | +** | |
| 73962 | +** The collating sequence might be determined by a COLLATE operator | |
| 73963 | +** or by the presence of a column with a defined collating sequence. | |
| 73964 | +** COLLATE operators take first precedence. Left operands take | |
| 73965 | +** precedence over right operands. | |
| 73966 | +*/ | |
| 73967 | +SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ | |
| 73968 | + sqlite3 *db = pParse->db; | |
| 73969 | + CollSeq *pColl = 0; | |
| 73970 | + Expr *p = pExpr; | |
| 73971 | + while( p ){ | |
| 73972 | + int op = p->op; | |
| 73973 | + if( op==TK_CAST || op==TK_UPLUS ){ | |
| 73974 | + p = p->pLeft; | |
| 73975 | + continue; | |
| 73976 | + } | |
| 73977 | + assert( op!=TK_REGISTER || p->op2!=TK_COLLATE ); | |
| 73978 | + if( op==TK_COLLATE ){ | |
| 73979 | + if( db->init.busy ){ | |
| 73980 | + /* Do not report errors when parsing while the schema */ | |
| 73981 | + pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0); | |
| 73982 | + }else{ | |
| 73983 | + pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); | |
| 73984 | + } | |
| 73985 | + break; | |
| 73986 | + } | |
| 73987 | + if( p->pTab!=0 | |
| 73988 | + && (op==TK_AGG_COLUMN || op==TK_COLUMN | |
| 73989 | + || op==TK_REGISTER || op==TK_TRIGGER) | |
| 73990 | + ){ | |
| 73991 | + /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally | |
| 73992 | + ** a TK_COLUMN but was previously evaluated and cached in a register */ | |
| 73993 | + int j = p->iColumn; | |
| 73994 | + if( j>=0 ){ | |
| 73995 | + const char *zColl = p->pTab->aCol[j].zColl; | |
| 73996 | + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); | |
| 73997 | + } | |
| 73998 | + break; | |
| 73999 | + } | |
| 74000 | + if( p->flags & EP_Collate ){ | |
| 74001 | + if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ | |
| 74002 | + p = p->pLeft; | |
| 74003 | + }else{ | |
| 74004 | + p = p->pRight; | |
| 74005 | + } | |
| 74006 | + }else{ | |
| 74007 | + break; | |
| 74008 | + } | |
| 73888 | 74009 | } |
| 73889 | 74010 | if( sqlite3CheckCollSeq(pParse, pColl) ){ |
| 73890 | 74011 | pColl = 0; |
| 73891 | 74012 | } |
| 73892 | 74013 | return pColl; |
| @@ -73986,16 +74107,14 @@ | ||
| 73986 | 74107 | Expr *pLeft, |
| 73987 | 74108 | Expr *pRight |
| 73988 | 74109 | ){ |
| 73989 | 74110 | CollSeq *pColl; |
| 73990 | 74111 | assert( pLeft ); |
| 73991 | - if( pLeft->flags & EP_ExpCollate ){ | |
| 73992 | - assert( pLeft->pColl ); | |
| 73993 | - pColl = pLeft->pColl; | |
| 73994 | - }else if( pRight && pRight->flags & EP_ExpCollate ){ | |
| 73995 | - assert( pRight->pColl ); | |
| 73996 | - pColl = pRight->pColl; | |
| 74112 | + if( pLeft->flags & EP_Collate ){ | |
| 74113 | + pColl = sqlite3ExprCollSeq(pParse, pLeft); | |
| 74114 | + }else if( pRight && (pRight->flags & EP_Collate)!=0 ){ | |
| 74115 | + pColl = sqlite3ExprCollSeq(pParse, pRight); | |
| 73997 | 74116 | }else{ |
| 73998 | 74117 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 73999 | 74118 | if( !pColl ){ |
| 74000 | 74119 | pColl = sqlite3ExprCollSeq(pParse, pRight); |
| 74001 | 74120 | } |
| @@ -74221,21 +74340,15 @@ | ||
| 74221 | 74340 | sqlite3ExprDelete(db, pLeft); |
| 74222 | 74341 | sqlite3ExprDelete(db, pRight); |
| 74223 | 74342 | }else{ |
| 74224 | 74343 | if( pRight ){ |
| 74225 | 74344 | pRoot->pRight = pRight; |
| 74226 | - if( pRight->flags & EP_ExpCollate ){ | |
| 74227 | - pRoot->flags |= EP_ExpCollate; | |
| 74228 | - pRoot->pColl = pRight->pColl; | |
| 74229 | - } | |
| 74345 | + pRoot->flags |= EP_Collate & pRight->flags; | |
| 74230 | 74346 | } |
| 74231 | 74347 | if( pLeft ){ |
| 74232 | 74348 | pRoot->pLeft = pLeft; |
| 74233 | - if( pLeft->flags & EP_ExpCollate ){ | |
| 74234 | - pRoot->flags |= EP_ExpCollate; | |
| 74235 | - pRoot->pColl = pLeft->pColl; | |
| 74236 | - } | |
| 74349 | + pRoot->flags |= EP_Collate & pLeft->flags; | |
| 74237 | 74350 | } |
| 74238 | 74351 | exprSetHeight(pRoot); |
| 74239 | 74352 | } |
| 74240 | 74353 | } |
| 74241 | 74354 | |
| @@ -74489,11 +74602,11 @@ | ||
| 74489 | 74602 | }else{ |
| 74490 | 74603 | assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); |
| 74491 | 74604 | assert( !ExprHasProperty(p, EP_FromJoin) ); |
| 74492 | 74605 | assert( (p->flags2 & EP2_MallocedToken)==0 ); |
| 74493 | 74606 | assert( (p->flags2 & EP2_Irreducible)==0 ); |
| 74494 | - if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ | |
| 74607 | + if( p->pLeft || p->pRight || p->x.pList ){ | |
| 74495 | 74608 | nSize = EXPR_REDUCEDSIZE | EP_Reduced; |
| 74496 | 74609 | }else{ |
| 74497 | 74610 | nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; |
| 74498 | 74611 | } |
| 74499 | 74612 | } |
| @@ -76513,10 +76626,11 @@ | ||
| 76513 | 76626 | sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); |
| 76514 | 76627 | sqlite3ReleaseTempReg(pParse, r3); |
| 76515 | 76628 | sqlite3ReleaseTempReg(pParse, r4); |
| 76516 | 76629 | break; |
| 76517 | 76630 | } |
| 76631 | + case TK_COLLATE: | |
| 76518 | 76632 | case TK_UPLUS: { |
| 76519 | 76633 | inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); |
| 76520 | 76634 | break; |
| 76521 | 76635 | } |
| 76522 | 76636 | |
| @@ -76881,10 +76995,16 @@ | ||
| 76881 | 76995 | case TK_UPLUS: zUniOp = "UPLUS"; break; |
| 76882 | 76996 | case TK_BITNOT: zUniOp = "BITNOT"; break; |
| 76883 | 76997 | case TK_NOT: zUniOp = "NOT"; break; |
| 76884 | 76998 | case TK_ISNULL: zUniOp = "ISNULL"; break; |
| 76885 | 76999 | case TK_NOTNULL: zUniOp = "NOTNULL"; break; |
| 77000 | + | |
| 77001 | + case TK_COLLATE: { | |
| 77002 | + sqlite3ExplainExpr(pOut, pExpr->pLeft); | |
| 77003 | + sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken); | |
| 77004 | + break; | |
| 77005 | + } | |
| 76886 | 77006 | |
| 76887 | 77007 | case TK_AGG_FUNCTION: |
| 76888 | 77008 | case TK_CONST_FUNC: |
| 76889 | 77009 | case TK_FUNCTION: { |
| 76890 | 77010 | ExprList *pFarg; /* List of function arguments */ |
| @@ -77019,10 +77139,16 @@ | ||
| 77019 | 77139 | for(i=0; i<pList->nExpr; i++){ |
| 77020 | 77140 | sqlite3ExplainPrintf(pOut, "item[%d] = ", i); |
| 77021 | 77141 | sqlite3ExplainPush(pOut); |
| 77022 | 77142 | sqlite3ExplainExpr(pOut, pList->a[i].pExpr); |
| 77023 | 77143 | sqlite3ExplainPop(pOut); |
| 77144 | + if( pList->a[i].zName ){ | |
| 77145 | + sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName); | |
| 77146 | + } | |
| 77147 | + if( pList->a[i].bSpanIsTab ){ | |
| 77148 | + sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan); | |
| 77149 | + } | |
| 77024 | 77150 | if( i<pList->nExpr-1 ){ |
| 77025 | 77151 | sqlite3ExplainNL(pOut); |
| 77026 | 77152 | } |
| 77027 | 77153 | } |
| 77028 | 77154 | sqlite3ExplainPop(pOut); |
| @@ -77100,10 +77226,13 @@ | ||
| 77100 | 77226 | switch( pExpr->op ){ |
| 77101 | 77227 | case TK_IN: |
| 77102 | 77228 | case TK_REGISTER: { |
| 77103 | 77229 | return WRC_Prune; |
| 77104 | 77230 | } |
| 77231 | + case TK_COLLATE: { | |
| 77232 | + return WRC_Continue; | |
| 77233 | + } | |
| 77105 | 77234 | case TK_FUNCTION: |
| 77106 | 77235 | case TK_AGG_FUNCTION: |
| 77107 | 77236 | case TK_CONST_FUNC: { |
| 77108 | 77237 | /* The arguments to a function have a fixed destination. |
| 77109 | 77238 | ** Mark them this way to avoid generated unneeded OP_SCopy |
| @@ -77121,13 +77250,15 @@ | ||
| 77121 | 77250 | break; |
| 77122 | 77251 | } |
| 77123 | 77252 | } |
| 77124 | 77253 | if( isAppropriateForFactoring(pExpr) ){ |
| 77125 | 77254 | int r1 = ++pParse->nMem; |
| 77126 | - int r2; | |
| 77127 | - r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); | |
| 77128 | - if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1); | |
| 77255 | + int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); | |
| 77256 | + /* If r2!=r1, it means that register r1 is never used. That is harmless | |
| 77257 | + ** but suboptimal, so we want to know about the situation to fix it. | |
| 77258 | + ** Hence the following assert: */ | |
| 77259 | + assert( r2==r1 ); | |
| 77129 | 77260 | pExpr->op2 = pExpr->op; |
| 77130 | 77261 | pExpr->op = TK_REGISTER; |
| 77131 | 77262 | pExpr->iTable = r2; |
| 77132 | 77263 | return WRC_Prune; |
| 77133 | 77264 | } |
| @@ -77540,11 +77671,19 @@ | ||
| 77540 | 77671 | assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); |
| 77541 | 77672 | if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ |
| 77542 | 77673 | return 2; |
| 77543 | 77674 | } |
| 77544 | 77675 | if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; |
| 77545 | - if( pA->op!=pB->op ) return 2; | |
| 77676 | + if( pA->op!=pB->op ){ | |
| 77677 | + if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){ | |
| 77678 | + return 1; | |
| 77679 | + } | |
| 77680 | + if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){ | |
| 77681 | + return 1; | |
| 77682 | + } | |
| 77683 | + return 2; | |
| 77684 | + } | |
| 77546 | 77685 | if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; |
| 77547 | 77686 | if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; |
| 77548 | 77687 | if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; |
| 77549 | 77688 | if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; |
| 77550 | 77689 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| @@ -77552,15 +77691,13 @@ | ||
| 77552 | 77691 | return 2; |
| 77553 | 77692 | } |
| 77554 | 77693 | }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){ |
| 77555 | 77694 | if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; |
| 77556 | 77695 | if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 77557 | - return 2; | |
| 77696 | + return pA->op==TK_COLLATE ? 1 : 2; | |
| 77558 | 77697 | } |
| 77559 | 77698 | } |
| 77560 | - if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1; | |
| 77561 | - if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2; | |
| 77562 | 77699 | return 0; |
| 77563 | 77700 | } |
| 77564 | 77701 | |
| 77565 | 77702 | /* |
| 77566 | 77703 | ** Compare two ExprList objects. Return 0 if they are identical and |
| @@ -83371,14 +83508,12 @@ | ||
| 83371 | 83508 | ** specified collation sequence names. |
| 83372 | 83509 | */ |
| 83373 | 83510 | for(i=0; i<pList->nExpr; i++){ |
| 83374 | 83511 | Expr *pExpr = pList->a[i].pExpr; |
| 83375 | 83512 | if( pExpr ){ |
| 83376 | - CollSeq *pColl = pExpr->pColl; | |
| 83377 | - /* Either pColl!=0 or there was an OOM failure. But if an OOM | |
| 83378 | - ** failure we have quit before reaching this point. */ | |
| 83379 | - if( ALWAYS(pColl) ){ | |
| 83513 | + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); | |
| 83514 | + if( pColl ){ | |
| 83380 | 83515 | nExtra += (1 + sqlite3Strlen30(pColl->zName)); |
| 83381 | 83516 | } |
| 83382 | 83517 | } |
| 83383 | 83518 | } |
| 83384 | 83519 | |
| @@ -83437,10 +83572,11 @@ | ||
| 83437 | 83572 | */ |
| 83438 | 83573 | for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ |
| 83439 | 83574 | const char *zColName = pListItem->zName; |
| 83440 | 83575 | Column *pTabCol; |
| 83441 | 83576 | int requestedSortOrder; |
| 83577 | + CollSeq *pColl; /* Collating sequence */ | |
| 83442 | 83578 | char *zColl; /* Collation sequence name */ |
| 83443 | 83579 | |
| 83444 | 83580 | for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ |
| 83445 | 83581 | if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; |
| 83446 | 83582 | } |
| @@ -83449,18 +83585,15 @@ | ||
| 83449 | 83585 | pTab->zName, zColName); |
| 83450 | 83586 | pParse->checkSchema = 1; |
| 83451 | 83587 | goto exit_create_index; |
| 83452 | 83588 | } |
| 83453 | 83589 | pIndex->aiColumn[i] = j; |
| 83454 | - /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of | |
| 83455 | - ** the way the "idxlist" non-terminal is constructed by the parser, | |
| 83456 | - ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl | |
| 83457 | - ** must exist or else there must have been an OOM error. But if there | |
| 83458 | - ** was an OOM error, we would never reach this point. */ | |
| 83459 | - if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){ | |
| 83590 | + if( pListItem->pExpr | |
| 83591 | + && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0 | |
| 83592 | + ){ | |
| 83460 | 83593 | int nColl; |
| 83461 | - zColl = pListItem->pExpr->pColl->zName; | |
| 83594 | + zColl = pColl->zName; | |
| 83462 | 83595 | nColl = sqlite3Strlen30(zColl) + 1; |
| 83463 | 83596 | assert( nExtra>=nColl ); |
| 83464 | 83597 | memcpy(zExtra, zColl, nColl); |
| 83465 | 83598 | zColl = zExtra; |
| 83466 | 83599 | zExtra += nColl; |
| @@ -87489,11 +87622,11 @@ | ||
| 87489 | 87622 | |
| 87490 | 87623 | /* |
| 87491 | 87624 | ** A foreign key constraint requires that the key columns in the parent |
| 87492 | 87625 | ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. |
| 87493 | 87626 | ** Given that pParent is the parent table for foreign key constraint pFKey, |
| 87494 | -** search the schema a unique index on the parent key columns. | |
| 87627 | +** search the schema for a unique index on the parent key columns. | |
| 87495 | 87628 | ** |
| 87496 | 87629 | ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY |
| 87497 | 87630 | ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx |
| 87498 | 87631 | ** is set to point to the unique index. |
| 87499 | 87632 | ** |
| @@ -87525,11 +87658,11 @@ | ||
| 87525 | 87658 | ** |
| 87526 | 87659 | ** then non-zero is returned, and a "foreign key mismatch" error loaded |
| 87527 | 87660 | ** into pParse. If an OOM error occurs, non-zero is returned and the |
| 87528 | 87661 | ** pParse->db->mallocFailed flag is set. |
| 87529 | 87662 | */ |
| 87530 | -static int locateFkeyIndex( | |
| 87663 | +SQLITE_PRIVATE int sqlite3FkLocateIndex( | |
| 87531 | 87664 | Parse *pParse, /* Parse context to store any error in */ |
| 87532 | 87665 | Table *pParent, /* Parent table of FK constraint pFKey */ |
| 87533 | 87666 | FKey *pFKey, /* Foreign key to find index for */ |
| 87534 | 87667 | Index **ppIdx, /* OUT: Unique index on parent table */ |
| 87535 | 87668 | int **paiCol /* OUT: Map of index columns in pFKey */ |
| @@ -87622,11 +87755,13 @@ | ||
| 87622 | 87755 | } |
| 87623 | 87756 | } |
| 87624 | 87757 | |
| 87625 | 87758 | if( !pIdx ){ |
| 87626 | 87759 | if( !pParse->disableTriggers ){ |
| 87627 | - sqlite3ErrorMsg(pParse, "foreign key mismatch"); | |
| 87760 | + sqlite3ErrorMsg(pParse, | |
| 87761 | + "foreign key mismatch - \"%w\" referencing \"%w\"", | |
| 87762 | + pFKey->pFrom->zName, pFKey->zTo); | |
| 87628 | 87763 | } |
| 87629 | 87764 | sqlite3DbFree(pParse->db, aiCol); |
| 87630 | 87765 | return 1; |
| 87631 | 87766 | } |
| 87632 | 87767 | |
| @@ -87858,16 +87993,19 @@ | ||
| 87858 | 87993 | if( pLeft ){ |
| 87859 | 87994 | /* Set the collation sequence and affinity of the LHS of each TK_EQ |
| 87860 | 87995 | ** expression to the parent key column defaults. */ |
| 87861 | 87996 | if( pIdx ){ |
| 87862 | 87997 | Column *pCol; |
| 87998 | + const char *zColl; | |
| 87863 | 87999 | iCol = pIdx->aiColumn[i]; |
| 87864 | 88000 | pCol = &pTab->aCol[iCol]; |
| 87865 | 88001 | if( pTab->iPKey==iCol ) iCol = -1; |
| 87866 | 88002 | pLeft->iTable = regData+iCol+1; |
| 87867 | 88003 | pLeft->affinity = pCol->affinity; |
| 87868 | - pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl); | |
| 88004 | + zColl = pCol->zColl; | |
| 88005 | + if( zColl==0 ) zColl = db->pDfltColl->zName; | |
| 88006 | + pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl); | |
| 87869 | 88007 | }else{ |
| 87870 | 88008 | pLeft->iTable = regData; |
| 87871 | 88009 | pLeft->affinity = SQLITE_AFF_INTEGER; |
| 87872 | 88010 | } |
| 87873 | 88011 | } |
| @@ -88080,11 +88218,11 @@ | ||
| 88080 | 88218 | if( pParse->disableTriggers ){ |
| 88081 | 88219 | pTo = sqlite3FindTable(db, pFKey->zTo, zDb); |
| 88082 | 88220 | }else{ |
| 88083 | 88221 | pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); |
| 88084 | 88222 | } |
| 88085 | - if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ | |
| 88223 | + if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ | |
| 88086 | 88224 | assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); |
| 88087 | 88225 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88088 | 88226 | if( pTo==0 ){ |
| 88089 | 88227 | /* If isIgnoreErrors is true, then a table is being dropped. In this |
| 88090 | 88228 | ** case SQLite runs a "DELETE FROM xxx" on the table being dropped |
| @@ -88160,11 +88298,11 @@ | ||
| 88160 | 88298 | /* Inserting a single row into a parent table cannot cause an immediate |
| 88161 | 88299 | ** foreign key violation. So do nothing in this case. */ |
| 88162 | 88300 | continue; |
| 88163 | 88301 | } |
| 88164 | 88302 | |
| 88165 | - if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ | |
| 88303 | + if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ | |
| 88166 | 88304 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88167 | 88305 | continue; |
| 88168 | 88306 | } |
| 88169 | 88307 | assert( aiCol || pFKey->nCol==1 ); |
| 88170 | 88308 | |
| @@ -88215,11 +88353,11 @@ | ||
| 88215 | 88353 | for(p=pTab->pFKey; p; p=p->pNextFrom){ |
| 88216 | 88354 | for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); |
| 88217 | 88355 | } |
| 88218 | 88356 | for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
| 88219 | 88357 | Index *pIdx = 0; |
| 88220 | - locateFkeyIndex(pParse, pTab, p, &pIdx, 0); | |
| 88358 | + sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); | |
| 88221 | 88359 | if( pIdx ){ |
| 88222 | 88360 | for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); |
| 88223 | 88361 | } |
| 88224 | 88362 | } |
| 88225 | 88363 | } |
| @@ -88341,11 +88479,11 @@ | ||
| 88341 | 88479 | ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ |
| 88342 | 88480 | Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ |
| 88343 | 88481 | int i; /* Iterator variable */ |
| 88344 | 88482 | Expr *pWhen = 0; /* WHEN clause for the trigger */ |
| 88345 | 88483 | |
| 88346 | - if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; | |
| 88484 | + if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; | |
| 88347 | 88485 | assert( aiCol || pFKey->nCol==1 ); |
| 88348 | 88486 | |
| 88349 | 88487 | for(i=0; i<pFKey->nCol; i++){ |
| 88350 | 88488 | Token tOld = { "old", 3 }; /* Literal "old" token */ |
| 88351 | 88489 | Token tNew = { "new", 3 }; /* Literal "new" token */ |
| @@ -89843,29 +89981,24 @@ | ||
| 89843 | 89981 | ExprList *pCheck = pTab->pCheck; |
| 89844 | 89982 | pParse->ckBase = regData; |
| 89845 | 89983 | onError = overrideError!=OE_Default ? overrideError : OE_Abort; |
| 89846 | 89984 | for(i=0; i<pCheck->nExpr; i++){ |
| 89847 | 89985 | int allOk = sqlite3VdbeMakeLabel(v); |
| 89848 | - Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0); | |
| 89849 | - if( !db->mallocFailed ){ | |
| 89850 | - assert( pDup!=0 ); | |
| 89851 | - sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL); | |
| 89852 | - if( onError==OE_Ignore ){ | |
| 89853 | - sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); | |
| 89854 | - }else{ | |
| 89855 | - char *zConsName = pCheck->a[i].zName; | |
| 89856 | - if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ | |
| 89857 | - if( zConsName ){ | |
| 89858 | - zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); | |
| 89859 | - }else{ | |
| 89860 | - zConsName = 0; | |
| 89861 | - } | |
| 89862 | - sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); | |
| 89863 | - } | |
| 89864 | - sqlite3VdbeResolveLabel(v, allOk); | |
| 89865 | - } | |
| 89866 | - sqlite3ExprDelete(db, pDup); | |
| 89986 | + sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); | |
| 89987 | + if( onError==OE_Ignore ){ | |
| 89988 | + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); | |
| 89989 | + }else{ | |
| 89990 | + char *zConsName = pCheck->a[i].zName; | |
| 89991 | + if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ | |
| 89992 | + if( zConsName ){ | |
| 89993 | + zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); | |
| 89994 | + }else{ | |
| 89995 | + zConsName = 0; | |
| 89996 | + } | |
| 89997 | + sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); | |
| 89998 | + } | |
| 89999 | + sqlite3VdbeResolveLabel(v, allOk); | |
| 89867 | 90000 | } |
| 89868 | 90001 | } |
| 89869 | 90002 | #endif /* !defined(SQLITE_OMIT_CHECK) */ |
| 89870 | 90003 | |
| 89871 | 90004 | /* If we have an INTEGER PRIMARY KEY, make sure the primary key |
| @@ -92686,13 +92819,15 @@ | ||
| 92686 | 92819 | if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ |
| 92687 | 92820 | Table *pTab; |
| 92688 | 92821 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 92689 | 92822 | pTab = sqlite3FindTable(db, zRight, zDb); |
| 92690 | 92823 | if( pTab ){ |
| 92691 | - int i; | |
| 92824 | + int i, k; | |
| 92692 | 92825 | int nHidden = 0; |
| 92693 | 92826 | Column *pCol; |
| 92827 | + Index *pPk; | |
| 92828 | + for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){} | |
| 92694 | 92829 | sqlite3VdbeSetNumCols(v, 6); |
| 92695 | 92830 | pParse->nMem = 6; |
| 92696 | 92831 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); |
| 92697 | 92832 | sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); |
| 92698 | 92833 | sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); |
| @@ -92713,12 +92848,18 @@ | ||
| 92713 | 92848 | if( pCol->zDflt ){ |
| 92714 | 92849 | sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); |
| 92715 | 92850 | }else{ |
| 92716 | 92851 | sqlite3VdbeAddOp2(v, OP_Null, 0, 5); |
| 92717 | 92852 | } |
| 92718 | - sqlite3VdbeAddOp2(v, OP_Integer, | |
| 92719 | - (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6); | |
| 92853 | + if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ | |
| 92854 | + k = 0; | |
| 92855 | + }else if( pPk==0 ){ | |
| 92856 | + k = 1; | |
| 92857 | + }else{ | |
| 92858 | + for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){} | |
| 92859 | + } | |
| 92860 | + sqlite3VdbeAddOp2(v, OP_Integer, k, 6); | |
| 92720 | 92861 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); |
| 92721 | 92862 | } |
| 92722 | 92863 | } |
| 92723 | 92864 | }else |
| 92724 | 92865 | |
| @@ -92849,10 +92990,124 @@ | ||
| 92849 | 92990 | ++i; |
| 92850 | 92991 | pFK = pFK->pNextFrom; |
| 92851 | 92992 | } |
| 92852 | 92993 | } |
| 92853 | 92994 | } |
| 92995 | + }else | |
| 92996 | +#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ | |
| 92997 | + | |
| 92998 | +#ifndef SQLITE_OMIT_FOREIGN_KEY | |
| 92999 | + if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){ | |
| 93000 | + FKey *pFK; /* A foreign key constraint */ | |
| 93001 | + Table *pTab; /* Child table contain "REFERENCES" keyword */ | |
| 93002 | + Table *pParent; /* Parent table that child points to */ | |
| 93003 | + Index *pIdx; /* Index in the parent table */ | |
| 93004 | + int i; /* Loop counter: Foreign key number for pTab */ | |
| 93005 | + int j; /* Loop counter: Field of the foreign key */ | |
| 93006 | + HashElem *k; /* Loop counter: Next table in schema */ | |
| 93007 | + int x; /* result variable */ | |
| 93008 | + int regResult; /* 3 registers to hold a result row */ | |
| 93009 | + int regKey; /* Register to hold key for checking the FK */ | |
| 93010 | + int regRow; /* Registers to hold a row from pTab */ | |
| 93011 | + int addrTop; /* Top of a loop checking foreign keys */ | |
| 93012 | + int addrOk; /* Jump here if the key is OK */ | |
| 93013 | + int *aiCols; /* child to parent column mapping */ | |
| 93014 | + | |
| 93015 | + if( sqlite3ReadSchema(pParse) ) goto pragma_out; | |
| 93016 | + regResult = pParse->nMem+1; | |
| 93017 | + pParse->nMem += 4; | |
| 93018 | + regKey = ++pParse->nMem; | |
| 93019 | + regRow = ++pParse->nMem; | |
| 93020 | + v = sqlite3GetVdbe(pParse); | |
| 93021 | + sqlite3VdbeSetNumCols(v, 4); | |
| 93022 | + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); | |
| 93023 | + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC); | |
| 93024 | + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC); | |
| 93025 | + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC); | |
| 93026 | + sqlite3CodeVerifySchema(pParse, iDb); | |
| 93027 | + k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); | |
| 93028 | + while( k ){ | |
| 93029 | + if( zRight ){ | |
| 93030 | + pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); | |
| 93031 | + k = 0; | |
| 93032 | + }else{ | |
| 93033 | + pTab = (Table*)sqliteHashData(k); | |
| 93034 | + k = sqliteHashNext(k); | |
| 93035 | + } | |
| 93036 | + if( pTab==0 || pTab->pFKey==0 ) continue; | |
| 93037 | + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); | |
| 93038 | + if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; | |
| 93039 | + sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); | |
| 93040 | + sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, | |
| 93041 | + P4_TRANSIENT); | |
| 93042 | + for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ | |
| 93043 | + pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); | |
| 93044 | + if( pParent==0 ) break; | |
| 93045 | + pIdx = 0; | |
| 93046 | + sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); | |
| 93047 | + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); | |
| 93048 | + if( x==0 ){ | |
| 93049 | + if( pIdx==0 ){ | |
| 93050 | + sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); | |
| 93051 | + }else{ | |
| 93052 | + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); | |
| 93053 | + sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); | |
| 93054 | + sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); | |
| 93055 | + } | |
| 93056 | + }else{ | |
| 93057 | + k = 0; | |
| 93058 | + break; | |
| 93059 | + } | |
| 93060 | + } | |
| 93061 | + if( pFK ) break; | |
| 93062 | + if( pParse->nTab<i ) pParse->nTab = i; | |
| 93063 | + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); | |
| 93064 | + for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ | |
| 93065 | + pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); | |
| 93066 | + assert( pParent!=0 ); | |
| 93067 | + pIdx = 0; | |
| 93068 | + aiCols = 0; | |
| 93069 | + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); | |
| 93070 | + assert( x==0 ); | |
| 93071 | + addrOk = sqlite3VdbeMakeLabel(v); | |
| 93072 | + if( pIdx==0 ){ | |
| 93073 | + int iKey = pFK->aCol[0].iFrom; | |
| 93074 | + assert( iKey>=0 && iKey<pTab->nCol ); | |
| 93075 | + if( iKey!=pTab->iPKey ){ | |
| 93076 | + sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); | |
| 93077 | + sqlite3ColumnDefault(v, pTab, iKey, regRow); | |
| 93078 | + sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); | |
| 93079 | + sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, | |
| 93080 | + sqlite3VdbeCurrentAddr(v)+3); | |
| 93081 | + }else{ | |
| 93082 | + sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); | |
| 93083 | + } | |
| 93084 | + sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); | |
| 93085 | + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); | |
| 93086 | + sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); | |
| 93087 | + }else{ | |
| 93088 | + for(j=0; j<pFK->nCol; j++){ | |
| 93089 | + sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, | |
| 93090 | + aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j); | |
| 93091 | + sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); | |
| 93092 | + } | |
| 93093 | + sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); | |
| 93094 | + sqlite3VdbeChangeP4(v, -1, | |
| 93095 | + sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); | |
| 93096 | + sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); | |
| 93097 | + } | |
| 93098 | + sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); | |
| 93099 | + sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, | |
| 93100 | + pFK->zTo, P4_TRANSIENT); | |
| 93101 | + sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3); | |
| 93102 | + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); | |
| 93103 | + sqlite3VdbeResolveLabel(v, addrOk); | |
| 93104 | + sqlite3DbFree(db, aiCols); | |
| 93105 | + } | |
| 93106 | + sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); | |
| 93107 | + sqlite3VdbeJumpHere(v, addrTop); | |
| 93108 | + } | |
| 92854 | 93109 | }else |
| 92855 | 93110 | #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
| 92856 | 93111 | |
| 92857 | 93112 | #ifndef NDEBUG |
| 92858 | 93113 | if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ |
| @@ -94308,11 +94563,11 @@ | ||
| 94308 | 94563 | SrcList *pSrc, /* the FROM clause -- which tables to scan */ |
| 94309 | 94564 | Expr *pWhere, /* the WHERE clause */ |
| 94310 | 94565 | ExprList *pGroupBy, /* the GROUP BY clause */ |
| 94311 | 94566 | Expr *pHaving, /* the HAVING clause */ |
| 94312 | 94567 | ExprList *pOrderBy, /* the ORDER BY clause */ |
| 94313 | - int isDistinct, /* true if the DISTINCT keyword is present */ | |
| 94568 | + u16 selFlags, /* Flag parameters, such as SF_Distinct */ | |
| 94314 | 94569 | Expr *pLimit, /* LIMIT value. NULL means not used */ |
| 94315 | 94570 | Expr *pOffset /* OFFSET value. NULL means no offset */ |
| 94316 | 94571 | ){ |
| 94317 | 94572 | Select *pNew; |
| 94318 | 94573 | Select standin; |
| @@ -94332,11 +94587,11 @@ | ||
| 94332 | 94587 | pNew->pSrc = pSrc; |
| 94333 | 94588 | pNew->pWhere = pWhere; |
| 94334 | 94589 | pNew->pGroupBy = pGroupBy; |
| 94335 | 94590 | pNew->pHaving = pHaving; |
| 94336 | 94591 | pNew->pOrderBy = pOrderBy; |
| 94337 | - pNew->selFlags = isDistinct ? SF_Distinct : 0; | |
| 94592 | + pNew->selFlags = selFlags; | |
| 94338 | 94593 | pNew->op = TK_SELECT; |
| 94339 | 94594 | pNew->pLimit = pLimit; |
| 94340 | 94595 | pNew->pOffset = pOffset; |
| 94341 | 94596 | assert( pOffset==0 || pLimit!=0 ); |
| 94342 | 94597 | pNew->addrOpenEphm[0] = -1; |
| @@ -95588,13 +95843,11 @@ | ||
| 95588 | 95843 | *paCol = aCol; |
| 95589 | 95844 | |
| 95590 | 95845 | for(i=0, pCol=aCol; i<nCol; i++, pCol++){ |
| 95591 | 95846 | /* Get an appropriate name for the column |
| 95592 | 95847 | */ |
| 95593 | - p = pEList->a[i].pExpr; | |
| 95594 | - assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue) | |
| 95595 | - || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 ); | |
| 95848 | + p = sqlite3ExprSkipCollate(pEList->a[i].pExpr); | |
| 95596 | 95849 | if( (zName = pEList->a[i].zName)!=0 ){ |
| 95597 | 95850 | /* If the column contains an "AS <name>" phrase, use <name> as the name */ |
| 95598 | 95851 | zName = sqlite3DbStrDup(db, zName); |
| 95599 | 95852 | }else{ |
| 95600 | 95853 | Expr *pColExpr = p; /* The expression that is the result column name */ |
| @@ -95628,10 +95881,13 @@ | ||
| 95628 | 95881 | */ |
| 95629 | 95882 | nName = sqlite3Strlen30(zName); |
| 95630 | 95883 | for(j=cnt=0; j<i; j++){ |
| 95631 | 95884 | if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ |
| 95632 | 95885 | char *zNewName; |
| 95886 | + int k; | |
| 95887 | + for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){} | |
| 95888 | + if( zName[k]==':' ) nName = k; | |
| 95633 | 95889 | zName[nName] = 0; |
| 95634 | 95890 | zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); |
| 95635 | 95891 | sqlite3DbFree(db, zName); |
| 95636 | 95892 | zName = zNewName; |
| 95637 | 95893 | j = -1; |
| @@ -96586,16 +96842,17 @@ | ||
| 96586 | 96842 | pKeyMerge->nField = (u16)nOrderBy; |
| 96587 | 96843 | pKeyMerge->enc = ENC(db); |
| 96588 | 96844 | for(i=0; i<nOrderBy; i++){ |
| 96589 | 96845 | CollSeq *pColl; |
| 96590 | 96846 | Expr *pTerm = pOrderBy->a[i].pExpr; |
| 96591 | - if( pTerm->flags & EP_ExpCollate ){ | |
| 96592 | - pColl = pTerm->pColl; | |
| 96847 | + if( pTerm->flags & EP_Collate ){ | |
| 96848 | + pColl = sqlite3ExprCollSeq(pParse, pTerm); | |
| 96593 | 96849 | }else{ |
| 96594 | 96850 | pColl = multiSelectCollSeq(pParse, p, aPermute[i]); |
| 96595 | - pTerm->flags |= EP_ExpCollate; | |
| 96596 | - pTerm->pColl = pColl; | |
| 96851 | + if( pColl==0 ) pColl = db->pDfltColl; | |
| 96852 | + pOrderBy->a[i].pExpr = | |
| 96853 | + sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); | |
| 96597 | 96854 | } |
| 96598 | 96855 | pKeyMerge->aColl[i] = pColl; |
| 96599 | 96856 | pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; |
| 96600 | 96857 | } |
| 96601 | 96858 | } |
| @@ -96794,10 +97051,11 @@ | ||
| 96794 | 97051 | */ |
| 96795 | 97052 | sqlite3VdbeResolveLabel(v, labelCmpr); |
| 96796 | 97053 | sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); |
| 96797 | 97054 | sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, |
| 96798 | 97055 | (char*)pKeyMerge, P4_KEYINFO_HANDOFF); |
| 97056 | + sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); | |
| 96799 | 97057 | sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); |
| 96800 | 97058 | |
| 96801 | 97059 | /* Release temporary registers |
| 96802 | 97060 | */ |
| 96803 | 97061 | if( regPrev ){ |
| @@ -96861,13 +97119,10 @@ | ||
| 96861 | 97119 | }else{ |
| 96862 | 97120 | Expr *pNew; |
| 96863 | 97121 | assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); |
| 96864 | 97122 | assert( pExpr->pLeft==0 && pExpr->pRight==0 ); |
| 96865 | 97123 | pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); |
| 96866 | - if( pNew && pExpr->pColl ){ | |
| 96867 | - pNew->pColl = pExpr->pColl; | |
| 96868 | - } | |
| 96869 | 97124 | sqlite3ExprDelete(db, pExpr); |
| 96870 | 97125 | pExpr = pNew; |
| 96871 | 97126 | } |
| 96872 | 97127 | }else{ |
| 96873 | 97128 | pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); |
| @@ -97414,38 +97669,47 @@ | ||
| 97414 | 97669 | return 1; |
| 97415 | 97670 | } |
| 97416 | 97671 | #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
| 97417 | 97672 | |
| 97418 | 97673 | /* |
| 97419 | -** Analyze the SELECT statement passed as an argument to see if it | |
| 97420 | -** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if | |
| 97421 | -** it is, or 0 otherwise. At present, a query is considered to be | |
| 97422 | -** a min()/max() query if: | |
| 97423 | -** | |
| 97424 | -** 1. There is a single object in the FROM clause. | |
| 97425 | -** | |
| 97426 | -** 2. There is a single expression in the result set, and it is | |
| 97427 | -** either min(x) or max(x), where x is a column reference. | |
| 97428 | -*/ | |
| 97429 | -static u8 minMaxQuery(Select *p){ | |
| 97430 | - Expr *pExpr; | |
| 97431 | - ExprList *pEList = p->pEList; | |
| 97432 | - | |
| 97433 | - if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL; | |
| 97434 | - pExpr = pEList->a[0].pExpr; | |
| 97435 | - if( pExpr->op!=TK_AGG_FUNCTION ) return 0; | |
| 97436 | - if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0; | |
| 97437 | - pEList = pExpr->x.pList; | |
| 97438 | - if( pEList==0 || pEList->nExpr!=1 ) return 0; | |
| 97439 | - if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL; | |
| 97440 | - assert( !ExprHasProperty(pExpr, EP_IntValue) ); | |
| 97441 | - if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){ | |
| 97442 | - return WHERE_ORDERBY_MIN; | |
| 97443 | - }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){ | |
| 97444 | - return WHERE_ORDERBY_MAX; | |
| 97445 | - } | |
| 97446 | - return WHERE_ORDERBY_NORMAL; | |
| 97674 | +** Based on the contents of the AggInfo structure indicated by the first | |
| 97675 | +** argument, this function checks if the following are true: | |
| 97676 | +** | |
| 97677 | +** * the query contains just a single aggregate function, | |
| 97678 | +** * the aggregate function is either min() or max(), and | |
| 97679 | +** * the argument to the aggregate function is a column value. | |
| 97680 | +** | |
| 97681 | +** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX | |
| 97682 | +** is returned as appropriate. Also, *ppMinMax is set to point to the | |
| 97683 | +** list of arguments passed to the aggregate before returning. | |
| 97684 | +** | |
| 97685 | +** Or, if the conditions above are not met, *ppMinMax is set to 0 and | |
| 97686 | +** WHERE_ORDERBY_NORMAL is returned. | |
| 97687 | +*/ | |
| 97688 | +static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ | |
| 97689 | + int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ | |
| 97690 | + | |
| 97691 | + *ppMinMax = 0; | |
| 97692 | + if( pAggInfo->nFunc==1 ){ | |
| 97693 | + Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ | |
| 97694 | + ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ | |
| 97695 | + | |
| 97696 | + assert( pExpr->op==TK_AGG_FUNCTION ); | |
| 97697 | + if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ | |
| 97698 | + const char *zFunc = pExpr->u.zToken; | |
| 97699 | + if( sqlite3StrICmp(zFunc, "min")==0 ){ | |
| 97700 | + eRet = WHERE_ORDERBY_MIN; | |
| 97701 | + *ppMinMax = pEList; | |
| 97702 | + }else if( sqlite3StrICmp(zFunc, "max")==0 ){ | |
| 97703 | + eRet = WHERE_ORDERBY_MAX; | |
| 97704 | + *ppMinMax = pEList; | |
| 97705 | + } | |
| 97706 | + } | |
| 97707 | + } | |
| 97708 | + | |
| 97709 | + assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); | |
| 97710 | + return eRet; | |
| 97447 | 97711 | } |
| 97448 | 97712 | |
| 97449 | 97713 | /* |
| 97450 | 97714 | ** The select statement passed as the first argument is an aggregate query. |
| 97451 | 97715 | ** The second argment is the associated aggregate-info object. This |
| @@ -97536,10 +97800,11 @@ | ||
| 97536 | 97800 | int i, j, k; |
| 97537 | 97801 | SrcList *pTabList; |
| 97538 | 97802 | ExprList *pEList; |
| 97539 | 97803 | struct SrcList_item *pFrom; |
| 97540 | 97804 | sqlite3 *db = pParse->db; |
| 97805 | + Expr *pE, *pRight, *pExpr; | |
| 97541 | 97806 | |
| 97542 | 97807 | if( db->mallocFailed ){ |
| 97543 | 97808 | return WRC_Abort; |
| 97544 | 97809 | } |
| 97545 | 97810 | if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){ |
| @@ -97621,11 +97886,11 @@ | ||
| 97621 | 97886 | ** |
| 97622 | 97887 | ** The first loop just checks to see if there are any "*" operators |
| 97623 | 97888 | ** that need expanding. |
| 97624 | 97889 | */ |
| 97625 | 97890 | for(k=0; k<pEList->nExpr; k++){ |
| 97626 | - Expr *pE = pEList->a[k].pExpr; | |
| 97891 | + pE = pEList->a[k].pExpr; | |
| 97627 | 97892 | if( pE->op==TK_ALL ) break; |
| 97628 | 97893 | assert( pE->op!=TK_DOT || pE->pRight!=0 ); |
| 97629 | 97894 | assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); |
| 97630 | 97895 | if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; |
| 97631 | 97896 | } |
| @@ -97639,14 +97904,22 @@ | ||
| 97639 | 97904 | ExprList *pNew = 0; |
| 97640 | 97905 | int flags = pParse->db->flags; |
| 97641 | 97906 | int longNames = (flags & SQLITE_FullColNames)!=0 |
| 97642 | 97907 | && (flags & SQLITE_ShortColNames)==0; |
| 97643 | 97908 | |
| 97909 | + /* When processing FROM-clause subqueries, it is always the case | |
| 97910 | + ** that full_column_names=OFF and short_column_names=ON. The | |
| 97911 | + ** sqlite3ResultSetOfSelect() routine makes it so. */ | |
| 97912 | + assert( (p->selFlags & SF_NestedFrom)==0 | |
| 97913 | + || ((flags & SQLITE_FullColNames)==0 && | |
| 97914 | + (flags & SQLITE_ShortColNames)!=0) ); | |
| 97915 | + | |
| 97644 | 97916 | for(k=0; k<pEList->nExpr; k++){ |
| 97645 | - Expr *pE = a[k].pExpr; | |
| 97646 | - assert( pE->op!=TK_DOT || pE->pRight!=0 ); | |
| 97647 | - if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){ | |
| 97917 | + pE = a[k].pExpr; | |
| 97918 | + pRight = pE->pRight; | |
| 97919 | + assert( pE->op!=TK_DOT || pRight!=0 ); | |
| 97920 | + if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){ | |
| 97648 | 97921 | /* This particular expression does not need to be expanded. |
| 97649 | 97922 | */ |
| 97650 | 97923 | pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); |
| 97651 | 97924 | if( pNew ){ |
| 97652 | 97925 | pNew->a[pNew->nExpr-1].zName = a[k].zName; |
| @@ -97657,44 +97930,56 @@ | ||
| 97657 | 97930 | a[k].pExpr = 0; |
| 97658 | 97931 | }else{ |
| 97659 | 97932 | /* This expression is a "*" or a "TABLE.*" and needs to be |
| 97660 | 97933 | ** expanded. */ |
| 97661 | 97934 | int tableSeen = 0; /* Set to 1 when TABLE matches */ |
| 97662 | - char *zTName; /* text of name of TABLE */ | |
| 97935 | + char *zTName = 0; /* text of name of TABLE */ | |
| 97663 | 97936 | if( pE->op==TK_DOT ){ |
| 97664 | 97937 | assert( pE->pLeft!=0 ); |
| 97665 | 97938 | assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); |
| 97666 | 97939 | zTName = pE->pLeft->u.zToken; |
| 97667 | - }else{ | |
| 97668 | - zTName = 0; | |
| 97669 | 97940 | } |
| 97670 | 97941 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 97671 | 97942 | Table *pTab = pFrom->pTab; |
| 97943 | + Select *pSub = pFrom->pSelect; | |
| 97672 | 97944 | char *zTabName = pFrom->zAlias; |
| 97945 | + const char *zSchemaName = 0; | |
| 97946 | + int iDb; | |
| 97673 | 97947 | if( zTabName==0 ){ |
| 97674 | 97948 | zTabName = pTab->zName; |
| 97675 | 97949 | } |
| 97676 | 97950 | if( db->mallocFailed ) break; |
| 97677 | - if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ | |
| 97678 | - continue; | |
| 97951 | + if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ | |
| 97952 | + pSub = 0; | |
| 97953 | + if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ | |
| 97954 | + continue; | |
| 97955 | + } | |
| 97956 | + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | |
| 97957 | + zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*"; | |
| 97679 | 97958 | } |
| 97680 | - tableSeen = 1; | |
| 97681 | 97959 | for(j=0; j<pTab->nCol; j++){ |
| 97682 | - Expr *pExpr, *pRight; | |
| 97683 | 97960 | char *zName = pTab->aCol[j].zName; |
| 97684 | 97961 | char *zColname; /* The computed column name */ |
| 97685 | 97962 | char *zToFree; /* Malloced string that needs to be freed */ |
| 97686 | 97963 | Token sColname; /* Computed column name as a token */ |
| 97964 | + | |
| 97965 | + assert( zName ); | |
| 97966 | + if( zTName && pSub | |
| 97967 | + && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0 | |
| 97968 | + ){ | |
| 97969 | + continue; | |
| 97970 | + } | |
| 97687 | 97971 | |
| 97688 | 97972 | /* If a column is marked as 'hidden' (currently only possible |
| 97689 | 97973 | ** for virtual tables), do not include it in the expanded |
| 97690 | 97974 | ** result-set list. |
| 97691 | 97975 | */ |
| 97692 | 97976 | if( IsHiddenColumn(&pTab->aCol[j]) ){ |
| 97693 | 97977 | assert(IsVirtual(pTab)); |
| 97694 | 97978 | continue; |
| 97695 | 97979 | } |
| 97980 | + tableSeen = 1; | |
| 97696 | 97981 | |
| 97697 | 97982 | if( i>0 && zTName==0 ){ |
| 97698 | 97983 | if( (pFrom->jointype & JT_NATURAL)!=0 |
| 97699 | 97984 | && tableAndColumnIndex(pTabList, i, zName, 0, 0) |
| 97700 | 97985 | ){ |
| @@ -97713,10 +97998,14 @@ | ||
| 97713 | 97998 | zToFree = 0; |
| 97714 | 97999 | if( longNames || pTabList->nSrc>1 ){ |
| 97715 | 98000 | Expr *pLeft; |
| 97716 | 98001 | pLeft = sqlite3Expr(db, TK_ID, zTabName); |
| 97717 | 98002 | pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); |
| 98003 | + if( zSchemaName ){ | |
| 98004 | + pLeft = sqlite3Expr(db, TK_ID, zSchemaName); | |
| 98005 | + pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0); | |
| 98006 | + } | |
| 97718 | 98007 | if( longNames ){ |
| 97719 | 98008 | zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); |
| 97720 | 98009 | zToFree = zColname; |
| 97721 | 98010 | } |
| 97722 | 98011 | }else{ |
| @@ -97724,10 +98013,22 @@ | ||
| 97724 | 98013 | } |
| 97725 | 98014 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
| 97726 | 98015 | sColname.z = zColname; |
| 97727 | 98016 | sColname.n = sqlite3Strlen30(zColname); |
| 97728 | 98017 | sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
| 98018 | + if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ | |
| 98019 | + struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; | |
| 98020 | + if( pSub ){ | |
| 98021 | + pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); | |
| 98022 | + testcase( pX->zSpan==0 ); | |
| 98023 | + }else{ | |
| 98024 | + pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s", | |
| 98025 | + zSchemaName, zTabName, zColname); | |
| 98026 | + testcase( pX->zSpan==0 ); | |
| 98027 | + } | |
| 98028 | + pX->bSpanIsTab = 1; | |
| 98029 | + } | |
| 97729 | 98030 | sqlite3DbFree(db, zToFree); |
| 97730 | 98031 | } |
| 97731 | 98032 | } |
| 97732 | 98033 | if( !tableSeen ){ |
| 97733 | 98034 | if( zTName ){ |
| @@ -98781,15 +99082,21 @@ | ||
| 98781 | 99082 | ** index or indices to use) should place a different priority on |
| 98782 | 99083 | ** satisfying the 'ORDER BY' clause than it does in other cases. |
| 98783 | 99084 | ** Refer to code and comments in where.c for details. |
| 98784 | 99085 | */ |
| 98785 | 99086 | ExprList *pMinMax = 0; |
| 98786 | - u8 flag = minMaxQuery(p); | |
| 99087 | + u8 flag = WHERE_ORDERBY_NORMAL; | |
| 99088 | + | |
| 99089 | + assert( p->pGroupBy==0 ); | |
| 99090 | + assert( flag==0 ); | |
| 99091 | + if( p->pHaving==0 ){ | |
| 99092 | + flag = minMaxQuery(&sAggInfo, &pMinMax); | |
| 99093 | + } | |
| 99094 | + assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); | |
| 99095 | + | |
| 98787 | 99096 | if( flag ){ |
| 98788 | - assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) ); | |
| 98789 | - assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 ); | |
| 98790 | - pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0); | |
| 99097 | + pMinMax = sqlite3ExprListDup(db, pMinMax, 0); | |
| 98791 | 99098 | pDel = pMinMax; |
| 98792 | 99099 | if( pMinMax && !db->mallocFailed ){ |
| 98793 | 99100 | pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
| 98794 | 99101 | pMinMax->a[0].pExpr->op = TK_COLUMN; |
| 98795 | 99102 | } |
| @@ -102673,11 +102980,11 @@ | ||
| 102673 | 102980 | #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ |
| 102674 | 102981 | #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ |
| 102675 | 102982 | #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ |
| 102676 | 102983 | #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ |
| 102677 | 102984 | #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ |
| 102678 | -#define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */ | |
| 102985 | +#define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */ | |
| 102679 | 102986 | #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */ |
| 102680 | 102987 | #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */ |
| 102681 | 102988 | #define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */ |
| 102682 | 102989 | #define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */ |
| 102683 | 102990 | #define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */ |
| @@ -102823,11 +103130,11 @@ | ||
| 102823 | 103130 | sqlite3DbFree(db, pOld); |
| 102824 | 103131 | } |
| 102825 | 103132 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 102826 | 103133 | } |
| 102827 | 103134 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 102828 | - pTerm->pExpr = p; | |
| 103135 | + pTerm->pExpr = sqlite3ExprSkipCollate(p); | |
| 102829 | 103136 | pTerm->wtFlags = wtFlags; |
| 102830 | 103137 | pTerm->pWC = pWC; |
| 102831 | 103138 | pTerm->iParent = -1; |
| 102832 | 103139 | return idx; |
| 102833 | 103140 | } |
| @@ -102983,27 +103290,36 @@ | ||
| 102983 | 103290 | |
| 102984 | 103291 | /* |
| 102985 | 103292 | ** Commute a comparison operator. Expressions of the form "X op Y" |
| 102986 | 103293 | ** are converted into "Y op X". |
| 102987 | 103294 | ** |
| 102988 | -** If a collation sequence is associated with either the left or right | |
| 103295 | +** If left/right precendence rules come into play when determining the | |
| 103296 | +** collating | |
| 102989 | 103297 | ** side of the comparison, it remains associated with the same side after |
| 102990 | 103298 | ** the commutation. So "Y collate NOCASE op X" becomes |
| 102991 | -** "X collate NOCASE op Y". This is because any collation sequence on | |
| 103299 | +** "X op Y". This is because any collation sequence on | |
| 102992 | 103300 | ** the left hand side of a comparison overrides any collation sequence |
| 102993 | -** attached to the right. For the same reason the EP_ExpCollate flag | |
| 103301 | +** attached to the right. For the same reason the EP_Collate flag | |
| 102994 | 103302 | ** is not commuted. |
| 102995 | 103303 | */ |
| 102996 | 103304 | static void exprCommute(Parse *pParse, Expr *pExpr){ |
| 102997 | - u16 expRight = (pExpr->pRight->flags & EP_ExpCollate); | |
| 102998 | - u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate); | |
| 103305 | + u16 expRight = (pExpr->pRight->flags & EP_Collate); | |
| 103306 | + u16 expLeft = (pExpr->pLeft->flags & EP_Collate); | |
| 102999 | 103307 | assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); |
| 103000 | - pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); | |
| 103001 | - pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); | |
| 103002 | - SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl); | |
| 103003 | - pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft; | |
| 103004 | - pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight; | |
| 103308 | + if( expRight==expLeft ){ | |
| 103309 | + /* Either X and Y both have COLLATE operator or neither do */ | |
| 103310 | + if( expRight ){ | |
| 103311 | + /* Both X and Y have COLLATE operators. Make sure X is always | |
| 103312 | + ** used by clearing the EP_Collate flag from Y. */ | |
| 103313 | + pExpr->pRight->flags &= ~EP_Collate; | |
| 103314 | + }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ | |
| 103315 | + /* Neither X nor Y have COLLATE operators, but X has a non-default | |
| 103316 | + ** collating sequence. So add the EP_Collate marker on X to cause | |
| 103317 | + ** it to be searched first. */ | |
| 103318 | + pExpr->pLeft->flags |= EP_Collate; | |
| 103319 | + } | |
| 103320 | + } | |
| 103005 | 103321 | SWAP(Expr*,pExpr->pRight,pExpr->pLeft); |
| 103006 | 103322 | if( pExpr->op>=TK_GT ){ |
| 103007 | 103323 | assert( TK_LT==TK_GT+2 ); |
| 103008 | 103324 | assert( TK_GE==TK_LE+2 ); |
| 103009 | 103325 | assert( TK_GT>TK_EQ ); |
| @@ -103076,16 +103392,16 @@ | ||
| 103076 | 103392 | ** it to be useful for optimising expression pX. Store this |
| 103077 | 103393 | ** value in variable pColl. |
| 103078 | 103394 | */ |
| 103079 | 103395 | assert(pX->pLeft); |
| 103080 | 103396 | pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| 103081 | - assert(pColl || pParse->nErr); | |
| 103397 | + if( pColl==0 ) pColl = pParse->db->pDfltColl; | |
| 103082 | 103398 | |
| 103083 | 103399 | for(j=0; pIdx->aiColumn[j]!=iColumn; j++){ |
| 103084 | 103400 | if( NEVER(j>=pIdx->nColumn) ) return 0; |
| 103085 | 103401 | } |
| 103086 | - if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; | |
| 103402 | + if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; | |
| 103087 | 103403 | } |
| 103088 | 103404 | return pTerm; |
| 103089 | 103405 | } |
| 103090 | 103406 | } |
| 103091 | 103407 | } |
| @@ -103600,10 +103916,11 @@ | ||
| 103600 | 103916 | return; |
| 103601 | 103917 | } |
| 103602 | 103918 | pTerm = &pWC->a[idxTerm]; |
| 103603 | 103919 | pMaskSet = pWC->pMaskSet; |
| 103604 | 103920 | pExpr = pTerm->pExpr; |
| 103921 | + assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); | |
| 103605 | 103922 | prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); |
| 103606 | 103923 | op = pExpr->op; |
| 103607 | 103924 | if( op==TK_IN ){ |
| 103608 | 103925 | assert( pExpr->pRight==0 ); |
| 103609 | 103926 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| @@ -103626,12 +103943,12 @@ | ||
| 103626 | 103943 | pTerm->prereqAll = prereqAll; |
| 103627 | 103944 | pTerm->leftCursor = -1; |
| 103628 | 103945 | pTerm->iParent = -1; |
| 103629 | 103946 | pTerm->eOperator = 0; |
| 103630 | 103947 | if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ |
| 103631 | - Expr *pLeft = pExpr->pLeft; | |
| 103632 | - Expr *pRight = pExpr->pRight; | |
| 103948 | + Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); | |
| 103949 | + Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); | |
| 103633 | 103950 | if( pLeft->op==TK_COLUMN ){ |
| 103634 | 103951 | pTerm->leftCursor = pLeft->iTable; |
| 103635 | 103952 | pTerm->u.leftColumn = pLeft->iColumn; |
| 103636 | 103953 | pTerm->eOperator = operatorMask(op); |
| 103637 | 103954 | } |
| @@ -103655,11 +103972,11 @@ | ||
| 103655 | 103972 | }else{ |
| 103656 | 103973 | pDup = pExpr; |
| 103657 | 103974 | pNew = pTerm; |
| 103658 | 103975 | } |
| 103659 | 103976 | exprCommute(pParse, pDup); |
| 103660 | - pLeft = pDup->pLeft; | |
| 103977 | + pLeft = sqlite3ExprSkipCollate(pDup->pLeft); | |
| 103661 | 103978 | pNew->leftCursor = pLeft->iTable; |
| 103662 | 103979 | pNew->u.leftColumn = pLeft->iColumn; |
| 103663 | 103980 | testcase( (prereqLeft | extraRight) != prereqLeft ); |
| 103664 | 103981 | pNew->prereqRight = prereqLeft | extraRight; |
| 103665 | 103982 | pNew->prereqAll = prereqAll; |
| @@ -103734,11 +104051,11 @@ | ||
| 103734 | 104051 | Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ |
| 103735 | 104052 | Expr *pNewExpr1; |
| 103736 | 104053 | Expr *pNewExpr2; |
| 103737 | 104054 | int idxNew1; |
| 103738 | 104055 | int idxNew2; |
| 103739 | - CollSeq *pColl; /* Collating sequence to use */ | |
| 104056 | + Token sCollSeqName; /* Name of collating sequence */ | |
| 103740 | 104057 | |
| 103741 | 104058 | pLeft = pExpr->x.pList->a[1].pExpr; |
| 103742 | 104059 | pStr2 = sqlite3ExprDup(db, pStr1, 0); |
| 103743 | 104060 | if( !db->mallocFailed ){ |
| 103744 | 104061 | u8 c, *pC; /* Last character before the first wildcard */ |
| @@ -103756,20 +104073,23 @@ | ||
| 103756 | 104073 | |
| 103757 | 104074 | c = sqlite3UpperToLower[c]; |
| 103758 | 104075 | } |
| 103759 | 104076 | *pC = c + 1; |
| 103760 | 104077 | } |
| 103761 | - pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0); | |
| 104078 | + sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; | |
| 104079 | + sCollSeqName.n = 6; | |
| 104080 | + pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); | |
| 103762 | 104081 | pNewExpr1 = sqlite3PExpr(pParse, TK_GE, |
| 103763 | - sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl), | |
| 103764 | - pStr1, 0); | |
| 104082 | + sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName), | |
| 104083 | + pStr1, 0); | |
| 103765 | 104084 | idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); |
| 103766 | 104085 | testcase( idxNew1==0 ); |
| 103767 | 104086 | exprAnalyze(pSrc, pWC, idxNew1); |
| 104087 | + pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); | |
| 103768 | 104088 | pNewExpr2 = sqlite3PExpr(pParse, TK_LT, |
| 103769 | - sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl), | |
| 103770 | - pStr2, 0); | |
| 104089 | + sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName), | |
| 104090 | + pStr2, 0); | |
| 103771 | 104091 | idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); |
| 103772 | 104092 | testcase( idxNew2==0 ); |
| 103773 | 104093 | exprAnalyze(pSrc, pWC, idxNew2); |
| 103774 | 104094 | pTerm = &pWC->a[idxTerm]; |
| 103775 | 104095 | if( isComplete ){ |
| @@ -103883,16 +104203,16 @@ | ||
| 103883 | 104203 | ){ |
| 103884 | 104204 | int i; |
| 103885 | 104205 | const char *zColl = pIdx->azColl[iCol]; |
| 103886 | 104206 | |
| 103887 | 104207 | for(i=0; i<pList->nExpr; i++){ |
| 103888 | - Expr *p = pList->a[i].pExpr; | |
| 104208 | + Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); | |
| 103889 | 104209 | if( p->op==TK_COLUMN |
| 103890 | 104210 | && p->iColumn==pIdx->aiColumn[iCol] |
| 103891 | 104211 | && p->iTable==iBase |
| 103892 | 104212 | ){ |
| 103893 | - CollSeq *pColl = sqlite3ExprCollSeq(pParse, p); | |
| 104213 | + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); | |
| 103894 | 104214 | if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ |
| 103895 | 104215 | return i; |
| 103896 | 104216 | } |
| 103897 | 104217 | } |
| 103898 | 104218 | } |
| @@ -103935,11 +104255,11 @@ | ||
| 103935 | 104255 | ** matching "col=X" expression and the column is on the same table as pIdx, |
| 103936 | 104256 | ** set the corresponding bit in variable mask. |
| 103937 | 104257 | */ |
| 103938 | 104258 | for(i=0; i<pDistinct->nExpr; i++){ |
| 103939 | 104259 | WhereTerm *pTerm; |
| 103940 | - Expr *p = pDistinct->a[i].pExpr; | |
| 104260 | + Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); | |
| 103941 | 104261 | if( p->op!=TK_COLUMN ) return 0; |
| 103942 | 104262 | pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0); |
| 103943 | 104263 | if( pTerm ){ |
| 103944 | 104264 | Expr *pX = pTerm->pExpr; |
| 103945 | 104265 | CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| @@ -103987,11 +104307,11 @@ | ||
| 103987 | 104307 | /* If any of the expressions is an IPK column on table iBase, then return |
| 103988 | 104308 | ** true. Note: The (p->iTable==iBase) part of this test may be false if the |
| 103989 | 104309 | ** current SELECT is a correlated sub-query. |
| 103990 | 104310 | */ |
| 103991 | 104311 | for(i=0; i<pDistinct->nExpr; i++){ |
| 103992 | - Expr *p = pDistinct->a[i].pExpr; | |
| 104312 | + Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); | |
| 103993 | 104313 | if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; |
| 103994 | 104314 | } |
| 103995 | 104315 | |
| 103996 | 104316 | /* Loop through all indices on the table, checking each to see if it makes |
| 103997 | 104317 | ** the DISTINCT qualifier redundant. It does so if: |
| @@ -104464,11 +104784,11 @@ | ||
| 104464 | 104784 | for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104465 | 104785 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104466 | 104786 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104467 | 104787 | testcase( pTerm->eOperator==WO_IN ); |
| 104468 | 104788 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104469 | - if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; | |
| 104789 | + if( pTerm->eOperator & (WO_ISNULL) ) continue; | |
| 104470 | 104790 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104471 | 104791 | nTerm++; |
| 104472 | 104792 | } |
| 104473 | 104793 | |
| 104474 | 104794 | /* If the ORDER BY clause contains only columns in the current |
| @@ -104512,29 +104832,32 @@ | ||
| 104512 | 104832 | *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; |
| 104513 | 104833 | *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = |
| 104514 | 104834 | pUsage; |
| 104515 | 104835 | |
| 104516 | 104836 | for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104837 | + u8 op; | |
| 104517 | 104838 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104518 | 104839 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104519 | 104840 | testcase( pTerm->eOperator==WO_IN ); |
| 104520 | 104841 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104521 | - if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; | |
| 104842 | + if( pTerm->eOperator & (WO_ISNULL) ) continue; | |
| 104522 | 104843 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104523 | 104844 | pIdxCons[j].iColumn = pTerm->u.leftColumn; |
| 104524 | 104845 | pIdxCons[j].iTermOffset = i; |
| 104525 | - pIdxCons[j].op = (u8)pTerm->eOperator; | |
| 104846 | + op = (u8)pTerm->eOperator; | |
| 104847 | + if( op==WO_IN ) op = WO_EQ; | |
| 104848 | + pIdxCons[j].op = op; | |
| 104526 | 104849 | /* The direct assignment in the previous line is possible only because |
| 104527 | 104850 | ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The |
| 104528 | 104851 | ** following asserts verify this fact. */ |
| 104529 | 104852 | assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); |
| 104530 | 104853 | assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); |
| 104531 | 104854 | assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); |
| 104532 | 104855 | assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); |
| 104533 | 104856 | assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); |
| 104534 | 104857 | assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); |
| 104535 | - assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); | |
| 104858 | + assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); | |
| 104536 | 104859 | j++; |
| 104537 | 104860 | } |
| 104538 | 104861 | for(i=0; i<nOrderBy; i++){ |
| 104539 | 104862 | Expr *pExpr = pOrderBy->a[i].pExpr; |
| 104540 | 104863 | pIdxOrderBy[i].iColumn = pExpr->iColumn; |
| @@ -104616,10 +104939,11 @@ | ||
| 104616 | 104939 | struct sqlite3_index_constraint *pIdxCons; |
| 104617 | 104940 | struct sqlite3_index_constraint_usage *pUsage; |
| 104618 | 104941 | WhereTerm *pTerm; |
| 104619 | 104942 | int i, j; |
| 104620 | 104943 | int nOrderBy; |
| 104944 | + int bAllowIN; /* Allow IN optimizations */ | |
| 104621 | 104945 | double rCost; |
| 104622 | 104946 | |
| 104623 | 104947 | /* Make sure wsFlags is initialized to some sane value. Otherwise, if the |
| 104624 | 104948 | ** malloc in allocateIndexInfo() fails and this function returns leaving |
| 104625 | 104949 | ** wsFlags in an uninitialized state, the caller may behave unpredictably. |
| @@ -104650,63 +104974,91 @@ | ||
| 104650 | 104974 | ** sqlite3ViewGetColumnNames() would have picked up the error. |
| 104651 | 104975 | */ |
| 104652 | 104976 | assert( pTab->azModuleArg && pTab->azModuleArg[0] ); |
| 104653 | 104977 | assert( sqlite3GetVTable(pParse->db, pTab) ); |
| 104654 | 104978 | |
| 104655 | - /* Set the aConstraint[].usable fields and initialize all | |
| 104656 | - ** output variables to zero. | |
| 104657 | - ** | |
| 104658 | - ** aConstraint[].usable is true for constraints where the right-hand | |
| 104659 | - ** side contains only references to tables to the left of the current | |
| 104660 | - ** table. In other words, if the constraint is of the form: | |
| 104661 | - ** | |
| 104662 | - ** column = expr | |
| 104663 | - ** | |
| 104664 | - ** and we are evaluating a join, then the constraint on column is | |
| 104665 | - ** only valid if all tables referenced in expr occur to the left | |
| 104666 | - ** of the table containing column. | |
| 104667 | - ** | |
| 104668 | - ** The aConstraints[] array contains entries for all constraints | |
| 104669 | - ** on the current table. That way we only have to compute it once | |
| 104670 | - ** even though we might try to pick the best index multiple times. | |
| 104671 | - ** For each attempt at picking an index, the order of tables in the | |
| 104672 | - ** join might be different so we have to recompute the usable flag | |
| 104673 | - ** each time. | |
| 104674 | - */ | |
| 104675 | - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; | |
| 104676 | - pUsage = pIdxInfo->aConstraintUsage; | |
| 104677 | - for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ | |
| 104678 | - j = pIdxCons->iTermOffset; | |
| 104679 | - pTerm = &pWC->a[j]; | |
| 104680 | - pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1; | |
| 104681 | - } | |
| 104682 | - memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); | |
| 104683 | - if( pIdxInfo->needToFreeIdxStr ){ | |
| 104684 | - sqlite3_free(pIdxInfo->idxStr); | |
| 104685 | - } | |
| 104686 | - pIdxInfo->idxStr = 0; | |
| 104687 | - pIdxInfo->idxNum = 0; | |
| 104688 | - pIdxInfo->needToFreeIdxStr = 0; | |
| 104689 | - pIdxInfo->orderByConsumed = 0; | |
| 104690 | - /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ | |
| 104691 | - pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); | |
| 104692 | - nOrderBy = pIdxInfo->nOrderBy; | |
| 104693 | - if( !p->pOrderBy ){ | |
| 104694 | - pIdxInfo->nOrderBy = 0; | |
| 104695 | - } | |
| 104696 | - | |
| 104697 | - if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ | |
| 104698 | - return; | |
| 104699 | - } | |
| 104700 | - | |
| 104701 | - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; | |
| 104702 | - for(i=0; i<pIdxInfo->nConstraint; i++){ | |
| 104703 | - if( pUsage[i].argvIndex>0 ){ | |
| 104704 | - p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight; | |
| 104705 | - } | |
| 104706 | - } | |
| 104707 | - | |
| 104979 | + /* Try once or twice. On the first attempt, allow IN optimizations. | |
| 104980 | + ** If an IN optimization is accepted by the virtual table xBestIndex | |
| 104981 | + ** method, but the pInfo->aConstrainUsage.omit flag is not set, then | |
| 104982 | + ** the query will not work because it might allow duplicate rows in | |
| 104983 | + ** output. In that case, run the xBestIndex method a second time | |
| 104984 | + ** without the IN constraints. Usually this loop only runs once. | |
| 104985 | + ** The loop will exit using a "break" statement. | |
| 104986 | + */ | |
| 104987 | + for(bAllowIN=1; 1; bAllowIN--){ | |
| 104988 | + assert( bAllowIN==0 || bAllowIN==1 ); | |
| 104989 | + | |
| 104990 | + /* Set the aConstraint[].usable fields and initialize all | |
| 104991 | + ** output variables to zero. | |
| 104992 | + ** | |
| 104993 | + ** aConstraint[].usable is true for constraints where the right-hand | |
| 104994 | + ** side contains only references to tables to the left of the current | |
| 104995 | + ** table. In other words, if the constraint is of the form: | |
| 104996 | + ** | |
| 104997 | + ** column = expr | |
| 104998 | + ** | |
| 104999 | + ** and we are evaluating a join, then the constraint on column is | |
| 105000 | + ** only valid if all tables referenced in expr occur to the left | |
| 105001 | + ** of the table containing column. | |
| 105002 | + ** | |
| 105003 | + ** The aConstraints[] array contains entries for all constraints | |
| 105004 | + ** on the current table. That way we only have to compute it once | |
| 105005 | + ** even though we might try to pick the best index multiple times. | |
| 105006 | + ** For each attempt at picking an index, the order of tables in the | |
| 105007 | + ** join might be different so we have to recompute the usable flag | |
| 105008 | + ** each time. | |
| 105009 | + */ | |
| 105010 | + pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; | |
| 105011 | + pUsage = pIdxInfo->aConstraintUsage; | |
| 105012 | + for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ | |
| 105013 | + j = pIdxCons->iTermOffset; | |
| 105014 | + pTerm = &pWC->a[j]; | |
| 105015 | + if( (pTerm->prereqRight&p->notReady)==0 | |
| 105016 | + && (bAllowIN || pTerm->eOperator!=WO_IN) | |
| 105017 | + ){ | |
| 105018 | + pIdxCons->usable = 1; | |
| 105019 | + }else{ | |
| 105020 | + pIdxCons->usable = 0; | |
| 105021 | + } | |
| 105022 | + } | |
| 105023 | + memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); | |
| 105024 | + if( pIdxInfo->needToFreeIdxStr ){ | |
| 105025 | + sqlite3_free(pIdxInfo->idxStr); | |
| 105026 | + } | |
| 105027 | + pIdxInfo->idxStr = 0; | |
| 105028 | + pIdxInfo->idxNum = 0; | |
| 105029 | + pIdxInfo->needToFreeIdxStr = 0; | |
| 105030 | + pIdxInfo->orderByConsumed = 0; | |
| 105031 | + /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ | |
| 105032 | + pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); | |
| 105033 | + nOrderBy = pIdxInfo->nOrderBy; | |
| 105034 | + if( !p->pOrderBy ){ | |
| 105035 | + pIdxInfo->nOrderBy = 0; | |
| 105036 | + } | |
| 105037 | + | |
| 105038 | + if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ | |
| 105039 | + return; | |
| 105040 | + } | |
| 105041 | + | |
| 105042 | + pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; | |
| 105043 | + for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ | |
| 105044 | + if( pUsage[i].argvIndex>0 ){ | |
| 105045 | + j = pIdxCons->iTermOffset; | |
| 105046 | + pTerm = &pWC->a[j]; | |
| 105047 | + p->cost.used |= pTerm->prereqRight; | |
| 105048 | + if( pTerm->eOperator==WO_IN && pUsage[i].omit==0 ){ | |
| 105049 | + /* Do not attempt to use an IN constraint if the virtual table | |
| 105050 | + ** says that the equivalent EQ constraint cannot be safely omitted. | |
| 105051 | + ** If we do attempt to use such a constraint, some rows might be | |
| 105052 | + ** repeated in the output. */ | |
| 105053 | + break; | |
| 105054 | + } | |
| 105055 | + } | |
| 105056 | + } | |
| 105057 | + if( i>=pIdxInfo->nConstraint ) break; | |
| 105058 | + } | |
| 105059 | + | |
| 104708 | 105060 | /* If there is an ORDER BY clause, and the selected virtual table index |
| 104709 | 105061 | ** does not satisfy it, increase the cost of the scan accordingly. This |
| 104710 | 105062 | ** matches the processing for non-virtual tables in bestBtreeIndex(). |
| 104711 | 105063 | */ |
| 104712 | 105064 | rCost = pIdxInfo->estimatedCost; |
| @@ -105273,11 +105625,11 @@ | ||
| 105273 | 105625 | WhereTerm *pConstraint; /* A constraint in the WHERE clause */ |
| 105274 | 105626 | |
| 105275 | 105627 | /* If the next term of the ORDER BY clause refers to anything other than |
| 105276 | 105628 | ** a column in the "base" table, then this index will not be of any |
| 105277 | 105629 | ** further use in handling the ORDER BY. */ |
| 105278 | - pOBExpr = pOBItem->pExpr; | |
| 105630 | + pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr); | |
| 105279 | 105631 | if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){ |
| 105280 | 105632 | break; |
| 105281 | 105633 | } |
| 105282 | 105634 | |
| 105283 | 105635 | /* Find column number and collating sequence for the next entry |
| @@ -105299,11 +105651,11 @@ | ||
| 105299 | 105651 | /* Check to see if the column number and collating sequence of the |
| 105300 | 105652 | ** index match the column number and collating sequence of the ORDER BY |
| 105301 | 105653 | ** clause entry. Set isMatch to 1 if they both match. */ |
| 105302 | 105654 | if( pOBExpr->iColumn==iColumn ){ |
| 105303 | 105655 | if( zColl ){ |
| 105304 | - pColl = sqlite3ExprCollSeq(pParse, pOBExpr); | |
| 105656 | + pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr); | |
| 105305 | 105657 | if( !pColl ) pColl = db->pDfltColl; |
| 105306 | 105658 | isMatch = sqlite3StrICmp(pColl->zName, zColl)==0; |
| 105307 | 105659 | }else{ |
| 105308 | 105660 | isMatch = 1; |
| 105309 | 105661 | } |
| @@ -105440,10 +105792,15 @@ | ||
| 105440 | 105792 | int idxEqTermMask; /* Index mask of valid equality operators */ |
| 105441 | 105793 | Index sPk; /* A fake index object for the primary key */ |
| 105442 | 105794 | tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ |
| 105443 | 105795 | int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ |
| 105444 | 105796 | int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */ |
| 105797 | + int nPriorSat; /* ORDER BY terms satisfied by outer loops */ | |
| 105798 | + int nOrderBy; /* Number of ORDER BY terms */ | |
| 105799 | + char bSortInit; /* Initializer for bSort in inner loop */ | |
| 105800 | + char bDistInit; /* Initializer for bDist in inner loop */ | |
| 105801 | + | |
| 105445 | 105802 | |
| 105446 | 105803 | /* Initialize the cost to a worst-case value */ |
| 105447 | 105804 | memset(&p->cost, 0, sizeof(p->cost)); |
| 105448 | 105805 | p->cost.rCost = SQLITE_BIG_DBL; |
| 105449 | 105806 | |
| @@ -105488,10 +105845,21 @@ | ||
| 105488 | 105845 | WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE |
| 105489 | 105846 | ); |
| 105490 | 105847 | eqTermMask = WO_EQ|WO_IN; |
| 105491 | 105848 | pIdx = 0; |
| 105492 | 105849 | } |
| 105850 | + | |
| 105851 | + nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; | |
| 105852 | + if( p->i ){ | |
| 105853 | + nPriorSat = p->aLevel[p->i-1].plan.nOBSat; | |
| 105854 | + bSortInit = nPriorSat<nOrderBy; | |
| 105855 | + bDistInit = 0; | |
| 105856 | + }else{ | |
| 105857 | + nPriorSat = 0; | |
| 105858 | + bSortInit = nOrderBy>0; | |
| 105859 | + bDistInit = p->pDistinct!=0; | |
| 105860 | + } | |
| 105493 | 105861 | |
| 105494 | 105862 | /* Loop over all indices looking for the best one to use |
| 105495 | 105863 | */ |
| 105496 | 105864 | for(; pProbe; pIdx=pProbe=pProbe->pNext){ |
| 105497 | 105865 | const tRowcnt * const aiRowEst = pProbe->aiRowEst; |
| @@ -105566,15 +105934,13 @@ | ||
| 105566 | 105934 | */ |
| 105567 | 105935 | int bInEst = 0; /* True if "x IN (SELECT...)" seen */ |
| 105568 | 105936 | int nInMul = 1; /* Number of distinct equalities to lookup */ |
| 105569 | 105937 | double rangeDiv = (double)1; /* Estimated reduction in search space */ |
| 105570 | 105938 | int nBound = 0; /* Number of range constraints seen */ |
| 105571 | - int bSort; /* True if external sort required */ | |
| 105572 | - int bDist; /* True if index cannot help with DISTINCT */ | |
| 105573 | - int bLookup = 0; /* True if not a covering index */ | |
| 105574 | - int nPriorSat; /* ORDER BY terms satisfied by outer loops */ | |
| 105575 | - int nOrderBy; /* Number of ORDER BY terms */ | |
| 105939 | + char bSort = bSortInit; /* True if external sort required */ | |
| 105940 | + char bDist = bDistInit; /* True if index cannot help with DISTINCT */ | |
| 105941 | + char bLookup = 0; /* True if not a covering index */ | |
| 105576 | 105942 | WhereTerm *pTerm; /* A single term of the WHERE clause */ |
| 105577 | 105943 | #ifdef SQLITE_ENABLE_STAT3 |
| 105578 | 105944 | WhereTerm *pFirstTerm = 0; /* First term matching the index */ |
| 105579 | 105945 | #endif |
| 105580 | 105946 | |
| @@ -105581,20 +105947,11 @@ | ||
| 105581 | 105947 | WHERETRACE(( |
| 105582 | 105948 | " %s(%s):\n", |
| 105583 | 105949 | pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk") |
| 105584 | 105950 | )); |
| 105585 | 105951 | memset(&pc, 0, sizeof(pc)); |
| 105586 | - nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; | |
| 105587 | - if( p->i ){ | |
| 105588 | - nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat; | |
| 105589 | - bSort = nPriorSat<nOrderBy; | |
| 105590 | - bDist = 0; | |
| 105591 | - }else{ | |
| 105592 | - nPriorSat = pc.plan.nOBSat = 0; | |
| 105593 | - bSort = nOrderBy>0; | |
| 105594 | - bDist = p->pDistinct!=0; | |
| 105595 | - } | |
| 105952 | + pc.plan.nOBSat = nPriorSat; | |
| 105596 | 105953 | |
| 105597 | 105954 | /* Determine the values of pc.plan.nEq and nInMul */ |
| 105598 | 105955 | for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){ |
| 105599 | 105956 | int j = pProbe->aiColumn[pc.plan.nEq]; |
| 105600 | 105957 | pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); |
| @@ -106466,32 +106823,40 @@ | ||
| 106466 | 106823 | if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ |
| 106467 | 106824 | /* Case 0: The table is a virtual-table. Use the VFilter and VNext |
| 106468 | 106825 | ** to access the data. |
| 106469 | 106826 | */ |
| 106470 | 106827 | int iReg; /* P3 Value for OP_VFilter */ |
| 106828 | + int addrNotFound; | |
| 106471 | 106829 | sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; |
| 106472 | 106830 | int nConstraint = pVtabIdx->nConstraint; |
| 106473 | 106831 | struct sqlite3_index_constraint_usage *aUsage = |
| 106474 | 106832 | pVtabIdx->aConstraintUsage; |
| 106475 | 106833 | const struct sqlite3_index_constraint *aConstraint = |
| 106476 | 106834 | pVtabIdx->aConstraint; |
| 106477 | 106835 | |
| 106478 | 106836 | sqlite3ExprCachePush(pParse); |
| 106479 | 106837 | iReg = sqlite3GetTempRange(pParse, nConstraint+2); |
| 106838 | + addrNotFound = pLevel->addrBrk; | |
| 106480 | 106839 | for(j=1; j<=nConstraint; j++){ |
| 106481 | 106840 | for(k=0; k<nConstraint; k++){ |
| 106482 | 106841 | if( aUsage[k].argvIndex==j ){ |
| 106483 | - int iTerm = aConstraint[k].iTermOffset; | |
| 106484 | - sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1); | |
| 106842 | + WhereTerm *pTerm = &pWC->a[aConstraint[k].iTermOffset]; | |
| 106843 | + int iTarget = iReg+j+1; | |
| 106844 | + if( pTerm->eOperator & WO_IN ){ | |
| 106845 | + codeEqualityTerm(pParse, pTerm, pLevel, iTarget); | |
| 106846 | + addrNotFound = pLevel->addrNxt; | |
| 106847 | + }else{ | |
| 106848 | + sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget); | |
| 106849 | + } | |
| 106485 | 106850 | break; |
| 106486 | 106851 | } |
| 106487 | 106852 | } |
| 106488 | 106853 | if( k==nConstraint ) break; |
| 106489 | 106854 | } |
| 106490 | 106855 | sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); |
| 106491 | 106856 | sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); |
| 106492 | - sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr, | |
| 106857 | + sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr, | |
| 106493 | 106858 | pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); |
| 106494 | 106859 | pVtabIdx->needToFreeIdxStr = 0; |
| 106495 | 106860 | for(j=0; j<nConstraint; j++){ |
| 106496 | 106861 | if( aUsage[j].omit ){ |
| 106497 | 106862 | int iTerm = aConstraint[j].iTermOffset; |
| @@ -108134,10 +108499,11 @@ | ||
| 108134 | 108499 | Expr* yy122; |
| 108135 | 108500 | Select* yy159; |
| 108136 | 108501 | IdList* yy180; |
| 108137 | 108502 | struct {int value; int mask;} yy207; |
| 108138 | 108503 | u8 yy258; |
| 108504 | + u16 yy305; | |
| 108139 | 108505 | struct LikeOp yy318; |
| 108140 | 108506 | TriggerStep* yy327; |
| 108141 | 108507 | ExprSpan yy342; |
| 108142 | 108508 | SrcList* yy347; |
| 108143 | 108509 | int yy392; |
| @@ -110084,22 +110450,19 @@ | ||
| 110084 | 110450 | case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); |
| 110085 | 110451 | case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); |
| 110086 | 110452 | case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); |
| 110087 | 110453 | case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98); |
| 110088 | 110454 | case 109: /* ifexists ::= */ yytestcase(yyruleno==109); |
| 110089 | - case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120); | |
| 110090 | - case 121: /* distinct ::= */ yytestcase(yyruleno==121); | |
| 110091 | 110455 | case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); |
| 110092 | 110456 | case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); |
| 110093 | 110457 | {yygotominor.yy392 = 0;} |
| 110094 | 110458 | break; |
| 110095 | 110459 | case 29: /* ifnotexists ::= IF NOT EXISTS */ |
| 110096 | 110460 | case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); |
| 110097 | 110461 | case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); |
| 110098 | 110462 | case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); |
| 110099 | 110463 | case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108); |
| 110100 | - case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119); | |
| 110101 | 110464 | case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); |
| 110102 | 110465 | case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); |
| 110103 | 110466 | {yygotominor.yy392 = 1;} |
| 110104 | 110467 | break; |
| 110105 | 110468 | case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ |
| @@ -110335,12 +110698,19 @@ | ||
| 110335 | 110698 | case 116: /* multiselect_op ::= UNION ALL */ |
| 110336 | 110699 | {yygotominor.yy392 = TK_ALL;} |
| 110337 | 110700 | break; |
| 110338 | 110701 | case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ |
| 110339 | 110702 | { |
| 110340 | - yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); | |
| 110703 | + yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); | |
| 110341 | 110704 | } |
| 110705 | + break; | |
| 110706 | + case 119: /* distinct ::= DISTINCT */ | |
| 110707 | +{yygotominor.yy305 = SF_Distinct;} | |
| 110708 | + break; | |
| 110709 | + case 120: /* distinct ::= ALL */ | |
| 110710 | + case 121: /* distinct ::= */ yytestcase(yyruleno==121); | |
| 110711 | +{yygotominor.yy305 = 0;} | |
| 110342 | 110712 | break; |
| 110343 | 110713 | case 122: /* sclp ::= selcollist COMMA */ |
| 110344 | 110714 | case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246); |
| 110345 | 110715 | {yygotominor.yy442 = yymsp[-1].minor.yy442;} |
| 110346 | 110716 | break; |
| @@ -110406,14 +110776,24 @@ | ||
| 110406 | 110776 | break; |
| 110407 | 110777 | case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ |
| 110408 | 110778 | { |
| 110409 | 110779 | if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ |
| 110410 | 110780 | yygotominor.yy347 = yymsp[-4].minor.yy347; |
| 110781 | + }else if( yymsp[-4].minor.yy347->nSrc==1 ){ | |
| 110782 | + yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); | |
| 110783 | + if( yygotominor.yy347 ){ | |
| 110784 | + struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1]; | |
| 110785 | + struct SrcList_item *pOld = yymsp[-4].minor.yy347->a; | |
| 110786 | + pNew->zName = pOld->zName; | |
| 110787 | + pNew->zDatabase = pOld->zDatabase; | |
| 110788 | + pOld->zName = pOld->zDatabase = 0; | |
| 110789 | + } | |
| 110790 | + sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347); | |
| 110411 | 110791 | }else{ |
| 110412 | 110792 | Select *pSubquery; |
| 110413 | 110793 | sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); |
| 110414 | - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0); | |
| 110794 | + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0); | |
| 110415 | 110795 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); |
| 110416 | 110796 | } |
| 110417 | 110797 | } |
| 110418 | 110798 | break; |
| 110419 | 110799 | case 137: /* dbnm ::= */ |
| @@ -110624,11 +111004,11 @@ | ||
| 110624 | 111004 | spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); |
| 110625 | 111005 | } |
| 110626 | 111006 | break; |
| 110627 | 111007 | case 194: /* expr ::= expr COLLATE ids */ |
| 110628 | 111008 | { |
| 110629 | - yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); | |
| 111009 | + yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); | |
| 110630 | 111010 | yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; |
| 110631 | 111011 | yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 110632 | 111012 | } |
| 110633 | 111013 | break; |
| 110634 | 111014 | case 195: /* expr ::= CAST LP expr AS typetoken RP */ |
| @@ -110642,11 +111022,11 @@ | ||
| 110642 | 111022 | if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ |
| 110643 | 111023 | sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); |
| 110644 | 111024 | } |
| 110645 | 111025 | yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); |
| 110646 | 111026 | spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); |
| 110647 | - if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){ | |
| 111027 | + if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){ | |
| 110648 | 111028 | yygotominor.yy342.pExpr->flags |= EP_Distinct; |
| 110649 | 111029 | } |
| 110650 | 111030 | } |
| 110651 | 111031 | break; |
| 110652 | 111032 | case 197: /* expr ::= ID LP STAR RP */ |
| @@ -110883,28 +111263,20 @@ | ||
| 110883 | 111263 | case 244: /* uniqueflag ::= */ |
| 110884 | 111264 | {yygotominor.yy392 = OE_None;} |
| 110885 | 111265 | break; |
| 110886 | 111266 | case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */ |
| 110887 | 111267 | { |
| 110888 | - Expr *p = 0; | |
| 110889 | - if( yymsp[-1].minor.yy0.n>0 ){ | |
| 110890 | - p = sqlite3Expr(pParse->db, TK_COLUMN, 0); | |
| 110891 | - sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); | |
| 110892 | - } | |
| 111268 | + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); | |
| 110893 | 111269 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p); |
| 110894 | 111270 | sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1); |
| 110895 | 111271 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 110896 | 111272 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 110897 | 111273 | } |
| 110898 | 111274 | break; |
| 110899 | 111275 | case 248: /* idxlist ::= nm collate sortorder */ |
| 110900 | 111276 | { |
| 110901 | - Expr *p = 0; | |
| 110902 | - if( yymsp[-1].minor.yy0.n>0 ){ | |
| 110903 | - p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); | |
| 110904 | - sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); | |
| 110905 | - } | |
| 111277 | + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); | |
| 110906 | 111278 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p); |
| 110907 | 111279 | sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); |
| 110908 | 111280 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 110909 | 111281 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 110910 | 111282 | } |
| @@ -141105,10 +141477,11 @@ | ||
| 141105 | 141477 | extern int Sqlitemultiplex_Init(Tcl_Interp*); |
| 141106 | 141478 | extern int SqliteSuperlock_Init(Tcl_Interp*); |
| 141107 | 141479 | extern int SqlitetestSyscall_Init(Tcl_Interp*); |
| 141108 | 141480 | extern int Sqlitetestfuzzer_Init(Tcl_Interp*); |
| 141109 | 141481 | extern int Sqlitetestwholenumber_Init(Tcl_Interp*); |
| 141482 | + extern int Sqlitetestregexp_Init(Tcl_Interp*); | |
| 141110 | 141483 | |
| 141111 | 141484 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141112 | 141485 | extern int Sqlitetestfts3_Init(Tcl_Interp *interp); |
| 141113 | 141486 | #endif |
| 141114 | 141487 | |
| @@ -141148,10 +141521,11 @@ | ||
| 141148 | 141521 | Sqlitemultiplex_Init(interp); |
| 141149 | 141522 | SqliteSuperlock_Init(interp); |
| 141150 | 141523 | SqlitetestSyscall_Init(interp); |
| 141151 | 141524 | Sqlitetestfuzzer_Init(interp); |
| 141152 | 141525 | Sqlitetestwholenumber_Init(interp); |
| 141526 | + Sqlitetestregexp_Init(interp); | |
| 141153 | 141527 | |
| 141154 | 141528 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141155 | 141529 | Sqlitetestfts3_Init(interp); |
| 141156 | 141530 | #endif |
| 141157 | 141531 | |
| 141158 | 141532 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.7.15. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -671,13 +671,13 @@ | |
| 671 | ** |
| 672 | ** See also: [sqlite3_libversion()], |
| 673 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 674 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 675 | */ |
| 676 | #define SQLITE_VERSION "3.7.15" |
| 677 | #define SQLITE_VERSION_NUMBER 3007015 |
| 678 | #define SQLITE_SOURCE_ID "2012-10-16 23:08:28 f021559d8a23934e3bdccad5b55fc7a91d185f53" |
| 679 | |
| 680 | /* |
| 681 | ** CAPI3REF: Run-Time Library Version Numbers |
| 682 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 683 | ** |
| @@ -2162,11 +2162,11 @@ | |
| 2162 | ** database connection is opened. By default, URI handling is globally |
| 2163 | ** disabled. The default value may be changed by compiling with the |
| 2164 | ** [SQLITE_USE_URI] symbol defined. |
| 2165 | ** |
| 2166 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 2167 | ** <dd> This option taks a single integer argument which is interpreted as |
| 2168 | ** a boolean in order to enable or disable the use of covering indices for |
| 2169 | ** full table scans in the query optimizer. The default setting is determined |
| 2170 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 2171 | ** if that compile-time option is omitted. |
| 2172 | ** The ability to disable the use of covering indices for full table scans |
| @@ -10573,24 +10573,24 @@ | |
| 10573 | ** and the value of Index.onError indicate the which conflict resolution |
| 10574 | ** algorithm to employ whenever an attempt is made to insert a non-unique |
| 10575 | ** element. |
| 10576 | */ |
| 10577 | struct Index { |
| 10578 | char *zName; /* Name of this index */ |
| 10579 | int *aiColumn; /* Which columns are used by this index. 1st is 0 */ |
| 10580 | tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ |
| 10581 | Table *pTable; /* The SQL table being indexed */ |
| 10582 | char *zColAff; /* String defining the affinity of each column */ |
| 10583 | Index *pNext; /* The next index associated with the same table */ |
| 10584 | Schema *pSchema; /* Schema containing this index */ |
| 10585 | u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ |
| 10586 | char **azColl; /* Array of collation sequence names for index */ |
| 10587 | int nColumn; /* Number of columns in the table used by this index */ |
| 10588 | int tnum; /* Page containing root of this index in database file */ |
| 10589 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| 10590 | u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ |
| 10591 | u8 bUnordered; /* Use this index for == or IN queries only */ |
| 10592 | #ifdef SQLITE_ENABLE_STAT3 |
| 10593 | int nSample; /* Number of elements in aSample[] */ |
| 10594 | tRowcnt avgEq; /* Average nEq value for key values not in aSample */ |
| 10595 | IndexSample *aSample; /* Samples of the left-most key */ |
| 10596 | #endif |
| @@ -10767,11 +10767,10 @@ | |
| 10767 | Expr *pRight; /* Right subnode */ |
| 10768 | union { |
| 10769 | ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */ |
| 10770 | Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */ |
| 10771 | } x; |
| 10772 | CollSeq *pColl; /* The collation type of the column or 0 */ |
| 10773 | |
| 10774 | /* If the EP_Reduced flag is set in the Expr.flags mask, then no |
| 10775 | ** space is allocated for the fields below this point. An attempt to |
| 10776 | ** access them will result in a segfault or malfunction. |
| 10777 | *********************************************************************/ |
| @@ -10803,11 +10802,11 @@ | |
| 10803 | #define EP_Error 0x0008 /* Expression contains one or more errors */ |
| 10804 | #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ |
| 10805 | #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ |
| 10806 | #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ |
| 10807 | #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ |
| 10808 | #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ |
| 10809 | #define EP_FixedDest 0x0200 /* Result needed in a specific register */ |
| 10810 | #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */ |
| 10811 | #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */ |
| 10812 | #define EP_Hint 0x1000 /* Not used */ |
| 10813 | #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ |
| @@ -10861,22 +10860,31 @@ | |
| 10861 | ** name. An expr/name combination can be used in several ways, such |
| 10862 | ** as the list of "expr AS ID" fields following a "SELECT" or in the |
| 10863 | ** list of "ID = expr" items in an UPDATE. A list of expressions can |
| 10864 | ** also be used as the argument to a function, in which case the a.zName |
| 10865 | ** field is not used. |
| 10866 | */ |
| 10867 | struct ExprList { |
| 10868 | int nExpr; /* Number of expressions on the list */ |
| 10869 | int iECursor; /* VDBE Cursor associated with this ExprList */ |
| 10870 | struct ExprList_item { /* For each expression in the list */ |
| 10871 | Expr *pExpr; /* The list of expressions */ |
| 10872 | char *zName; /* Token associated with this expression */ |
| 10873 | char *zSpan; /* Original text of the expression */ |
| 10874 | u8 sortOrder; /* 1 for DESC or 0 for ASC */ |
| 10875 | u8 done; /* A flag to indicate when processing is finished */ |
| 10876 | u16 iOrderByCol; /* For ORDER BY, column number in result set */ |
| 10877 | u16 iAlias; /* Index into Parse.aAlias[] for zName */ |
| 10878 | } *a; /* Alloc a power of two greater or equal to nExpr */ |
| 10879 | }; |
| 10880 | |
| 10881 | /* |
| 10882 | ** An instance of this structure is used by the parser to record both |
| @@ -11192,10 +11200,11 @@ | |
| 11192 | #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ |
| 11193 | #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ |
| 11194 | #define SF_UseSorter 0x0040 /* Sort using a sorter */ |
| 11195 | #define SF_Values 0x0080 /* Synthesized from VALUES clause */ |
| 11196 | #define SF_Materialize 0x0100 /* Force materialization of views */ |
| 11197 | |
| 11198 | |
| 11199 | /* |
| 11200 | ** The results of a select can be distributed in several ways. The |
| 11201 | ** "SRT" prefix means "SELECT Result Type". |
| @@ -11420,10 +11429,11 @@ | |
| 11420 | #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ |
| 11421 | #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ |
| 11422 | #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ |
| 11423 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ |
| 11424 | #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ |
| 11425 | |
| 11426 | /* |
| 11427 | * Each trigger present in the database schema is stored as an instance of |
| 11428 | * struct Trigger. |
| 11429 | * |
| @@ -11904,11 +11914,11 @@ | |
| 11904 | SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, |
| 11905 | Token*, int, int); |
| 11906 | SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); |
| 11907 | SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); |
| 11908 | SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, |
| 11909 | Expr*,ExprList*,int,Expr*,Expr*); |
| 11910 | SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); |
| 11911 | SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); |
| 11912 | SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); |
| 11913 | SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); |
| 11914 | #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) |
| @@ -12112,12 +12122,13 @@ | |
| 12112 | SQLITE_PRIVATE const char *sqlite3ErrStr(int); |
| 12113 | SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); |
| 12114 | SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); |
| 12115 | SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); |
| 12116 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); |
| 12117 | SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*); |
| 12118 | SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*); |
| 12119 | SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); |
| 12120 | SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); |
| 12121 | SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); |
| 12122 | SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); |
| 12123 | SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); |
| @@ -12160,10 +12171,11 @@ | |
| 12160 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); |
| 12161 | SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); |
| 12162 | SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); |
| 12163 | SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); |
| 12164 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); |
| 12165 | SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); |
| 12166 | SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); |
| 12167 | SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); |
| 12168 | SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); |
| 12169 | SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); |
| @@ -12298,12 +12310,14 @@ | |
| 12298 | #define sqlite3FkOldmask(a,b) 0 |
| 12299 | #define sqlite3FkRequired(a,b,c,d) 0 |
| 12300 | #endif |
| 12301 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 12302 | SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); |
| 12303 | #else |
| 12304 | #define sqlite3FkDelete(a,b) |
| 12305 | #endif |
| 12306 | |
| 12307 | |
| 12308 | /* |
| 12309 | ** Available fault injectors. Should be numbered beginning with 0. |
| @@ -23307,15 +23321,11 @@ | |
| 23307 | { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, |
| 23308 | #endif |
| 23309 | #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ |
| 23310 | aSyscall[13].pCurrent) |
| 23311 | |
| 23312 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 23313 | { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, |
| 23314 | #else |
| 23315 | { "fchmod", (sqlite3_syscall_ptr)0, 0 }, |
| 23316 | #endif |
| 23317 | #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) |
| 23318 | |
| 23319 | #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE |
| 23320 | { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, |
| 23321 | #else |
| @@ -23336,13 +23346,10 @@ | |
| 23336 | #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) |
| 23337 | |
| 23338 | { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, |
| 23339 | #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) |
| 23340 | |
| 23341 | { "umask", (sqlite3_syscall_ptr)umask, 0 }, |
| 23342 | #define osUmask ((mode_t(*)(mode_t))aSyscall[21].pCurrent) |
| 23343 | |
| 23344 | }; /* End of the overrideable system calls */ |
| 23345 | |
| 23346 | /* |
| 23347 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 23348 | ** "unix" VFSes. Return SQLITE_OK opon successfully updating the |
| @@ -23443,31 +23450,29 @@ | |
| 23443 | ** process that is able to write to the database will also be able to |
| 23444 | ** recover the hot journals. |
| 23445 | */ |
| 23446 | static int robust_open(const char *z, int f, mode_t m){ |
| 23447 | int fd; |
| 23448 | mode_t m2; |
| 23449 | mode_t origM = 0; |
| 23450 | if( m==0 ){ |
| 23451 | m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; |
| 23452 | }else{ |
| 23453 | m2 = m; |
| 23454 | origM = osUmask(0); |
| 23455 | } |
| 23456 | do{ |
| 23457 | #if defined(O_CLOEXEC) |
| 23458 | fd = osOpen(z,f|O_CLOEXEC,m2); |
| 23459 | #else |
| 23460 | fd = osOpen(z,f,m2); |
| 23461 | #endif |
| 23462 | }while( fd<0 && errno==EINTR ); |
| 23463 | if( m ){ |
| 23464 | osUmask(origM); |
| 23465 | } |
| 23466 | #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) |
| 23467 | if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 23468 | #endif |
| 23469 | return fd; |
| 23470 | } |
| 23471 | |
| 23472 | /* |
| 23473 | ** Helper functions to obtain and relinquish the global mutex. The |
| @@ -29889,11 +29894,11 @@ | |
| 29889 | }; |
| 29890 | unsigned int i; /* Loop counter */ |
| 29891 | |
| 29892 | /* Double-check that the aSyscall[] array has been constructed |
| 29893 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 29894 | assert( ArraySize(aSyscall)==22 ); |
| 29895 | |
| 29896 | /* Register all VFSes defined in the aVfs[] array */ |
| 29897 | for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 29898 | sqlite3_vfs_register(&aVfs[i], i==0); |
| 29899 | } |
| @@ -56355,11 +56360,11 @@ | |
| 56355 | sqlite3BtreeLeave(p); |
| 56356 | return 0; |
| 56357 | } |
| 56358 | i = PENDING_BYTE_PAGE(pBt); |
| 56359 | if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); |
| 56360 | sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); |
| 56361 | sCheck.errMsg.useMalloc = 2; |
| 56362 | |
| 56363 | /* Check the integrity of the freelist |
| 56364 | */ |
| 56365 | checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), |
| @@ -56890,11 +56895,16 @@ | |
| 56890 | /* |
| 56891 | ** Parameter zSrcData points to a buffer containing the data for |
| 56892 | ** page iSrcPg from the source database. Copy this data into the |
| 56893 | ** destination database. |
| 56894 | */ |
| 56895 | static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){ |
| 56896 | Pager * const pDestPager = sqlite3BtreePager(p->pDest); |
| 56897 | const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); |
| 56898 | int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); |
| 56899 | const int nCopy = MIN(nSrcPgsz, nDestPgsz); |
| 56900 | const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; |
| @@ -56963,10 +56973,13 @@ | |
| 56963 | ** cached parse of the page). MemPage.isInit is marked |
| 56964 | ** "MUST BE FIRST" for this purpose. |
| 56965 | */ |
| 56966 | memcpy(zOut, zIn, nCopy); |
| 56967 | ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; |
| 56968 | } |
| 56969 | sqlite3PagerUnref(pDestPg); |
| 56970 | } |
| 56971 | |
| 56972 | return rc; |
| @@ -57069,11 +57082,11 @@ | |
| 57069 | const Pgno iSrcPg = p->iNext; /* Source page number */ |
| 57070 | if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ |
| 57071 | DbPage *pSrcPg; /* Source page object */ |
| 57072 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); |
| 57073 | if( rc==SQLITE_OK ){ |
| 57074 | rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg)); |
| 57075 | sqlite3PagerUnref(pSrcPg); |
| 57076 | } |
| 57077 | } |
| 57078 | p->iNext++; |
| 57079 | } |
| @@ -57317,11 +57330,11 @@ | |
| 57317 | ** the new data into the backup. |
| 57318 | */ |
| 57319 | int rc; |
| 57320 | assert( p->pDestDb ); |
| 57321 | sqlite3_mutex_enter(p->pDestDb->mutex); |
| 57322 | rc = backupOnePage(p, iPage, aData); |
| 57323 | sqlite3_mutex_leave(p->pDestDb->mutex); |
| 57324 | assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); |
| 57325 | if( rc!=SQLITE_OK ){ |
| 57326 | p->rc = rc; |
| 57327 | } |
| @@ -59434,26 +59447,22 @@ | |
| 59434 | assert( pKeyInfo->aSortOrder!=0 ); |
| 59435 | sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); |
| 59436 | i = sqlite3Strlen30(zTemp); |
| 59437 | for(j=0; j<pKeyInfo->nField; j++){ |
| 59438 | CollSeq *pColl = pKeyInfo->aColl[j]; |
| 59439 | if( pColl ){ |
| 59440 | int n = sqlite3Strlen30(pColl->zName); |
| 59441 | if( i+n>nTemp-6 ){ |
| 59442 | memcpy(&zTemp[i],",...",4); |
| 59443 | break; |
| 59444 | } |
| 59445 | zTemp[i++] = ','; |
| 59446 | if( pKeyInfo->aSortOrder[j] ){ |
| 59447 | zTemp[i++] = '-'; |
| 59448 | } |
| 59449 | memcpy(&zTemp[i], pColl->zName,n+1); |
| 59450 | i += n; |
| 59451 | }else if( i+4<nTemp-6 ){ |
| 59452 | memcpy(&zTemp[i],",nil",4); |
| 59453 | i += 4; |
| 59454 | } |
| 59455 | } |
| 59456 | zTemp[i++] = ')'; |
| 59457 | zTemp[i] = 0; |
| 59458 | assert( i<nTemp ); |
| 59459 | break; |
| @@ -63839,11 +63848,13 @@ | |
| 63839 | #ifdef SQLITE_DEBUG |
| 63840 | /* |
| 63841 | ** Print the value of a register for tracing purposes: |
| 63842 | */ |
| 63843 | static void memTracePrint(FILE *out, Mem *p){ |
| 63844 | if( p->flags & MEM_Null ){ |
| 63845 | fprintf(out, " NULL"); |
| 63846 | }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ |
| 63847 | fprintf(out, " si:%lld", p->u.i); |
| 63848 | }else if( p->flags & MEM_Int ){ |
| 63849 | fprintf(out, " i:%lld", p->u.i); |
| @@ -64112,10 +64123,11 @@ | |
| 64112 | } af; |
| 64113 | struct OP_Concat_stack_vars { |
| 64114 | i64 nByte; |
| 64115 | } ag; |
| 64116 | struct OP_Remainder_stack_vars { |
| 64117 | int flags; /* Combined MEM_* flags from both inputs */ |
| 64118 | i64 iA; /* Integer value of left operand */ |
| 64119 | i64 iB; /* Integer value of right operand */ |
| 64120 | double rA; /* Real value of left operand */ |
| 64121 | double rB; /* Real value of right operand */ |
| @@ -65021,10 +65033,13 @@ | |
| 65021 | pOut = &aMem[pOp->p2]; |
| 65022 | assert( pOut!=pIn1 ); |
| 65023 | while( 1 ){ |
| 65024 | sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); |
| 65025 | Deephemeralize(pOut); |
| 65026 | REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut); |
| 65027 | if( (u.ae.n--)==0 ) break; |
| 65028 | pOut++; |
| 65029 | pIn1++; |
| 65030 | } |
| @@ -65214,10 +65229,11 @@ | |
| 65214 | case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ |
| 65215 | case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ |
| 65216 | case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ |
| 65217 | case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ |
| 65218 | #if 0 /* local variables moved into u.ah */ |
| 65219 | int flags; /* Combined MEM_* flags from both inputs */ |
| 65220 | i64 iA; /* Integer value of left operand */ |
| 65221 | i64 iB; /* Integer value of right operand */ |
| 65222 | double rA; /* Real value of left operand */ |
| 65223 | double rB; /* Real value of right operand */ |
| @@ -65231,10 +65247,11 @@ | |
| 65231 | u.ah.flags = pIn1->flags | pIn2->flags; |
| 65232 | if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; |
| 65233 | if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ |
| 65234 | u.ah.iA = pIn1->u.i; |
| 65235 | u.ah.iB = pIn2->u.i; |
| 65236 | switch( pOp->opcode ){ |
| 65237 | case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65238 | case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65239 | case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65240 | case OP_Divide: { |
| @@ -65251,10 +65268,11 @@ | |
| 65251 | } |
| 65252 | } |
| 65253 | pOut->u.i = u.ah.iB; |
| 65254 | MemSetTypeFlag(pOut, MEM_Int); |
| 65255 | }else{ |
| 65256 | fp_math: |
| 65257 | u.ah.rA = sqlite3VdbeRealValue(pIn1); |
| 65258 | u.ah.rB = sqlite3VdbeRealValue(pIn2); |
| 65259 | switch( pOp->opcode ){ |
| 65260 | case OP_Add: u.ah.rB += u.ah.rA; break; |
| @@ -65282,11 +65300,11 @@ | |
| 65282 | if( sqlite3IsNaN(u.ah.rB) ){ |
| 65283 | goto arithmetic_result_is_null; |
| 65284 | } |
| 65285 | pOut->r = u.ah.rB; |
| 65286 | MemSetTypeFlag(pOut, MEM_Real); |
| 65287 | if( (u.ah.flags & MEM_Real)==0 ){ |
| 65288 | sqlite3VdbeIntegerAffinity(pOut); |
| 65289 | } |
| 65290 | #endif |
| 65291 | } |
| 65292 | break; |
| @@ -65843,26 +65861,31 @@ | |
| 65843 | /* Opcode: Permutation * * * P4 * |
| 65844 | ** |
| 65845 | ** Set the permutation used by the OP_Compare operator to be the array |
| 65846 | ** of integers in P4. |
| 65847 | ** |
| 65848 | ** The permutation is only valid until the next OP_Permutation, OP_Compare, |
| 65849 | ** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur |
| 65850 | ** immediately prior to the OP_Compare. |
| 65851 | */ |
| 65852 | case OP_Permutation: { |
| 65853 | assert( pOp->p4type==P4_INTARRAY ); |
| 65854 | assert( pOp->p4.ai ); |
| 65855 | aPermute = pOp->p4.ai; |
| 65856 | break; |
| 65857 | } |
| 65858 | |
| 65859 | /* Opcode: Compare P1 P2 P3 P4 * |
| 65860 | ** |
| 65861 | ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this |
| 65862 | ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of |
| 65863 | ** the comparison for use by the next OP_Jump instruct. |
| 65864 | ** |
| 65865 | ** P4 is a KeyInfo structure that defines collating sequences and sort |
| 65866 | ** orders for the comparison. The permutation applies to registers |
| 65867 | ** only. The KeyInfo elements are used sequentially. |
| 65868 | ** |
| @@ -65880,10 +65903,11 @@ | |
| 65880 | int idx; |
| 65881 | CollSeq *pColl; /* Collating sequence to use on this term */ |
| 65882 | int bRev; /* True for DESCENDING sort order */ |
| 65883 | #endif /* local variables moved into u.al */ |
| 65884 | |
| 65885 | u.al.n = pOp->p3; |
| 65886 | u.al.pKeyInfo = pOp->p4.pKeyInfo; |
| 65887 | assert( u.al.n>0 ); |
| 65888 | assert( u.al.pKeyInfo!=0 ); |
| 65889 | u.al.p1 = pOp->p1; |
| @@ -66025,12 +66049,10 @@ | |
| 66025 | |
| 66026 | /* Opcode: Once P1 P2 * * * |
| 66027 | ** |
| 66028 | ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, |
| 66029 | ** set the flag and fall through to the next instruction. |
| 66030 | ** |
| 66031 | ** See also: JumpOnce |
| 66032 | */ |
| 66033 | case OP_Once: { /* jump */ |
| 66034 | assert( pOp->p1<p->nOnceFlag ); |
| 66035 | if( p->aOnceFlag[pOp->p1] ){ |
| 66036 | pc = pOp->p2-1; |
| @@ -71902,10 +71924,18 @@ | |
| 71902 | p->pReal = pReal; |
| 71903 | if( p->iSize>0 ){ |
| 71904 | assert(p->iSize<=p->nBuf); |
| 71905 | rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); |
| 71906 | } |
| 71907 | } |
| 71908 | } |
| 71909 | return rc; |
| 71910 | } |
| 71911 | |
| @@ -72565,10 +72595,19 @@ | |
| 72565 | ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 |
| 72566 | ** |
| 72567 | ** The result of random()%5 in the GROUP BY clause is probably different |
| 72568 | ** from the result in the result-set. We might fix this someday. Or |
| 72569 | ** then again, we might not... |
| 72570 | ** |
| 72571 | ** The nSubquery parameter specifies how many levels of subquery the |
| 72572 | ** alias is removed from the original expression. The usually value is |
| 72573 | ** zero but it might be more if the alias is contained within a subquery |
| 72574 | ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION |
| @@ -72589,45 +72628,40 @@ | |
| 72589 | assert( iCol>=0 && iCol<pEList->nExpr ); |
| 72590 | pOrig = pEList->a[iCol].pExpr; |
| 72591 | assert( pOrig!=0 ); |
| 72592 | assert( pOrig->flags & EP_Resolved ); |
| 72593 | db = pParse->db; |
| 72594 | if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ |
| 72595 | pDup = sqlite3ExprDup(db, pOrig, 0); |
| 72596 | incrAggFunctionDepth(pDup, nSubquery); |
| 72597 | pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); |
| 72598 | if( pDup==0 ) return; |
| 72599 | if( pEList->a[iCol].iAlias==0 ){ |
| 72600 | pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); |
| 72601 | } |
| 72602 | pDup->iTable = pEList->a[iCol].iAlias; |
| 72603 | }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){ |
| 72604 | pDup = sqlite3ExprDup(db, pOrig, 0); |
| 72605 | if( pDup==0 ) return; |
| 72606 | }else{ |
| 72607 | char *zToken = pOrig->u.zToken; |
| 72608 | assert( zToken!=0 ); |
| 72609 | pOrig->u.zToken = 0; |
| 72610 | pDup = sqlite3ExprDup(db, pOrig, 0); |
| 72611 | pOrig->u.zToken = zToken; |
| 72612 | if( pDup==0 ) return; |
| 72613 | assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 ); |
| 72614 | pDup->flags2 |= EP2_MallocedToken; |
| 72615 | pDup->u.zToken = sqlite3DbStrDup(db, zToken); |
| 72616 | } |
| 72617 | if( pExpr->flags & EP_ExpCollate ){ |
| 72618 | pDup->pColl = pExpr->pColl; |
| 72619 | pDup->flags |= EP_ExpCollate; |
| 72620 | } |
| 72621 | |
| 72622 | /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This |
| 72623 | ** prevents ExprDelete() from deleting the Expr structure itself, |
| 72624 | ** allowing it to be repopulated by the memcpy() on the following line. |
| 72625 | */ |
| 72626 | ExprSetProperty(pExpr, EP_Static); |
| 72627 | sqlite3ExprDelete(db, pExpr); |
| 72628 | memcpy(pExpr, pDup, sizeof(*pExpr)); |
| 72629 | sqlite3DbFree(db, pDup); |
| 72630 | } |
| 72631 | |
| 72632 | |
| 72633 | /* |
| @@ -72644,10 +72678,39 @@ | |
| 72644 | } |
| 72645 | } |
| 72646 | return 0; |
| 72647 | } |
| 72648 | |
| 72649 | |
| 72650 | /* |
| 72651 | ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up |
| 72652 | ** that name in the set of source tables in pSrcList and make the pExpr |
| 72653 | ** expression node refer back to that source column. The following changes |
| @@ -72699,44 +72762,63 @@ | |
| 72699 | |
| 72700 | /* Initialize the node to no-match */ |
| 72701 | pExpr->iTable = -1; |
| 72702 | pExpr->pTab = 0; |
| 72703 | ExprSetIrreducible(pExpr); |
| 72704 | |
| 72705 | /* Start at the inner-most context and move outward until a match is found */ |
| 72706 | while( pNC && cnt==0 ){ |
| 72707 | ExprList *pEList; |
| 72708 | SrcList *pSrcList = pNC->pSrcList; |
| 72709 | |
| 72710 | if( pSrcList ){ |
| 72711 | for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ |
| 72712 | Table *pTab; |
| 72713 | int iDb; |
| 72714 | Column *pCol; |
| 72715 | |
| 72716 | pTab = pItem->pTab; |
| 72717 | assert( pTab!=0 && pTab->zName!=0 ); |
| 72718 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 72719 | assert( pTab->nCol>0 ); |
| 72720 | if( zTab ){ |
| 72721 | if( pItem->zAlias ){ |
| 72722 | char *zTabName = pItem->zAlias; |
| 72723 | if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; |
| 72724 | }else{ |
| 72725 | char *zTabName = pTab->zName; |
| 72726 | if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){ |
| 72727 | continue; |
| 72728 | } |
| 72729 | if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ |
| 72730 | continue; |
| 72731 | } |
| 72732 | } |
| 72733 | } |
| 72734 | if( 0==(cntTab++) ){ |
| 72735 | pExpr->iTable = pItem->iCursor; |
| 72736 | pExpr->pTab = pTab; |
| 72737 | pSchema = pTab->pSchema; |
| 72738 | pMatch = pItem; |
| 72739 | } |
| 72740 | for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ |
| 72741 | if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ |
| 72742 | /* If there has been exactly one prior match and this match |
| @@ -72746,21 +72828,23 @@ | |
| 72746 | if( cnt==1 ){ |
| 72747 | if( pItem->jointype & JT_NATURAL ) continue; |
| 72748 | if( nameInUsingClause(pItem->pUsing, zCol) ) continue; |
| 72749 | } |
| 72750 | cnt++; |
| 72751 | pExpr->iTable = pItem->iCursor; |
| 72752 | pExpr->pTab = pTab; |
| 72753 | pMatch = pItem; |
| 72754 | pSchema = pTab->pSchema; |
| 72755 | /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ |
| 72756 | pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; |
| 72757 | break; |
| 72758 | } |
| 72759 | } |
| 72760 | } |
| 72761 | } |
| 72762 | |
| 72763 | #ifndef SQLITE_OMIT_TRIGGER |
| 72764 | /* If we have not already resolved the name, then maybe |
| 72765 | ** it is a new.* or old.* trigger argument reference |
| 72766 | */ |
| @@ -73055,42 +73139,43 @@ | |
| 73055 | int wrong_num_args = 0; /* True if wrong number of arguments */ |
| 73056 | int is_agg = 0; /* True if is an aggregate function */ |
| 73057 | int auth; /* Authorization to use the function */ |
| 73058 | int nId; /* Number of characters in function name */ |
| 73059 | const char *zId; /* The function name. */ |
| 73060 | FuncDef *pDef; /* Information about the function */ |
| 73061 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 73062 | |
| 73063 | testcase( pExpr->op==TK_CONST_FUNC ); |
| 73064 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 73065 | zId = pExpr->u.zToken; |
| 73066 | nId = sqlite3Strlen30(zId); |
| 73067 | pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); |
| 73068 | if( pDef==0 ){ |
| 73069 | pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); |
| 73070 | if( pDef==0 ){ |
| 73071 | no_such_func = 1; |
| 73072 | }else{ |
| 73073 | wrong_num_args = 1; |
| 73074 | } |
| 73075 | }else{ |
| 73076 | is_agg = pDef->xFunc==0; |
| 73077 | } |
| 73078 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 73079 | if( pDef ){ |
| 73080 | auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); |
| 73081 | if( auth!=SQLITE_OK ){ |
| 73082 | if( auth==SQLITE_DENY ){ |
| 73083 | sqlite3ErrorMsg(pParse, "not authorized to use function: %s", |
| 73084 | pDef->zName); |
| 73085 | pNC->nErr++; |
| 73086 | } |
| 73087 | pExpr->op = TK_NULL; |
| 73088 | return WRC_Prune; |
| 73089 | } |
| 73090 | } |
| 73091 | #endif |
| 73092 | if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ |
| 73093 | sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); |
| 73094 | pNC->nErr++; |
| 73095 | is_agg = 0; |
| 73096 | }else if( no_such_func ){ |
| @@ -73310,11 +73395,11 @@ | |
| 73310 | assert( pEList!=0 ); |
| 73311 | for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ |
| 73312 | int iCol = -1; |
| 73313 | Expr *pE, *pDup; |
| 73314 | if( pItem->done ) continue; |
| 73315 | pE = pItem->pExpr; |
| 73316 | if( sqlite3ExprIsInteger(pE, &iCol) ){ |
| 73317 | if( iCol<=0 || iCol>pEList->nExpr ){ |
| 73318 | resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); |
| 73319 | return 1; |
| 73320 | } |
| @@ -73328,18 +73413,24 @@ | |
| 73328 | } |
| 73329 | sqlite3ExprDelete(db, pDup); |
| 73330 | } |
| 73331 | } |
| 73332 | if( iCol>0 ){ |
| 73333 | CollSeq *pColl = pE->pColl; |
| 73334 | int flags = pE->flags & EP_ExpCollate; |
| 73335 | sqlite3ExprDelete(db, pE); |
| 73336 | pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0); |
| 73337 | if( pE==0 ) return 1; |
| 73338 | pE->pColl = pColl; |
| 73339 | pE->flags |= EP_IntValue | flags; |
| 73340 | pE->u.iValue = iCol; |
| 73341 | pItem->iOrderByCol = (u16)iCol; |
| 73342 | pItem->done = 1; |
| 73343 | }else{ |
| 73344 | moreToDo = 1; |
| 73345 | } |
| @@ -73440,15 +73531,15 @@ | |
| 73440 | ** sqlite3ResolveOrderGroupBy() will convert the expression to a |
| 73441 | ** copy of the iCol-th result-set expression. */ |
| 73442 | pItem->iOrderByCol = (u16)iCol; |
| 73443 | continue; |
| 73444 | } |
| 73445 | if( sqlite3ExprIsInteger(pE, &iCol) ){ |
| 73446 | /* The ORDER BY term is an integer constant. Again, set the column |
| 73447 | ** number so that sqlite3ResolveOrderGroupBy() will convert the |
| 73448 | ** order-by term to a copy of the result-set expression */ |
| 73449 | if( iCol<1 ){ |
| 73450 | resolveOutOfRangeError(pParse, zType, i+1, nResult); |
| 73451 | return 1; |
| 73452 | } |
| 73453 | pItem->iOrderByCol = (u16)iCol; |
| 73454 | continue; |
| @@ -73521,27 +73612,10 @@ | |
| 73521 | if( sqlite3ResolveExprNames(&sNC, p->pLimit) || |
| 73522 | sqlite3ResolveExprNames(&sNC, p->pOffset) ){ |
| 73523 | return WRC_Abort; |
| 73524 | } |
| 73525 | |
| 73526 | /* Set up the local name-context to pass to sqlite3ResolveExprNames() to |
| 73527 | ** resolve the result-set expression list. |
| 73528 | */ |
| 73529 | sNC.ncFlags = NC_AllowAgg; |
| 73530 | sNC.pSrcList = p->pSrc; |
| 73531 | sNC.pNext = pOuterNC; |
| 73532 | |
| 73533 | /* Resolve names in the result set. */ |
| 73534 | pEList = p->pEList; |
| 73535 | assert( pEList!=0 ); |
| 73536 | for(i=0; i<pEList->nExpr; i++){ |
| 73537 | Expr *pX = pEList->a[i].pExpr; |
| 73538 | if( sqlite3ResolveExprNames(&sNC, pX) ){ |
| 73539 | return WRC_Abort; |
| 73540 | } |
| 73541 | } |
| 73542 | |
| 73543 | /* Recursively resolve names in all subqueries |
| 73544 | */ |
| 73545 | for(i=0; i<p->pSrc->nSrc; i++){ |
| 73546 | struct SrcList_item *pItem = &p->pSrc->a[i]; |
| 73547 | if( pItem->pSelect ){ |
| @@ -73564,10 +73638,27 @@ | |
| 73564 | for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; |
| 73565 | assert( pItem->isCorrelated==0 && nRef<=0 ); |
| 73566 | pItem->isCorrelated = (nRef!=0); |
| 73567 | } |
| 73568 | } |
| 73569 | |
| 73570 | /* If there are no aggregate functions in the result-set, and no GROUP BY |
| 73571 | ** expression, do not allow aggregates in any of the other expressions. |
| 73572 | */ |
| 73573 | assert( (p->selFlags & SF_Aggregate)==0 ); |
| @@ -73798,11 +73889,13 @@ | |
| 73798 | ** SELECT * FROM t1 WHERE a; |
| 73799 | ** SELECT a AS b FROM t1 WHERE b; |
| 73800 | ** SELECT * FROM t1 WHERE (select a from t1); |
| 73801 | */ |
| 73802 | SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ |
| 73803 | int op = pExpr->op; |
| 73804 | if( op==TK_SELECT ){ |
| 73805 | assert( pExpr->flags&EP_xIsSelect ); |
| 73806 | return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); |
| 73807 | } |
| 73808 | #ifndef SQLITE_OMIT_CAST |
| @@ -73823,70 +73916,98 @@ | |
| 73823 | } |
| 73824 | return pExpr->affinity; |
| 73825 | } |
| 73826 | |
| 73827 | /* |
| 73828 | ** Set the explicit collating sequence for an expression to the |
| 73829 | ** collating sequence supplied in the second argument. |
| 73830 | */ |
| 73831 | SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){ |
| 73832 | if( pExpr && pColl ){ |
| 73833 | pExpr->pColl = pColl; |
| 73834 | pExpr->flags |= EP_ExpCollate; |
| 73835 | } |
| 73836 | return pExpr; |
| 73837 | } |
| 73838 | |
| 73839 | /* |
| 73840 | ** Set the collating sequence for expression pExpr to be the collating |
| 73841 | ** sequence named by pToken. Return a pointer to the revised expression. |
| 73842 | ** The collating sequence is marked as "explicit" using the EP_ExpCollate |
| 73843 | ** flag. An explicit collating sequence will override implicit |
| 73844 | ** collating sequences. |
| 73845 | */ |
| 73846 | SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){ |
| 73847 | char *zColl = 0; /* Dequoted name of collation sequence */ |
| 73848 | CollSeq *pColl; |
| 73849 | sqlite3 *db = pParse->db; |
| 73850 | zColl = sqlite3NameFromToken(db, pCollName); |
| 73851 | pColl = sqlite3LocateCollSeq(pParse, zColl); |
| 73852 | sqlite3ExprSetColl(pExpr, pColl); |
| 73853 | sqlite3DbFree(db, zColl); |
| 73854 | return pExpr; |
| 73855 | } |
| 73856 | |
| 73857 | /* |
| 73858 | ** Return the default collation sequence for the expression pExpr. If |
| 73859 | ** there is no default collation type, return 0. |
| 73860 | */ |
| 73861 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ |
| 73862 | CollSeq *pColl = 0; |
| 73863 | Expr *p = pExpr; |
| 73864 | while( p ){ |
| 73865 | int op; |
| 73866 | pColl = p->pColl; |
| 73867 | if( pColl ) break; |
| 73868 | op = p->op; |
| 73869 | if( p->pTab!=0 && ( |
| 73870 | op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER |
| 73871 | )){ |
| 73872 | /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally |
| 73873 | ** a TK_COLUMN but was previously evaluated and cached in a register */ |
| 73874 | const char *zColl; |
| 73875 | int j = p->iColumn; |
| 73876 | if( j>=0 ){ |
| 73877 | sqlite3 *db = pParse->db; |
| 73878 | zColl = p->pTab->aCol[j].zColl; |
| 73879 | pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); |
| 73880 | pExpr->pColl = pColl; |
| 73881 | } |
| 73882 | break; |
| 73883 | } |
| 73884 | if( op!=TK_CAST && op!=TK_UPLUS ){ |
| 73885 | break; |
| 73886 | } |
| 73887 | p = p->pLeft; |
| 73888 | } |
| 73889 | if( sqlite3CheckCollSeq(pParse, pColl) ){ |
| 73890 | pColl = 0; |
| 73891 | } |
| 73892 | return pColl; |
| @@ -73986,16 +74107,14 @@ | |
| 73986 | Expr *pLeft, |
| 73987 | Expr *pRight |
| 73988 | ){ |
| 73989 | CollSeq *pColl; |
| 73990 | assert( pLeft ); |
| 73991 | if( pLeft->flags & EP_ExpCollate ){ |
| 73992 | assert( pLeft->pColl ); |
| 73993 | pColl = pLeft->pColl; |
| 73994 | }else if( pRight && pRight->flags & EP_ExpCollate ){ |
| 73995 | assert( pRight->pColl ); |
| 73996 | pColl = pRight->pColl; |
| 73997 | }else{ |
| 73998 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 73999 | if( !pColl ){ |
| 74000 | pColl = sqlite3ExprCollSeq(pParse, pRight); |
| 74001 | } |
| @@ -74221,21 +74340,15 @@ | |
| 74221 | sqlite3ExprDelete(db, pLeft); |
| 74222 | sqlite3ExprDelete(db, pRight); |
| 74223 | }else{ |
| 74224 | if( pRight ){ |
| 74225 | pRoot->pRight = pRight; |
| 74226 | if( pRight->flags & EP_ExpCollate ){ |
| 74227 | pRoot->flags |= EP_ExpCollate; |
| 74228 | pRoot->pColl = pRight->pColl; |
| 74229 | } |
| 74230 | } |
| 74231 | if( pLeft ){ |
| 74232 | pRoot->pLeft = pLeft; |
| 74233 | if( pLeft->flags & EP_ExpCollate ){ |
| 74234 | pRoot->flags |= EP_ExpCollate; |
| 74235 | pRoot->pColl = pLeft->pColl; |
| 74236 | } |
| 74237 | } |
| 74238 | exprSetHeight(pRoot); |
| 74239 | } |
| 74240 | } |
| 74241 | |
| @@ -74489,11 +74602,11 @@ | |
| 74489 | }else{ |
| 74490 | assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); |
| 74491 | assert( !ExprHasProperty(p, EP_FromJoin) ); |
| 74492 | assert( (p->flags2 & EP2_MallocedToken)==0 ); |
| 74493 | assert( (p->flags2 & EP2_Irreducible)==0 ); |
| 74494 | if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ |
| 74495 | nSize = EXPR_REDUCEDSIZE | EP_Reduced; |
| 74496 | }else{ |
| 74497 | nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; |
| 74498 | } |
| 74499 | } |
| @@ -76513,10 +76626,11 @@ | |
| 76513 | sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); |
| 76514 | sqlite3ReleaseTempReg(pParse, r3); |
| 76515 | sqlite3ReleaseTempReg(pParse, r4); |
| 76516 | break; |
| 76517 | } |
| 76518 | case TK_UPLUS: { |
| 76519 | inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); |
| 76520 | break; |
| 76521 | } |
| 76522 | |
| @@ -76881,10 +76995,16 @@ | |
| 76881 | case TK_UPLUS: zUniOp = "UPLUS"; break; |
| 76882 | case TK_BITNOT: zUniOp = "BITNOT"; break; |
| 76883 | case TK_NOT: zUniOp = "NOT"; break; |
| 76884 | case TK_ISNULL: zUniOp = "ISNULL"; break; |
| 76885 | case TK_NOTNULL: zUniOp = "NOTNULL"; break; |
| 76886 | |
| 76887 | case TK_AGG_FUNCTION: |
| 76888 | case TK_CONST_FUNC: |
| 76889 | case TK_FUNCTION: { |
| 76890 | ExprList *pFarg; /* List of function arguments */ |
| @@ -77019,10 +77139,16 @@ | |
| 77019 | for(i=0; i<pList->nExpr; i++){ |
| 77020 | sqlite3ExplainPrintf(pOut, "item[%d] = ", i); |
| 77021 | sqlite3ExplainPush(pOut); |
| 77022 | sqlite3ExplainExpr(pOut, pList->a[i].pExpr); |
| 77023 | sqlite3ExplainPop(pOut); |
| 77024 | if( i<pList->nExpr-1 ){ |
| 77025 | sqlite3ExplainNL(pOut); |
| 77026 | } |
| 77027 | } |
| 77028 | sqlite3ExplainPop(pOut); |
| @@ -77100,10 +77226,13 @@ | |
| 77100 | switch( pExpr->op ){ |
| 77101 | case TK_IN: |
| 77102 | case TK_REGISTER: { |
| 77103 | return WRC_Prune; |
| 77104 | } |
| 77105 | case TK_FUNCTION: |
| 77106 | case TK_AGG_FUNCTION: |
| 77107 | case TK_CONST_FUNC: { |
| 77108 | /* The arguments to a function have a fixed destination. |
| 77109 | ** Mark them this way to avoid generated unneeded OP_SCopy |
| @@ -77121,13 +77250,15 @@ | |
| 77121 | break; |
| 77122 | } |
| 77123 | } |
| 77124 | if( isAppropriateForFactoring(pExpr) ){ |
| 77125 | int r1 = ++pParse->nMem; |
| 77126 | int r2; |
| 77127 | r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); |
| 77128 | if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1); |
| 77129 | pExpr->op2 = pExpr->op; |
| 77130 | pExpr->op = TK_REGISTER; |
| 77131 | pExpr->iTable = r2; |
| 77132 | return WRC_Prune; |
| 77133 | } |
| @@ -77540,11 +77671,19 @@ | |
| 77540 | assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); |
| 77541 | if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ |
| 77542 | return 2; |
| 77543 | } |
| 77544 | if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; |
| 77545 | if( pA->op!=pB->op ) return 2; |
| 77546 | if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; |
| 77547 | if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; |
| 77548 | if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; |
| 77549 | if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; |
| 77550 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| @@ -77552,15 +77691,13 @@ | |
| 77552 | return 2; |
| 77553 | } |
| 77554 | }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){ |
| 77555 | if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; |
| 77556 | if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 77557 | return 2; |
| 77558 | } |
| 77559 | } |
| 77560 | if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1; |
| 77561 | if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2; |
| 77562 | return 0; |
| 77563 | } |
| 77564 | |
| 77565 | /* |
| 77566 | ** Compare two ExprList objects. Return 0 if they are identical and |
| @@ -83371,14 +83508,12 @@ | |
| 83371 | ** specified collation sequence names. |
| 83372 | */ |
| 83373 | for(i=0; i<pList->nExpr; i++){ |
| 83374 | Expr *pExpr = pList->a[i].pExpr; |
| 83375 | if( pExpr ){ |
| 83376 | CollSeq *pColl = pExpr->pColl; |
| 83377 | /* Either pColl!=0 or there was an OOM failure. But if an OOM |
| 83378 | ** failure we have quit before reaching this point. */ |
| 83379 | if( ALWAYS(pColl) ){ |
| 83380 | nExtra += (1 + sqlite3Strlen30(pColl->zName)); |
| 83381 | } |
| 83382 | } |
| 83383 | } |
| 83384 | |
| @@ -83437,10 +83572,11 @@ | |
| 83437 | */ |
| 83438 | for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ |
| 83439 | const char *zColName = pListItem->zName; |
| 83440 | Column *pTabCol; |
| 83441 | int requestedSortOrder; |
| 83442 | char *zColl; /* Collation sequence name */ |
| 83443 | |
| 83444 | for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ |
| 83445 | if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; |
| 83446 | } |
| @@ -83449,18 +83585,15 @@ | |
| 83449 | pTab->zName, zColName); |
| 83450 | pParse->checkSchema = 1; |
| 83451 | goto exit_create_index; |
| 83452 | } |
| 83453 | pIndex->aiColumn[i] = j; |
| 83454 | /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of |
| 83455 | ** the way the "idxlist" non-terminal is constructed by the parser, |
| 83456 | ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl |
| 83457 | ** must exist or else there must have been an OOM error. But if there |
| 83458 | ** was an OOM error, we would never reach this point. */ |
| 83459 | if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){ |
| 83460 | int nColl; |
| 83461 | zColl = pListItem->pExpr->pColl->zName; |
| 83462 | nColl = sqlite3Strlen30(zColl) + 1; |
| 83463 | assert( nExtra>=nColl ); |
| 83464 | memcpy(zExtra, zColl, nColl); |
| 83465 | zColl = zExtra; |
| 83466 | zExtra += nColl; |
| @@ -87489,11 +87622,11 @@ | |
| 87489 | |
| 87490 | /* |
| 87491 | ** A foreign key constraint requires that the key columns in the parent |
| 87492 | ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. |
| 87493 | ** Given that pParent is the parent table for foreign key constraint pFKey, |
| 87494 | ** search the schema a unique index on the parent key columns. |
| 87495 | ** |
| 87496 | ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY |
| 87497 | ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx |
| 87498 | ** is set to point to the unique index. |
| 87499 | ** |
| @@ -87525,11 +87658,11 @@ | |
| 87525 | ** |
| 87526 | ** then non-zero is returned, and a "foreign key mismatch" error loaded |
| 87527 | ** into pParse. If an OOM error occurs, non-zero is returned and the |
| 87528 | ** pParse->db->mallocFailed flag is set. |
| 87529 | */ |
| 87530 | static int locateFkeyIndex( |
| 87531 | Parse *pParse, /* Parse context to store any error in */ |
| 87532 | Table *pParent, /* Parent table of FK constraint pFKey */ |
| 87533 | FKey *pFKey, /* Foreign key to find index for */ |
| 87534 | Index **ppIdx, /* OUT: Unique index on parent table */ |
| 87535 | int **paiCol /* OUT: Map of index columns in pFKey */ |
| @@ -87622,11 +87755,13 @@ | |
| 87622 | } |
| 87623 | } |
| 87624 | |
| 87625 | if( !pIdx ){ |
| 87626 | if( !pParse->disableTriggers ){ |
| 87627 | sqlite3ErrorMsg(pParse, "foreign key mismatch"); |
| 87628 | } |
| 87629 | sqlite3DbFree(pParse->db, aiCol); |
| 87630 | return 1; |
| 87631 | } |
| 87632 | |
| @@ -87858,16 +87993,19 @@ | |
| 87858 | if( pLeft ){ |
| 87859 | /* Set the collation sequence and affinity of the LHS of each TK_EQ |
| 87860 | ** expression to the parent key column defaults. */ |
| 87861 | if( pIdx ){ |
| 87862 | Column *pCol; |
| 87863 | iCol = pIdx->aiColumn[i]; |
| 87864 | pCol = &pTab->aCol[iCol]; |
| 87865 | if( pTab->iPKey==iCol ) iCol = -1; |
| 87866 | pLeft->iTable = regData+iCol+1; |
| 87867 | pLeft->affinity = pCol->affinity; |
| 87868 | pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl); |
| 87869 | }else{ |
| 87870 | pLeft->iTable = regData; |
| 87871 | pLeft->affinity = SQLITE_AFF_INTEGER; |
| 87872 | } |
| 87873 | } |
| @@ -88080,11 +88218,11 @@ | |
| 88080 | if( pParse->disableTriggers ){ |
| 88081 | pTo = sqlite3FindTable(db, pFKey->zTo, zDb); |
| 88082 | }else{ |
| 88083 | pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); |
| 88084 | } |
| 88085 | if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ |
| 88086 | assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); |
| 88087 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88088 | if( pTo==0 ){ |
| 88089 | /* If isIgnoreErrors is true, then a table is being dropped. In this |
| 88090 | ** case SQLite runs a "DELETE FROM xxx" on the table being dropped |
| @@ -88160,11 +88298,11 @@ | |
| 88160 | /* Inserting a single row into a parent table cannot cause an immediate |
| 88161 | ** foreign key violation. So do nothing in this case. */ |
| 88162 | continue; |
| 88163 | } |
| 88164 | |
| 88165 | if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 88166 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88167 | continue; |
| 88168 | } |
| 88169 | assert( aiCol || pFKey->nCol==1 ); |
| 88170 | |
| @@ -88215,11 +88353,11 @@ | |
| 88215 | for(p=pTab->pFKey; p; p=p->pNextFrom){ |
| 88216 | for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); |
| 88217 | } |
| 88218 | for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
| 88219 | Index *pIdx = 0; |
| 88220 | locateFkeyIndex(pParse, pTab, p, &pIdx, 0); |
| 88221 | if( pIdx ){ |
| 88222 | for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); |
| 88223 | } |
| 88224 | } |
| 88225 | } |
| @@ -88341,11 +88479,11 @@ | |
| 88341 | ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ |
| 88342 | Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ |
| 88343 | int i; /* Iterator variable */ |
| 88344 | Expr *pWhen = 0; /* WHEN clause for the trigger */ |
| 88345 | |
| 88346 | if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; |
| 88347 | assert( aiCol || pFKey->nCol==1 ); |
| 88348 | |
| 88349 | for(i=0; i<pFKey->nCol; i++){ |
| 88350 | Token tOld = { "old", 3 }; /* Literal "old" token */ |
| 88351 | Token tNew = { "new", 3 }; /* Literal "new" token */ |
| @@ -89843,29 +89981,24 @@ | |
| 89843 | ExprList *pCheck = pTab->pCheck; |
| 89844 | pParse->ckBase = regData; |
| 89845 | onError = overrideError!=OE_Default ? overrideError : OE_Abort; |
| 89846 | for(i=0; i<pCheck->nExpr; i++){ |
| 89847 | int allOk = sqlite3VdbeMakeLabel(v); |
| 89848 | Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0); |
| 89849 | if( !db->mallocFailed ){ |
| 89850 | assert( pDup!=0 ); |
| 89851 | sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL); |
| 89852 | if( onError==OE_Ignore ){ |
| 89853 | sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); |
| 89854 | }else{ |
| 89855 | char *zConsName = pCheck->a[i].zName; |
| 89856 | if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ |
| 89857 | if( zConsName ){ |
| 89858 | zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); |
| 89859 | }else{ |
| 89860 | zConsName = 0; |
| 89861 | } |
| 89862 | sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); |
| 89863 | } |
| 89864 | sqlite3VdbeResolveLabel(v, allOk); |
| 89865 | } |
| 89866 | sqlite3ExprDelete(db, pDup); |
| 89867 | } |
| 89868 | } |
| 89869 | #endif /* !defined(SQLITE_OMIT_CHECK) */ |
| 89870 | |
| 89871 | /* If we have an INTEGER PRIMARY KEY, make sure the primary key |
| @@ -92686,13 +92819,15 @@ | |
| 92686 | if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ |
| 92687 | Table *pTab; |
| 92688 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 92689 | pTab = sqlite3FindTable(db, zRight, zDb); |
| 92690 | if( pTab ){ |
| 92691 | int i; |
| 92692 | int nHidden = 0; |
| 92693 | Column *pCol; |
| 92694 | sqlite3VdbeSetNumCols(v, 6); |
| 92695 | pParse->nMem = 6; |
| 92696 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); |
| 92697 | sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); |
| 92698 | sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); |
| @@ -92713,12 +92848,18 @@ | |
| 92713 | if( pCol->zDflt ){ |
| 92714 | sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); |
| 92715 | }else{ |
| 92716 | sqlite3VdbeAddOp2(v, OP_Null, 0, 5); |
| 92717 | } |
| 92718 | sqlite3VdbeAddOp2(v, OP_Integer, |
| 92719 | (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6); |
| 92720 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); |
| 92721 | } |
| 92722 | } |
| 92723 | }else |
| 92724 | |
| @@ -92849,10 +92990,124 @@ | |
| 92849 | ++i; |
| 92850 | pFK = pFK->pNextFrom; |
| 92851 | } |
| 92852 | } |
| 92853 | } |
| 92854 | }else |
| 92855 | #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
| 92856 | |
| 92857 | #ifndef NDEBUG |
| 92858 | if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ |
| @@ -94308,11 +94563,11 @@ | |
| 94308 | SrcList *pSrc, /* the FROM clause -- which tables to scan */ |
| 94309 | Expr *pWhere, /* the WHERE clause */ |
| 94310 | ExprList *pGroupBy, /* the GROUP BY clause */ |
| 94311 | Expr *pHaving, /* the HAVING clause */ |
| 94312 | ExprList *pOrderBy, /* the ORDER BY clause */ |
| 94313 | int isDistinct, /* true if the DISTINCT keyword is present */ |
| 94314 | Expr *pLimit, /* LIMIT value. NULL means not used */ |
| 94315 | Expr *pOffset /* OFFSET value. NULL means no offset */ |
| 94316 | ){ |
| 94317 | Select *pNew; |
| 94318 | Select standin; |
| @@ -94332,11 +94587,11 @@ | |
| 94332 | pNew->pSrc = pSrc; |
| 94333 | pNew->pWhere = pWhere; |
| 94334 | pNew->pGroupBy = pGroupBy; |
| 94335 | pNew->pHaving = pHaving; |
| 94336 | pNew->pOrderBy = pOrderBy; |
| 94337 | pNew->selFlags = isDistinct ? SF_Distinct : 0; |
| 94338 | pNew->op = TK_SELECT; |
| 94339 | pNew->pLimit = pLimit; |
| 94340 | pNew->pOffset = pOffset; |
| 94341 | assert( pOffset==0 || pLimit!=0 ); |
| 94342 | pNew->addrOpenEphm[0] = -1; |
| @@ -95588,13 +95843,11 @@ | |
| 95588 | *paCol = aCol; |
| 95589 | |
| 95590 | for(i=0, pCol=aCol; i<nCol; i++, pCol++){ |
| 95591 | /* Get an appropriate name for the column |
| 95592 | */ |
| 95593 | p = pEList->a[i].pExpr; |
| 95594 | assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue) |
| 95595 | || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 ); |
| 95596 | if( (zName = pEList->a[i].zName)!=0 ){ |
| 95597 | /* If the column contains an "AS <name>" phrase, use <name> as the name */ |
| 95598 | zName = sqlite3DbStrDup(db, zName); |
| 95599 | }else{ |
| 95600 | Expr *pColExpr = p; /* The expression that is the result column name */ |
| @@ -95628,10 +95881,13 @@ | |
| 95628 | */ |
| 95629 | nName = sqlite3Strlen30(zName); |
| 95630 | for(j=cnt=0; j<i; j++){ |
| 95631 | if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ |
| 95632 | char *zNewName; |
| 95633 | zName[nName] = 0; |
| 95634 | zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); |
| 95635 | sqlite3DbFree(db, zName); |
| 95636 | zName = zNewName; |
| 95637 | j = -1; |
| @@ -96586,16 +96842,17 @@ | |
| 96586 | pKeyMerge->nField = (u16)nOrderBy; |
| 96587 | pKeyMerge->enc = ENC(db); |
| 96588 | for(i=0; i<nOrderBy; i++){ |
| 96589 | CollSeq *pColl; |
| 96590 | Expr *pTerm = pOrderBy->a[i].pExpr; |
| 96591 | if( pTerm->flags & EP_ExpCollate ){ |
| 96592 | pColl = pTerm->pColl; |
| 96593 | }else{ |
| 96594 | pColl = multiSelectCollSeq(pParse, p, aPermute[i]); |
| 96595 | pTerm->flags |= EP_ExpCollate; |
| 96596 | pTerm->pColl = pColl; |
| 96597 | } |
| 96598 | pKeyMerge->aColl[i] = pColl; |
| 96599 | pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; |
| 96600 | } |
| 96601 | } |
| @@ -96794,10 +97051,11 @@ | |
| 96794 | */ |
| 96795 | sqlite3VdbeResolveLabel(v, labelCmpr); |
| 96796 | sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); |
| 96797 | sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, |
| 96798 | (char*)pKeyMerge, P4_KEYINFO_HANDOFF); |
| 96799 | sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); |
| 96800 | |
| 96801 | /* Release temporary registers |
| 96802 | */ |
| 96803 | if( regPrev ){ |
| @@ -96861,13 +97119,10 @@ | |
| 96861 | }else{ |
| 96862 | Expr *pNew; |
| 96863 | assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); |
| 96864 | assert( pExpr->pLeft==0 && pExpr->pRight==0 ); |
| 96865 | pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); |
| 96866 | if( pNew && pExpr->pColl ){ |
| 96867 | pNew->pColl = pExpr->pColl; |
| 96868 | } |
| 96869 | sqlite3ExprDelete(db, pExpr); |
| 96870 | pExpr = pNew; |
| 96871 | } |
| 96872 | }else{ |
| 96873 | pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); |
| @@ -97414,38 +97669,47 @@ | |
| 97414 | return 1; |
| 97415 | } |
| 97416 | #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
| 97417 | |
| 97418 | /* |
| 97419 | ** Analyze the SELECT statement passed as an argument to see if it |
| 97420 | ** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if |
| 97421 | ** it is, or 0 otherwise. At present, a query is considered to be |
| 97422 | ** a min()/max() query if: |
| 97423 | ** |
| 97424 | ** 1. There is a single object in the FROM clause. |
| 97425 | ** |
| 97426 | ** 2. There is a single expression in the result set, and it is |
| 97427 | ** either min(x) or max(x), where x is a column reference. |
| 97428 | */ |
| 97429 | static u8 minMaxQuery(Select *p){ |
| 97430 | Expr *pExpr; |
| 97431 | ExprList *pEList = p->pEList; |
| 97432 | |
| 97433 | if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL; |
| 97434 | pExpr = pEList->a[0].pExpr; |
| 97435 | if( pExpr->op!=TK_AGG_FUNCTION ) return 0; |
| 97436 | if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0; |
| 97437 | pEList = pExpr->x.pList; |
| 97438 | if( pEList==0 || pEList->nExpr!=1 ) return 0; |
| 97439 | if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL; |
| 97440 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 97441 | if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){ |
| 97442 | return WHERE_ORDERBY_MIN; |
| 97443 | }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){ |
| 97444 | return WHERE_ORDERBY_MAX; |
| 97445 | } |
| 97446 | return WHERE_ORDERBY_NORMAL; |
| 97447 | } |
| 97448 | |
| 97449 | /* |
| 97450 | ** The select statement passed as the first argument is an aggregate query. |
| 97451 | ** The second argment is the associated aggregate-info object. This |
| @@ -97536,10 +97800,11 @@ | |
| 97536 | int i, j, k; |
| 97537 | SrcList *pTabList; |
| 97538 | ExprList *pEList; |
| 97539 | struct SrcList_item *pFrom; |
| 97540 | sqlite3 *db = pParse->db; |
| 97541 | |
| 97542 | if( db->mallocFailed ){ |
| 97543 | return WRC_Abort; |
| 97544 | } |
| 97545 | if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){ |
| @@ -97621,11 +97886,11 @@ | |
| 97621 | ** |
| 97622 | ** The first loop just checks to see if there are any "*" operators |
| 97623 | ** that need expanding. |
| 97624 | */ |
| 97625 | for(k=0; k<pEList->nExpr; k++){ |
| 97626 | Expr *pE = pEList->a[k].pExpr; |
| 97627 | if( pE->op==TK_ALL ) break; |
| 97628 | assert( pE->op!=TK_DOT || pE->pRight!=0 ); |
| 97629 | assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); |
| 97630 | if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; |
| 97631 | } |
| @@ -97639,14 +97904,22 @@ | |
| 97639 | ExprList *pNew = 0; |
| 97640 | int flags = pParse->db->flags; |
| 97641 | int longNames = (flags & SQLITE_FullColNames)!=0 |
| 97642 | && (flags & SQLITE_ShortColNames)==0; |
| 97643 | |
| 97644 | for(k=0; k<pEList->nExpr; k++){ |
| 97645 | Expr *pE = a[k].pExpr; |
| 97646 | assert( pE->op!=TK_DOT || pE->pRight!=0 ); |
| 97647 | if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){ |
| 97648 | /* This particular expression does not need to be expanded. |
| 97649 | */ |
| 97650 | pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); |
| 97651 | if( pNew ){ |
| 97652 | pNew->a[pNew->nExpr-1].zName = a[k].zName; |
| @@ -97657,44 +97930,56 @@ | |
| 97657 | a[k].pExpr = 0; |
| 97658 | }else{ |
| 97659 | /* This expression is a "*" or a "TABLE.*" and needs to be |
| 97660 | ** expanded. */ |
| 97661 | int tableSeen = 0; /* Set to 1 when TABLE matches */ |
| 97662 | char *zTName; /* text of name of TABLE */ |
| 97663 | if( pE->op==TK_DOT ){ |
| 97664 | assert( pE->pLeft!=0 ); |
| 97665 | assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); |
| 97666 | zTName = pE->pLeft->u.zToken; |
| 97667 | }else{ |
| 97668 | zTName = 0; |
| 97669 | } |
| 97670 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 97671 | Table *pTab = pFrom->pTab; |
| 97672 | char *zTabName = pFrom->zAlias; |
| 97673 | if( zTabName==0 ){ |
| 97674 | zTabName = pTab->zName; |
| 97675 | } |
| 97676 | if( db->mallocFailed ) break; |
| 97677 | if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ |
| 97678 | continue; |
| 97679 | } |
| 97680 | tableSeen = 1; |
| 97681 | for(j=0; j<pTab->nCol; j++){ |
| 97682 | Expr *pExpr, *pRight; |
| 97683 | char *zName = pTab->aCol[j].zName; |
| 97684 | char *zColname; /* The computed column name */ |
| 97685 | char *zToFree; /* Malloced string that needs to be freed */ |
| 97686 | Token sColname; /* Computed column name as a token */ |
| 97687 | |
| 97688 | /* If a column is marked as 'hidden' (currently only possible |
| 97689 | ** for virtual tables), do not include it in the expanded |
| 97690 | ** result-set list. |
| 97691 | */ |
| 97692 | if( IsHiddenColumn(&pTab->aCol[j]) ){ |
| 97693 | assert(IsVirtual(pTab)); |
| 97694 | continue; |
| 97695 | } |
| 97696 | |
| 97697 | if( i>0 && zTName==0 ){ |
| 97698 | if( (pFrom->jointype & JT_NATURAL)!=0 |
| 97699 | && tableAndColumnIndex(pTabList, i, zName, 0, 0) |
| 97700 | ){ |
| @@ -97713,10 +97998,14 @@ | |
| 97713 | zToFree = 0; |
| 97714 | if( longNames || pTabList->nSrc>1 ){ |
| 97715 | Expr *pLeft; |
| 97716 | pLeft = sqlite3Expr(db, TK_ID, zTabName); |
| 97717 | pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); |
| 97718 | if( longNames ){ |
| 97719 | zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); |
| 97720 | zToFree = zColname; |
| 97721 | } |
| 97722 | }else{ |
| @@ -97724,10 +98013,22 @@ | |
| 97724 | } |
| 97725 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
| 97726 | sColname.z = zColname; |
| 97727 | sColname.n = sqlite3Strlen30(zColname); |
| 97728 | sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
| 97729 | sqlite3DbFree(db, zToFree); |
| 97730 | } |
| 97731 | } |
| 97732 | if( !tableSeen ){ |
| 97733 | if( zTName ){ |
| @@ -98781,15 +99082,21 @@ | |
| 98781 | ** index or indices to use) should place a different priority on |
| 98782 | ** satisfying the 'ORDER BY' clause than it does in other cases. |
| 98783 | ** Refer to code and comments in where.c for details. |
| 98784 | */ |
| 98785 | ExprList *pMinMax = 0; |
| 98786 | u8 flag = minMaxQuery(p); |
| 98787 | if( flag ){ |
| 98788 | assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) ); |
| 98789 | assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 ); |
| 98790 | pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0); |
| 98791 | pDel = pMinMax; |
| 98792 | if( pMinMax && !db->mallocFailed ){ |
| 98793 | pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
| 98794 | pMinMax->a[0].pExpr->op = TK_COLUMN; |
| 98795 | } |
| @@ -102673,11 +102980,11 @@ | |
| 102673 | #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ |
| 102674 | #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ |
| 102675 | #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ |
| 102676 | #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ |
| 102677 | #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ |
| 102678 | #define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */ |
| 102679 | #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */ |
| 102680 | #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */ |
| 102681 | #define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */ |
| 102682 | #define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */ |
| 102683 | #define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */ |
| @@ -102823,11 +103130,11 @@ | |
| 102823 | sqlite3DbFree(db, pOld); |
| 102824 | } |
| 102825 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 102826 | } |
| 102827 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 102828 | pTerm->pExpr = p; |
| 102829 | pTerm->wtFlags = wtFlags; |
| 102830 | pTerm->pWC = pWC; |
| 102831 | pTerm->iParent = -1; |
| 102832 | return idx; |
| 102833 | } |
| @@ -102983,27 +103290,36 @@ | |
| 102983 | |
| 102984 | /* |
| 102985 | ** Commute a comparison operator. Expressions of the form "X op Y" |
| 102986 | ** are converted into "Y op X". |
| 102987 | ** |
| 102988 | ** If a collation sequence is associated with either the left or right |
| 102989 | ** side of the comparison, it remains associated with the same side after |
| 102990 | ** the commutation. So "Y collate NOCASE op X" becomes |
| 102991 | ** "X collate NOCASE op Y". This is because any collation sequence on |
| 102992 | ** the left hand side of a comparison overrides any collation sequence |
| 102993 | ** attached to the right. For the same reason the EP_ExpCollate flag |
| 102994 | ** is not commuted. |
| 102995 | */ |
| 102996 | static void exprCommute(Parse *pParse, Expr *pExpr){ |
| 102997 | u16 expRight = (pExpr->pRight->flags & EP_ExpCollate); |
| 102998 | u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate); |
| 102999 | assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); |
| 103000 | pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); |
| 103001 | pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); |
| 103002 | SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl); |
| 103003 | pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft; |
| 103004 | pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight; |
| 103005 | SWAP(Expr*,pExpr->pRight,pExpr->pLeft); |
| 103006 | if( pExpr->op>=TK_GT ){ |
| 103007 | assert( TK_LT==TK_GT+2 ); |
| 103008 | assert( TK_GE==TK_LE+2 ); |
| 103009 | assert( TK_GT>TK_EQ ); |
| @@ -103076,16 +103392,16 @@ | |
| 103076 | ** it to be useful for optimising expression pX. Store this |
| 103077 | ** value in variable pColl. |
| 103078 | */ |
| 103079 | assert(pX->pLeft); |
| 103080 | pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| 103081 | assert(pColl || pParse->nErr); |
| 103082 | |
| 103083 | for(j=0; pIdx->aiColumn[j]!=iColumn; j++){ |
| 103084 | if( NEVER(j>=pIdx->nColumn) ) return 0; |
| 103085 | } |
| 103086 | if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; |
| 103087 | } |
| 103088 | return pTerm; |
| 103089 | } |
| 103090 | } |
| 103091 | } |
| @@ -103600,10 +103916,11 @@ | |
| 103600 | return; |
| 103601 | } |
| 103602 | pTerm = &pWC->a[idxTerm]; |
| 103603 | pMaskSet = pWC->pMaskSet; |
| 103604 | pExpr = pTerm->pExpr; |
| 103605 | prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); |
| 103606 | op = pExpr->op; |
| 103607 | if( op==TK_IN ){ |
| 103608 | assert( pExpr->pRight==0 ); |
| 103609 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| @@ -103626,12 +103943,12 @@ | |
| 103626 | pTerm->prereqAll = prereqAll; |
| 103627 | pTerm->leftCursor = -1; |
| 103628 | pTerm->iParent = -1; |
| 103629 | pTerm->eOperator = 0; |
| 103630 | if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ |
| 103631 | Expr *pLeft = pExpr->pLeft; |
| 103632 | Expr *pRight = pExpr->pRight; |
| 103633 | if( pLeft->op==TK_COLUMN ){ |
| 103634 | pTerm->leftCursor = pLeft->iTable; |
| 103635 | pTerm->u.leftColumn = pLeft->iColumn; |
| 103636 | pTerm->eOperator = operatorMask(op); |
| 103637 | } |
| @@ -103655,11 +103972,11 @@ | |
| 103655 | }else{ |
| 103656 | pDup = pExpr; |
| 103657 | pNew = pTerm; |
| 103658 | } |
| 103659 | exprCommute(pParse, pDup); |
| 103660 | pLeft = pDup->pLeft; |
| 103661 | pNew->leftCursor = pLeft->iTable; |
| 103662 | pNew->u.leftColumn = pLeft->iColumn; |
| 103663 | testcase( (prereqLeft | extraRight) != prereqLeft ); |
| 103664 | pNew->prereqRight = prereqLeft | extraRight; |
| 103665 | pNew->prereqAll = prereqAll; |
| @@ -103734,11 +104051,11 @@ | |
| 103734 | Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ |
| 103735 | Expr *pNewExpr1; |
| 103736 | Expr *pNewExpr2; |
| 103737 | int idxNew1; |
| 103738 | int idxNew2; |
| 103739 | CollSeq *pColl; /* Collating sequence to use */ |
| 103740 | |
| 103741 | pLeft = pExpr->x.pList->a[1].pExpr; |
| 103742 | pStr2 = sqlite3ExprDup(db, pStr1, 0); |
| 103743 | if( !db->mallocFailed ){ |
| 103744 | u8 c, *pC; /* Last character before the first wildcard */ |
| @@ -103756,20 +104073,23 @@ | |
| 103756 | |
| 103757 | c = sqlite3UpperToLower[c]; |
| 103758 | } |
| 103759 | *pC = c + 1; |
| 103760 | } |
| 103761 | pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0); |
| 103762 | pNewExpr1 = sqlite3PExpr(pParse, TK_GE, |
| 103763 | sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl), |
| 103764 | pStr1, 0); |
| 103765 | idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); |
| 103766 | testcase( idxNew1==0 ); |
| 103767 | exprAnalyze(pSrc, pWC, idxNew1); |
| 103768 | pNewExpr2 = sqlite3PExpr(pParse, TK_LT, |
| 103769 | sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl), |
| 103770 | pStr2, 0); |
| 103771 | idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); |
| 103772 | testcase( idxNew2==0 ); |
| 103773 | exprAnalyze(pSrc, pWC, idxNew2); |
| 103774 | pTerm = &pWC->a[idxTerm]; |
| 103775 | if( isComplete ){ |
| @@ -103883,16 +104203,16 @@ | |
| 103883 | ){ |
| 103884 | int i; |
| 103885 | const char *zColl = pIdx->azColl[iCol]; |
| 103886 | |
| 103887 | for(i=0; i<pList->nExpr; i++){ |
| 103888 | Expr *p = pList->a[i].pExpr; |
| 103889 | if( p->op==TK_COLUMN |
| 103890 | && p->iColumn==pIdx->aiColumn[iCol] |
| 103891 | && p->iTable==iBase |
| 103892 | ){ |
| 103893 | CollSeq *pColl = sqlite3ExprCollSeq(pParse, p); |
| 103894 | if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ |
| 103895 | return i; |
| 103896 | } |
| 103897 | } |
| 103898 | } |
| @@ -103935,11 +104255,11 @@ | |
| 103935 | ** matching "col=X" expression and the column is on the same table as pIdx, |
| 103936 | ** set the corresponding bit in variable mask. |
| 103937 | */ |
| 103938 | for(i=0; i<pDistinct->nExpr; i++){ |
| 103939 | WhereTerm *pTerm; |
| 103940 | Expr *p = pDistinct->a[i].pExpr; |
| 103941 | if( p->op!=TK_COLUMN ) return 0; |
| 103942 | pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0); |
| 103943 | if( pTerm ){ |
| 103944 | Expr *pX = pTerm->pExpr; |
| 103945 | CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| @@ -103987,11 +104307,11 @@ | |
| 103987 | /* If any of the expressions is an IPK column on table iBase, then return |
| 103988 | ** true. Note: The (p->iTable==iBase) part of this test may be false if the |
| 103989 | ** current SELECT is a correlated sub-query. |
| 103990 | */ |
| 103991 | for(i=0; i<pDistinct->nExpr; i++){ |
| 103992 | Expr *p = pDistinct->a[i].pExpr; |
| 103993 | if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; |
| 103994 | } |
| 103995 | |
| 103996 | /* Loop through all indices on the table, checking each to see if it makes |
| 103997 | ** the DISTINCT qualifier redundant. It does so if: |
| @@ -104464,11 +104784,11 @@ | |
| 104464 | for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104465 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104466 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104467 | testcase( pTerm->eOperator==WO_IN ); |
| 104468 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104469 | if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; |
| 104470 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104471 | nTerm++; |
| 104472 | } |
| 104473 | |
| 104474 | /* If the ORDER BY clause contains only columns in the current |
| @@ -104512,29 +104832,32 @@ | |
| 104512 | *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; |
| 104513 | *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = |
| 104514 | pUsage; |
| 104515 | |
| 104516 | for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104517 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104518 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104519 | testcase( pTerm->eOperator==WO_IN ); |
| 104520 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104521 | if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; |
| 104522 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104523 | pIdxCons[j].iColumn = pTerm->u.leftColumn; |
| 104524 | pIdxCons[j].iTermOffset = i; |
| 104525 | pIdxCons[j].op = (u8)pTerm->eOperator; |
| 104526 | /* The direct assignment in the previous line is possible only because |
| 104527 | ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The |
| 104528 | ** following asserts verify this fact. */ |
| 104529 | assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); |
| 104530 | assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); |
| 104531 | assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); |
| 104532 | assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); |
| 104533 | assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); |
| 104534 | assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); |
| 104535 | assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); |
| 104536 | j++; |
| 104537 | } |
| 104538 | for(i=0; i<nOrderBy; i++){ |
| 104539 | Expr *pExpr = pOrderBy->a[i].pExpr; |
| 104540 | pIdxOrderBy[i].iColumn = pExpr->iColumn; |
| @@ -104616,10 +104939,11 @@ | |
| 104616 | struct sqlite3_index_constraint *pIdxCons; |
| 104617 | struct sqlite3_index_constraint_usage *pUsage; |
| 104618 | WhereTerm *pTerm; |
| 104619 | int i, j; |
| 104620 | int nOrderBy; |
| 104621 | double rCost; |
| 104622 | |
| 104623 | /* Make sure wsFlags is initialized to some sane value. Otherwise, if the |
| 104624 | ** malloc in allocateIndexInfo() fails and this function returns leaving |
| 104625 | ** wsFlags in an uninitialized state, the caller may behave unpredictably. |
| @@ -104650,63 +104974,91 @@ | |
| 104650 | ** sqlite3ViewGetColumnNames() would have picked up the error. |
| 104651 | */ |
| 104652 | assert( pTab->azModuleArg && pTab->azModuleArg[0] ); |
| 104653 | assert( sqlite3GetVTable(pParse->db, pTab) ); |
| 104654 | |
| 104655 | /* Set the aConstraint[].usable fields and initialize all |
| 104656 | ** output variables to zero. |
| 104657 | ** |
| 104658 | ** aConstraint[].usable is true for constraints where the right-hand |
| 104659 | ** side contains only references to tables to the left of the current |
| 104660 | ** table. In other words, if the constraint is of the form: |
| 104661 | ** |
| 104662 | ** column = expr |
| 104663 | ** |
| 104664 | ** and we are evaluating a join, then the constraint on column is |
| 104665 | ** only valid if all tables referenced in expr occur to the left |
| 104666 | ** of the table containing column. |
| 104667 | ** |
| 104668 | ** The aConstraints[] array contains entries for all constraints |
| 104669 | ** on the current table. That way we only have to compute it once |
| 104670 | ** even though we might try to pick the best index multiple times. |
| 104671 | ** For each attempt at picking an index, the order of tables in the |
| 104672 | ** join might be different so we have to recompute the usable flag |
| 104673 | ** each time. |
| 104674 | */ |
| 104675 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 104676 | pUsage = pIdxInfo->aConstraintUsage; |
| 104677 | for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ |
| 104678 | j = pIdxCons->iTermOffset; |
| 104679 | pTerm = &pWC->a[j]; |
| 104680 | pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1; |
| 104681 | } |
| 104682 | memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); |
| 104683 | if( pIdxInfo->needToFreeIdxStr ){ |
| 104684 | sqlite3_free(pIdxInfo->idxStr); |
| 104685 | } |
| 104686 | pIdxInfo->idxStr = 0; |
| 104687 | pIdxInfo->idxNum = 0; |
| 104688 | pIdxInfo->needToFreeIdxStr = 0; |
| 104689 | pIdxInfo->orderByConsumed = 0; |
| 104690 | /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ |
| 104691 | pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); |
| 104692 | nOrderBy = pIdxInfo->nOrderBy; |
| 104693 | if( !p->pOrderBy ){ |
| 104694 | pIdxInfo->nOrderBy = 0; |
| 104695 | } |
| 104696 | |
| 104697 | if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ |
| 104698 | return; |
| 104699 | } |
| 104700 | |
| 104701 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 104702 | for(i=0; i<pIdxInfo->nConstraint; i++){ |
| 104703 | if( pUsage[i].argvIndex>0 ){ |
| 104704 | p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight; |
| 104705 | } |
| 104706 | } |
| 104707 | |
| 104708 | /* If there is an ORDER BY clause, and the selected virtual table index |
| 104709 | ** does not satisfy it, increase the cost of the scan accordingly. This |
| 104710 | ** matches the processing for non-virtual tables in bestBtreeIndex(). |
| 104711 | */ |
| 104712 | rCost = pIdxInfo->estimatedCost; |
| @@ -105273,11 +105625,11 @@ | |
| 105273 | WhereTerm *pConstraint; /* A constraint in the WHERE clause */ |
| 105274 | |
| 105275 | /* If the next term of the ORDER BY clause refers to anything other than |
| 105276 | ** a column in the "base" table, then this index will not be of any |
| 105277 | ** further use in handling the ORDER BY. */ |
| 105278 | pOBExpr = pOBItem->pExpr; |
| 105279 | if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){ |
| 105280 | break; |
| 105281 | } |
| 105282 | |
| 105283 | /* Find column number and collating sequence for the next entry |
| @@ -105299,11 +105651,11 @@ | |
| 105299 | /* Check to see if the column number and collating sequence of the |
| 105300 | ** index match the column number and collating sequence of the ORDER BY |
| 105301 | ** clause entry. Set isMatch to 1 if they both match. */ |
| 105302 | if( pOBExpr->iColumn==iColumn ){ |
| 105303 | if( zColl ){ |
| 105304 | pColl = sqlite3ExprCollSeq(pParse, pOBExpr); |
| 105305 | if( !pColl ) pColl = db->pDfltColl; |
| 105306 | isMatch = sqlite3StrICmp(pColl->zName, zColl)==0; |
| 105307 | }else{ |
| 105308 | isMatch = 1; |
| 105309 | } |
| @@ -105440,10 +105792,15 @@ | |
| 105440 | int idxEqTermMask; /* Index mask of valid equality operators */ |
| 105441 | Index sPk; /* A fake index object for the primary key */ |
| 105442 | tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ |
| 105443 | int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ |
| 105444 | int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */ |
| 105445 | |
| 105446 | /* Initialize the cost to a worst-case value */ |
| 105447 | memset(&p->cost, 0, sizeof(p->cost)); |
| 105448 | p->cost.rCost = SQLITE_BIG_DBL; |
| 105449 | |
| @@ -105488,10 +105845,21 @@ | |
| 105488 | WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE |
| 105489 | ); |
| 105490 | eqTermMask = WO_EQ|WO_IN; |
| 105491 | pIdx = 0; |
| 105492 | } |
| 105493 | |
| 105494 | /* Loop over all indices looking for the best one to use |
| 105495 | */ |
| 105496 | for(; pProbe; pIdx=pProbe=pProbe->pNext){ |
| 105497 | const tRowcnt * const aiRowEst = pProbe->aiRowEst; |
| @@ -105566,15 +105934,13 @@ | |
| 105566 | */ |
| 105567 | int bInEst = 0; /* True if "x IN (SELECT...)" seen */ |
| 105568 | int nInMul = 1; /* Number of distinct equalities to lookup */ |
| 105569 | double rangeDiv = (double)1; /* Estimated reduction in search space */ |
| 105570 | int nBound = 0; /* Number of range constraints seen */ |
| 105571 | int bSort; /* True if external sort required */ |
| 105572 | int bDist; /* True if index cannot help with DISTINCT */ |
| 105573 | int bLookup = 0; /* True if not a covering index */ |
| 105574 | int nPriorSat; /* ORDER BY terms satisfied by outer loops */ |
| 105575 | int nOrderBy; /* Number of ORDER BY terms */ |
| 105576 | WhereTerm *pTerm; /* A single term of the WHERE clause */ |
| 105577 | #ifdef SQLITE_ENABLE_STAT3 |
| 105578 | WhereTerm *pFirstTerm = 0; /* First term matching the index */ |
| 105579 | #endif |
| 105580 | |
| @@ -105581,20 +105947,11 @@ | |
| 105581 | WHERETRACE(( |
| 105582 | " %s(%s):\n", |
| 105583 | pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk") |
| 105584 | )); |
| 105585 | memset(&pc, 0, sizeof(pc)); |
| 105586 | nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; |
| 105587 | if( p->i ){ |
| 105588 | nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat; |
| 105589 | bSort = nPriorSat<nOrderBy; |
| 105590 | bDist = 0; |
| 105591 | }else{ |
| 105592 | nPriorSat = pc.plan.nOBSat = 0; |
| 105593 | bSort = nOrderBy>0; |
| 105594 | bDist = p->pDistinct!=0; |
| 105595 | } |
| 105596 | |
| 105597 | /* Determine the values of pc.plan.nEq and nInMul */ |
| 105598 | for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){ |
| 105599 | int j = pProbe->aiColumn[pc.plan.nEq]; |
| 105600 | pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); |
| @@ -106466,32 +106823,40 @@ | |
| 106466 | if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ |
| 106467 | /* Case 0: The table is a virtual-table. Use the VFilter and VNext |
| 106468 | ** to access the data. |
| 106469 | */ |
| 106470 | int iReg; /* P3 Value for OP_VFilter */ |
| 106471 | sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; |
| 106472 | int nConstraint = pVtabIdx->nConstraint; |
| 106473 | struct sqlite3_index_constraint_usage *aUsage = |
| 106474 | pVtabIdx->aConstraintUsage; |
| 106475 | const struct sqlite3_index_constraint *aConstraint = |
| 106476 | pVtabIdx->aConstraint; |
| 106477 | |
| 106478 | sqlite3ExprCachePush(pParse); |
| 106479 | iReg = sqlite3GetTempRange(pParse, nConstraint+2); |
| 106480 | for(j=1; j<=nConstraint; j++){ |
| 106481 | for(k=0; k<nConstraint; k++){ |
| 106482 | if( aUsage[k].argvIndex==j ){ |
| 106483 | int iTerm = aConstraint[k].iTermOffset; |
| 106484 | sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1); |
| 106485 | break; |
| 106486 | } |
| 106487 | } |
| 106488 | if( k==nConstraint ) break; |
| 106489 | } |
| 106490 | sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); |
| 106491 | sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); |
| 106492 | sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr, |
| 106493 | pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); |
| 106494 | pVtabIdx->needToFreeIdxStr = 0; |
| 106495 | for(j=0; j<nConstraint; j++){ |
| 106496 | if( aUsage[j].omit ){ |
| 106497 | int iTerm = aConstraint[j].iTermOffset; |
| @@ -108134,10 +108499,11 @@ | |
| 108134 | Expr* yy122; |
| 108135 | Select* yy159; |
| 108136 | IdList* yy180; |
| 108137 | struct {int value; int mask;} yy207; |
| 108138 | u8 yy258; |
| 108139 | struct LikeOp yy318; |
| 108140 | TriggerStep* yy327; |
| 108141 | ExprSpan yy342; |
| 108142 | SrcList* yy347; |
| 108143 | int yy392; |
| @@ -110084,22 +110450,19 @@ | |
| 110084 | case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); |
| 110085 | case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); |
| 110086 | case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); |
| 110087 | case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98); |
| 110088 | case 109: /* ifexists ::= */ yytestcase(yyruleno==109); |
| 110089 | case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120); |
| 110090 | case 121: /* distinct ::= */ yytestcase(yyruleno==121); |
| 110091 | case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); |
| 110092 | case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); |
| 110093 | {yygotominor.yy392 = 0;} |
| 110094 | break; |
| 110095 | case 29: /* ifnotexists ::= IF NOT EXISTS */ |
| 110096 | case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); |
| 110097 | case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); |
| 110098 | case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); |
| 110099 | case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108); |
| 110100 | case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119); |
| 110101 | case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); |
| 110102 | case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); |
| 110103 | {yygotominor.yy392 = 1;} |
| 110104 | break; |
| 110105 | case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ |
| @@ -110335,12 +110698,19 @@ | |
| 110335 | case 116: /* multiselect_op ::= UNION ALL */ |
| 110336 | {yygotominor.yy392 = TK_ALL;} |
| 110337 | break; |
| 110338 | case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ |
| 110339 | { |
| 110340 | yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); |
| 110341 | } |
| 110342 | break; |
| 110343 | case 122: /* sclp ::= selcollist COMMA */ |
| 110344 | case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246); |
| 110345 | {yygotominor.yy442 = yymsp[-1].minor.yy442;} |
| 110346 | break; |
| @@ -110406,14 +110776,24 @@ | |
| 110406 | break; |
| 110407 | case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ |
| 110408 | { |
| 110409 | if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ |
| 110410 | yygotominor.yy347 = yymsp[-4].minor.yy347; |
| 110411 | }else{ |
| 110412 | Select *pSubquery; |
| 110413 | sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); |
| 110414 | pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0); |
| 110415 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); |
| 110416 | } |
| 110417 | } |
| 110418 | break; |
| 110419 | case 137: /* dbnm ::= */ |
| @@ -110624,11 +111004,11 @@ | |
| 110624 | spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); |
| 110625 | } |
| 110626 | break; |
| 110627 | case 194: /* expr ::= expr COLLATE ids */ |
| 110628 | { |
| 110629 | yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); |
| 110630 | yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; |
| 110631 | yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 110632 | } |
| 110633 | break; |
| 110634 | case 195: /* expr ::= CAST LP expr AS typetoken RP */ |
| @@ -110642,11 +111022,11 @@ | |
| 110642 | if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ |
| 110643 | sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); |
| 110644 | } |
| 110645 | yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); |
| 110646 | spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); |
| 110647 | if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){ |
| 110648 | yygotominor.yy342.pExpr->flags |= EP_Distinct; |
| 110649 | } |
| 110650 | } |
| 110651 | break; |
| 110652 | case 197: /* expr ::= ID LP STAR RP */ |
| @@ -110883,28 +111263,20 @@ | |
| 110883 | case 244: /* uniqueflag ::= */ |
| 110884 | {yygotominor.yy392 = OE_None;} |
| 110885 | break; |
| 110886 | case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */ |
| 110887 | { |
| 110888 | Expr *p = 0; |
| 110889 | if( yymsp[-1].minor.yy0.n>0 ){ |
| 110890 | p = sqlite3Expr(pParse->db, TK_COLUMN, 0); |
| 110891 | sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); |
| 110892 | } |
| 110893 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p); |
| 110894 | sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1); |
| 110895 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 110896 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 110897 | } |
| 110898 | break; |
| 110899 | case 248: /* idxlist ::= nm collate sortorder */ |
| 110900 | { |
| 110901 | Expr *p = 0; |
| 110902 | if( yymsp[-1].minor.yy0.n>0 ){ |
| 110903 | p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); |
| 110904 | sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); |
| 110905 | } |
| 110906 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p); |
| 110907 | sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); |
| 110908 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 110909 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 110910 | } |
| @@ -141105,10 +141477,11 @@ | |
| 141105 | extern int Sqlitemultiplex_Init(Tcl_Interp*); |
| 141106 | extern int SqliteSuperlock_Init(Tcl_Interp*); |
| 141107 | extern int SqlitetestSyscall_Init(Tcl_Interp*); |
| 141108 | extern int Sqlitetestfuzzer_Init(Tcl_Interp*); |
| 141109 | extern int Sqlitetestwholenumber_Init(Tcl_Interp*); |
| 141110 | |
| 141111 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141112 | extern int Sqlitetestfts3_Init(Tcl_Interp *interp); |
| 141113 | #endif |
| 141114 | |
| @@ -141148,10 +141521,11 @@ | |
| 141148 | Sqlitemultiplex_Init(interp); |
| 141149 | SqliteSuperlock_Init(interp); |
| 141150 | SqlitetestSyscall_Init(interp); |
| 141151 | Sqlitetestfuzzer_Init(interp); |
| 141152 | Sqlitetestwholenumber_Init(interp); |
| 141153 | |
| 141154 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141155 | Sqlitetestfts3_Init(interp); |
| 141156 | #endif |
| 141157 | |
| 141158 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.7.16. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -671,13 +671,13 @@ | |
| 671 | ** |
| 672 | ** See also: [sqlite3_libversion()], |
| 673 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 674 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 675 | */ |
| 676 | #define SQLITE_VERSION "3.7.16" |
| 677 | #define SQLITE_VERSION_NUMBER 3007016 |
| 678 | #define SQLITE_SOURCE_ID "2012-12-08 06:46:05 e65db42c9fdc1d6f257c8db54a46ee4fc0d7aaf0" |
| 679 | |
| 680 | /* |
| 681 | ** CAPI3REF: Run-Time Library Version Numbers |
| 682 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 683 | ** |
| @@ -2162,11 +2162,11 @@ | |
| 2162 | ** database connection is opened. By default, URI handling is globally |
| 2163 | ** disabled. The default value may be changed by compiling with the |
| 2164 | ** [SQLITE_USE_URI] symbol defined. |
| 2165 | ** |
| 2166 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 2167 | ** <dd> This option takes a single integer argument which is interpreted as |
| 2168 | ** a boolean in order to enable or disable the use of covering indices for |
| 2169 | ** full table scans in the query optimizer. The default setting is determined |
| 2170 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 2171 | ** if that compile-time option is omitted. |
| 2172 | ** The ability to disable the use of covering indices for full table scans |
| @@ -10573,24 +10573,24 @@ | |
| 10573 | ** and the value of Index.onError indicate the which conflict resolution |
| 10574 | ** algorithm to employ whenever an attempt is made to insert a non-unique |
| 10575 | ** element. |
| 10576 | */ |
| 10577 | struct Index { |
| 10578 | char *zName; /* Name of this index */ |
| 10579 | int *aiColumn; /* Which columns are used by this index. 1st is 0 */ |
| 10580 | tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ |
| 10581 | Table *pTable; /* The SQL table being indexed */ |
| 10582 | char *zColAff; /* String defining the affinity of each column */ |
| 10583 | Index *pNext; /* The next index associated with the same table */ |
| 10584 | Schema *pSchema; /* Schema containing this index */ |
| 10585 | u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ |
| 10586 | char **azColl; /* Array of collation sequence names for index */ |
| 10587 | int tnum; /* DB Page containing root of this index */ |
| 10588 | u16 nColumn; /* Number of columns in table used by this index */ |
| 10589 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| 10590 | unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ |
| 10591 | unsigned bUnordered:1; /* Use this index for == or IN queries only */ |
| 10592 | #ifdef SQLITE_ENABLE_STAT3 |
| 10593 | int nSample; /* Number of elements in aSample[] */ |
| 10594 | tRowcnt avgEq; /* Average nEq value for key values not in aSample */ |
| 10595 | IndexSample *aSample; /* Samples of the left-most key */ |
| 10596 | #endif |
| @@ -10767,11 +10767,10 @@ | |
| 10767 | Expr *pRight; /* Right subnode */ |
| 10768 | union { |
| 10769 | ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */ |
| 10770 | Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */ |
| 10771 | } x; |
| 10772 | |
| 10773 | /* If the EP_Reduced flag is set in the Expr.flags mask, then no |
| 10774 | ** space is allocated for the fields below this point. An attempt to |
| 10775 | ** access them will result in a segfault or malfunction. |
| 10776 | *********************************************************************/ |
| @@ -10803,11 +10802,11 @@ | |
| 10802 | #define EP_Error 0x0008 /* Expression contains one or more errors */ |
| 10803 | #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ |
| 10804 | #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ |
| 10805 | #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ |
| 10806 | #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ |
| 10807 | #define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */ |
| 10808 | #define EP_FixedDest 0x0200 /* Result needed in a specific register */ |
| 10809 | #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */ |
| 10810 | #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */ |
| 10811 | #define EP_Hint 0x1000 /* Not used */ |
| 10812 | #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ |
| @@ -10861,22 +10860,31 @@ | |
| 10860 | ** name. An expr/name combination can be used in several ways, such |
| 10861 | ** as the list of "expr AS ID" fields following a "SELECT" or in the |
| 10862 | ** list of "ID = expr" items in an UPDATE. A list of expressions can |
| 10863 | ** also be used as the argument to a function, in which case the a.zName |
| 10864 | ** field is not used. |
| 10865 | ** |
| 10866 | ** By default the Expr.zSpan field holds a human-readable description of |
| 10867 | ** the expression that is used in the generation of error messages and |
| 10868 | ** column labels. In this case, Expr.zSpan is typically the text of a |
| 10869 | ** column expression as it exists in a SELECT statement. However, if |
| 10870 | ** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name |
| 10871 | ** of the result column in the form: DATABASE.TABLE.COLUMN. This later |
| 10872 | ** form is used for name resolution with nested FROM clauses. |
| 10873 | */ |
| 10874 | struct ExprList { |
| 10875 | int nExpr; /* Number of expressions on the list */ |
| 10876 | int iECursor; /* VDBE Cursor associated with this ExprList */ |
| 10877 | struct ExprList_item { /* For each expression in the list */ |
| 10878 | Expr *pExpr; /* The list of expressions */ |
| 10879 | char *zName; /* Token associated with this expression */ |
| 10880 | char *zSpan; /* Original text of the expression */ |
| 10881 | u8 sortOrder; /* 1 for DESC or 0 for ASC */ |
| 10882 | unsigned done :1; /* A flag to indicate when processing is finished */ |
| 10883 | unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ |
| 10884 | u16 iOrderByCol; /* For ORDER BY, column number in result set */ |
| 10885 | u16 iAlias; /* Index into Parse.aAlias[] for zName */ |
| 10886 | } *a; /* Alloc a power of two greater or equal to nExpr */ |
| 10887 | }; |
| 10888 | |
| 10889 | /* |
| 10890 | ** An instance of this structure is used by the parser to record both |
| @@ -11192,10 +11200,11 @@ | |
| 11200 | #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ |
| 11201 | #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ |
| 11202 | #define SF_UseSorter 0x0040 /* Sort using a sorter */ |
| 11203 | #define SF_Values 0x0080 /* Synthesized from VALUES clause */ |
| 11204 | #define SF_Materialize 0x0100 /* Force materialization of views */ |
| 11205 | #define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ |
| 11206 | |
| 11207 | |
| 11208 | /* |
| 11209 | ** The results of a select can be distributed in several ways. The |
| 11210 | ** "SRT" prefix means "SELECT Result Type". |
| @@ -11420,10 +11429,11 @@ | |
| 11429 | #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ |
| 11430 | #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ |
| 11431 | #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ |
| 11432 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ |
| 11433 | #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ |
| 11434 | #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ |
| 11435 | |
| 11436 | /* |
| 11437 | * Each trigger present in the database schema is stored as an instance of |
| 11438 | * struct Trigger. |
| 11439 | * |
| @@ -11904,11 +11914,11 @@ | |
| 11914 | SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, |
| 11915 | Token*, int, int); |
| 11916 | SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); |
| 11917 | SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); |
| 11918 | SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, |
| 11919 | Expr*,ExprList*,u16,Expr*,Expr*); |
| 11920 | SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); |
| 11921 | SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); |
| 11922 | SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); |
| 11923 | SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); |
| 11924 | #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) |
| @@ -12112,12 +12122,13 @@ | |
| 12122 | SQLITE_PRIVATE const char *sqlite3ErrStr(int); |
| 12123 | SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); |
| 12124 | SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); |
| 12125 | SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); |
| 12126 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); |
| 12127 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*); |
| 12128 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); |
| 12129 | SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); |
| 12130 | SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); |
| 12131 | SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); |
| 12132 | SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); |
| 12133 | SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); |
| 12134 | SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); |
| @@ -12160,10 +12171,11 @@ | |
| 12171 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); |
| 12172 | SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); |
| 12173 | SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); |
| 12174 | SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); |
| 12175 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); |
| 12176 | SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); |
| 12177 | SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); |
| 12178 | SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); |
| 12179 | SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); |
| 12180 | SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); |
| 12181 | SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); |
| @@ -12298,12 +12310,14 @@ | |
| 12310 | #define sqlite3FkOldmask(a,b) 0 |
| 12311 | #define sqlite3FkRequired(a,b,c,d) 0 |
| 12312 | #endif |
| 12313 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 12314 | SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); |
| 12315 | SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); |
| 12316 | #else |
| 12317 | #define sqlite3FkDelete(a,b) |
| 12318 | #define sqlite3FkLocateIndex(a,b,c,d,e) |
| 12319 | #endif |
| 12320 | |
| 12321 | |
| 12322 | /* |
| 12323 | ** Available fault injectors. Should be numbered beginning with 0. |
| @@ -23307,15 +23321,11 @@ | |
| 23321 | { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, |
| 23322 | #endif |
| 23323 | #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ |
| 23324 | aSyscall[13].pCurrent) |
| 23325 | |
| 23326 | { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, |
| 23327 | #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) |
| 23328 | |
| 23329 | #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE |
| 23330 | { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, |
| 23331 | #else |
| @@ -23336,13 +23346,10 @@ | |
| 23346 | #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) |
| 23347 | |
| 23348 | { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, |
| 23349 | #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) |
| 23350 | |
| 23351 | }; /* End of the overrideable system calls */ |
| 23352 | |
| 23353 | /* |
| 23354 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 23355 | ** "unix" VFSes. Return SQLITE_OK opon successfully updating the |
| @@ -23443,31 +23450,29 @@ | |
| 23450 | ** process that is able to write to the database will also be able to |
| 23451 | ** recover the hot journals. |
| 23452 | */ |
| 23453 | static int robust_open(const char *z, int f, mode_t m){ |
| 23454 | int fd; |
| 23455 | mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS; |
| 23456 | do{ |
| 23457 | #if defined(O_CLOEXEC) |
| 23458 | fd = osOpen(z,f|O_CLOEXEC,m2); |
| 23459 | #else |
| 23460 | fd = osOpen(z,f,m2); |
| 23461 | #endif |
| 23462 | }while( fd<0 && errno==EINTR ); |
| 23463 | if( fd>=0 ){ |
| 23464 | if( m!=0 ){ |
| 23465 | struct stat statbuf; |
| 23466 | if( osFstat(fd, &statbuf)==0 && (statbuf.st_mode&0777)!=m ){ |
| 23467 | osFchmod(fd, m); |
| 23468 | } |
| 23469 | } |
| 23470 | #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) |
| 23471 | osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 23472 | #endif |
| 23473 | } |
| 23474 | return fd; |
| 23475 | } |
| 23476 | |
| 23477 | /* |
| 23478 | ** Helper functions to obtain and relinquish the global mutex. The |
| @@ -29889,11 +29894,11 @@ | |
| 29894 | }; |
| 29895 | unsigned int i; /* Loop counter */ |
| 29896 | |
| 29897 | /* Double-check that the aSyscall[] array has been constructed |
| 29898 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 29899 | assert( ArraySize(aSyscall)==21 ); |
| 29900 | |
| 29901 | /* Register all VFSes defined in the aVfs[] array */ |
| 29902 | for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 29903 | sqlite3_vfs_register(&aVfs[i], i==0); |
| 29904 | } |
| @@ -56355,11 +56360,11 @@ | |
| 56360 | sqlite3BtreeLeave(p); |
| 56361 | return 0; |
| 56362 | } |
| 56363 | i = PENDING_BYTE_PAGE(pBt); |
| 56364 | if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); |
| 56365 | sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); |
| 56366 | sCheck.errMsg.useMalloc = 2; |
| 56367 | |
| 56368 | /* Check the integrity of the freelist |
| 56369 | */ |
| 56370 | checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), |
| @@ -56890,11 +56895,16 @@ | |
| 56895 | /* |
| 56896 | ** Parameter zSrcData points to a buffer containing the data for |
| 56897 | ** page iSrcPg from the source database. Copy this data into the |
| 56898 | ** destination database. |
| 56899 | */ |
| 56900 | static int backupOnePage( |
| 56901 | sqlite3_backup *p, /* Backup handle */ |
| 56902 | Pgno iSrcPg, /* Source database page to backup */ |
| 56903 | const u8 *zSrcData, /* Source database page data */ |
| 56904 | int bUpdate /* True for an update, false otherwise */ |
| 56905 | ){ |
| 56906 | Pager * const pDestPager = sqlite3BtreePager(p->pDest); |
| 56907 | const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); |
| 56908 | int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); |
| 56909 | const int nCopy = MIN(nSrcPgsz, nDestPgsz); |
| 56910 | const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; |
| @@ -56963,10 +56973,13 @@ | |
| 56973 | ** cached parse of the page). MemPage.isInit is marked |
| 56974 | ** "MUST BE FIRST" for this purpose. |
| 56975 | */ |
| 56976 | memcpy(zOut, zIn, nCopy); |
| 56977 | ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; |
| 56978 | if( iOff==0 && bUpdate==0 ){ |
| 56979 | sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); |
| 56980 | } |
| 56981 | } |
| 56982 | sqlite3PagerUnref(pDestPg); |
| 56983 | } |
| 56984 | |
| 56985 | return rc; |
| @@ -57069,11 +57082,11 @@ | |
| 57082 | const Pgno iSrcPg = p->iNext; /* Source page number */ |
| 57083 | if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ |
| 57084 | DbPage *pSrcPg; /* Source page object */ |
| 57085 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); |
| 57086 | if( rc==SQLITE_OK ){ |
| 57087 | rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); |
| 57088 | sqlite3PagerUnref(pSrcPg); |
| 57089 | } |
| 57090 | } |
| 57091 | p->iNext++; |
| 57092 | } |
| @@ -57317,11 +57330,11 @@ | |
| 57330 | ** the new data into the backup. |
| 57331 | */ |
| 57332 | int rc; |
| 57333 | assert( p->pDestDb ); |
| 57334 | sqlite3_mutex_enter(p->pDestDb->mutex); |
| 57335 | rc = backupOnePage(p, iPage, aData, 1); |
| 57336 | sqlite3_mutex_leave(p->pDestDb->mutex); |
| 57337 | assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); |
| 57338 | if( rc!=SQLITE_OK ){ |
| 57339 | p->rc = rc; |
| 57340 | } |
| @@ -59434,26 +59447,22 @@ | |
| 59447 | assert( pKeyInfo->aSortOrder!=0 ); |
| 59448 | sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); |
| 59449 | i = sqlite3Strlen30(zTemp); |
| 59450 | for(j=0; j<pKeyInfo->nField; j++){ |
| 59451 | CollSeq *pColl = pKeyInfo->aColl[j]; |
| 59452 | const char *zColl = pColl ? pColl->zName : "nil"; |
| 59453 | int n = sqlite3Strlen30(zColl); |
| 59454 | if( i+n>nTemp-6 ){ |
| 59455 | memcpy(&zTemp[i],",...",4); |
| 59456 | break; |
| 59457 | } |
| 59458 | zTemp[i++] = ','; |
| 59459 | if( pKeyInfo->aSortOrder[j] ){ |
| 59460 | zTemp[i++] = '-'; |
| 59461 | } |
| 59462 | memcpy(&zTemp[i], zColl, n+1); |
| 59463 | i += n; |
| 59464 | } |
| 59465 | zTemp[i++] = ')'; |
| 59466 | zTemp[i] = 0; |
| 59467 | assert( i<nTemp ); |
| 59468 | break; |
| @@ -63839,11 +63848,13 @@ | |
| 63848 | #ifdef SQLITE_DEBUG |
| 63849 | /* |
| 63850 | ** Print the value of a register for tracing purposes: |
| 63851 | */ |
| 63852 | static void memTracePrint(FILE *out, Mem *p){ |
| 63853 | if( p->flags & MEM_Invalid ){ |
| 63854 | fprintf(out, " undefined"); |
| 63855 | }else if( p->flags & MEM_Null ){ |
| 63856 | fprintf(out, " NULL"); |
| 63857 | }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ |
| 63858 | fprintf(out, " si:%lld", p->u.i); |
| 63859 | }else if( p->flags & MEM_Int ){ |
| 63860 | fprintf(out, " i:%lld", p->u.i); |
| @@ -64112,10 +64123,11 @@ | |
| 64123 | } af; |
| 64124 | struct OP_Concat_stack_vars { |
| 64125 | i64 nByte; |
| 64126 | } ag; |
| 64127 | struct OP_Remainder_stack_vars { |
| 64128 | char bIntint; /* Started out as two integer operands */ |
| 64129 | int flags; /* Combined MEM_* flags from both inputs */ |
| 64130 | i64 iA; /* Integer value of left operand */ |
| 64131 | i64 iB; /* Integer value of right operand */ |
| 64132 | double rA; /* Real value of left operand */ |
| 64133 | double rB; /* Real value of right operand */ |
| @@ -65021,10 +65033,13 @@ | |
| 65033 | pOut = &aMem[pOp->p2]; |
| 65034 | assert( pOut!=pIn1 ); |
| 65035 | while( 1 ){ |
| 65036 | sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); |
| 65037 | Deephemeralize(pOut); |
| 65038 | #ifdef SQLITE_DEBUG |
| 65039 | pOut->pScopyFrom = 0; |
| 65040 | #endif |
| 65041 | REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut); |
| 65042 | if( (u.ae.n--)==0 ) break; |
| 65043 | pOut++; |
| 65044 | pIn1++; |
| 65045 | } |
| @@ -65214,10 +65229,11 @@ | |
| 65229 | case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ |
| 65230 | case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ |
| 65231 | case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ |
| 65232 | case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ |
| 65233 | #if 0 /* local variables moved into u.ah */ |
| 65234 | char bIntint; /* Started out as two integer operands */ |
| 65235 | int flags; /* Combined MEM_* flags from both inputs */ |
| 65236 | i64 iA; /* Integer value of left operand */ |
| 65237 | i64 iB; /* Integer value of right operand */ |
| 65238 | double rA; /* Real value of left operand */ |
| 65239 | double rB; /* Real value of right operand */ |
| @@ -65231,10 +65247,11 @@ | |
| 65247 | u.ah.flags = pIn1->flags | pIn2->flags; |
| 65248 | if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; |
| 65249 | if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ |
| 65250 | u.ah.iA = pIn1->u.i; |
| 65251 | u.ah.iB = pIn2->u.i; |
| 65252 | u.ah.bIntint = 1; |
| 65253 | switch( pOp->opcode ){ |
| 65254 | case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65255 | case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65256 | case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65257 | case OP_Divide: { |
| @@ -65251,10 +65268,11 @@ | |
| 65268 | } |
| 65269 | } |
| 65270 | pOut->u.i = u.ah.iB; |
| 65271 | MemSetTypeFlag(pOut, MEM_Int); |
| 65272 | }else{ |
| 65273 | u.ah.bIntint = 0; |
| 65274 | fp_math: |
| 65275 | u.ah.rA = sqlite3VdbeRealValue(pIn1); |
| 65276 | u.ah.rB = sqlite3VdbeRealValue(pIn2); |
| 65277 | switch( pOp->opcode ){ |
| 65278 | case OP_Add: u.ah.rB += u.ah.rA; break; |
| @@ -65282,11 +65300,11 @@ | |
| 65300 | if( sqlite3IsNaN(u.ah.rB) ){ |
| 65301 | goto arithmetic_result_is_null; |
| 65302 | } |
| 65303 | pOut->r = u.ah.rB; |
| 65304 | MemSetTypeFlag(pOut, MEM_Real); |
| 65305 | if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){ |
| 65306 | sqlite3VdbeIntegerAffinity(pOut); |
| 65307 | } |
| 65308 | #endif |
| 65309 | } |
| 65310 | break; |
| @@ -65843,26 +65861,31 @@ | |
| 65861 | /* Opcode: Permutation * * * P4 * |
| 65862 | ** |
| 65863 | ** Set the permutation used by the OP_Compare operator to be the array |
| 65864 | ** of integers in P4. |
| 65865 | ** |
| 65866 | ** The permutation is only valid until the next OP_Compare that has |
| 65867 | ** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should |
| 65868 | ** occur immediately prior to the OP_Compare. |
| 65869 | */ |
| 65870 | case OP_Permutation: { |
| 65871 | assert( pOp->p4type==P4_INTARRAY ); |
| 65872 | assert( pOp->p4.ai ); |
| 65873 | aPermute = pOp->p4.ai; |
| 65874 | break; |
| 65875 | } |
| 65876 | |
| 65877 | /* Opcode: Compare P1 P2 P3 P4 P5 |
| 65878 | ** |
| 65879 | ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this |
| 65880 | ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of |
| 65881 | ** the comparison for use by the next OP_Jump instruct. |
| 65882 | ** |
| 65883 | ** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is |
| 65884 | ** determined by the most recent OP_Permutation operator. If the |
| 65885 | ** OPFLAG_PERMUTE bit is clear, then register are compared in sequential |
| 65886 | ** order. |
| 65887 | ** |
| 65888 | ** P4 is a KeyInfo structure that defines collating sequences and sort |
| 65889 | ** orders for the comparison. The permutation applies to registers |
| 65890 | ** only. The KeyInfo elements are used sequentially. |
| 65891 | ** |
| @@ -65880,10 +65903,11 @@ | |
| 65903 | int idx; |
| 65904 | CollSeq *pColl; /* Collating sequence to use on this term */ |
| 65905 | int bRev; /* True for DESCENDING sort order */ |
| 65906 | #endif /* local variables moved into u.al */ |
| 65907 | |
| 65908 | if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0; |
| 65909 | u.al.n = pOp->p3; |
| 65910 | u.al.pKeyInfo = pOp->p4.pKeyInfo; |
| 65911 | assert( u.al.n>0 ); |
| 65912 | assert( u.al.pKeyInfo!=0 ); |
| 65913 | u.al.p1 = pOp->p1; |
| @@ -66025,12 +66049,10 @@ | |
| 66049 | |
| 66050 | /* Opcode: Once P1 P2 * * * |
| 66051 | ** |
| 66052 | ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, |
| 66053 | ** set the flag and fall through to the next instruction. |
| 66054 | */ |
| 66055 | case OP_Once: { /* jump */ |
| 66056 | assert( pOp->p1<p->nOnceFlag ); |
| 66057 | if( p->aOnceFlag[pOp->p1] ){ |
| 66058 | pc = pOp->p2-1; |
| @@ -71902,10 +71924,18 @@ | |
| 71924 | p->pReal = pReal; |
| 71925 | if( p->iSize>0 ){ |
| 71926 | assert(p->iSize<=p->nBuf); |
| 71927 | rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); |
| 71928 | } |
| 71929 | if( rc!=SQLITE_OK ){ |
| 71930 | /* If an error occurred while writing to the file, close it before |
| 71931 | ** returning. This way, SQLite uses the in-memory journal data to |
| 71932 | ** roll back changes made to the internal page-cache before this |
| 71933 | ** function was called. */ |
| 71934 | sqlite3OsClose(pReal); |
| 71935 | p->pReal = 0; |
| 71936 | } |
| 71937 | } |
| 71938 | } |
| 71939 | return rc; |
| 71940 | } |
| 71941 | |
| @@ -72565,10 +72595,19 @@ | |
| 72595 | ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 |
| 72596 | ** |
| 72597 | ** The result of random()%5 in the GROUP BY clause is probably different |
| 72598 | ** from the result in the result-set. We might fix this someday. Or |
| 72599 | ** then again, we might not... |
| 72600 | ** |
| 72601 | ** If the reference is followed by a COLLATE operator, then make sure |
| 72602 | ** the COLLATE operator is preserved. For example: |
| 72603 | ** |
| 72604 | ** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase; |
| 72605 | ** |
| 72606 | ** Should be transformed into: |
| 72607 | ** |
| 72608 | ** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; |
| 72609 | ** |
| 72610 | ** The nSubquery parameter specifies how many levels of subquery the |
| 72611 | ** alias is removed from the original expression. The usually value is |
| 72612 | ** zero but it might be more if the alias is contained within a subquery |
| 72613 | ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION |
| @@ -72589,45 +72628,40 @@ | |
| 72628 | assert( iCol>=0 && iCol<pEList->nExpr ); |
| 72629 | pOrig = pEList->a[iCol].pExpr; |
| 72630 | assert( pOrig!=0 ); |
| 72631 | assert( pOrig->flags & EP_Resolved ); |
| 72632 | db = pParse->db; |
| 72633 | pDup = sqlite3ExprDup(db, pOrig, 0); |
| 72634 | if( pDup==0 ) return; |
| 72635 | if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ |
| 72636 | incrAggFunctionDepth(pDup, nSubquery); |
| 72637 | pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); |
| 72638 | if( pDup==0 ) return; |
| 72639 | if( pEList->a[iCol].iAlias==0 ){ |
| 72640 | pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); |
| 72641 | } |
| 72642 | pDup->iTable = pEList->a[iCol].iAlias; |
| 72643 | } |
| 72644 | if( pExpr->op==TK_COLLATE ){ |
| 72645 | pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); |
| 72646 | } |
| 72647 | |
| 72648 | /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This |
| 72649 | ** prevents ExprDelete() from deleting the Expr structure itself, |
| 72650 | ** allowing it to be repopulated by the memcpy() on the following line. |
| 72651 | ** The pExpr->u.zToken might point into memory that will be freed by the |
| 72652 | ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to |
| 72653 | ** make a copy of the token before doing the sqlite3DbFree(). |
| 72654 | */ |
| 72655 | ExprSetProperty(pExpr, EP_Static); |
| 72656 | sqlite3ExprDelete(db, pExpr); |
| 72657 | memcpy(pExpr, pDup, sizeof(*pExpr)); |
| 72658 | if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ |
| 72659 | assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); |
| 72660 | pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); |
| 72661 | pExpr->flags2 |= EP2_MallocedToken; |
| 72662 | } |
| 72663 | sqlite3DbFree(db, pDup); |
| 72664 | } |
| 72665 | |
| 72666 | |
| 72667 | /* |
| @@ -72644,10 +72678,39 @@ | |
| 72678 | } |
| 72679 | } |
| 72680 | return 0; |
| 72681 | } |
| 72682 | |
| 72683 | /* |
| 72684 | ** Subqueries stores the original database, table and column names for their |
| 72685 | ** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN". |
| 72686 | ** Check to see if the zSpan given to this routine matches the zDb, zTab, |
| 72687 | ** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will |
| 72688 | ** match anything. |
| 72689 | */ |
| 72690 | SQLITE_PRIVATE int sqlite3MatchSpanName( |
| 72691 | const char *zSpan, |
| 72692 | const char *zCol, |
| 72693 | const char *zTab, |
| 72694 | const char *zDb |
| 72695 | ){ |
| 72696 | int n; |
| 72697 | for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} |
| 72698 | if( zDb && sqlite3StrNICmp(zSpan, zDb, n)!=0 ){ |
| 72699 | return 0; |
| 72700 | } |
| 72701 | zSpan += n+1; |
| 72702 | for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} |
| 72703 | if( zTab && sqlite3StrNICmp(zSpan, zTab, n)!=0 ){ |
| 72704 | return 0; |
| 72705 | } |
| 72706 | zSpan += n+1; |
| 72707 | if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ |
| 72708 | return 0; |
| 72709 | } |
| 72710 | return 1; |
| 72711 | } |
| 72712 | |
| 72713 | /* |
| 72714 | ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up |
| 72715 | ** that name in the set of source tables in pSrcList and make the pExpr |
| 72716 | ** expression node refer back to that source column. The following changes |
| @@ -72699,44 +72762,63 @@ | |
| 72762 | |
| 72763 | /* Initialize the node to no-match */ |
| 72764 | pExpr->iTable = -1; |
| 72765 | pExpr->pTab = 0; |
| 72766 | ExprSetIrreducible(pExpr); |
| 72767 | |
| 72768 | /* Translate the schema name in zDb into a pointer to the corresponding |
| 72769 | ** schema. If not found, pSchema will remain NULL and nothing will match |
| 72770 | ** resulting in an appropriate error message toward the end of this routine |
| 72771 | */ |
| 72772 | if( zDb ){ |
| 72773 | for(i=0; i<db->nDb; i++){ |
| 72774 | assert( db->aDb[i].zName ); |
| 72775 | if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){ |
| 72776 | pSchema = db->aDb[i].pSchema; |
| 72777 | break; |
| 72778 | } |
| 72779 | } |
| 72780 | } |
| 72781 | |
| 72782 | /* Start at the inner-most context and move outward until a match is found */ |
| 72783 | while( pNC && cnt==0 ){ |
| 72784 | ExprList *pEList; |
| 72785 | SrcList *pSrcList = pNC->pSrcList; |
| 72786 | |
| 72787 | if( pSrcList ){ |
| 72788 | for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ |
| 72789 | Table *pTab; |
| 72790 | Column *pCol; |
| 72791 | |
| 72792 | pTab = pItem->pTab; |
| 72793 | assert( pTab!=0 && pTab->zName!=0 ); |
| 72794 | assert( pTab->nCol>0 ); |
| 72795 | if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ |
| 72796 | ExprList *pEList = pItem->pSelect->pEList; |
| 72797 | int hit = 0; |
| 72798 | for(j=0; j<pEList->nExpr; j++){ |
| 72799 | if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){ |
| 72800 | cnt++; |
| 72801 | cntTab = 2; |
| 72802 | pMatch = pItem; |
| 72803 | pExpr->iColumn = j; |
| 72804 | hit = 1; |
| 72805 | } |
| 72806 | } |
| 72807 | if( hit || zTab==0 ) continue; |
| 72808 | } |
| 72809 | if( zDb && pTab->pSchema!=pSchema ){ |
| 72810 | continue; |
| 72811 | } |
| 72812 | if( zTab ){ |
| 72813 | const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; |
| 72814 | assert( zTabName!=0 ); |
| 72815 | if( sqlite3StrICmp(zTabName, zTab)!=0 ){ |
| 72816 | continue; |
| 72817 | } |
| 72818 | } |
| 72819 | if( 0==(cntTab++) ){ |
| 72820 | pMatch = pItem; |
| 72821 | } |
| 72822 | for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ |
| 72823 | if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ |
| 72824 | /* If there has been exactly one prior match and this match |
| @@ -72746,21 +72828,23 @@ | |
| 72828 | if( cnt==1 ){ |
| 72829 | if( pItem->jointype & JT_NATURAL ) continue; |
| 72830 | if( nameInUsingClause(pItem->pUsing, zCol) ) continue; |
| 72831 | } |
| 72832 | cnt++; |
| 72833 | pMatch = pItem; |
| 72834 | /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ |
| 72835 | pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; |
| 72836 | break; |
| 72837 | } |
| 72838 | } |
| 72839 | } |
| 72840 | if( pMatch ){ |
| 72841 | pExpr->iTable = pMatch->iCursor; |
| 72842 | pExpr->pTab = pMatch->pTab; |
| 72843 | pSchema = pExpr->pTab->pSchema; |
| 72844 | } |
| 72845 | } /* if( pSrcList ) */ |
| 72846 | |
| 72847 | #ifndef SQLITE_OMIT_TRIGGER |
| 72848 | /* If we have not already resolved the name, then maybe |
| 72849 | ** it is a new.* or old.* trigger argument reference |
| 72850 | */ |
| @@ -73055,42 +73139,43 @@ | |
| 73139 | int wrong_num_args = 0; /* True if wrong number of arguments */ |
| 73140 | int is_agg = 0; /* True if is an aggregate function */ |
| 73141 | int auth; /* Authorization to use the function */ |
| 73142 | int nId; /* Number of characters in function name */ |
| 73143 | const char *zId; /* The function name. */ |
| 73144 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 73145 | |
| 73146 | testcase( pExpr->op==TK_CONST_FUNC ); |
| 73147 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 73148 | zId = pExpr->u.zToken; |
| 73149 | nId = sqlite3Strlen30(zId); |
| 73150 | if( pParse->db->init.busy==0 ){ |
| 73151 | FuncDef *pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); |
| 73152 | if( pDef==0 ){ |
| 73153 | pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); |
| 73154 | if( pDef==0 ){ |
| 73155 | no_such_func = 1; |
| 73156 | }else{ |
| 73157 | wrong_num_args = 1; |
| 73158 | } |
| 73159 | }else{ |
| 73160 | is_agg = pDef->xFunc==0; |
| 73161 | } |
| 73162 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 73163 | if( pDef ){ |
| 73164 | auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); |
| 73165 | if( auth!=SQLITE_OK ){ |
| 73166 | if( auth==SQLITE_DENY ){ |
| 73167 | sqlite3ErrorMsg(pParse, "not authorized to use function: %s", |
| 73168 | pDef->zName); |
| 73169 | pNC->nErr++; |
| 73170 | } |
| 73171 | pExpr->op = TK_NULL; |
| 73172 | return WRC_Prune; |
| 73173 | } |
| 73174 | } |
| 73175 | #endif |
| 73176 | } |
| 73177 | if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ |
| 73178 | sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); |
| 73179 | pNC->nErr++; |
| 73180 | is_agg = 0; |
| 73181 | }else if( no_such_func ){ |
| @@ -73310,11 +73395,11 @@ | |
| 73395 | assert( pEList!=0 ); |
| 73396 | for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ |
| 73397 | int iCol = -1; |
| 73398 | Expr *pE, *pDup; |
| 73399 | if( pItem->done ) continue; |
| 73400 | pE = sqlite3ExprSkipCollate(pItem->pExpr); |
| 73401 | if( sqlite3ExprIsInteger(pE, &iCol) ){ |
| 73402 | if( iCol<=0 || iCol>pEList->nExpr ){ |
| 73403 | resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); |
| 73404 | return 1; |
| 73405 | } |
| @@ -73328,18 +73413,24 @@ | |
| 73413 | } |
| 73414 | sqlite3ExprDelete(db, pDup); |
| 73415 | } |
| 73416 | } |
| 73417 | if( iCol>0 ){ |
| 73418 | /* Convert the ORDER BY term into an integer column number iCol, |
| 73419 | ** taking care to preserve the COLLATE clause if it exists */ |
| 73420 | Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); |
| 73421 | if( pNew==0 ) return 1; |
| 73422 | pNew->flags |= EP_IntValue; |
| 73423 | pNew->u.iValue = iCol; |
| 73424 | if( pItem->pExpr==pE ){ |
| 73425 | pItem->pExpr = pNew; |
| 73426 | }else{ |
| 73427 | assert( pItem->pExpr->op==TK_COLLATE ); |
| 73428 | assert( pItem->pExpr->pLeft==pE ); |
| 73429 | pItem->pExpr->pLeft = pNew; |
| 73430 | } |
| 73431 | sqlite3ExprDelete(db, pE); |
| 73432 | pItem->iOrderByCol = (u16)iCol; |
| 73433 | pItem->done = 1; |
| 73434 | }else{ |
| 73435 | moreToDo = 1; |
| 73436 | } |
| @@ -73440,15 +73531,15 @@ | |
| 73531 | ** sqlite3ResolveOrderGroupBy() will convert the expression to a |
| 73532 | ** copy of the iCol-th result-set expression. */ |
| 73533 | pItem->iOrderByCol = (u16)iCol; |
| 73534 | continue; |
| 73535 | } |
| 73536 | if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){ |
| 73537 | /* The ORDER BY term is an integer constant. Again, set the column |
| 73538 | ** number so that sqlite3ResolveOrderGroupBy() will convert the |
| 73539 | ** order-by term to a copy of the result-set expression */ |
| 73540 | if( iCol<1 || iCol>0xffff ){ |
| 73541 | resolveOutOfRangeError(pParse, zType, i+1, nResult); |
| 73542 | return 1; |
| 73543 | } |
| 73544 | pItem->iOrderByCol = (u16)iCol; |
| 73545 | continue; |
| @@ -73521,27 +73612,10 @@ | |
| 73612 | if( sqlite3ResolveExprNames(&sNC, p->pLimit) || |
| 73613 | sqlite3ResolveExprNames(&sNC, p->pOffset) ){ |
| 73614 | return WRC_Abort; |
| 73615 | } |
| 73616 | |
| 73617 | /* Recursively resolve names in all subqueries |
| 73618 | */ |
| 73619 | for(i=0; i<p->pSrc->nSrc; i++){ |
| 73620 | struct SrcList_item *pItem = &p->pSrc->a[i]; |
| 73621 | if( pItem->pSelect ){ |
| @@ -73564,10 +73638,27 @@ | |
| 73638 | for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; |
| 73639 | assert( pItem->isCorrelated==0 && nRef<=0 ); |
| 73640 | pItem->isCorrelated = (nRef!=0); |
| 73641 | } |
| 73642 | } |
| 73643 | |
| 73644 | /* Set up the local name-context to pass to sqlite3ResolveExprNames() to |
| 73645 | ** resolve the result-set expression list. |
| 73646 | */ |
| 73647 | sNC.ncFlags = NC_AllowAgg; |
| 73648 | sNC.pSrcList = p->pSrc; |
| 73649 | sNC.pNext = pOuterNC; |
| 73650 | |
| 73651 | /* Resolve names in the result set. */ |
| 73652 | pEList = p->pEList; |
| 73653 | assert( pEList!=0 ); |
| 73654 | for(i=0; i<pEList->nExpr; i++){ |
| 73655 | Expr *pX = pEList->a[i].pExpr; |
| 73656 | if( sqlite3ResolveExprNames(&sNC, pX) ){ |
| 73657 | return WRC_Abort; |
| 73658 | } |
| 73659 | } |
| 73660 | |
| 73661 | /* If there are no aggregate functions in the result-set, and no GROUP BY |
| 73662 | ** expression, do not allow aggregates in any of the other expressions. |
| 73663 | */ |
| 73664 | assert( (p->selFlags & SF_Aggregate)==0 ); |
| @@ -73798,11 +73889,13 @@ | |
| 73889 | ** SELECT * FROM t1 WHERE a; |
| 73890 | ** SELECT a AS b FROM t1 WHERE b; |
| 73891 | ** SELECT * FROM t1 WHERE (select a from t1); |
| 73892 | */ |
| 73893 | SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ |
| 73894 | int op; |
| 73895 | pExpr = sqlite3ExprSkipCollate(pExpr); |
| 73896 | op = pExpr->op; |
| 73897 | if( op==TK_SELECT ){ |
| 73898 | assert( pExpr->flags&EP_xIsSelect ); |
| 73899 | return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); |
| 73900 | } |
| 73901 | #ifndef SQLITE_OMIT_CAST |
| @@ -73823,70 +73916,98 @@ | |
| 73916 | } |
| 73917 | return pExpr->affinity; |
| 73918 | } |
| 73919 | |
| 73920 | /* |
| 73921 | ** Set the collating sequence for expression pExpr to be the collating |
| 73922 | ** sequence named by pToken. Return a pointer to a new Expr node that |
| 73923 | ** implements the COLLATE operator. |
| 73924 | ** |
| 73925 | ** If a memory allocation error occurs, that fact is recorded in pParse->db |
| 73926 | ** and the pExpr parameter is returned unchanged. |
| 73927 | */ |
| 73928 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){ |
| 73929 | if( pCollName->n>0 ){ |
| 73930 | Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); |
| 73931 | if( pNew ){ |
| 73932 | pNew->pLeft = pExpr; |
| 73933 | pNew->flags |= EP_Collate; |
| 73934 | pExpr = pNew; |
| 73935 | } |
| 73936 | } |
| 73937 | return pExpr; |
| 73938 | } |
| 73939 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ |
| 73940 | Token s; |
| 73941 | assert( zC!=0 ); |
| 73942 | s.z = zC; |
| 73943 | s.n = sqlite3Strlen30(s.z); |
| 73944 | return sqlite3ExprAddCollateToken(pParse, pExpr, &s); |
| 73945 | } |
| 73946 | |
| 73947 | /* |
| 73948 | ** Skip over any TK_COLLATE and/or TK_AS operators at the root of |
| 73949 | ** an expression. |
| 73950 | */ |
| 73951 | SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ |
| 73952 | while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){ |
| 73953 | pExpr = pExpr->pLeft; |
| 73954 | } |
| 73955 | return pExpr; |
| 73956 | } |
| 73957 | |
| 73958 | /* |
| 73959 | ** Return the collation sequence for the expression pExpr. If |
| 73960 | ** there is no defined collating sequence, return NULL. |
| 73961 | ** |
| 73962 | ** The collating sequence might be determined by a COLLATE operator |
| 73963 | ** or by the presence of a column with a defined collating sequence. |
| 73964 | ** COLLATE operators take first precedence. Left operands take |
| 73965 | ** precedence over right operands. |
| 73966 | */ |
| 73967 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ |
| 73968 | sqlite3 *db = pParse->db; |
| 73969 | CollSeq *pColl = 0; |
| 73970 | Expr *p = pExpr; |
| 73971 | while( p ){ |
| 73972 | int op = p->op; |
| 73973 | if( op==TK_CAST || op==TK_UPLUS ){ |
| 73974 | p = p->pLeft; |
| 73975 | continue; |
| 73976 | } |
| 73977 | assert( op!=TK_REGISTER || p->op2!=TK_COLLATE ); |
| 73978 | if( op==TK_COLLATE ){ |
| 73979 | if( db->init.busy ){ |
| 73980 | /* Do not report errors when parsing while the schema */ |
| 73981 | pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0); |
| 73982 | }else{ |
| 73983 | pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); |
| 73984 | } |
| 73985 | break; |
| 73986 | } |
| 73987 | if( p->pTab!=0 |
| 73988 | && (op==TK_AGG_COLUMN || op==TK_COLUMN |
| 73989 | || op==TK_REGISTER || op==TK_TRIGGER) |
| 73990 | ){ |
| 73991 | /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally |
| 73992 | ** a TK_COLUMN but was previously evaluated and cached in a register */ |
| 73993 | int j = p->iColumn; |
| 73994 | if( j>=0 ){ |
| 73995 | const char *zColl = p->pTab->aCol[j].zColl; |
| 73996 | pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); |
| 73997 | } |
| 73998 | break; |
| 73999 | } |
| 74000 | if( p->flags & EP_Collate ){ |
| 74001 | if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ |
| 74002 | p = p->pLeft; |
| 74003 | }else{ |
| 74004 | p = p->pRight; |
| 74005 | } |
| 74006 | }else{ |
| 74007 | break; |
| 74008 | } |
| 74009 | } |
| 74010 | if( sqlite3CheckCollSeq(pParse, pColl) ){ |
| 74011 | pColl = 0; |
| 74012 | } |
| 74013 | return pColl; |
| @@ -73986,16 +74107,14 @@ | |
| 74107 | Expr *pLeft, |
| 74108 | Expr *pRight |
| 74109 | ){ |
| 74110 | CollSeq *pColl; |
| 74111 | assert( pLeft ); |
| 74112 | if( pLeft->flags & EP_Collate ){ |
| 74113 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 74114 | }else if( pRight && (pRight->flags & EP_Collate)!=0 ){ |
| 74115 | pColl = sqlite3ExprCollSeq(pParse, pRight); |
| 74116 | }else{ |
| 74117 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 74118 | if( !pColl ){ |
| 74119 | pColl = sqlite3ExprCollSeq(pParse, pRight); |
| 74120 | } |
| @@ -74221,21 +74340,15 @@ | |
| 74340 | sqlite3ExprDelete(db, pLeft); |
| 74341 | sqlite3ExprDelete(db, pRight); |
| 74342 | }else{ |
| 74343 | if( pRight ){ |
| 74344 | pRoot->pRight = pRight; |
| 74345 | pRoot->flags |= EP_Collate & pRight->flags; |
| 74346 | } |
| 74347 | if( pLeft ){ |
| 74348 | pRoot->pLeft = pLeft; |
| 74349 | pRoot->flags |= EP_Collate & pLeft->flags; |
| 74350 | } |
| 74351 | exprSetHeight(pRoot); |
| 74352 | } |
| 74353 | } |
| 74354 | |
| @@ -74489,11 +74602,11 @@ | |
| 74602 | }else{ |
| 74603 | assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); |
| 74604 | assert( !ExprHasProperty(p, EP_FromJoin) ); |
| 74605 | assert( (p->flags2 & EP2_MallocedToken)==0 ); |
| 74606 | assert( (p->flags2 & EP2_Irreducible)==0 ); |
| 74607 | if( p->pLeft || p->pRight || p->x.pList ){ |
| 74608 | nSize = EXPR_REDUCEDSIZE | EP_Reduced; |
| 74609 | }else{ |
| 74610 | nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; |
| 74611 | } |
| 74612 | } |
| @@ -76513,10 +76626,11 @@ | |
| 76626 | sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); |
| 76627 | sqlite3ReleaseTempReg(pParse, r3); |
| 76628 | sqlite3ReleaseTempReg(pParse, r4); |
| 76629 | break; |
| 76630 | } |
| 76631 | case TK_COLLATE: |
| 76632 | case TK_UPLUS: { |
| 76633 | inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); |
| 76634 | break; |
| 76635 | } |
| 76636 | |
| @@ -76881,10 +76995,16 @@ | |
| 76995 | case TK_UPLUS: zUniOp = "UPLUS"; break; |
| 76996 | case TK_BITNOT: zUniOp = "BITNOT"; break; |
| 76997 | case TK_NOT: zUniOp = "NOT"; break; |
| 76998 | case TK_ISNULL: zUniOp = "ISNULL"; break; |
| 76999 | case TK_NOTNULL: zUniOp = "NOTNULL"; break; |
| 77000 | |
| 77001 | case TK_COLLATE: { |
| 77002 | sqlite3ExplainExpr(pOut, pExpr->pLeft); |
| 77003 | sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken); |
| 77004 | break; |
| 77005 | } |
| 77006 | |
| 77007 | case TK_AGG_FUNCTION: |
| 77008 | case TK_CONST_FUNC: |
| 77009 | case TK_FUNCTION: { |
| 77010 | ExprList *pFarg; /* List of function arguments */ |
| @@ -77019,10 +77139,16 @@ | |
| 77139 | for(i=0; i<pList->nExpr; i++){ |
| 77140 | sqlite3ExplainPrintf(pOut, "item[%d] = ", i); |
| 77141 | sqlite3ExplainPush(pOut); |
| 77142 | sqlite3ExplainExpr(pOut, pList->a[i].pExpr); |
| 77143 | sqlite3ExplainPop(pOut); |
| 77144 | if( pList->a[i].zName ){ |
| 77145 | sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName); |
| 77146 | } |
| 77147 | if( pList->a[i].bSpanIsTab ){ |
| 77148 | sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan); |
| 77149 | } |
| 77150 | if( i<pList->nExpr-1 ){ |
| 77151 | sqlite3ExplainNL(pOut); |
| 77152 | } |
| 77153 | } |
| 77154 | sqlite3ExplainPop(pOut); |
| @@ -77100,10 +77226,13 @@ | |
| 77226 | switch( pExpr->op ){ |
| 77227 | case TK_IN: |
| 77228 | case TK_REGISTER: { |
| 77229 | return WRC_Prune; |
| 77230 | } |
| 77231 | case TK_COLLATE: { |
| 77232 | return WRC_Continue; |
| 77233 | } |
| 77234 | case TK_FUNCTION: |
| 77235 | case TK_AGG_FUNCTION: |
| 77236 | case TK_CONST_FUNC: { |
| 77237 | /* The arguments to a function have a fixed destination. |
| 77238 | ** Mark them this way to avoid generated unneeded OP_SCopy |
| @@ -77121,13 +77250,15 @@ | |
| 77250 | break; |
| 77251 | } |
| 77252 | } |
| 77253 | if( isAppropriateForFactoring(pExpr) ){ |
| 77254 | int r1 = ++pParse->nMem; |
| 77255 | int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); |
| 77256 | /* If r2!=r1, it means that register r1 is never used. That is harmless |
| 77257 | ** but suboptimal, so we want to know about the situation to fix it. |
| 77258 | ** Hence the following assert: */ |
| 77259 | assert( r2==r1 ); |
| 77260 | pExpr->op2 = pExpr->op; |
| 77261 | pExpr->op = TK_REGISTER; |
| 77262 | pExpr->iTable = r2; |
| 77263 | return WRC_Prune; |
| 77264 | } |
| @@ -77540,11 +77671,19 @@ | |
| 77671 | assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); |
| 77672 | if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ |
| 77673 | return 2; |
| 77674 | } |
| 77675 | if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; |
| 77676 | if( pA->op!=pB->op ){ |
| 77677 | if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){ |
| 77678 | return 1; |
| 77679 | } |
| 77680 | if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){ |
| 77681 | return 1; |
| 77682 | } |
| 77683 | return 2; |
| 77684 | } |
| 77685 | if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; |
| 77686 | if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; |
| 77687 | if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; |
| 77688 | if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; |
| 77689 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| @@ -77552,15 +77691,13 @@ | |
| 77691 | return 2; |
| 77692 | } |
| 77693 | }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){ |
| 77694 | if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; |
| 77695 | if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 77696 | return pA->op==TK_COLLATE ? 1 : 2; |
| 77697 | } |
| 77698 | } |
| 77699 | return 0; |
| 77700 | } |
| 77701 | |
| 77702 | /* |
| 77703 | ** Compare two ExprList objects. Return 0 if they are identical and |
| @@ -83371,14 +83508,12 @@ | |
| 83508 | ** specified collation sequence names. |
| 83509 | */ |
| 83510 | for(i=0; i<pList->nExpr; i++){ |
| 83511 | Expr *pExpr = pList->a[i].pExpr; |
| 83512 | if( pExpr ){ |
| 83513 | CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); |
| 83514 | if( pColl ){ |
| 83515 | nExtra += (1 + sqlite3Strlen30(pColl->zName)); |
| 83516 | } |
| 83517 | } |
| 83518 | } |
| 83519 | |
| @@ -83437,10 +83572,11 @@ | |
| 83572 | */ |
| 83573 | for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ |
| 83574 | const char *zColName = pListItem->zName; |
| 83575 | Column *pTabCol; |
| 83576 | int requestedSortOrder; |
| 83577 | CollSeq *pColl; /* Collating sequence */ |
| 83578 | char *zColl; /* Collation sequence name */ |
| 83579 | |
| 83580 | for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ |
| 83581 | if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; |
| 83582 | } |
| @@ -83449,18 +83585,15 @@ | |
| 83585 | pTab->zName, zColName); |
| 83586 | pParse->checkSchema = 1; |
| 83587 | goto exit_create_index; |
| 83588 | } |
| 83589 | pIndex->aiColumn[i] = j; |
| 83590 | if( pListItem->pExpr |
| 83591 | && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0 |
| 83592 | ){ |
| 83593 | int nColl; |
| 83594 | zColl = pColl->zName; |
| 83595 | nColl = sqlite3Strlen30(zColl) + 1; |
| 83596 | assert( nExtra>=nColl ); |
| 83597 | memcpy(zExtra, zColl, nColl); |
| 83598 | zColl = zExtra; |
| 83599 | zExtra += nColl; |
| @@ -87489,11 +87622,11 @@ | |
| 87622 | |
| 87623 | /* |
| 87624 | ** A foreign key constraint requires that the key columns in the parent |
| 87625 | ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. |
| 87626 | ** Given that pParent is the parent table for foreign key constraint pFKey, |
| 87627 | ** search the schema for a unique index on the parent key columns. |
| 87628 | ** |
| 87629 | ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY |
| 87630 | ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx |
| 87631 | ** is set to point to the unique index. |
| 87632 | ** |
| @@ -87525,11 +87658,11 @@ | |
| 87658 | ** |
| 87659 | ** then non-zero is returned, and a "foreign key mismatch" error loaded |
| 87660 | ** into pParse. If an OOM error occurs, non-zero is returned and the |
| 87661 | ** pParse->db->mallocFailed flag is set. |
| 87662 | */ |
| 87663 | SQLITE_PRIVATE int sqlite3FkLocateIndex( |
| 87664 | Parse *pParse, /* Parse context to store any error in */ |
| 87665 | Table *pParent, /* Parent table of FK constraint pFKey */ |
| 87666 | FKey *pFKey, /* Foreign key to find index for */ |
| 87667 | Index **ppIdx, /* OUT: Unique index on parent table */ |
| 87668 | int **paiCol /* OUT: Map of index columns in pFKey */ |
| @@ -87622,11 +87755,13 @@ | |
| 87755 | } |
| 87756 | } |
| 87757 | |
| 87758 | if( !pIdx ){ |
| 87759 | if( !pParse->disableTriggers ){ |
| 87760 | sqlite3ErrorMsg(pParse, |
| 87761 | "foreign key mismatch - \"%w\" referencing \"%w\"", |
| 87762 | pFKey->pFrom->zName, pFKey->zTo); |
| 87763 | } |
| 87764 | sqlite3DbFree(pParse->db, aiCol); |
| 87765 | return 1; |
| 87766 | } |
| 87767 | |
| @@ -87858,16 +87993,19 @@ | |
| 87993 | if( pLeft ){ |
| 87994 | /* Set the collation sequence and affinity of the LHS of each TK_EQ |
| 87995 | ** expression to the parent key column defaults. */ |
| 87996 | if( pIdx ){ |
| 87997 | Column *pCol; |
| 87998 | const char *zColl; |
| 87999 | iCol = pIdx->aiColumn[i]; |
| 88000 | pCol = &pTab->aCol[iCol]; |
| 88001 | if( pTab->iPKey==iCol ) iCol = -1; |
| 88002 | pLeft->iTable = regData+iCol+1; |
| 88003 | pLeft->affinity = pCol->affinity; |
| 88004 | zColl = pCol->zColl; |
| 88005 | if( zColl==0 ) zColl = db->pDfltColl->zName; |
| 88006 | pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl); |
| 88007 | }else{ |
| 88008 | pLeft->iTable = regData; |
| 88009 | pLeft->affinity = SQLITE_AFF_INTEGER; |
| 88010 | } |
| 88011 | } |
| @@ -88080,11 +88218,11 @@ | |
| 88218 | if( pParse->disableTriggers ){ |
| 88219 | pTo = sqlite3FindTable(db, pFKey->zTo, zDb); |
| 88220 | }else{ |
| 88221 | pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); |
| 88222 | } |
| 88223 | if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ |
| 88224 | assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); |
| 88225 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88226 | if( pTo==0 ){ |
| 88227 | /* If isIgnoreErrors is true, then a table is being dropped. In this |
| 88228 | ** case SQLite runs a "DELETE FROM xxx" on the table being dropped |
| @@ -88160,11 +88298,11 @@ | |
| 88298 | /* Inserting a single row into a parent table cannot cause an immediate |
| 88299 | ** foreign key violation. So do nothing in this case. */ |
| 88300 | continue; |
| 88301 | } |
| 88302 | |
| 88303 | if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 88304 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88305 | continue; |
| 88306 | } |
| 88307 | assert( aiCol || pFKey->nCol==1 ); |
| 88308 | |
| @@ -88215,11 +88353,11 @@ | |
| 88353 | for(p=pTab->pFKey; p; p=p->pNextFrom){ |
| 88354 | for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); |
| 88355 | } |
| 88356 | for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
| 88357 | Index *pIdx = 0; |
| 88358 | sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); |
| 88359 | if( pIdx ){ |
| 88360 | for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); |
| 88361 | } |
| 88362 | } |
| 88363 | } |
| @@ -88341,11 +88479,11 @@ | |
| 88479 | ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ |
| 88480 | Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ |
| 88481 | int i; /* Iterator variable */ |
| 88482 | Expr *pWhen = 0; /* WHEN clause for the trigger */ |
| 88483 | |
| 88484 | if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; |
| 88485 | assert( aiCol || pFKey->nCol==1 ); |
| 88486 | |
| 88487 | for(i=0; i<pFKey->nCol; i++){ |
| 88488 | Token tOld = { "old", 3 }; /* Literal "old" token */ |
| 88489 | Token tNew = { "new", 3 }; /* Literal "new" token */ |
| @@ -89843,29 +89981,24 @@ | |
| 89981 | ExprList *pCheck = pTab->pCheck; |
| 89982 | pParse->ckBase = regData; |
| 89983 | onError = overrideError!=OE_Default ? overrideError : OE_Abort; |
| 89984 | for(i=0; i<pCheck->nExpr; i++){ |
| 89985 | int allOk = sqlite3VdbeMakeLabel(v); |
| 89986 | sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); |
| 89987 | if( onError==OE_Ignore ){ |
| 89988 | sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); |
| 89989 | }else{ |
| 89990 | char *zConsName = pCheck->a[i].zName; |
| 89991 | if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ |
| 89992 | if( zConsName ){ |
| 89993 | zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); |
| 89994 | }else{ |
| 89995 | zConsName = 0; |
| 89996 | } |
| 89997 | sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); |
| 89998 | } |
| 89999 | sqlite3VdbeResolveLabel(v, allOk); |
| 90000 | } |
| 90001 | } |
| 90002 | #endif /* !defined(SQLITE_OMIT_CHECK) */ |
| 90003 | |
| 90004 | /* If we have an INTEGER PRIMARY KEY, make sure the primary key |
| @@ -92686,13 +92819,15 @@ | |
| 92819 | if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ |
| 92820 | Table *pTab; |
| 92821 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 92822 | pTab = sqlite3FindTable(db, zRight, zDb); |
| 92823 | if( pTab ){ |
| 92824 | int i, k; |
| 92825 | int nHidden = 0; |
| 92826 | Column *pCol; |
| 92827 | Index *pPk; |
| 92828 | for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){} |
| 92829 | sqlite3VdbeSetNumCols(v, 6); |
| 92830 | pParse->nMem = 6; |
| 92831 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); |
| 92832 | sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); |
| 92833 | sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); |
| @@ -92713,12 +92848,18 @@ | |
| 92848 | if( pCol->zDflt ){ |
| 92849 | sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); |
| 92850 | }else{ |
| 92851 | sqlite3VdbeAddOp2(v, OP_Null, 0, 5); |
| 92852 | } |
| 92853 | if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ |
| 92854 | k = 0; |
| 92855 | }else if( pPk==0 ){ |
| 92856 | k = 1; |
| 92857 | }else{ |
| 92858 | for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){} |
| 92859 | } |
| 92860 | sqlite3VdbeAddOp2(v, OP_Integer, k, 6); |
| 92861 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); |
| 92862 | } |
| 92863 | } |
| 92864 | }else |
| 92865 | |
| @@ -92849,10 +92990,124 @@ | |
| 92990 | ++i; |
| 92991 | pFK = pFK->pNextFrom; |
| 92992 | } |
| 92993 | } |
| 92994 | } |
| 92995 | }else |
| 92996 | #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
| 92997 | |
| 92998 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 92999 | if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){ |
| 93000 | FKey *pFK; /* A foreign key constraint */ |
| 93001 | Table *pTab; /* Child table contain "REFERENCES" keyword */ |
| 93002 | Table *pParent; /* Parent table that child points to */ |
| 93003 | Index *pIdx; /* Index in the parent table */ |
| 93004 | int i; /* Loop counter: Foreign key number for pTab */ |
| 93005 | int j; /* Loop counter: Field of the foreign key */ |
| 93006 | HashElem *k; /* Loop counter: Next table in schema */ |
| 93007 | int x; /* result variable */ |
| 93008 | int regResult; /* 3 registers to hold a result row */ |
| 93009 | int regKey; /* Register to hold key for checking the FK */ |
| 93010 | int regRow; /* Registers to hold a row from pTab */ |
| 93011 | int addrTop; /* Top of a loop checking foreign keys */ |
| 93012 | int addrOk; /* Jump here if the key is OK */ |
| 93013 | int *aiCols; /* child to parent column mapping */ |
| 93014 | |
| 93015 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 93016 | regResult = pParse->nMem+1; |
| 93017 | pParse->nMem += 4; |
| 93018 | regKey = ++pParse->nMem; |
| 93019 | regRow = ++pParse->nMem; |
| 93020 | v = sqlite3GetVdbe(pParse); |
| 93021 | sqlite3VdbeSetNumCols(v, 4); |
| 93022 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); |
| 93023 | sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC); |
| 93024 | sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC); |
| 93025 | sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC); |
| 93026 | sqlite3CodeVerifySchema(pParse, iDb); |
| 93027 | k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); |
| 93028 | while( k ){ |
| 93029 | if( zRight ){ |
| 93030 | pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); |
| 93031 | k = 0; |
| 93032 | }else{ |
| 93033 | pTab = (Table*)sqliteHashData(k); |
| 93034 | k = sqliteHashNext(k); |
| 93035 | } |
| 93036 | if( pTab==0 || pTab->pFKey==0 ) continue; |
| 93037 | sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); |
| 93038 | if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; |
| 93039 | sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); |
| 93040 | sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, |
| 93041 | P4_TRANSIENT); |
| 93042 | for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ |
| 93043 | pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); |
| 93044 | if( pParent==0 ) break; |
| 93045 | pIdx = 0; |
| 93046 | sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); |
| 93047 | x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); |
| 93048 | if( x==0 ){ |
| 93049 | if( pIdx==0 ){ |
| 93050 | sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); |
| 93051 | }else{ |
| 93052 | KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); |
| 93053 | sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); |
| 93054 | sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); |
| 93055 | } |
| 93056 | }else{ |
| 93057 | k = 0; |
| 93058 | break; |
| 93059 | } |
| 93060 | } |
| 93061 | if( pFK ) break; |
| 93062 | if( pParse->nTab<i ) pParse->nTab = i; |
| 93063 | addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); |
| 93064 | for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ |
| 93065 | pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); |
| 93066 | assert( pParent!=0 ); |
| 93067 | pIdx = 0; |
| 93068 | aiCols = 0; |
| 93069 | x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); |
| 93070 | assert( x==0 ); |
| 93071 | addrOk = sqlite3VdbeMakeLabel(v); |
| 93072 | if( pIdx==0 ){ |
| 93073 | int iKey = pFK->aCol[0].iFrom; |
| 93074 | assert( iKey>=0 && iKey<pTab->nCol ); |
| 93075 | if( iKey!=pTab->iPKey ){ |
| 93076 | sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); |
| 93077 | sqlite3ColumnDefault(v, pTab, iKey, regRow); |
| 93078 | sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); |
| 93079 | sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, |
| 93080 | sqlite3VdbeCurrentAddr(v)+3); |
| 93081 | }else{ |
| 93082 | sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); |
| 93083 | } |
| 93084 | sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); |
| 93085 | sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); |
| 93086 | sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); |
| 93087 | }else{ |
| 93088 | for(j=0; j<pFK->nCol; j++){ |
| 93089 | sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, |
| 93090 | aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j); |
| 93091 | sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); |
| 93092 | } |
| 93093 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); |
| 93094 | sqlite3VdbeChangeP4(v, -1, |
| 93095 | sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); |
| 93096 | sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); |
| 93097 | } |
| 93098 | sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); |
| 93099 | sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, |
| 93100 | pFK->zTo, P4_TRANSIENT); |
| 93101 | sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3); |
| 93102 | sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); |
| 93103 | sqlite3VdbeResolveLabel(v, addrOk); |
| 93104 | sqlite3DbFree(db, aiCols); |
| 93105 | } |
| 93106 | sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); |
| 93107 | sqlite3VdbeJumpHere(v, addrTop); |
| 93108 | } |
| 93109 | }else |
| 93110 | #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
| 93111 | |
| 93112 | #ifndef NDEBUG |
| 93113 | if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ |
| @@ -94308,11 +94563,11 @@ | |
| 94563 | SrcList *pSrc, /* the FROM clause -- which tables to scan */ |
| 94564 | Expr *pWhere, /* the WHERE clause */ |
| 94565 | ExprList *pGroupBy, /* the GROUP BY clause */ |
| 94566 | Expr *pHaving, /* the HAVING clause */ |
| 94567 | ExprList *pOrderBy, /* the ORDER BY clause */ |
| 94568 | u16 selFlags, /* Flag parameters, such as SF_Distinct */ |
| 94569 | Expr *pLimit, /* LIMIT value. NULL means not used */ |
| 94570 | Expr *pOffset /* OFFSET value. NULL means no offset */ |
| 94571 | ){ |
| 94572 | Select *pNew; |
| 94573 | Select standin; |
| @@ -94332,11 +94587,11 @@ | |
| 94587 | pNew->pSrc = pSrc; |
| 94588 | pNew->pWhere = pWhere; |
| 94589 | pNew->pGroupBy = pGroupBy; |
| 94590 | pNew->pHaving = pHaving; |
| 94591 | pNew->pOrderBy = pOrderBy; |
| 94592 | pNew->selFlags = selFlags; |
| 94593 | pNew->op = TK_SELECT; |
| 94594 | pNew->pLimit = pLimit; |
| 94595 | pNew->pOffset = pOffset; |
| 94596 | assert( pOffset==0 || pLimit!=0 ); |
| 94597 | pNew->addrOpenEphm[0] = -1; |
| @@ -95588,13 +95843,11 @@ | |
| 95843 | *paCol = aCol; |
| 95844 | |
| 95845 | for(i=0, pCol=aCol; i<nCol; i++, pCol++){ |
| 95846 | /* Get an appropriate name for the column |
| 95847 | */ |
| 95848 | p = sqlite3ExprSkipCollate(pEList->a[i].pExpr); |
| 95849 | if( (zName = pEList->a[i].zName)!=0 ){ |
| 95850 | /* If the column contains an "AS <name>" phrase, use <name> as the name */ |
| 95851 | zName = sqlite3DbStrDup(db, zName); |
| 95852 | }else{ |
| 95853 | Expr *pColExpr = p; /* The expression that is the result column name */ |
| @@ -95628,10 +95881,13 @@ | |
| 95881 | */ |
| 95882 | nName = sqlite3Strlen30(zName); |
| 95883 | for(j=cnt=0; j<i; j++){ |
| 95884 | if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ |
| 95885 | char *zNewName; |
| 95886 | int k; |
| 95887 | for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){} |
| 95888 | if( zName[k]==':' ) nName = k; |
| 95889 | zName[nName] = 0; |
| 95890 | zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); |
| 95891 | sqlite3DbFree(db, zName); |
| 95892 | zName = zNewName; |
| 95893 | j = -1; |
| @@ -96586,16 +96842,17 @@ | |
| 96842 | pKeyMerge->nField = (u16)nOrderBy; |
| 96843 | pKeyMerge->enc = ENC(db); |
| 96844 | for(i=0; i<nOrderBy; i++){ |
| 96845 | CollSeq *pColl; |
| 96846 | Expr *pTerm = pOrderBy->a[i].pExpr; |
| 96847 | if( pTerm->flags & EP_Collate ){ |
| 96848 | pColl = sqlite3ExprCollSeq(pParse, pTerm); |
| 96849 | }else{ |
| 96850 | pColl = multiSelectCollSeq(pParse, p, aPermute[i]); |
| 96851 | if( pColl==0 ) pColl = db->pDfltColl; |
| 96852 | pOrderBy->a[i].pExpr = |
| 96853 | sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); |
| 96854 | } |
| 96855 | pKeyMerge->aColl[i] = pColl; |
| 96856 | pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; |
| 96857 | } |
| 96858 | } |
| @@ -96794,10 +97051,11 @@ | |
| 97051 | */ |
| 97052 | sqlite3VdbeResolveLabel(v, labelCmpr); |
| 97053 | sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); |
| 97054 | sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, |
| 97055 | (char*)pKeyMerge, P4_KEYINFO_HANDOFF); |
| 97056 | sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); |
| 97057 | sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); |
| 97058 | |
| 97059 | /* Release temporary registers |
| 97060 | */ |
| 97061 | if( regPrev ){ |
| @@ -96861,13 +97119,10 @@ | |
| 97119 | }else{ |
| 97120 | Expr *pNew; |
| 97121 | assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); |
| 97122 | assert( pExpr->pLeft==0 && pExpr->pRight==0 ); |
| 97123 | pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); |
| 97124 | sqlite3ExprDelete(db, pExpr); |
| 97125 | pExpr = pNew; |
| 97126 | } |
| 97127 | }else{ |
| 97128 | pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); |
| @@ -97414,38 +97669,47 @@ | |
| 97669 | return 1; |
| 97670 | } |
| 97671 | #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
| 97672 | |
| 97673 | /* |
| 97674 | ** Based on the contents of the AggInfo structure indicated by the first |
| 97675 | ** argument, this function checks if the following are true: |
| 97676 | ** |
| 97677 | ** * the query contains just a single aggregate function, |
| 97678 | ** * the aggregate function is either min() or max(), and |
| 97679 | ** * the argument to the aggregate function is a column value. |
| 97680 | ** |
| 97681 | ** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX |
| 97682 | ** is returned as appropriate. Also, *ppMinMax is set to point to the |
| 97683 | ** list of arguments passed to the aggregate before returning. |
| 97684 | ** |
| 97685 | ** Or, if the conditions above are not met, *ppMinMax is set to 0 and |
| 97686 | ** WHERE_ORDERBY_NORMAL is returned. |
| 97687 | */ |
| 97688 | static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ |
| 97689 | int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ |
| 97690 | |
| 97691 | *ppMinMax = 0; |
| 97692 | if( pAggInfo->nFunc==1 ){ |
| 97693 | Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ |
| 97694 | ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ |
| 97695 | |
| 97696 | assert( pExpr->op==TK_AGG_FUNCTION ); |
| 97697 | if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ |
| 97698 | const char *zFunc = pExpr->u.zToken; |
| 97699 | if( sqlite3StrICmp(zFunc, "min")==0 ){ |
| 97700 | eRet = WHERE_ORDERBY_MIN; |
| 97701 | *ppMinMax = pEList; |
| 97702 | }else if( sqlite3StrICmp(zFunc, "max")==0 ){ |
| 97703 | eRet = WHERE_ORDERBY_MAX; |
| 97704 | *ppMinMax = pEList; |
| 97705 | } |
| 97706 | } |
| 97707 | } |
| 97708 | |
| 97709 | assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); |
| 97710 | return eRet; |
| 97711 | } |
| 97712 | |
| 97713 | /* |
| 97714 | ** The select statement passed as the first argument is an aggregate query. |
| 97715 | ** The second argment is the associated aggregate-info object. This |
| @@ -97536,10 +97800,11 @@ | |
| 97800 | int i, j, k; |
| 97801 | SrcList *pTabList; |
| 97802 | ExprList *pEList; |
| 97803 | struct SrcList_item *pFrom; |
| 97804 | sqlite3 *db = pParse->db; |
| 97805 | Expr *pE, *pRight, *pExpr; |
| 97806 | |
| 97807 | if( db->mallocFailed ){ |
| 97808 | return WRC_Abort; |
| 97809 | } |
| 97810 | if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){ |
| @@ -97621,11 +97886,11 @@ | |
| 97886 | ** |
| 97887 | ** The first loop just checks to see if there are any "*" operators |
| 97888 | ** that need expanding. |
| 97889 | */ |
| 97890 | for(k=0; k<pEList->nExpr; k++){ |
| 97891 | pE = pEList->a[k].pExpr; |
| 97892 | if( pE->op==TK_ALL ) break; |
| 97893 | assert( pE->op!=TK_DOT || pE->pRight!=0 ); |
| 97894 | assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); |
| 97895 | if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; |
| 97896 | } |
| @@ -97639,14 +97904,22 @@ | |
| 97904 | ExprList *pNew = 0; |
| 97905 | int flags = pParse->db->flags; |
| 97906 | int longNames = (flags & SQLITE_FullColNames)!=0 |
| 97907 | && (flags & SQLITE_ShortColNames)==0; |
| 97908 | |
| 97909 | /* When processing FROM-clause subqueries, it is always the case |
| 97910 | ** that full_column_names=OFF and short_column_names=ON. The |
| 97911 | ** sqlite3ResultSetOfSelect() routine makes it so. */ |
| 97912 | assert( (p->selFlags & SF_NestedFrom)==0 |
| 97913 | || ((flags & SQLITE_FullColNames)==0 && |
| 97914 | (flags & SQLITE_ShortColNames)!=0) ); |
| 97915 | |
| 97916 | for(k=0; k<pEList->nExpr; k++){ |
| 97917 | pE = a[k].pExpr; |
| 97918 | pRight = pE->pRight; |
| 97919 | assert( pE->op!=TK_DOT || pRight!=0 ); |
| 97920 | if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){ |
| 97921 | /* This particular expression does not need to be expanded. |
| 97922 | */ |
| 97923 | pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); |
| 97924 | if( pNew ){ |
| 97925 | pNew->a[pNew->nExpr-1].zName = a[k].zName; |
| @@ -97657,44 +97930,56 @@ | |
| 97930 | a[k].pExpr = 0; |
| 97931 | }else{ |
| 97932 | /* This expression is a "*" or a "TABLE.*" and needs to be |
| 97933 | ** expanded. */ |
| 97934 | int tableSeen = 0; /* Set to 1 when TABLE matches */ |
| 97935 | char *zTName = 0; /* text of name of TABLE */ |
| 97936 | if( pE->op==TK_DOT ){ |
| 97937 | assert( pE->pLeft!=0 ); |
| 97938 | assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); |
| 97939 | zTName = pE->pLeft->u.zToken; |
| 97940 | } |
| 97941 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 97942 | Table *pTab = pFrom->pTab; |
| 97943 | Select *pSub = pFrom->pSelect; |
| 97944 | char *zTabName = pFrom->zAlias; |
| 97945 | const char *zSchemaName = 0; |
| 97946 | int iDb; |
| 97947 | if( zTabName==0 ){ |
| 97948 | zTabName = pTab->zName; |
| 97949 | } |
| 97950 | if( db->mallocFailed ) break; |
| 97951 | if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ |
| 97952 | pSub = 0; |
| 97953 | if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ |
| 97954 | continue; |
| 97955 | } |
| 97956 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 97957 | zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*"; |
| 97958 | } |
| 97959 | for(j=0; j<pTab->nCol; j++){ |
| 97960 | char *zName = pTab->aCol[j].zName; |
| 97961 | char *zColname; /* The computed column name */ |
| 97962 | char *zToFree; /* Malloced string that needs to be freed */ |
| 97963 | Token sColname; /* Computed column name as a token */ |
| 97964 | |
| 97965 | assert( zName ); |
| 97966 | if( zTName && pSub |
| 97967 | && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0 |
| 97968 | ){ |
| 97969 | continue; |
| 97970 | } |
| 97971 | |
| 97972 | /* If a column is marked as 'hidden' (currently only possible |
| 97973 | ** for virtual tables), do not include it in the expanded |
| 97974 | ** result-set list. |
| 97975 | */ |
| 97976 | if( IsHiddenColumn(&pTab->aCol[j]) ){ |
| 97977 | assert(IsVirtual(pTab)); |
| 97978 | continue; |
| 97979 | } |
| 97980 | tableSeen = 1; |
| 97981 | |
| 97982 | if( i>0 && zTName==0 ){ |
| 97983 | if( (pFrom->jointype & JT_NATURAL)!=0 |
| 97984 | && tableAndColumnIndex(pTabList, i, zName, 0, 0) |
| 97985 | ){ |
| @@ -97713,10 +97998,14 @@ | |
| 97998 | zToFree = 0; |
| 97999 | if( longNames || pTabList->nSrc>1 ){ |
| 98000 | Expr *pLeft; |
| 98001 | pLeft = sqlite3Expr(db, TK_ID, zTabName); |
| 98002 | pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); |
| 98003 | if( zSchemaName ){ |
| 98004 | pLeft = sqlite3Expr(db, TK_ID, zSchemaName); |
| 98005 | pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0); |
| 98006 | } |
| 98007 | if( longNames ){ |
| 98008 | zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); |
| 98009 | zToFree = zColname; |
| 98010 | } |
| 98011 | }else{ |
| @@ -97724,10 +98013,22 @@ | |
| 98013 | } |
| 98014 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
| 98015 | sColname.z = zColname; |
| 98016 | sColname.n = sqlite3Strlen30(zColname); |
| 98017 | sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
| 98018 | if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ |
| 98019 | struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; |
| 98020 | if( pSub ){ |
| 98021 | pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); |
| 98022 | testcase( pX->zSpan==0 ); |
| 98023 | }else{ |
| 98024 | pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s", |
| 98025 | zSchemaName, zTabName, zColname); |
| 98026 | testcase( pX->zSpan==0 ); |
| 98027 | } |
| 98028 | pX->bSpanIsTab = 1; |
| 98029 | } |
| 98030 | sqlite3DbFree(db, zToFree); |
| 98031 | } |
| 98032 | } |
| 98033 | if( !tableSeen ){ |
| 98034 | if( zTName ){ |
| @@ -98781,15 +99082,21 @@ | |
| 99082 | ** index or indices to use) should place a different priority on |
| 99083 | ** satisfying the 'ORDER BY' clause than it does in other cases. |
| 99084 | ** Refer to code and comments in where.c for details. |
| 99085 | */ |
| 99086 | ExprList *pMinMax = 0; |
| 99087 | u8 flag = WHERE_ORDERBY_NORMAL; |
| 99088 | |
| 99089 | assert( p->pGroupBy==0 ); |
| 99090 | assert( flag==0 ); |
| 99091 | if( p->pHaving==0 ){ |
| 99092 | flag = minMaxQuery(&sAggInfo, &pMinMax); |
| 99093 | } |
| 99094 | assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); |
| 99095 | |
| 99096 | if( flag ){ |
| 99097 | pMinMax = sqlite3ExprListDup(db, pMinMax, 0); |
| 99098 | pDel = pMinMax; |
| 99099 | if( pMinMax && !db->mallocFailed ){ |
| 99100 | pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
| 99101 | pMinMax->a[0].pExpr->op = TK_COLUMN; |
| 99102 | } |
| @@ -102673,11 +102980,11 @@ | |
| 102980 | #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ |
| 102981 | #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ |
| 102982 | #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ |
| 102983 | #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ |
| 102984 | #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ |
| 102985 | #define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */ |
| 102986 | #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */ |
| 102987 | #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */ |
| 102988 | #define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */ |
| 102989 | #define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */ |
| 102990 | #define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */ |
| @@ -102823,11 +103130,11 @@ | |
| 103130 | sqlite3DbFree(db, pOld); |
| 103131 | } |
| 103132 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 103133 | } |
| 103134 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 103135 | pTerm->pExpr = sqlite3ExprSkipCollate(p); |
| 103136 | pTerm->wtFlags = wtFlags; |
| 103137 | pTerm->pWC = pWC; |
| 103138 | pTerm->iParent = -1; |
| 103139 | return idx; |
| 103140 | } |
| @@ -102983,27 +103290,36 @@ | |
| 103290 | |
| 103291 | /* |
| 103292 | ** Commute a comparison operator. Expressions of the form "X op Y" |
| 103293 | ** are converted into "Y op X". |
| 103294 | ** |
| 103295 | ** If left/right precendence rules come into play when determining the |
| 103296 | ** collating |
| 103297 | ** side of the comparison, it remains associated with the same side after |
| 103298 | ** the commutation. So "Y collate NOCASE op X" becomes |
| 103299 | ** "X op Y". This is because any collation sequence on |
| 103300 | ** the left hand side of a comparison overrides any collation sequence |
| 103301 | ** attached to the right. For the same reason the EP_Collate flag |
| 103302 | ** is not commuted. |
| 103303 | */ |
| 103304 | static void exprCommute(Parse *pParse, Expr *pExpr){ |
| 103305 | u16 expRight = (pExpr->pRight->flags & EP_Collate); |
| 103306 | u16 expLeft = (pExpr->pLeft->flags & EP_Collate); |
| 103307 | assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); |
| 103308 | if( expRight==expLeft ){ |
| 103309 | /* Either X and Y both have COLLATE operator or neither do */ |
| 103310 | if( expRight ){ |
| 103311 | /* Both X and Y have COLLATE operators. Make sure X is always |
| 103312 | ** used by clearing the EP_Collate flag from Y. */ |
| 103313 | pExpr->pRight->flags &= ~EP_Collate; |
| 103314 | }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ |
| 103315 | /* Neither X nor Y have COLLATE operators, but X has a non-default |
| 103316 | ** collating sequence. So add the EP_Collate marker on X to cause |
| 103317 | ** it to be searched first. */ |
| 103318 | pExpr->pLeft->flags |= EP_Collate; |
| 103319 | } |
| 103320 | } |
| 103321 | SWAP(Expr*,pExpr->pRight,pExpr->pLeft); |
| 103322 | if( pExpr->op>=TK_GT ){ |
| 103323 | assert( TK_LT==TK_GT+2 ); |
| 103324 | assert( TK_GE==TK_LE+2 ); |
| 103325 | assert( TK_GT>TK_EQ ); |
| @@ -103076,16 +103392,16 @@ | |
| 103392 | ** it to be useful for optimising expression pX. Store this |
| 103393 | ** value in variable pColl. |
| 103394 | */ |
| 103395 | assert(pX->pLeft); |
| 103396 | pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| 103397 | if( pColl==0 ) pColl = pParse->db->pDfltColl; |
| 103398 | |
| 103399 | for(j=0; pIdx->aiColumn[j]!=iColumn; j++){ |
| 103400 | if( NEVER(j>=pIdx->nColumn) ) return 0; |
| 103401 | } |
| 103402 | if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; |
| 103403 | } |
| 103404 | return pTerm; |
| 103405 | } |
| 103406 | } |
| 103407 | } |
| @@ -103600,10 +103916,11 @@ | |
| 103916 | return; |
| 103917 | } |
| 103918 | pTerm = &pWC->a[idxTerm]; |
| 103919 | pMaskSet = pWC->pMaskSet; |
| 103920 | pExpr = pTerm->pExpr; |
| 103921 | assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); |
| 103922 | prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); |
| 103923 | op = pExpr->op; |
| 103924 | if( op==TK_IN ){ |
| 103925 | assert( pExpr->pRight==0 ); |
| 103926 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| @@ -103626,12 +103943,12 @@ | |
| 103943 | pTerm->prereqAll = prereqAll; |
| 103944 | pTerm->leftCursor = -1; |
| 103945 | pTerm->iParent = -1; |
| 103946 | pTerm->eOperator = 0; |
| 103947 | if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ |
| 103948 | Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); |
| 103949 | Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); |
| 103950 | if( pLeft->op==TK_COLUMN ){ |
| 103951 | pTerm->leftCursor = pLeft->iTable; |
| 103952 | pTerm->u.leftColumn = pLeft->iColumn; |
| 103953 | pTerm->eOperator = operatorMask(op); |
| 103954 | } |
| @@ -103655,11 +103972,11 @@ | |
| 103972 | }else{ |
| 103973 | pDup = pExpr; |
| 103974 | pNew = pTerm; |
| 103975 | } |
| 103976 | exprCommute(pParse, pDup); |
| 103977 | pLeft = sqlite3ExprSkipCollate(pDup->pLeft); |
| 103978 | pNew->leftCursor = pLeft->iTable; |
| 103979 | pNew->u.leftColumn = pLeft->iColumn; |
| 103980 | testcase( (prereqLeft | extraRight) != prereqLeft ); |
| 103981 | pNew->prereqRight = prereqLeft | extraRight; |
| 103982 | pNew->prereqAll = prereqAll; |
| @@ -103734,11 +104051,11 @@ | |
| 104051 | Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ |
| 104052 | Expr *pNewExpr1; |
| 104053 | Expr *pNewExpr2; |
| 104054 | int idxNew1; |
| 104055 | int idxNew2; |
| 104056 | Token sCollSeqName; /* Name of collating sequence */ |
| 104057 | |
| 104058 | pLeft = pExpr->x.pList->a[1].pExpr; |
| 104059 | pStr2 = sqlite3ExprDup(db, pStr1, 0); |
| 104060 | if( !db->mallocFailed ){ |
| 104061 | u8 c, *pC; /* Last character before the first wildcard */ |
| @@ -103756,20 +104073,23 @@ | |
| 104073 | |
| 104074 | c = sqlite3UpperToLower[c]; |
| 104075 | } |
| 104076 | *pC = c + 1; |
| 104077 | } |
| 104078 | sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; |
| 104079 | sCollSeqName.n = 6; |
| 104080 | pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); |
| 104081 | pNewExpr1 = sqlite3PExpr(pParse, TK_GE, |
| 104082 | sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName), |
| 104083 | pStr1, 0); |
| 104084 | idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); |
| 104085 | testcase( idxNew1==0 ); |
| 104086 | exprAnalyze(pSrc, pWC, idxNew1); |
| 104087 | pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); |
| 104088 | pNewExpr2 = sqlite3PExpr(pParse, TK_LT, |
| 104089 | sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName), |
| 104090 | pStr2, 0); |
| 104091 | idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); |
| 104092 | testcase( idxNew2==0 ); |
| 104093 | exprAnalyze(pSrc, pWC, idxNew2); |
| 104094 | pTerm = &pWC->a[idxTerm]; |
| 104095 | if( isComplete ){ |
| @@ -103883,16 +104203,16 @@ | |
| 104203 | ){ |
| 104204 | int i; |
| 104205 | const char *zColl = pIdx->azColl[iCol]; |
| 104206 | |
| 104207 | for(i=0; i<pList->nExpr; i++){ |
| 104208 | Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); |
| 104209 | if( p->op==TK_COLUMN |
| 104210 | && p->iColumn==pIdx->aiColumn[iCol] |
| 104211 | && p->iTable==iBase |
| 104212 | ){ |
| 104213 | CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); |
| 104214 | if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ |
| 104215 | return i; |
| 104216 | } |
| 104217 | } |
| 104218 | } |
| @@ -103935,11 +104255,11 @@ | |
| 104255 | ** matching "col=X" expression and the column is on the same table as pIdx, |
| 104256 | ** set the corresponding bit in variable mask. |
| 104257 | */ |
| 104258 | for(i=0; i<pDistinct->nExpr; i++){ |
| 104259 | WhereTerm *pTerm; |
| 104260 | Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); |
| 104261 | if( p->op!=TK_COLUMN ) return 0; |
| 104262 | pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0); |
| 104263 | if( pTerm ){ |
| 104264 | Expr *pX = pTerm->pExpr; |
| 104265 | CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| @@ -103987,11 +104307,11 @@ | |
| 104307 | /* If any of the expressions is an IPK column on table iBase, then return |
| 104308 | ** true. Note: The (p->iTable==iBase) part of this test may be false if the |
| 104309 | ** current SELECT is a correlated sub-query. |
| 104310 | */ |
| 104311 | for(i=0; i<pDistinct->nExpr; i++){ |
| 104312 | Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); |
| 104313 | if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; |
| 104314 | } |
| 104315 | |
| 104316 | /* Loop through all indices on the table, checking each to see if it makes |
| 104317 | ** the DISTINCT qualifier redundant. It does so if: |
| @@ -104464,11 +104784,11 @@ | |
| 104784 | for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104785 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104786 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104787 | testcase( pTerm->eOperator==WO_IN ); |
| 104788 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104789 | if( pTerm->eOperator & (WO_ISNULL) ) continue; |
| 104790 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104791 | nTerm++; |
| 104792 | } |
| 104793 | |
| 104794 | /* If the ORDER BY clause contains only columns in the current |
| @@ -104512,29 +104832,32 @@ | |
| 104832 | *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; |
| 104833 | *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = |
| 104834 | pUsage; |
| 104835 | |
| 104836 | for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104837 | u8 op; |
| 104838 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104839 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104840 | testcase( pTerm->eOperator==WO_IN ); |
| 104841 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104842 | if( pTerm->eOperator & (WO_ISNULL) ) continue; |
| 104843 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104844 | pIdxCons[j].iColumn = pTerm->u.leftColumn; |
| 104845 | pIdxCons[j].iTermOffset = i; |
| 104846 | op = (u8)pTerm->eOperator; |
| 104847 | if( op==WO_IN ) op = WO_EQ; |
| 104848 | pIdxCons[j].op = op; |
| 104849 | /* The direct assignment in the previous line is possible only because |
| 104850 | ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The |
| 104851 | ** following asserts verify this fact. */ |
| 104852 | assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); |
| 104853 | assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); |
| 104854 | assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); |
| 104855 | assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); |
| 104856 | assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); |
| 104857 | assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); |
| 104858 | assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); |
| 104859 | j++; |
| 104860 | } |
| 104861 | for(i=0; i<nOrderBy; i++){ |
| 104862 | Expr *pExpr = pOrderBy->a[i].pExpr; |
| 104863 | pIdxOrderBy[i].iColumn = pExpr->iColumn; |
| @@ -104616,10 +104939,11 @@ | |
| 104939 | struct sqlite3_index_constraint *pIdxCons; |
| 104940 | struct sqlite3_index_constraint_usage *pUsage; |
| 104941 | WhereTerm *pTerm; |
| 104942 | int i, j; |
| 104943 | int nOrderBy; |
| 104944 | int bAllowIN; /* Allow IN optimizations */ |
| 104945 | double rCost; |
| 104946 | |
| 104947 | /* Make sure wsFlags is initialized to some sane value. Otherwise, if the |
| 104948 | ** malloc in allocateIndexInfo() fails and this function returns leaving |
| 104949 | ** wsFlags in an uninitialized state, the caller may behave unpredictably. |
| @@ -104650,63 +104974,91 @@ | |
| 104974 | ** sqlite3ViewGetColumnNames() would have picked up the error. |
| 104975 | */ |
| 104976 | assert( pTab->azModuleArg && pTab->azModuleArg[0] ); |
| 104977 | assert( sqlite3GetVTable(pParse->db, pTab) ); |
| 104978 | |
| 104979 | /* Try once or twice. On the first attempt, allow IN optimizations. |
| 104980 | ** If an IN optimization is accepted by the virtual table xBestIndex |
| 104981 | ** method, but the pInfo->aConstrainUsage.omit flag is not set, then |
| 104982 | ** the query will not work because it might allow duplicate rows in |
| 104983 | ** output. In that case, run the xBestIndex method a second time |
| 104984 | ** without the IN constraints. Usually this loop only runs once. |
| 104985 | ** The loop will exit using a "break" statement. |
| 104986 | */ |
| 104987 | for(bAllowIN=1; 1; bAllowIN--){ |
| 104988 | assert( bAllowIN==0 || bAllowIN==1 ); |
| 104989 | |
| 104990 | /* Set the aConstraint[].usable fields and initialize all |
| 104991 | ** output variables to zero. |
| 104992 | ** |
| 104993 | ** aConstraint[].usable is true for constraints where the right-hand |
| 104994 | ** side contains only references to tables to the left of the current |
| 104995 | ** table. In other words, if the constraint is of the form: |
| 104996 | ** |
| 104997 | ** column = expr |
| 104998 | ** |
| 104999 | ** and we are evaluating a join, then the constraint on column is |
| 105000 | ** only valid if all tables referenced in expr occur to the left |
| 105001 | ** of the table containing column. |
| 105002 | ** |
| 105003 | ** The aConstraints[] array contains entries for all constraints |
| 105004 | ** on the current table. That way we only have to compute it once |
| 105005 | ** even though we might try to pick the best index multiple times. |
| 105006 | ** For each attempt at picking an index, the order of tables in the |
| 105007 | ** join might be different so we have to recompute the usable flag |
| 105008 | ** each time. |
| 105009 | */ |
| 105010 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 105011 | pUsage = pIdxInfo->aConstraintUsage; |
| 105012 | for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ |
| 105013 | j = pIdxCons->iTermOffset; |
| 105014 | pTerm = &pWC->a[j]; |
| 105015 | if( (pTerm->prereqRight&p->notReady)==0 |
| 105016 | && (bAllowIN || pTerm->eOperator!=WO_IN) |
| 105017 | ){ |
| 105018 | pIdxCons->usable = 1; |
| 105019 | }else{ |
| 105020 | pIdxCons->usable = 0; |
| 105021 | } |
| 105022 | } |
| 105023 | memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); |
| 105024 | if( pIdxInfo->needToFreeIdxStr ){ |
| 105025 | sqlite3_free(pIdxInfo->idxStr); |
| 105026 | } |
| 105027 | pIdxInfo->idxStr = 0; |
| 105028 | pIdxInfo->idxNum = 0; |
| 105029 | pIdxInfo->needToFreeIdxStr = 0; |
| 105030 | pIdxInfo->orderByConsumed = 0; |
| 105031 | /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ |
| 105032 | pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); |
| 105033 | nOrderBy = pIdxInfo->nOrderBy; |
| 105034 | if( !p->pOrderBy ){ |
| 105035 | pIdxInfo->nOrderBy = 0; |
| 105036 | } |
| 105037 | |
| 105038 | if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ |
| 105039 | return; |
| 105040 | } |
| 105041 | |
| 105042 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 105043 | for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ |
| 105044 | if( pUsage[i].argvIndex>0 ){ |
| 105045 | j = pIdxCons->iTermOffset; |
| 105046 | pTerm = &pWC->a[j]; |
| 105047 | p->cost.used |= pTerm->prereqRight; |
| 105048 | if( pTerm->eOperator==WO_IN && pUsage[i].omit==0 ){ |
| 105049 | /* Do not attempt to use an IN constraint if the virtual table |
| 105050 | ** says that the equivalent EQ constraint cannot be safely omitted. |
| 105051 | ** If we do attempt to use such a constraint, some rows might be |
| 105052 | ** repeated in the output. */ |
| 105053 | break; |
| 105054 | } |
| 105055 | } |
| 105056 | } |
| 105057 | if( i>=pIdxInfo->nConstraint ) break; |
| 105058 | } |
| 105059 | |
| 105060 | /* If there is an ORDER BY clause, and the selected virtual table index |
| 105061 | ** does not satisfy it, increase the cost of the scan accordingly. This |
| 105062 | ** matches the processing for non-virtual tables in bestBtreeIndex(). |
| 105063 | */ |
| 105064 | rCost = pIdxInfo->estimatedCost; |
| @@ -105273,11 +105625,11 @@ | |
| 105625 | WhereTerm *pConstraint; /* A constraint in the WHERE clause */ |
| 105626 | |
| 105627 | /* If the next term of the ORDER BY clause refers to anything other than |
| 105628 | ** a column in the "base" table, then this index will not be of any |
| 105629 | ** further use in handling the ORDER BY. */ |
| 105630 | pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr); |
| 105631 | if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){ |
| 105632 | break; |
| 105633 | } |
| 105634 | |
| 105635 | /* Find column number and collating sequence for the next entry |
| @@ -105299,11 +105651,11 @@ | |
| 105651 | /* Check to see if the column number and collating sequence of the |
| 105652 | ** index match the column number and collating sequence of the ORDER BY |
| 105653 | ** clause entry. Set isMatch to 1 if they both match. */ |
| 105654 | if( pOBExpr->iColumn==iColumn ){ |
| 105655 | if( zColl ){ |
| 105656 | pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr); |
| 105657 | if( !pColl ) pColl = db->pDfltColl; |
| 105658 | isMatch = sqlite3StrICmp(pColl->zName, zColl)==0; |
| 105659 | }else{ |
| 105660 | isMatch = 1; |
| 105661 | } |
| @@ -105440,10 +105792,15 @@ | |
| 105792 | int idxEqTermMask; /* Index mask of valid equality operators */ |
| 105793 | Index sPk; /* A fake index object for the primary key */ |
| 105794 | tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ |
| 105795 | int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ |
| 105796 | int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */ |
| 105797 | int nPriorSat; /* ORDER BY terms satisfied by outer loops */ |
| 105798 | int nOrderBy; /* Number of ORDER BY terms */ |
| 105799 | char bSortInit; /* Initializer for bSort in inner loop */ |
| 105800 | char bDistInit; /* Initializer for bDist in inner loop */ |
| 105801 | |
| 105802 | |
| 105803 | /* Initialize the cost to a worst-case value */ |
| 105804 | memset(&p->cost, 0, sizeof(p->cost)); |
| 105805 | p->cost.rCost = SQLITE_BIG_DBL; |
| 105806 | |
| @@ -105488,10 +105845,21 @@ | |
| 105845 | WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE |
| 105846 | ); |
| 105847 | eqTermMask = WO_EQ|WO_IN; |
| 105848 | pIdx = 0; |
| 105849 | } |
| 105850 | |
| 105851 | nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; |
| 105852 | if( p->i ){ |
| 105853 | nPriorSat = p->aLevel[p->i-1].plan.nOBSat; |
| 105854 | bSortInit = nPriorSat<nOrderBy; |
| 105855 | bDistInit = 0; |
| 105856 | }else{ |
| 105857 | nPriorSat = 0; |
| 105858 | bSortInit = nOrderBy>0; |
| 105859 | bDistInit = p->pDistinct!=0; |
| 105860 | } |
| 105861 | |
| 105862 | /* Loop over all indices looking for the best one to use |
| 105863 | */ |
| 105864 | for(; pProbe; pIdx=pProbe=pProbe->pNext){ |
| 105865 | const tRowcnt * const aiRowEst = pProbe->aiRowEst; |
| @@ -105566,15 +105934,13 @@ | |
| 105934 | */ |
| 105935 | int bInEst = 0; /* True if "x IN (SELECT...)" seen */ |
| 105936 | int nInMul = 1; /* Number of distinct equalities to lookup */ |
| 105937 | double rangeDiv = (double)1; /* Estimated reduction in search space */ |
| 105938 | int nBound = 0; /* Number of range constraints seen */ |
| 105939 | char bSort = bSortInit; /* True if external sort required */ |
| 105940 | char bDist = bDistInit; /* True if index cannot help with DISTINCT */ |
| 105941 | char bLookup = 0; /* True if not a covering index */ |
| 105942 | WhereTerm *pTerm; /* A single term of the WHERE clause */ |
| 105943 | #ifdef SQLITE_ENABLE_STAT3 |
| 105944 | WhereTerm *pFirstTerm = 0; /* First term matching the index */ |
| 105945 | #endif |
| 105946 | |
| @@ -105581,20 +105947,11 @@ | |
| 105947 | WHERETRACE(( |
| 105948 | " %s(%s):\n", |
| 105949 | pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk") |
| 105950 | )); |
| 105951 | memset(&pc, 0, sizeof(pc)); |
| 105952 | pc.plan.nOBSat = nPriorSat; |
| 105953 | |
| 105954 | /* Determine the values of pc.plan.nEq and nInMul */ |
| 105955 | for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){ |
| 105956 | int j = pProbe->aiColumn[pc.plan.nEq]; |
| 105957 | pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); |
| @@ -106466,32 +106823,40 @@ | |
| 106823 | if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ |
| 106824 | /* Case 0: The table is a virtual-table. Use the VFilter and VNext |
| 106825 | ** to access the data. |
| 106826 | */ |
| 106827 | int iReg; /* P3 Value for OP_VFilter */ |
| 106828 | int addrNotFound; |
| 106829 | sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; |
| 106830 | int nConstraint = pVtabIdx->nConstraint; |
| 106831 | struct sqlite3_index_constraint_usage *aUsage = |
| 106832 | pVtabIdx->aConstraintUsage; |
| 106833 | const struct sqlite3_index_constraint *aConstraint = |
| 106834 | pVtabIdx->aConstraint; |
| 106835 | |
| 106836 | sqlite3ExprCachePush(pParse); |
| 106837 | iReg = sqlite3GetTempRange(pParse, nConstraint+2); |
| 106838 | addrNotFound = pLevel->addrBrk; |
| 106839 | for(j=1; j<=nConstraint; j++){ |
| 106840 | for(k=0; k<nConstraint; k++){ |
| 106841 | if( aUsage[k].argvIndex==j ){ |
| 106842 | WhereTerm *pTerm = &pWC->a[aConstraint[k].iTermOffset]; |
| 106843 | int iTarget = iReg+j+1; |
| 106844 | if( pTerm->eOperator & WO_IN ){ |
| 106845 | codeEqualityTerm(pParse, pTerm, pLevel, iTarget); |
| 106846 | addrNotFound = pLevel->addrNxt; |
| 106847 | }else{ |
| 106848 | sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget); |
| 106849 | } |
| 106850 | break; |
| 106851 | } |
| 106852 | } |
| 106853 | if( k==nConstraint ) break; |
| 106854 | } |
| 106855 | sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); |
| 106856 | sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); |
| 106857 | sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr, |
| 106858 | pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); |
| 106859 | pVtabIdx->needToFreeIdxStr = 0; |
| 106860 | for(j=0; j<nConstraint; j++){ |
| 106861 | if( aUsage[j].omit ){ |
| 106862 | int iTerm = aConstraint[j].iTermOffset; |
| @@ -108134,10 +108499,11 @@ | |
| 108499 | Expr* yy122; |
| 108500 | Select* yy159; |
| 108501 | IdList* yy180; |
| 108502 | struct {int value; int mask;} yy207; |
| 108503 | u8 yy258; |
| 108504 | u16 yy305; |
| 108505 | struct LikeOp yy318; |
| 108506 | TriggerStep* yy327; |
| 108507 | ExprSpan yy342; |
| 108508 | SrcList* yy347; |
| 108509 | int yy392; |
| @@ -110084,22 +110450,19 @@ | |
| 110450 | case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); |
| 110451 | case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); |
| 110452 | case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); |
| 110453 | case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98); |
| 110454 | case 109: /* ifexists ::= */ yytestcase(yyruleno==109); |
| 110455 | case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); |
| 110456 | case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); |
| 110457 | {yygotominor.yy392 = 0;} |
| 110458 | break; |
| 110459 | case 29: /* ifnotexists ::= IF NOT EXISTS */ |
| 110460 | case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); |
| 110461 | case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); |
| 110462 | case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); |
| 110463 | case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108); |
| 110464 | case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); |
| 110465 | case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); |
| 110466 | {yygotominor.yy392 = 1;} |
| 110467 | break; |
| 110468 | case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ |
| @@ -110335,12 +110698,19 @@ | |
| 110698 | case 116: /* multiselect_op ::= UNION ALL */ |
| 110699 | {yygotominor.yy392 = TK_ALL;} |
| 110700 | break; |
| 110701 | case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ |
| 110702 | { |
| 110703 | yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); |
| 110704 | } |
| 110705 | break; |
| 110706 | case 119: /* distinct ::= DISTINCT */ |
| 110707 | {yygotominor.yy305 = SF_Distinct;} |
| 110708 | break; |
| 110709 | case 120: /* distinct ::= ALL */ |
| 110710 | case 121: /* distinct ::= */ yytestcase(yyruleno==121); |
| 110711 | {yygotominor.yy305 = 0;} |
| 110712 | break; |
| 110713 | case 122: /* sclp ::= selcollist COMMA */ |
| 110714 | case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246); |
| 110715 | {yygotominor.yy442 = yymsp[-1].minor.yy442;} |
| 110716 | break; |
| @@ -110406,14 +110776,24 @@ | |
| 110776 | break; |
| 110777 | case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ |
| 110778 | { |
| 110779 | if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ |
| 110780 | yygotominor.yy347 = yymsp[-4].minor.yy347; |
| 110781 | }else if( yymsp[-4].minor.yy347->nSrc==1 ){ |
| 110782 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); |
| 110783 | if( yygotominor.yy347 ){ |
| 110784 | struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1]; |
| 110785 | struct SrcList_item *pOld = yymsp[-4].minor.yy347->a; |
| 110786 | pNew->zName = pOld->zName; |
| 110787 | pNew->zDatabase = pOld->zDatabase; |
| 110788 | pOld->zName = pOld->zDatabase = 0; |
| 110789 | } |
| 110790 | sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347); |
| 110791 | }else{ |
| 110792 | Select *pSubquery; |
| 110793 | sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); |
| 110794 | pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0); |
| 110795 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); |
| 110796 | } |
| 110797 | } |
| 110798 | break; |
| 110799 | case 137: /* dbnm ::= */ |
| @@ -110624,11 +111004,11 @@ | |
| 111004 | spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); |
| 111005 | } |
| 111006 | break; |
| 111007 | case 194: /* expr ::= expr COLLATE ids */ |
| 111008 | { |
| 111009 | yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); |
| 111010 | yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; |
| 111011 | yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 111012 | } |
| 111013 | break; |
| 111014 | case 195: /* expr ::= CAST LP expr AS typetoken RP */ |
| @@ -110642,11 +111022,11 @@ | |
| 111022 | if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ |
| 111023 | sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); |
| 111024 | } |
| 111025 | yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); |
| 111026 | spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); |
| 111027 | if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){ |
| 111028 | yygotominor.yy342.pExpr->flags |= EP_Distinct; |
| 111029 | } |
| 111030 | } |
| 111031 | break; |
| 111032 | case 197: /* expr ::= ID LP STAR RP */ |
| @@ -110883,28 +111263,20 @@ | |
| 111263 | case 244: /* uniqueflag ::= */ |
| 111264 | {yygotominor.yy392 = OE_None;} |
| 111265 | break; |
| 111266 | case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */ |
| 111267 | { |
| 111268 | Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); |
| 111269 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p); |
| 111270 | sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1); |
| 111271 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 111272 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 111273 | } |
| 111274 | break; |
| 111275 | case 248: /* idxlist ::= nm collate sortorder */ |
| 111276 | { |
| 111277 | Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); |
| 111278 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p); |
| 111279 | sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); |
| 111280 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 111281 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 111282 | } |
| @@ -141105,10 +141477,11 @@ | |
| 141477 | extern int Sqlitemultiplex_Init(Tcl_Interp*); |
| 141478 | extern int SqliteSuperlock_Init(Tcl_Interp*); |
| 141479 | extern int SqlitetestSyscall_Init(Tcl_Interp*); |
| 141480 | extern int Sqlitetestfuzzer_Init(Tcl_Interp*); |
| 141481 | extern int Sqlitetestwholenumber_Init(Tcl_Interp*); |
| 141482 | extern int Sqlitetestregexp_Init(Tcl_Interp*); |
| 141483 | |
| 141484 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141485 | extern int Sqlitetestfts3_Init(Tcl_Interp *interp); |
| 141486 | #endif |
| 141487 | |
| @@ -141148,10 +141521,11 @@ | |
| 141521 | Sqlitemultiplex_Init(interp); |
| 141522 | SqliteSuperlock_Init(interp); |
| 141523 | SqlitetestSyscall_Init(interp); |
| 141524 | Sqlitetestfuzzer_Init(interp); |
| 141525 | Sqlitetestwholenumber_Init(interp); |
| 141526 | Sqlitetestregexp_Init(interp); |
| 141527 | |
| 141528 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141529 | Sqlitetestfts3_Init(interp); |
| 141530 | #endif |
| 141531 | |
| 141532 |
+844
-470
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | -** version 3.7.15. By combining all the individual C code files into this | |
| 3 | +** version 3.7.16. By combining all the individual C code files into this | |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| @@ -671,13 +671,13 @@ | ||
| 671 | 671 | ** |
| 672 | 672 | ** See also: [sqlite3_libversion()], |
| 673 | 673 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 674 | 674 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 675 | 675 | */ |
| 676 | -#define SQLITE_VERSION "3.7.15" | |
| 677 | -#define SQLITE_VERSION_NUMBER 3007015 | |
| 678 | -#define SQLITE_SOURCE_ID "2012-10-16 23:08:28 f021559d8a23934e3bdccad5b55fc7a91d185f53" | |
| 676 | +#define SQLITE_VERSION "3.7.16" | |
| 677 | +#define SQLITE_VERSION_NUMBER 3007016 | |
| 678 | +#define SQLITE_SOURCE_ID "2012-12-08 06:46:05 e65db42c9fdc1d6f257c8db54a46ee4fc0d7aaf0" | |
| 679 | 679 | |
| 680 | 680 | /* |
| 681 | 681 | ** CAPI3REF: Run-Time Library Version Numbers |
| 682 | 682 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 683 | 683 | ** |
| @@ -2162,11 +2162,11 @@ | ||
| 2162 | 2162 | ** database connection is opened. By default, URI handling is globally |
| 2163 | 2163 | ** disabled. The default value may be changed by compiling with the |
| 2164 | 2164 | ** [SQLITE_USE_URI] symbol defined. |
| 2165 | 2165 | ** |
| 2166 | 2166 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 2167 | -** <dd> This option taks a single integer argument which is interpreted as | |
| 2167 | +** <dd> This option takes a single integer argument which is interpreted as | |
| 2168 | 2168 | ** a boolean in order to enable or disable the use of covering indices for |
| 2169 | 2169 | ** full table scans in the query optimizer. The default setting is determined |
| 2170 | 2170 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 2171 | 2171 | ** if that compile-time option is omitted. |
| 2172 | 2172 | ** The ability to disable the use of covering indices for full table scans |
| @@ -10573,24 +10573,24 @@ | ||
| 10573 | 10573 | ** and the value of Index.onError indicate the which conflict resolution |
| 10574 | 10574 | ** algorithm to employ whenever an attempt is made to insert a non-unique |
| 10575 | 10575 | ** element. |
| 10576 | 10576 | */ |
| 10577 | 10577 | struct Index { |
| 10578 | - char *zName; /* Name of this index */ | |
| 10579 | - int *aiColumn; /* Which columns are used by this index. 1st is 0 */ | |
| 10580 | - tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ | |
| 10581 | - Table *pTable; /* The SQL table being indexed */ | |
| 10582 | - char *zColAff; /* String defining the affinity of each column */ | |
| 10583 | - Index *pNext; /* The next index associated with the same table */ | |
| 10584 | - Schema *pSchema; /* Schema containing this index */ | |
| 10585 | - u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ | |
| 10586 | - char **azColl; /* Array of collation sequence names for index */ | |
| 10587 | - int nColumn; /* Number of columns in the table used by this index */ | |
| 10588 | - int tnum; /* Page containing root of this index in database file */ | |
| 10589 | - u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ | |
| 10590 | - u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ | |
| 10591 | - u8 bUnordered; /* Use this index for == or IN queries only */ | |
| 10578 | + char *zName; /* Name of this index */ | |
| 10579 | + int *aiColumn; /* Which columns are used by this index. 1st is 0 */ | |
| 10580 | + tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ | |
| 10581 | + Table *pTable; /* The SQL table being indexed */ | |
| 10582 | + char *zColAff; /* String defining the affinity of each column */ | |
| 10583 | + Index *pNext; /* The next index associated with the same table */ | |
| 10584 | + Schema *pSchema; /* Schema containing this index */ | |
| 10585 | + u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ | |
| 10586 | + char **azColl; /* Array of collation sequence names for index */ | |
| 10587 | + int tnum; /* DB Page containing root of this index */ | |
| 10588 | + u16 nColumn; /* Number of columns in table used by this index */ | |
| 10589 | + u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ | |
| 10590 | + unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ | |
| 10591 | + unsigned bUnordered:1; /* Use this index for == or IN queries only */ | |
| 10592 | 10592 | #ifdef SQLITE_ENABLE_STAT3 |
| 10593 | 10593 | int nSample; /* Number of elements in aSample[] */ |
| 10594 | 10594 | tRowcnt avgEq; /* Average nEq value for key values not in aSample */ |
| 10595 | 10595 | IndexSample *aSample; /* Samples of the left-most key */ |
| 10596 | 10596 | #endif |
| @@ -10767,11 +10767,10 @@ | ||
| 10767 | 10767 | Expr *pRight; /* Right subnode */ |
| 10768 | 10768 | union { |
| 10769 | 10769 | ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */ |
| 10770 | 10770 | Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */ |
| 10771 | 10771 | } x; |
| 10772 | - CollSeq *pColl; /* The collation type of the column or 0 */ | |
| 10773 | 10772 | |
| 10774 | 10773 | /* If the EP_Reduced flag is set in the Expr.flags mask, then no |
| 10775 | 10774 | ** space is allocated for the fields below this point. An attempt to |
| 10776 | 10775 | ** access them will result in a segfault or malfunction. |
| 10777 | 10776 | *********************************************************************/ |
| @@ -10803,11 +10802,11 @@ | ||
| 10803 | 10802 | #define EP_Error 0x0008 /* Expression contains one or more errors */ |
| 10804 | 10803 | #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ |
| 10805 | 10804 | #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ |
| 10806 | 10805 | #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ |
| 10807 | 10806 | #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ |
| 10808 | -#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ | |
| 10807 | +#define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */ | |
| 10809 | 10808 | #define EP_FixedDest 0x0200 /* Result needed in a specific register */ |
| 10810 | 10809 | #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */ |
| 10811 | 10810 | #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */ |
| 10812 | 10811 | #define EP_Hint 0x1000 /* Not used */ |
| 10813 | 10812 | #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ |
| @@ -10861,22 +10860,31 @@ | ||
| 10861 | 10860 | ** name. An expr/name combination can be used in several ways, such |
| 10862 | 10861 | ** as the list of "expr AS ID" fields following a "SELECT" or in the |
| 10863 | 10862 | ** list of "ID = expr" items in an UPDATE. A list of expressions can |
| 10864 | 10863 | ** also be used as the argument to a function, in which case the a.zName |
| 10865 | 10864 | ** field is not used. |
| 10865 | +** | |
| 10866 | +** By default the Expr.zSpan field holds a human-readable description of | |
| 10867 | +** the expression that is used in the generation of error messages and | |
| 10868 | +** column labels. In this case, Expr.zSpan is typically the text of a | |
| 10869 | +** column expression as it exists in a SELECT statement. However, if | |
| 10870 | +** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name | |
| 10871 | +** of the result column in the form: DATABASE.TABLE.COLUMN. This later | |
| 10872 | +** form is used for name resolution with nested FROM clauses. | |
| 10866 | 10873 | */ |
| 10867 | 10874 | struct ExprList { |
| 10868 | 10875 | int nExpr; /* Number of expressions on the list */ |
| 10869 | 10876 | int iECursor; /* VDBE Cursor associated with this ExprList */ |
| 10870 | 10877 | struct ExprList_item { /* For each expression in the list */ |
| 10871 | - Expr *pExpr; /* The list of expressions */ | |
| 10872 | - char *zName; /* Token associated with this expression */ | |
| 10873 | - char *zSpan; /* Original text of the expression */ | |
| 10874 | - u8 sortOrder; /* 1 for DESC or 0 for ASC */ | |
| 10875 | - u8 done; /* A flag to indicate when processing is finished */ | |
| 10876 | - u16 iOrderByCol; /* For ORDER BY, column number in result set */ | |
| 10877 | - u16 iAlias; /* Index into Parse.aAlias[] for zName */ | |
| 10878 | + Expr *pExpr; /* The list of expressions */ | |
| 10879 | + char *zName; /* Token associated with this expression */ | |
| 10880 | + char *zSpan; /* Original text of the expression */ | |
| 10881 | + u8 sortOrder; /* 1 for DESC or 0 for ASC */ | |
| 10882 | + unsigned done :1; /* A flag to indicate when processing is finished */ | |
| 10883 | + unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ | |
| 10884 | + u16 iOrderByCol; /* For ORDER BY, column number in result set */ | |
| 10885 | + u16 iAlias; /* Index into Parse.aAlias[] for zName */ | |
| 10878 | 10886 | } *a; /* Alloc a power of two greater or equal to nExpr */ |
| 10879 | 10887 | }; |
| 10880 | 10888 | |
| 10881 | 10889 | /* |
| 10882 | 10890 | ** An instance of this structure is used by the parser to record both |
| @@ -11192,10 +11200,11 @@ | ||
| 11192 | 11200 | #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ |
| 11193 | 11201 | #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ |
| 11194 | 11202 | #define SF_UseSorter 0x0040 /* Sort using a sorter */ |
| 11195 | 11203 | #define SF_Values 0x0080 /* Synthesized from VALUES clause */ |
| 11196 | 11204 | #define SF_Materialize 0x0100 /* Force materialization of views */ |
| 11205 | +#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ | |
| 11197 | 11206 | |
| 11198 | 11207 | |
| 11199 | 11208 | /* |
| 11200 | 11209 | ** The results of a select can be distributed in several ways. The |
| 11201 | 11210 | ** "SRT" prefix means "SELECT Result Type". |
| @@ -11420,10 +11429,11 @@ | ||
| 11420 | 11429 | #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ |
| 11421 | 11430 | #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ |
| 11422 | 11431 | #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ |
| 11423 | 11432 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ |
| 11424 | 11433 | #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ |
| 11434 | +#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ | |
| 11425 | 11435 | |
| 11426 | 11436 | /* |
| 11427 | 11437 | * Each trigger present in the database schema is stored as an instance of |
| 11428 | 11438 | * struct Trigger. |
| 11429 | 11439 | * |
| @@ -11904,11 +11914,11 @@ | ||
| 11904 | 11914 | SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, |
| 11905 | 11915 | Token*, int, int); |
| 11906 | 11916 | SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); |
| 11907 | 11917 | SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); |
| 11908 | 11918 | SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, |
| 11909 | - Expr*,ExprList*,int,Expr*,Expr*); | |
| 11919 | + Expr*,ExprList*,u16,Expr*,Expr*); | |
| 11910 | 11920 | SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); |
| 11911 | 11921 | SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); |
| 11912 | 11922 | SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); |
| 11913 | 11923 | SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); |
| 11914 | 11924 | #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) |
| @@ -12112,12 +12122,13 @@ | ||
| 12112 | 12122 | SQLITE_PRIVATE const char *sqlite3ErrStr(int); |
| 12113 | 12123 | SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); |
| 12114 | 12124 | SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); |
| 12115 | 12125 | SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); |
| 12116 | 12126 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); |
| 12117 | -SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*); | |
| 12118 | -SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*); | |
| 12127 | +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*); | |
| 12128 | +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); | |
| 12129 | +SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); | |
| 12119 | 12130 | SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); |
| 12120 | 12131 | SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); |
| 12121 | 12132 | SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); |
| 12122 | 12133 | SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); |
| 12123 | 12134 | SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); |
| @@ -12160,10 +12171,11 @@ | ||
| 12160 | 12171 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); |
| 12161 | 12172 | SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); |
| 12162 | 12173 | SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); |
| 12163 | 12174 | SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); |
| 12164 | 12175 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); |
| 12176 | +SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); | |
| 12165 | 12177 | SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); |
| 12166 | 12178 | SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); |
| 12167 | 12179 | SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); |
| 12168 | 12180 | SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); |
| 12169 | 12181 | SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); |
| @@ -12298,12 +12310,14 @@ | ||
| 12298 | 12310 | #define sqlite3FkOldmask(a,b) 0 |
| 12299 | 12311 | #define sqlite3FkRequired(a,b,c,d) 0 |
| 12300 | 12312 | #endif |
| 12301 | 12313 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 12302 | 12314 | SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); |
| 12315 | +SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); | |
| 12303 | 12316 | #else |
| 12304 | 12317 | #define sqlite3FkDelete(a,b) |
| 12318 | + #define sqlite3FkLocateIndex(a,b,c,d,e) | |
| 12305 | 12319 | #endif |
| 12306 | 12320 | |
| 12307 | 12321 | |
| 12308 | 12322 | /* |
| 12309 | 12323 | ** Available fault injectors. Should be numbered beginning with 0. |
| @@ -23307,15 +23321,11 @@ | ||
| 23307 | 23321 | { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, |
| 23308 | 23322 | #endif |
| 23309 | 23323 | #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ |
| 23310 | 23324 | aSyscall[13].pCurrent) |
| 23311 | 23325 | |
| 23312 | -#if SQLITE_ENABLE_LOCKING_STYLE | |
| 23313 | 23326 | { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, |
| 23314 | -#else | |
| 23315 | - { "fchmod", (sqlite3_syscall_ptr)0, 0 }, | |
| 23316 | -#endif | |
| 23317 | 23327 | #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) |
| 23318 | 23328 | |
| 23319 | 23329 | #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE |
| 23320 | 23330 | { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, |
| 23321 | 23331 | #else |
| @@ -23336,13 +23346,10 @@ | ||
| 23336 | 23346 | #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) |
| 23337 | 23347 | |
| 23338 | 23348 | { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, |
| 23339 | 23349 | #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) |
| 23340 | 23350 | |
| 23341 | - { "umask", (sqlite3_syscall_ptr)umask, 0 }, | |
| 23342 | -#define osUmask ((mode_t(*)(mode_t))aSyscall[21].pCurrent) | |
| 23343 | - | |
| 23344 | 23351 | }; /* End of the overrideable system calls */ |
| 23345 | 23352 | |
| 23346 | 23353 | /* |
| 23347 | 23354 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 23348 | 23355 | ** "unix" VFSes. Return SQLITE_OK opon successfully updating the |
| @@ -23443,31 +23450,29 @@ | ||
| 23443 | 23450 | ** process that is able to write to the database will also be able to |
| 23444 | 23451 | ** recover the hot journals. |
| 23445 | 23452 | */ |
| 23446 | 23453 | static int robust_open(const char *z, int f, mode_t m){ |
| 23447 | 23454 | int fd; |
| 23448 | - mode_t m2; | |
| 23449 | - mode_t origM = 0; | |
| 23450 | - if( m==0 ){ | |
| 23451 | - m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; | |
| 23452 | - }else{ | |
| 23453 | - m2 = m; | |
| 23454 | - origM = osUmask(0); | |
| 23455 | - } | |
| 23455 | + mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS; | |
| 23456 | 23456 | do{ |
| 23457 | 23457 | #if defined(O_CLOEXEC) |
| 23458 | 23458 | fd = osOpen(z,f|O_CLOEXEC,m2); |
| 23459 | 23459 | #else |
| 23460 | 23460 | fd = osOpen(z,f,m2); |
| 23461 | 23461 | #endif |
| 23462 | 23462 | }while( fd<0 && errno==EINTR ); |
| 23463 | - if( m ){ | |
| 23464 | - osUmask(origM); | |
| 23465 | - } | |
| 23463 | + if( fd>=0 ){ | |
| 23464 | + if( m!=0 ){ | |
| 23465 | + struct stat statbuf; | |
| 23466 | + if( osFstat(fd, &statbuf)==0 && (statbuf.st_mode&0777)!=m ){ | |
| 23467 | + osFchmod(fd, m); | |
| 23468 | + } | |
| 23469 | + } | |
| 23466 | 23470 | #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) |
| 23467 | - if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); | |
| 23471 | + osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); | |
| 23468 | 23472 | #endif |
| 23473 | + } | |
| 23469 | 23474 | return fd; |
| 23470 | 23475 | } |
| 23471 | 23476 | |
| 23472 | 23477 | /* |
| 23473 | 23478 | ** Helper functions to obtain and relinquish the global mutex. The |
| @@ -29889,11 +29894,11 @@ | ||
| 29889 | 29894 | }; |
| 29890 | 29895 | unsigned int i; /* Loop counter */ |
| 29891 | 29896 | |
| 29892 | 29897 | /* Double-check that the aSyscall[] array has been constructed |
| 29893 | 29898 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 29894 | - assert( ArraySize(aSyscall)==22 ); | |
| 29899 | + assert( ArraySize(aSyscall)==21 ); | |
| 29895 | 29900 | |
| 29896 | 29901 | /* Register all VFSes defined in the aVfs[] array */ |
| 29897 | 29902 | for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 29898 | 29903 | sqlite3_vfs_register(&aVfs[i], i==0); |
| 29899 | 29904 | } |
| @@ -56355,11 +56360,11 @@ | ||
| 56355 | 56360 | sqlite3BtreeLeave(p); |
| 56356 | 56361 | return 0; |
| 56357 | 56362 | } |
| 56358 | 56363 | i = PENDING_BYTE_PAGE(pBt); |
| 56359 | 56364 | if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); |
| 56360 | - sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); | |
| 56365 | + sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); | |
| 56361 | 56366 | sCheck.errMsg.useMalloc = 2; |
| 56362 | 56367 | |
| 56363 | 56368 | /* Check the integrity of the freelist |
| 56364 | 56369 | */ |
| 56365 | 56370 | checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), |
| @@ -56890,11 +56895,16 @@ | ||
| 56890 | 56895 | /* |
| 56891 | 56896 | ** Parameter zSrcData points to a buffer containing the data for |
| 56892 | 56897 | ** page iSrcPg from the source database. Copy this data into the |
| 56893 | 56898 | ** destination database. |
| 56894 | 56899 | */ |
| 56895 | -static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){ | |
| 56900 | +static int backupOnePage( | |
| 56901 | + sqlite3_backup *p, /* Backup handle */ | |
| 56902 | + Pgno iSrcPg, /* Source database page to backup */ | |
| 56903 | + const u8 *zSrcData, /* Source database page data */ | |
| 56904 | + int bUpdate /* True for an update, false otherwise */ | |
| 56905 | +){ | |
| 56896 | 56906 | Pager * const pDestPager = sqlite3BtreePager(p->pDest); |
| 56897 | 56907 | const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); |
| 56898 | 56908 | int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); |
| 56899 | 56909 | const int nCopy = MIN(nSrcPgsz, nDestPgsz); |
| 56900 | 56910 | const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; |
| @@ -56963,10 +56973,13 @@ | ||
| 56963 | 56973 | ** cached parse of the page). MemPage.isInit is marked |
| 56964 | 56974 | ** "MUST BE FIRST" for this purpose. |
| 56965 | 56975 | */ |
| 56966 | 56976 | memcpy(zOut, zIn, nCopy); |
| 56967 | 56977 | ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; |
| 56978 | + if( iOff==0 && bUpdate==0 ){ | |
| 56979 | + sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); | |
| 56980 | + } | |
| 56968 | 56981 | } |
| 56969 | 56982 | sqlite3PagerUnref(pDestPg); |
| 56970 | 56983 | } |
| 56971 | 56984 | |
| 56972 | 56985 | return rc; |
| @@ -57069,11 +57082,11 @@ | ||
| 57069 | 57082 | const Pgno iSrcPg = p->iNext; /* Source page number */ |
| 57070 | 57083 | if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ |
| 57071 | 57084 | DbPage *pSrcPg; /* Source page object */ |
| 57072 | 57085 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); |
| 57073 | 57086 | if( rc==SQLITE_OK ){ |
| 57074 | - rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg)); | |
| 57087 | + rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); | |
| 57075 | 57088 | sqlite3PagerUnref(pSrcPg); |
| 57076 | 57089 | } |
| 57077 | 57090 | } |
| 57078 | 57091 | p->iNext++; |
| 57079 | 57092 | } |
| @@ -57317,11 +57330,11 @@ | ||
| 57317 | 57330 | ** the new data into the backup. |
| 57318 | 57331 | */ |
| 57319 | 57332 | int rc; |
| 57320 | 57333 | assert( p->pDestDb ); |
| 57321 | 57334 | sqlite3_mutex_enter(p->pDestDb->mutex); |
| 57322 | - rc = backupOnePage(p, iPage, aData); | |
| 57335 | + rc = backupOnePage(p, iPage, aData, 1); | |
| 57323 | 57336 | sqlite3_mutex_leave(p->pDestDb->mutex); |
| 57324 | 57337 | assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); |
| 57325 | 57338 | if( rc!=SQLITE_OK ){ |
| 57326 | 57339 | p->rc = rc; |
| 57327 | 57340 | } |
| @@ -59434,26 +59447,22 @@ | ||
| 59434 | 59447 | assert( pKeyInfo->aSortOrder!=0 ); |
| 59435 | 59448 | sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); |
| 59436 | 59449 | i = sqlite3Strlen30(zTemp); |
| 59437 | 59450 | for(j=0; j<pKeyInfo->nField; j++){ |
| 59438 | 59451 | CollSeq *pColl = pKeyInfo->aColl[j]; |
| 59439 | - if( pColl ){ | |
| 59440 | - int n = sqlite3Strlen30(pColl->zName); | |
| 59441 | - if( i+n>nTemp-6 ){ | |
| 59442 | - memcpy(&zTemp[i],",...",4); | |
| 59443 | - break; | |
| 59444 | - } | |
| 59445 | - zTemp[i++] = ','; | |
| 59446 | - if( pKeyInfo->aSortOrder[j] ){ | |
| 59447 | - zTemp[i++] = '-'; | |
| 59448 | - } | |
| 59449 | - memcpy(&zTemp[i], pColl->zName,n+1); | |
| 59450 | - i += n; | |
| 59451 | - }else if( i+4<nTemp-6 ){ | |
| 59452 | - memcpy(&zTemp[i],",nil",4); | |
| 59453 | - i += 4; | |
| 59454 | - } | |
| 59452 | + const char *zColl = pColl ? pColl->zName : "nil"; | |
| 59453 | + int n = sqlite3Strlen30(zColl); | |
| 59454 | + if( i+n>nTemp-6 ){ | |
| 59455 | + memcpy(&zTemp[i],",...",4); | |
| 59456 | + break; | |
| 59457 | + } | |
| 59458 | + zTemp[i++] = ','; | |
| 59459 | + if( pKeyInfo->aSortOrder[j] ){ | |
| 59460 | + zTemp[i++] = '-'; | |
| 59461 | + } | |
| 59462 | + memcpy(&zTemp[i], zColl, n+1); | |
| 59463 | + i += n; | |
| 59455 | 59464 | } |
| 59456 | 59465 | zTemp[i++] = ')'; |
| 59457 | 59466 | zTemp[i] = 0; |
| 59458 | 59467 | assert( i<nTemp ); |
| 59459 | 59468 | break; |
| @@ -63839,11 +63848,13 @@ | ||
| 63839 | 63848 | #ifdef SQLITE_DEBUG |
| 63840 | 63849 | /* |
| 63841 | 63850 | ** Print the value of a register for tracing purposes: |
| 63842 | 63851 | */ |
| 63843 | 63852 | static void memTracePrint(FILE *out, Mem *p){ |
| 63844 | - if( p->flags & MEM_Null ){ | |
| 63853 | + if( p->flags & MEM_Invalid ){ | |
| 63854 | + fprintf(out, " undefined"); | |
| 63855 | + }else if( p->flags & MEM_Null ){ | |
| 63845 | 63856 | fprintf(out, " NULL"); |
| 63846 | 63857 | }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ |
| 63847 | 63858 | fprintf(out, " si:%lld", p->u.i); |
| 63848 | 63859 | }else if( p->flags & MEM_Int ){ |
| 63849 | 63860 | fprintf(out, " i:%lld", p->u.i); |
| @@ -64112,10 +64123,11 @@ | ||
| 64112 | 64123 | } af; |
| 64113 | 64124 | struct OP_Concat_stack_vars { |
| 64114 | 64125 | i64 nByte; |
| 64115 | 64126 | } ag; |
| 64116 | 64127 | struct OP_Remainder_stack_vars { |
| 64128 | + char bIntint; /* Started out as two integer operands */ | |
| 64117 | 64129 | int flags; /* Combined MEM_* flags from both inputs */ |
| 64118 | 64130 | i64 iA; /* Integer value of left operand */ |
| 64119 | 64131 | i64 iB; /* Integer value of right operand */ |
| 64120 | 64132 | double rA; /* Real value of left operand */ |
| 64121 | 64133 | double rB; /* Real value of right operand */ |
| @@ -65021,10 +65033,13 @@ | ||
| 65021 | 65033 | pOut = &aMem[pOp->p2]; |
| 65022 | 65034 | assert( pOut!=pIn1 ); |
| 65023 | 65035 | while( 1 ){ |
| 65024 | 65036 | sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); |
| 65025 | 65037 | Deephemeralize(pOut); |
| 65038 | +#ifdef SQLITE_DEBUG | |
| 65039 | + pOut->pScopyFrom = 0; | |
| 65040 | +#endif | |
| 65026 | 65041 | REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut); |
| 65027 | 65042 | if( (u.ae.n--)==0 ) break; |
| 65028 | 65043 | pOut++; |
| 65029 | 65044 | pIn1++; |
| 65030 | 65045 | } |
| @@ -65214,10 +65229,11 @@ | ||
| 65214 | 65229 | case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ |
| 65215 | 65230 | case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ |
| 65216 | 65231 | case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ |
| 65217 | 65232 | case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ |
| 65218 | 65233 | #if 0 /* local variables moved into u.ah */ |
| 65234 | + char bIntint; /* Started out as two integer operands */ | |
| 65219 | 65235 | int flags; /* Combined MEM_* flags from both inputs */ |
| 65220 | 65236 | i64 iA; /* Integer value of left operand */ |
| 65221 | 65237 | i64 iB; /* Integer value of right operand */ |
| 65222 | 65238 | double rA; /* Real value of left operand */ |
| 65223 | 65239 | double rB; /* Real value of right operand */ |
| @@ -65231,10 +65247,11 @@ | ||
| 65231 | 65247 | u.ah.flags = pIn1->flags | pIn2->flags; |
| 65232 | 65248 | if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; |
| 65233 | 65249 | if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ |
| 65234 | 65250 | u.ah.iA = pIn1->u.i; |
| 65235 | 65251 | u.ah.iB = pIn2->u.i; |
| 65252 | + u.ah.bIntint = 1; | |
| 65236 | 65253 | switch( pOp->opcode ){ |
| 65237 | 65254 | case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65238 | 65255 | case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65239 | 65256 | case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65240 | 65257 | case OP_Divide: { |
| @@ -65251,10 +65268,11 @@ | ||
| 65251 | 65268 | } |
| 65252 | 65269 | } |
| 65253 | 65270 | pOut->u.i = u.ah.iB; |
| 65254 | 65271 | MemSetTypeFlag(pOut, MEM_Int); |
| 65255 | 65272 | }else{ |
| 65273 | + u.ah.bIntint = 0; | |
| 65256 | 65274 | fp_math: |
| 65257 | 65275 | u.ah.rA = sqlite3VdbeRealValue(pIn1); |
| 65258 | 65276 | u.ah.rB = sqlite3VdbeRealValue(pIn2); |
| 65259 | 65277 | switch( pOp->opcode ){ |
| 65260 | 65278 | case OP_Add: u.ah.rB += u.ah.rA; break; |
| @@ -65282,11 +65300,11 @@ | ||
| 65282 | 65300 | if( sqlite3IsNaN(u.ah.rB) ){ |
| 65283 | 65301 | goto arithmetic_result_is_null; |
| 65284 | 65302 | } |
| 65285 | 65303 | pOut->r = u.ah.rB; |
| 65286 | 65304 | MemSetTypeFlag(pOut, MEM_Real); |
| 65287 | - if( (u.ah.flags & MEM_Real)==0 ){ | |
| 65305 | + if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){ | |
| 65288 | 65306 | sqlite3VdbeIntegerAffinity(pOut); |
| 65289 | 65307 | } |
| 65290 | 65308 | #endif |
| 65291 | 65309 | } |
| 65292 | 65310 | break; |
| @@ -65843,26 +65861,31 @@ | ||
| 65843 | 65861 | /* Opcode: Permutation * * * P4 * |
| 65844 | 65862 | ** |
| 65845 | 65863 | ** Set the permutation used by the OP_Compare operator to be the array |
| 65846 | 65864 | ** of integers in P4. |
| 65847 | 65865 | ** |
| 65848 | -** The permutation is only valid until the next OP_Permutation, OP_Compare, | |
| 65849 | -** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur | |
| 65850 | -** immediately prior to the OP_Compare. | |
| 65866 | +** The permutation is only valid until the next OP_Compare that has | |
| 65867 | +** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should | |
| 65868 | +** occur immediately prior to the OP_Compare. | |
| 65851 | 65869 | */ |
| 65852 | 65870 | case OP_Permutation: { |
| 65853 | 65871 | assert( pOp->p4type==P4_INTARRAY ); |
| 65854 | 65872 | assert( pOp->p4.ai ); |
| 65855 | 65873 | aPermute = pOp->p4.ai; |
| 65856 | 65874 | break; |
| 65857 | 65875 | } |
| 65858 | 65876 | |
| 65859 | -/* Opcode: Compare P1 P2 P3 P4 * | |
| 65877 | +/* Opcode: Compare P1 P2 P3 P4 P5 | |
| 65860 | 65878 | ** |
| 65861 | 65879 | ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this |
| 65862 | 65880 | ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of |
| 65863 | 65881 | ** the comparison for use by the next OP_Jump instruct. |
| 65882 | +** | |
| 65883 | +** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is | |
| 65884 | +** determined by the most recent OP_Permutation operator. If the | |
| 65885 | +** OPFLAG_PERMUTE bit is clear, then register are compared in sequential | |
| 65886 | +** order. | |
| 65864 | 65887 | ** |
| 65865 | 65888 | ** P4 is a KeyInfo structure that defines collating sequences and sort |
| 65866 | 65889 | ** orders for the comparison. The permutation applies to registers |
| 65867 | 65890 | ** only. The KeyInfo elements are used sequentially. |
| 65868 | 65891 | ** |
| @@ -65880,10 +65903,11 @@ | ||
| 65880 | 65903 | int idx; |
| 65881 | 65904 | CollSeq *pColl; /* Collating sequence to use on this term */ |
| 65882 | 65905 | int bRev; /* True for DESCENDING sort order */ |
| 65883 | 65906 | #endif /* local variables moved into u.al */ |
| 65884 | 65907 | |
| 65908 | + if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0; | |
| 65885 | 65909 | u.al.n = pOp->p3; |
| 65886 | 65910 | u.al.pKeyInfo = pOp->p4.pKeyInfo; |
| 65887 | 65911 | assert( u.al.n>0 ); |
| 65888 | 65912 | assert( u.al.pKeyInfo!=0 ); |
| 65889 | 65913 | u.al.p1 = pOp->p1; |
| @@ -66025,12 +66049,10 @@ | ||
| 66025 | 66049 | |
| 66026 | 66050 | /* Opcode: Once P1 P2 * * * |
| 66027 | 66051 | ** |
| 66028 | 66052 | ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, |
| 66029 | 66053 | ** set the flag and fall through to the next instruction. |
| 66030 | -** | |
| 66031 | -** See also: JumpOnce | |
| 66032 | 66054 | */ |
| 66033 | 66055 | case OP_Once: { /* jump */ |
| 66034 | 66056 | assert( pOp->p1<p->nOnceFlag ); |
| 66035 | 66057 | if( p->aOnceFlag[pOp->p1] ){ |
| 66036 | 66058 | pc = pOp->p2-1; |
| @@ -71902,10 +71924,18 @@ | ||
| 71902 | 71924 | p->pReal = pReal; |
| 71903 | 71925 | if( p->iSize>0 ){ |
| 71904 | 71926 | assert(p->iSize<=p->nBuf); |
| 71905 | 71927 | rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); |
| 71906 | 71928 | } |
| 71929 | + if( rc!=SQLITE_OK ){ | |
| 71930 | + /* If an error occurred while writing to the file, close it before | |
| 71931 | + ** returning. This way, SQLite uses the in-memory journal data to | |
| 71932 | + ** roll back changes made to the internal page-cache before this | |
| 71933 | + ** function was called. */ | |
| 71934 | + sqlite3OsClose(pReal); | |
| 71935 | + p->pReal = 0; | |
| 71936 | + } | |
| 71907 | 71937 | } |
| 71908 | 71938 | } |
| 71909 | 71939 | return rc; |
| 71910 | 71940 | } |
| 71911 | 71941 | |
| @@ -72565,10 +72595,19 @@ | ||
| 72565 | 72595 | ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 |
| 72566 | 72596 | ** |
| 72567 | 72597 | ** The result of random()%5 in the GROUP BY clause is probably different |
| 72568 | 72598 | ** from the result in the result-set. We might fix this someday. Or |
| 72569 | 72599 | ** then again, we might not... |
| 72600 | +** | |
| 72601 | +** If the reference is followed by a COLLATE operator, then make sure | |
| 72602 | +** the COLLATE operator is preserved. For example: | |
| 72603 | +** | |
| 72604 | +** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase; | |
| 72605 | +** | |
| 72606 | +** Should be transformed into: | |
| 72607 | +** | |
| 72608 | +** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; | |
| 72570 | 72609 | ** |
| 72571 | 72610 | ** The nSubquery parameter specifies how many levels of subquery the |
| 72572 | 72611 | ** alias is removed from the original expression. The usually value is |
| 72573 | 72612 | ** zero but it might be more if the alias is contained within a subquery |
| 72574 | 72613 | ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION |
| @@ -72589,45 +72628,40 @@ | ||
| 72589 | 72628 | assert( iCol>=0 && iCol<pEList->nExpr ); |
| 72590 | 72629 | pOrig = pEList->a[iCol].pExpr; |
| 72591 | 72630 | assert( pOrig!=0 ); |
| 72592 | 72631 | assert( pOrig->flags & EP_Resolved ); |
| 72593 | 72632 | db = pParse->db; |
| 72633 | + pDup = sqlite3ExprDup(db, pOrig, 0); | |
| 72634 | + if( pDup==0 ) return; | |
| 72594 | 72635 | if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ |
| 72595 | - pDup = sqlite3ExprDup(db, pOrig, 0); | |
| 72596 | 72636 | incrAggFunctionDepth(pDup, nSubquery); |
| 72597 | 72637 | pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); |
| 72598 | 72638 | if( pDup==0 ) return; |
| 72599 | 72639 | if( pEList->a[iCol].iAlias==0 ){ |
| 72600 | 72640 | pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); |
| 72601 | 72641 | } |
| 72602 | 72642 | pDup->iTable = pEList->a[iCol].iAlias; |
| 72603 | - }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){ | |
| 72604 | - pDup = sqlite3ExprDup(db, pOrig, 0); | |
| 72605 | - if( pDup==0 ) return; | |
| 72606 | - }else{ | |
| 72607 | - char *zToken = pOrig->u.zToken; | |
| 72608 | - assert( zToken!=0 ); | |
| 72609 | - pOrig->u.zToken = 0; | |
| 72610 | - pDup = sqlite3ExprDup(db, pOrig, 0); | |
| 72611 | - pOrig->u.zToken = zToken; | |
| 72612 | - if( pDup==0 ) return; | |
| 72613 | - assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 ); | |
| 72614 | - pDup->flags2 |= EP2_MallocedToken; | |
| 72615 | - pDup->u.zToken = sqlite3DbStrDup(db, zToken); | |
| 72616 | - } | |
| 72617 | - if( pExpr->flags & EP_ExpCollate ){ | |
| 72618 | - pDup->pColl = pExpr->pColl; | |
| 72619 | - pDup->flags |= EP_ExpCollate; | |
| 72643 | + } | |
| 72644 | + if( pExpr->op==TK_COLLATE ){ | |
| 72645 | + pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); | |
| 72620 | 72646 | } |
| 72621 | 72647 | |
| 72622 | 72648 | /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This |
| 72623 | 72649 | ** prevents ExprDelete() from deleting the Expr structure itself, |
| 72624 | 72650 | ** allowing it to be repopulated by the memcpy() on the following line. |
| 72651 | + ** The pExpr->u.zToken might point into memory that will be freed by the | |
| 72652 | + ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to | |
| 72653 | + ** make a copy of the token before doing the sqlite3DbFree(). | |
| 72625 | 72654 | */ |
| 72626 | 72655 | ExprSetProperty(pExpr, EP_Static); |
| 72627 | 72656 | sqlite3ExprDelete(db, pExpr); |
| 72628 | 72657 | memcpy(pExpr, pDup, sizeof(*pExpr)); |
| 72658 | + if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ | |
| 72659 | + assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); | |
| 72660 | + pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); | |
| 72661 | + pExpr->flags2 |= EP2_MallocedToken; | |
| 72662 | + } | |
| 72629 | 72663 | sqlite3DbFree(db, pDup); |
| 72630 | 72664 | } |
| 72631 | 72665 | |
| 72632 | 72666 | |
| 72633 | 72667 | /* |
| @@ -72644,10 +72678,39 @@ | ||
| 72644 | 72678 | } |
| 72645 | 72679 | } |
| 72646 | 72680 | return 0; |
| 72647 | 72681 | } |
| 72648 | 72682 | |
| 72683 | +/* | |
| 72684 | +** Subqueries stores the original database, table and column names for their | |
| 72685 | +** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN". | |
| 72686 | +** Check to see if the zSpan given to this routine matches the zDb, zTab, | |
| 72687 | +** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will | |
| 72688 | +** match anything. | |
| 72689 | +*/ | |
| 72690 | +SQLITE_PRIVATE int sqlite3MatchSpanName( | |
| 72691 | + const char *zSpan, | |
| 72692 | + const char *zCol, | |
| 72693 | + const char *zTab, | |
| 72694 | + const char *zDb | |
| 72695 | +){ | |
| 72696 | + int n; | |
| 72697 | + for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} | |
| 72698 | + if( zDb && sqlite3StrNICmp(zSpan, zDb, n)!=0 ){ | |
| 72699 | + return 0; | |
| 72700 | + } | |
| 72701 | + zSpan += n+1; | |
| 72702 | + for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} | |
| 72703 | + if( zTab && sqlite3StrNICmp(zSpan, zTab, n)!=0 ){ | |
| 72704 | + return 0; | |
| 72705 | + } | |
| 72706 | + zSpan += n+1; | |
| 72707 | + if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ | |
| 72708 | + return 0; | |
| 72709 | + } | |
| 72710 | + return 1; | |
| 72711 | +} | |
| 72649 | 72712 | |
| 72650 | 72713 | /* |
| 72651 | 72714 | ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up |
| 72652 | 72715 | ** that name in the set of source tables in pSrcList and make the pExpr |
| 72653 | 72716 | ** expression node refer back to that source column. The following changes |
| @@ -72699,44 +72762,63 @@ | ||
| 72699 | 72762 | |
| 72700 | 72763 | /* Initialize the node to no-match */ |
| 72701 | 72764 | pExpr->iTable = -1; |
| 72702 | 72765 | pExpr->pTab = 0; |
| 72703 | 72766 | ExprSetIrreducible(pExpr); |
| 72767 | + | |
| 72768 | + /* Translate the schema name in zDb into a pointer to the corresponding | |
| 72769 | + ** schema. If not found, pSchema will remain NULL and nothing will match | |
| 72770 | + ** resulting in an appropriate error message toward the end of this routine | |
| 72771 | + */ | |
| 72772 | + if( zDb ){ | |
| 72773 | + for(i=0; i<db->nDb; i++){ | |
| 72774 | + assert( db->aDb[i].zName ); | |
| 72775 | + if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){ | |
| 72776 | + pSchema = db->aDb[i].pSchema; | |
| 72777 | + break; | |
| 72778 | + } | |
| 72779 | + } | |
| 72780 | + } | |
| 72704 | 72781 | |
| 72705 | 72782 | /* Start at the inner-most context and move outward until a match is found */ |
| 72706 | 72783 | while( pNC && cnt==0 ){ |
| 72707 | 72784 | ExprList *pEList; |
| 72708 | 72785 | SrcList *pSrcList = pNC->pSrcList; |
| 72709 | 72786 | |
| 72710 | 72787 | if( pSrcList ){ |
| 72711 | 72788 | for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ |
| 72712 | 72789 | Table *pTab; |
| 72713 | - int iDb; | |
| 72714 | 72790 | Column *pCol; |
| 72715 | 72791 | |
| 72716 | 72792 | pTab = pItem->pTab; |
| 72717 | 72793 | assert( pTab!=0 && pTab->zName!=0 ); |
| 72718 | - iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | |
| 72719 | 72794 | assert( pTab->nCol>0 ); |
| 72795 | + if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ | |
| 72796 | + ExprList *pEList = pItem->pSelect->pEList; | |
| 72797 | + int hit = 0; | |
| 72798 | + for(j=0; j<pEList->nExpr; j++){ | |
| 72799 | + if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){ | |
| 72800 | + cnt++; | |
| 72801 | + cntTab = 2; | |
| 72802 | + pMatch = pItem; | |
| 72803 | + pExpr->iColumn = j; | |
| 72804 | + hit = 1; | |
| 72805 | + } | |
| 72806 | + } | |
| 72807 | + if( hit || zTab==0 ) continue; | |
| 72808 | + } | |
| 72809 | + if( zDb && pTab->pSchema!=pSchema ){ | |
| 72810 | + continue; | |
| 72811 | + } | |
| 72720 | 72812 | if( zTab ){ |
| 72721 | - if( pItem->zAlias ){ | |
| 72722 | - char *zTabName = pItem->zAlias; | |
| 72723 | - if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; | |
| 72724 | - }else{ | |
| 72725 | - char *zTabName = pTab->zName; | |
| 72726 | - if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){ | |
| 72727 | - continue; | |
| 72728 | - } | |
| 72729 | - if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ | |
| 72730 | - continue; | |
| 72731 | - } | |
| 72813 | + const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; | |
| 72814 | + assert( zTabName!=0 ); | |
| 72815 | + if( sqlite3StrICmp(zTabName, zTab)!=0 ){ | |
| 72816 | + continue; | |
| 72732 | 72817 | } |
| 72733 | 72818 | } |
| 72734 | 72819 | if( 0==(cntTab++) ){ |
| 72735 | - pExpr->iTable = pItem->iCursor; | |
| 72736 | - pExpr->pTab = pTab; | |
| 72737 | - pSchema = pTab->pSchema; | |
| 72738 | 72820 | pMatch = pItem; |
| 72739 | 72821 | } |
| 72740 | 72822 | for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ |
| 72741 | 72823 | if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ |
| 72742 | 72824 | /* If there has been exactly one prior match and this match |
| @@ -72746,21 +72828,23 @@ | ||
| 72746 | 72828 | if( cnt==1 ){ |
| 72747 | 72829 | if( pItem->jointype & JT_NATURAL ) continue; |
| 72748 | 72830 | if( nameInUsingClause(pItem->pUsing, zCol) ) continue; |
| 72749 | 72831 | } |
| 72750 | 72832 | cnt++; |
| 72751 | - pExpr->iTable = pItem->iCursor; | |
| 72752 | - pExpr->pTab = pTab; | |
| 72753 | 72833 | pMatch = pItem; |
| 72754 | - pSchema = pTab->pSchema; | |
| 72755 | 72834 | /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ |
| 72756 | 72835 | pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; |
| 72757 | 72836 | break; |
| 72758 | 72837 | } |
| 72759 | 72838 | } |
| 72760 | 72839 | } |
| 72761 | - } | |
| 72840 | + if( pMatch ){ | |
| 72841 | + pExpr->iTable = pMatch->iCursor; | |
| 72842 | + pExpr->pTab = pMatch->pTab; | |
| 72843 | + pSchema = pExpr->pTab->pSchema; | |
| 72844 | + } | |
| 72845 | + } /* if( pSrcList ) */ | |
| 72762 | 72846 | |
| 72763 | 72847 | #ifndef SQLITE_OMIT_TRIGGER |
| 72764 | 72848 | /* If we have not already resolved the name, then maybe |
| 72765 | 72849 | ** it is a new.* or old.* trigger argument reference |
| 72766 | 72850 | */ |
| @@ -73055,42 +73139,43 @@ | ||
| 73055 | 73139 | int wrong_num_args = 0; /* True if wrong number of arguments */ |
| 73056 | 73140 | int is_agg = 0; /* True if is an aggregate function */ |
| 73057 | 73141 | int auth; /* Authorization to use the function */ |
| 73058 | 73142 | int nId; /* Number of characters in function name */ |
| 73059 | 73143 | const char *zId; /* The function name. */ |
| 73060 | - FuncDef *pDef; /* Information about the function */ | |
| 73061 | 73144 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 73062 | 73145 | |
| 73063 | 73146 | testcase( pExpr->op==TK_CONST_FUNC ); |
| 73064 | 73147 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 73065 | 73148 | zId = pExpr->u.zToken; |
| 73066 | 73149 | nId = sqlite3Strlen30(zId); |
| 73067 | - pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); | |
| 73068 | - if( pDef==0 ){ | |
| 73069 | - pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); | |
| 73070 | - if( pDef==0 ){ | |
| 73071 | - no_such_func = 1; | |
| 73072 | - }else{ | |
| 73073 | - wrong_num_args = 1; | |
| 73074 | - } | |
| 73075 | - }else{ | |
| 73076 | - is_agg = pDef->xFunc==0; | |
| 73077 | - } | |
| 73078 | -#ifndef SQLITE_OMIT_AUTHORIZATION | |
| 73079 | - if( pDef ){ | |
| 73080 | - auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); | |
| 73081 | - if( auth!=SQLITE_OK ){ | |
| 73082 | - if( auth==SQLITE_DENY ){ | |
| 73083 | - sqlite3ErrorMsg(pParse, "not authorized to use function: %s", | |
| 73084 | - pDef->zName); | |
| 73085 | - pNC->nErr++; | |
| 73086 | - } | |
| 73087 | - pExpr->op = TK_NULL; | |
| 73088 | - return WRC_Prune; | |
| 73089 | - } | |
| 73090 | - } | |
| 73091 | -#endif | |
| 73150 | + if( pParse->db->init.busy==0 ){ | |
| 73151 | + FuncDef *pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); | |
| 73152 | + if( pDef==0 ){ | |
| 73153 | + pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); | |
| 73154 | + if( pDef==0 ){ | |
| 73155 | + no_such_func = 1; | |
| 73156 | + }else{ | |
| 73157 | + wrong_num_args = 1; | |
| 73158 | + } | |
| 73159 | + }else{ | |
| 73160 | + is_agg = pDef->xFunc==0; | |
| 73161 | + } | |
| 73162 | +#ifndef SQLITE_OMIT_AUTHORIZATION | |
| 73163 | + if( pDef ){ | |
| 73164 | + auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); | |
| 73165 | + if( auth!=SQLITE_OK ){ | |
| 73166 | + if( auth==SQLITE_DENY ){ | |
| 73167 | + sqlite3ErrorMsg(pParse, "not authorized to use function: %s", | |
| 73168 | + pDef->zName); | |
| 73169 | + pNC->nErr++; | |
| 73170 | + } | |
| 73171 | + pExpr->op = TK_NULL; | |
| 73172 | + return WRC_Prune; | |
| 73173 | + } | |
| 73174 | + } | |
| 73175 | +#endif | |
| 73176 | + } | |
| 73092 | 73177 | if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ |
| 73093 | 73178 | sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); |
| 73094 | 73179 | pNC->nErr++; |
| 73095 | 73180 | is_agg = 0; |
| 73096 | 73181 | }else if( no_such_func ){ |
| @@ -73310,11 +73395,11 @@ | ||
| 73310 | 73395 | assert( pEList!=0 ); |
| 73311 | 73396 | for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ |
| 73312 | 73397 | int iCol = -1; |
| 73313 | 73398 | Expr *pE, *pDup; |
| 73314 | 73399 | if( pItem->done ) continue; |
| 73315 | - pE = pItem->pExpr; | |
| 73400 | + pE = sqlite3ExprSkipCollate(pItem->pExpr); | |
| 73316 | 73401 | if( sqlite3ExprIsInteger(pE, &iCol) ){ |
| 73317 | 73402 | if( iCol<=0 || iCol>pEList->nExpr ){ |
| 73318 | 73403 | resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); |
| 73319 | 73404 | return 1; |
| 73320 | 73405 | } |
| @@ -73328,18 +73413,24 @@ | ||
| 73328 | 73413 | } |
| 73329 | 73414 | sqlite3ExprDelete(db, pDup); |
| 73330 | 73415 | } |
| 73331 | 73416 | } |
| 73332 | 73417 | if( iCol>0 ){ |
| 73333 | - CollSeq *pColl = pE->pColl; | |
| 73334 | - int flags = pE->flags & EP_ExpCollate; | |
| 73418 | + /* Convert the ORDER BY term into an integer column number iCol, | |
| 73419 | + ** taking care to preserve the COLLATE clause if it exists */ | |
| 73420 | + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); | |
| 73421 | + if( pNew==0 ) return 1; | |
| 73422 | + pNew->flags |= EP_IntValue; | |
| 73423 | + pNew->u.iValue = iCol; | |
| 73424 | + if( pItem->pExpr==pE ){ | |
| 73425 | + pItem->pExpr = pNew; | |
| 73426 | + }else{ | |
| 73427 | + assert( pItem->pExpr->op==TK_COLLATE ); | |
| 73428 | + assert( pItem->pExpr->pLeft==pE ); | |
| 73429 | + pItem->pExpr->pLeft = pNew; | |
| 73430 | + } | |
| 73335 | 73431 | sqlite3ExprDelete(db, pE); |
| 73336 | - pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0); | |
| 73337 | - if( pE==0 ) return 1; | |
| 73338 | - pE->pColl = pColl; | |
| 73339 | - pE->flags |= EP_IntValue | flags; | |
| 73340 | - pE->u.iValue = iCol; | |
| 73341 | 73432 | pItem->iOrderByCol = (u16)iCol; |
| 73342 | 73433 | pItem->done = 1; |
| 73343 | 73434 | }else{ |
| 73344 | 73435 | moreToDo = 1; |
| 73345 | 73436 | } |
| @@ -73440,15 +73531,15 @@ | ||
| 73440 | 73531 | ** sqlite3ResolveOrderGroupBy() will convert the expression to a |
| 73441 | 73532 | ** copy of the iCol-th result-set expression. */ |
| 73442 | 73533 | pItem->iOrderByCol = (u16)iCol; |
| 73443 | 73534 | continue; |
| 73444 | 73535 | } |
| 73445 | - if( sqlite3ExprIsInteger(pE, &iCol) ){ | |
| 73536 | + if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){ | |
| 73446 | 73537 | /* The ORDER BY term is an integer constant. Again, set the column |
| 73447 | 73538 | ** number so that sqlite3ResolveOrderGroupBy() will convert the |
| 73448 | 73539 | ** order-by term to a copy of the result-set expression */ |
| 73449 | - if( iCol<1 ){ | |
| 73540 | + if( iCol<1 || iCol>0xffff ){ | |
| 73450 | 73541 | resolveOutOfRangeError(pParse, zType, i+1, nResult); |
| 73451 | 73542 | return 1; |
| 73452 | 73543 | } |
| 73453 | 73544 | pItem->iOrderByCol = (u16)iCol; |
| 73454 | 73545 | continue; |
| @@ -73521,27 +73612,10 @@ | ||
| 73521 | 73612 | if( sqlite3ResolveExprNames(&sNC, p->pLimit) || |
| 73522 | 73613 | sqlite3ResolveExprNames(&sNC, p->pOffset) ){ |
| 73523 | 73614 | return WRC_Abort; |
| 73524 | 73615 | } |
| 73525 | 73616 | |
| 73526 | - /* Set up the local name-context to pass to sqlite3ResolveExprNames() to | |
| 73527 | - ** resolve the result-set expression list. | |
| 73528 | - */ | |
| 73529 | - sNC.ncFlags = NC_AllowAgg; | |
| 73530 | - sNC.pSrcList = p->pSrc; | |
| 73531 | - sNC.pNext = pOuterNC; | |
| 73532 | - | |
| 73533 | - /* Resolve names in the result set. */ | |
| 73534 | - pEList = p->pEList; | |
| 73535 | - assert( pEList!=0 ); | |
| 73536 | - for(i=0; i<pEList->nExpr; i++){ | |
| 73537 | - Expr *pX = pEList->a[i].pExpr; | |
| 73538 | - if( sqlite3ResolveExprNames(&sNC, pX) ){ | |
| 73539 | - return WRC_Abort; | |
| 73540 | - } | |
| 73541 | - } | |
| 73542 | - | |
| 73543 | 73617 | /* Recursively resolve names in all subqueries |
| 73544 | 73618 | */ |
| 73545 | 73619 | for(i=0; i<p->pSrc->nSrc; i++){ |
| 73546 | 73620 | struct SrcList_item *pItem = &p->pSrc->a[i]; |
| 73547 | 73621 | if( pItem->pSelect ){ |
| @@ -73564,10 +73638,27 @@ | ||
| 73564 | 73638 | for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; |
| 73565 | 73639 | assert( pItem->isCorrelated==0 && nRef<=0 ); |
| 73566 | 73640 | pItem->isCorrelated = (nRef!=0); |
| 73567 | 73641 | } |
| 73568 | 73642 | } |
| 73643 | + | |
| 73644 | + /* Set up the local name-context to pass to sqlite3ResolveExprNames() to | |
| 73645 | + ** resolve the result-set expression list. | |
| 73646 | + */ | |
| 73647 | + sNC.ncFlags = NC_AllowAgg; | |
| 73648 | + sNC.pSrcList = p->pSrc; | |
| 73649 | + sNC.pNext = pOuterNC; | |
| 73650 | + | |
| 73651 | + /* Resolve names in the result set. */ | |
| 73652 | + pEList = p->pEList; | |
| 73653 | + assert( pEList!=0 ); | |
| 73654 | + for(i=0; i<pEList->nExpr; i++){ | |
| 73655 | + Expr *pX = pEList->a[i].pExpr; | |
| 73656 | + if( sqlite3ResolveExprNames(&sNC, pX) ){ | |
| 73657 | + return WRC_Abort; | |
| 73658 | + } | |
| 73659 | + } | |
| 73569 | 73660 | |
| 73570 | 73661 | /* If there are no aggregate functions in the result-set, and no GROUP BY |
| 73571 | 73662 | ** expression, do not allow aggregates in any of the other expressions. |
| 73572 | 73663 | */ |
| 73573 | 73664 | assert( (p->selFlags & SF_Aggregate)==0 ); |
| @@ -73798,11 +73889,13 @@ | ||
| 73798 | 73889 | ** SELECT * FROM t1 WHERE a; |
| 73799 | 73890 | ** SELECT a AS b FROM t1 WHERE b; |
| 73800 | 73891 | ** SELECT * FROM t1 WHERE (select a from t1); |
| 73801 | 73892 | */ |
| 73802 | 73893 | SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ |
| 73803 | - int op = pExpr->op; | |
| 73894 | + int op; | |
| 73895 | + pExpr = sqlite3ExprSkipCollate(pExpr); | |
| 73896 | + op = pExpr->op; | |
| 73804 | 73897 | if( op==TK_SELECT ){ |
| 73805 | 73898 | assert( pExpr->flags&EP_xIsSelect ); |
| 73806 | 73899 | return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); |
| 73807 | 73900 | } |
| 73808 | 73901 | #ifndef SQLITE_OMIT_CAST |
| @@ -73823,70 +73916,98 @@ | ||
| 73823 | 73916 | } |
| 73824 | 73917 | return pExpr->affinity; |
| 73825 | 73918 | } |
| 73826 | 73919 | |
| 73827 | 73920 | /* |
| 73828 | -** Set the explicit collating sequence for an expression to the | |
| 73829 | -** collating sequence supplied in the second argument. | |
| 73830 | -*/ | |
| 73831 | -SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){ | |
| 73832 | - if( pExpr && pColl ){ | |
| 73833 | - pExpr->pColl = pColl; | |
| 73834 | - pExpr->flags |= EP_ExpCollate; | |
| 73835 | - } | |
| 73836 | - return pExpr; | |
| 73837 | -} | |
| 73838 | - | |
| 73839 | -/* | |
| 73840 | -** Set the collating sequence for expression pExpr to be the collating | |
| 73841 | -** sequence named by pToken. Return a pointer to the revised expression. | |
| 73842 | -** The collating sequence is marked as "explicit" using the EP_ExpCollate | |
| 73843 | -** flag. An explicit collating sequence will override implicit | |
| 73844 | -** collating sequences. | |
| 73845 | -*/ | |
| 73846 | -SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){ | |
| 73847 | - char *zColl = 0; /* Dequoted name of collation sequence */ | |
| 73848 | - CollSeq *pColl; | |
| 73849 | - sqlite3 *db = pParse->db; | |
| 73850 | - zColl = sqlite3NameFromToken(db, pCollName); | |
| 73851 | - pColl = sqlite3LocateCollSeq(pParse, zColl); | |
| 73852 | - sqlite3ExprSetColl(pExpr, pColl); | |
| 73853 | - sqlite3DbFree(db, zColl); | |
| 73854 | - return pExpr; | |
| 73855 | -} | |
| 73856 | - | |
| 73857 | -/* | |
| 73858 | -** Return the default collation sequence for the expression pExpr. If | |
| 73859 | -** there is no default collation type, return 0. | |
| 73860 | -*/ | |
| 73861 | -SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ | |
| 73862 | - CollSeq *pColl = 0; | |
| 73863 | - Expr *p = pExpr; | |
| 73864 | - while( p ){ | |
| 73865 | - int op; | |
| 73866 | - pColl = p->pColl; | |
| 73867 | - if( pColl ) break; | |
| 73868 | - op = p->op; | |
| 73869 | - if( p->pTab!=0 && ( | |
| 73870 | - op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER | |
| 73871 | - )){ | |
| 73872 | - /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally | |
| 73873 | - ** a TK_COLUMN but was previously evaluated and cached in a register */ | |
| 73874 | - const char *zColl; | |
| 73875 | - int j = p->iColumn; | |
| 73876 | - if( j>=0 ){ | |
| 73877 | - sqlite3 *db = pParse->db; | |
| 73878 | - zColl = p->pTab->aCol[j].zColl; | |
| 73879 | - pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); | |
| 73880 | - pExpr->pColl = pColl; | |
| 73881 | - } | |
| 73882 | - break; | |
| 73883 | - } | |
| 73884 | - if( op!=TK_CAST && op!=TK_UPLUS ){ | |
| 73885 | - break; | |
| 73886 | - } | |
| 73887 | - p = p->pLeft; | |
| 73921 | +** Set the collating sequence for expression pExpr to be the collating | |
| 73922 | +** sequence named by pToken. Return a pointer to a new Expr node that | |
| 73923 | +** implements the COLLATE operator. | |
| 73924 | +** | |
| 73925 | +** If a memory allocation error occurs, that fact is recorded in pParse->db | |
| 73926 | +** and the pExpr parameter is returned unchanged. | |
| 73927 | +*/ | |
| 73928 | +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){ | |
| 73929 | + if( pCollName->n>0 ){ | |
| 73930 | + Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); | |
| 73931 | + if( pNew ){ | |
| 73932 | + pNew->pLeft = pExpr; | |
| 73933 | + pNew->flags |= EP_Collate; | |
| 73934 | + pExpr = pNew; | |
| 73935 | + } | |
| 73936 | + } | |
| 73937 | + return pExpr; | |
| 73938 | +} | |
| 73939 | +SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ | |
| 73940 | + Token s; | |
| 73941 | + assert( zC!=0 ); | |
| 73942 | + s.z = zC; | |
| 73943 | + s.n = sqlite3Strlen30(s.z); | |
| 73944 | + return sqlite3ExprAddCollateToken(pParse, pExpr, &s); | |
| 73945 | +} | |
| 73946 | + | |
| 73947 | +/* | |
| 73948 | +** Skip over any TK_COLLATE and/or TK_AS operators at the root of | |
| 73949 | +** an expression. | |
| 73950 | +*/ | |
| 73951 | +SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ | |
| 73952 | + while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){ | |
| 73953 | + pExpr = pExpr->pLeft; | |
| 73954 | + } | |
| 73955 | + return pExpr; | |
| 73956 | +} | |
| 73957 | + | |
| 73958 | +/* | |
| 73959 | +** Return the collation sequence for the expression pExpr. If | |
| 73960 | +** there is no defined collating sequence, return NULL. | |
| 73961 | +** | |
| 73962 | +** The collating sequence might be determined by a COLLATE operator | |
| 73963 | +** or by the presence of a column with a defined collating sequence. | |
| 73964 | +** COLLATE operators take first precedence. Left operands take | |
| 73965 | +** precedence over right operands. | |
| 73966 | +*/ | |
| 73967 | +SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ | |
| 73968 | + sqlite3 *db = pParse->db; | |
| 73969 | + CollSeq *pColl = 0; | |
| 73970 | + Expr *p = pExpr; | |
| 73971 | + while( p ){ | |
| 73972 | + int op = p->op; | |
| 73973 | + if( op==TK_CAST || op==TK_UPLUS ){ | |
| 73974 | + p = p->pLeft; | |
| 73975 | + continue; | |
| 73976 | + } | |
| 73977 | + assert( op!=TK_REGISTER || p->op2!=TK_COLLATE ); | |
| 73978 | + if( op==TK_COLLATE ){ | |
| 73979 | + if( db->init.busy ){ | |
| 73980 | + /* Do not report errors when parsing while the schema */ | |
| 73981 | + pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0); | |
| 73982 | + }else{ | |
| 73983 | + pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); | |
| 73984 | + } | |
| 73985 | + break; | |
| 73986 | + } | |
| 73987 | + if( p->pTab!=0 | |
| 73988 | + && (op==TK_AGG_COLUMN || op==TK_COLUMN | |
| 73989 | + || op==TK_REGISTER || op==TK_TRIGGER) | |
| 73990 | + ){ | |
| 73991 | + /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally | |
| 73992 | + ** a TK_COLUMN but was previously evaluated and cached in a register */ | |
| 73993 | + int j = p->iColumn; | |
| 73994 | + if( j>=0 ){ | |
| 73995 | + const char *zColl = p->pTab->aCol[j].zColl; | |
| 73996 | + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); | |
| 73997 | + } | |
| 73998 | + break; | |
| 73999 | + } | |
| 74000 | + if( p->flags & EP_Collate ){ | |
| 74001 | + if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ | |
| 74002 | + p = p->pLeft; | |
| 74003 | + }else{ | |
| 74004 | + p = p->pRight; | |
| 74005 | + } | |
| 74006 | + }else{ | |
| 74007 | + break; | |
| 74008 | + } | |
| 73888 | 74009 | } |
| 73889 | 74010 | if( sqlite3CheckCollSeq(pParse, pColl) ){ |
| 73890 | 74011 | pColl = 0; |
| 73891 | 74012 | } |
| 73892 | 74013 | return pColl; |
| @@ -73986,16 +74107,14 @@ | ||
| 73986 | 74107 | Expr *pLeft, |
| 73987 | 74108 | Expr *pRight |
| 73988 | 74109 | ){ |
| 73989 | 74110 | CollSeq *pColl; |
| 73990 | 74111 | assert( pLeft ); |
| 73991 | - if( pLeft->flags & EP_ExpCollate ){ | |
| 73992 | - assert( pLeft->pColl ); | |
| 73993 | - pColl = pLeft->pColl; | |
| 73994 | - }else if( pRight && pRight->flags & EP_ExpCollate ){ | |
| 73995 | - assert( pRight->pColl ); | |
| 73996 | - pColl = pRight->pColl; | |
| 74112 | + if( pLeft->flags & EP_Collate ){ | |
| 74113 | + pColl = sqlite3ExprCollSeq(pParse, pLeft); | |
| 74114 | + }else if( pRight && (pRight->flags & EP_Collate)!=0 ){ | |
| 74115 | + pColl = sqlite3ExprCollSeq(pParse, pRight); | |
| 73997 | 74116 | }else{ |
| 73998 | 74117 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 73999 | 74118 | if( !pColl ){ |
| 74000 | 74119 | pColl = sqlite3ExprCollSeq(pParse, pRight); |
| 74001 | 74120 | } |
| @@ -74221,21 +74340,15 @@ | ||
| 74221 | 74340 | sqlite3ExprDelete(db, pLeft); |
| 74222 | 74341 | sqlite3ExprDelete(db, pRight); |
| 74223 | 74342 | }else{ |
| 74224 | 74343 | if( pRight ){ |
| 74225 | 74344 | pRoot->pRight = pRight; |
| 74226 | - if( pRight->flags & EP_ExpCollate ){ | |
| 74227 | - pRoot->flags |= EP_ExpCollate; | |
| 74228 | - pRoot->pColl = pRight->pColl; | |
| 74229 | - } | |
| 74345 | + pRoot->flags |= EP_Collate & pRight->flags; | |
| 74230 | 74346 | } |
| 74231 | 74347 | if( pLeft ){ |
| 74232 | 74348 | pRoot->pLeft = pLeft; |
| 74233 | - if( pLeft->flags & EP_ExpCollate ){ | |
| 74234 | - pRoot->flags |= EP_ExpCollate; | |
| 74235 | - pRoot->pColl = pLeft->pColl; | |
| 74236 | - } | |
| 74349 | + pRoot->flags |= EP_Collate & pLeft->flags; | |
| 74237 | 74350 | } |
| 74238 | 74351 | exprSetHeight(pRoot); |
| 74239 | 74352 | } |
| 74240 | 74353 | } |
| 74241 | 74354 | |
| @@ -74489,11 +74602,11 @@ | ||
| 74489 | 74602 | }else{ |
| 74490 | 74603 | assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); |
| 74491 | 74604 | assert( !ExprHasProperty(p, EP_FromJoin) ); |
| 74492 | 74605 | assert( (p->flags2 & EP2_MallocedToken)==0 ); |
| 74493 | 74606 | assert( (p->flags2 & EP2_Irreducible)==0 ); |
| 74494 | - if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ | |
| 74607 | + if( p->pLeft || p->pRight || p->x.pList ){ | |
| 74495 | 74608 | nSize = EXPR_REDUCEDSIZE | EP_Reduced; |
| 74496 | 74609 | }else{ |
| 74497 | 74610 | nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; |
| 74498 | 74611 | } |
| 74499 | 74612 | } |
| @@ -76513,10 +76626,11 @@ | ||
| 76513 | 76626 | sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); |
| 76514 | 76627 | sqlite3ReleaseTempReg(pParse, r3); |
| 76515 | 76628 | sqlite3ReleaseTempReg(pParse, r4); |
| 76516 | 76629 | break; |
| 76517 | 76630 | } |
| 76631 | + case TK_COLLATE: | |
| 76518 | 76632 | case TK_UPLUS: { |
| 76519 | 76633 | inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); |
| 76520 | 76634 | break; |
| 76521 | 76635 | } |
| 76522 | 76636 | |
| @@ -76881,10 +76995,16 @@ | ||
| 76881 | 76995 | case TK_UPLUS: zUniOp = "UPLUS"; break; |
| 76882 | 76996 | case TK_BITNOT: zUniOp = "BITNOT"; break; |
| 76883 | 76997 | case TK_NOT: zUniOp = "NOT"; break; |
| 76884 | 76998 | case TK_ISNULL: zUniOp = "ISNULL"; break; |
| 76885 | 76999 | case TK_NOTNULL: zUniOp = "NOTNULL"; break; |
| 77000 | + | |
| 77001 | + case TK_COLLATE: { | |
| 77002 | + sqlite3ExplainExpr(pOut, pExpr->pLeft); | |
| 77003 | + sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken); | |
| 77004 | + break; | |
| 77005 | + } | |
| 76886 | 77006 | |
| 76887 | 77007 | case TK_AGG_FUNCTION: |
| 76888 | 77008 | case TK_CONST_FUNC: |
| 76889 | 77009 | case TK_FUNCTION: { |
| 76890 | 77010 | ExprList *pFarg; /* List of function arguments */ |
| @@ -77019,10 +77139,16 @@ | ||
| 77019 | 77139 | for(i=0; i<pList->nExpr; i++){ |
| 77020 | 77140 | sqlite3ExplainPrintf(pOut, "item[%d] = ", i); |
| 77021 | 77141 | sqlite3ExplainPush(pOut); |
| 77022 | 77142 | sqlite3ExplainExpr(pOut, pList->a[i].pExpr); |
| 77023 | 77143 | sqlite3ExplainPop(pOut); |
| 77144 | + if( pList->a[i].zName ){ | |
| 77145 | + sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName); | |
| 77146 | + } | |
| 77147 | + if( pList->a[i].bSpanIsTab ){ | |
| 77148 | + sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan); | |
| 77149 | + } | |
| 77024 | 77150 | if( i<pList->nExpr-1 ){ |
| 77025 | 77151 | sqlite3ExplainNL(pOut); |
| 77026 | 77152 | } |
| 77027 | 77153 | } |
| 77028 | 77154 | sqlite3ExplainPop(pOut); |
| @@ -77100,10 +77226,13 @@ | ||
| 77100 | 77226 | switch( pExpr->op ){ |
| 77101 | 77227 | case TK_IN: |
| 77102 | 77228 | case TK_REGISTER: { |
| 77103 | 77229 | return WRC_Prune; |
| 77104 | 77230 | } |
| 77231 | + case TK_COLLATE: { | |
| 77232 | + return WRC_Continue; | |
| 77233 | + } | |
| 77105 | 77234 | case TK_FUNCTION: |
| 77106 | 77235 | case TK_AGG_FUNCTION: |
| 77107 | 77236 | case TK_CONST_FUNC: { |
| 77108 | 77237 | /* The arguments to a function have a fixed destination. |
| 77109 | 77238 | ** Mark them this way to avoid generated unneeded OP_SCopy |
| @@ -77121,13 +77250,15 @@ | ||
| 77121 | 77250 | break; |
| 77122 | 77251 | } |
| 77123 | 77252 | } |
| 77124 | 77253 | if( isAppropriateForFactoring(pExpr) ){ |
| 77125 | 77254 | int r1 = ++pParse->nMem; |
| 77126 | - int r2; | |
| 77127 | - r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); | |
| 77128 | - if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1); | |
| 77255 | + int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); | |
| 77256 | + /* If r2!=r1, it means that register r1 is never used. That is harmless | |
| 77257 | + ** but suboptimal, so we want to know about the situation to fix it. | |
| 77258 | + ** Hence the following assert: */ | |
| 77259 | + assert( r2==r1 ); | |
| 77129 | 77260 | pExpr->op2 = pExpr->op; |
| 77130 | 77261 | pExpr->op = TK_REGISTER; |
| 77131 | 77262 | pExpr->iTable = r2; |
| 77132 | 77263 | return WRC_Prune; |
| 77133 | 77264 | } |
| @@ -77540,11 +77671,19 @@ | ||
| 77540 | 77671 | assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); |
| 77541 | 77672 | if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ |
| 77542 | 77673 | return 2; |
| 77543 | 77674 | } |
| 77544 | 77675 | if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; |
| 77545 | - if( pA->op!=pB->op ) return 2; | |
| 77676 | + if( pA->op!=pB->op ){ | |
| 77677 | + if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){ | |
| 77678 | + return 1; | |
| 77679 | + } | |
| 77680 | + if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){ | |
| 77681 | + return 1; | |
| 77682 | + } | |
| 77683 | + return 2; | |
| 77684 | + } | |
| 77546 | 77685 | if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; |
| 77547 | 77686 | if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; |
| 77548 | 77687 | if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; |
| 77549 | 77688 | if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; |
| 77550 | 77689 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| @@ -77552,15 +77691,13 @@ | ||
| 77552 | 77691 | return 2; |
| 77553 | 77692 | } |
| 77554 | 77693 | }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){ |
| 77555 | 77694 | if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; |
| 77556 | 77695 | if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 77557 | - return 2; | |
| 77696 | + return pA->op==TK_COLLATE ? 1 : 2; | |
| 77558 | 77697 | } |
| 77559 | 77698 | } |
| 77560 | - if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1; | |
| 77561 | - if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2; | |
| 77562 | 77699 | return 0; |
| 77563 | 77700 | } |
| 77564 | 77701 | |
| 77565 | 77702 | /* |
| 77566 | 77703 | ** Compare two ExprList objects. Return 0 if they are identical and |
| @@ -83371,14 +83508,12 @@ | ||
| 83371 | 83508 | ** specified collation sequence names. |
| 83372 | 83509 | */ |
| 83373 | 83510 | for(i=0; i<pList->nExpr; i++){ |
| 83374 | 83511 | Expr *pExpr = pList->a[i].pExpr; |
| 83375 | 83512 | if( pExpr ){ |
| 83376 | - CollSeq *pColl = pExpr->pColl; | |
| 83377 | - /* Either pColl!=0 or there was an OOM failure. But if an OOM | |
| 83378 | - ** failure we have quit before reaching this point. */ | |
| 83379 | - if( ALWAYS(pColl) ){ | |
| 83513 | + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); | |
| 83514 | + if( pColl ){ | |
| 83380 | 83515 | nExtra += (1 + sqlite3Strlen30(pColl->zName)); |
| 83381 | 83516 | } |
| 83382 | 83517 | } |
| 83383 | 83518 | } |
| 83384 | 83519 | |
| @@ -83437,10 +83572,11 @@ | ||
| 83437 | 83572 | */ |
| 83438 | 83573 | for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ |
| 83439 | 83574 | const char *zColName = pListItem->zName; |
| 83440 | 83575 | Column *pTabCol; |
| 83441 | 83576 | int requestedSortOrder; |
| 83577 | + CollSeq *pColl; /* Collating sequence */ | |
| 83442 | 83578 | char *zColl; /* Collation sequence name */ |
| 83443 | 83579 | |
| 83444 | 83580 | for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ |
| 83445 | 83581 | if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; |
| 83446 | 83582 | } |
| @@ -83449,18 +83585,15 @@ | ||
| 83449 | 83585 | pTab->zName, zColName); |
| 83450 | 83586 | pParse->checkSchema = 1; |
| 83451 | 83587 | goto exit_create_index; |
| 83452 | 83588 | } |
| 83453 | 83589 | pIndex->aiColumn[i] = j; |
| 83454 | - /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of | |
| 83455 | - ** the way the "idxlist" non-terminal is constructed by the parser, | |
| 83456 | - ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl | |
| 83457 | - ** must exist or else there must have been an OOM error. But if there | |
| 83458 | - ** was an OOM error, we would never reach this point. */ | |
| 83459 | - if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){ | |
| 83590 | + if( pListItem->pExpr | |
| 83591 | + && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0 | |
| 83592 | + ){ | |
| 83460 | 83593 | int nColl; |
| 83461 | - zColl = pListItem->pExpr->pColl->zName; | |
| 83594 | + zColl = pColl->zName; | |
| 83462 | 83595 | nColl = sqlite3Strlen30(zColl) + 1; |
| 83463 | 83596 | assert( nExtra>=nColl ); |
| 83464 | 83597 | memcpy(zExtra, zColl, nColl); |
| 83465 | 83598 | zColl = zExtra; |
| 83466 | 83599 | zExtra += nColl; |
| @@ -87489,11 +87622,11 @@ | ||
| 87489 | 87622 | |
| 87490 | 87623 | /* |
| 87491 | 87624 | ** A foreign key constraint requires that the key columns in the parent |
| 87492 | 87625 | ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. |
| 87493 | 87626 | ** Given that pParent is the parent table for foreign key constraint pFKey, |
| 87494 | -** search the schema a unique index on the parent key columns. | |
| 87627 | +** search the schema for a unique index on the parent key columns. | |
| 87495 | 87628 | ** |
| 87496 | 87629 | ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY |
| 87497 | 87630 | ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx |
| 87498 | 87631 | ** is set to point to the unique index. |
| 87499 | 87632 | ** |
| @@ -87525,11 +87658,11 @@ | ||
| 87525 | 87658 | ** |
| 87526 | 87659 | ** then non-zero is returned, and a "foreign key mismatch" error loaded |
| 87527 | 87660 | ** into pParse. If an OOM error occurs, non-zero is returned and the |
| 87528 | 87661 | ** pParse->db->mallocFailed flag is set. |
| 87529 | 87662 | */ |
| 87530 | -static int locateFkeyIndex( | |
| 87663 | +SQLITE_PRIVATE int sqlite3FkLocateIndex( | |
| 87531 | 87664 | Parse *pParse, /* Parse context to store any error in */ |
| 87532 | 87665 | Table *pParent, /* Parent table of FK constraint pFKey */ |
| 87533 | 87666 | FKey *pFKey, /* Foreign key to find index for */ |
| 87534 | 87667 | Index **ppIdx, /* OUT: Unique index on parent table */ |
| 87535 | 87668 | int **paiCol /* OUT: Map of index columns in pFKey */ |
| @@ -87622,11 +87755,13 @@ | ||
| 87622 | 87755 | } |
| 87623 | 87756 | } |
| 87624 | 87757 | |
| 87625 | 87758 | if( !pIdx ){ |
| 87626 | 87759 | if( !pParse->disableTriggers ){ |
| 87627 | - sqlite3ErrorMsg(pParse, "foreign key mismatch"); | |
| 87760 | + sqlite3ErrorMsg(pParse, | |
| 87761 | + "foreign key mismatch - \"%w\" referencing \"%w\"", | |
| 87762 | + pFKey->pFrom->zName, pFKey->zTo); | |
| 87628 | 87763 | } |
| 87629 | 87764 | sqlite3DbFree(pParse->db, aiCol); |
| 87630 | 87765 | return 1; |
| 87631 | 87766 | } |
| 87632 | 87767 | |
| @@ -87858,16 +87993,19 @@ | ||
| 87858 | 87993 | if( pLeft ){ |
| 87859 | 87994 | /* Set the collation sequence and affinity of the LHS of each TK_EQ |
| 87860 | 87995 | ** expression to the parent key column defaults. */ |
| 87861 | 87996 | if( pIdx ){ |
| 87862 | 87997 | Column *pCol; |
| 87998 | + const char *zColl; | |
| 87863 | 87999 | iCol = pIdx->aiColumn[i]; |
| 87864 | 88000 | pCol = &pTab->aCol[iCol]; |
| 87865 | 88001 | if( pTab->iPKey==iCol ) iCol = -1; |
| 87866 | 88002 | pLeft->iTable = regData+iCol+1; |
| 87867 | 88003 | pLeft->affinity = pCol->affinity; |
| 87868 | - pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl); | |
| 88004 | + zColl = pCol->zColl; | |
| 88005 | + if( zColl==0 ) zColl = db->pDfltColl->zName; | |
| 88006 | + pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl); | |
| 87869 | 88007 | }else{ |
| 87870 | 88008 | pLeft->iTable = regData; |
| 87871 | 88009 | pLeft->affinity = SQLITE_AFF_INTEGER; |
| 87872 | 88010 | } |
| 87873 | 88011 | } |
| @@ -88080,11 +88218,11 @@ | ||
| 88080 | 88218 | if( pParse->disableTriggers ){ |
| 88081 | 88219 | pTo = sqlite3FindTable(db, pFKey->zTo, zDb); |
| 88082 | 88220 | }else{ |
| 88083 | 88221 | pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); |
| 88084 | 88222 | } |
| 88085 | - if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ | |
| 88223 | + if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ | |
| 88086 | 88224 | assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); |
| 88087 | 88225 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88088 | 88226 | if( pTo==0 ){ |
| 88089 | 88227 | /* If isIgnoreErrors is true, then a table is being dropped. In this |
| 88090 | 88228 | ** case SQLite runs a "DELETE FROM xxx" on the table being dropped |
| @@ -88160,11 +88298,11 @@ | ||
| 88160 | 88298 | /* Inserting a single row into a parent table cannot cause an immediate |
| 88161 | 88299 | ** foreign key violation. So do nothing in this case. */ |
| 88162 | 88300 | continue; |
| 88163 | 88301 | } |
| 88164 | 88302 | |
| 88165 | - if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ | |
| 88303 | + if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ | |
| 88166 | 88304 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88167 | 88305 | continue; |
| 88168 | 88306 | } |
| 88169 | 88307 | assert( aiCol || pFKey->nCol==1 ); |
| 88170 | 88308 | |
| @@ -88215,11 +88353,11 @@ | ||
| 88215 | 88353 | for(p=pTab->pFKey; p; p=p->pNextFrom){ |
| 88216 | 88354 | for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); |
| 88217 | 88355 | } |
| 88218 | 88356 | for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
| 88219 | 88357 | Index *pIdx = 0; |
| 88220 | - locateFkeyIndex(pParse, pTab, p, &pIdx, 0); | |
| 88358 | + sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); | |
| 88221 | 88359 | if( pIdx ){ |
| 88222 | 88360 | for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); |
| 88223 | 88361 | } |
| 88224 | 88362 | } |
| 88225 | 88363 | } |
| @@ -88341,11 +88479,11 @@ | ||
| 88341 | 88479 | ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ |
| 88342 | 88480 | Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ |
| 88343 | 88481 | int i; /* Iterator variable */ |
| 88344 | 88482 | Expr *pWhen = 0; /* WHEN clause for the trigger */ |
| 88345 | 88483 | |
| 88346 | - if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; | |
| 88484 | + if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; | |
| 88347 | 88485 | assert( aiCol || pFKey->nCol==1 ); |
| 88348 | 88486 | |
| 88349 | 88487 | for(i=0; i<pFKey->nCol; i++){ |
| 88350 | 88488 | Token tOld = { "old", 3 }; /* Literal "old" token */ |
| 88351 | 88489 | Token tNew = { "new", 3 }; /* Literal "new" token */ |
| @@ -89843,29 +89981,24 @@ | ||
| 89843 | 89981 | ExprList *pCheck = pTab->pCheck; |
| 89844 | 89982 | pParse->ckBase = regData; |
| 89845 | 89983 | onError = overrideError!=OE_Default ? overrideError : OE_Abort; |
| 89846 | 89984 | for(i=0; i<pCheck->nExpr; i++){ |
| 89847 | 89985 | int allOk = sqlite3VdbeMakeLabel(v); |
| 89848 | - Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0); | |
| 89849 | - if( !db->mallocFailed ){ | |
| 89850 | - assert( pDup!=0 ); | |
| 89851 | - sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL); | |
| 89852 | - if( onError==OE_Ignore ){ | |
| 89853 | - sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); | |
| 89854 | - }else{ | |
| 89855 | - char *zConsName = pCheck->a[i].zName; | |
| 89856 | - if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ | |
| 89857 | - if( zConsName ){ | |
| 89858 | - zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); | |
| 89859 | - }else{ | |
| 89860 | - zConsName = 0; | |
| 89861 | - } | |
| 89862 | - sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); | |
| 89863 | - } | |
| 89864 | - sqlite3VdbeResolveLabel(v, allOk); | |
| 89865 | - } | |
| 89866 | - sqlite3ExprDelete(db, pDup); | |
| 89986 | + sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); | |
| 89987 | + if( onError==OE_Ignore ){ | |
| 89988 | + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); | |
| 89989 | + }else{ | |
| 89990 | + char *zConsName = pCheck->a[i].zName; | |
| 89991 | + if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ | |
| 89992 | + if( zConsName ){ | |
| 89993 | + zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); | |
| 89994 | + }else{ | |
| 89995 | + zConsName = 0; | |
| 89996 | + } | |
| 89997 | + sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); | |
| 89998 | + } | |
| 89999 | + sqlite3VdbeResolveLabel(v, allOk); | |
| 89867 | 90000 | } |
| 89868 | 90001 | } |
| 89869 | 90002 | #endif /* !defined(SQLITE_OMIT_CHECK) */ |
| 89870 | 90003 | |
| 89871 | 90004 | /* If we have an INTEGER PRIMARY KEY, make sure the primary key |
| @@ -92686,13 +92819,15 @@ | ||
| 92686 | 92819 | if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ |
| 92687 | 92820 | Table *pTab; |
| 92688 | 92821 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 92689 | 92822 | pTab = sqlite3FindTable(db, zRight, zDb); |
| 92690 | 92823 | if( pTab ){ |
| 92691 | - int i; | |
| 92824 | + int i, k; | |
| 92692 | 92825 | int nHidden = 0; |
| 92693 | 92826 | Column *pCol; |
| 92827 | + Index *pPk; | |
| 92828 | + for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){} | |
| 92694 | 92829 | sqlite3VdbeSetNumCols(v, 6); |
| 92695 | 92830 | pParse->nMem = 6; |
| 92696 | 92831 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); |
| 92697 | 92832 | sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); |
| 92698 | 92833 | sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); |
| @@ -92713,12 +92848,18 @@ | ||
| 92713 | 92848 | if( pCol->zDflt ){ |
| 92714 | 92849 | sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); |
| 92715 | 92850 | }else{ |
| 92716 | 92851 | sqlite3VdbeAddOp2(v, OP_Null, 0, 5); |
| 92717 | 92852 | } |
| 92718 | - sqlite3VdbeAddOp2(v, OP_Integer, | |
| 92719 | - (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6); | |
| 92853 | + if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ | |
| 92854 | + k = 0; | |
| 92855 | + }else if( pPk==0 ){ | |
| 92856 | + k = 1; | |
| 92857 | + }else{ | |
| 92858 | + for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){} | |
| 92859 | + } | |
| 92860 | + sqlite3VdbeAddOp2(v, OP_Integer, k, 6); | |
| 92720 | 92861 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); |
| 92721 | 92862 | } |
| 92722 | 92863 | } |
| 92723 | 92864 | }else |
| 92724 | 92865 | |
| @@ -92849,10 +92990,124 @@ | ||
| 92849 | 92990 | ++i; |
| 92850 | 92991 | pFK = pFK->pNextFrom; |
| 92851 | 92992 | } |
| 92852 | 92993 | } |
| 92853 | 92994 | } |
| 92995 | + }else | |
| 92996 | +#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ | |
| 92997 | + | |
| 92998 | +#ifndef SQLITE_OMIT_FOREIGN_KEY | |
| 92999 | + if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){ | |
| 93000 | + FKey *pFK; /* A foreign key constraint */ | |
| 93001 | + Table *pTab; /* Child table contain "REFERENCES" keyword */ | |
| 93002 | + Table *pParent; /* Parent table that child points to */ | |
| 93003 | + Index *pIdx; /* Index in the parent table */ | |
| 93004 | + int i; /* Loop counter: Foreign key number for pTab */ | |
| 93005 | + int j; /* Loop counter: Field of the foreign key */ | |
| 93006 | + HashElem *k; /* Loop counter: Next table in schema */ | |
| 93007 | + int x; /* result variable */ | |
| 93008 | + int regResult; /* 3 registers to hold a result row */ | |
| 93009 | + int regKey; /* Register to hold key for checking the FK */ | |
| 93010 | + int regRow; /* Registers to hold a row from pTab */ | |
| 93011 | + int addrTop; /* Top of a loop checking foreign keys */ | |
| 93012 | + int addrOk; /* Jump here if the key is OK */ | |
| 93013 | + int *aiCols; /* child to parent column mapping */ | |
| 93014 | + | |
| 93015 | + if( sqlite3ReadSchema(pParse) ) goto pragma_out; | |
| 93016 | + regResult = pParse->nMem+1; | |
| 93017 | + pParse->nMem += 4; | |
| 93018 | + regKey = ++pParse->nMem; | |
| 93019 | + regRow = ++pParse->nMem; | |
| 93020 | + v = sqlite3GetVdbe(pParse); | |
| 93021 | + sqlite3VdbeSetNumCols(v, 4); | |
| 93022 | + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); | |
| 93023 | + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC); | |
| 93024 | + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC); | |
| 93025 | + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC); | |
| 93026 | + sqlite3CodeVerifySchema(pParse, iDb); | |
| 93027 | + k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); | |
| 93028 | + while( k ){ | |
| 93029 | + if( zRight ){ | |
| 93030 | + pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); | |
| 93031 | + k = 0; | |
| 93032 | + }else{ | |
| 93033 | + pTab = (Table*)sqliteHashData(k); | |
| 93034 | + k = sqliteHashNext(k); | |
| 93035 | + } | |
| 93036 | + if( pTab==0 || pTab->pFKey==0 ) continue; | |
| 93037 | + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); | |
| 93038 | + if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; | |
| 93039 | + sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); | |
| 93040 | + sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, | |
| 93041 | + P4_TRANSIENT); | |
| 93042 | + for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ | |
| 93043 | + pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); | |
| 93044 | + if( pParent==0 ) break; | |
| 93045 | + pIdx = 0; | |
| 93046 | + sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); | |
| 93047 | + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); | |
| 93048 | + if( x==0 ){ | |
| 93049 | + if( pIdx==0 ){ | |
| 93050 | + sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); | |
| 93051 | + }else{ | |
| 93052 | + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); | |
| 93053 | + sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); | |
| 93054 | + sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); | |
| 93055 | + } | |
| 93056 | + }else{ | |
| 93057 | + k = 0; | |
| 93058 | + break; | |
| 93059 | + } | |
| 93060 | + } | |
| 93061 | + if( pFK ) break; | |
| 93062 | + if( pParse->nTab<i ) pParse->nTab = i; | |
| 93063 | + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); | |
| 93064 | + for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ | |
| 93065 | + pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); | |
| 93066 | + assert( pParent!=0 ); | |
| 93067 | + pIdx = 0; | |
| 93068 | + aiCols = 0; | |
| 93069 | + x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); | |
| 93070 | + assert( x==0 ); | |
| 93071 | + addrOk = sqlite3VdbeMakeLabel(v); | |
| 93072 | + if( pIdx==0 ){ | |
| 93073 | + int iKey = pFK->aCol[0].iFrom; | |
| 93074 | + assert( iKey>=0 && iKey<pTab->nCol ); | |
| 93075 | + if( iKey!=pTab->iPKey ){ | |
| 93076 | + sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); | |
| 93077 | + sqlite3ColumnDefault(v, pTab, iKey, regRow); | |
| 93078 | + sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); | |
| 93079 | + sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, | |
| 93080 | + sqlite3VdbeCurrentAddr(v)+3); | |
| 93081 | + }else{ | |
| 93082 | + sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); | |
| 93083 | + } | |
| 93084 | + sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); | |
| 93085 | + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); | |
| 93086 | + sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); | |
| 93087 | + }else{ | |
| 93088 | + for(j=0; j<pFK->nCol; j++){ | |
| 93089 | + sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, | |
| 93090 | + aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j); | |
| 93091 | + sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); | |
| 93092 | + } | |
| 93093 | + sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); | |
| 93094 | + sqlite3VdbeChangeP4(v, -1, | |
| 93095 | + sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); | |
| 93096 | + sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); | |
| 93097 | + } | |
| 93098 | + sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); | |
| 93099 | + sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, | |
| 93100 | + pFK->zTo, P4_TRANSIENT); | |
| 93101 | + sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3); | |
| 93102 | + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); | |
| 93103 | + sqlite3VdbeResolveLabel(v, addrOk); | |
| 93104 | + sqlite3DbFree(db, aiCols); | |
| 93105 | + } | |
| 93106 | + sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); | |
| 93107 | + sqlite3VdbeJumpHere(v, addrTop); | |
| 93108 | + } | |
| 92854 | 93109 | }else |
| 92855 | 93110 | #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
| 92856 | 93111 | |
| 92857 | 93112 | #ifndef NDEBUG |
| 92858 | 93113 | if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ |
| @@ -94308,11 +94563,11 @@ | ||
| 94308 | 94563 | SrcList *pSrc, /* the FROM clause -- which tables to scan */ |
| 94309 | 94564 | Expr *pWhere, /* the WHERE clause */ |
| 94310 | 94565 | ExprList *pGroupBy, /* the GROUP BY clause */ |
| 94311 | 94566 | Expr *pHaving, /* the HAVING clause */ |
| 94312 | 94567 | ExprList *pOrderBy, /* the ORDER BY clause */ |
| 94313 | - int isDistinct, /* true if the DISTINCT keyword is present */ | |
| 94568 | + u16 selFlags, /* Flag parameters, such as SF_Distinct */ | |
| 94314 | 94569 | Expr *pLimit, /* LIMIT value. NULL means not used */ |
| 94315 | 94570 | Expr *pOffset /* OFFSET value. NULL means no offset */ |
| 94316 | 94571 | ){ |
| 94317 | 94572 | Select *pNew; |
| 94318 | 94573 | Select standin; |
| @@ -94332,11 +94587,11 @@ | ||
| 94332 | 94587 | pNew->pSrc = pSrc; |
| 94333 | 94588 | pNew->pWhere = pWhere; |
| 94334 | 94589 | pNew->pGroupBy = pGroupBy; |
| 94335 | 94590 | pNew->pHaving = pHaving; |
| 94336 | 94591 | pNew->pOrderBy = pOrderBy; |
| 94337 | - pNew->selFlags = isDistinct ? SF_Distinct : 0; | |
| 94592 | + pNew->selFlags = selFlags; | |
| 94338 | 94593 | pNew->op = TK_SELECT; |
| 94339 | 94594 | pNew->pLimit = pLimit; |
| 94340 | 94595 | pNew->pOffset = pOffset; |
| 94341 | 94596 | assert( pOffset==0 || pLimit!=0 ); |
| 94342 | 94597 | pNew->addrOpenEphm[0] = -1; |
| @@ -95588,13 +95843,11 @@ | ||
| 95588 | 95843 | *paCol = aCol; |
| 95589 | 95844 | |
| 95590 | 95845 | for(i=0, pCol=aCol; i<nCol; i++, pCol++){ |
| 95591 | 95846 | /* Get an appropriate name for the column |
| 95592 | 95847 | */ |
| 95593 | - p = pEList->a[i].pExpr; | |
| 95594 | - assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue) | |
| 95595 | - || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 ); | |
| 95848 | + p = sqlite3ExprSkipCollate(pEList->a[i].pExpr); | |
| 95596 | 95849 | if( (zName = pEList->a[i].zName)!=0 ){ |
| 95597 | 95850 | /* If the column contains an "AS <name>" phrase, use <name> as the name */ |
| 95598 | 95851 | zName = sqlite3DbStrDup(db, zName); |
| 95599 | 95852 | }else{ |
| 95600 | 95853 | Expr *pColExpr = p; /* The expression that is the result column name */ |
| @@ -95628,10 +95881,13 @@ | ||
| 95628 | 95881 | */ |
| 95629 | 95882 | nName = sqlite3Strlen30(zName); |
| 95630 | 95883 | for(j=cnt=0; j<i; j++){ |
| 95631 | 95884 | if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ |
| 95632 | 95885 | char *zNewName; |
| 95886 | + int k; | |
| 95887 | + for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){} | |
| 95888 | + if( zName[k]==':' ) nName = k; | |
| 95633 | 95889 | zName[nName] = 0; |
| 95634 | 95890 | zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); |
| 95635 | 95891 | sqlite3DbFree(db, zName); |
| 95636 | 95892 | zName = zNewName; |
| 95637 | 95893 | j = -1; |
| @@ -96586,16 +96842,17 @@ | ||
| 96586 | 96842 | pKeyMerge->nField = (u16)nOrderBy; |
| 96587 | 96843 | pKeyMerge->enc = ENC(db); |
| 96588 | 96844 | for(i=0; i<nOrderBy; i++){ |
| 96589 | 96845 | CollSeq *pColl; |
| 96590 | 96846 | Expr *pTerm = pOrderBy->a[i].pExpr; |
| 96591 | - if( pTerm->flags & EP_ExpCollate ){ | |
| 96592 | - pColl = pTerm->pColl; | |
| 96847 | + if( pTerm->flags & EP_Collate ){ | |
| 96848 | + pColl = sqlite3ExprCollSeq(pParse, pTerm); | |
| 96593 | 96849 | }else{ |
| 96594 | 96850 | pColl = multiSelectCollSeq(pParse, p, aPermute[i]); |
| 96595 | - pTerm->flags |= EP_ExpCollate; | |
| 96596 | - pTerm->pColl = pColl; | |
| 96851 | + if( pColl==0 ) pColl = db->pDfltColl; | |
| 96852 | + pOrderBy->a[i].pExpr = | |
| 96853 | + sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); | |
| 96597 | 96854 | } |
| 96598 | 96855 | pKeyMerge->aColl[i] = pColl; |
| 96599 | 96856 | pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; |
| 96600 | 96857 | } |
| 96601 | 96858 | } |
| @@ -96794,10 +97051,11 @@ | ||
| 96794 | 97051 | */ |
| 96795 | 97052 | sqlite3VdbeResolveLabel(v, labelCmpr); |
| 96796 | 97053 | sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); |
| 96797 | 97054 | sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, |
| 96798 | 97055 | (char*)pKeyMerge, P4_KEYINFO_HANDOFF); |
| 97056 | + sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); | |
| 96799 | 97057 | sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); |
| 96800 | 97058 | |
| 96801 | 97059 | /* Release temporary registers |
| 96802 | 97060 | */ |
| 96803 | 97061 | if( regPrev ){ |
| @@ -96861,13 +97119,10 @@ | ||
| 96861 | 97119 | }else{ |
| 96862 | 97120 | Expr *pNew; |
| 96863 | 97121 | assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); |
| 96864 | 97122 | assert( pExpr->pLeft==0 && pExpr->pRight==0 ); |
| 96865 | 97123 | pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); |
| 96866 | - if( pNew && pExpr->pColl ){ | |
| 96867 | - pNew->pColl = pExpr->pColl; | |
| 96868 | - } | |
| 96869 | 97124 | sqlite3ExprDelete(db, pExpr); |
| 96870 | 97125 | pExpr = pNew; |
| 96871 | 97126 | } |
| 96872 | 97127 | }else{ |
| 96873 | 97128 | pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); |
| @@ -97414,38 +97669,47 @@ | ||
| 97414 | 97669 | return 1; |
| 97415 | 97670 | } |
| 97416 | 97671 | #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
| 97417 | 97672 | |
| 97418 | 97673 | /* |
| 97419 | -** Analyze the SELECT statement passed as an argument to see if it | |
| 97420 | -** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if | |
| 97421 | -** it is, or 0 otherwise. At present, a query is considered to be | |
| 97422 | -** a min()/max() query if: | |
| 97423 | -** | |
| 97424 | -** 1. There is a single object in the FROM clause. | |
| 97425 | -** | |
| 97426 | -** 2. There is a single expression in the result set, and it is | |
| 97427 | -** either min(x) or max(x), where x is a column reference. | |
| 97428 | -*/ | |
| 97429 | -static u8 minMaxQuery(Select *p){ | |
| 97430 | - Expr *pExpr; | |
| 97431 | - ExprList *pEList = p->pEList; | |
| 97432 | - | |
| 97433 | - if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL; | |
| 97434 | - pExpr = pEList->a[0].pExpr; | |
| 97435 | - if( pExpr->op!=TK_AGG_FUNCTION ) return 0; | |
| 97436 | - if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0; | |
| 97437 | - pEList = pExpr->x.pList; | |
| 97438 | - if( pEList==0 || pEList->nExpr!=1 ) return 0; | |
| 97439 | - if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL; | |
| 97440 | - assert( !ExprHasProperty(pExpr, EP_IntValue) ); | |
| 97441 | - if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){ | |
| 97442 | - return WHERE_ORDERBY_MIN; | |
| 97443 | - }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){ | |
| 97444 | - return WHERE_ORDERBY_MAX; | |
| 97445 | - } | |
| 97446 | - return WHERE_ORDERBY_NORMAL; | |
| 97674 | +** Based on the contents of the AggInfo structure indicated by the first | |
| 97675 | +** argument, this function checks if the following are true: | |
| 97676 | +** | |
| 97677 | +** * the query contains just a single aggregate function, | |
| 97678 | +** * the aggregate function is either min() or max(), and | |
| 97679 | +** * the argument to the aggregate function is a column value. | |
| 97680 | +** | |
| 97681 | +** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX | |
| 97682 | +** is returned as appropriate. Also, *ppMinMax is set to point to the | |
| 97683 | +** list of arguments passed to the aggregate before returning. | |
| 97684 | +** | |
| 97685 | +** Or, if the conditions above are not met, *ppMinMax is set to 0 and | |
| 97686 | +** WHERE_ORDERBY_NORMAL is returned. | |
| 97687 | +*/ | |
| 97688 | +static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ | |
| 97689 | + int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ | |
| 97690 | + | |
| 97691 | + *ppMinMax = 0; | |
| 97692 | + if( pAggInfo->nFunc==1 ){ | |
| 97693 | + Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ | |
| 97694 | + ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ | |
| 97695 | + | |
| 97696 | + assert( pExpr->op==TK_AGG_FUNCTION ); | |
| 97697 | + if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ | |
| 97698 | + const char *zFunc = pExpr->u.zToken; | |
| 97699 | + if( sqlite3StrICmp(zFunc, "min")==0 ){ | |
| 97700 | + eRet = WHERE_ORDERBY_MIN; | |
| 97701 | + *ppMinMax = pEList; | |
| 97702 | + }else if( sqlite3StrICmp(zFunc, "max")==0 ){ | |
| 97703 | + eRet = WHERE_ORDERBY_MAX; | |
| 97704 | + *ppMinMax = pEList; | |
| 97705 | + } | |
| 97706 | + } | |
| 97707 | + } | |
| 97708 | + | |
| 97709 | + assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); | |
| 97710 | + return eRet; | |
| 97447 | 97711 | } |
| 97448 | 97712 | |
| 97449 | 97713 | /* |
| 97450 | 97714 | ** The select statement passed as the first argument is an aggregate query. |
| 97451 | 97715 | ** The second argment is the associated aggregate-info object. This |
| @@ -97536,10 +97800,11 @@ | ||
| 97536 | 97800 | int i, j, k; |
| 97537 | 97801 | SrcList *pTabList; |
| 97538 | 97802 | ExprList *pEList; |
| 97539 | 97803 | struct SrcList_item *pFrom; |
| 97540 | 97804 | sqlite3 *db = pParse->db; |
| 97805 | + Expr *pE, *pRight, *pExpr; | |
| 97541 | 97806 | |
| 97542 | 97807 | if( db->mallocFailed ){ |
| 97543 | 97808 | return WRC_Abort; |
| 97544 | 97809 | } |
| 97545 | 97810 | if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){ |
| @@ -97621,11 +97886,11 @@ | ||
| 97621 | 97886 | ** |
| 97622 | 97887 | ** The first loop just checks to see if there are any "*" operators |
| 97623 | 97888 | ** that need expanding. |
| 97624 | 97889 | */ |
| 97625 | 97890 | for(k=0; k<pEList->nExpr; k++){ |
| 97626 | - Expr *pE = pEList->a[k].pExpr; | |
| 97891 | + pE = pEList->a[k].pExpr; | |
| 97627 | 97892 | if( pE->op==TK_ALL ) break; |
| 97628 | 97893 | assert( pE->op!=TK_DOT || pE->pRight!=0 ); |
| 97629 | 97894 | assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); |
| 97630 | 97895 | if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; |
| 97631 | 97896 | } |
| @@ -97639,14 +97904,22 @@ | ||
| 97639 | 97904 | ExprList *pNew = 0; |
| 97640 | 97905 | int flags = pParse->db->flags; |
| 97641 | 97906 | int longNames = (flags & SQLITE_FullColNames)!=0 |
| 97642 | 97907 | && (flags & SQLITE_ShortColNames)==0; |
| 97643 | 97908 | |
| 97909 | + /* When processing FROM-clause subqueries, it is always the case | |
| 97910 | + ** that full_column_names=OFF and short_column_names=ON. The | |
| 97911 | + ** sqlite3ResultSetOfSelect() routine makes it so. */ | |
| 97912 | + assert( (p->selFlags & SF_NestedFrom)==0 | |
| 97913 | + || ((flags & SQLITE_FullColNames)==0 && | |
| 97914 | + (flags & SQLITE_ShortColNames)!=0) ); | |
| 97915 | + | |
| 97644 | 97916 | for(k=0; k<pEList->nExpr; k++){ |
| 97645 | - Expr *pE = a[k].pExpr; | |
| 97646 | - assert( pE->op!=TK_DOT || pE->pRight!=0 ); | |
| 97647 | - if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){ | |
| 97917 | + pE = a[k].pExpr; | |
| 97918 | + pRight = pE->pRight; | |
| 97919 | + assert( pE->op!=TK_DOT || pRight!=0 ); | |
| 97920 | + if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){ | |
| 97648 | 97921 | /* This particular expression does not need to be expanded. |
| 97649 | 97922 | */ |
| 97650 | 97923 | pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); |
| 97651 | 97924 | if( pNew ){ |
| 97652 | 97925 | pNew->a[pNew->nExpr-1].zName = a[k].zName; |
| @@ -97657,44 +97930,56 @@ | ||
| 97657 | 97930 | a[k].pExpr = 0; |
| 97658 | 97931 | }else{ |
| 97659 | 97932 | /* This expression is a "*" or a "TABLE.*" and needs to be |
| 97660 | 97933 | ** expanded. */ |
| 97661 | 97934 | int tableSeen = 0; /* Set to 1 when TABLE matches */ |
| 97662 | - char *zTName; /* text of name of TABLE */ | |
| 97935 | + char *zTName = 0; /* text of name of TABLE */ | |
| 97663 | 97936 | if( pE->op==TK_DOT ){ |
| 97664 | 97937 | assert( pE->pLeft!=0 ); |
| 97665 | 97938 | assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); |
| 97666 | 97939 | zTName = pE->pLeft->u.zToken; |
| 97667 | - }else{ | |
| 97668 | - zTName = 0; | |
| 97669 | 97940 | } |
| 97670 | 97941 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 97671 | 97942 | Table *pTab = pFrom->pTab; |
| 97943 | + Select *pSub = pFrom->pSelect; | |
| 97672 | 97944 | char *zTabName = pFrom->zAlias; |
| 97945 | + const char *zSchemaName = 0; | |
| 97946 | + int iDb; | |
| 97673 | 97947 | if( zTabName==0 ){ |
| 97674 | 97948 | zTabName = pTab->zName; |
| 97675 | 97949 | } |
| 97676 | 97950 | if( db->mallocFailed ) break; |
| 97677 | - if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ | |
| 97678 | - continue; | |
| 97951 | + if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ | |
| 97952 | + pSub = 0; | |
| 97953 | + if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ | |
| 97954 | + continue; | |
| 97955 | + } | |
| 97956 | + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | |
| 97957 | + zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*"; | |
| 97679 | 97958 | } |
| 97680 | - tableSeen = 1; | |
| 97681 | 97959 | for(j=0; j<pTab->nCol; j++){ |
| 97682 | - Expr *pExpr, *pRight; | |
| 97683 | 97960 | char *zName = pTab->aCol[j].zName; |
| 97684 | 97961 | char *zColname; /* The computed column name */ |
| 97685 | 97962 | char *zToFree; /* Malloced string that needs to be freed */ |
| 97686 | 97963 | Token sColname; /* Computed column name as a token */ |
| 97964 | + | |
| 97965 | + assert( zName ); | |
| 97966 | + if( zTName && pSub | |
| 97967 | + && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0 | |
| 97968 | + ){ | |
| 97969 | + continue; | |
| 97970 | + } | |
| 97687 | 97971 | |
| 97688 | 97972 | /* If a column is marked as 'hidden' (currently only possible |
| 97689 | 97973 | ** for virtual tables), do not include it in the expanded |
| 97690 | 97974 | ** result-set list. |
| 97691 | 97975 | */ |
| 97692 | 97976 | if( IsHiddenColumn(&pTab->aCol[j]) ){ |
| 97693 | 97977 | assert(IsVirtual(pTab)); |
| 97694 | 97978 | continue; |
| 97695 | 97979 | } |
| 97980 | + tableSeen = 1; | |
| 97696 | 97981 | |
| 97697 | 97982 | if( i>0 && zTName==0 ){ |
| 97698 | 97983 | if( (pFrom->jointype & JT_NATURAL)!=0 |
| 97699 | 97984 | && tableAndColumnIndex(pTabList, i, zName, 0, 0) |
| 97700 | 97985 | ){ |
| @@ -97713,10 +97998,14 @@ | ||
| 97713 | 97998 | zToFree = 0; |
| 97714 | 97999 | if( longNames || pTabList->nSrc>1 ){ |
| 97715 | 98000 | Expr *pLeft; |
| 97716 | 98001 | pLeft = sqlite3Expr(db, TK_ID, zTabName); |
| 97717 | 98002 | pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); |
| 98003 | + if( zSchemaName ){ | |
| 98004 | + pLeft = sqlite3Expr(db, TK_ID, zSchemaName); | |
| 98005 | + pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0); | |
| 98006 | + } | |
| 97718 | 98007 | if( longNames ){ |
| 97719 | 98008 | zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); |
| 97720 | 98009 | zToFree = zColname; |
| 97721 | 98010 | } |
| 97722 | 98011 | }else{ |
| @@ -97724,10 +98013,22 @@ | ||
| 97724 | 98013 | } |
| 97725 | 98014 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
| 97726 | 98015 | sColname.z = zColname; |
| 97727 | 98016 | sColname.n = sqlite3Strlen30(zColname); |
| 97728 | 98017 | sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
| 98018 | + if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ | |
| 98019 | + struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; | |
| 98020 | + if( pSub ){ | |
| 98021 | + pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); | |
| 98022 | + testcase( pX->zSpan==0 ); | |
| 98023 | + }else{ | |
| 98024 | + pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s", | |
| 98025 | + zSchemaName, zTabName, zColname); | |
| 98026 | + testcase( pX->zSpan==0 ); | |
| 98027 | + } | |
| 98028 | + pX->bSpanIsTab = 1; | |
| 98029 | + } | |
| 97729 | 98030 | sqlite3DbFree(db, zToFree); |
| 97730 | 98031 | } |
| 97731 | 98032 | } |
| 97732 | 98033 | if( !tableSeen ){ |
| 97733 | 98034 | if( zTName ){ |
| @@ -98781,15 +99082,21 @@ | ||
| 98781 | 99082 | ** index or indices to use) should place a different priority on |
| 98782 | 99083 | ** satisfying the 'ORDER BY' clause than it does in other cases. |
| 98783 | 99084 | ** Refer to code and comments in where.c for details. |
| 98784 | 99085 | */ |
| 98785 | 99086 | ExprList *pMinMax = 0; |
| 98786 | - u8 flag = minMaxQuery(p); | |
| 99087 | + u8 flag = WHERE_ORDERBY_NORMAL; | |
| 99088 | + | |
| 99089 | + assert( p->pGroupBy==0 ); | |
| 99090 | + assert( flag==0 ); | |
| 99091 | + if( p->pHaving==0 ){ | |
| 99092 | + flag = minMaxQuery(&sAggInfo, &pMinMax); | |
| 99093 | + } | |
| 99094 | + assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); | |
| 99095 | + | |
| 98787 | 99096 | if( flag ){ |
| 98788 | - assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) ); | |
| 98789 | - assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 ); | |
| 98790 | - pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0); | |
| 99097 | + pMinMax = sqlite3ExprListDup(db, pMinMax, 0); | |
| 98791 | 99098 | pDel = pMinMax; |
| 98792 | 99099 | if( pMinMax && !db->mallocFailed ){ |
| 98793 | 99100 | pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
| 98794 | 99101 | pMinMax->a[0].pExpr->op = TK_COLUMN; |
| 98795 | 99102 | } |
| @@ -102673,11 +102980,11 @@ | ||
| 102673 | 102980 | #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ |
| 102674 | 102981 | #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ |
| 102675 | 102982 | #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ |
| 102676 | 102983 | #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ |
| 102677 | 102984 | #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ |
| 102678 | -#define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */ | |
| 102985 | +#define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */ | |
| 102679 | 102986 | #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */ |
| 102680 | 102987 | #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */ |
| 102681 | 102988 | #define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */ |
| 102682 | 102989 | #define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */ |
| 102683 | 102990 | #define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */ |
| @@ -102823,11 +103130,11 @@ | ||
| 102823 | 103130 | sqlite3DbFree(db, pOld); |
| 102824 | 103131 | } |
| 102825 | 103132 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 102826 | 103133 | } |
| 102827 | 103134 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 102828 | - pTerm->pExpr = p; | |
| 103135 | + pTerm->pExpr = sqlite3ExprSkipCollate(p); | |
| 102829 | 103136 | pTerm->wtFlags = wtFlags; |
| 102830 | 103137 | pTerm->pWC = pWC; |
| 102831 | 103138 | pTerm->iParent = -1; |
| 102832 | 103139 | return idx; |
| 102833 | 103140 | } |
| @@ -102983,27 +103290,36 @@ | ||
| 102983 | 103290 | |
| 102984 | 103291 | /* |
| 102985 | 103292 | ** Commute a comparison operator. Expressions of the form "X op Y" |
| 102986 | 103293 | ** are converted into "Y op X". |
| 102987 | 103294 | ** |
| 102988 | -** If a collation sequence is associated with either the left or right | |
| 103295 | +** If left/right precendence rules come into play when determining the | |
| 103296 | +** collating | |
| 102989 | 103297 | ** side of the comparison, it remains associated with the same side after |
| 102990 | 103298 | ** the commutation. So "Y collate NOCASE op X" becomes |
| 102991 | -** "X collate NOCASE op Y". This is because any collation sequence on | |
| 103299 | +** "X op Y". This is because any collation sequence on | |
| 102992 | 103300 | ** the left hand side of a comparison overrides any collation sequence |
| 102993 | -** attached to the right. For the same reason the EP_ExpCollate flag | |
| 103301 | +** attached to the right. For the same reason the EP_Collate flag | |
| 102994 | 103302 | ** is not commuted. |
| 102995 | 103303 | */ |
| 102996 | 103304 | static void exprCommute(Parse *pParse, Expr *pExpr){ |
| 102997 | - u16 expRight = (pExpr->pRight->flags & EP_ExpCollate); | |
| 102998 | - u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate); | |
| 103305 | + u16 expRight = (pExpr->pRight->flags & EP_Collate); | |
| 103306 | + u16 expLeft = (pExpr->pLeft->flags & EP_Collate); | |
| 102999 | 103307 | assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); |
| 103000 | - pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); | |
| 103001 | - pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); | |
| 103002 | - SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl); | |
| 103003 | - pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft; | |
| 103004 | - pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight; | |
| 103308 | + if( expRight==expLeft ){ | |
| 103309 | + /* Either X and Y both have COLLATE operator or neither do */ | |
| 103310 | + if( expRight ){ | |
| 103311 | + /* Both X and Y have COLLATE operators. Make sure X is always | |
| 103312 | + ** used by clearing the EP_Collate flag from Y. */ | |
| 103313 | + pExpr->pRight->flags &= ~EP_Collate; | |
| 103314 | + }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ | |
| 103315 | + /* Neither X nor Y have COLLATE operators, but X has a non-default | |
| 103316 | + ** collating sequence. So add the EP_Collate marker on X to cause | |
| 103317 | + ** it to be searched first. */ | |
| 103318 | + pExpr->pLeft->flags |= EP_Collate; | |
| 103319 | + } | |
| 103320 | + } | |
| 103005 | 103321 | SWAP(Expr*,pExpr->pRight,pExpr->pLeft); |
| 103006 | 103322 | if( pExpr->op>=TK_GT ){ |
| 103007 | 103323 | assert( TK_LT==TK_GT+2 ); |
| 103008 | 103324 | assert( TK_GE==TK_LE+2 ); |
| 103009 | 103325 | assert( TK_GT>TK_EQ ); |
| @@ -103076,16 +103392,16 @@ | ||
| 103076 | 103392 | ** it to be useful for optimising expression pX. Store this |
| 103077 | 103393 | ** value in variable pColl. |
| 103078 | 103394 | */ |
| 103079 | 103395 | assert(pX->pLeft); |
| 103080 | 103396 | pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| 103081 | - assert(pColl || pParse->nErr); | |
| 103397 | + if( pColl==0 ) pColl = pParse->db->pDfltColl; | |
| 103082 | 103398 | |
| 103083 | 103399 | for(j=0; pIdx->aiColumn[j]!=iColumn; j++){ |
| 103084 | 103400 | if( NEVER(j>=pIdx->nColumn) ) return 0; |
| 103085 | 103401 | } |
| 103086 | - if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; | |
| 103402 | + if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; | |
| 103087 | 103403 | } |
| 103088 | 103404 | return pTerm; |
| 103089 | 103405 | } |
| 103090 | 103406 | } |
| 103091 | 103407 | } |
| @@ -103600,10 +103916,11 @@ | ||
| 103600 | 103916 | return; |
| 103601 | 103917 | } |
| 103602 | 103918 | pTerm = &pWC->a[idxTerm]; |
| 103603 | 103919 | pMaskSet = pWC->pMaskSet; |
| 103604 | 103920 | pExpr = pTerm->pExpr; |
| 103921 | + assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); | |
| 103605 | 103922 | prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); |
| 103606 | 103923 | op = pExpr->op; |
| 103607 | 103924 | if( op==TK_IN ){ |
| 103608 | 103925 | assert( pExpr->pRight==0 ); |
| 103609 | 103926 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| @@ -103626,12 +103943,12 @@ | ||
| 103626 | 103943 | pTerm->prereqAll = prereqAll; |
| 103627 | 103944 | pTerm->leftCursor = -1; |
| 103628 | 103945 | pTerm->iParent = -1; |
| 103629 | 103946 | pTerm->eOperator = 0; |
| 103630 | 103947 | if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ |
| 103631 | - Expr *pLeft = pExpr->pLeft; | |
| 103632 | - Expr *pRight = pExpr->pRight; | |
| 103948 | + Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); | |
| 103949 | + Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); | |
| 103633 | 103950 | if( pLeft->op==TK_COLUMN ){ |
| 103634 | 103951 | pTerm->leftCursor = pLeft->iTable; |
| 103635 | 103952 | pTerm->u.leftColumn = pLeft->iColumn; |
| 103636 | 103953 | pTerm->eOperator = operatorMask(op); |
| 103637 | 103954 | } |
| @@ -103655,11 +103972,11 @@ | ||
| 103655 | 103972 | }else{ |
| 103656 | 103973 | pDup = pExpr; |
| 103657 | 103974 | pNew = pTerm; |
| 103658 | 103975 | } |
| 103659 | 103976 | exprCommute(pParse, pDup); |
| 103660 | - pLeft = pDup->pLeft; | |
| 103977 | + pLeft = sqlite3ExprSkipCollate(pDup->pLeft); | |
| 103661 | 103978 | pNew->leftCursor = pLeft->iTable; |
| 103662 | 103979 | pNew->u.leftColumn = pLeft->iColumn; |
| 103663 | 103980 | testcase( (prereqLeft | extraRight) != prereqLeft ); |
| 103664 | 103981 | pNew->prereqRight = prereqLeft | extraRight; |
| 103665 | 103982 | pNew->prereqAll = prereqAll; |
| @@ -103734,11 +104051,11 @@ | ||
| 103734 | 104051 | Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ |
| 103735 | 104052 | Expr *pNewExpr1; |
| 103736 | 104053 | Expr *pNewExpr2; |
| 103737 | 104054 | int idxNew1; |
| 103738 | 104055 | int idxNew2; |
| 103739 | - CollSeq *pColl; /* Collating sequence to use */ | |
| 104056 | + Token sCollSeqName; /* Name of collating sequence */ | |
| 103740 | 104057 | |
| 103741 | 104058 | pLeft = pExpr->x.pList->a[1].pExpr; |
| 103742 | 104059 | pStr2 = sqlite3ExprDup(db, pStr1, 0); |
| 103743 | 104060 | if( !db->mallocFailed ){ |
| 103744 | 104061 | u8 c, *pC; /* Last character before the first wildcard */ |
| @@ -103756,20 +104073,23 @@ | ||
| 103756 | 104073 | |
| 103757 | 104074 | c = sqlite3UpperToLower[c]; |
| 103758 | 104075 | } |
| 103759 | 104076 | *pC = c + 1; |
| 103760 | 104077 | } |
| 103761 | - pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0); | |
| 104078 | + sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; | |
| 104079 | + sCollSeqName.n = 6; | |
| 104080 | + pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); | |
| 103762 | 104081 | pNewExpr1 = sqlite3PExpr(pParse, TK_GE, |
| 103763 | - sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl), | |
| 103764 | - pStr1, 0); | |
| 104082 | + sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName), | |
| 104083 | + pStr1, 0); | |
| 103765 | 104084 | idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); |
| 103766 | 104085 | testcase( idxNew1==0 ); |
| 103767 | 104086 | exprAnalyze(pSrc, pWC, idxNew1); |
| 104087 | + pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); | |
| 103768 | 104088 | pNewExpr2 = sqlite3PExpr(pParse, TK_LT, |
| 103769 | - sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl), | |
| 103770 | - pStr2, 0); | |
| 104089 | + sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName), | |
| 104090 | + pStr2, 0); | |
| 103771 | 104091 | idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); |
| 103772 | 104092 | testcase( idxNew2==0 ); |
| 103773 | 104093 | exprAnalyze(pSrc, pWC, idxNew2); |
| 103774 | 104094 | pTerm = &pWC->a[idxTerm]; |
| 103775 | 104095 | if( isComplete ){ |
| @@ -103883,16 +104203,16 @@ | ||
| 103883 | 104203 | ){ |
| 103884 | 104204 | int i; |
| 103885 | 104205 | const char *zColl = pIdx->azColl[iCol]; |
| 103886 | 104206 | |
| 103887 | 104207 | for(i=0; i<pList->nExpr; i++){ |
| 103888 | - Expr *p = pList->a[i].pExpr; | |
| 104208 | + Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); | |
| 103889 | 104209 | if( p->op==TK_COLUMN |
| 103890 | 104210 | && p->iColumn==pIdx->aiColumn[iCol] |
| 103891 | 104211 | && p->iTable==iBase |
| 103892 | 104212 | ){ |
| 103893 | - CollSeq *pColl = sqlite3ExprCollSeq(pParse, p); | |
| 104213 | + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); | |
| 103894 | 104214 | if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ |
| 103895 | 104215 | return i; |
| 103896 | 104216 | } |
| 103897 | 104217 | } |
| 103898 | 104218 | } |
| @@ -103935,11 +104255,11 @@ | ||
| 103935 | 104255 | ** matching "col=X" expression and the column is on the same table as pIdx, |
| 103936 | 104256 | ** set the corresponding bit in variable mask. |
| 103937 | 104257 | */ |
| 103938 | 104258 | for(i=0; i<pDistinct->nExpr; i++){ |
| 103939 | 104259 | WhereTerm *pTerm; |
| 103940 | - Expr *p = pDistinct->a[i].pExpr; | |
| 104260 | + Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); | |
| 103941 | 104261 | if( p->op!=TK_COLUMN ) return 0; |
| 103942 | 104262 | pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0); |
| 103943 | 104263 | if( pTerm ){ |
| 103944 | 104264 | Expr *pX = pTerm->pExpr; |
| 103945 | 104265 | CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| @@ -103987,11 +104307,11 @@ | ||
| 103987 | 104307 | /* If any of the expressions is an IPK column on table iBase, then return |
| 103988 | 104308 | ** true. Note: The (p->iTable==iBase) part of this test may be false if the |
| 103989 | 104309 | ** current SELECT is a correlated sub-query. |
| 103990 | 104310 | */ |
| 103991 | 104311 | for(i=0; i<pDistinct->nExpr; i++){ |
| 103992 | - Expr *p = pDistinct->a[i].pExpr; | |
| 104312 | + Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); | |
| 103993 | 104313 | if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; |
| 103994 | 104314 | } |
| 103995 | 104315 | |
| 103996 | 104316 | /* Loop through all indices on the table, checking each to see if it makes |
| 103997 | 104317 | ** the DISTINCT qualifier redundant. It does so if: |
| @@ -104464,11 +104784,11 @@ | ||
| 104464 | 104784 | for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104465 | 104785 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104466 | 104786 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104467 | 104787 | testcase( pTerm->eOperator==WO_IN ); |
| 104468 | 104788 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104469 | - if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; | |
| 104789 | + if( pTerm->eOperator & (WO_ISNULL) ) continue; | |
| 104470 | 104790 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104471 | 104791 | nTerm++; |
| 104472 | 104792 | } |
| 104473 | 104793 | |
| 104474 | 104794 | /* If the ORDER BY clause contains only columns in the current |
| @@ -104512,29 +104832,32 @@ | ||
| 104512 | 104832 | *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; |
| 104513 | 104833 | *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = |
| 104514 | 104834 | pUsage; |
| 104515 | 104835 | |
| 104516 | 104836 | for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104837 | + u8 op; | |
| 104517 | 104838 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104518 | 104839 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104519 | 104840 | testcase( pTerm->eOperator==WO_IN ); |
| 104520 | 104841 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104521 | - if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; | |
| 104842 | + if( pTerm->eOperator & (WO_ISNULL) ) continue; | |
| 104522 | 104843 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104523 | 104844 | pIdxCons[j].iColumn = pTerm->u.leftColumn; |
| 104524 | 104845 | pIdxCons[j].iTermOffset = i; |
| 104525 | - pIdxCons[j].op = (u8)pTerm->eOperator; | |
| 104846 | + op = (u8)pTerm->eOperator; | |
| 104847 | + if( op==WO_IN ) op = WO_EQ; | |
| 104848 | + pIdxCons[j].op = op; | |
| 104526 | 104849 | /* The direct assignment in the previous line is possible only because |
| 104527 | 104850 | ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The |
| 104528 | 104851 | ** following asserts verify this fact. */ |
| 104529 | 104852 | assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); |
| 104530 | 104853 | assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); |
| 104531 | 104854 | assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); |
| 104532 | 104855 | assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); |
| 104533 | 104856 | assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); |
| 104534 | 104857 | assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); |
| 104535 | - assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); | |
| 104858 | + assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); | |
| 104536 | 104859 | j++; |
| 104537 | 104860 | } |
| 104538 | 104861 | for(i=0; i<nOrderBy; i++){ |
| 104539 | 104862 | Expr *pExpr = pOrderBy->a[i].pExpr; |
| 104540 | 104863 | pIdxOrderBy[i].iColumn = pExpr->iColumn; |
| @@ -104616,10 +104939,11 @@ | ||
| 104616 | 104939 | struct sqlite3_index_constraint *pIdxCons; |
| 104617 | 104940 | struct sqlite3_index_constraint_usage *pUsage; |
| 104618 | 104941 | WhereTerm *pTerm; |
| 104619 | 104942 | int i, j; |
| 104620 | 104943 | int nOrderBy; |
| 104944 | + int bAllowIN; /* Allow IN optimizations */ | |
| 104621 | 104945 | double rCost; |
| 104622 | 104946 | |
| 104623 | 104947 | /* Make sure wsFlags is initialized to some sane value. Otherwise, if the |
| 104624 | 104948 | ** malloc in allocateIndexInfo() fails and this function returns leaving |
| 104625 | 104949 | ** wsFlags in an uninitialized state, the caller may behave unpredictably. |
| @@ -104650,63 +104974,91 @@ | ||
| 104650 | 104974 | ** sqlite3ViewGetColumnNames() would have picked up the error. |
| 104651 | 104975 | */ |
| 104652 | 104976 | assert( pTab->azModuleArg && pTab->azModuleArg[0] ); |
| 104653 | 104977 | assert( sqlite3GetVTable(pParse->db, pTab) ); |
| 104654 | 104978 | |
| 104655 | - /* Set the aConstraint[].usable fields and initialize all | |
| 104656 | - ** output variables to zero. | |
| 104657 | - ** | |
| 104658 | - ** aConstraint[].usable is true for constraints where the right-hand | |
| 104659 | - ** side contains only references to tables to the left of the current | |
| 104660 | - ** table. In other words, if the constraint is of the form: | |
| 104661 | - ** | |
| 104662 | - ** column = expr | |
| 104663 | - ** | |
| 104664 | - ** and we are evaluating a join, then the constraint on column is | |
| 104665 | - ** only valid if all tables referenced in expr occur to the left | |
| 104666 | - ** of the table containing column. | |
| 104667 | - ** | |
| 104668 | - ** The aConstraints[] array contains entries for all constraints | |
| 104669 | - ** on the current table. That way we only have to compute it once | |
| 104670 | - ** even though we might try to pick the best index multiple times. | |
| 104671 | - ** For each attempt at picking an index, the order of tables in the | |
| 104672 | - ** join might be different so we have to recompute the usable flag | |
| 104673 | - ** each time. | |
| 104674 | - */ | |
| 104675 | - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; | |
| 104676 | - pUsage = pIdxInfo->aConstraintUsage; | |
| 104677 | - for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ | |
| 104678 | - j = pIdxCons->iTermOffset; | |
| 104679 | - pTerm = &pWC->a[j]; | |
| 104680 | - pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1; | |
| 104681 | - } | |
| 104682 | - memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); | |
| 104683 | - if( pIdxInfo->needToFreeIdxStr ){ | |
| 104684 | - sqlite3_free(pIdxInfo->idxStr); | |
| 104685 | - } | |
| 104686 | - pIdxInfo->idxStr = 0; | |
| 104687 | - pIdxInfo->idxNum = 0; | |
| 104688 | - pIdxInfo->needToFreeIdxStr = 0; | |
| 104689 | - pIdxInfo->orderByConsumed = 0; | |
| 104690 | - /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ | |
| 104691 | - pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); | |
| 104692 | - nOrderBy = pIdxInfo->nOrderBy; | |
| 104693 | - if( !p->pOrderBy ){ | |
| 104694 | - pIdxInfo->nOrderBy = 0; | |
| 104695 | - } | |
| 104696 | - | |
| 104697 | - if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ | |
| 104698 | - return; | |
| 104699 | - } | |
| 104700 | - | |
| 104701 | - pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; | |
| 104702 | - for(i=0; i<pIdxInfo->nConstraint; i++){ | |
| 104703 | - if( pUsage[i].argvIndex>0 ){ | |
| 104704 | - p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight; | |
| 104705 | - } | |
| 104706 | - } | |
| 104707 | - | |
| 104979 | + /* Try once or twice. On the first attempt, allow IN optimizations. | |
| 104980 | + ** If an IN optimization is accepted by the virtual table xBestIndex | |
| 104981 | + ** method, but the pInfo->aConstrainUsage.omit flag is not set, then | |
| 104982 | + ** the query will not work because it might allow duplicate rows in | |
| 104983 | + ** output. In that case, run the xBestIndex method a second time | |
| 104984 | + ** without the IN constraints. Usually this loop only runs once. | |
| 104985 | + ** The loop will exit using a "break" statement. | |
| 104986 | + */ | |
| 104987 | + for(bAllowIN=1; 1; bAllowIN--){ | |
| 104988 | + assert( bAllowIN==0 || bAllowIN==1 ); | |
| 104989 | + | |
| 104990 | + /* Set the aConstraint[].usable fields and initialize all | |
| 104991 | + ** output variables to zero. | |
| 104992 | + ** | |
| 104993 | + ** aConstraint[].usable is true for constraints where the right-hand | |
| 104994 | + ** side contains only references to tables to the left of the current | |
| 104995 | + ** table. In other words, if the constraint is of the form: | |
| 104996 | + ** | |
| 104997 | + ** column = expr | |
| 104998 | + ** | |
| 104999 | + ** and we are evaluating a join, then the constraint on column is | |
| 105000 | + ** only valid if all tables referenced in expr occur to the left | |
| 105001 | + ** of the table containing column. | |
| 105002 | + ** | |
| 105003 | + ** The aConstraints[] array contains entries for all constraints | |
| 105004 | + ** on the current table. That way we only have to compute it once | |
| 105005 | + ** even though we might try to pick the best index multiple times. | |
| 105006 | + ** For each attempt at picking an index, the order of tables in the | |
| 105007 | + ** join might be different so we have to recompute the usable flag | |
| 105008 | + ** each time. | |
| 105009 | + */ | |
| 105010 | + pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; | |
| 105011 | + pUsage = pIdxInfo->aConstraintUsage; | |
| 105012 | + for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ | |
| 105013 | + j = pIdxCons->iTermOffset; | |
| 105014 | + pTerm = &pWC->a[j]; | |
| 105015 | + if( (pTerm->prereqRight&p->notReady)==0 | |
| 105016 | + && (bAllowIN || pTerm->eOperator!=WO_IN) | |
| 105017 | + ){ | |
| 105018 | + pIdxCons->usable = 1; | |
| 105019 | + }else{ | |
| 105020 | + pIdxCons->usable = 0; | |
| 105021 | + } | |
| 105022 | + } | |
| 105023 | + memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); | |
| 105024 | + if( pIdxInfo->needToFreeIdxStr ){ | |
| 105025 | + sqlite3_free(pIdxInfo->idxStr); | |
| 105026 | + } | |
| 105027 | + pIdxInfo->idxStr = 0; | |
| 105028 | + pIdxInfo->idxNum = 0; | |
| 105029 | + pIdxInfo->needToFreeIdxStr = 0; | |
| 105030 | + pIdxInfo->orderByConsumed = 0; | |
| 105031 | + /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ | |
| 105032 | + pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); | |
| 105033 | + nOrderBy = pIdxInfo->nOrderBy; | |
| 105034 | + if( !p->pOrderBy ){ | |
| 105035 | + pIdxInfo->nOrderBy = 0; | |
| 105036 | + } | |
| 105037 | + | |
| 105038 | + if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ | |
| 105039 | + return; | |
| 105040 | + } | |
| 105041 | + | |
| 105042 | + pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; | |
| 105043 | + for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ | |
| 105044 | + if( pUsage[i].argvIndex>0 ){ | |
| 105045 | + j = pIdxCons->iTermOffset; | |
| 105046 | + pTerm = &pWC->a[j]; | |
| 105047 | + p->cost.used |= pTerm->prereqRight; | |
| 105048 | + if( pTerm->eOperator==WO_IN && pUsage[i].omit==0 ){ | |
| 105049 | + /* Do not attempt to use an IN constraint if the virtual table | |
| 105050 | + ** says that the equivalent EQ constraint cannot be safely omitted. | |
| 105051 | + ** If we do attempt to use such a constraint, some rows might be | |
| 105052 | + ** repeated in the output. */ | |
| 105053 | + break; | |
| 105054 | + } | |
| 105055 | + } | |
| 105056 | + } | |
| 105057 | + if( i>=pIdxInfo->nConstraint ) break; | |
| 105058 | + } | |
| 105059 | + | |
| 104708 | 105060 | /* If there is an ORDER BY clause, and the selected virtual table index |
| 104709 | 105061 | ** does not satisfy it, increase the cost of the scan accordingly. This |
| 104710 | 105062 | ** matches the processing for non-virtual tables in bestBtreeIndex(). |
| 104711 | 105063 | */ |
| 104712 | 105064 | rCost = pIdxInfo->estimatedCost; |
| @@ -105273,11 +105625,11 @@ | ||
| 105273 | 105625 | WhereTerm *pConstraint; /* A constraint in the WHERE clause */ |
| 105274 | 105626 | |
| 105275 | 105627 | /* If the next term of the ORDER BY clause refers to anything other than |
| 105276 | 105628 | ** a column in the "base" table, then this index will not be of any |
| 105277 | 105629 | ** further use in handling the ORDER BY. */ |
| 105278 | - pOBExpr = pOBItem->pExpr; | |
| 105630 | + pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr); | |
| 105279 | 105631 | if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){ |
| 105280 | 105632 | break; |
| 105281 | 105633 | } |
| 105282 | 105634 | |
| 105283 | 105635 | /* Find column number and collating sequence for the next entry |
| @@ -105299,11 +105651,11 @@ | ||
| 105299 | 105651 | /* Check to see if the column number and collating sequence of the |
| 105300 | 105652 | ** index match the column number and collating sequence of the ORDER BY |
| 105301 | 105653 | ** clause entry. Set isMatch to 1 if they both match. */ |
| 105302 | 105654 | if( pOBExpr->iColumn==iColumn ){ |
| 105303 | 105655 | if( zColl ){ |
| 105304 | - pColl = sqlite3ExprCollSeq(pParse, pOBExpr); | |
| 105656 | + pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr); | |
| 105305 | 105657 | if( !pColl ) pColl = db->pDfltColl; |
| 105306 | 105658 | isMatch = sqlite3StrICmp(pColl->zName, zColl)==0; |
| 105307 | 105659 | }else{ |
| 105308 | 105660 | isMatch = 1; |
| 105309 | 105661 | } |
| @@ -105440,10 +105792,15 @@ | ||
| 105440 | 105792 | int idxEqTermMask; /* Index mask of valid equality operators */ |
| 105441 | 105793 | Index sPk; /* A fake index object for the primary key */ |
| 105442 | 105794 | tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ |
| 105443 | 105795 | int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ |
| 105444 | 105796 | int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */ |
| 105797 | + int nPriorSat; /* ORDER BY terms satisfied by outer loops */ | |
| 105798 | + int nOrderBy; /* Number of ORDER BY terms */ | |
| 105799 | + char bSortInit; /* Initializer for bSort in inner loop */ | |
| 105800 | + char bDistInit; /* Initializer for bDist in inner loop */ | |
| 105801 | + | |
| 105445 | 105802 | |
| 105446 | 105803 | /* Initialize the cost to a worst-case value */ |
| 105447 | 105804 | memset(&p->cost, 0, sizeof(p->cost)); |
| 105448 | 105805 | p->cost.rCost = SQLITE_BIG_DBL; |
| 105449 | 105806 | |
| @@ -105488,10 +105845,21 @@ | ||
| 105488 | 105845 | WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE |
| 105489 | 105846 | ); |
| 105490 | 105847 | eqTermMask = WO_EQ|WO_IN; |
| 105491 | 105848 | pIdx = 0; |
| 105492 | 105849 | } |
| 105850 | + | |
| 105851 | + nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; | |
| 105852 | + if( p->i ){ | |
| 105853 | + nPriorSat = p->aLevel[p->i-1].plan.nOBSat; | |
| 105854 | + bSortInit = nPriorSat<nOrderBy; | |
| 105855 | + bDistInit = 0; | |
| 105856 | + }else{ | |
| 105857 | + nPriorSat = 0; | |
| 105858 | + bSortInit = nOrderBy>0; | |
| 105859 | + bDistInit = p->pDistinct!=0; | |
| 105860 | + } | |
| 105493 | 105861 | |
| 105494 | 105862 | /* Loop over all indices looking for the best one to use |
| 105495 | 105863 | */ |
| 105496 | 105864 | for(; pProbe; pIdx=pProbe=pProbe->pNext){ |
| 105497 | 105865 | const tRowcnt * const aiRowEst = pProbe->aiRowEst; |
| @@ -105566,15 +105934,13 @@ | ||
| 105566 | 105934 | */ |
| 105567 | 105935 | int bInEst = 0; /* True if "x IN (SELECT...)" seen */ |
| 105568 | 105936 | int nInMul = 1; /* Number of distinct equalities to lookup */ |
| 105569 | 105937 | double rangeDiv = (double)1; /* Estimated reduction in search space */ |
| 105570 | 105938 | int nBound = 0; /* Number of range constraints seen */ |
| 105571 | - int bSort; /* True if external sort required */ | |
| 105572 | - int bDist; /* True if index cannot help with DISTINCT */ | |
| 105573 | - int bLookup = 0; /* True if not a covering index */ | |
| 105574 | - int nPriorSat; /* ORDER BY terms satisfied by outer loops */ | |
| 105575 | - int nOrderBy; /* Number of ORDER BY terms */ | |
| 105939 | + char bSort = bSortInit; /* True if external sort required */ | |
| 105940 | + char bDist = bDistInit; /* True if index cannot help with DISTINCT */ | |
| 105941 | + char bLookup = 0; /* True if not a covering index */ | |
| 105576 | 105942 | WhereTerm *pTerm; /* A single term of the WHERE clause */ |
| 105577 | 105943 | #ifdef SQLITE_ENABLE_STAT3 |
| 105578 | 105944 | WhereTerm *pFirstTerm = 0; /* First term matching the index */ |
| 105579 | 105945 | #endif |
| 105580 | 105946 | |
| @@ -105581,20 +105947,11 @@ | ||
| 105581 | 105947 | WHERETRACE(( |
| 105582 | 105948 | " %s(%s):\n", |
| 105583 | 105949 | pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk") |
| 105584 | 105950 | )); |
| 105585 | 105951 | memset(&pc, 0, sizeof(pc)); |
| 105586 | - nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; | |
| 105587 | - if( p->i ){ | |
| 105588 | - nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat; | |
| 105589 | - bSort = nPriorSat<nOrderBy; | |
| 105590 | - bDist = 0; | |
| 105591 | - }else{ | |
| 105592 | - nPriorSat = pc.plan.nOBSat = 0; | |
| 105593 | - bSort = nOrderBy>0; | |
| 105594 | - bDist = p->pDistinct!=0; | |
| 105595 | - } | |
| 105952 | + pc.plan.nOBSat = nPriorSat; | |
| 105596 | 105953 | |
| 105597 | 105954 | /* Determine the values of pc.plan.nEq and nInMul */ |
| 105598 | 105955 | for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){ |
| 105599 | 105956 | int j = pProbe->aiColumn[pc.plan.nEq]; |
| 105600 | 105957 | pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); |
| @@ -106466,32 +106823,40 @@ | ||
| 106466 | 106823 | if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ |
| 106467 | 106824 | /* Case 0: The table is a virtual-table. Use the VFilter and VNext |
| 106468 | 106825 | ** to access the data. |
| 106469 | 106826 | */ |
| 106470 | 106827 | int iReg; /* P3 Value for OP_VFilter */ |
| 106828 | + int addrNotFound; | |
| 106471 | 106829 | sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; |
| 106472 | 106830 | int nConstraint = pVtabIdx->nConstraint; |
| 106473 | 106831 | struct sqlite3_index_constraint_usage *aUsage = |
| 106474 | 106832 | pVtabIdx->aConstraintUsage; |
| 106475 | 106833 | const struct sqlite3_index_constraint *aConstraint = |
| 106476 | 106834 | pVtabIdx->aConstraint; |
| 106477 | 106835 | |
| 106478 | 106836 | sqlite3ExprCachePush(pParse); |
| 106479 | 106837 | iReg = sqlite3GetTempRange(pParse, nConstraint+2); |
| 106838 | + addrNotFound = pLevel->addrBrk; | |
| 106480 | 106839 | for(j=1; j<=nConstraint; j++){ |
| 106481 | 106840 | for(k=0; k<nConstraint; k++){ |
| 106482 | 106841 | if( aUsage[k].argvIndex==j ){ |
| 106483 | - int iTerm = aConstraint[k].iTermOffset; | |
| 106484 | - sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1); | |
| 106842 | + WhereTerm *pTerm = &pWC->a[aConstraint[k].iTermOffset]; | |
| 106843 | + int iTarget = iReg+j+1; | |
| 106844 | + if( pTerm->eOperator & WO_IN ){ | |
| 106845 | + codeEqualityTerm(pParse, pTerm, pLevel, iTarget); | |
| 106846 | + addrNotFound = pLevel->addrNxt; | |
| 106847 | + }else{ | |
| 106848 | + sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget); | |
| 106849 | + } | |
| 106485 | 106850 | break; |
| 106486 | 106851 | } |
| 106487 | 106852 | } |
| 106488 | 106853 | if( k==nConstraint ) break; |
| 106489 | 106854 | } |
| 106490 | 106855 | sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); |
| 106491 | 106856 | sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); |
| 106492 | - sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr, | |
| 106857 | + sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr, | |
| 106493 | 106858 | pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); |
| 106494 | 106859 | pVtabIdx->needToFreeIdxStr = 0; |
| 106495 | 106860 | for(j=0; j<nConstraint; j++){ |
| 106496 | 106861 | if( aUsage[j].omit ){ |
| 106497 | 106862 | int iTerm = aConstraint[j].iTermOffset; |
| @@ -108134,10 +108499,11 @@ | ||
| 108134 | 108499 | Expr* yy122; |
| 108135 | 108500 | Select* yy159; |
| 108136 | 108501 | IdList* yy180; |
| 108137 | 108502 | struct {int value; int mask;} yy207; |
| 108138 | 108503 | u8 yy258; |
| 108504 | + u16 yy305; | |
| 108139 | 108505 | struct LikeOp yy318; |
| 108140 | 108506 | TriggerStep* yy327; |
| 108141 | 108507 | ExprSpan yy342; |
| 108142 | 108508 | SrcList* yy347; |
| 108143 | 108509 | int yy392; |
| @@ -110084,22 +110450,19 @@ | ||
| 110084 | 110450 | case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); |
| 110085 | 110451 | case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); |
| 110086 | 110452 | case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); |
| 110087 | 110453 | case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98); |
| 110088 | 110454 | case 109: /* ifexists ::= */ yytestcase(yyruleno==109); |
| 110089 | - case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120); | |
| 110090 | - case 121: /* distinct ::= */ yytestcase(yyruleno==121); | |
| 110091 | 110455 | case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); |
| 110092 | 110456 | case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); |
| 110093 | 110457 | {yygotominor.yy392 = 0;} |
| 110094 | 110458 | break; |
| 110095 | 110459 | case 29: /* ifnotexists ::= IF NOT EXISTS */ |
| 110096 | 110460 | case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); |
| 110097 | 110461 | case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); |
| 110098 | 110462 | case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); |
| 110099 | 110463 | case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108); |
| 110100 | - case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119); | |
| 110101 | 110464 | case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); |
| 110102 | 110465 | case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); |
| 110103 | 110466 | {yygotominor.yy392 = 1;} |
| 110104 | 110467 | break; |
| 110105 | 110468 | case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ |
| @@ -110335,12 +110698,19 @@ | ||
| 110335 | 110698 | case 116: /* multiselect_op ::= UNION ALL */ |
| 110336 | 110699 | {yygotominor.yy392 = TK_ALL;} |
| 110337 | 110700 | break; |
| 110338 | 110701 | case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ |
| 110339 | 110702 | { |
| 110340 | - yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); | |
| 110703 | + yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); | |
| 110341 | 110704 | } |
| 110705 | + break; | |
| 110706 | + case 119: /* distinct ::= DISTINCT */ | |
| 110707 | +{yygotominor.yy305 = SF_Distinct;} | |
| 110708 | + break; | |
| 110709 | + case 120: /* distinct ::= ALL */ | |
| 110710 | + case 121: /* distinct ::= */ yytestcase(yyruleno==121); | |
| 110711 | +{yygotominor.yy305 = 0;} | |
| 110342 | 110712 | break; |
| 110343 | 110713 | case 122: /* sclp ::= selcollist COMMA */ |
| 110344 | 110714 | case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246); |
| 110345 | 110715 | {yygotominor.yy442 = yymsp[-1].minor.yy442;} |
| 110346 | 110716 | break; |
| @@ -110406,14 +110776,24 @@ | ||
| 110406 | 110776 | break; |
| 110407 | 110777 | case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ |
| 110408 | 110778 | { |
| 110409 | 110779 | if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ |
| 110410 | 110780 | yygotominor.yy347 = yymsp[-4].minor.yy347; |
| 110781 | + }else if( yymsp[-4].minor.yy347->nSrc==1 ){ | |
| 110782 | + yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); | |
| 110783 | + if( yygotominor.yy347 ){ | |
| 110784 | + struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1]; | |
| 110785 | + struct SrcList_item *pOld = yymsp[-4].minor.yy347->a; | |
| 110786 | + pNew->zName = pOld->zName; | |
| 110787 | + pNew->zDatabase = pOld->zDatabase; | |
| 110788 | + pOld->zName = pOld->zDatabase = 0; | |
| 110789 | + } | |
| 110790 | + sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347); | |
| 110411 | 110791 | }else{ |
| 110412 | 110792 | Select *pSubquery; |
| 110413 | 110793 | sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); |
| 110414 | - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0); | |
| 110794 | + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0); | |
| 110415 | 110795 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); |
| 110416 | 110796 | } |
| 110417 | 110797 | } |
| 110418 | 110798 | break; |
| 110419 | 110799 | case 137: /* dbnm ::= */ |
| @@ -110624,11 +111004,11 @@ | ||
| 110624 | 111004 | spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); |
| 110625 | 111005 | } |
| 110626 | 111006 | break; |
| 110627 | 111007 | case 194: /* expr ::= expr COLLATE ids */ |
| 110628 | 111008 | { |
| 110629 | - yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); | |
| 111009 | + yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); | |
| 110630 | 111010 | yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; |
| 110631 | 111011 | yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 110632 | 111012 | } |
| 110633 | 111013 | break; |
| 110634 | 111014 | case 195: /* expr ::= CAST LP expr AS typetoken RP */ |
| @@ -110642,11 +111022,11 @@ | ||
| 110642 | 111022 | if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ |
| 110643 | 111023 | sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); |
| 110644 | 111024 | } |
| 110645 | 111025 | yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); |
| 110646 | 111026 | spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); |
| 110647 | - if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){ | |
| 111027 | + if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){ | |
| 110648 | 111028 | yygotominor.yy342.pExpr->flags |= EP_Distinct; |
| 110649 | 111029 | } |
| 110650 | 111030 | } |
| 110651 | 111031 | break; |
| 110652 | 111032 | case 197: /* expr ::= ID LP STAR RP */ |
| @@ -110883,28 +111263,20 @@ | ||
| 110883 | 111263 | case 244: /* uniqueflag ::= */ |
| 110884 | 111264 | {yygotominor.yy392 = OE_None;} |
| 110885 | 111265 | break; |
| 110886 | 111266 | case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */ |
| 110887 | 111267 | { |
| 110888 | - Expr *p = 0; | |
| 110889 | - if( yymsp[-1].minor.yy0.n>0 ){ | |
| 110890 | - p = sqlite3Expr(pParse->db, TK_COLUMN, 0); | |
| 110891 | - sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); | |
| 110892 | - } | |
| 111268 | + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); | |
| 110893 | 111269 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p); |
| 110894 | 111270 | sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1); |
| 110895 | 111271 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 110896 | 111272 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 110897 | 111273 | } |
| 110898 | 111274 | break; |
| 110899 | 111275 | case 248: /* idxlist ::= nm collate sortorder */ |
| 110900 | 111276 | { |
| 110901 | - Expr *p = 0; | |
| 110902 | - if( yymsp[-1].minor.yy0.n>0 ){ | |
| 110903 | - p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); | |
| 110904 | - sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); | |
| 110905 | - } | |
| 111277 | + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); | |
| 110906 | 111278 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p); |
| 110907 | 111279 | sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); |
| 110908 | 111280 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 110909 | 111281 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 110910 | 111282 | } |
| @@ -141105,10 +141477,11 @@ | ||
| 141105 | 141477 | extern int Sqlitemultiplex_Init(Tcl_Interp*); |
| 141106 | 141478 | extern int SqliteSuperlock_Init(Tcl_Interp*); |
| 141107 | 141479 | extern int SqlitetestSyscall_Init(Tcl_Interp*); |
| 141108 | 141480 | extern int Sqlitetestfuzzer_Init(Tcl_Interp*); |
| 141109 | 141481 | extern int Sqlitetestwholenumber_Init(Tcl_Interp*); |
| 141482 | + extern int Sqlitetestregexp_Init(Tcl_Interp*); | |
| 141110 | 141483 | |
| 141111 | 141484 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141112 | 141485 | extern int Sqlitetestfts3_Init(Tcl_Interp *interp); |
| 141113 | 141486 | #endif |
| 141114 | 141487 | |
| @@ -141148,10 +141521,11 @@ | ||
| 141148 | 141521 | Sqlitemultiplex_Init(interp); |
| 141149 | 141522 | SqliteSuperlock_Init(interp); |
| 141150 | 141523 | SqlitetestSyscall_Init(interp); |
| 141151 | 141524 | Sqlitetestfuzzer_Init(interp); |
| 141152 | 141525 | Sqlitetestwholenumber_Init(interp); |
| 141526 | + Sqlitetestregexp_Init(interp); | |
| 141153 | 141527 | |
| 141154 | 141528 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141155 | 141529 | Sqlitetestfts3_Init(interp); |
| 141156 | 141530 | #endif |
| 141157 | 141531 | |
| 141158 | 141532 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.7.15. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -671,13 +671,13 @@ | |
| 671 | ** |
| 672 | ** See also: [sqlite3_libversion()], |
| 673 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 674 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 675 | */ |
| 676 | #define SQLITE_VERSION "3.7.15" |
| 677 | #define SQLITE_VERSION_NUMBER 3007015 |
| 678 | #define SQLITE_SOURCE_ID "2012-10-16 23:08:28 f021559d8a23934e3bdccad5b55fc7a91d185f53" |
| 679 | |
| 680 | /* |
| 681 | ** CAPI3REF: Run-Time Library Version Numbers |
| 682 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 683 | ** |
| @@ -2162,11 +2162,11 @@ | |
| 2162 | ** database connection is opened. By default, URI handling is globally |
| 2163 | ** disabled. The default value may be changed by compiling with the |
| 2164 | ** [SQLITE_USE_URI] symbol defined. |
| 2165 | ** |
| 2166 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 2167 | ** <dd> This option taks a single integer argument which is interpreted as |
| 2168 | ** a boolean in order to enable or disable the use of covering indices for |
| 2169 | ** full table scans in the query optimizer. The default setting is determined |
| 2170 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 2171 | ** if that compile-time option is omitted. |
| 2172 | ** The ability to disable the use of covering indices for full table scans |
| @@ -10573,24 +10573,24 @@ | |
| 10573 | ** and the value of Index.onError indicate the which conflict resolution |
| 10574 | ** algorithm to employ whenever an attempt is made to insert a non-unique |
| 10575 | ** element. |
| 10576 | */ |
| 10577 | struct Index { |
| 10578 | char *zName; /* Name of this index */ |
| 10579 | int *aiColumn; /* Which columns are used by this index. 1st is 0 */ |
| 10580 | tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ |
| 10581 | Table *pTable; /* The SQL table being indexed */ |
| 10582 | char *zColAff; /* String defining the affinity of each column */ |
| 10583 | Index *pNext; /* The next index associated with the same table */ |
| 10584 | Schema *pSchema; /* Schema containing this index */ |
| 10585 | u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ |
| 10586 | char **azColl; /* Array of collation sequence names for index */ |
| 10587 | int nColumn; /* Number of columns in the table used by this index */ |
| 10588 | int tnum; /* Page containing root of this index in database file */ |
| 10589 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| 10590 | u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ |
| 10591 | u8 bUnordered; /* Use this index for == or IN queries only */ |
| 10592 | #ifdef SQLITE_ENABLE_STAT3 |
| 10593 | int nSample; /* Number of elements in aSample[] */ |
| 10594 | tRowcnt avgEq; /* Average nEq value for key values not in aSample */ |
| 10595 | IndexSample *aSample; /* Samples of the left-most key */ |
| 10596 | #endif |
| @@ -10767,11 +10767,10 @@ | |
| 10767 | Expr *pRight; /* Right subnode */ |
| 10768 | union { |
| 10769 | ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */ |
| 10770 | Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */ |
| 10771 | } x; |
| 10772 | CollSeq *pColl; /* The collation type of the column or 0 */ |
| 10773 | |
| 10774 | /* If the EP_Reduced flag is set in the Expr.flags mask, then no |
| 10775 | ** space is allocated for the fields below this point. An attempt to |
| 10776 | ** access them will result in a segfault or malfunction. |
| 10777 | *********************************************************************/ |
| @@ -10803,11 +10802,11 @@ | |
| 10803 | #define EP_Error 0x0008 /* Expression contains one or more errors */ |
| 10804 | #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ |
| 10805 | #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ |
| 10806 | #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ |
| 10807 | #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ |
| 10808 | #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ |
| 10809 | #define EP_FixedDest 0x0200 /* Result needed in a specific register */ |
| 10810 | #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */ |
| 10811 | #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */ |
| 10812 | #define EP_Hint 0x1000 /* Not used */ |
| 10813 | #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ |
| @@ -10861,22 +10860,31 @@ | |
| 10861 | ** name. An expr/name combination can be used in several ways, such |
| 10862 | ** as the list of "expr AS ID" fields following a "SELECT" or in the |
| 10863 | ** list of "ID = expr" items in an UPDATE. A list of expressions can |
| 10864 | ** also be used as the argument to a function, in which case the a.zName |
| 10865 | ** field is not used. |
| 10866 | */ |
| 10867 | struct ExprList { |
| 10868 | int nExpr; /* Number of expressions on the list */ |
| 10869 | int iECursor; /* VDBE Cursor associated with this ExprList */ |
| 10870 | struct ExprList_item { /* For each expression in the list */ |
| 10871 | Expr *pExpr; /* The list of expressions */ |
| 10872 | char *zName; /* Token associated with this expression */ |
| 10873 | char *zSpan; /* Original text of the expression */ |
| 10874 | u8 sortOrder; /* 1 for DESC or 0 for ASC */ |
| 10875 | u8 done; /* A flag to indicate when processing is finished */ |
| 10876 | u16 iOrderByCol; /* For ORDER BY, column number in result set */ |
| 10877 | u16 iAlias; /* Index into Parse.aAlias[] for zName */ |
| 10878 | } *a; /* Alloc a power of two greater or equal to nExpr */ |
| 10879 | }; |
| 10880 | |
| 10881 | /* |
| 10882 | ** An instance of this structure is used by the parser to record both |
| @@ -11192,10 +11200,11 @@ | |
| 11192 | #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ |
| 11193 | #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ |
| 11194 | #define SF_UseSorter 0x0040 /* Sort using a sorter */ |
| 11195 | #define SF_Values 0x0080 /* Synthesized from VALUES clause */ |
| 11196 | #define SF_Materialize 0x0100 /* Force materialization of views */ |
| 11197 | |
| 11198 | |
| 11199 | /* |
| 11200 | ** The results of a select can be distributed in several ways. The |
| 11201 | ** "SRT" prefix means "SELECT Result Type". |
| @@ -11420,10 +11429,11 @@ | |
| 11420 | #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ |
| 11421 | #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ |
| 11422 | #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ |
| 11423 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ |
| 11424 | #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ |
| 11425 | |
| 11426 | /* |
| 11427 | * Each trigger present in the database schema is stored as an instance of |
| 11428 | * struct Trigger. |
| 11429 | * |
| @@ -11904,11 +11914,11 @@ | |
| 11904 | SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, |
| 11905 | Token*, int, int); |
| 11906 | SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); |
| 11907 | SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); |
| 11908 | SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, |
| 11909 | Expr*,ExprList*,int,Expr*,Expr*); |
| 11910 | SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); |
| 11911 | SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); |
| 11912 | SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); |
| 11913 | SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); |
| 11914 | #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) |
| @@ -12112,12 +12122,13 @@ | |
| 12112 | SQLITE_PRIVATE const char *sqlite3ErrStr(int); |
| 12113 | SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); |
| 12114 | SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); |
| 12115 | SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); |
| 12116 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); |
| 12117 | SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*); |
| 12118 | SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*); |
| 12119 | SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); |
| 12120 | SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); |
| 12121 | SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); |
| 12122 | SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); |
| 12123 | SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); |
| @@ -12160,10 +12171,11 @@ | |
| 12160 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); |
| 12161 | SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); |
| 12162 | SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); |
| 12163 | SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); |
| 12164 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); |
| 12165 | SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); |
| 12166 | SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); |
| 12167 | SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); |
| 12168 | SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); |
| 12169 | SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); |
| @@ -12298,12 +12310,14 @@ | |
| 12298 | #define sqlite3FkOldmask(a,b) 0 |
| 12299 | #define sqlite3FkRequired(a,b,c,d) 0 |
| 12300 | #endif |
| 12301 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 12302 | SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); |
| 12303 | #else |
| 12304 | #define sqlite3FkDelete(a,b) |
| 12305 | #endif |
| 12306 | |
| 12307 | |
| 12308 | /* |
| 12309 | ** Available fault injectors. Should be numbered beginning with 0. |
| @@ -23307,15 +23321,11 @@ | |
| 23307 | { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, |
| 23308 | #endif |
| 23309 | #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ |
| 23310 | aSyscall[13].pCurrent) |
| 23311 | |
| 23312 | #if SQLITE_ENABLE_LOCKING_STYLE |
| 23313 | { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, |
| 23314 | #else |
| 23315 | { "fchmod", (sqlite3_syscall_ptr)0, 0 }, |
| 23316 | #endif |
| 23317 | #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) |
| 23318 | |
| 23319 | #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE |
| 23320 | { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, |
| 23321 | #else |
| @@ -23336,13 +23346,10 @@ | |
| 23336 | #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) |
| 23337 | |
| 23338 | { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, |
| 23339 | #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) |
| 23340 | |
| 23341 | { "umask", (sqlite3_syscall_ptr)umask, 0 }, |
| 23342 | #define osUmask ((mode_t(*)(mode_t))aSyscall[21].pCurrent) |
| 23343 | |
| 23344 | }; /* End of the overrideable system calls */ |
| 23345 | |
| 23346 | /* |
| 23347 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 23348 | ** "unix" VFSes. Return SQLITE_OK opon successfully updating the |
| @@ -23443,31 +23450,29 @@ | |
| 23443 | ** process that is able to write to the database will also be able to |
| 23444 | ** recover the hot journals. |
| 23445 | */ |
| 23446 | static int robust_open(const char *z, int f, mode_t m){ |
| 23447 | int fd; |
| 23448 | mode_t m2; |
| 23449 | mode_t origM = 0; |
| 23450 | if( m==0 ){ |
| 23451 | m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; |
| 23452 | }else{ |
| 23453 | m2 = m; |
| 23454 | origM = osUmask(0); |
| 23455 | } |
| 23456 | do{ |
| 23457 | #if defined(O_CLOEXEC) |
| 23458 | fd = osOpen(z,f|O_CLOEXEC,m2); |
| 23459 | #else |
| 23460 | fd = osOpen(z,f,m2); |
| 23461 | #endif |
| 23462 | }while( fd<0 && errno==EINTR ); |
| 23463 | if( m ){ |
| 23464 | osUmask(origM); |
| 23465 | } |
| 23466 | #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) |
| 23467 | if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 23468 | #endif |
| 23469 | return fd; |
| 23470 | } |
| 23471 | |
| 23472 | /* |
| 23473 | ** Helper functions to obtain and relinquish the global mutex. The |
| @@ -29889,11 +29894,11 @@ | |
| 29889 | }; |
| 29890 | unsigned int i; /* Loop counter */ |
| 29891 | |
| 29892 | /* Double-check that the aSyscall[] array has been constructed |
| 29893 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 29894 | assert( ArraySize(aSyscall)==22 ); |
| 29895 | |
| 29896 | /* Register all VFSes defined in the aVfs[] array */ |
| 29897 | for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 29898 | sqlite3_vfs_register(&aVfs[i], i==0); |
| 29899 | } |
| @@ -56355,11 +56360,11 @@ | |
| 56355 | sqlite3BtreeLeave(p); |
| 56356 | return 0; |
| 56357 | } |
| 56358 | i = PENDING_BYTE_PAGE(pBt); |
| 56359 | if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); |
| 56360 | sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); |
| 56361 | sCheck.errMsg.useMalloc = 2; |
| 56362 | |
| 56363 | /* Check the integrity of the freelist |
| 56364 | */ |
| 56365 | checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), |
| @@ -56890,11 +56895,16 @@ | |
| 56890 | /* |
| 56891 | ** Parameter zSrcData points to a buffer containing the data for |
| 56892 | ** page iSrcPg from the source database. Copy this data into the |
| 56893 | ** destination database. |
| 56894 | */ |
| 56895 | static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){ |
| 56896 | Pager * const pDestPager = sqlite3BtreePager(p->pDest); |
| 56897 | const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); |
| 56898 | int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); |
| 56899 | const int nCopy = MIN(nSrcPgsz, nDestPgsz); |
| 56900 | const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; |
| @@ -56963,10 +56973,13 @@ | |
| 56963 | ** cached parse of the page). MemPage.isInit is marked |
| 56964 | ** "MUST BE FIRST" for this purpose. |
| 56965 | */ |
| 56966 | memcpy(zOut, zIn, nCopy); |
| 56967 | ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; |
| 56968 | } |
| 56969 | sqlite3PagerUnref(pDestPg); |
| 56970 | } |
| 56971 | |
| 56972 | return rc; |
| @@ -57069,11 +57082,11 @@ | |
| 57069 | const Pgno iSrcPg = p->iNext; /* Source page number */ |
| 57070 | if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ |
| 57071 | DbPage *pSrcPg; /* Source page object */ |
| 57072 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); |
| 57073 | if( rc==SQLITE_OK ){ |
| 57074 | rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg)); |
| 57075 | sqlite3PagerUnref(pSrcPg); |
| 57076 | } |
| 57077 | } |
| 57078 | p->iNext++; |
| 57079 | } |
| @@ -57317,11 +57330,11 @@ | |
| 57317 | ** the new data into the backup. |
| 57318 | */ |
| 57319 | int rc; |
| 57320 | assert( p->pDestDb ); |
| 57321 | sqlite3_mutex_enter(p->pDestDb->mutex); |
| 57322 | rc = backupOnePage(p, iPage, aData); |
| 57323 | sqlite3_mutex_leave(p->pDestDb->mutex); |
| 57324 | assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); |
| 57325 | if( rc!=SQLITE_OK ){ |
| 57326 | p->rc = rc; |
| 57327 | } |
| @@ -59434,26 +59447,22 @@ | |
| 59434 | assert( pKeyInfo->aSortOrder!=0 ); |
| 59435 | sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); |
| 59436 | i = sqlite3Strlen30(zTemp); |
| 59437 | for(j=0; j<pKeyInfo->nField; j++){ |
| 59438 | CollSeq *pColl = pKeyInfo->aColl[j]; |
| 59439 | if( pColl ){ |
| 59440 | int n = sqlite3Strlen30(pColl->zName); |
| 59441 | if( i+n>nTemp-6 ){ |
| 59442 | memcpy(&zTemp[i],",...",4); |
| 59443 | break; |
| 59444 | } |
| 59445 | zTemp[i++] = ','; |
| 59446 | if( pKeyInfo->aSortOrder[j] ){ |
| 59447 | zTemp[i++] = '-'; |
| 59448 | } |
| 59449 | memcpy(&zTemp[i], pColl->zName,n+1); |
| 59450 | i += n; |
| 59451 | }else if( i+4<nTemp-6 ){ |
| 59452 | memcpy(&zTemp[i],",nil",4); |
| 59453 | i += 4; |
| 59454 | } |
| 59455 | } |
| 59456 | zTemp[i++] = ')'; |
| 59457 | zTemp[i] = 0; |
| 59458 | assert( i<nTemp ); |
| 59459 | break; |
| @@ -63839,11 +63848,13 @@ | |
| 63839 | #ifdef SQLITE_DEBUG |
| 63840 | /* |
| 63841 | ** Print the value of a register for tracing purposes: |
| 63842 | */ |
| 63843 | static void memTracePrint(FILE *out, Mem *p){ |
| 63844 | if( p->flags & MEM_Null ){ |
| 63845 | fprintf(out, " NULL"); |
| 63846 | }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ |
| 63847 | fprintf(out, " si:%lld", p->u.i); |
| 63848 | }else if( p->flags & MEM_Int ){ |
| 63849 | fprintf(out, " i:%lld", p->u.i); |
| @@ -64112,10 +64123,11 @@ | |
| 64112 | } af; |
| 64113 | struct OP_Concat_stack_vars { |
| 64114 | i64 nByte; |
| 64115 | } ag; |
| 64116 | struct OP_Remainder_stack_vars { |
| 64117 | int flags; /* Combined MEM_* flags from both inputs */ |
| 64118 | i64 iA; /* Integer value of left operand */ |
| 64119 | i64 iB; /* Integer value of right operand */ |
| 64120 | double rA; /* Real value of left operand */ |
| 64121 | double rB; /* Real value of right operand */ |
| @@ -65021,10 +65033,13 @@ | |
| 65021 | pOut = &aMem[pOp->p2]; |
| 65022 | assert( pOut!=pIn1 ); |
| 65023 | while( 1 ){ |
| 65024 | sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); |
| 65025 | Deephemeralize(pOut); |
| 65026 | REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut); |
| 65027 | if( (u.ae.n--)==0 ) break; |
| 65028 | pOut++; |
| 65029 | pIn1++; |
| 65030 | } |
| @@ -65214,10 +65229,11 @@ | |
| 65214 | case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ |
| 65215 | case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ |
| 65216 | case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ |
| 65217 | case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ |
| 65218 | #if 0 /* local variables moved into u.ah */ |
| 65219 | int flags; /* Combined MEM_* flags from both inputs */ |
| 65220 | i64 iA; /* Integer value of left operand */ |
| 65221 | i64 iB; /* Integer value of right operand */ |
| 65222 | double rA; /* Real value of left operand */ |
| 65223 | double rB; /* Real value of right operand */ |
| @@ -65231,10 +65247,11 @@ | |
| 65231 | u.ah.flags = pIn1->flags | pIn2->flags; |
| 65232 | if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; |
| 65233 | if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ |
| 65234 | u.ah.iA = pIn1->u.i; |
| 65235 | u.ah.iB = pIn2->u.i; |
| 65236 | switch( pOp->opcode ){ |
| 65237 | case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65238 | case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65239 | case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65240 | case OP_Divide: { |
| @@ -65251,10 +65268,11 @@ | |
| 65251 | } |
| 65252 | } |
| 65253 | pOut->u.i = u.ah.iB; |
| 65254 | MemSetTypeFlag(pOut, MEM_Int); |
| 65255 | }else{ |
| 65256 | fp_math: |
| 65257 | u.ah.rA = sqlite3VdbeRealValue(pIn1); |
| 65258 | u.ah.rB = sqlite3VdbeRealValue(pIn2); |
| 65259 | switch( pOp->opcode ){ |
| 65260 | case OP_Add: u.ah.rB += u.ah.rA; break; |
| @@ -65282,11 +65300,11 @@ | |
| 65282 | if( sqlite3IsNaN(u.ah.rB) ){ |
| 65283 | goto arithmetic_result_is_null; |
| 65284 | } |
| 65285 | pOut->r = u.ah.rB; |
| 65286 | MemSetTypeFlag(pOut, MEM_Real); |
| 65287 | if( (u.ah.flags & MEM_Real)==0 ){ |
| 65288 | sqlite3VdbeIntegerAffinity(pOut); |
| 65289 | } |
| 65290 | #endif |
| 65291 | } |
| 65292 | break; |
| @@ -65843,26 +65861,31 @@ | |
| 65843 | /* Opcode: Permutation * * * P4 * |
| 65844 | ** |
| 65845 | ** Set the permutation used by the OP_Compare operator to be the array |
| 65846 | ** of integers in P4. |
| 65847 | ** |
| 65848 | ** The permutation is only valid until the next OP_Permutation, OP_Compare, |
| 65849 | ** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur |
| 65850 | ** immediately prior to the OP_Compare. |
| 65851 | */ |
| 65852 | case OP_Permutation: { |
| 65853 | assert( pOp->p4type==P4_INTARRAY ); |
| 65854 | assert( pOp->p4.ai ); |
| 65855 | aPermute = pOp->p4.ai; |
| 65856 | break; |
| 65857 | } |
| 65858 | |
| 65859 | /* Opcode: Compare P1 P2 P3 P4 * |
| 65860 | ** |
| 65861 | ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this |
| 65862 | ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of |
| 65863 | ** the comparison for use by the next OP_Jump instruct. |
| 65864 | ** |
| 65865 | ** P4 is a KeyInfo structure that defines collating sequences and sort |
| 65866 | ** orders for the comparison. The permutation applies to registers |
| 65867 | ** only. The KeyInfo elements are used sequentially. |
| 65868 | ** |
| @@ -65880,10 +65903,11 @@ | |
| 65880 | int idx; |
| 65881 | CollSeq *pColl; /* Collating sequence to use on this term */ |
| 65882 | int bRev; /* True for DESCENDING sort order */ |
| 65883 | #endif /* local variables moved into u.al */ |
| 65884 | |
| 65885 | u.al.n = pOp->p3; |
| 65886 | u.al.pKeyInfo = pOp->p4.pKeyInfo; |
| 65887 | assert( u.al.n>0 ); |
| 65888 | assert( u.al.pKeyInfo!=0 ); |
| 65889 | u.al.p1 = pOp->p1; |
| @@ -66025,12 +66049,10 @@ | |
| 66025 | |
| 66026 | /* Opcode: Once P1 P2 * * * |
| 66027 | ** |
| 66028 | ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, |
| 66029 | ** set the flag and fall through to the next instruction. |
| 66030 | ** |
| 66031 | ** See also: JumpOnce |
| 66032 | */ |
| 66033 | case OP_Once: { /* jump */ |
| 66034 | assert( pOp->p1<p->nOnceFlag ); |
| 66035 | if( p->aOnceFlag[pOp->p1] ){ |
| 66036 | pc = pOp->p2-1; |
| @@ -71902,10 +71924,18 @@ | |
| 71902 | p->pReal = pReal; |
| 71903 | if( p->iSize>0 ){ |
| 71904 | assert(p->iSize<=p->nBuf); |
| 71905 | rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); |
| 71906 | } |
| 71907 | } |
| 71908 | } |
| 71909 | return rc; |
| 71910 | } |
| 71911 | |
| @@ -72565,10 +72595,19 @@ | |
| 72565 | ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 |
| 72566 | ** |
| 72567 | ** The result of random()%5 in the GROUP BY clause is probably different |
| 72568 | ** from the result in the result-set. We might fix this someday. Or |
| 72569 | ** then again, we might not... |
| 72570 | ** |
| 72571 | ** The nSubquery parameter specifies how many levels of subquery the |
| 72572 | ** alias is removed from the original expression. The usually value is |
| 72573 | ** zero but it might be more if the alias is contained within a subquery |
| 72574 | ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION |
| @@ -72589,45 +72628,40 @@ | |
| 72589 | assert( iCol>=0 && iCol<pEList->nExpr ); |
| 72590 | pOrig = pEList->a[iCol].pExpr; |
| 72591 | assert( pOrig!=0 ); |
| 72592 | assert( pOrig->flags & EP_Resolved ); |
| 72593 | db = pParse->db; |
| 72594 | if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ |
| 72595 | pDup = sqlite3ExprDup(db, pOrig, 0); |
| 72596 | incrAggFunctionDepth(pDup, nSubquery); |
| 72597 | pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); |
| 72598 | if( pDup==0 ) return; |
| 72599 | if( pEList->a[iCol].iAlias==0 ){ |
| 72600 | pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); |
| 72601 | } |
| 72602 | pDup->iTable = pEList->a[iCol].iAlias; |
| 72603 | }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){ |
| 72604 | pDup = sqlite3ExprDup(db, pOrig, 0); |
| 72605 | if( pDup==0 ) return; |
| 72606 | }else{ |
| 72607 | char *zToken = pOrig->u.zToken; |
| 72608 | assert( zToken!=0 ); |
| 72609 | pOrig->u.zToken = 0; |
| 72610 | pDup = sqlite3ExprDup(db, pOrig, 0); |
| 72611 | pOrig->u.zToken = zToken; |
| 72612 | if( pDup==0 ) return; |
| 72613 | assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 ); |
| 72614 | pDup->flags2 |= EP2_MallocedToken; |
| 72615 | pDup->u.zToken = sqlite3DbStrDup(db, zToken); |
| 72616 | } |
| 72617 | if( pExpr->flags & EP_ExpCollate ){ |
| 72618 | pDup->pColl = pExpr->pColl; |
| 72619 | pDup->flags |= EP_ExpCollate; |
| 72620 | } |
| 72621 | |
| 72622 | /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This |
| 72623 | ** prevents ExprDelete() from deleting the Expr structure itself, |
| 72624 | ** allowing it to be repopulated by the memcpy() on the following line. |
| 72625 | */ |
| 72626 | ExprSetProperty(pExpr, EP_Static); |
| 72627 | sqlite3ExprDelete(db, pExpr); |
| 72628 | memcpy(pExpr, pDup, sizeof(*pExpr)); |
| 72629 | sqlite3DbFree(db, pDup); |
| 72630 | } |
| 72631 | |
| 72632 | |
| 72633 | /* |
| @@ -72644,10 +72678,39 @@ | |
| 72644 | } |
| 72645 | } |
| 72646 | return 0; |
| 72647 | } |
| 72648 | |
| 72649 | |
| 72650 | /* |
| 72651 | ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up |
| 72652 | ** that name in the set of source tables in pSrcList and make the pExpr |
| 72653 | ** expression node refer back to that source column. The following changes |
| @@ -72699,44 +72762,63 @@ | |
| 72699 | |
| 72700 | /* Initialize the node to no-match */ |
| 72701 | pExpr->iTable = -1; |
| 72702 | pExpr->pTab = 0; |
| 72703 | ExprSetIrreducible(pExpr); |
| 72704 | |
| 72705 | /* Start at the inner-most context and move outward until a match is found */ |
| 72706 | while( pNC && cnt==0 ){ |
| 72707 | ExprList *pEList; |
| 72708 | SrcList *pSrcList = pNC->pSrcList; |
| 72709 | |
| 72710 | if( pSrcList ){ |
| 72711 | for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ |
| 72712 | Table *pTab; |
| 72713 | int iDb; |
| 72714 | Column *pCol; |
| 72715 | |
| 72716 | pTab = pItem->pTab; |
| 72717 | assert( pTab!=0 && pTab->zName!=0 ); |
| 72718 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 72719 | assert( pTab->nCol>0 ); |
| 72720 | if( zTab ){ |
| 72721 | if( pItem->zAlias ){ |
| 72722 | char *zTabName = pItem->zAlias; |
| 72723 | if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; |
| 72724 | }else{ |
| 72725 | char *zTabName = pTab->zName; |
| 72726 | if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){ |
| 72727 | continue; |
| 72728 | } |
| 72729 | if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ |
| 72730 | continue; |
| 72731 | } |
| 72732 | } |
| 72733 | } |
| 72734 | if( 0==(cntTab++) ){ |
| 72735 | pExpr->iTable = pItem->iCursor; |
| 72736 | pExpr->pTab = pTab; |
| 72737 | pSchema = pTab->pSchema; |
| 72738 | pMatch = pItem; |
| 72739 | } |
| 72740 | for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ |
| 72741 | if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ |
| 72742 | /* If there has been exactly one prior match and this match |
| @@ -72746,21 +72828,23 @@ | |
| 72746 | if( cnt==1 ){ |
| 72747 | if( pItem->jointype & JT_NATURAL ) continue; |
| 72748 | if( nameInUsingClause(pItem->pUsing, zCol) ) continue; |
| 72749 | } |
| 72750 | cnt++; |
| 72751 | pExpr->iTable = pItem->iCursor; |
| 72752 | pExpr->pTab = pTab; |
| 72753 | pMatch = pItem; |
| 72754 | pSchema = pTab->pSchema; |
| 72755 | /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ |
| 72756 | pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; |
| 72757 | break; |
| 72758 | } |
| 72759 | } |
| 72760 | } |
| 72761 | } |
| 72762 | |
| 72763 | #ifndef SQLITE_OMIT_TRIGGER |
| 72764 | /* If we have not already resolved the name, then maybe |
| 72765 | ** it is a new.* or old.* trigger argument reference |
| 72766 | */ |
| @@ -73055,42 +73139,43 @@ | |
| 73055 | int wrong_num_args = 0; /* True if wrong number of arguments */ |
| 73056 | int is_agg = 0; /* True if is an aggregate function */ |
| 73057 | int auth; /* Authorization to use the function */ |
| 73058 | int nId; /* Number of characters in function name */ |
| 73059 | const char *zId; /* The function name. */ |
| 73060 | FuncDef *pDef; /* Information about the function */ |
| 73061 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 73062 | |
| 73063 | testcase( pExpr->op==TK_CONST_FUNC ); |
| 73064 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 73065 | zId = pExpr->u.zToken; |
| 73066 | nId = sqlite3Strlen30(zId); |
| 73067 | pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); |
| 73068 | if( pDef==0 ){ |
| 73069 | pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); |
| 73070 | if( pDef==0 ){ |
| 73071 | no_such_func = 1; |
| 73072 | }else{ |
| 73073 | wrong_num_args = 1; |
| 73074 | } |
| 73075 | }else{ |
| 73076 | is_agg = pDef->xFunc==0; |
| 73077 | } |
| 73078 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 73079 | if( pDef ){ |
| 73080 | auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); |
| 73081 | if( auth!=SQLITE_OK ){ |
| 73082 | if( auth==SQLITE_DENY ){ |
| 73083 | sqlite3ErrorMsg(pParse, "not authorized to use function: %s", |
| 73084 | pDef->zName); |
| 73085 | pNC->nErr++; |
| 73086 | } |
| 73087 | pExpr->op = TK_NULL; |
| 73088 | return WRC_Prune; |
| 73089 | } |
| 73090 | } |
| 73091 | #endif |
| 73092 | if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ |
| 73093 | sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); |
| 73094 | pNC->nErr++; |
| 73095 | is_agg = 0; |
| 73096 | }else if( no_such_func ){ |
| @@ -73310,11 +73395,11 @@ | |
| 73310 | assert( pEList!=0 ); |
| 73311 | for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ |
| 73312 | int iCol = -1; |
| 73313 | Expr *pE, *pDup; |
| 73314 | if( pItem->done ) continue; |
| 73315 | pE = pItem->pExpr; |
| 73316 | if( sqlite3ExprIsInteger(pE, &iCol) ){ |
| 73317 | if( iCol<=0 || iCol>pEList->nExpr ){ |
| 73318 | resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); |
| 73319 | return 1; |
| 73320 | } |
| @@ -73328,18 +73413,24 @@ | |
| 73328 | } |
| 73329 | sqlite3ExprDelete(db, pDup); |
| 73330 | } |
| 73331 | } |
| 73332 | if( iCol>0 ){ |
| 73333 | CollSeq *pColl = pE->pColl; |
| 73334 | int flags = pE->flags & EP_ExpCollate; |
| 73335 | sqlite3ExprDelete(db, pE); |
| 73336 | pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0); |
| 73337 | if( pE==0 ) return 1; |
| 73338 | pE->pColl = pColl; |
| 73339 | pE->flags |= EP_IntValue | flags; |
| 73340 | pE->u.iValue = iCol; |
| 73341 | pItem->iOrderByCol = (u16)iCol; |
| 73342 | pItem->done = 1; |
| 73343 | }else{ |
| 73344 | moreToDo = 1; |
| 73345 | } |
| @@ -73440,15 +73531,15 @@ | |
| 73440 | ** sqlite3ResolveOrderGroupBy() will convert the expression to a |
| 73441 | ** copy of the iCol-th result-set expression. */ |
| 73442 | pItem->iOrderByCol = (u16)iCol; |
| 73443 | continue; |
| 73444 | } |
| 73445 | if( sqlite3ExprIsInteger(pE, &iCol) ){ |
| 73446 | /* The ORDER BY term is an integer constant. Again, set the column |
| 73447 | ** number so that sqlite3ResolveOrderGroupBy() will convert the |
| 73448 | ** order-by term to a copy of the result-set expression */ |
| 73449 | if( iCol<1 ){ |
| 73450 | resolveOutOfRangeError(pParse, zType, i+1, nResult); |
| 73451 | return 1; |
| 73452 | } |
| 73453 | pItem->iOrderByCol = (u16)iCol; |
| 73454 | continue; |
| @@ -73521,27 +73612,10 @@ | |
| 73521 | if( sqlite3ResolveExprNames(&sNC, p->pLimit) || |
| 73522 | sqlite3ResolveExprNames(&sNC, p->pOffset) ){ |
| 73523 | return WRC_Abort; |
| 73524 | } |
| 73525 | |
| 73526 | /* Set up the local name-context to pass to sqlite3ResolveExprNames() to |
| 73527 | ** resolve the result-set expression list. |
| 73528 | */ |
| 73529 | sNC.ncFlags = NC_AllowAgg; |
| 73530 | sNC.pSrcList = p->pSrc; |
| 73531 | sNC.pNext = pOuterNC; |
| 73532 | |
| 73533 | /* Resolve names in the result set. */ |
| 73534 | pEList = p->pEList; |
| 73535 | assert( pEList!=0 ); |
| 73536 | for(i=0; i<pEList->nExpr; i++){ |
| 73537 | Expr *pX = pEList->a[i].pExpr; |
| 73538 | if( sqlite3ResolveExprNames(&sNC, pX) ){ |
| 73539 | return WRC_Abort; |
| 73540 | } |
| 73541 | } |
| 73542 | |
| 73543 | /* Recursively resolve names in all subqueries |
| 73544 | */ |
| 73545 | for(i=0; i<p->pSrc->nSrc; i++){ |
| 73546 | struct SrcList_item *pItem = &p->pSrc->a[i]; |
| 73547 | if( pItem->pSelect ){ |
| @@ -73564,10 +73638,27 @@ | |
| 73564 | for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; |
| 73565 | assert( pItem->isCorrelated==0 && nRef<=0 ); |
| 73566 | pItem->isCorrelated = (nRef!=0); |
| 73567 | } |
| 73568 | } |
| 73569 | |
| 73570 | /* If there are no aggregate functions in the result-set, and no GROUP BY |
| 73571 | ** expression, do not allow aggregates in any of the other expressions. |
| 73572 | */ |
| 73573 | assert( (p->selFlags & SF_Aggregate)==0 ); |
| @@ -73798,11 +73889,13 @@ | |
| 73798 | ** SELECT * FROM t1 WHERE a; |
| 73799 | ** SELECT a AS b FROM t1 WHERE b; |
| 73800 | ** SELECT * FROM t1 WHERE (select a from t1); |
| 73801 | */ |
| 73802 | SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ |
| 73803 | int op = pExpr->op; |
| 73804 | if( op==TK_SELECT ){ |
| 73805 | assert( pExpr->flags&EP_xIsSelect ); |
| 73806 | return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); |
| 73807 | } |
| 73808 | #ifndef SQLITE_OMIT_CAST |
| @@ -73823,70 +73916,98 @@ | |
| 73823 | } |
| 73824 | return pExpr->affinity; |
| 73825 | } |
| 73826 | |
| 73827 | /* |
| 73828 | ** Set the explicit collating sequence for an expression to the |
| 73829 | ** collating sequence supplied in the second argument. |
| 73830 | */ |
| 73831 | SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){ |
| 73832 | if( pExpr && pColl ){ |
| 73833 | pExpr->pColl = pColl; |
| 73834 | pExpr->flags |= EP_ExpCollate; |
| 73835 | } |
| 73836 | return pExpr; |
| 73837 | } |
| 73838 | |
| 73839 | /* |
| 73840 | ** Set the collating sequence for expression pExpr to be the collating |
| 73841 | ** sequence named by pToken. Return a pointer to the revised expression. |
| 73842 | ** The collating sequence is marked as "explicit" using the EP_ExpCollate |
| 73843 | ** flag. An explicit collating sequence will override implicit |
| 73844 | ** collating sequences. |
| 73845 | */ |
| 73846 | SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){ |
| 73847 | char *zColl = 0; /* Dequoted name of collation sequence */ |
| 73848 | CollSeq *pColl; |
| 73849 | sqlite3 *db = pParse->db; |
| 73850 | zColl = sqlite3NameFromToken(db, pCollName); |
| 73851 | pColl = sqlite3LocateCollSeq(pParse, zColl); |
| 73852 | sqlite3ExprSetColl(pExpr, pColl); |
| 73853 | sqlite3DbFree(db, zColl); |
| 73854 | return pExpr; |
| 73855 | } |
| 73856 | |
| 73857 | /* |
| 73858 | ** Return the default collation sequence for the expression pExpr. If |
| 73859 | ** there is no default collation type, return 0. |
| 73860 | */ |
| 73861 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ |
| 73862 | CollSeq *pColl = 0; |
| 73863 | Expr *p = pExpr; |
| 73864 | while( p ){ |
| 73865 | int op; |
| 73866 | pColl = p->pColl; |
| 73867 | if( pColl ) break; |
| 73868 | op = p->op; |
| 73869 | if( p->pTab!=0 && ( |
| 73870 | op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER |
| 73871 | )){ |
| 73872 | /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally |
| 73873 | ** a TK_COLUMN but was previously evaluated and cached in a register */ |
| 73874 | const char *zColl; |
| 73875 | int j = p->iColumn; |
| 73876 | if( j>=0 ){ |
| 73877 | sqlite3 *db = pParse->db; |
| 73878 | zColl = p->pTab->aCol[j].zColl; |
| 73879 | pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); |
| 73880 | pExpr->pColl = pColl; |
| 73881 | } |
| 73882 | break; |
| 73883 | } |
| 73884 | if( op!=TK_CAST && op!=TK_UPLUS ){ |
| 73885 | break; |
| 73886 | } |
| 73887 | p = p->pLeft; |
| 73888 | } |
| 73889 | if( sqlite3CheckCollSeq(pParse, pColl) ){ |
| 73890 | pColl = 0; |
| 73891 | } |
| 73892 | return pColl; |
| @@ -73986,16 +74107,14 @@ | |
| 73986 | Expr *pLeft, |
| 73987 | Expr *pRight |
| 73988 | ){ |
| 73989 | CollSeq *pColl; |
| 73990 | assert( pLeft ); |
| 73991 | if( pLeft->flags & EP_ExpCollate ){ |
| 73992 | assert( pLeft->pColl ); |
| 73993 | pColl = pLeft->pColl; |
| 73994 | }else if( pRight && pRight->flags & EP_ExpCollate ){ |
| 73995 | assert( pRight->pColl ); |
| 73996 | pColl = pRight->pColl; |
| 73997 | }else{ |
| 73998 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 73999 | if( !pColl ){ |
| 74000 | pColl = sqlite3ExprCollSeq(pParse, pRight); |
| 74001 | } |
| @@ -74221,21 +74340,15 @@ | |
| 74221 | sqlite3ExprDelete(db, pLeft); |
| 74222 | sqlite3ExprDelete(db, pRight); |
| 74223 | }else{ |
| 74224 | if( pRight ){ |
| 74225 | pRoot->pRight = pRight; |
| 74226 | if( pRight->flags & EP_ExpCollate ){ |
| 74227 | pRoot->flags |= EP_ExpCollate; |
| 74228 | pRoot->pColl = pRight->pColl; |
| 74229 | } |
| 74230 | } |
| 74231 | if( pLeft ){ |
| 74232 | pRoot->pLeft = pLeft; |
| 74233 | if( pLeft->flags & EP_ExpCollate ){ |
| 74234 | pRoot->flags |= EP_ExpCollate; |
| 74235 | pRoot->pColl = pLeft->pColl; |
| 74236 | } |
| 74237 | } |
| 74238 | exprSetHeight(pRoot); |
| 74239 | } |
| 74240 | } |
| 74241 | |
| @@ -74489,11 +74602,11 @@ | |
| 74489 | }else{ |
| 74490 | assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); |
| 74491 | assert( !ExprHasProperty(p, EP_FromJoin) ); |
| 74492 | assert( (p->flags2 & EP2_MallocedToken)==0 ); |
| 74493 | assert( (p->flags2 & EP2_Irreducible)==0 ); |
| 74494 | if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ |
| 74495 | nSize = EXPR_REDUCEDSIZE | EP_Reduced; |
| 74496 | }else{ |
| 74497 | nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; |
| 74498 | } |
| 74499 | } |
| @@ -76513,10 +76626,11 @@ | |
| 76513 | sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); |
| 76514 | sqlite3ReleaseTempReg(pParse, r3); |
| 76515 | sqlite3ReleaseTempReg(pParse, r4); |
| 76516 | break; |
| 76517 | } |
| 76518 | case TK_UPLUS: { |
| 76519 | inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); |
| 76520 | break; |
| 76521 | } |
| 76522 | |
| @@ -76881,10 +76995,16 @@ | |
| 76881 | case TK_UPLUS: zUniOp = "UPLUS"; break; |
| 76882 | case TK_BITNOT: zUniOp = "BITNOT"; break; |
| 76883 | case TK_NOT: zUniOp = "NOT"; break; |
| 76884 | case TK_ISNULL: zUniOp = "ISNULL"; break; |
| 76885 | case TK_NOTNULL: zUniOp = "NOTNULL"; break; |
| 76886 | |
| 76887 | case TK_AGG_FUNCTION: |
| 76888 | case TK_CONST_FUNC: |
| 76889 | case TK_FUNCTION: { |
| 76890 | ExprList *pFarg; /* List of function arguments */ |
| @@ -77019,10 +77139,16 @@ | |
| 77019 | for(i=0; i<pList->nExpr; i++){ |
| 77020 | sqlite3ExplainPrintf(pOut, "item[%d] = ", i); |
| 77021 | sqlite3ExplainPush(pOut); |
| 77022 | sqlite3ExplainExpr(pOut, pList->a[i].pExpr); |
| 77023 | sqlite3ExplainPop(pOut); |
| 77024 | if( i<pList->nExpr-1 ){ |
| 77025 | sqlite3ExplainNL(pOut); |
| 77026 | } |
| 77027 | } |
| 77028 | sqlite3ExplainPop(pOut); |
| @@ -77100,10 +77226,13 @@ | |
| 77100 | switch( pExpr->op ){ |
| 77101 | case TK_IN: |
| 77102 | case TK_REGISTER: { |
| 77103 | return WRC_Prune; |
| 77104 | } |
| 77105 | case TK_FUNCTION: |
| 77106 | case TK_AGG_FUNCTION: |
| 77107 | case TK_CONST_FUNC: { |
| 77108 | /* The arguments to a function have a fixed destination. |
| 77109 | ** Mark them this way to avoid generated unneeded OP_SCopy |
| @@ -77121,13 +77250,15 @@ | |
| 77121 | break; |
| 77122 | } |
| 77123 | } |
| 77124 | if( isAppropriateForFactoring(pExpr) ){ |
| 77125 | int r1 = ++pParse->nMem; |
| 77126 | int r2; |
| 77127 | r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); |
| 77128 | if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1); |
| 77129 | pExpr->op2 = pExpr->op; |
| 77130 | pExpr->op = TK_REGISTER; |
| 77131 | pExpr->iTable = r2; |
| 77132 | return WRC_Prune; |
| 77133 | } |
| @@ -77540,11 +77671,19 @@ | |
| 77540 | assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); |
| 77541 | if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ |
| 77542 | return 2; |
| 77543 | } |
| 77544 | if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; |
| 77545 | if( pA->op!=pB->op ) return 2; |
| 77546 | if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; |
| 77547 | if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; |
| 77548 | if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; |
| 77549 | if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; |
| 77550 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| @@ -77552,15 +77691,13 @@ | |
| 77552 | return 2; |
| 77553 | } |
| 77554 | }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){ |
| 77555 | if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; |
| 77556 | if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 77557 | return 2; |
| 77558 | } |
| 77559 | } |
| 77560 | if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1; |
| 77561 | if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2; |
| 77562 | return 0; |
| 77563 | } |
| 77564 | |
| 77565 | /* |
| 77566 | ** Compare two ExprList objects. Return 0 if they are identical and |
| @@ -83371,14 +83508,12 @@ | |
| 83371 | ** specified collation sequence names. |
| 83372 | */ |
| 83373 | for(i=0; i<pList->nExpr; i++){ |
| 83374 | Expr *pExpr = pList->a[i].pExpr; |
| 83375 | if( pExpr ){ |
| 83376 | CollSeq *pColl = pExpr->pColl; |
| 83377 | /* Either pColl!=0 or there was an OOM failure. But if an OOM |
| 83378 | ** failure we have quit before reaching this point. */ |
| 83379 | if( ALWAYS(pColl) ){ |
| 83380 | nExtra += (1 + sqlite3Strlen30(pColl->zName)); |
| 83381 | } |
| 83382 | } |
| 83383 | } |
| 83384 | |
| @@ -83437,10 +83572,11 @@ | |
| 83437 | */ |
| 83438 | for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ |
| 83439 | const char *zColName = pListItem->zName; |
| 83440 | Column *pTabCol; |
| 83441 | int requestedSortOrder; |
| 83442 | char *zColl; /* Collation sequence name */ |
| 83443 | |
| 83444 | for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ |
| 83445 | if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; |
| 83446 | } |
| @@ -83449,18 +83585,15 @@ | |
| 83449 | pTab->zName, zColName); |
| 83450 | pParse->checkSchema = 1; |
| 83451 | goto exit_create_index; |
| 83452 | } |
| 83453 | pIndex->aiColumn[i] = j; |
| 83454 | /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of |
| 83455 | ** the way the "idxlist" non-terminal is constructed by the parser, |
| 83456 | ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl |
| 83457 | ** must exist or else there must have been an OOM error. But if there |
| 83458 | ** was an OOM error, we would never reach this point. */ |
| 83459 | if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){ |
| 83460 | int nColl; |
| 83461 | zColl = pListItem->pExpr->pColl->zName; |
| 83462 | nColl = sqlite3Strlen30(zColl) + 1; |
| 83463 | assert( nExtra>=nColl ); |
| 83464 | memcpy(zExtra, zColl, nColl); |
| 83465 | zColl = zExtra; |
| 83466 | zExtra += nColl; |
| @@ -87489,11 +87622,11 @@ | |
| 87489 | |
| 87490 | /* |
| 87491 | ** A foreign key constraint requires that the key columns in the parent |
| 87492 | ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. |
| 87493 | ** Given that pParent is the parent table for foreign key constraint pFKey, |
| 87494 | ** search the schema a unique index on the parent key columns. |
| 87495 | ** |
| 87496 | ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY |
| 87497 | ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx |
| 87498 | ** is set to point to the unique index. |
| 87499 | ** |
| @@ -87525,11 +87658,11 @@ | |
| 87525 | ** |
| 87526 | ** then non-zero is returned, and a "foreign key mismatch" error loaded |
| 87527 | ** into pParse. If an OOM error occurs, non-zero is returned and the |
| 87528 | ** pParse->db->mallocFailed flag is set. |
| 87529 | */ |
| 87530 | static int locateFkeyIndex( |
| 87531 | Parse *pParse, /* Parse context to store any error in */ |
| 87532 | Table *pParent, /* Parent table of FK constraint pFKey */ |
| 87533 | FKey *pFKey, /* Foreign key to find index for */ |
| 87534 | Index **ppIdx, /* OUT: Unique index on parent table */ |
| 87535 | int **paiCol /* OUT: Map of index columns in pFKey */ |
| @@ -87622,11 +87755,13 @@ | |
| 87622 | } |
| 87623 | } |
| 87624 | |
| 87625 | if( !pIdx ){ |
| 87626 | if( !pParse->disableTriggers ){ |
| 87627 | sqlite3ErrorMsg(pParse, "foreign key mismatch"); |
| 87628 | } |
| 87629 | sqlite3DbFree(pParse->db, aiCol); |
| 87630 | return 1; |
| 87631 | } |
| 87632 | |
| @@ -87858,16 +87993,19 @@ | |
| 87858 | if( pLeft ){ |
| 87859 | /* Set the collation sequence and affinity of the LHS of each TK_EQ |
| 87860 | ** expression to the parent key column defaults. */ |
| 87861 | if( pIdx ){ |
| 87862 | Column *pCol; |
| 87863 | iCol = pIdx->aiColumn[i]; |
| 87864 | pCol = &pTab->aCol[iCol]; |
| 87865 | if( pTab->iPKey==iCol ) iCol = -1; |
| 87866 | pLeft->iTable = regData+iCol+1; |
| 87867 | pLeft->affinity = pCol->affinity; |
| 87868 | pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl); |
| 87869 | }else{ |
| 87870 | pLeft->iTable = regData; |
| 87871 | pLeft->affinity = SQLITE_AFF_INTEGER; |
| 87872 | } |
| 87873 | } |
| @@ -88080,11 +88218,11 @@ | |
| 88080 | if( pParse->disableTriggers ){ |
| 88081 | pTo = sqlite3FindTable(db, pFKey->zTo, zDb); |
| 88082 | }else{ |
| 88083 | pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); |
| 88084 | } |
| 88085 | if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ |
| 88086 | assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); |
| 88087 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88088 | if( pTo==0 ){ |
| 88089 | /* If isIgnoreErrors is true, then a table is being dropped. In this |
| 88090 | ** case SQLite runs a "DELETE FROM xxx" on the table being dropped |
| @@ -88160,11 +88298,11 @@ | |
| 88160 | /* Inserting a single row into a parent table cannot cause an immediate |
| 88161 | ** foreign key violation. So do nothing in this case. */ |
| 88162 | continue; |
| 88163 | } |
| 88164 | |
| 88165 | if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 88166 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88167 | continue; |
| 88168 | } |
| 88169 | assert( aiCol || pFKey->nCol==1 ); |
| 88170 | |
| @@ -88215,11 +88353,11 @@ | |
| 88215 | for(p=pTab->pFKey; p; p=p->pNextFrom){ |
| 88216 | for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); |
| 88217 | } |
| 88218 | for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
| 88219 | Index *pIdx = 0; |
| 88220 | locateFkeyIndex(pParse, pTab, p, &pIdx, 0); |
| 88221 | if( pIdx ){ |
| 88222 | for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); |
| 88223 | } |
| 88224 | } |
| 88225 | } |
| @@ -88341,11 +88479,11 @@ | |
| 88341 | ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ |
| 88342 | Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ |
| 88343 | int i; /* Iterator variable */ |
| 88344 | Expr *pWhen = 0; /* WHEN clause for the trigger */ |
| 88345 | |
| 88346 | if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; |
| 88347 | assert( aiCol || pFKey->nCol==1 ); |
| 88348 | |
| 88349 | for(i=0; i<pFKey->nCol; i++){ |
| 88350 | Token tOld = { "old", 3 }; /* Literal "old" token */ |
| 88351 | Token tNew = { "new", 3 }; /* Literal "new" token */ |
| @@ -89843,29 +89981,24 @@ | |
| 89843 | ExprList *pCheck = pTab->pCheck; |
| 89844 | pParse->ckBase = regData; |
| 89845 | onError = overrideError!=OE_Default ? overrideError : OE_Abort; |
| 89846 | for(i=0; i<pCheck->nExpr; i++){ |
| 89847 | int allOk = sqlite3VdbeMakeLabel(v); |
| 89848 | Expr *pDup = sqlite3ExprDup(db, pCheck->a[i].pExpr, 0); |
| 89849 | if( !db->mallocFailed ){ |
| 89850 | assert( pDup!=0 ); |
| 89851 | sqlite3ExprIfTrue(pParse, pDup, allOk, SQLITE_JUMPIFNULL); |
| 89852 | if( onError==OE_Ignore ){ |
| 89853 | sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); |
| 89854 | }else{ |
| 89855 | char *zConsName = pCheck->a[i].zName; |
| 89856 | if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ |
| 89857 | if( zConsName ){ |
| 89858 | zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); |
| 89859 | }else{ |
| 89860 | zConsName = 0; |
| 89861 | } |
| 89862 | sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); |
| 89863 | } |
| 89864 | sqlite3VdbeResolveLabel(v, allOk); |
| 89865 | } |
| 89866 | sqlite3ExprDelete(db, pDup); |
| 89867 | } |
| 89868 | } |
| 89869 | #endif /* !defined(SQLITE_OMIT_CHECK) */ |
| 89870 | |
| 89871 | /* If we have an INTEGER PRIMARY KEY, make sure the primary key |
| @@ -92686,13 +92819,15 @@ | |
| 92686 | if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ |
| 92687 | Table *pTab; |
| 92688 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 92689 | pTab = sqlite3FindTable(db, zRight, zDb); |
| 92690 | if( pTab ){ |
| 92691 | int i; |
| 92692 | int nHidden = 0; |
| 92693 | Column *pCol; |
| 92694 | sqlite3VdbeSetNumCols(v, 6); |
| 92695 | pParse->nMem = 6; |
| 92696 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); |
| 92697 | sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); |
| 92698 | sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); |
| @@ -92713,12 +92848,18 @@ | |
| 92713 | if( pCol->zDflt ){ |
| 92714 | sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); |
| 92715 | }else{ |
| 92716 | sqlite3VdbeAddOp2(v, OP_Null, 0, 5); |
| 92717 | } |
| 92718 | sqlite3VdbeAddOp2(v, OP_Integer, |
| 92719 | (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6); |
| 92720 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); |
| 92721 | } |
| 92722 | } |
| 92723 | }else |
| 92724 | |
| @@ -92849,10 +92990,124 @@ | |
| 92849 | ++i; |
| 92850 | pFK = pFK->pNextFrom; |
| 92851 | } |
| 92852 | } |
| 92853 | } |
| 92854 | }else |
| 92855 | #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
| 92856 | |
| 92857 | #ifndef NDEBUG |
| 92858 | if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ |
| @@ -94308,11 +94563,11 @@ | |
| 94308 | SrcList *pSrc, /* the FROM clause -- which tables to scan */ |
| 94309 | Expr *pWhere, /* the WHERE clause */ |
| 94310 | ExprList *pGroupBy, /* the GROUP BY clause */ |
| 94311 | Expr *pHaving, /* the HAVING clause */ |
| 94312 | ExprList *pOrderBy, /* the ORDER BY clause */ |
| 94313 | int isDistinct, /* true if the DISTINCT keyword is present */ |
| 94314 | Expr *pLimit, /* LIMIT value. NULL means not used */ |
| 94315 | Expr *pOffset /* OFFSET value. NULL means no offset */ |
| 94316 | ){ |
| 94317 | Select *pNew; |
| 94318 | Select standin; |
| @@ -94332,11 +94587,11 @@ | |
| 94332 | pNew->pSrc = pSrc; |
| 94333 | pNew->pWhere = pWhere; |
| 94334 | pNew->pGroupBy = pGroupBy; |
| 94335 | pNew->pHaving = pHaving; |
| 94336 | pNew->pOrderBy = pOrderBy; |
| 94337 | pNew->selFlags = isDistinct ? SF_Distinct : 0; |
| 94338 | pNew->op = TK_SELECT; |
| 94339 | pNew->pLimit = pLimit; |
| 94340 | pNew->pOffset = pOffset; |
| 94341 | assert( pOffset==0 || pLimit!=0 ); |
| 94342 | pNew->addrOpenEphm[0] = -1; |
| @@ -95588,13 +95843,11 @@ | |
| 95588 | *paCol = aCol; |
| 95589 | |
| 95590 | for(i=0, pCol=aCol; i<nCol; i++, pCol++){ |
| 95591 | /* Get an appropriate name for the column |
| 95592 | */ |
| 95593 | p = pEList->a[i].pExpr; |
| 95594 | assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue) |
| 95595 | || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 ); |
| 95596 | if( (zName = pEList->a[i].zName)!=0 ){ |
| 95597 | /* If the column contains an "AS <name>" phrase, use <name> as the name */ |
| 95598 | zName = sqlite3DbStrDup(db, zName); |
| 95599 | }else{ |
| 95600 | Expr *pColExpr = p; /* The expression that is the result column name */ |
| @@ -95628,10 +95881,13 @@ | |
| 95628 | */ |
| 95629 | nName = sqlite3Strlen30(zName); |
| 95630 | for(j=cnt=0; j<i; j++){ |
| 95631 | if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ |
| 95632 | char *zNewName; |
| 95633 | zName[nName] = 0; |
| 95634 | zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); |
| 95635 | sqlite3DbFree(db, zName); |
| 95636 | zName = zNewName; |
| 95637 | j = -1; |
| @@ -96586,16 +96842,17 @@ | |
| 96586 | pKeyMerge->nField = (u16)nOrderBy; |
| 96587 | pKeyMerge->enc = ENC(db); |
| 96588 | for(i=0; i<nOrderBy; i++){ |
| 96589 | CollSeq *pColl; |
| 96590 | Expr *pTerm = pOrderBy->a[i].pExpr; |
| 96591 | if( pTerm->flags & EP_ExpCollate ){ |
| 96592 | pColl = pTerm->pColl; |
| 96593 | }else{ |
| 96594 | pColl = multiSelectCollSeq(pParse, p, aPermute[i]); |
| 96595 | pTerm->flags |= EP_ExpCollate; |
| 96596 | pTerm->pColl = pColl; |
| 96597 | } |
| 96598 | pKeyMerge->aColl[i] = pColl; |
| 96599 | pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; |
| 96600 | } |
| 96601 | } |
| @@ -96794,10 +97051,11 @@ | |
| 96794 | */ |
| 96795 | sqlite3VdbeResolveLabel(v, labelCmpr); |
| 96796 | sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); |
| 96797 | sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, |
| 96798 | (char*)pKeyMerge, P4_KEYINFO_HANDOFF); |
| 96799 | sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); |
| 96800 | |
| 96801 | /* Release temporary registers |
| 96802 | */ |
| 96803 | if( regPrev ){ |
| @@ -96861,13 +97119,10 @@ | |
| 96861 | }else{ |
| 96862 | Expr *pNew; |
| 96863 | assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); |
| 96864 | assert( pExpr->pLeft==0 && pExpr->pRight==0 ); |
| 96865 | pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); |
| 96866 | if( pNew && pExpr->pColl ){ |
| 96867 | pNew->pColl = pExpr->pColl; |
| 96868 | } |
| 96869 | sqlite3ExprDelete(db, pExpr); |
| 96870 | pExpr = pNew; |
| 96871 | } |
| 96872 | }else{ |
| 96873 | pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); |
| @@ -97414,38 +97669,47 @@ | |
| 97414 | return 1; |
| 97415 | } |
| 97416 | #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
| 97417 | |
| 97418 | /* |
| 97419 | ** Analyze the SELECT statement passed as an argument to see if it |
| 97420 | ** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if |
| 97421 | ** it is, or 0 otherwise. At present, a query is considered to be |
| 97422 | ** a min()/max() query if: |
| 97423 | ** |
| 97424 | ** 1. There is a single object in the FROM clause. |
| 97425 | ** |
| 97426 | ** 2. There is a single expression in the result set, and it is |
| 97427 | ** either min(x) or max(x), where x is a column reference. |
| 97428 | */ |
| 97429 | static u8 minMaxQuery(Select *p){ |
| 97430 | Expr *pExpr; |
| 97431 | ExprList *pEList = p->pEList; |
| 97432 | |
| 97433 | if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL; |
| 97434 | pExpr = pEList->a[0].pExpr; |
| 97435 | if( pExpr->op!=TK_AGG_FUNCTION ) return 0; |
| 97436 | if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0; |
| 97437 | pEList = pExpr->x.pList; |
| 97438 | if( pEList==0 || pEList->nExpr!=1 ) return 0; |
| 97439 | if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL; |
| 97440 | assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
| 97441 | if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){ |
| 97442 | return WHERE_ORDERBY_MIN; |
| 97443 | }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){ |
| 97444 | return WHERE_ORDERBY_MAX; |
| 97445 | } |
| 97446 | return WHERE_ORDERBY_NORMAL; |
| 97447 | } |
| 97448 | |
| 97449 | /* |
| 97450 | ** The select statement passed as the first argument is an aggregate query. |
| 97451 | ** The second argment is the associated aggregate-info object. This |
| @@ -97536,10 +97800,11 @@ | |
| 97536 | int i, j, k; |
| 97537 | SrcList *pTabList; |
| 97538 | ExprList *pEList; |
| 97539 | struct SrcList_item *pFrom; |
| 97540 | sqlite3 *db = pParse->db; |
| 97541 | |
| 97542 | if( db->mallocFailed ){ |
| 97543 | return WRC_Abort; |
| 97544 | } |
| 97545 | if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){ |
| @@ -97621,11 +97886,11 @@ | |
| 97621 | ** |
| 97622 | ** The first loop just checks to see if there are any "*" operators |
| 97623 | ** that need expanding. |
| 97624 | */ |
| 97625 | for(k=0; k<pEList->nExpr; k++){ |
| 97626 | Expr *pE = pEList->a[k].pExpr; |
| 97627 | if( pE->op==TK_ALL ) break; |
| 97628 | assert( pE->op!=TK_DOT || pE->pRight!=0 ); |
| 97629 | assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); |
| 97630 | if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; |
| 97631 | } |
| @@ -97639,14 +97904,22 @@ | |
| 97639 | ExprList *pNew = 0; |
| 97640 | int flags = pParse->db->flags; |
| 97641 | int longNames = (flags & SQLITE_FullColNames)!=0 |
| 97642 | && (flags & SQLITE_ShortColNames)==0; |
| 97643 | |
| 97644 | for(k=0; k<pEList->nExpr; k++){ |
| 97645 | Expr *pE = a[k].pExpr; |
| 97646 | assert( pE->op!=TK_DOT || pE->pRight!=0 ); |
| 97647 | if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){ |
| 97648 | /* This particular expression does not need to be expanded. |
| 97649 | */ |
| 97650 | pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); |
| 97651 | if( pNew ){ |
| 97652 | pNew->a[pNew->nExpr-1].zName = a[k].zName; |
| @@ -97657,44 +97930,56 @@ | |
| 97657 | a[k].pExpr = 0; |
| 97658 | }else{ |
| 97659 | /* This expression is a "*" or a "TABLE.*" and needs to be |
| 97660 | ** expanded. */ |
| 97661 | int tableSeen = 0; /* Set to 1 when TABLE matches */ |
| 97662 | char *zTName; /* text of name of TABLE */ |
| 97663 | if( pE->op==TK_DOT ){ |
| 97664 | assert( pE->pLeft!=0 ); |
| 97665 | assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); |
| 97666 | zTName = pE->pLeft->u.zToken; |
| 97667 | }else{ |
| 97668 | zTName = 0; |
| 97669 | } |
| 97670 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 97671 | Table *pTab = pFrom->pTab; |
| 97672 | char *zTabName = pFrom->zAlias; |
| 97673 | if( zTabName==0 ){ |
| 97674 | zTabName = pTab->zName; |
| 97675 | } |
| 97676 | if( db->mallocFailed ) break; |
| 97677 | if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ |
| 97678 | continue; |
| 97679 | } |
| 97680 | tableSeen = 1; |
| 97681 | for(j=0; j<pTab->nCol; j++){ |
| 97682 | Expr *pExpr, *pRight; |
| 97683 | char *zName = pTab->aCol[j].zName; |
| 97684 | char *zColname; /* The computed column name */ |
| 97685 | char *zToFree; /* Malloced string that needs to be freed */ |
| 97686 | Token sColname; /* Computed column name as a token */ |
| 97687 | |
| 97688 | /* If a column is marked as 'hidden' (currently only possible |
| 97689 | ** for virtual tables), do not include it in the expanded |
| 97690 | ** result-set list. |
| 97691 | */ |
| 97692 | if( IsHiddenColumn(&pTab->aCol[j]) ){ |
| 97693 | assert(IsVirtual(pTab)); |
| 97694 | continue; |
| 97695 | } |
| 97696 | |
| 97697 | if( i>0 && zTName==0 ){ |
| 97698 | if( (pFrom->jointype & JT_NATURAL)!=0 |
| 97699 | && tableAndColumnIndex(pTabList, i, zName, 0, 0) |
| 97700 | ){ |
| @@ -97713,10 +97998,14 @@ | |
| 97713 | zToFree = 0; |
| 97714 | if( longNames || pTabList->nSrc>1 ){ |
| 97715 | Expr *pLeft; |
| 97716 | pLeft = sqlite3Expr(db, TK_ID, zTabName); |
| 97717 | pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); |
| 97718 | if( longNames ){ |
| 97719 | zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); |
| 97720 | zToFree = zColname; |
| 97721 | } |
| 97722 | }else{ |
| @@ -97724,10 +98013,22 @@ | |
| 97724 | } |
| 97725 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
| 97726 | sColname.z = zColname; |
| 97727 | sColname.n = sqlite3Strlen30(zColname); |
| 97728 | sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
| 97729 | sqlite3DbFree(db, zToFree); |
| 97730 | } |
| 97731 | } |
| 97732 | if( !tableSeen ){ |
| 97733 | if( zTName ){ |
| @@ -98781,15 +99082,21 @@ | |
| 98781 | ** index or indices to use) should place a different priority on |
| 98782 | ** satisfying the 'ORDER BY' clause than it does in other cases. |
| 98783 | ** Refer to code and comments in where.c for details. |
| 98784 | */ |
| 98785 | ExprList *pMinMax = 0; |
| 98786 | u8 flag = minMaxQuery(p); |
| 98787 | if( flag ){ |
| 98788 | assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) ); |
| 98789 | assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 ); |
| 98790 | pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0); |
| 98791 | pDel = pMinMax; |
| 98792 | if( pMinMax && !db->mallocFailed ){ |
| 98793 | pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
| 98794 | pMinMax->a[0].pExpr->op = TK_COLUMN; |
| 98795 | } |
| @@ -102673,11 +102980,11 @@ | |
| 102673 | #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ |
| 102674 | #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ |
| 102675 | #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ |
| 102676 | #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ |
| 102677 | #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ |
| 102678 | #define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */ |
| 102679 | #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */ |
| 102680 | #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */ |
| 102681 | #define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */ |
| 102682 | #define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */ |
| 102683 | #define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */ |
| @@ -102823,11 +103130,11 @@ | |
| 102823 | sqlite3DbFree(db, pOld); |
| 102824 | } |
| 102825 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 102826 | } |
| 102827 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 102828 | pTerm->pExpr = p; |
| 102829 | pTerm->wtFlags = wtFlags; |
| 102830 | pTerm->pWC = pWC; |
| 102831 | pTerm->iParent = -1; |
| 102832 | return idx; |
| 102833 | } |
| @@ -102983,27 +103290,36 @@ | |
| 102983 | |
| 102984 | /* |
| 102985 | ** Commute a comparison operator. Expressions of the form "X op Y" |
| 102986 | ** are converted into "Y op X". |
| 102987 | ** |
| 102988 | ** If a collation sequence is associated with either the left or right |
| 102989 | ** side of the comparison, it remains associated with the same side after |
| 102990 | ** the commutation. So "Y collate NOCASE op X" becomes |
| 102991 | ** "X collate NOCASE op Y". This is because any collation sequence on |
| 102992 | ** the left hand side of a comparison overrides any collation sequence |
| 102993 | ** attached to the right. For the same reason the EP_ExpCollate flag |
| 102994 | ** is not commuted. |
| 102995 | */ |
| 102996 | static void exprCommute(Parse *pParse, Expr *pExpr){ |
| 102997 | u16 expRight = (pExpr->pRight->flags & EP_ExpCollate); |
| 102998 | u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate); |
| 102999 | assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); |
| 103000 | pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); |
| 103001 | pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); |
| 103002 | SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl); |
| 103003 | pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft; |
| 103004 | pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight; |
| 103005 | SWAP(Expr*,pExpr->pRight,pExpr->pLeft); |
| 103006 | if( pExpr->op>=TK_GT ){ |
| 103007 | assert( TK_LT==TK_GT+2 ); |
| 103008 | assert( TK_GE==TK_LE+2 ); |
| 103009 | assert( TK_GT>TK_EQ ); |
| @@ -103076,16 +103392,16 @@ | |
| 103076 | ** it to be useful for optimising expression pX. Store this |
| 103077 | ** value in variable pColl. |
| 103078 | */ |
| 103079 | assert(pX->pLeft); |
| 103080 | pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| 103081 | assert(pColl || pParse->nErr); |
| 103082 | |
| 103083 | for(j=0; pIdx->aiColumn[j]!=iColumn; j++){ |
| 103084 | if( NEVER(j>=pIdx->nColumn) ) return 0; |
| 103085 | } |
| 103086 | if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; |
| 103087 | } |
| 103088 | return pTerm; |
| 103089 | } |
| 103090 | } |
| 103091 | } |
| @@ -103600,10 +103916,11 @@ | |
| 103600 | return; |
| 103601 | } |
| 103602 | pTerm = &pWC->a[idxTerm]; |
| 103603 | pMaskSet = pWC->pMaskSet; |
| 103604 | pExpr = pTerm->pExpr; |
| 103605 | prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); |
| 103606 | op = pExpr->op; |
| 103607 | if( op==TK_IN ){ |
| 103608 | assert( pExpr->pRight==0 ); |
| 103609 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| @@ -103626,12 +103943,12 @@ | |
| 103626 | pTerm->prereqAll = prereqAll; |
| 103627 | pTerm->leftCursor = -1; |
| 103628 | pTerm->iParent = -1; |
| 103629 | pTerm->eOperator = 0; |
| 103630 | if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ |
| 103631 | Expr *pLeft = pExpr->pLeft; |
| 103632 | Expr *pRight = pExpr->pRight; |
| 103633 | if( pLeft->op==TK_COLUMN ){ |
| 103634 | pTerm->leftCursor = pLeft->iTable; |
| 103635 | pTerm->u.leftColumn = pLeft->iColumn; |
| 103636 | pTerm->eOperator = operatorMask(op); |
| 103637 | } |
| @@ -103655,11 +103972,11 @@ | |
| 103655 | }else{ |
| 103656 | pDup = pExpr; |
| 103657 | pNew = pTerm; |
| 103658 | } |
| 103659 | exprCommute(pParse, pDup); |
| 103660 | pLeft = pDup->pLeft; |
| 103661 | pNew->leftCursor = pLeft->iTable; |
| 103662 | pNew->u.leftColumn = pLeft->iColumn; |
| 103663 | testcase( (prereqLeft | extraRight) != prereqLeft ); |
| 103664 | pNew->prereqRight = prereqLeft | extraRight; |
| 103665 | pNew->prereqAll = prereqAll; |
| @@ -103734,11 +104051,11 @@ | |
| 103734 | Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ |
| 103735 | Expr *pNewExpr1; |
| 103736 | Expr *pNewExpr2; |
| 103737 | int idxNew1; |
| 103738 | int idxNew2; |
| 103739 | CollSeq *pColl; /* Collating sequence to use */ |
| 103740 | |
| 103741 | pLeft = pExpr->x.pList->a[1].pExpr; |
| 103742 | pStr2 = sqlite3ExprDup(db, pStr1, 0); |
| 103743 | if( !db->mallocFailed ){ |
| 103744 | u8 c, *pC; /* Last character before the first wildcard */ |
| @@ -103756,20 +104073,23 @@ | |
| 103756 | |
| 103757 | c = sqlite3UpperToLower[c]; |
| 103758 | } |
| 103759 | *pC = c + 1; |
| 103760 | } |
| 103761 | pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0); |
| 103762 | pNewExpr1 = sqlite3PExpr(pParse, TK_GE, |
| 103763 | sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl), |
| 103764 | pStr1, 0); |
| 103765 | idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); |
| 103766 | testcase( idxNew1==0 ); |
| 103767 | exprAnalyze(pSrc, pWC, idxNew1); |
| 103768 | pNewExpr2 = sqlite3PExpr(pParse, TK_LT, |
| 103769 | sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl), |
| 103770 | pStr2, 0); |
| 103771 | idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); |
| 103772 | testcase( idxNew2==0 ); |
| 103773 | exprAnalyze(pSrc, pWC, idxNew2); |
| 103774 | pTerm = &pWC->a[idxTerm]; |
| 103775 | if( isComplete ){ |
| @@ -103883,16 +104203,16 @@ | |
| 103883 | ){ |
| 103884 | int i; |
| 103885 | const char *zColl = pIdx->azColl[iCol]; |
| 103886 | |
| 103887 | for(i=0; i<pList->nExpr; i++){ |
| 103888 | Expr *p = pList->a[i].pExpr; |
| 103889 | if( p->op==TK_COLUMN |
| 103890 | && p->iColumn==pIdx->aiColumn[iCol] |
| 103891 | && p->iTable==iBase |
| 103892 | ){ |
| 103893 | CollSeq *pColl = sqlite3ExprCollSeq(pParse, p); |
| 103894 | if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ |
| 103895 | return i; |
| 103896 | } |
| 103897 | } |
| 103898 | } |
| @@ -103935,11 +104255,11 @@ | |
| 103935 | ** matching "col=X" expression and the column is on the same table as pIdx, |
| 103936 | ** set the corresponding bit in variable mask. |
| 103937 | */ |
| 103938 | for(i=0; i<pDistinct->nExpr; i++){ |
| 103939 | WhereTerm *pTerm; |
| 103940 | Expr *p = pDistinct->a[i].pExpr; |
| 103941 | if( p->op!=TK_COLUMN ) return 0; |
| 103942 | pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0); |
| 103943 | if( pTerm ){ |
| 103944 | Expr *pX = pTerm->pExpr; |
| 103945 | CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| @@ -103987,11 +104307,11 @@ | |
| 103987 | /* If any of the expressions is an IPK column on table iBase, then return |
| 103988 | ** true. Note: The (p->iTable==iBase) part of this test may be false if the |
| 103989 | ** current SELECT is a correlated sub-query. |
| 103990 | */ |
| 103991 | for(i=0; i<pDistinct->nExpr; i++){ |
| 103992 | Expr *p = pDistinct->a[i].pExpr; |
| 103993 | if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; |
| 103994 | } |
| 103995 | |
| 103996 | /* Loop through all indices on the table, checking each to see if it makes |
| 103997 | ** the DISTINCT qualifier redundant. It does so if: |
| @@ -104464,11 +104784,11 @@ | |
| 104464 | for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104465 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104466 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104467 | testcase( pTerm->eOperator==WO_IN ); |
| 104468 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104469 | if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; |
| 104470 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104471 | nTerm++; |
| 104472 | } |
| 104473 | |
| 104474 | /* If the ORDER BY clause contains only columns in the current |
| @@ -104512,29 +104832,32 @@ | |
| 104512 | *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; |
| 104513 | *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = |
| 104514 | pUsage; |
| 104515 | |
| 104516 | for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104517 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104518 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104519 | testcase( pTerm->eOperator==WO_IN ); |
| 104520 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104521 | if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; |
| 104522 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104523 | pIdxCons[j].iColumn = pTerm->u.leftColumn; |
| 104524 | pIdxCons[j].iTermOffset = i; |
| 104525 | pIdxCons[j].op = (u8)pTerm->eOperator; |
| 104526 | /* The direct assignment in the previous line is possible only because |
| 104527 | ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The |
| 104528 | ** following asserts verify this fact. */ |
| 104529 | assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); |
| 104530 | assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); |
| 104531 | assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); |
| 104532 | assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); |
| 104533 | assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); |
| 104534 | assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); |
| 104535 | assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); |
| 104536 | j++; |
| 104537 | } |
| 104538 | for(i=0; i<nOrderBy; i++){ |
| 104539 | Expr *pExpr = pOrderBy->a[i].pExpr; |
| 104540 | pIdxOrderBy[i].iColumn = pExpr->iColumn; |
| @@ -104616,10 +104939,11 @@ | |
| 104616 | struct sqlite3_index_constraint *pIdxCons; |
| 104617 | struct sqlite3_index_constraint_usage *pUsage; |
| 104618 | WhereTerm *pTerm; |
| 104619 | int i, j; |
| 104620 | int nOrderBy; |
| 104621 | double rCost; |
| 104622 | |
| 104623 | /* Make sure wsFlags is initialized to some sane value. Otherwise, if the |
| 104624 | ** malloc in allocateIndexInfo() fails and this function returns leaving |
| 104625 | ** wsFlags in an uninitialized state, the caller may behave unpredictably. |
| @@ -104650,63 +104974,91 @@ | |
| 104650 | ** sqlite3ViewGetColumnNames() would have picked up the error. |
| 104651 | */ |
| 104652 | assert( pTab->azModuleArg && pTab->azModuleArg[0] ); |
| 104653 | assert( sqlite3GetVTable(pParse->db, pTab) ); |
| 104654 | |
| 104655 | /* Set the aConstraint[].usable fields and initialize all |
| 104656 | ** output variables to zero. |
| 104657 | ** |
| 104658 | ** aConstraint[].usable is true for constraints where the right-hand |
| 104659 | ** side contains only references to tables to the left of the current |
| 104660 | ** table. In other words, if the constraint is of the form: |
| 104661 | ** |
| 104662 | ** column = expr |
| 104663 | ** |
| 104664 | ** and we are evaluating a join, then the constraint on column is |
| 104665 | ** only valid if all tables referenced in expr occur to the left |
| 104666 | ** of the table containing column. |
| 104667 | ** |
| 104668 | ** The aConstraints[] array contains entries for all constraints |
| 104669 | ** on the current table. That way we only have to compute it once |
| 104670 | ** even though we might try to pick the best index multiple times. |
| 104671 | ** For each attempt at picking an index, the order of tables in the |
| 104672 | ** join might be different so we have to recompute the usable flag |
| 104673 | ** each time. |
| 104674 | */ |
| 104675 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 104676 | pUsage = pIdxInfo->aConstraintUsage; |
| 104677 | for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ |
| 104678 | j = pIdxCons->iTermOffset; |
| 104679 | pTerm = &pWC->a[j]; |
| 104680 | pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1; |
| 104681 | } |
| 104682 | memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); |
| 104683 | if( pIdxInfo->needToFreeIdxStr ){ |
| 104684 | sqlite3_free(pIdxInfo->idxStr); |
| 104685 | } |
| 104686 | pIdxInfo->idxStr = 0; |
| 104687 | pIdxInfo->idxNum = 0; |
| 104688 | pIdxInfo->needToFreeIdxStr = 0; |
| 104689 | pIdxInfo->orderByConsumed = 0; |
| 104690 | /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ |
| 104691 | pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); |
| 104692 | nOrderBy = pIdxInfo->nOrderBy; |
| 104693 | if( !p->pOrderBy ){ |
| 104694 | pIdxInfo->nOrderBy = 0; |
| 104695 | } |
| 104696 | |
| 104697 | if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ |
| 104698 | return; |
| 104699 | } |
| 104700 | |
| 104701 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 104702 | for(i=0; i<pIdxInfo->nConstraint; i++){ |
| 104703 | if( pUsage[i].argvIndex>0 ){ |
| 104704 | p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight; |
| 104705 | } |
| 104706 | } |
| 104707 | |
| 104708 | /* If there is an ORDER BY clause, and the selected virtual table index |
| 104709 | ** does not satisfy it, increase the cost of the scan accordingly. This |
| 104710 | ** matches the processing for non-virtual tables in bestBtreeIndex(). |
| 104711 | */ |
| 104712 | rCost = pIdxInfo->estimatedCost; |
| @@ -105273,11 +105625,11 @@ | |
| 105273 | WhereTerm *pConstraint; /* A constraint in the WHERE clause */ |
| 105274 | |
| 105275 | /* If the next term of the ORDER BY clause refers to anything other than |
| 105276 | ** a column in the "base" table, then this index will not be of any |
| 105277 | ** further use in handling the ORDER BY. */ |
| 105278 | pOBExpr = pOBItem->pExpr; |
| 105279 | if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){ |
| 105280 | break; |
| 105281 | } |
| 105282 | |
| 105283 | /* Find column number and collating sequence for the next entry |
| @@ -105299,11 +105651,11 @@ | |
| 105299 | /* Check to see if the column number and collating sequence of the |
| 105300 | ** index match the column number and collating sequence of the ORDER BY |
| 105301 | ** clause entry. Set isMatch to 1 if they both match. */ |
| 105302 | if( pOBExpr->iColumn==iColumn ){ |
| 105303 | if( zColl ){ |
| 105304 | pColl = sqlite3ExprCollSeq(pParse, pOBExpr); |
| 105305 | if( !pColl ) pColl = db->pDfltColl; |
| 105306 | isMatch = sqlite3StrICmp(pColl->zName, zColl)==0; |
| 105307 | }else{ |
| 105308 | isMatch = 1; |
| 105309 | } |
| @@ -105440,10 +105792,15 @@ | |
| 105440 | int idxEqTermMask; /* Index mask of valid equality operators */ |
| 105441 | Index sPk; /* A fake index object for the primary key */ |
| 105442 | tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ |
| 105443 | int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ |
| 105444 | int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */ |
| 105445 | |
| 105446 | /* Initialize the cost to a worst-case value */ |
| 105447 | memset(&p->cost, 0, sizeof(p->cost)); |
| 105448 | p->cost.rCost = SQLITE_BIG_DBL; |
| 105449 | |
| @@ -105488,10 +105845,21 @@ | |
| 105488 | WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE |
| 105489 | ); |
| 105490 | eqTermMask = WO_EQ|WO_IN; |
| 105491 | pIdx = 0; |
| 105492 | } |
| 105493 | |
| 105494 | /* Loop over all indices looking for the best one to use |
| 105495 | */ |
| 105496 | for(; pProbe; pIdx=pProbe=pProbe->pNext){ |
| 105497 | const tRowcnt * const aiRowEst = pProbe->aiRowEst; |
| @@ -105566,15 +105934,13 @@ | |
| 105566 | */ |
| 105567 | int bInEst = 0; /* True if "x IN (SELECT...)" seen */ |
| 105568 | int nInMul = 1; /* Number of distinct equalities to lookup */ |
| 105569 | double rangeDiv = (double)1; /* Estimated reduction in search space */ |
| 105570 | int nBound = 0; /* Number of range constraints seen */ |
| 105571 | int bSort; /* True if external sort required */ |
| 105572 | int bDist; /* True if index cannot help with DISTINCT */ |
| 105573 | int bLookup = 0; /* True if not a covering index */ |
| 105574 | int nPriorSat; /* ORDER BY terms satisfied by outer loops */ |
| 105575 | int nOrderBy; /* Number of ORDER BY terms */ |
| 105576 | WhereTerm *pTerm; /* A single term of the WHERE clause */ |
| 105577 | #ifdef SQLITE_ENABLE_STAT3 |
| 105578 | WhereTerm *pFirstTerm = 0; /* First term matching the index */ |
| 105579 | #endif |
| 105580 | |
| @@ -105581,20 +105947,11 @@ | |
| 105581 | WHERETRACE(( |
| 105582 | " %s(%s):\n", |
| 105583 | pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk") |
| 105584 | )); |
| 105585 | memset(&pc, 0, sizeof(pc)); |
| 105586 | nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; |
| 105587 | if( p->i ){ |
| 105588 | nPriorSat = pc.plan.nOBSat = p->aLevel[p->i-1].plan.nOBSat; |
| 105589 | bSort = nPriorSat<nOrderBy; |
| 105590 | bDist = 0; |
| 105591 | }else{ |
| 105592 | nPriorSat = pc.plan.nOBSat = 0; |
| 105593 | bSort = nOrderBy>0; |
| 105594 | bDist = p->pDistinct!=0; |
| 105595 | } |
| 105596 | |
| 105597 | /* Determine the values of pc.plan.nEq and nInMul */ |
| 105598 | for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){ |
| 105599 | int j = pProbe->aiColumn[pc.plan.nEq]; |
| 105600 | pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); |
| @@ -106466,32 +106823,40 @@ | |
| 106466 | if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ |
| 106467 | /* Case 0: The table is a virtual-table. Use the VFilter and VNext |
| 106468 | ** to access the data. |
| 106469 | */ |
| 106470 | int iReg; /* P3 Value for OP_VFilter */ |
| 106471 | sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; |
| 106472 | int nConstraint = pVtabIdx->nConstraint; |
| 106473 | struct sqlite3_index_constraint_usage *aUsage = |
| 106474 | pVtabIdx->aConstraintUsage; |
| 106475 | const struct sqlite3_index_constraint *aConstraint = |
| 106476 | pVtabIdx->aConstraint; |
| 106477 | |
| 106478 | sqlite3ExprCachePush(pParse); |
| 106479 | iReg = sqlite3GetTempRange(pParse, nConstraint+2); |
| 106480 | for(j=1; j<=nConstraint; j++){ |
| 106481 | for(k=0; k<nConstraint; k++){ |
| 106482 | if( aUsage[k].argvIndex==j ){ |
| 106483 | int iTerm = aConstraint[k].iTermOffset; |
| 106484 | sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1); |
| 106485 | break; |
| 106486 | } |
| 106487 | } |
| 106488 | if( k==nConstraint ) break; |
| 106489 | } |
| 106490 | sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); |
| 106491 | sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); |
| 106492 | sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr, |
| 106493 | pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); |
| 106494 | pVtabIdx->needToFreeIdxStr = 0; |
| 106495 | for(j=0; j<nConstraint; j++){ |
| 106496 | if( aUsage[j].omit ){ |
| 106497 | int iTerm = aConstraint[j].iTermOffset; |
| @@ -108134,10 +108499,11 @@ | |
| 108134 | Expr* yy122; |
| 108135 | Select* yy159; |
| 108136 | IdList* yy180; |
| 108137 | struct {int value; int mask;} yy207; |
| 108138 | u8 yy258; |
| 108139 | struct LikeOp yy318; |
| 108140 | TriggerStep* yy327; |
| 108141 | ExprSpan yy342; |
| 108142 | SrcList* yy347; |
| 108143 | int yy392; |
| @@ -110084,22 +110450,19 @@ | |
| 110084 | case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); |
| 110085 | case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); |
| 110086 | case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); |
| 110087 | case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98); |
| 110088 | case 109: /* ifexists ::= */ yytestcase(yyruleno==109); |
| 110089 | case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120); |
| 110090 | case 121: /* distinct ::= */ yytestcase(yyruleno==121); |
| 110091 | case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); |
| 110092 | case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); |
| 110093 | {yygotominor.yy392 = 0;} |
| 110094 | break; |
| 110095 | case 29: /* ifnotexists ::= IF NOT EXISTS */ |
| 110096 | case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); |
| 110097 | case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); |
| 110098 | case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); |
| 110099 | case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108); |
| 110100 | case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119); |
| 110101 | case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); |
| 110102 | case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); |
| 110103 | {yygotominor.yy392 = 1;} |
| 110104 | break; |
| 110105 | case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ |
| @@ -110335,12 +110698,19 @@ | |
| 110335 | case 116: /* multiselect_op ::= UNION ALL */ |
| 110336 | {yygotominor.yy392 = TK_ALL;} |
| 110337 | break; |
| 110338 | case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ |
| 110339 | { |
| 110340 | yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); |
| 110341 | } |
| 110342 | break; |
| 110343 | case 122: /* sclp ::= selcollist COMMA */ |
| 110344 | case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246); |
| 110345 | {yygotominor.yy442 = yymsp[-1].minor.yy442;} |
| 110346 | break; |
| @@ -110406,14 +110776,24 @@ | |
| 110406 | break; |
| 110407 | case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ |
| 110408 | { |
| 110409 | if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ |
| 110410 | yygotominor.yy347 = yymsp[-4].minor.yy347; |
| 110411 | }else{ |
| 110412 | Select *pSubquery; |
| 110413 | sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); |
| 110414 | pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0); |
| 110415 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); |
| 110416 | } |
| 110417 | } |
| 110418 | break; |
| 110419 | case 137: /* dbnm ::= */ |
| @@ -110624,11 +111004,11 @@ | |
| 110624 | spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); |
| 110625 | } |
| 110626 | break; |
| 110627 | case 194: /* expr ::= expr COLLATE ids */ |
| 110628 | { |
| 110629 | yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); |
| 110630 | yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; |
| 110631 | yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 110632 | } |
| 110633 | break; |
| 110634 | case 195: /* expr ::= CAST LP expr AS typetoken RP */ |
| @@ -110642,11 +111022,11 @@ | |
| 110642 | if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ |
| 110643 | sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); |
| 110644 | } |
| 110645 | yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); |
| 110646 | spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); |
| 110647 | if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){ |
| 110648 | yygotominor.yy342.pExpr->flags |= EP_Distinct; |
| 110649 | } |
| 110650 | } |
| 110651 | break; |
| 110652 | case 197: /* expr ::= ID LP STAR RP */ |
| @@ -110883,28 +111263,20 @@ | |
| 110883 | case 244: /* uniqueflag ::= */ |
| 110884 | {yygotominor.yy392 = OE_None;} |
| 110885 | break; |
| 110886 | case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */ |
| 110887 | { |
| 110888 | Expr *p = 0; |
| 110889 | if( yymsp[-1].minor.yy0.n>0 ){ |
| 110890 | p = sqlite3Expr(pParse->db, TK_COLUMN, 0); |
| 110891 | sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); |
| 110892 | } |
| 110893 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p); |
| 110894 | sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1); |
| 110895 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 110896 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 110897 | } |
| 110898 | break; |
| 110899 | case 248: /* idxlist ::= nm collate sortorder */ |
| 110900 | { |
| 110901 | Expr *p = 0; |
| 110902 | if( yymsp[-1].minor.yy0.n>0 ){ |
| 110903 | p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); |
| 110904 | sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); |
| 110905 | } |
| 110906 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p); |
| 110907 | sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); |
| 110908 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 110909 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 110910 | } |
| @@ -141105,10 +141477,11 @@ | |
| 141105 | extern int Sqlitemultiplex_Init(Tcl_Interp*); |
| 141106 | extern int SqliteSuperlock_Init(Tcl_Interp*); |
| 141107 | extern int SqlitetestSyscall_Init(Tcl_Interp*); |
| 141108 | extern int Sqlitetestfuzzer_Init(Tcl_Interp*); |
| 141109 | extern int Sqlitetestwholenumber_Init(Tcl_Interp*); |
| 141110 | |
| 141111 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141112 | extern int Sqlitetestfts3_Init(Tcl_Interp *interp); |
| 141113 | #endif |
| 141114 | |
| @@ -141148,10 +141521,11 @@ | |
| 141148 | Sqlitemultiplex_Init(interp); |
| 141149 | SqliteSuperlock_Init(interp); |
| 141150 | SqlitetestSyscall_Init(interp); |
| 141151 | Sqlitetestfuzzer_Init(interp); |
| 141152 | Sqlitetestwholenumber_Init(interp); |
| 141153 | |
| 141154 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141155 | Sqlitetestfts3_Init(interp); |
| 141156 | #endif |
| 141157 | |
| 141158 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -1,8 +1,8 @@ | |
| 1 | /****************************************************************************** |
| 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | ** version 3.7.16. By combining all the individual C code files into this |
| 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | ** translation unit. |
| @@ -671,13 +671,13 @@ | |
| 671 | ** |
| 672 | ** See also: [sqlite3_libversion()], |
| 673 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 674 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 675 | */ |
| 676 | #define SQLITE_VERSION "3.7.16" |
| 677 | #define SQLITE_VERSION_NUMBER 3007016 |
| 678 | #define SQLITE_SOURCE_ID "2012-12-08 06:46:05 e65db42c9fdc1d6f257c8db54a46ee4fc0d7aaf0" |
| 679 | |
| 680 | /* |
| 681 | ** CAPI3REF: Run-Time Library Version Numbers |
| 682 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 683 | ** |
| @@ -2162,11 +2162,11 @@ | |
| 2162 | ** database connection is opened. By default, URI handling is globally |
| 2163 | ** disabled. The default value may be changed by compiling with the |
| 2164 | ** [SQLITE_USE_URI] symbol defined. |
| 2165 | ** |
| 2166 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 2167 | ** <dd> This option takes a single integer argument which is interpreted as |
| 2168 | ** a boolean in order to enable or disable the use of covering indices for |
| 2169 | ** full table scans in the query optimizer. The default setting is determined |
| 2170 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 2171 | ** if that compile-time option is omitted. |
| 2172 | ** The ability to disable the use of covering indices for full table scans |
| @@ -10573,24 +10573,24 @@ | |
| 10573 | ** and the value of Index.onError indicate the which conflict resolution |
| 10574 | ** algorithm to employ whenever an attempt is made to insert a non-unique |
| 10575 | ** element. |
| 10576 | */ |
| 10577 | struct Index { |
| 10578 | char *zName; /* Name of this index */ |
| 10579 | int *aiColumn; /* Which columns are used by this index. 1st is 0 */ |
| 10580 | tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ |
| 10581 | Table *pTable; /* The SQL table being indexed */ |
| 10582 | char *zColAff; /* String defining the affinity of each column */ |
| 10583 | Index *pNext; /* The next index associated with the same table */ |
| 10584 | Schema *pSchema; /* Schema containing this index */ |
| 10585 | u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ |
| 10586 | char **azColl; /* Array of collation sequence names for index */ |
| 10587 | int tnum; /* DB Page containing root of this index */ |
| 10588 | u16 nColumn; /* Number of columns in table used by this index */ |
| 10589 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| 10590 | unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */ |
| 10591 | unsigned bUnordered:1; /* Use this index for == or IN queries only */ |
| 10592 | #ifdef SQLITE_ENABLE_STAT3 |
| 10593 | int nSample; /* Number of elements in aSample[] */ |
| 10594 | tRowcnt avgEq; /* Average nEq value for key values not in aSample */ |
| 10595 | IndexSample *aSample; /* Samples of the left-most key */ |
| 10596 | #endif |
| @@ -10767,11 +10767,10 @@ | |
| 10767 | Expr *pRight; /* Right subnode */ |
| 10768 | union { |
| 10769 | ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */ |
| 10770 | Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */ |
| 10771 | } x; |
| 10772 | |
| 10773 | /* If the EP_Reduced flag is set in the Expr.flags mask, then no |
| 10774 | ** space is allocated for the fields below this point. An attempt to |
| 10775 | ** access them will result in a segfault or malfunction. |
| 10776 | *********************************************************************/ |
| @@ -10803,11 +10802,11 @@ | |
| 10802 | #define EP_Error 0x0008 /* Expression contains one or more errors */ |
| 10803 | #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ |
| 10804 | #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ |
| 10805 | #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ |
| 10806 | #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ |
| 10807 | #define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */ |
| 10808 | #define EP_FixedDest 0x0200 /* Result needed in a specific register */ |
| 10809 | #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */ |
| 10810 | #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */ |
| 10811 | #define EP_Hint 0x1000 /* Not used */ |
| 10812 | #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ |
| @@ -10861,22 +10860,31 @@ | |
| 10860 | ** name. An expr/name combination can be used in several ways, such |
| 10861 | ** as the list of "expr AS ID" fields following a "SELECT" or in the |
| 10862 | ** list of "ID = expr" items in an UPDATE. A list of expressions can |
| 10863 | ** also be used as the argument to a function, in which case the a.zName |
| 10864 | ** field is not used. |
| 10865 | ** |
| 10866 | ** By default the Expr.zSpan field holds a human-readable description of |
| 10867 | ** the expression that is used in the generation of error messages and |
| 10868 | ** column labels. In this case, Expr.zSpan is typically the text of a |
| 10869 | ** column expression as it exists in a SELECT statement. However, if |
| 10870 | ** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name |
| 10871 | ** of the result column in the form: DATABASE.TABLE.COLUMN. This later |
| 10872 | ** form is used for name resolution with nested FROM clauses. |
| 10873 | */ |
| 10874 | struct ExprList { |
| 10875 | int nExpr; /* Number of expressions on the list */ |
| 10876 | int iECursor; /* VDBE Cursor associated with this ExprList */ |
| 10877 | struct ExprList_item { /* For each expression in the list */ |
| 10878 | Expr *pExpr; /* The list of expressions */ |
| 10879 | char *zName; /* Token associated with this expression */ |
| 10880 | char *zSpan; /* Original text of the expression */ |
| 10881 | u8 sortOrder; /* 1 for DESC or 0 for ASC */ |
| 10882 | unsigned done :1; /* A flag to indicate when processing is finished */ |
| 10883 | unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ |
| 10884 | u16 iOrderByCol; /* For ORDER BY, column number in result set */ |
| 10885 | u16 iAlias; /* Index into Parse.aAlias[] for zName */ |
| 10886 | } *a; /* Alloc a power of two greater or equal to nExpr */ |
| 10887 | }; |
| 10888 | |
| 10889 | /* |
| 10890 | ** An instance of this structure is used by the parser to record both |
| @@ -11192,10 +11200,11 @@ | |
| 11200 | #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ |
| 11201 | #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ |
| 11202 | #define SF_UseSorter 0x0040 /* Sort using a sorter */ |
| 11203 | #define SF_Values 0x0080 /* Synthesized from VALUES clause */ |
| 11204 | #define SF_Materialize 0x0100 /* Force materialization of views */ |
| 11205 | #define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ |
| 11206 | |
| 11207 | |
| 11208 | /* |
| 11209 | ** The results of a select can be distributed in several ways. The |
| 11210 | ** "SRT" prefix means "SELECT Result Type". |
| @@ -11420,10 +11429,11 @@ | |
| 11429 | #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ |
| 11430 | #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ |
| 11431 | #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ |
| 11432 | #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ |
| 11433 | #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ |
| 11434 | #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ |
| 11435 | |
| 11436 | /* |
| 11437 | * Each trigger present in the database schema is stored as an instance of |
| 11438 | * struct Trigger. |
| 11439 | * |
| @@ -11904,11 +11914,11 @@ | |
| 11914 | SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, |
| 11915 | Token*, int, int); |
| 11916 | SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int); |
| 11917 | SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*); |
| 11918 | SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, |
| 11919 | Expr*,ExprList*,u16,Expr*,Expr*); |
| 11920 | SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*); |
| 11921 | SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*); |
| 11922 | SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int); |
| 11923 | SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); |
| 11924 | #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) |
| @@ -12112,12 +12122,13 @@ | |
| 12122 | SQLITE_PRIVATE const char *sqlite3ErrStr(int); |
| 12123 | SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); |
| 12124 | SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); |
| 12125 | SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); |
| 12126 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); |
| 12127 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*); |
| 12128 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); |
| 12129 | SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); |
| 12130 | SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); |
| 12131 | SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); |
| 12132 | SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); |
| 12133 | SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); |
| 12134 | SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64); |
| @@ -12160,10 +12171,11 @@ | |
| 12171 | SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); |
| 12172 | SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); |
| 12173 | SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*); |
| 12174 | SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int); |
| 12175 | SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); |
| 12176 | SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); |
| 12177 | SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*); |
| 12178 | SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); |
| 12179 | SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); |
| 12180 | SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int); |
| 12181 | SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *); |
| @@ -12298,12 +12310,14 @@ | |
| 12310 | #define sqlite3FkOldmask(a,b) 0 |
| 12311 | #define sqlite3FkRequired(a,b,c,d) 0 |
| 12312 | #endif |
| 12313 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 12314 | SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); |
| 12315 | SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); |
| 12316 | #else |
| 12317 | #define sqlite3FkDelete(a,b) |
| 12318 | #define sqlite3FkLocateIndex(a,b,c,d,e) |
| 12319 | #endif |
| 12320 | |
| 12321 | |
| 12322 | /* |
| 12323 | ** Available fault injectors. Should be numbered beginning with 0. |
| @@ -23307,15 +23321,11 @@ | |
| 23321 | { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, |
| 23322 | #endif |
| 23323 | #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\ |
| 23324 | aSyscall[13].pCurrent) |
| 23325 | |
| 23326 | { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, |
| 23327 | #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) |
| 23328 | |
| 23329 | #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE |
| 23330 | { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, |
| 23331 | #else |
| @@ -23336,13 +23346,10 @@ | |
| 23346 | #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) |
| 23347 | |
| 23348 | { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, |
| 23349 | #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) |
| 23350 | |
| 23351 | }; /* End of the overrideable system calls */ |
| 23352 | |
| 23353 | /* |
| 23354 | ** This is the xSetSystemCall() method of sqlite3_vfs for all of the |
| 23355 | ** "unix" VFSes. Return SQLITE_OK opon successfully updating the |
| @@ -23443,31 +23450,29 @@ | |
| 23450 | ** process that is able to write to the database will also be able to |
| 23451 | ** recover the hot journals. |
| 23452 | */ |
| 23453 | static int robust_open(const char *z, int f, mode_t m){ |
| 23454 | int fd; |
| 23455 | mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS; |
| 23456 | do{ |
| 23457 | #if defined(O_CLOEXEC) |
| 23458 | fd = osOpen(z,f|O_CLOEXEC,m2); |
| 23459 | #else |
| 23460 | fd = osOpen(z,f,m2); |
| 23461 | #endif |
| 23462 | }while( fd<0 && errno==EINTR ); |
| 23463 | if( fd>=0 ){ |
| 23464 | if( m!=0 ){ |
| 23465 | struct stat statbuf; |
| 23466 | if( osFstat(fd, &statbuf)==0 && (statbuf.st_mode&0777)!=m ){ |
| 23467 | osFchmod(fd, m); |
| 23468 | } |
| 23469 | } |
| 23470 | #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) |
| 23471 | osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); |
| 23472 | #endif |
| 23473 | } |
| 23474 | return fd; |
| 23475 | } |
| 23476 | |
| 23477 | /* |
| 23478 | ** Helper functions to obtain and relinquish the global mutex. The |
| @@ -29889,11 +29894,11 @@ | |
| 29894 | }; |
| 29895 | unsigned int i; /* Loop counter */ |
| 29896 | |
| 29897 | /* Double-check that the aSyscall[] array has been constructed |
| 29898 | ** correctly. See ticket [bb3a86e890c8e96ab] */ |
| 29899 | assert( ArraySize(aSyscall)==21 ); |
| 29900 | |
| 29901 | /* Register all VFSes defined in the aVfs[] array */ |
| 29902 | for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ |
| 29903 | sqlite3_vfs_register(&aVfs[i], i==0); |
| 29904 | } |
| @@ -56355,11 +56360,11 @@ | |
| 56360 | sqlite3BtreeLeave(p); |
| 56361 | return 0; |
| 56362 | } |
| 56363 | i = PENDING_BYTE_PAGE(pBt); |
| 56364 | if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); |
| 56365 | sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); |
| 56366 | sCheck.errMsg.useMalloc = 2; |
| 56367 | |
| 56368 | /* Check the integrity of the freelist |
| 56369 | */ |
| 56370 | checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), |
| @@ -56890,11 +56895,16 @@ | |
| 56895 | /* |
| 56896 | ** Parameter zSrcData points to a buffer containing the data for |
| 56897 | ** page iSrcPg from the source database. Copy this data into the |
| 56898 | ** destination database. |
| 56899 | */ |
| 56900 | static int backupOnePage( |
| 56901 | sqlite3_backup *p, /* Backup handle */ |
| 56902 | Pgno iSrcPg, /* Source database page to backup */ |
| 56903 | const u8 *zSrcData, /* Source database page data */ |
| 56904 | int bUpdate /* True for an update, false otherwise */ |
| 56905 | ){ |
| 56906 | Pager * const pDestPager = sqlite3BtreePager(p->pDest); |
| 56907 | const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); |
| 56908 | int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); |
| 56909 | const int nCopy = MIN(nSrcPgsz, nDestPgsz); |
| 56910 | const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; |
| @@ -56963,10 +56973,13 @@ | |
| 56973 | ** cached parse of the page). MemPage.isInit is marked |
| 56974 | ** "MUST BE FIRST" for this purpose. |
| 56975 | */ |
| 56976 | memcpy(zOut, zIn, nCopy); |
| 56977 | ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; |
| 56978 | if( iOff==0 && bUpdate==0 ){ |
| 56979 | sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); |
| 56980 | } |
| 56981 | } |
| 56982 | sqlite3PagerUnref(pDestPg); |
| 56983 | } |
| 56984 | |
| 56985 | return rc; |
| @@ -57069,11 +57082,11 @@ | |
| 57082 | const Pgno iSrcPg = p->iNext; /* Source page number */ |
| 57083 | if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ |
| 57084 | DbPage *pSrcPg; /* Source page object */ |
| 57085 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); |
| 57086 | if( rc==SQLITE_OK ){ |
| 57087 | rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); |
| 57088 | sqlite3PagerUnref(pSrcPg); |
| 57089 | } |
| 57090 | } |
| 57091 | p->iNext++; |
| 57092 | } |
| @@ -57317,11 +57330,11 @@ | |
| 57330 | ** the new data into the backup. |
| 57331 | */ |
| 57332 | int rc; |
| 57333 | assert( p->pDestDb ); |
| 57334 | sqlite3_mutex_enter(p->pDestDb->mutex); |
| 57335 | rc = backupOnePage(p, iPage, aData, 1); |
| 57336 | sqlite3_mutex_leave(p->pDestDb->mutex); |
| 57337 | assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); |
| 57338 | if( rc!=SQLITE_OK ){ |
| 57339 | p->rc = rc; |
| 57340 | } |
| @@ -59434,26 +59447,22 @@ | |
| 59447 | assert( pKeyInfo->aSortOrder!=0 ); |
| 59448 | sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); |
| 59449 | i = sqlite3Strlen30(zTemp); |
| 59450 | for(j=0; j<pKeyInfo->nField; j++){ |
| 59451 | CollSeq *pColl = pKeyInfo->aColl[j]; |
| 59452 | const char *zColl = pColl ? pColl->zName : "nil"; |
| 59453 | int n = sqlite3Strlen30(zColl); |
| 59454 | if( i+n>nTemp-6 ){ |
| 59455 | memcpy(&zTemp[i],",...",4); |
| 59456 | break; |
| 59457 | } |
| 59458 | zTemp[i++] = ','; |
| 59459 | if( pKeyInfo->aSortOrder[j] ){ |
| 59460 | zTemp[i++] = '-'; |
| 59461 | } |
| 59462 | memcpy(&zTemp[i], zColl, n+1); |
| 59463 | i += n; |
| 59464 | } |
| 59465 | zTemp[i++] = ')'; |
| 59466 | zTemp[i] = 0; |
| 59467 | assert( i<nTemp ); |
| 59468 | break; |
| @@ -63839,11 +63848,13 @@ | |
| 63848 | #ifdef SQLITE_DEBUG |
| 63849 | /* |
| 63850 | ** Print the value of a register for tracing purposes: |
| 63851 | */ |
| 63852 | static void memTracePrint(FILE *out, Mem *p){ |
| 63853 | if( p->flags & MEM_Invalid ){ |
| 63854 | fprintf(out, " undefined"); |
| 63855 | }else if( p->flags & MEM_Null ){ |
| 63856 | fprintf(out, " NULL"); |
| 63857 | }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ |
| 63858 | fprintf(out, " si:%lld", p->u.i); |
| 63859 | }else if( p->flags & MEM_Int ){ |
| 63860 | fprintf(out, " i:%lld", p->u.i); |
| @@ -64112,10 +64123,11 @@ | |
| 64123 | } af; |
| 64124 | struct OP_Concat_stack_vars { |
| 64125 | i64 nByte; |
| 64126 | } ag; |
| 64127 | struct OP_Remainder_stack_vars { |
| 64128 | char bIntint; /* Started out as two integer operands */ |
| 64129 | int flags; /* Combined MEM_* flags from both inputs */ |
| 64130 | i64 iA; /* Integer value of left operand */ |
| 64131 | i64 iB; /* Integer value of right operand */ |
| 64132 | double rA; /* Real value of left operand */ |
| 64133 | double rB; /* Real value of right operand */ |
| @@ -65021,10 +65033,13 @@ | |
| 65033 | pOut = &aMem[pOp->p2]; |
| 65034 | assert( pOut!=pIn1 ); |
| 65035 | while( 1 ){ |
| 65036 | sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); |
| 65037 | Deephemeralize(pOut); |
| 65038 | #ifdef SQLITE_DEBUG |
| 65039 | pOut->pScopyFrom = 0; |
| 65040 | #endif |
| 65041 | REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut); |
| 65042 | if( (u.ae.n--)==0 ) break; |
| 65043 | pOut++; |
| 65044 | pIn1++; |
| 65045 | } |
| @@ -65214,10 +65229,11 @@ | |
| 65229 | case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ |
| 65230 | case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ |
| 65231 | case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ |
| 65232 | case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ |
| 65233 | #if 0 /* local variables moved into u.ah */ |
| 65234 | char bIntint; /* Started out as two integer operands */ |
| 65235 | int flags; /* Combined MEM_* flags from both inputs */ |
| 65236 | i64 iA; /* Integer value of left operand */ |
| 65237 | i64 iB; /* Integer value of right operand */ |
| 65238 | double rA; /* Real value of left operand */ |
| 65239 | double rB; /* Real value of right operand */ |
| @@ -65231,10 +65247,11 @@ | |
| 65247 | u.ah.flags = pIn1->flags | pIn2->flags; |
| 65248 | if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; |
| 65249 | if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ |
| 65250 | u.ah.iA = pIn1->u.i; |
| 65251 | u.ah.iB = pIn2->u.i; |
| 65252 | u.ah.bIntint = 1; |
| 65253 | switch( pOp->opcode ){ |
| 65254 | case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65255 | case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65256 | case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break; |
| 65257 | case OP_Divide: { |
| @@ -65251,10 +65268,11 @@ | |
| 65268 | } |
| 65269 | } |
| 65270 | pOut->u.i = u.ah.iB; |
| 65271 | MemSetTypeFlag(pOut, MEM_Int); |
| 65272 | }else{ |
| 65273 | u.ah.bIntint = 0; |
| 65274 | fp_math: |
| 65275 | u.ah.rA = sqlite3VdbeRealValue(pIn1); |
| 65276 | u.ah.rB = sqlite3VdbeRealValue(pIn2); |
| 65277 | switch( pOp->opcode ){ |
| 65278 | case OP_Add: u.ah.rB += u.ah.rA; break; |
| @@ -65282,11 +65300,11 @@ | |
| 65300 | if( sqlite3IsNaN(u.ah.rB) ){ |
| 65301 | goto arithmetic_result_is_null; |
| 65302 | } |
| 65303 | pOut->r = u.ah.rB; |
| 65304 | MemSetTypeFlag(pOut, MEM_Real); |
| 65305 | if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){ |
| 65306 | sqlite3VdbeIntegerAffinity(pOut); |
| 65307 | } |
| 65308 | #endif |
| 65309 | } |
| 65310 | break; |
| @@ -65843,26 +65861,31 @@ | |
| 65861 | /* Opcode: Permutation * * * P4 * |
| 65862 | ** |
| 65863 | ** Set the permutation used by the OP_Compare operator to be the array |
| 65864 | ** of integers in P4. |
| 65865 | ** |
| 65866 | ** The permutation is only valid until the next OP_Compare that has |
| 65867 | ** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should |
| 65868 | ** occur immediately prior to the OP_Compare. |
| 65869 | */ |
| 65870 | case OP_Permutation: { |
| 65871 | assert( pOp->p4type==P4_INTARRAY ); |
| 65872 | assert( pOp->p4.ai ); |
| 65873 | aPermute = pOp->p4.ai; |
| 65874 | break; |
| 65875 | } |
| 65876 | |
| 65877 | /* Opcode: Compare P1 P2 P3 P4 P5 |
| 65878 | ** |
| 65879 | ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this |
| 65880 | ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of |
| 65881 | ** the comparison for use by the next OP_Jump instruct. |
| 65882 | ** |
| 65883 | ** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is |
| 65884 | ** determined by the most recent OP_Permutation operator. If the |
| 65885 | ** OPFLAG_PERMUTE bit is clear, then register are compared in sequential |
| 65886 | ** order. |
| 65887 | ** |
| 65888 | ** P4 is a KeyInfo structure that defines collating sequences and sort |
| 65889 | ** orders for the comparison. The permutation applies to registers |
| 65890 | ** only. The KeyInfo elements are used sequentially. |
| 65891 | ** |
| @@ -65880,10 +65903,11 @@ | |
| 65903 | int idx; |
| 65904 | CollSeq *pColl; /* Collating sequence to use on this term */ |
| 65905 | int bRev; /* True for DESCENDING sort order */ |
| 65906 | #endif /* local variables moved into u.al */ |
| 65907 | |
| 65908 | if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0; |
| 65909 | u.al.n = pOp->p3; |
| 65910 | u.al.pKeyInfo = pOp->p4.pKeyInfo; |
| 65911 | assert( u.al.n>0 ); |
| 65912 | assert( u.al.pKeyInfo!=0 ); |
| 65913 | u.al.p1 = pOp->p1; |
| @@ -66025,12 +66049,10 @@ | |
| 66049 | |
| 66050 | /* Opcode: Once P1 P2 * * * |
| 66051 | ** |
| 66052 | ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, |
| 66053 | ** set the flag and fall through to the next instruction. |
| 66054 | */ |
| 66055 | case OP_Once: { /* jump */ |
| 66056 | assert( pOp->p1<p->nOnceFlag ); |
| 66057 | if( p->aOnceFlag[pOp->p1] ){ |
| 66058 | pc = pOp->p2-1; |
| @@ -71902,10 +71924,18 @@ | |
| 71924 | p->pReal = pReal; |
| 71925 | if( p->iSize>0 ){ |
| 71926 | assert(p->iSize<=p->nBuf); |
| 71927 | rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); |
| 71928 | } |
| 71929 | if( rc!=SQLITE_OK ){ |
| 71930 | /* If an error occurred while writing to the file, close it before |
| 71931 | ** returning. This way, SQLite uses the in-memory journal data to |
| 71932 | ** roll back changes made to the internal page-cache before this |
| 71933 | ** function was called. */ |
| 71934 | sqlite3OsClose(pReal); |
| 71935 | p->pReal = 0; |
| 71936 | } |
| 71937 | } |
| 71938 | } |
| 71939 | return rc; |
| 71940 | } |
| 71941 | |
| @@ -72565,10 +72595,19 @@ | |
| 72595 | ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 |
| 72596 | ** |
| 72597 | ** The result of random()%5 in the GROUP BY clause is probably different |
| 72598 | ** from the result in the result-set. We might fix this someday. Or |
| 72599 | ** then again, we might not... |
| 72600 | ** |
| 72601 | ** If the reference is followed by a COLLATE operator, then make sure |
| 72602 | ** the COLLATE operator is preserved. For example: |
| 72603 | ** |
| 72604 | ** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase; |
| 72605 | ** |
| 72606 | ** Should be transformed into: |
| 72607 | ** |
| 72608 | ** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; |
| 72609 | ** |
| 72610 | ** The nSubquery parameter specifies how many levels of subquery the |
| 72611 | ** alias is removed from the original expression. The usually value is |
| 72612 | ** zero but it might be more if the alias is contained within a subquery |
| 72613 | ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION |
| @@ -72589,45 +72628,40 @@ | |
| 72628 | assert( iCol>=0 && iCol<pEList->nExpr ); |
| 72629 | pOrig = pEList->a[iCol].pExpr; |
| 72630 | assert( pOrig!=0 ); |
| 72631 | assert( pOrig->flags & EP_Resolved ); |
| 72632 | db = pParse->db; |
| 72633 | pDup = sqlite3ExprDup(db, pOrig, 0); |
| 72634 | if( pDup==0 ) return; |
| 72635 | if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ |
| 72636 | incrAggFunctionDepth(pDup, nSubquery); |
| 72637 | pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); |
| 72638 | if( pDup==0 ) return; |
| 72639 | if( pEList->a[iCol].iAlias==0 ){ |
| 72640 | pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); |
| 72641 | } |
| 72642 | pDup->iTable = pEList->a[iCol].iAlias; |
| 72643 | } |
| 72644 | if( pExpr->op==TK_COLLATE ){ |
| 72645 | pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); |
| 72646 | } |
| 72647 | |
| 72648 | /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This |
| 72649 | ** prevents ExprDelete() from deleting the Expr structure itself, |
| 72650 | ** allowing it to be repopulated by the memcpy() on the following line. |
| 72651 | ** The pExpr->u.zToken might point into memory that will be freed by the |
| 72652 | ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to |
| 72653 | ** make a copy of the token before doing the sqlite3DbFree(). |
| 72654 | */ |
| 72655 | ExprSetProperty(pExpr, EP_Static); |
| 72656 | sqlite3ExprDelete(db, pExpr); |
| 72657 | memcpy(pExpr, pDup, sizeof(*pExpr)); |
| 72658 | if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ |
| 72659 | assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); |
| 72660 | pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); |
| 72661 | pExpr->flags2 |= EP2_MallocedToken; |
| 72662 | } |
| 72663 | sqlite3DbFree(db, pDup); |
| 72664 | } |
| 72665 | |
| 72666 | |
| 72667 | /* |
| @@ -72644,10 +72678,39 @@ | |
| 72678 | } |
| 72679 | } |
| 72680 | return 0; |
| 72681 | } |
| 72682 | |
| 72683 | /* |
| 72684 | ** Subqueries stores the original database, table and column names for their |
| 72685 | ** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN". |
| 72686 | ** Check to see if the zSpan given to this routine matches the zDb, zTab, |
| 72687 | ** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will |
| 72688 | ** match anything. |
| 72689 | */ |
| 72690 | SQLITE_PRIVATE int sqlite3MatchSpanName( |
| 72691 | const char *zSpan, |
| 72692 | const char *zCol, |
| 72693 | const char *zTab, |
| 72694 | const char *zDb |
| 72695 | ){ |
| 72696 | int n; |
| 72697 | for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} |
| 72698 | if( zDb && sqlite3StrNICmp(zSpan, zDb, n)!=0 ){ |
| 72699 | return 0; |
| 72700 | } |
| 72701 | zSpan += n+1; |
| 72702 | for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} |
| 72703 | if( zTab && sqlite3StrNICmp(zSpan, zTab, n)!=0 ){ |
| 72704 | return 0; |
| 72705 | } |
| 72706 | zSpan += n+1; |
| 72707 | if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ |
| 72708 | return 0; |
| 72709 | } |
| 72710 | return 1; |
| 72711 | } |
| 72712 | |
| 72713 | /* |
| 72714 | ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up |
| 72715 | ** that name in the set of source tables in pSrcList and make the pExpr |
| 72716 | ** expression node refer back to that source column. The following changes |
| @@ -72699,44 +72762,63 @@ | |
| 72762 | |
| 72763 | /* Initialize the node to no-match */ |
| 72764 | pExpr->iTable = -1; |
| 72765 | pExpr->pTab = 0; |
| 72766 | ExprSetIrreducible(pExpr); |
| 72767 | |
| 72768 | /* Translate the schema name in zDb into a pointer to the corresponding |
| 72769 | ** schema. If not found, pSchema will remain NULL and nothing will match |
| 72770 | ** resulting in an appropriate error message toward the end of this routine |
| 72771 | */ |
| 72772 | if( zDb ){ |
| 72773 | for(i=0; i<db->nDb; i++){ |
| 72774 | assert( db->aDb[i].zName ); |
| 72775 | if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){ |
| 72776 | pSchema = db->aDb[i].pSchema; |
| 72777 | break; |
| 72778 | } |
| 72779 | } |
| 72780 | } |
| 72781 | |
| 72782 | /* Start at the inner-most context and move outward until a match is found */ |
| 72783 | while( pNC && cnt==0 ){ |
| 72784 | ExprList *pEList; |
| 72785 | SrcList *pSrcList = pNC->pSrcList; |
| 72786 | |
| 72787 | if( pSrcList ){ |
| 72788 | for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ |
| 72789 | Table *pTab; |
| 72790 | Column *pCol; |
| 72791 | |
| 72792 | pTab = pItem->pTab; |
| 72793 | assert( pTab!=0 && pTab->zName!=0 ); |
| 72794 | assert( pTab->nCol>0 ); |
| 72795 | if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ |
| 72796 | ExprList *pEList = pItem->pSelect->pEList; |
| 72797 | int hit = 0; |
| 72798 | for(j=0; j<pEList->nExpr; j++){ |
| 72799 | if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){ |
| 72800 | cnt++; |
| 72801 | cntTab = 2; |
| 72802 | pMatch = pItem; |
| 72803 | pExpr->iColumn = j; |
| 72804 | hit = 1; |
| 72805 | } |
| 72806 | } |
| 72807 | if( hit || zTab==0 ) continue; |
| 72808 | } |
| 72809 | if( zDb && pTab->pSchema!=pSchema ){ |
| 72810 | continue; |
| 72811 | } |
| 72812 | if( zTab ){ |
| 72813 | const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; |
| 72814 | assert( zTabName!=0 ); |
| 72815 | if( sqlite3StrICmp(zTabName, zTab)!=0 ){ |
| 72816 | continue; |
| 72817 | } |
| 72818 | } |
| 72819 | if( 0==(cntTab++) ){ |
| 72820 | pMatch = pItem; |
| 72821 | } |
| 72822 | for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ |
| 72823 | if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ |
| 72824 | /* If there has been exactly one prior match and this match |
| @@ -72746,21 +72828,23 @@ | |
| 72828 | if( cnt==1 ){ |
| 72829 | if( pItem->jointype & JT_NATURAL ) continue; |
| 72830 | if( nameInUsingClause(pItem->pUsing, zCol) ) continue; |
| 72831 | } |
| 72832 | cnt++; |
| 72833 | pMatch = pItem; |
| 72834 | /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ |
| 72835 | pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; |
| 72836 | break; |
| 72837 | } |
| 72838 | } |
| 72839 | } |
| 72840 | if( pMatch ){ |
| 72841 | pExpr->iTable = pMatch->iCursor; |
| 72842 | pExpr->pTab = pMatch->pTab; |
| 72843 | pSchema = pExpr->pTab->pSchema; |
| 72844 | } |
| 72845 | } /* if( pSrcList ) */ |
| 72846 | |
| 72847 | #ifndef SQLITE_OMIT_TRIGGER |
| 72848 | /* If we have not already resolved the name, then maybe |
| 72849 | ** it is a new.* or old.* trigger argument reference |
| 72850 | */ |
| @@ -73055,42 +73139,43 @@ | |
| 73139 | int wrong_num_args = 0; /* True if wrong number of arguments */ |
| 73140 | int is_agg = 0; /* True if is an aggregate function */ |
| 73141 | int auth; /* Authorization to use the function */ |
| 73142 | int nId; /* Number of characters in function name */ |
| 73143 | const char *zId; /* The function name. */ |
| 73144 | u8 enc = ENC(pParse->db); /* The database encoding */ |
| 73145 | |
| 73146 | testcase( pExpr->op==TK_CONST_FUNC ); |
| 73147 | assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); |
| 73148 | zId = pExpr->u.zToken; |
| 73149 | nId = sqlite3Strlen30(zId); |
| 73150 | if( pParse->db->init.busy==0 ){ |
| 73151 | FuncDef *pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); |
| 73152 | if( pDef==0 ){ |
| 73153 | pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); |
| 73154 | if( pDef==0 ){ |
| 73155 | no_such_func = 1; |
| 73156 | }else{ |
| 73157 | wrong_num_args = 1; |
| 73158 | } |
| 73159 | }else{ |
| 73160 | is_agg = pDef->xFunc==0; |
| 73161 | } |
| 73162 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 73163 | if( pDef ){ |
| 73164 | auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); |
| 73165 | if( auth!=SQLITE_OK ){ |
| 73166 | if( auth==SQLITE_DENY ){ |
| 73167 | sqlite3ErrorMsg(pParse, "not authorized to use function: %s", |
| 73168 | pDef->zName); |
| 73169 | pNC->nErr++; |
| 73170 | } |
| 73171 | pExpr->op = TK_NULL; |
| 73172 | return WRC_Prune; |
| 73173 | } |
| 73174 | } |
| 73175 | #endif |
| 73176 | } |
| 73177 | if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ |
| 73178 | sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); |
| 73179 | pNC->nErr++; |
| 73180 | is_agg = 0; |
| 73181 | }else if( no_such_func ){ |
| @@ -73310,11 +73395,11 @@ | |
| 73395 | assert( pEList!=0 ); |
| 73396 | for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ |
| 73397 | int iCol = -1; |
| 73398 | Expr *pE, *pDup; |
| 73399 | if( pItem->done ) continue; |
| 73400 | pE = sqlite3ExprSkipCollate(pItem->pExpr); |
| 73401 | if( sqlite3ExprIsInteger(pE, &iCol) ){ |
| 73402 | if( iCol<=0 || iCol>pEList->nExpr ){ |
| 73403 | resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); |
| 73404 | return 1; |
| 73405 | } |
| @@ -73328,18 +73413,24 @@ | |
| 73413 | } |
| 73414 | sqlite3ExprDelete(db, pDup); |
| 73415 | } |
| 73416 | } |
| 73417 | if( iCol>0 ){ |
| 73418 | /* Convert the ORDER BY term into an integer column number iCol, |
| 73419 | ** taking care to preserve the COLLATE clause if it exists */ |
| 73420 | Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); |
| 73421 | if( pNew==0 ) return 1; |
| 73422 | pNew->flags |= EP_IntValue; |
| 73423 | pNew->u.iValue = iCol; |
| 73424 | if( pItem->pExpr==pE ){ |
| 73425 | pItem->pExpr = pNew; |
| 73426 | }else{ |
| 73427 | assert( pItem->pExpr->op==TK_COLLATE ); |
| 73428 | assert( pItem->pExpr->pLeft==pE ); |
| 73429 | pItem->pExpr->pLeft = pNew; |
| 73430 | } |
| 73431 | sqlite3ExprDelete(db, pE); |
| 73432 | pItem->iOrderByCol = (u16)iCol; |
| 73433 | pItem->done = 1; |
| 73434 | }else{ |
| 73435 | moreToDo = 1; |
| 73436 | } |
| @@ -73440,15 +73531,15 @@ | |
| 73531 | ** sqlite3ResolveOrderGroupBy() will convert the expression to a |
| 73532 | ** copy of the iCol-th result-set expression. */ |
| 73533 | pItem->iOrderByCol = (u16)iCol; |
| 73534 | continue; |
| 73535 | } |
| 73536 | if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){ |
| 73537 | /* The ORDER BY term is an integer constant. Again, set the column |
| 73538 | ** number so that sqlite3ResolveOrderGroupBy() will convert the |
| 73539 | ** order-by term to a copy of the result-set expression */ |
| 73540 | if( iCol<1 || iCol>0xffff ){ |
| 73541 | resolveOutOfRangeError(pParse, zType, i+1, nResult); |
| 73542 | return 1; |
| 73543 | } |
| 73544 | pItem->iOrderByCol = (u16)iCol; |
| 73545 | continue; |
| @@ -73521,27 +73612,10 @@ | |
| 73612 | if( sqlite3ResolveExprNames(&sNC, p->pLimit) || |
| 73613 | sqlite3ResolveExprNames(&sNC, p->pOffset) ){ |
| 73614 | return WRC_Abort; |
| 73615 | } |
| 73616 | |
| 73617 | /* Recursively resolve names in all subqueries |
| 73618 | */ |
| 73619 | for(i=0; i<p->pSrc->nSrc; i++){ |
| 73620 | struct SrcList_item *pItem = &p->pSrc->a[i]; |
| 73621 | if( pItem->pSelect ){ |
| @@ -73564,10 +73638,27 @@ | |
| 73638 | for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; |
| 73639 | assert( pItem->isCorrelated==0 && nRef<=0 ); |
| 73640 | pItem->isCorrelated = (nRef!=0); |
| 73641 | } |
| 73642 | } |
| 73643 | |
| 73644 | /* Set up the local name-context to pass to sqlite3ResolveExprNames() to |
| 73645 | ** resolve the result-set expression list. |
| 73646 | */ |
| 73647 | sNC.ncFlags = NC_AllowAgg; |
| 73648 | sNC.pSrcList = p->pSrc; |
| 73649 | sNC.pNext = pOuterNC; |
| 73650 | |
| 73651 | /* Resolve names in the result set. */ |
| 73652 | pEList = p->pEList; |
| 73653 | assert( pEList!=0 ); |
| 73654 | for(i=0; i<pEList->nExpr; i++){ |
| 73655 | Expr *pX = pEList->a[i].pExpr; |
| 73656 | if( sqlite3ResolveExprNames(&sNC, pX) ){ |
| 73657 | return WRC_Abort; |
| 73658 | } |
| 73659 | } |
| 73660 | |
| 73661 | /* If there are no aggregate functions in the result-set, and no GROUP BY |
| 73662 | ** expression, do not allow aggregates in any of the other expressions. |
| 73663 | */ |
| 73664 | assert( (p->selFlags & SF_Aggregate)==0 ); |
| @@ -73798,11 +73889,13 @@ | |
| 73889 | ** SELECT * FROM t1 WHERE a; |
| 73890 | ** SELECT a AS b FROM t1 WHERE b; |
| 73891 | ** SELECT * FROM t1 WHERE (select a from t1); |
| 73892 | */ |
| 73893 | SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ |
| 73894 | int op; |
| 73895 | pExpr = sqlite3ExprSkipCollate(pExpr); |
| 73896 | op = pExpr->op; |
| 73897 | if( op==TK_SELECT ){ |
| 73898 | assert( pExpr->flags&EP_xIsSelect ); |
| 73899 | return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); |
| 73900 | } |
| 73901 | #ifndef SQLITE_OMIT_CAST |
| @@ -73823,70 +73916,98 @@ | |
| 73916 | } |
| 73917 | return pExpr->affinity; |
| 73918 | } |
| 73919 | |
| 73920 | /* |
| 73921 | ** Set the collating sequence for expression pExpr to be the collating |
| 73922 | ** sequence named by pToken. Return a pointer to a new Expr node that |
| 73923 | ** implements the COLLATE operator. |
| 73924 | ** |
| 73925 | ** If a memory allocation error occurs, that fact is recorded in pParse->db |
| 73926 | ** and the pExpr parameter is returned unchanged. |
| 73927 | */ |
| 73928 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){ |
| 73929 | if( pCollName->n>0 ){ |
| 73930 | Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); |
| 73931 | if( pNew ){ |
| 73932 | pNew->pLeft = pExpr; |
| 73933 | pNew->flags |= EP_Collate; |
| 73934 | pExpr = pNew; |
| 73935 | } |
| 73936 | } |
| 73937 | return pExpr; |
| 73938 | } |
| 73939 | SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ |
| 73940 | Token s; |
| 73941 | assert( zC!=0 ); |
| 73942 | s.z = zC; |
| 73943 | s.n = sqlite3Strlen30(s.z); |
| 73944 | return sqlite3ExprAddCollateToken(pParse, pExpr, &s); |
| 73945 | } |
| 73946 | |
| 73947 | /* |
| 73948 | ** Skip over any TK_COLLATE and/or TK_AS operators at the root of |
| 73949 | ** an expression. |
| 73950 | */ |
| 73951 | SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ |
| 73952 | while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){ |
| 73953 | pExpr = pExpr->pLeft; |
| 73954 | } |
| 73955 | return pExpr; |
| 73956 | } |
| 73957 | |
| 73958 | /* |
| 73959 | ** Return the collation sequence for the expression pExpr. If |
| 73960 | ** there is no defined collating sequence, return NULL. |
| 73961 | ** |
| 73962 | ** The collating sequence might be determined by a COLLATE operator |
| 73963 | ** or by the presence of a column with a defined collating sequence. |
| 73964 | ** COLLATE operators take first precedence. Left operands take |
| 73965 | ** precedence over right operands. |
| 73966 | */ |
| 73967 | SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ |
| 73968 | sqlite3 *db = pParse->db; |
| 73969 | CollSeq *pColl = 0; |
| 73970 | Expr *p = pExpr; |
| 73971 | while( p ){ |
| 73972 | int op = p->op; |
| 73973 | if( op==TK_CAST || op==TK_UPLUS ){ |
| 73974 | p = p->pLeft; |
| 73975 | continue; |
| 73976 | } |
| 73977 | assert( op!=TK_REGISTER || p->op2!=TK_COLLATE ); |
| 73978 | if( op==TK_COLLATE ){ |
| 73979 | if( db->init.busy ){ |
| 73980 | /* Do not report errors when parsing while the schema */ |
| 73981 | pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0); |
| 73982 | }else{ |
| 73983 | pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); |
| 73984 | } |
| 73985 | break; |
| 73986 | } |
| 73987 | if( p->pTab!=0 |
| 73988 | && (op==TK_AGG_COLUMN || op==TK_COLUMN |
| 73989 | || op==TK_REGISTER || op==TK_TRIGGER) |
| 73990 | ){ |
| 73991 | /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally |
| 73992 | ** a TK_COLUMN but was previously evaluated and cached in a register */ |
| 73993 | int j = p->iColumn; |
| 73994 | if( j>=0 ){ |
| 73995 | const char *zColl = p->pTab->aCol[j].zColl; |
| 73996 | pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); |
| 73997 | } |
| 73998 | break; |
| 73999 | } |
| 74000 | if( p->flags & EP_Collate ){ |
| 74001 | if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ |
| 74002 | p = p->pLeft; |
| 74003 | }else{ |
| 74004 | p = p->pRight; |
| 74005 | } |
| 74006 | }else{ |
| 74007 | break; |
| 74008 | } |
| 74009 | } |
| 74010 | if( sqlite3CheckCollSeq(pParse, pColl) ){ |
| 74011 | pColl = 0; |
| 74012 | } |
| 74013 | return pColl; |
| @@ -73986,16 +74107,14 @@ | |
| 74107 | Expr *pLeft, |
| 74108 | Expr *pRight |
| 74109 | ){ |
| 74110 | CollSeq *pColl; |
| 74111 | assert( pLeft ); |
| 74112 | if( pLeft->flags & EP_Collate ){ |
| 74113 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 74114 | }else if( pRight && (pRight->flags & EP_Collate)!=0 ){ |
| 74115 | pColl = sqlite3ExprCollSeq(pParse, pRight); |
| 74116 | }else{ |
| 74117 | pColl = sqlite3ExprCollSeq(pParse, pLeft); |
| 74118 | if( !pColl ){ |
| 74119 | pColl = sqlite3ExprCollSeq(pParse, pRight); |
| 74120 | } |
| @@ -74221,21 +74340,15 @@ | |
| 74340 | sqlite3ExprDelete(db, pLeft); |
| 74341 | sqlite3ExprDelete(db, pRight); |
| 74342 | }else{ |
| 74343 | if( pRight ){ |
| 74344 | pRoot->pRight = pRight; |
| 74345 | pRoot->flags |= EP_Collate & pRight->flags; |
| 74346 | } |
| 74347 | if( pLeft ){ |
| 74348 | pRoot->pLeft = pLeft; |
| 74349 | pRoot->flags |= EP_Collate & pLeft->flags; |
| 74350 | } |
| 74351 | exprSetHeight(pRoot); |
| 74352 | } |
| 74353 | } |
| 74354 | |
| @@ -74489,11 +74602,11 @@ | |
| 74602 | }else{ |
| 74603 | assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); |
| 74604 | assert( !ExprHasProperty(p, EP_FromJoin) ); |
| 74605 | assert( (p->flags2 & EP2_MallocedToken)==0 ); |
| 74606 | assert( (p->flags2 & EP2_Irreducible)==0 ); |
| 74607 | if( p->pLeft || p->pRight || p->x.pList ){ |
| 74608 | nSize = EXPR_REDUCEDSIZE | EP_Reduced; |
| 74609 | }else{ |
| 74610 | nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; |
| 74611 | } |
| 74612 | } |
| @@ -76513,10 +76626,11 @@ | |
| 76626 | sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); |
| 76627 | sqlite3ReleaseTempReg(pParse, r3); |
| 76628 | sqlite3ReleaseTempReg(pParse, r4); |
| 76629 | break; |
| 76630 | } |
| 76631 | case TK_COLLATE: |
| 76632 | case TK_UPLUS: { |
| 76633 | inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); |
| 76634 | break; |
| 76635 | } |
| 76636 | |
| @@ -76881,10 +76995,16 @@ | |
| 76995 | case TK_UPLUS: zUniOp = "UPLUS"; break; |
| 76996 | case TK_BITNOT: zUniOp = "BITNOT"; break; |
| 76997 | case TK_NOT: zUniOp = "NOT"; break; |
| 76998 | case TK_ISNULL: zUniOp = "ISNULL"; break; |
| 76999 | case TK_NOTNULL: zUniOp = "NOTNULL"; break; |
| 77000 | |
| 77001 | case TK_COLLATE: { |
| 77002 | sqlite3ExplainExpr(pOut, pExpr->pLeft); |
| 77003 | sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken); |
| 77004 | break; |
| 77005 | } |
| 77006 | |
| 77007 | case TK_AGG_FUNCTION: |
| 77008 | case TK_CONST_FUNC: |
| 77009 | case TK_FUNCTION: { |
| 77010 | ExprList *pFarg; /* List of function arguments */ |
| @@ -77019,10 +77139,16 @@ | |
| 77139 | for(i=0; i<pList->nExpr; i++){ |
| 77140 | sqlite3ExplainPrintf(pOut, "item[%d] = ", i); |
| 77141 | sqlite3ExplainPush(pOut); |
| 77142 | sqlite3ExplainExpr(pOut, pList->a[i].pExpr); |
| 77143 | sqlite3ExplainPop(pOut); |
| 77144 | if( pList->a[i].zName ){ |
| 77145 | sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName); |
| 77146 | } |
| 77147 | if( pList->a[i].bSpanIsTab ){ |
| 77148 | sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan); |
| 77149 | } |
| 77150 | if( i<pList->nExpr-1 ){ |
| 77151 | sqlite3ExplainNL(pOut); |
| 77152 | } |
| 77153 | } |
| 77154 | sqlite3ExplainPop(pOut); |
| @@ -77100,10 +77226,13 @@ | |
| 77226 | switch( pExpr->op ){ |
| 77227 | case TK_IN: |
| 77228 | case TK_REGISTER: { |
| 77229 | return WRC_Prune; |
| 77230 | } |
| 77231 | case TK_COLLATE: { |
| 77232 | return WRC_Continue; |
| 77233 | } |
| 77234 | case TK_FUNCTION: |
| 77235 | case TK_AGG_FUNCTION: |
| 77236 | case TK_CONST_FUNC: { |
| 77237 | /* The arguments to a function have a fixed destination. |
| 77238 | ** Mark them this way to avoid generated unneeded OP_SCopy |
| @@ -77121,13 +77250,15 @@ | |
| 77250 | break; |
| 77251 | } |
| 77252 | } |
| 77253 | if( isAppropriateForFactoring(pExpr) ){ |
| 77254 | int r1 = ++pParse->nMem; |
| 77255 | int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); |
| 77256 | /* If r2!=r1, it means that register r1 is never used. That is harmless |
| 77257 | ** but suboptimal, so we want to know about the situation to fix it. |
| 77258 | ** Hence the following assert: */ |
| 77259 | assert( r2==r1 ); |
| 77260 | pExpr->op2 = pExpr->op; |
| 77261 | pExpr->op = TK_REGISTER; |
| 77262 | pExpr->iTable = r2; |
| 77263 | return WRC_Prune; |
| 77264 | } |
| @@ -77540,11 +77671,19 @@ | |
| 77671 | assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); |
| 77672 | if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ |
| 77673 | return 2; |
| 77674 | } |
| 77675 | if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; |
| 77676 | if( pA->op!=pB->op ){ |
| 77677 | if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){ |
| 77678 | return 1; |
| 77679 | } |
| 77680 | if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){ |
| 77681 | return 1; |
| 77682 | } |
| 77683 | return 2; |
| 77684 | } |
| 77685 | if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; |
| 77686 | if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; |
| 77687 | if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; |
| 77688 | if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; |
| 77689 | if( ExprHasProperty(pA, EP_IntValue) ){ |
| @@ -77552,15 +77691,13 @@ | |
| 77691 | return 2; |
| 77692 | } |
| 77693 | }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){ |
| 77694 | if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; |
| 77695 | if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
| 77696 | return pA->op==TK_COLLATE ? 1 : 2; |
| 77697 | } |
| 77698 | } |
| 77699 | return 0; |
| 77700 | } |
| 77701 | |
| 77702 | /* |
| 77703 | ** Compare two ExprList objects. Return 0 if they are identical and |
| @@ -83371,14 +83508,12 @@ | |
| 83508 | ** specified collation sequence names. |
| 83509 | */ |
| 83510 | for(i=0; i<pList->nExpr; i++){ |
| 83511 | Expr *pExpr = pList->a[i].pExpr; |
| 83512 | if( pExpr ){ |
| 83513 | CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); |
| 83514 | if( pColl ){ |
| 83515 | nExtra += (1 + sqlite3Strlen30(pColl->zName)); |
| 83516 | } |
| 83517 | } |
| 83518 | } |
| 83519 | |
| @@ -83437,10 +83572,11 @@ | |
| 83572 | */ |
| 83573 | for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ |
| 83574 | const char *zColName = pListItem->zName; |
| 83575 | Column *pTabCol; |
| 83576 | int requestedSortOrder; |
| 83577 | CollSeq *pColl; /* Collating sequence */ |
| 83578 | char *zColl; /* Collation sequence name */ |
| 83579 | |
| 83580 | for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ |
| 83581 | if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; |
| 83582 | } |
| @@ -83449,18 +83585,15 @@ | |
| 83585 | pTab->zName, zColName); |
| 83586 | pParse->checkSchema = 1; |
| 83587 | goto exit_create_index; |
| 83588 | } |
| 83589 | pIndex->aiColumn[i] = j; |
| 83590 | if( pListItem->pExpr |
| 83591 | && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0 |
| 83592 | ){ |
| 83593 | int nColl; |
| 83594 | zColl = pColl->zName; |
| 83595 | nColl = sqlite3Strlen30(zColl) + 1; |
| 83596 | assert( nExtra>=nColl ); |
| 83597 | memcpy(zExtra, zColl, nColl); |
| 83598 | zColl = zExtra; |
| 83599 | zExtra += nColl; |
| @@ -87489,11 +87622,11 @@ | |
| 87622 | |
| 87623 | /* |
| 87624 | ** A foreign key constraint requires that the key columns in the parent |
| 87625 | ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint. |
| 87626 | ** Given that pParent is the parent table for foreign key constraint pFKey, |
| 87627 | ** search the schema for a unique index on the parent key columns. |
| 87628 | ** |
| 87629 | ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY |
| 87630 | ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx |
| 87631 | ** is set to point to the unique index. |
| 87632 | ** |
| @@ -87525,11 +87658,11 @@ | |
| 87658 | ** |
| 87659 | ** then non-zero is returned, and a "foreign key mismatch" error loaded |
| 87660 | ** into pParse. If an OOM error occurs, non-zero is returned and the |
| 87661 | ** pParse->db->mallocFailed flag is set. |
| 87662 | */ |
| 87663 | SQLITE_PRIVATE int sqlite3FkLocateIndex( |
| 87664 | Parse *pParse, /* Parse context to store any error in */ |
| 87665 | Table *pParent, /* Parent table of FK constraint pFKey */ |
| 87666 | FKey *pFKey, /* Foreign key to find index for */ |
| 87667 | Index **ppIdx, /* OUT: Unique index on parent table */ |
| 87668 | int **paiCol /* OUT: Map of index columns in pFKey */ |
| @@ -87622,11 +87755,13 @@ | |
| 87755 | } |
| 87756 | } |
| 87757 | |
| 87758 | if( !pIdx ){ |
| 87759 | if( !pParse->disableTriggers ){ |
| 87760 | sqlite3ErrorMsg(pParse, |
| 87761 | "foreign key mismatch - \"%w\" referencing \"%w\"", |
| 87762 | pFKey->pFrom->zName, pFKey->zTo); |
| 87763 | } |
| 87764 | sqlite3DbFree(pParse->db, aiCol); |
| 87765 | return 1; |
| 87766 | } |
| 87767 | |
| @@ -87858,16 +87993,19 @@ | |
| 87993 | if( pLeft ){ |
| 87994 | /* Set the collation sequence and affinity of the LHS of each TK_EQ |
| 87995 | ** expression to the parent key column defaults. */ |
| 87996 | if( pIdx ){ |
| 87997 | Column *pCol; |
| 87998 | const char *zColl; |
| 87999 | iCol = pIdx->aiColumn[i]; |
| 88000 | pCol = &pTab->aCol[iCol]; |
| 88001 | if( pTab->iPKey==iCol ) iCol = -1; |
| 88002 | pLeft->iTable = regData+iCol+1; |
| 88003 | pLeft->affinity = pCol->affinity; |
| 88004 | zColl = pCol->zColl; |
| 88005 | if( zColl==0 ) zColl = db->pDfltColl->zName; |
| 88006 | pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl); |
| 88007 | }else{ |
| 88008 | pLeft->iTable = regData; |
| 88009 | pLeft->affinity = SQLITE_AFF_INTEGER; |
| 88010 | } |
| 88011 | } |
| @@ -88080,11 +88218,11 @@ | |
| 88218 | if( pParse->disableTriggers ){ |
| 88219 | pTo = sqlite3FindTable(db, pFKey->zTo, zDb); |
| 88220 | }else{ |
| 88221 | pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb); |
| 88222 | } |
| 88223 | if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){ |
| 88224 | assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) ); |
| 88225 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88226 | if( pTo==0 ){ |
| 88227 | /* If isIgnoreErrors is true, then a table is being dropped. In this |
| 88228 | ** case SQLite runs a "DELETE FROM xxx" on the table being dropped |
| @@ -88160,11 +88298,11 @@ | |
| 88298 | /* Inserting a single row into a parent table cannot cause an immediate |
| 88299 | ** foreign key violation. So do nothing in this case. */ |
| 88300 | continue; |
| 88301 | } |
| 88302 | |
| 88303 | if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 88304 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| 88305 | continue; |
| 88306 | } |
| 88307 | assert( aiCol || pFKey->nCol==1 ); |
| 88308 | |
| @@ -88215,11 +88353,11 @@ | |
| 88353 | for(p=pTab->pFKey; p; p=p->pNextFrom){ |
| 88354 | for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom); |
| 88355 | } |
| 88356 | for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ |
| 88357 | Index *pIdx = 0; |
| 88358 | sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0); |
| 88359 | if( pIdx ){ |
| 88360 | for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]); |
| 88361 | } |
| 88362 | } |
| 88363 | } |
| @@ -88341,11 +88479,11 @@ | |
| 88479 | ExprList *pList = 0; /* Changes list if ON UPDATE CASCADE */ |
| 88480 | Select *pSelect = 0; /* If RESTRICT, "SELECT RAISE(...)" */ |
| 88481 | int i; /* Iterator variable */ |
| 88482 | Expr *pWhen = 0; /* WHEN clause for the trigger */ |
| 88483 | |
| 88484 | if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0; |
| 88485 | assert( aiCol || pFKey->nCol==1 ); |
| 88486 | |
| 88487 | for(i=0; i<pFKey->nCol; i++){ |
| 88488 | Token tOld = { "old", 3 }; /* Literal "old" token */ |
| 88489 | Token tNew = { "new", 3 }; /* Literal "new" token */ |
| @@ -89843,29 +89981,24 @@ | |
| 89981 | ExprList *pCheck = pTab->pCheck; |
| 89982 | pParse->ckBase = regData; |
| 89983 | onError = overrideError!=OE_Default ? overrideError : OE_Abort; |
| 89984 | for(i=0; i<pCheck->nExpr; i++){ |
| 89985 | int allOk = sqlite3VdbeMakeLabel(v); |
| 89986 | sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); |
| 89987 | if( onError==OE_Ignore ){ |
| 89988 | sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); |
| 89989 | }else{ |
| 89990 | char *zConsName = pCheck->a[i].zName; |
| 89991 | if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ |
| 89992 | if( zConsName ){ |
| 89993 | zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); |
| 89994 | }else{ |
| 89995 | zConsName = 0; |
| 89996 | } |
| 89997 | sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); |
| 89998 | } |
| 89999 | sqlite3VdbeResolveLabel(v, allOk); |
| 90000 | } |
| 90001 | } |
| 90002 | #endif /* !defined(SQLITE_OMIT_CHECK) */ |
| 90003 | |
| 90004 | /* If we have an INTEGER PRIMARY KEY, make sure the primary key |
| @@ -92686,13 +92819,15 @@ | |
| 92819 | if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ |
| 92820 | Table *pTab; |
| 92821 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 92822 | pTab = sqlite3FindTable(db, zRight, zDb); |
| 92823 | if( pTab ){ |
| 92824 | int i, k; |
| 92825 | int nHidden = 0; |
| 92826 | Column *pCol; |
| 92827 | Index *pPk; |
| 92828 | for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){} |
| 92829 | sqlite3VdbeSetNumCols(v, 6); |
| 92830 | pParse->nMem = 6; |
| 92831 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC); |
| 92832 | sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); |
| 92833 | sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC); |
| @@ -92713,12 +92848,18 @@ | |
| 92848 | if( pCol->zDflt ){ |
| 92849 | sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0); |
| 92850 | }else{ |
| 92851 | sqlite3VdbeAddOp2(v, OP_Null, 0, 5); |
| 92852 | } |
| 92853 | if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){ |
| 92854 | k = 0; |
| 92855 | }else if( pPk==0 ){ |
| 92856 | k = 1; |
| 92857 | }else{ |
| 92858 | for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){} |
| 92859 | } |
| 92860 | sqlite3VdbeAddOp2(v, OP_Integer, k, 6); |
| 92861 | sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); |
| 92862 | } |
| 92863 | } |
| 92864 | }else |
| 92865 | |
| @@ -92849,10 +92990,124 @@ | |
| 92990 | ++i; |
| 92991 | pFK = pFK->pNextFrom; |
| 92992 | } |
| 92993 | } |
| 92994 | } |
| 92995 | }else |
| 92996 | #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
| 92997 | |
| 92998 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 92999 | if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){ |
| 93000 | FKey *pFK; /* A foreign key constraint */ |
| 93001 | Table *pTab; /* Child table contain "REFERENCES" keyword */ |
| 93002 | Table *pParent; /* Parent table that child points to */ |
| 93003 | Index *pIdx; /* Index in the parent table */ |
| 93004 | int i; /* Loop counter: Foreign key number for pTab */ |
| 93005 | int j; /* Loop counter: Field of the foreign key */ |
| 93006 | HashElem *k; /* Loop counter: Next table in schema */ |
| 93007 | int x; /* result variable */ |
| 93008 | int regResult; /* 3 registers to hold a result row */ |
| 93009 | int regKey; /* Register to hold key for checking the FK */ |
| 93010 | int regRow; /* Registers to hold a row from pTab */ |
| 93011 | int addrTop; /* Top of a loop checking foreign keys */ |
| 93012 | int addrOk; /* Jump here if the key is OK */ |
| 93013 | int *aiCols; /* child to parent column mapping */ |
| 93014 | |
| 93015 | if( sqlite3ReadSchema(pParse) ) goto pragma_out; |
| 93016 | regResult = pParse->nMem+1; |
| 93017 | pParse->nMem += 4; |
| 93018 | regKey = ++pParse->nMem; |
| 93019 | regRow = ++pParse->nMem; |
| 93020 | v = sqlite3GetVdbe(pParse); |
| 93021 | sqlite3VdbeSetNumCols(v, 4); |
| 93022 | sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC); |
| 93023 | sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC); |
| 93024 | sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC); |
| 93025 | sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC); |
| 93026 | sqlite3CodeVerifySchema(pParse, iDb); |
| 93027 | k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); |
| 93028 | while( k ){ |
| 93029 | if( zRight ){ |
| 93030 | pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); |
| 93031 | k = 0; |
| 93032 | }else{ |
| 93033 | pTab = (Table*)sqliteHashData(k); |
| 93034 | k = sqliteHashNext(k); |
| 93035 | } |
| 93036 | if( pTab==0 || pTab->pFKey==0 ) continue; |
| 93037 | sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); |
| 93038 | if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; |
| 93039 | sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); |
| 93040 | sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName, |
| 93041 | P4_TRANSIENT); |
| 93042 | for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ |
| 93043 | pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); |
| 93044 | if( pParent==0 ) break; |
| 93045 | pIdx = 0; |
| 93046 | sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); |
| 93047 | x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); |
| 93048 | if( x==0 ){ |
| 93049 | if( pIdx==0 ){ |
| 93050 | sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); |
| 93051 | }else{ |
| 93052 | KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); |
| 93053 | sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); |
| 93054 | sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF); |
| 93055 | } |
| 93056 | }else{ |
| 93057 | k = 0; |
| 93058 | break; |
| 93059 | } |
| 93060 | } |
| 93061 | if( pFK ) break; |
| 93062 | if( pParse->nTab<i ) pParse->nTab = i; |
| 93063 | addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); |
| 93064 | for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ |
| 93065 | pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb); |
| 93066 | assert( pParent!=0 ); |
| 93067 | pIdx = 0; |
| 93068 | aiCols = 0; |
| 93069 | x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols); |
| 93070 | assert( x==0 ); |
| 93071 | addrOk = sqlite3VdbeMakeLabel(v); |
| 93072 | if( pIdx==0 ){ |
| 93073 | int iKey = pFK->aCol[0].iFrom; |
| 93074 | assert( iKey>=0 && iKey<pTab->nCol ); |
| 93075 | if( iKey!=pTab->iPKey ){ |
| 93076 | sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow); |
| 93077 | sqlite3ColumnDefault(v, pTab, iKey, regRow); |
| 93078 | sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); |
| 93079 | sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow, |
| 93080 | sqlite3VdbeCurrentAddr(v)+3); |
| 93081 | }else{ |
| 93082 | sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow); |
| 93083 | } |
| 93084 | sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow); |
| 93085 | sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk); |
| 93086 | sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); |
| 93087 | }else{ |
| 93088 | for(j=0; j<pFK->nCol; j++){ |
| 93089 | sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, |
| 93090 | aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j); |
| 93091 | sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); |
| 93092 | } |
| 93093 | sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey); |
| 93094 | sqlite3VdbeChangeP4(v, -1, |
| 93095 | sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT); |
| 93096 | sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); |
| 93097 | } |
| 93098 | sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1); |
| 93099 | sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, |
| 93100 | pFK->zTo, P4_TRANSIENT); |
| 93101 | sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3); |
| 93102 | sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); |
| 93103 | sqlite3VdbeResolveLabel(v, addrOk); |
| 93104 | sqlite3DbFree(db, aiCols); |
| 93105 | } |
| 93106 | sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1); |
| 93107 | sqlite3VdbeJumpHere(v, addrTop); |
| 93108 | } |
| 93109 | }else |
| 93110 | #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ |
| 93111 | |
| 93112 | #ifndef NDEBUG |
| 93113 | if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ |
| @@ -94308,11 +94563,11 @@ | |
| 94563 | SrcList *pSrc, /* the FROM clause -- which tables to scan */ |
| 94564 | Expr *pWhere, /* the WHERE clause */ |
| 94565 | ExprList *pGroupBy, /* the GROUP BY clause */ |
| 94566 | Expr *pHaving, /* the HAVING clause */ |
| 94567 | ExprList *pOrderBy, /* the ORDER BY clause */ |
| 94568 | u16 selFlags, /* Flag parameters, such as SF_Distinct */ |
| 94569 | Expr *pLimit, /* LIMIT value. NULL means not used */ |
| 94570 | Expr *pOffset /* OFFSET value. NULL means no offset */ |
| 94571 | ){ |
| 94572 | Select *pNew; |
| 94573 | Select standin; |
| @@ -94332,11 +94587,11 @@ | |
| 94587 | pNew->pSrc = pSrc; |
| 94588 | pNew->pWhere = pWhere; |
| 94589 | pNew->pGroupBy = pGroupBy; |
| 94590 | pNew->pHaving = pHaving; |
| 94591 | pNew->pOrderBy = pOrderBy; |
| 94592 | pNew->selFlags = selFlags; |
| 94593 | pNew->op = TK_SELECT; |
| 94594 | pNew->pLimit = pLimit; |
| 94595 | pNew->pOffset = pOffset; |
| 94596 | assert( pOffset==0 || pLimit!=0 ); |
| 94597 | pNew->addrOpenEphm[0] = -1; |
| @@ -95588,13 +95843,11 @@ | |
| 95843 | *paCol = aCol; |
| 95844 | |
| 95845 | for(i=0, pCol=aCol; i<nCol; i++, pCol++){ |
| 95846 | /* Get an appropriate name for the column |
| 95847 | */ |
| 95848 | p = sqlite3ExprSkipCollate(pEList->a[i].pExpr); |
| 95849 | if( (zName = pEList->a[i].zName)!=0 ){ |
| 95850 | /* If the column contains an "AS <name>" phrase, use <name> as the name */ |
| 95851 | zName = sqlite3DbStrDup(db, zName); |
| 95852 | }else{ |
| 95853 | Expr *pColExpr = p; /* The expression that is the result column name */ |
| @@ -95628,10 +95881,13 @@ | |
| 95881 | */ |
| 95882 | nName = sqlite3Strlen30(zName); |
| 95883 | for(j=cnt=0; j<i; j++){ |
| 95884 | if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ |
| 95885 | char *zNewName; |
| 95886 | int k; |
| 95887 | for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){} |
| 95888 | if( zName[k]==':' ) nName = k; |
| 95889 | zName[nName] = 0; |
| 95890 | zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); |
| 95891 | sqlite3DbFree(db, zName); |
| 95892 | zName = zNewName; |
| 95893 | j = -1; |
| @@ -96586,16 +96842,17 @@ | |
| 96842 | pKeyMerge->nField = (u16)nOrderBy; |
| 96843 | pKeyMerge->enc = ENC(db); |
| 96844 | for(i=0; i<nOrderBy; i++){ |
| 96845 | CollSeq *pColl; |
| 96846 | Expr *pTerm = pOrderBy->a[i].pExpr; |
| 96847 | if( pTerm->flags & EP_Collate ){ |
| 96848 | pColl = sqlite3ExprCollSeq(pParse, pTerm); |
| 96849 | }else{ |
| 96850 | pColl = multiSelectCollSeq(pParse, p, aPermute[i]); |
| 96851 | if( pColl==0 ) pColl = db->pDfltColl; |
| 96852 | pOrderBy->a[i].pExpr = |
| 96853 | sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); |
| 96854 | } |
| 96855 | pKeyMerge->aColl[i] = pColl; |
| 96856 | pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; |
| 96857 | } |
| 96858 | } |
| @@ -96794,10 +97051,11 @@ | |
| 97051 | */ |
| 97052 | sqlite3VdbeResolveLabel(v, labelCmpr); |
| 97053 | sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); |
| 97054 | sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, |
| 97055 | (char*)pKeyMerge, P4_KEYINFO_HANDOFF); |
| 97056 | sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); |
| 97057 | sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); |
| 97058 | |
| 97059 | /* Release temporary registers |
| 97060 | */ |
| 97061 | if( regPrev ){ |
| @@ -96861,13 +97119,10 @@ | |
| 97119 | }else{ |
| 97120 | Expr *pNew; |
| 97121 | assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); |
| 97122 | assert( pExpr->pLeft==0 && pExpr->pRight==0 ); |
| 97123 | pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); |
| 97124 | sqlite3ExprDelete(db, pExpr); |
| 97125 | pExpr = pNew; |
| 97126 | } |
| 97127 | }else{ |
| 97128 | pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); |
| @@ -97414,38 +97669,47 @@ | |
| 97669 | return 1; |
| 97670 | } |
| 97671 | #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
| 97672 | |
| 97673 | /* |
| 97674 | ** Based on the contents of the AggInfo structure indicated by the first |
| 97675 | ** argument, this function checks if the following are true: |
| 97676 | ** |
| 97677 | ** * the query contains just a single aggregate function, |
| 97678 | ** * the aggregate function is either min() or max(), and |
| 97679 | ** * the argument to the aggregate function is a column value. |
| 97680 | ** |
| 97681 | ** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX |
| 97682 | ** is returned as appropriate. Also, *ppMinMax is set to point to the |
| 97683 | ** list of arguments passed to the aggregate before returning. |
| 97684 | ** |
| 97685 | ** Or, if the conditions above are not met, *ppMinMax is set to 0 and |
| 97686 | ** WHERE_ORDERBY_NORMAL is returned. |
| 97687 | */ |
| 97688 | static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ |
| 97689 | int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ |
| 97690 | |
| 97691 | *ppMinMax = 0; |
| 97692 | if( pAggInfo->nFunc==1 ){ |
| 97693 | Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ |
| 97694 | ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ |
| 97695 | |
| 97696 | assert( pExpr->op==TK_AGG_FUNCTION ); |
| 97697 | if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ |
| 97698 | const char *zFunc = pExpr->u.zToken; |
| 97699 | if( sqlite3StrICmp(zFunc, "min")==0 ){ |
| 97700 | eRet = WHERE_ORDERBY_MIN; |
| 97701 | *ppMinMax = pEList; |
| 97702 | }else if( sqlite3StrICmp(zFunc, "max")==0 ){ |
| 97703 | eRet = WHERE_ORDERBY_MAX; |
| 97704 | *ppMinMax = pEList; |
| 97705 | } |
| 97706 | } |
| 97707 | } |
| 97708 | |
| 97709 | assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); |
| 97710 | return eRet; |
| 97711 | } |
| 97712 | |
| 97713 | /* |
| 97714 | ** The select statement passed as the first argument is an aggregate query. |
| 97715 | ** The second argment is the associated aggregate-info object. This |
| @@ -97536,10 +97800,11 @@ | |
| 97800 | int i, j, k; |
| 97801 | SrcList *pTabList; |
| 97802 | ExprList *pEList; |
| 97803 | struct SrcList_item *pFrom; |
| 97804 | sqlite3 *db = pParse->db; |
| 97805 | Expr *pE, *pRight, *pExpr; |
| 97806 | |
| 97807 | if( db->mallocFailed ){ |
| 97808 | return WRC_Abort; |
| 97809 | } |
| 97810 | if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){ |
| @@ -97621,11 +97886,11 @@ | |
| 97886 | ** |
| 97887 | ** The first loop just checks to see if there are any "*" operators |
| 97888 | ** that need expanding. |
| 97889 | */ |
| 97890 | for(k=0; k<pEList->nExpr; k++){ |
| 97891 | pE = pEList->a[k].pExpr; |
| 97892 | if( pE->op==TK_ALL ) break; |
| 97893 | assert( pE->op!=TK_DOT || pE->pRight!=0 ); |
| 97894 | assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); |
| 97895 | if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; |
| 97896 | } |
| @@ -97639,14 +97904,22 @@ | |
| 97904 | ExprList *pNew = 0; |
| 97905 | int flags = pParse->db->flags; |
| 97906 | int longNames = (flags & SQLITE_FullColNames)!=0 |
| 97907 | && (flags & SQLITE_ShortColNames)==0; |
| 97908 | |
| 97909 | /* When processing FROM-clause subqueries, it is always the case |
| 97910 | ** that full_column_names=OFF and short_column_names=ON. The |
| 97911 | ** sqlite3ResultSetOfSelect() routine makes it so. */ |
| 97912 | assert( (p->selFlags & SF_NestedFrom)==0 |
| 97913 | || ((flags & SQLITE_FullColNames)==0 && |
| 97914 | (flags & SQLITE_ShortColNames)!=0) ); |
| 97915 | |
| 97916 | for(k=0; k<pEList->nExpr; k++){ |
| 97917 | pE = a[k].pExpr; |
| 97918 | pRight = pE->pRight; |
| 97919 | assert( pE->op!=TK_DOT || pRight!=0 ); |
| 97920 | if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){ |
| 97921 | /* This particular expression does not need to be expanded. |
| 97922 | */ |
| 97923 | pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); |
| 97924 | if( pNew ){ |
| 97925 | pNew->a[pNew->nExpr-1].zName = a[k].zName; |
| @@ -97657,44 +97930,56 @@ | |
| 97930 | a[k].pExpr = 0; |
| 97931 | }else{ |
| 97932 | /* This expression is a "*" or a "TABLE.*" and needs to be |
| 97933 | ** expanded. */ |
| 97934 | int tableSeen = 0; /* Set to 1 when TABLE matches */ |
| 97935 | char *zTName = 0; /* text of name of TABLE */ |
| 97936 | if( pE->op==TK_DOT ){ |
| 97937 | assert( pE->pLeft!=0 ); |
| 97938 | assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); |
| 97939 | zTName = pE->pLeft->u.zToken; |
| 97940 | } |
| 97941 | for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
| 97942 | Table *pTab = pFrom->pTab; |
| 97943 | Select *pSub = pFrom->pSelect; |
| 97944 | char *zTabName = pFrom->zAlias; |
| 97945 | const char *zSchemaName = 0; |
| 97946 | int iDb; |
| 97947 | if( zTabName==0 ){ |
| 97948 | zTabName = pTab->zName; |
| 97949 | } |
| 97950 | if( db->mallocFailed ) break; |
| 97951 | if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ |
| 97952 | pSub = 0; |
| 97953 | if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ |
| 97954 | continue; |
| 97955 | } |
| 97956 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 97957 | zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*"; |
| 97958 | } |
| 97959 | for(j=0; j<pTab->nCol; j++){ |
| 97960 | char *zName = pTab->aCol[j].zName; |
| 97961 | char *zColname; /* The computed column name */ |
| 97962 | char *zToFree; /* Malloced string that needs to be freed */ |
| 97963 | Token sColname; /* Computed column name as a token */ |
| 97964 | |
| 97965 | assert( zName ); |
| 97966 | if( zTName && pSub |
| 97967 | && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0 |
| 97968 | ){ |
| 97969 | continue; |
| 97970 | } |
| 97971 | |
| 97972 | /* If a column is marked as 'hidden' (currently only possible |
| 97973 | ** for virtual tables), do not include it in the expanded |
| 97974 | ** result-set list. |
| 97975 | */ |
| 97976 | if( IsHiddenColumn(&pTab->aCol[j]) ){ |
| 97977 | assert(IsVirtual(pTab)); |
| 97978 | continue; |
| 97979 | } |
| 97980 | tableSeen = 1; |
| 97981 | |
| 97982 | if( i>0 && zTName==0 ){ |
| 97983 | if( (pFrom->jointype & JT_NATURAL)!=0 |
| 97984 | && tableAndColumnIndex(pTabList, i, zName, 0, 0) |
| 97985 | ){ |
| @@ -97713,10 +97998,14 @@ | |
| 97998 | zToFree = 0; |
| 97999 | if( longNames || pTabList->nSrc>1 ){ |
| 98000 | Expr *pLeft; |
| 98001 | pLeft = sqlite3Expr(db, TK_ID, zTabName); |
| 98002 | pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); |
| 98003 | if( zSchemaName ){ |
| 98004 | pLeft = sqlite3Expr(db, TK_ID, zSchemaName); |
| 98005 | pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0); |
| 98006 | } |
| 98007 | if( longNames ){ |
| 98008 | zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); |
| 98009 | zToFree = zColname; |
| 98010 | } |
| 98011 | }else{ |
| @@ -97724,10 +98013,22 @@ | |
| 98013 | } |
| 98014 | pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); |
| 98015 | sColname.z = zColname; |
| 98016 | sColname.n = sqlite3Strlen30(zColname); |
| 98017 | sqlite3ExprListSetName(pParse, pNew, &sColname, 0); |
| 98018 | if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ |
| 98019 | struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; |
| 98020 | if( pSub ){ |
| 98021 | pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); |
| 98022 | testcase( pX->zSpan==0 ); |
| 98023 | }else{ |
| 98024 | pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s", |
| 98025 | zSchemaName, zTabName, zColname); |
| 98026 | testcase( pX->zSpan==0 ); |
| 98027 | } |
| 98028 | pX->bSpanIsTab = 1; |
| 98029 | } |
| 98030 | sqlite3DbFree(db, zToFree); |
| 98031 | } |
| 98032 | } |
| 98033 | if( !tableSeen ){ |
| 98034 | if( zTName ){ |
| @@ -98781,15 +99082,21 @@ | |
| 99082 | ** index or indices to use) should place a different priority on |
| 99083 | ** satisfying the 'ORDER BY' clause than it does in other cases. |
| 99084 | ** Refer to code and comments in where.c for details. |
| 99085 | */ |
| 99086 | ExprList *pMinMax = 0; |
| 99087 | u8 flag = WHERE_ORDERBY_NORMAL; |
| 99088 | |
| 99089 | assert( p->pGroupBy==0 ); |
| 99090 | assert( flag==0 ); |
| 99091 | if( p->pHaving==0 ){ |
| 99092 | flag = minMaxQuery(&sAggInfo, &pMinMax); |
| 99093 | } |
| 99094 | assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); |
| 99095 | |
| 99096 | if( flag ){ |
| 99097 | pMinMax = sqlite3ExprListDup(db, pMinMax, 0); |
| 99098 | pDel = pMinMax; |
| 99099 | if( pMinMax && !db->mallocFailed ){ |
| 99100 | pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; |
| 99101 | pMinMax->a[0].pExpr->op = TK_COLUMN; |
| 99102 | } |
| @@ -102673,11 +102980,11 @@ | |
| 102980 | #define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */ |
| 102981 | #define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */ |
| 102982 | #define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */ |
| 102983 | #define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */ |
| 102984 | #define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */ |
| 102985 | #define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */ |
| 102986 | #define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */ |
| 102987 | #define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */ |
| 102988 | #define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */ |
| 102989 | #define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */ |
| 102990 | #define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */ |
| @@ -102823,11 +103130,11 @@ | |
| 103130 | sqlite3DbFree(db, pOld); |
| 103131 | } |
| 103132 | pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); |
| 103133 | } |
| 103134 | pTerm = &pWC->a[idx = pWC->nTerm++]; |
| 103135 | pTerm->pExpr = sqlite3ExprSkipCollate(p); |
| 103136 | pTerm->wtFlags = wtFlags; |
| 103137 | pTerm->pWC = pWC; |
| 103138 | pTerm->iParent = -1; |
| 103139 | return idx; |
| 103140 | } |
| @@ -102983,27 +103290,36 @@ | |
| 103290 | |
| 103291 | /* |
| 103292 | ** Commute a comparison operator. Expressions of the form "X op Y" |
| 103293 | ** are converted into "Y op X". |
| 103294 | ** |
| 103295 | ** If left/right precendence rules come into play when determining the |
| 103296 | ** collating |
| 103297 | ** side of the comparison, it remains associated with the same side after |
| 103298 | ** the commutation. So "Y collate NOCASE op X" becomes |
| 103299 | ** "X op Y". This is because any collation sequence on |
| 103300 | ** the left hand side of a comparison overrides any collation sequence |
| 103301 | ** attached to the right. For the same reason the EP_Collate flag |
| 103302 | ** is not commuted. |
| 103303 | */ |
| 103304 | static void exprCommute(Parse *pParse, Expr *pExpr){ |
| 103305 | u16 expRight = (pExpr->pRight->flags & EP_Collate); |
| 103306 | u16 expLeft = (pExpr->pLeft->flags & EP_Collate); |
| 103307 | assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); |
| 103308 | if( expRight==expLeft ){ |
| 103309 | /* Either X and Y both have COLLATE operator or neither do */ |
| 103310 | if( expRight ){ |
| 103311 | /* Both X and Y have COLLATE operators. Make sure X is always |
| 103312 | ** used by clearing the EP_Collate flag from Y. */ |
| 103313 | pExpr->pRight->flags &= ~EP_Collate; |
| 103314 | }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ |
| 103315 | /* Neither X nor Y have COLLATE operators, but X has a non-default |
| 103316 | ** collating sequence. So add the EP_Collate marker on X to cause |
| 103317 | ** it to be searched first. */ |
| 103318 | pExpr->pLeft->flags |= EP_Collate; |
| 103319 | } |
| 103320 | } |
| 103321 | SWAP(Expr*,pExpr->pRight,pExpr->pLeft); |
| 103322 | if( pExpr->op>=TK_GT ){ |
| 103323 | assert( TK_LT==TK_GT+2 ); |
| 103324 | assert( TK_GE==TK_LE+2 ); |
| 103325 | assert( TK_GT>TK_EQ ); |
| @@ -103076,16 +103392,16 @@ | |
| 103392 | ** it to be useful for optimising expression pX. Store this |
| 103393 | ** value in variable pColl. |
| 103394 | */ |
| 103395 | assert(pX->pLeft); |
| 103396 | pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| 103397 | if( pColl==0 ) pColl = pParse->db->pDfltColl; |
| 103398 | |
| 103399 | for(j=0; pIdx->aiColumn[j]!=iColumn; j++){ |
| 103400 | if( NEVER(j>=pIdx->nColumn) ) return 0; |
| 103401 | } |
| 103402 | if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; |
| 103403 | } |
| 103404 | return pTerm; |
| 103405 | } |
| 103406 | } |
| 103407 | } |
| @@ -103600,10 +103916,11 @@ | |
| 103916 | return; |
| 103917 | } |
| 103918 | pTerm = &pWC->a[idxTerm]; |
| 103919 | pMaskSet = pWC->pMaskSet; |
| 103920 | pExpr = pTerm->pExpr; |
| 103921 | assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); |
| 103922 | prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); |
| 103923 | op = pExpr->op; |
| 103924 | if( op==TK_IN ){ |
| 103925 | assert( pExpr->pRight==0 ); |
| 103926 | if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
| @@ -103626,12 +103943,12 @@ | |
| 103943 | pTerm->prereqAll = prereqAll; |
| 103944 | pTerm->leftCursor = -1; |
| 103945 | pTerm->iParent = -1; |
| 103946 | pTerm->eOperator = 0; |
| 103947 | if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ |
| 103948 | Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); |
| 103949 | Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); |
| 103950 | if( pLeft->op==TK_COLUMN ){ |
| 103951 | pTerm->leftCursor = pLeft->iTable; |
| 103952 | pTerm->u.leftColumn = pLeft->iColumn; |
| 103953 | pTerm->eOperator = operatorMask(op); |
| 103954 | } |
| @@ -103655,11 +103972,11 @@ | |
| 103972 | }else{ |
| 103973 | pDup = pExpr; |
| 103974 | pNew = pTerm; |
| 103975 | } |
| 103976 | exprCommute(pParse, pDup); |
| 103977 | pLeft = sqlite3ExprSkipCollate(pDup->pLeft); |
| 103978 | pNew->leftCursor = pLeft->iTable; |
| 103979 | pNew->u.leftColumn = pLeft->iColumn; |
| 103980 | testcase( (prereqLeft | extraRight) != prereqLeft ); |
| 103981 | pNew->prereqRight = prereqLeft | extraRight; |
| 103982 | pNew->prereqAll = prereqAll; |
| @@ -103734,11 +104051,11 @@ | |
| 104051 | Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ |
| 104052 | Expr *pNewExpr1; |
| 104053 | Expr *pNewExpr2; |
| 104054 | int idxNew1; |
| 104055 | int idxNew2; |
| 104056 | Token sCollSeqName; /* Name of collating sequence */ |
| 104057 | |
| 104058 | pLeft = pExpr->x.pList->a[1].pExpr; |
| 104059 | pStr2 = sqlite3ExprDup(db, pStr1, 0); |
| 104060 | if( !db->mallocFailed ){ |
| 104061 | u8 c, *pC; /* Last character before the first wildcard */ |
| @@ -103756,20 +104073,23 @@ | |
| 104073 | |
| 104074 | c = sqlite3UpperToLower[c]; |
| 104075 | } |
| 104076 | *pC = c + 1; |
| 104077 | } |
| 104078 | sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; |
| 104079 | sCollSeqName.n = 6; |
| 104080 | pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); |
| 104081 | pNewExpr1 = sqlite3PExpr(pParse, TK_GE, |
| 104082 | sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName), |
| 104083 | pStr1, 0); |
| 104084 | idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); |
| 104085 | testcase( idxNew1==0 ); |
| 104086 | exprAnalyze(pSrc, pWC, idxNew1); |
| 104087 | pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); |
| 104088 | pNewExpr2 = sqlite3PExpr(pParse, TK_LT, |
| 104089 | sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName), |
| 104090 | pStr2, 0); |
| 104091 | idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); |
| 104092 | testcase( idxNew2==0 ); |
| 104093 | exprAnalyze(pSrc, pWC, idxNew2); |
| 104094 | pTerm = &pWC->a[idxTerm]; |
| 104095 | if( isComplete ){ |
| @@ -103883,16 +104203,16 @@ | |
| 104203 | ){ |
| 104204 | int i; |
| 104205 | const char *zColl = pIdx->azColl[iCol]; |
| 104206 | |
| 104207 | for(i=0; i<pList->nExpr; i++){ |
| 104208 | Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); |
| 104209 | if( p->op==TK_COLUMN |
| 104210 | && p->iColumn==pIdx->aiColumn[iCol] |
| 104211 | && p->iTable==iBase |
| 104212 | ){ |
| 104213 | CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); |
| 104214 | if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ |
| 104215 | return i; |
| 104216 | } |
| 104217 | } |
| 104218 | } |
| @@ -103935,11 +104255,11 @@ | |
| 104255 | ** matching "col=X" expression and the column is on the same table as pIdx, |
| 104256 | ** set the corresponding bit in variable mask. |
| 104257 | */ |
| 104258 | for(i=0; i<pDistinct->nExpr; i++){ |
| 104259 | WhereTerm *pTerm; |
| 104260 | Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); |
| 104261 | if( p->op!=TK_COLUMN ) return 0; |
| 104262 | pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0); |
| 104263 | if( pTerm ){ |
| 104264 | Expr *pX = pTerm->pExpr; |
| 104265 | CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); |
| @@ -103987,11 +104307,11 @@ | |
| 104307 | /* If any of the expressions is an IPK column on table iBase, then return |
| 104308 | ** true. Note: The (p->iTable==iBase) part of this test may be false if the |
| 104309 | ** current SELECT is a correlated sub-query. |
| 104310 | */ |
| 104311 | for(i=0; i<pDistinct->nExpr; i++){ |
| 104312 | Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); |
| 104313 | if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; |
| 104314 | } |
| 104315 | |
| 104316 | /* Loop through all indices on the table, checking each to see if it makes |
| 104317 | ** the DISTINCT qualifier redundant. It does so if: |
| @@ -104464,11 +104784,11 @@ | |
| 104784 | for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104785 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104786 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104787 | testcase( pTerm->eOperator==WO_IN ); |
| 104788 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104789 | if( pTerm->eOperator & (WO_ISNULL) ) continue; |
| 104790 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104791 | nTerm++; |
| 104792 | } |
| 104793 | |
| 104794 | /* If the ORDER BY clause contains only columns in the current |
| @@ -104512,29 +104832,32 @@ | |
| 104832 | *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; |
| 104833 | *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage = |
| 104834 | pUsage; |
| 104835 | |
| 104836 | for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ |
| 104837 | u8 op; |
| 104838 | if( pTerm->leftCursor != pSrc->iCursor ) continue; |
| 104839 | assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); |
| 104840 | testcase( pTerm->eOperator==WO_IN ); |
| 104841 | testcase( pTerm->eOperator==WO_ISNULL ); |
| 104842 | if( pTerm->eOperator & (WO_ISNULL) ) continue; |
| 104843 | if( pTerm->wtFlags & TERM_VNULL ) continue; |
| 104844 | pIdxCons[j].iColumn = pTerm->u.leftColumn; |
| 104845 | pIdxCons[j].iTermOffset = i; |
| 104846 | op = (u8)pTerm->eOperator; |
| 104847 | if( op==WO_IN ) op = WO_EQ; |
| 104848 | pIdxCons[j].op = op; |
| 104849 | /* The direct assignment in the previous line is possible only because |
| 104850 | ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The |
| 104851 | ** following asserts verify this fact. */ |
| 104852 | assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); |
| 104853 | assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); |
| 104854 | assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); |
| 104855 | assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); |
| 104856 | assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); |
| 104857 | assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); |
| 104858 | assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); |
| 104859 | j++; |
| 104860 | } |
| 104861 | for(i=0; i<nOrderBy; i++){ |
| 104862 | Expr *pExpr = pOrderBy->a[i].pExpr; |
| 104863 | pIdxOrderBy[i].iColumn = pExpr->iColumn; |
| @@ -104616,10 +104939,11 @@ | |
| 104939 | struct sqlite3_index_constraint *pIdxCons; |
| 104940 | struct sqlite3_index_constraint_usage *pUsage; |
| 104941 | WhereTerm *pTerm; |
| 104942 | int i, j; |
| 104943 | int nOrderBy; |
| 104944 | int bAllowIN; /* Allow IN optimizations */ |
| 104945 | double rCost; |
| 104946 | |
| 104947 | /* Make sure wsFlags is initialized to some sane value. Otherwise, if the |
| 104948 | ** malloc in allocateIndexInfo() fails and this function returns leaving |
| 104949 | ** wsFlags in an uninitialized state, the caller may behave unpredictably. |
| @@ -104650,63 +104974,91 @@ | |
| 104974 | ** sqlite3ViewGetColumnNames() would have picked up the error. |
| 104975 | */ |
| 104976 | assert( pTab->azModuleArg && pTab->azModuleArg[0] ); |
| 104977 | assert( sqlite3GetVTable(pParse->db, pTab) ); |
| 104978 | |
| 104979 | /* Try once or twice. On the first attempt, allow IN optimizations. |
| 104980 | ** If an IN optimization is accepted by the virtual table xBestIndex |
| 104981 | ** method, but the pInfo->aConstrainUsage.omit flag is not set, then |
| 104982 | ** the query will not work because it might allow duplicate rows in |
| 104983 | ** output. In that case, run the xBestIndex method a second time |
| 104984 | ** without the IN constraints. Usually this loop only runs once. |
| 104985 | ** The loop will exit using a "break" statement. |
| 104986 | */ |
| 104987 | for(bAllowIN=1; 1; bAllowIN--){ |
| 104988 | assert( bAllowIN==0 || bAllowIN==1 ); |
| 104989 | |
| 104990 | /* Set the aConstraint[].usable fields and initialize all |
| 104991 | ** output variables to zero. |
| 104992 | ** |
| 104993 | ** aConstraint[].usable is true for constraints where the right-hand |
| 104994 | ** side contains only references to tables to the left of the current |
| 104995 | ** table. In other words, if the constraint is of the form: |
| 104996 | ** |
| 104997 | ** column = expr |
| 104998 | ** |
| 104999 | ** and we are evaluating a join, then the constraint on column is |
| 105000 | ** only valid if all tables referenced in expr occur to the left |
| 105001 | ** of the table containing column. |
| 105002 | ** |
| 105003 | ** The aConstraints[] array contains entries for all constraints |
| 105004 | ** on the current table. That way we only have to compute it once |
| 105005 | ** even though we might try to pick the best index multiple times. |
| 105006 | ** For each attempt at picking an index, the order of tables in the |
| 105007 | ** join might be different so we have to recompute the usable flag |
| 105008 | ** each time. |
| 105009 | */ |
| 105010 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 105011 | pUsage = pIdxInfo->aConstraintUsage; |
| 105012 | for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ |
| 105013 | j = pIdxCons->iTermOffset; |
| 105014 | pTerm = &pWC->a[j]; |
| 105015 | if( (pTerm->prereqRight&p->notReady)==0 |
| 105016 | && (bAllowIN || pTerm->eOperator!=WO_IN) |
| 105017 | ){ |
| 105018 | pIdxCons->usable = 1; |
| 105019 | }else{ |
| 105020 | pIdxCons->usable = 0; |
| 105021 | } |
| 105022 | } |
| 105023 | memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); |
| 105024 | if( pIdxInfo->needToFreeIdxStr ){ |
| 105025 | sqlite3_free(pIdxInfo->idxStr); |
| 105026 | } |
| 105027 | pIdxInfo->idxStr = 0; |
| 105028 | pIdxInfo->idxNum = 0; |
| 105029 | pIdxInfo->needToFreeIdxStr = 0; |
| 105030 | pIdxInfo->orderByConsumed = 0; |
| 105031 | /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */ |
| 105032 | pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2); |
| 105033 | nOrderBy = pIdxInfo->nOrderBy; |
| 105034 | if( !p->pOrderBy ){ |
| 105035 | pIdxInfo->nOrderBy = 0; |
| 105036 | } |
| 105037 | |
| 105038 | if( vtabBestIndex(pParse, pTab, pIdxInfo) ){ |
| 105039 | return; |
| 105040 | } |
| 105041 | |
| 105042 | pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; |
| 105043 | for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ |
| 105044 | if( pUsage[i].argvIndex>0 ){ |
| 105045 | j = pIdxCons->iTermOffset; |
| 105046 | pTerm = &pWC->a[j]; |
| 105047 | p->cost.used |= pTerm->prereqRight; |
| 105048 | if( pTerm->eOperator==WO_IN && pUsage[i].omit==0 ){ |
| 105049 | /* Do not attempt to use an IN constraint if the virtual table |
| 105050 | ** says that the equivalent EQ constraint cannot be safely omitted. |
| 105051 | ** If we do attempt to use such a constraint, some rows might be |
| 105052 | ** repeated in the output. */ |
| 105053 | break; |
| 105054 | } |
| 105055 | } |
| 105056 | } |
| 105057 | if( i>=pIdxInfo->nConstraint ) break; |
| 105058 | } |
| 105059 | |
| 105060 | /* If there is an ORDER BY clause, and the selected virtual table index |
| 105061 | ** does not satisfy it, increase the cost of the scan accordingly. This |
| 105062 | ** matches the processing for non-virtual tables in bestBtreeIndex(). |
| 105063 | */ |
| 105064 | rCost = pIdxInfo->estimatedCost; |
| @@ -105273,11 +105625,11 @@ | |
| 105625 | WhereTerm *pConstraint; /* A constraint in the WHERE clause */ |
| 105626 | |
| 105627 | /* If the next term of the ORDER BY clause refers to anything other than |
| 105628 | ** a column in the "base" table, then this index will not be of any |
| 105629 | ** further use in handling the ORDER BY. */ |
| 105630 | pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr); |
| 105631 | if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){ |
| 105632 | break; |
| 105633 | } |
| 105634 | |
| 105635 | /* Find column number and collating sequence for the next entry |
| @@ -105299,11 +105651,11 @@ | |
| 105651 | /* Check to see if the column number and collating sequence of the |
| 105652 | ** index match the column number and collating sequence of the ORDER BY |
| 105653 | ** clause entry. Set isMatch to 1 if they both match. */ |
| 105654 | if( pOBExpr->iColumn==iColumn ){ |
| 105655 | if( zColl ){ |
| 105656 | pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr); |
| 105657 | if( !pColl ) pColl = db->pDfltColl; |
| 105658 | isMatch = sqlite3StrICmp(pColl->zName, zColl)==0; |
| 105659 | }else{ |
| 105660 | isMatch = 1; |
| 105661 | } |
| @@ -105440,10 +105792,15 @@ | |
| 105792 | int idxEqTermMask; /* Index mask of valid equality operators */ |
| 105793 | Index sPk; /* A fake index object for the primary key */ |
| 105794 | tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ |
| 105795 | int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ |
| 105796 | int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */ |
| 105797 | int nPriorSat; /* ORDER BY terms satisfied by outer loops */ |
| 105798 | int nOrderBy; /* Number of ORDER BY terms */ |
| 105799 | char bSortInit; /* Initializer for bSort in inner loop */ |
| 105800 | char bDistInit; /* Initializer for bDist in inner loop */ |
| 105801 | |
| 105802 | |
| 105803 | /* Initialize the cost to a worst-case value */ |
| 105804 | memset(&p->cost, 0, sizeof(p->cost)); |
| 105805 | p->cost.rCost = SQLITE_BIG_DBL; |
| 105806 | |
| @@ -105488,10 +105845,21 @@ | |
| 105845 | WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE |
| 105846 | ); |
| 105847 | eqTermMask = WO_EQ|WO_IN; |
| 105848 | pIdx = 0; |
| 105849 | } |
| 105850 | |
| 105851 | nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; |
| 105852 | if( p->i ){ |
| 105853 | nPriorSat = p->aLevel[p->i-1].plan.nOBSat; |
| 105854 | bSortInit = nPriorSat<nOrderBy; |
| 105855 | bDistInit = 0; |
| 105856 | }else{ |
| 105857 | nPriorSat = 0; |
| 105858 | bSortInit = nOrderBy>0; |
| 105859 | bDistInit = p->pDistinct!=0; |
| 105860 | } |
| 105861 | |
| 105862 | /* Loop over all indices looking for the best one to use |
| 105863 | */ |
| 105864 | for(; pProbe; pIdx=pProbe=pProbe->pNext){ |
| 105865 | const tRowcnt * const aiRowEst = pProbe->aiRowEst; |
| @@ -105566,15 +105934,13 @@ | |
| 105934 | */ |
| 105935 | int bInEst = 0; /* True if "x IN (SELECT...)" seen */ |
| 105936 | int nInMul = 1; /* Number of distinct equalities to lookup */ |
| 105937 | double rangeDiv = (double)1; /* Estimated reduction in search space */ |
| 105938 | int nBound = 0; /* Number of range constraints seen */ |
| 105939 | char bSort = bSortInit; /* True if external sort required */ |
| 105940 | char bDist = bDistInit; /* True if index cannot help with DISTINCT */ |
| 105941 | char bLookup = 0; /* True if not a covering index */ |
| 105942 | WhereTerm *pTerm; /* A single term of the WHERE clause */ |
| 105943 | #ifdef SQLITE_ENABLE_STAT3 |
| 105944 | WhereTerm *pFirstTerm = 0; /* First term matching the index */ |
| 105945 | #endif |
| 105946 | |
| @@ -105581,20 +105947,11 @@ | |
| 105947 | WHERETRACE(( |
| 105948 | " %s(%s):\n", |
| 105949 | pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk") |
| 105950 | )); |
| 105951 | memset(&pc, 0, sizeof(pc)); |
| 105952 | pc.plan.nOBSat = nPriorSat; |
| 105953 | |
| 105954 | /* Determine the values of pc.plan.nEq and nInMul */ |
| 105955 | for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){ |
| 105956 | int j = pProbe->aiColumn[pc.plan.nEq]; |
| 105957 | pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); |
| @@ -106466,32 +106823,40 @@ | |
| 106823 | if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ |
| 106824 | /* Case 0: The table is a virtual-table. Use the VFilter and VNext |
| 106825 | ** to access the data. |
| 106826 | */ |
| 106827 | int iReg; /* P3 Value for OP_VFilter */ |
| 106828 | int addrNotFound; |
| 106829 | sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx; |
| 106830 | int nConstraint = pVtabIdx->nConstraint; |
| 106831 | struct sqlite3_index_constraint_usage *aUsage = |
| 106832 | pVtabIdx->aConstraintUsage; |
| 106833 | const struct sqlite3_index_constraint *aConstraint = |
| 106834 | pVtabIdx->aConstraint; |
| 106835 | |
| 106836 | sqlite3ExprCachePush(pParse); |
| 106837 | iReg = sqlite3GetTempRange(pParse, nConstraint+2); |
| 106838 | addrNotFound = pLevel->addrBrk; |
| 106839 | for(j=1; j<=nConstraint; j++){ |
| 106840 | for(k=0; k<nConstraint; k++){ |
| 106841 | if( aUsage[k].argvIndex==j ){ |
| 106842 | WhereTerm *pTerm = &pWC->a[aConstraint[k].iTermOffset]; |
| 106843 | int iTarget = iReg+j+1; |
| 106844 | if( pTerm->eOperator & WO_IN ){ |
| 106845 | codeEqualityTerm(pParse, pTerm, pLevel, iTarget); |
| 106846 | addrNotFound = pLevel->addrNxt; |
| 106847 | }else{ |
| 106848 | sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget); |
| 106849 | } |
| 106850 | break; |
| 106851 | } |
| 106852 | } |
| 106853 | if( k==nConstraint ) break; |
| 106854 | } |
| 106855 | sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg); |
| 106856 | sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1); |
| 106857 | sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr, |
| 106858 | pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC); |
| 106859 | pVtabIdx->needToFreeIdxStr = 0; |
| 106860 | for(j=0; j<nConstraint; j++){ |
| 106861 | if( aUsage[j].omit ){ |
| 106862 | int iTerm = aConstraint[j].iTermOffset; |
| @@ -108134,10 +108499,11 @@ | |
| 108499 | Expr* yy122; |
| 108500 | Select* yy159; |
| 108501 | IdList* yy180; |
| 108502 | struct {int value; int mask;} yy207; |
| 108503 | u8 yy258; |
| 108504 | u16 yy305; |
| 108505 | struct LikeOp yy318; |
| 108506 | TriggerStep* yy327; |
| 108507 | ExprSpan yy342; |
| 108508 | SrcList* yy347; |
| 108509 | int yy392; |
| @@ -110084,22 +110450,19 @@ | |
| 110450 | case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); |
| 110451 | case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); |
| 110452 | case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); |
| 110453 | case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98); |
| 110454 | case 109: /* ifexists ::= */ yytestcase(yyruleno==109); |
| 110455 | case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); |
| 110456 | case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); |
| 110457 | {yygotominor.yy392 = 0;} |
| 110458 | break; |
| 110459 | case 29: /* ifnotexists ::= IF NOT EXISTS */ |
| 110460 | case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30); |
| 110461 | case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); |
| 110462 | case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); |
| 110463 | case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108); |
| 110464 | case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); |
| 110465 | case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); |
| 110466 | {yygotominor.yy392 = 1;} |
| 110467 | break; |
| 110468 | case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ |
| @@ -110335,12 +110698,19 @@ | |
| 110698 | case 116: /* multiselect_op ::= UNION ALL */ |
| 110699 | {yygotominor.yy392 = TK_ALL;} |
| 110700 | break; |
| 110701 | case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ |
| 110702 | { |
| 110703 | yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); |
| 110704 | } |
| 110705 | break; |
| 110706 | case 119: /* distinct ::= DISTINCT */ |
| 110707 | {yygotominor.yy305 = SF_Distinct;} |
| 110708 | break; |
| 110709 | case 120: /* distinct ::= ALL */ |
| 110710 | case 121: /* distinct ::= */ yytestcase(yyruleno==121); |
| 110711 | {yygotominor.yy305 = 0;} |
| 110712 | break; |
| 110713 | case 122: /* sclp ::= selcollist COMMA */ |
| 110714 | case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246); |
| 110715 | {yygotominor.yy442 = yymsp[-1].minor.yy442;} |
| 110716 | break; |
| @@ -110406,14 +110776,24 @@ | |
| 110776 | break; |
| 110777 | case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ |
| 110778 | { |
| 110779 | if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ |
| 110780 | yygotominor.yy347 = yymsp[-4].minor.yy347; |
| 110781 | }else if( yymsp[-4].minor.yy347->nSrc==1 ){ |
| 110782 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); |
| 110783 | if( yygotominor.yy347 ){ |
| 110784 | struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1]; |
| 110785 | struct SrcList_item *pOld = yymsp[-4].minor.yy347->a; |
| 110786 | pNew->zName = pOld->zName; |
| 110787 | pNew->zDatabase = pOld->zDatabase; |
| 110788 | pOld->zName = pOld->zDatabase = 0; |
| 110789 | } |
| 110790 | sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347); |
| 110791 | }else{ |
| 110792 | Select *pSubquery; |
| 110793 | sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); |
| 110794 | pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0); |
| 110795 | yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); |
| 110796 | } |
| 110797 | } |
| 110798 | break; |
| 110799 | case 137: /* dbnm ::= */ |
| @@ -110624,11 +111004,11 @@ | |
| 111004 | spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); |
| 111005 | } |
| 111006 | break; |
| 111007 | case 194: /* expr ::= expr COLLATE ids */ |
| 111008 | { |
| 111009 | yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); |
| 111010 | yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; |
| 111011 | yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; |
| 111012 | } |
| 111013 | break; |
| 111014 | case 195: /* expr ::= CAST LP expr AS typetoken RP */ |
| @@ -110642,11 +111022,11 @@ | |
| 111022 | if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ |
| 111023 | sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); |
| 111024 | } |
| 111025 | yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); |
| 111026 | spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); |
| 111027 | if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){ |
| 111028 | yygotominor.yy342.pExpr->flags |= EP_Distinct; |
| 111029 | } |
| 111030 | } |
| 111031 | break; |
| 111032 | case 197: /* expr ::= ID LP STAR RP */ |
| @@ -110883,28 +111263,20 @@ | |
| 111263 | case 244: /* uniqueflag ::= */ |
| 111264 | {yygotominor.yy392 = OE_None;} |
| 111265 | break; |
| 111266 | case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */ |
| 111267 | { |
| 111268 | Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); |
| 111269 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p); |
| 111270 | sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1); |
| 111271 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 111272 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 111273 | } |
| 111274 | break; |
| 111275 | case 248: /* idxlist ::= nm collate sortorder */ |
| 111276 | { |
| 111277 | Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0); |
| 111278 | yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p); |
| 111279 | sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); |
| 111280 | sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); |
| 111281 | if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; |
| 111282 | } |
| @@ -141105,10 +141477,11 @@ | |
| 141477 | extern int Sqlitemultiplex_Init(Tcl_Interp*); |
| 141478 | extern int SqliteSuperlock_Init(Tcl_Interp*); |
| 141479 | extern int SqlitetestSyscall_Init(Tcl_Interp*); |
| 141480 | extern int Sqlitetestfuzzer_Init(Tcl_Interp*); |
| 141481 | extern int Sqlitetestwholenumber_Init(Tcl_Interp*); |
| 141482 | extern int Sqlitetestregexp_Init(Tcl_Interp*); |
| 141483 | |
| 141484 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141485 | extern int Sqlitetestfts3_Init(Tcl_Interp *interp); |
| 141486 | #endif |
| 141487 | |
| @@ -141148,10 +141521,11 @@ | |
| 141521 | Sqlitemultiplex_Init(interp); |
| 141522 | SqliteSuperlock_Init(interp); |
| 141523 | SqlitetestSyscall_Init(interp); |
| 141524 | Sqlitetestfuzzer_Init(interp); |
| 141525 | Sqlitetestwholenumber_Init(interp); |
| 141526 | Sqlitetestregexp_Init(interp); |
| 141527 | |
| 141528 | #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) |
| 141529 | Sqlitetestfts3_Init(interp); |
| 141530 | #endif |
| 141531 | |
| 141532 |
+4
-4
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -105,13 +105,13 @@ | ||
| 105 | 105 | ** |
| 106 | 106 | ** See also: [sqlite3_libversion()], |
| 107 | 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | 109 | */ |
| 110 | -#define SQLITE_VERSION "3.7.15" | |
| 111 | -#define SQLITE_VERSION_NUMBER 3007015 | |
| 112 | -#define SQLITE_SOURCE_ID "2012-10-16 23:08:28 f021559d8a23934e3bdccad5b55fc7a91d185f53" | |
| 110 | +#define SQLITE_VERSION "3.7.16" | |
| 111 | +#define SQLITE_VERSION_NUMBER 3007016 | |
| 112 | +#define SQLITE_SOURCE_ID "2012-12-08 06:46:05 e65db42c9fdc1d6f257c8db54a46ee4fc0d7aaf0" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | 117 | ** |
| @@ -1596,11 +1596,11 @@ | ||
| 1596 | 1596 | ** database connection is opened. By default, URI handling is globally |
| 1597 | 1597 | ** disabled. The default value may be changed by compiling with the |
| 1598 | 1598 | ** [SQLITE_USE_URI] symbol defined. |
| 1599 | 1599 | ** |
| 1600 | 1600 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 1601 | -** <dd> This option taks a single integer argument which is interpreted as | |
| 1601 | +** <dd> This option takes a single integer argument which is interpreted as | |
| 1602 | 1602 | ** a boolean in order to enable or disable the use of covering indices for |
| 1603 | 1603 | ** full table scans in the query optimizer. The default setting is determined |
| 1604 | 1604 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 1605 | 1605 | ** if that compile-time option is omitted. |
| 1606 | 1606 | ** The ability to disable the use of covering indices for full table scans |
| 1607 | 1607 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -105,13 +105,13 @@ | |
| 105 | ** |
| 106 | ** See also: [sqlite3_libversion()], |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.7.15" |
| 111 | #define SQLITE_VERSION_NUMBER 3007015 |
| 112 | #define SQLITE_SOURCE_ID "2012-10-16 23:08:28 f021559d8a23934e3bdccad5b55fc7a91d185f53" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -1596,11 +1596,11 @@ | |
| 1596 | ** database connection is opened. By default, URI handling is globally |
| 1597 | ** disabled. The default value may be changed by compiling with the |
| 1598 | ** [SQLITE_USE_URI] symbol defined. |
| 1599 | ** |
| 1600 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 1601 | ** <dd> This option taks a single integer argument which is interpreted as |
| 1602 | ** a boolean in order to enable or disable the use of covering indices for |
| 1603 | ** full table scans in the query optimizer. The default setting is determined |
| 1604 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 1605 | ** if that compile-time option is omitted. |
| 1606 | ** The ability to disable the use of covering indices for full table scans |
| 1607 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -105,13 +105,13 @@ | |
| 105 | ** |
| 106 | ** See also: [sqlite3_libversion()], |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.7.16" |
| 111 | #define SQLITE_VERSION_NUMBER 3007016 |
| 112 | #define SQLITE_SOURCE_ID "2012-12-08 06:46:05 e65db42c9fdc1d6f257c8db54a46ee4fc0d7aaf0" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -1596,11 +1596,11 @@ | |
| 1596 | ** database connection is opened. By default, URI handling is globally |
| 1597 | ** disabled. The default value may be changed by compiling with the |
| 1598 | ** [SQLITE_USE_URI] symbol defined. |
| 1599 | ** |
| 1600 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 1601 | ** <dd> This option takes a single integer argument which is interpreted as |
| 1602 | ** a boolean in order to enable or disable the use of covering indices for |
| 1603 | ** full table scans in the query optimizer. The default setting is determined |
| 1604 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 1605 | ** if that compile-time option is omitted. |
| 1606 | ** The ability to disable the use of covering indices for full table scans |
| 1607 |
+4
-4
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -105,13 +105,13 @@ | ||
| 105 | 105 | ** |
| 106 | 106 | ** See also: [sqlite3_libversion()], |
| 107 | 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | 109 | */ |
| 110 | -#define SQLITE_VERSION "3.7.15" | |
| 111 | -#define SQLITE_VERSION_NUMBER 3007015 | |
| 112 | -#define SQLITE_SOURCE_ID "2012-10-16 23:08:28 f021559d8a23934e3bdccad5b55fc7a91d185f53" | |
| 110 | +#define SQLITE_VERSION "3.7.16" | |
| 111 | +#define SQLITE_VERSION_NUMBER 3007016 | |
| 112 | +#define SQLITE_SOURCE_ID "2012-12-08 06:46:05 e65db42c9fdc1d6f257c8db54a46ee4fc0d7aaf0" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | 117 | ** |
| @@ -1596,11 +1596,11 @@ | ||
| 1596 | 1596 | ** database connection is opened. By default, URI handling is globally |
| 1597 | 1597 | ** disabled. The default value may be changed by compiling with the |
| 1598 | 1598 | ** [SQLITE_USE_URI] symbol defined. |
| 1599 | 1599 | ** |
| 1600 | 1600 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 1601 | -** <dd> This option taks a single integer argument which is interpreted as | |
| 1601 | +** <dd> This option takes a single integer argument which is interpreted as | |
| 1602 | 1602 | ** a boolean in order to enable or disable the use of covering indices for |
| 1603 | 1603 | ** full table scans in the query optimizer. The default setting is determined |
| 1604 | 1604 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 1605 | 1605 | ** if that compile-time option is omitted. |
| 1606 | 1606 | ** The ability to disable the use of covering indices for full table scans |
| 1607 | 1607 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -105,13 +105,13 @@ | |
| 105 | ** |
| 106 | ** See also: [sqlite3_libversion()], |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.7.15" |
| 111 | #define SQLITE_VERSION_NUMBER 3007015 |
| 112 | #define SQLITE_SOURCE_ID "2012-10-16 23:08:28 f021559d8a23934e3bdccad5b55fc7a91d185f53" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -1596,11 +1596,11 @@ | |
| 1596 | ** database connection is opened. By default, URI handling is globally |
| 1597 | ** disabled. The default value may be changed by compiling with the |
| 1598 | ** [SQLITE_USE_URI] symbol defined. |
| 1599 | ** |
| 1600 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 1601 | ** <dd> This option taks a single integer argument which is interpreted as |
| 1602 | ** a boolean in order to enable or disable the use of covering indices for |
| 1603 | ** full table scans in the query optimizer. The default setting is determined |
| 1604 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 1605 | ** if that compile-time option is omitted. |
| 1606 | ** The ability to disable the use of covering indices for full table scans |
| 1607 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -105,13 +105,13 @@ | |
| 105 | ** |
| 106 | ** See also: [sqlite3_libversion()], |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.7.16" |
| 111 | #define SQLITE_VERSION_NUMBER 3007016 |
| 112 | #define SQLITE_SOURCE_ID "2012-12-08 06:46:05 e65db42c9fdc1d6f257c8db54a46ee4fc0d7aaf0" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -1596,11 +1596,11 @@ | |
| 1596 | ** database connection is opened. By default, URI handling is globally |
| 1597 | ** disabled. The default value may be changed by compiling with the |
| 1598 | ** [SQLITE_USE_URI] symbol defined. |
| 1599 | ** |
| 1600 | ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN |
| 1601 | ** <dd> This option takes a single integer argument which is interpreted as |
| 1602 | ** a boolean in order to enable or disable the use of covering indices for |
| 1603 | ** full table scans in the query optimizer. The default setting is determined |
| 1604 | ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" |
| 1605 | ** if that compile-time option is omitted. |
| 1606 | ** The ability to disable the use of covering indices for full table scans |
| 1607 |
+1
-1
| --- src/stat.c | ||
| +++ src/stat.c | ||
| @@ -115,11 +115,11 @@ | ||
| 115 | 115 | @ </td></tr> |
| 116 | 116 | } |
| 117 | 117 | @ <tr><th>Duration Of Project:</th><td> |
| 118 | 118 | n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)" |
| 119 | 119 | " + 0.99"); |
| 120 | - @ %d(n) days or approximately %.2f(n/356.24) years. | |
| 120 | + @ %d(n) days or approximately %.2f(n/365.24) years. | |
| 121 | 121 | @ </td></tr> |
| 122 | 122 | @ <tr><th>Project ID:</th><td>%h(db_get("project-code",""))</td></tr> |
| 123 | 123 | @ <tr><th>Server ID:</th><td>%h(db_get("server-code",""))</td></tr> |
| 124 | 124 | @ <tr><th>Fossil Version:</th><td> |
| 125 | 125 | @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION) |
| 126 | 126 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -115,11 +115,11 @@ | |
| 115 | @ </td></tr> |
| 116 | } |
| 117 | @ <tr><th>Duration Of Project:</th><td> |
| 118 | n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)" |
| 119 | " + 0.99"); |
| 120 | @ %d(n) days or approximately %.2f(n/356.24) years. |
| 121 | @ </td></tr> |
| 122 | @ <tr><th>Project ID:</th><td>%h(db_get("project-code",""))</td></tr> |
| 123 | @ <tr><th>Server ID:</th><td>%h(db_get("server-code",""))</td></tr> |
| 124 | @ <tr><th>Fossil Version:</th><td> |
| 125 | @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION) |
| 126 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -115,11 +115,11 @@ | |
| 115 | @ </td></tr> |
| 116 | } |
| 117 | @ <tr><th>Duration Of Project:</th><td> |
| 118 | n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)" |
| 119 | " + 0.99"); |
| 120 | @ %d(n) days or approximately %.2f(n/365.24) years. |
| 121 | @ </td></tr> |
| 122 | @ <tr><th>Project ID:</th><td>%h(db_get("project-code",""))</td></tr> |
| 123 | @ <tr><th>Server ID:</th><td>%h(db_get("server-code",""))</td></tr> |
| 124 | @ <tr><th>Fossil Version:</th><td> |
| 125 | @ %h(RELEASE_VERSION) %h(MANIFEST_DATE) %h(MANIFEST_VERSION) |
| 126 |
+18
-4
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -439,11 +439,13 @@ | ||
| 439 | 439 | /* |
| 440 | 440 | ** The default page footer |
| 441 | 441 | */ |
| 442 | 442 | const char zDefaultFooter[] = |
| 443 | 443 | @ <div class="footer"> |
| 444 | -@ Fossil version $release_version $manifest_version $manifest_date | |
| 444 | +@ This page was generated in about | |
| 445 | +@ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by | |
| 446 | +@ Fossil version $manifest_version $manifest_date | |
| 445 | 447 | @ </div> |
| 446 | 448 | @ </body></html> |
| 447 | 449 | ; |
| 448 | 450 | |
| 449 | 451 | /* |
| @@ -586,12 +588,13 @@ | ||
| 586 | 588 | @ div.footer a:visited { color: white; } |
| 587 | 589 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 588 | 590 | @ |
| 589 | 591 | @ /* verbatim blocks */ |
| 590 | 592 | @ pre.verbatim { |
| 591 | -@ background-color: #f5f5f5; | |
| 592 | -@ padding: 0.5em; | |
| 593 | +@ background-color: #f5f5f5; | |
| 594 | +@ padding: 0.5em; | |
| 595 | +@ white-space: pre-wrap; | |
| 593 | 596 | @} |
| 594 | 597 | @ |
| 595 | 598 | @ /* The label/value pairs on (for example) the ci page */ |
| 596 | 599 | @ table.label-value th { |
| 597 | 600 | @ vertical-align: top; |
| @@ -959,11 +962,11 @@ | ||
| 959 | 962 | @ line-height: 100%; |
| 960 | 963 | }, |
| 961 | 964 | { "div.sbsdiff", |
| 962 | 965 | "side-by-side diff display", |
| 963 | 966 | @ font-family: monospace; |
| 964 | - @ font-size: smaller; | |
| 967 | + @ font-size: xx-small; | |
| 965 | 968 | @ white-space: pre; |
| 966 | 969 | }, |
| 967 | 970 | { "div.udiff", |
| 968 | 971 | "context diff display", |
| 969 | 972 | @ font-family: monospace; |
| @@ -991,10 +994,21 @@ | ||
| 991 | 994 | }, |
| 992 | 995 | { "span.modpending", |
| 993 | 996 | "Moderation Pending message on timeline", |
| 994 | 997 | @ color: #b03800; |
| 995 | 998 | @ font-style: italic; |
| 999 | + }, | |
| 1000 | + { "pre.th1result", | |
| 1001 | + "format for th1 script results", | |
| 1002 | + @ white-space: pre-wrap; | |
| 1003 | + @ word-wrap: break-word; | |
| 1004 | + }, | |
| 1005 | + { "pre.th1error", | |
| 1006 | + "format for th1 script errors", | |
| 1007 | + @ white-space: pre-wrap; | |
| 1008 | + @ word-wrap: break-word; | |
| 1009 | + @ color: red; | |
| 996 | 1010 | }, |
| 997 | 1011 | { 0, |
| 998 | 1012 | 0, |
| 999 | 1013 | 0 |
| 1000 | 1014 | } |
| 1001 | 1015 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -439,11 +439,13 @@ | |
| 439 | /* |
| 440 | ** The default page footer |
| 441 | */ |
| 442 | const char zDefaultFooter[] = |
| 443 | @ <div class="footer"> |
| 444 | @ Fossil version $release_version $manifest_version $manifest_date |
| 445 | @ </div> |
| 446 | @ </body></html> |
| 447 | ; |
| 448 | |
| 449 | /* |
| @@ -586,12 +588,13 @@ | |
| 586 | @ div.footer a:visited { color: white; } |
| 587 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 588 | @ |
| 589 | @ /* verbatim blocks */ |
| 590 | @ pre.verbatim { |
| 591 | @ background-color: #f5f5f5; |
| 592 | @ padding: 0.5em; |
| 593 | @} |
| 594 | @ |
| 595 | @ /* The label/value pairs on (for example) the ci page */ |
| 596 | @ table.label-value th { |
| 597 | @ vertical-align: top; |
| @@ -959,11 +962,11 @@ | |
| 959 | @ line-height: 100%; |
| 960 | }, |
| 961 | { "div.sbsdiff", |
| 962 | "side-by-side diff display", |
| 963 | @ font-family: monospace; |
| 964 | @ font-size: smaller; |
| 965 | @ white-space: pre; |
| 966 | }, |
| 967 | { "div.udiff", |
| 968 | "context diff display", |
| 969 | @ font-family: monospace; |
| @@ -991,10 +994,21 @@ | |
| 991 | }, |
| 992 | { "span.modpending", |
| 993 | "Moderation Pending message on timeline", |
| 994 | @ color: #b03800; |
| 995 | @ font-style: italic; |
| 996 | }, |
| 997 | { 0, |
| 998 | 0, |
| 999 | 0 |
| 1000 | } |
| 1001 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -439,11 +439,13 @@ | |
| 439 | /* |
| 440 | ** The default page footer |
| 441 | */ |
| 442 | const char zDefaultFooter[] = |
| 443 | @ <div class="footer"> |
| 444 | @ This page was generated in about |
| 445 | @ <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by |
| 446 | @ Fossil version $manifest_version $manifest_date |
| 447 | @ </div> |
| 448 | @ </body></html> |
| 449 | ; |
| 450 | |
| 451 | /* |
| @@ -586,12 +588,13 @@ | |
| 588 | @ div.footer a:visited { color: white; } |
| 589 | @ div.footer a:hover { background-color: white; color: #558195; } |
| 590 | @ |
| 591 | @ /* verbatim blocks */ |
| 592 | @ pre.verbatim { |
| 593 | @ background-color: #f5f5f5; |
| 594 | @ padding: 0.5em; |
| 595 | @ white-space: pre-wrap; |
| 596 | @} |
| 597 | @ |
| 598 | @ /* The label/value pairs on (for example) the ci page */ |
| 599 | @ table.label-value th { |
| 600 | @ vertical-align: top; |
| @@ -959,11 +962,11 @@ | |
| 962 | @ line-height: 100%; |
| 963 | }, |
| 964 | { "div.sbsdiff", |
| 965 | "side-by-side diff display", |
| 966 | @ font-family: monospace; |
| 967 | @ font-size: xx-small; |
| 968 | @ white-space: pre; |
| 969 | }, |
| 970 | { "div.udiff", |
| 971 | "context diff display", |
| 972 | @ font-family: monospace; |
| @@ -991,10 +994,21 @@ | |
| 994 | }, |
| 995 | { "span.modpending", |
| 996 | "Moderation Pending message on timeline", |
| 997 | @ color: #b03800; |
| 998 | @ font-style: italic; |
| 999 | }, |
| 1000 | { "pre.th1result", |
| 1001 | "format for th1 script results", |
| 1002 | @ white-space: pre-wrap; |
| 1003 | @ word-wrap: break-word; |
| 1004 | }, |
| 1005 | { "pre.th1error", |
| 1006 | "format for th1 script errors", |
| 1007 | @ white-space: pre-wrap; |
| 1008 | @ word-wrap: break-word; |
| 1009 | @ color: red; |
| 1010 | }, |
| 1011 | { 0, |
| 1012 | 0, |
| 1013 | 0 |
| 1014 | } |
| 1015 |
+7
-2
| --- src/th_main.c | ||
| +++ src/th_main.c | ||
| @@ -611,10 +611,11 @@ | ||
| 611 | 611 | int nSql; |
| 612 | 612 | const char *zTail; |
| 613 | 613 | int n, i; |
| 614 | 614 | int res = TH_OK; |
| 615 | 615 | int nVar; |
| 616 | + char *zErr = 0; | |
| 616 | 617 | |
| 617 | 618 | if( argc!=3 ){ |
| 618 | 619 | return Th_WrongNumArgs(interp, "query SQL CODE"); |
| 619 | 620 | } |
| 620 | 621 | if( g.db==0 ){ |
| @@ -622,13 +623,17 @@ | ||
| 622 | 623 | return TH_ERROR; |
| 623 | 624 | } |
| 624 | 625 | zSql = argv[1]; |
| 625 | 626 | nSql = argl[1]; |
| 626 | 627 | while( res==TH_OK && nSql>0 ){ |
| 628 | + zErr = 0; | |
| 629 | + sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr); | |
| 627 | 630 | rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail); |
| 628 | - if( rc!=0 ){ | |
| 629 | - Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1); | |
| 631 | + sqlite3_set_authorizer(g.db, 0, 0); | |
| 632 | + if( rc!=0 || zErr!=0 ){ | |
| 633 | + Th_ErrorMessage(interp, "SQL error: ", | |
| 634 | + zErr ? zErr : sqlite3_errmsg(g.db), -1); | |
| 630 | 635 | return TH_ERROR; |
| 631 | 636 | } |
| 632 | 637 | n = (int)(zTail - zSql); |
| 633 | 638 | zSql += n; |
| 634 | 639 | nSql -= n; |
| 635 | 640 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -611,10 +611,11 @@ | |
| 611 | int nSql; |
| 612 | const char *zTail; |
| 613 | int n, i; |
| 614 | int res = TH_OK; |
| 615 | int nVar; |
| 616 | |
| 617 | if( argc!=3 ){ |
| 618 | return Th_WrongNumArgs(interp, "query SQL CODE"); |
| 619 | } |
| 620 | if( g.db==0 ){ |
| @@ -622,13 +623,17 @@ | |
| 622 | return TH_ERROR; |
| 623 | } |
| 624 | zSql = argv[1]; |
| 625 | nSql = argl[1]; |
| 626 | while( res==TH_OK && nSql>0 ){ |
| 627 | rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail); |
| 628 | if( rc!=0 ){ |
| 629 | Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1); |
| 630 | return TH_ERROR; |
| 631 | } |
| 632 | n = (int)(zTail - zSql); |
| 633 | zSql += n; |
| 634 | nSql -= n; |
| 635 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -611,10 +611,11 @@ | |
| 611 | int nSql; |
| 612 | const char *zTail; |
| 613 | int n, i; |
| 614 | int res = TH_OK; |
| 615 | int nVar; |
| 616 | char *zErr = 0; |
| 617 | |
| 618 | if( argc!=3 ){ |
| 619 | return Th_WrongNumArgs(interp, "query SQL CODE"); |
| 620 | } |
| 621 | if( g.db==0 ){ |
| @@ -622,13 +623,17 @@ | |
| 623 | return TH_ERROR; |
| 624 | } |
| 625 | zSql = argv[1]; |
| 626 | nSql = argl[1]; |
| 627 | while( res==TH_OK && nSql>0 ){ |
| 628 | zErr = 0; |
| 629 | sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr); |
| 630 | rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail); |
| 631 | sqlite3_set_authorizer(g.db, 0, 0); |
| 632 | if( rc!=0 || zErr!=0 ){ |
| 633 | Th_ErrorMessage(interp, "SQL error: ", |
| 634 | zErr ? zErr : sqlite3_errmsg(g.db), -1); |
| 635 | return TH_ERROR; |
| 636 | } |
| 637 | n = (int)(zTail - zSql); |
| 638 | zSql += n; |
| 639 | nSql -= n; |
| 640 |
+7
-2
| --- src/th_main.c | ||
| +++ src/th_main.c | ||
| @@ -611,10 +611,11 @@ | ||
| 611 | 611 | int nSql; |
| 612 | 612 | const char *zTail; |
| 613 | 613 | int n, i; |
| 614 | 614 | int res = TH_OK; |
| 615 | 615 | int nVar; |
| 616 | + char *zErr = 0; | |
| 616 | 617 | |
| 617 | 618 | if( argc!=3 ){ |
| 618 | 619 | return Th_WrongNumArgs(interp, "query SQL CODE"); |
| 619 | 620 | } |
| 620 | 621 | if( g.db==0 ){ |
| @@ -622,13 +623,17 @@ | ||
| 622 | 623 | return TH_ERROR; |
| 623 | 624 | } |
| 624 | 625 | zSql = argv[1]; |
| 625 | 626 | nSql = argl[1]; |
| 626 | 627 | while( res==TH_OK && nSql>0 ){ |
| 628 | + zErr = 0; | |
| 629 | + sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr); | |
| 627 | 630 | rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail); |
| 628 | - if( rc!=0 ){ | |
| 629 | - Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1); | |
| 631 | + sqlite3_set_authorizer(g.db, 0, 0); | |
| 632 | + if( rc!=0 || zErr!=0 ){ | |
| 633 | + Th_ErrorMessage(interp, "SQL error: ", | |
| 634 | + zErr ? zErr : sqlite3_errmsg(g.db), -1); | |
| 630 | 635 | return TH_ERROR; |
| 631 | 636 | } |
| 632 | 637 | n = (int)(zTail - zSql); |
| 633 | 638 | zSql += n; |
| 634 | 639 | nSql -= n; |
| 635 | 640 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -611,10 +611,11 @@ | |
| 611 | int nSql; |
| 612 | const char *zTail; |
| 613 | int n, i; |
| 614 | int res = TH_OK; |
| 615 | int nVar; |
| 616 | |
| 617 | if( argc!=3 ){ |
| 618 | return Th_WrongNumArgs(interp, "query SQL CODE"); |
| 619 | } |
| 620 | if( g.db==0 ){ |
| @@ -622,13 +623,17 @@ | |
| 622 | return TH_ERROR; |
| 623 | } |
| 624 | zSql = argv[1]; |
| 625 | nSql = argl[1]; |
| 626 | while( res==TH_OK && nSql>0 ){ |
| 627 | rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail); |
| 628 | if( rc!=0 ){ |
| 629 | Th_ErrorMessage(interp, "SQL error: ", sqlite3_errmsg(g.db), -1); |
| 630 | return TH_ERROR; |
| 631 | } |
| 632 | n = (int)(zTail - zSql); |
| 633 | zSql += n; |
| 634 | nSql -= n; |
| 635 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -611,10 +611,11 @@ | |
| 611 | int nSql; |
| 612 | const char *zTail; |
| 613 | int n, i; |
| 614 | int res = TH_OK; |
| 615 | int nVar; |
| 616 | char *zErr = 0; |
| 617 | |
| 618 | if( argc!=3 ){ |
| 619 | return Th_WrongNumArgs(interp, "query SQL CODE"); |
| 620 | } |
| 621 | if( g.db==0 ){ |
| @@ -622,13 +623,17 @@ | |
| 623 | return TH_ERROR; |
| 624 | } |
| 625 | zSql = argv[1]; |
| 626 | nSql = argl[1]; |
| 627 | while( res==TH_OK && nSql>0 ){ |
| 628 | zErr = 0; |
| 629 | sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr); |
| 630 | rc = sqlite3_prepare_v2(g.db, argv[1], argl[1], &pStmt, &zTail); |
| 631 | sqlite3_set_authorizer(g.db, 0, 0); |
| 632 | if( rc!=0 || zErr!=0 ){ |
| 633 | Th_ErrorMessage(interp, "SQL error: ", |
| 634 | zErr ? zErr : sqlite3_errmsg(g.db), -1); |
| 635 | return TH_ERROR; |
| 636 | } |
| 637 | n = (int)(zTail - zSql); |
| 638 | zSql += n; |
| 639 | nSql -= n; |
| 640 |
+11
-32
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -211,19 +211,20 @@ | ||
| 211 | 211 | if( tmFlags & TIMELINE_GRAPH ){ |
| 212 | 212 | pGraph = graph_init(); |
| 213 | 213 | /* style is not moved to css, because this is |
| 214 | 214 | ** a technical div for the timeline graph |
| 215 | 215 | */ |
| 216 | - @ <div id="canvas" style="position:relative;width:1px;height:1px;" | |
| 216 | + @ <div id="canvas" style="position:relative;height:0px;width:0px;" | |
| 217 | 217 | @ onclick="clickOnGraph(event)"></div> |
| 218 | 218 | } |
| 219 | 219 | db_static_prepare(&qbranch, |
| 220 | 220 | "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid", |
| 221 | 221 | TAG_BRANCH |
| 222 | 222 | ); |
| 223 | 223 | |
| 224 | - @ <table id="timelineTable" class="timelineTable"> | |
| 224 | + @ <table id="timelineTable" class="timelineTable" | |
| 225 | + @ onclick="clickOnGraph(event)"> | |
| 225 | 226 | blob_zero(&comment); |
| 226 | 227 | while( db_step(pQuery)==SQLITE_ROW ){ |
| 227 | 228 | int rid = db_column_int(pQuery, 0); |
| 228 | 229 | const char *zUuid = db_column_text(pQuery, 1); |
| 229 | 230 | int isLeaf = db_column_int(pQuery, 5); |
| @@ -426,10 +427,12 @@ | ||
| 426 | 427 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 427 | 428 | " (SELECT uuid FROM blob WHERE rid=pid)," |
| 428 | 429 | " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm" |
| 429 | 430 | " FROM mlink" |
| 430 | 431 | " WHERE mid=:mid AND (pid!=fid OR pfnid>0)" |
| 432 | + " AND (fid>0 OR" | |
| 433 | + " fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=:mid))" | |
| 431 | 434 | " ORDER BY 3 /*sort*/" |
| 432 | 435 | ); |
| 433 | 436 | fchngQueryInit = 1; |
| 434 | 437 | } |
| 435 | 438 | db_bind_int(&fchngQuery, ":mid", rid); |
| @@ -725,42 +728,16 @@ | ||
| 725 | 728 | @ for(var i in rowinfo){ |
| 726 | 729 | @ rowinfo[i].y = absoluteY("m"+rowinfo[i].id) + 10 - canvasY; |
| 727 | 730 | @ rowinfo[i].x = left + rowinfo[i].r*railPitch; |
| 728 | 731 | @ } |
| 729 | 732 | @ var btm = absoluteY("grbtm") + 10 - canvasY; |
| 730 | -#if 0 | |
| 731 | - @ if( btm<32768 ){ | |
| 732 | - @ canvasDiv.innerHTML = '<canvas id="timeline-canvas" '+ | |
| 733 | - @ 'style="position:absolute;left:'+(left-5)+'px;"' + | |
| 734 | - @ ' width="'+width+'" height="'+btm+'"><'+'/canvas>'; | |
| 735 | - @ realCanvas = gebi('timeline-canvas'); | |
| 736 | - @ }else{ | |
| 737 | - @ realCanvas = 0; | |
| 738 | - @ } | |
| 739 | - @ var context; | |
| 740 | - @ if( realCanvas && realCanvas.getContext | |
| 741 | - @ && (context = realCanvas.getContext('2d'))) { | |
| 742 | - @ drawBox = function(color,x0,y0,x1,y1) { | |
| 743 | - @ if( y0>32767 || y1>32767 ) return; | |
| 744 | - @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } | |
| 745 | - @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } | |
| 746 | - @ if(isNaN(x0) || isNaN(y0) || isNaN(x1) || isNaN(y1)) return; | |
| 747 | - @ context.fillStyle = color; | |
| 748 | - @ context.fillRect(x0-left+5,y0,x1-x0+1,y1-y0+1); | |
| 749 | - @ }; | |
| 750 | - @ } | |
| 751 | -#endif | |
| 752 | 733 | @ for(var i in rowinfo){ |
| 753 | 734 | @ drawNode(rowinfo[i], left, btm); |
| 754 | 735 | @ } |
| 755 | 736 | @ if( selRow!=null ) clickOnRow(selRow); |
| 756 | 737 | @ } |
| 757 | 738 | @ function clickOnGraph(event){ |
| 758 | -#ifdef OMIT_IE8_SUPPORT | |
| 759 | - @ var x=event.clientX-absoluteX("canvas")+window.pageXOffset; | |
| 760 | - @ var y=event.clientY-absoluteY("canvas")+window.pageYOffset; | |
| 761 | -#else | |
| 762 | 739 | @ var x=event.clientX-absoluteX("canvas"); |
| 763 | 740 | @ var y=event.clientY-absoluteY("canvas"); |
| 764 | 741 | @ if(window.pageXOffset!=null){ |
| 765 | 742 | @ x += window.pageXOffset; |
| 766 | 743 | @ y += window.pageYOffset; |
| @@ -768,16 +745,18 @@ | ||
| 768 | 745 | @ var d = window.document.documentElement; |
| 769 | 746 | @ if(document.compatMode!="CSS1Compat") d = d.body; |
| 770 | 747 | @ x += d.scrollLeft; |
| 771 | 748 | @ y += d.scrollTop; |
| 772 | 749 | @ } |
| 773 | -#endif | |
| 750 | + if( P("clicktest")!=0 ){ | |
| 751 | + @ alert("click at "+x+","+y) | |
| 752 | + } | |
| 774 | 753 | @ for(var i in rowinfo){ |
| 775 | 754 | @ p = rowinfo[i]; |
| 776 | - @ if( p.y<y-10 ) continue; | |
| 777 | - @ if( p.y>y+10 ) break; | |
| 778 | - @ if( p.x>x-10 && p.x<x+10 ){ | |
| 755 | + @ if( p.y<y-11 ) continue; | |
| 756 | + @ if( p.y>y+9 ) break; | |
| 757 | + @ if( p.x>x-11 && p.x<x+9 ){ | |
| 779 | 758 | @ clickOnRow(p); |
| 780 | 759 | @ break; |
| 781 | 760 | @ } |
| 782 | 761 | @ } |
| 783 | 762 | @ } |
| 784 | 763 | |
| 785 | 764 | ADDED src/unicode.c |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -211,19 +211,20 @@ | |
| 211 | if( tmFlags & TIMELINE_GRAPH ){ |
| 212 | pGraph = graph_init(); |
| 213 | /* style is not moved to css, because this is |
| 214 | ** a technical div for the timeline graph |
| 215 | */ |
| 216 | @ <div id="canvas" style="position:relative;width:1px;height:1px;" |
| 217 | @ onclick="clickOnGraph(event)"></div> |
| 218 | } |
| 219 | db_static_prepare(&qbranch, |
| 220 | "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid", |
| 221 | TAG_BRANCH |
| 222 | ); |
| 223 | |
| 224 | @ <table id="timelineTable" class="timelineTable"> |
| 225 | blob_zero(&comment); |
| 226 | while( db_step(pQuery)==SQLITE_ROW ){ |
| 227 | int rid = db_column_int(pQuery, 0); |
| 228 | const char *zUuid = db_column_text(pQuery, 1); |
| 229 | int isLeaf = db_column_int(pQuery, 5); |
| @@ -426,10 +427,12 @@ | |
| 426 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 427 | " (SELECT uuid FROM blob WHERE rid=pid)," |
| 428 | " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm" |
| 429 | " FROM mlink" |
| 430 | " WHERE mid=:mid AND (pid!=fid OR pfnid>0)" |
| 431 | " ORDER BY 3 /*sort*/" |
| 432 | ); |
| 433 | fchngQueryInit = 1; |
| 434 | } |
| 435 | db_bind_int(&fchngQuery, ":mid", rid); |
| @@ -725,42 +728,16 @@ | |
| 725 | @ for(var i in rowinfo){ |
| 726 | @ rowinfo[i].y = absoluteY("m"+rowinfo[i].id) + 10 - canvasY; |
| 727 | @ rowinfo[i].x = left + rowinfo[i].r*railPitch; |
| 728 | @ } |
| 729 | @ var btm = absoluteY("grbtm") + 10 - canvasY; |
| 730 | #if 0 |
| 731 | @ if( btm<32768 ){ |
| 732 | @ canvasDiv.innerHTML = '<canvas id="timeline-canvas" '+ |
| 733 | @ 'style="position:absolute;left:'+(left-5)+'px;"' + |
| 734 | @ ' width="'+width+'" height="'+btm+'"><'+'/canvas>'; |
| 735 | @ realCanvas = gebi('timeline-canvas'); |
| 736 | @ }else{ |
| 737 | @ realCanvas = 0; |
| 738 | @ } |
| 739 | @ var context; |
| 740 | @ if( realCanvas && realCanvas.getContext |
| 741 | @ && (context = realCanvas.getContext('2d'))) { |
| 742 | @ drawBox = function(color,x0,y0,x1,y1) { |
| 743 | @ if( y0>32767 || y1>32767 ) return; |
| 744 | @ if( x0>x1 ){ var t=x0; x0=x1; x1=t; } |
| 745 | @ if( y0>y1 ){ var t=y0; y0=y1; y1=t; } |
| 746 | @ if(isNaN(x0) || isNaN(y0) || isNaN(x1) || isNaN(y1)) return; |
| 747 | @ context.fillStyle = color; |
| 748 | @ context.fillRect(x0-left+5,y0,x1-x0+1,y1-y0+1); |
| 749 | @ }; |
| 750 | @ } |
| 751 | #endif |
| 752 | @ for(var i in rowinfo){ |
| 753 | @ drawNode(rowinfo[i], left, btm); |
| 754 | @ } |
| 755 | @ if( selRow!=null ) clickOnRow(selRow); |
| 756 | @ } |
| 757 | @ function clickOnGraph(event){ |
| 758 | #ifdef OMIT_IE8_SUPPORT |
| 759 | @ var x=event.clientX-absoluteX("canvas")+window.pageXOffset; |
| 760 | @ var y=event.clientY-absoluteY("canvas")+window.pageYOffset; |
| 761 | #else |
| 762 | @ var x=event.clientX-absoluteX("canvas"); |
| 763 | @ var y=event.clientY-absoluteY("canvas"); |
| 764 | @ if(window.pageXOffset!=null){ |
| 765 | @ x += window.pageXOffset; |
| 766 | @ y += window.pageYOffset; |
| @@ -768,16 +745,18 @@ | |
| 768 | @ var d = window.document.documentElement; |
| 769 | @ if(document.compatMode!="CSS1Compat") d = d.body; |
| 770 | @ x += d.scrollLeft; |
| 771 | @ y += d.scrollTop; |
| 772 | @ } |
| 773 | #endif |
| 774 | @ for(var i in rowinfo){ |
| 775 | @ p = rowinfo[i]; |
| 776 | @ if( p.y<y-10 ) continue; |
| 777 | @ if( p.y>y+10 ) break; |
| 778 | @ if( p.x>x-10 && p.x<x+10 ){ |
| 779 | @ clickOnRow(p); |
| 780 | @ break; |
| 781 | @ } |
| 782 | @ } |
| 783 | @ } |
| 784 | |
| 785 | DDED src/unicode.c |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -211,19 +211,20 @@ | |
| 211 | if( tmFlags & TIMELINE_GRAPH ){ |
| 212 | pGraph = graph_init(); |
| 213 | /* style is not moved to css, because this is |
| 214 | ** a technical div for the timeline graph |
| 215 | */ |
| 216 | @ <div id="canvas" style="position:relative;height:0px;width:0px;" |
| 217 | @ onclick="clickOnGraph(event)"></div> |
| 218 | } |
| 219 | db_static_prepare(&qbranch, |
| 220 | "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=:rid", |
| 221 | TAG_BRANCH |
| 222 | ); |
| 223 | |
| 224 | @ <table id="timelineTable" class="timelineTable" |
| 225 | @ onclick="clickOnGraph(event)"> |
| 226 | blob_zero(&comment); |
| 227 | while( db_step(pQuery)==SQLITE_ROW ){ |
| 228 | int rid = db_column_int(pQuery, 0); |
| 229 | const char *zUuid = db_column_text(pQuery, 1); |
| 230 | int isLeaf = db_column_int(pQuery, 5); |
| @@ -426,10 +427,12 @@ | |
| 427 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 428 | " (SELECT uuid FROM blob WHERE rid=pid)," |
| 429 | " (SELECT name FROM filename WHERE fnid=mlink.pfnid) AS oldnm" |
| 430 | " FROM mlink" |
| 431 | " WHERE mid=:mid AND (pid!=fid OR pfnid>0)" |
| 432 | " AND (fid>0 OR" |
| 433 | " fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=:mid))" |
| 434 | " ORDER BY 3 /*sort*/" |
| 435 | ); |
| 436 | fchngQueryInit = 1; |
| 437 | } |
| 438 | db_bind_int(&fchngQuery, ":mid", rid); |
| @@ -725,42 +728,16 @@ | |
| 728 | @ for(var i in rowinfo){ |
| 729 | @ rowinfo[i].y = absoluteY("m"+rowinfo[i].id) + 10 - canvasY; |
| 730 | @ rowinfo[i].x = left + rowinfo[i].r*railPitch; |
| 731 | @ } |
| 732 | @ var btm = absoluteY("grbtm") + 10 - canvasY; |
| 733 | @ for(var i in rowinfo){ |
| 734 | @ drawNode(rowinfo[i], left, btm); |
| 735 | @ } |
| 736 | @ if( selRow!=null ) clickOnRow(selRow); |
| 737 | @ } |
| 738 | @ function clickOnGraph(event){ |
| 739 | @ var x=event.clientX-absoluteX("canvas"); |
| 740 | @ var y=event.clientY-absoluteY("canvas"); |
| 741 | @ if(window.pageXOffset!=null){ |
| 742 | @ x += window.pageXOffset; |
| 743 | @ y += window.pageYOffset; |
| @@ -768,16 +745,18 @@ | |
| 745 | @ var d = window.document.documentElement; |
| 746 | @ if(document.compatMode!="CSS1Compat") d = d.body; |
| 747 | @ x += d.scrollLeft; |
| 748 | @ y += d.scrollTop; |
| 749 | @ } |
| 750 | if( P("clicktest")!=0 ){ |
| 751 | @ alert("click at "+x+","+y) |
| 752 | } |
| 753 | @ for(var i in rowinfo){ |
| 754 | @ p = rowinfo[i]; |
| 755 | @ if( p.y<y-11 ) continue; |
| 756 | @ if( p.y>y+9 ) break; |
| 757 | @ if( p.x>x-11 && p.x<x+9 ){ |
| 758 | @ clickOnRow(p); |
| 759 | @ break; |
| 760 | @ } |
| 761 | @ } |
| 762 | @ } |
| 763 | |
| 764 | DDED src/unicode.c |
+528
| --- a/src/unicode.c | ||
| +++ b/src/unicode.c | ||
| @@ -0,0 +1,528 @@ | ||
| 1 | +/* | |
| 2 | +*8028020F606809F8C0B, 0x03600001, | |
| 3 | + 0x03ECA401, | |
| 4 | + 0x03F88033, | |
| 5 | + 0x03FC6807, | |
| 6 | + 0x03FFE405, | |
| 7 | + 0x0406400C, | |
| 8 | + 0x040E7C01, | |
| 9 | + 0x04247C01, | |
| 10 | + 0x0428E003, | |
| 11 | + 0x042B9402 0x043D18 0x0441FC04, 0x0442C012, | |
| 12 | + 0x04450004, 0x04451402, | |
| 13 | + 0x044B7C0C, 0x044C0004, | |
| 14 | + 0x044D2C03, 0x0FC01, 0x00320404, | |
| 15 | + 0x00335402, | |
| 16 | + 0x00351803, | |
| 17 | + 0x0035E401, | |
| 18 | + 0x00376008, | |
| 19 | + 0x00391C09, | |
| 20 | + 6, 0x003AEC02C80331, 0x00AF2835, | |
| 21 | + 0x00B39406, | |
| 22 | + 0x00B5F | |
| 23 | + 0x00BC00D6, | |
| 24 | + 0x00C0D802, | |
| 25 | + 0x00C64002, | |
| 26 | + 0x00C94001, | |
| 27 | + 0x01370040, | |
| 28 | + 0x029A7802, | |
| 29 | + 0x02A00801, | |
| 30 | + 0x02A1D004,2A3E003, | |
| 31 | + 0x02A57C01, | |
| 32 | +3/fts302A8A40E, | |
| 33 | + 0x02A9EC03, | |
| 34 | + 0x02AB0401, | |
| 35 | + 0x02AF8C0B, | |
| 36 | + 0x03EC7801, 0x03ECA | |
| 37 | + 0x03F8001A, | |
| 38 | + 0x03FC040F, | |
| 39 | + 0x03FFA 0x0421DC02, | |
| 40 | + 0x00292C03, | |
| 41 | + 0x042B2001, | |
| 42 | + 0x 0x002AF001, | |
| 43 | + 0x04471409,* | |
| 44 | +*8028 0x002BC002, | |
| 45 | + 0x002D1C02, 0x002D2C03, | |
| 46 | + 0x002E0801, 0x002EF805, | |
| 47 | + 0x002FCC08, 0x00300004, | |
| 48 | + 0x00315402, 0x00318802, | |
| 49 | + 0x0032F807, 0x00331803, | |
| 50 | + 0x00340403, 0x0034F807688, 61700351803, 0x00352804, | |
| 51 | + 0x0035E401, 0x00360802, | |
| 52 | + 0x00376008, 0x0037C803, | |
| 53 | + 0x00391C09, 0x00396802, | |
| 54 | + 0x003B2006, 0x003C041F, | |
| 55 | + 0x003E6424, 0x003EF80F, | |
| 56 | + 0x00415804, 0x00417803, | |
| 57 | + 0x0042080C, 0x00423C01, | |
| 58 | + 0x004E400A, 0 | |
| 59 | + **, 'y', 'y', 'a', 'c0x005F6004, | |
| 60 | + 0x0062A401, 0x0064800C, | |
| 61 | + 0x00677822, 0x00685C05, | |
| 62 | + 0x0069FC01, 0x006A8007, | |
| 63 | + | |
| 64 | + 0x006FF004, 0x00709014,, 0x03600001, | |
| 65 | + 0x03ECA401, | |
| 66 | + 0x03F88033, | |
| 67 | + 0x03FC6807, | |
| 68 | + 0x03FFE405, | |
| 69 | + 0x0406400C | |
| 70 | + 0x007FB403, 0x007FF402, | |
| 71 | + 0 007FB403, 0x007FF402, | |
| 72 | + 0x00822805, 0x0082801F, | |
| 73 | + 0x00842002, 0x00845001, | |
| 74 | + 0x00const static84A401, | |
| 75 | + 0x00852804, 0x00853C01, 0x00862802, 0x0086426F, 0x00900027, | |
| 76 | + 0x009E53E0, 0x00ADD820, | |
| 77 | + 00391C09, | |
| 78 | + 6, 0x003AEC02C80331, 8, 0x00AFB004, 0x00B394060x05BE3C000B5F | |
| 79 | + 0x00BC00D6, | |
| 80 | + 0x00C0 0x00B5C001, 0x00B5FC01, | |
| 81 | + 00C94001, | |
| 82 | + 0x0137005, 0x00BA001A, 0x00C0A807, 0x00C0DC01, | |
| 83 | + 0x00C05, 0x00181816, | |
| 84 | + 0x001B9C07,2A00801, | |
| 85 | + 0x02A0D8 | |
| 86 | + 0x001CC01B,x0472A40E, | |
| 87 | + 0x02A380 | |
| 88 | + 0x00206C09, | |
| 89 | + 0x02A8A40E, 0x02 | |
| 90 | + 0x00217x03600001, | |
| 91 | + 0x03EC7801, 0x03ECA401, | |
| 92 | + 0x03F8001A, 0x03F88033, | |
| 93 | + 0x03FC040F, 0x03FC6807, | |
| 94 | + 0x03FFA007, 0x03FFE405, | |
| 95 | + 0x04063003, 0x0406400C, | |
| 96 | + 0x040DD805, 0x040E7C01, | |
| 97 | + 0x0421DC02, 0x04247C01, | |
| 98 | + 0x04d', 'e', 'e', 'g', 'h', 'i 0x04283004, 0x0428E003, | |
| 99 | + 0x042B2001, 0x042B9402, | |
| 100 | + 0x04400003, 0x0440E016, | |
| 101 | + 0x04449C0E, 0x04450004, | |
| 102 | + 0x04471409, 0x04476C01, | |
| 103 | + 0F606809F8C0B, 0x03600001, | |
| 104 | + 0x044D2C03, 0x044D5C01, | |
| 105 | + 0x0450D412, 0x04512C05, | |
| 106 | + 0x04531801, 0x0456BC07, | |
| 107 | + 0x0459800D, 0x045AAC0D, | |
| 108 | + 040DD805, | |
| 109 | + 0x0421DC02, | |
| 110 | + 41FC04, | |
| 111 | + 0x04450004, | |
| 112 | + 0x0 | |
| 113 | + 0x0471C9800D, | |
| 114 | + 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E, | |
| 115 | + 0x0474FC07, 0x04751C01, | |
| 116 | + 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC05C01, 0x00358802, 0x0035E401, | |
| 117 | + 01, 0x006A8007, | |
| 118 | + 0 0x00376008, | |
| 119 | + 709014,, 0x03600001, | |
| 120 | + 0x00391C09, | |
| 121 | + 807, | |
| 122 | + 0x03FFE405, | |
| 123 | + 0x003B2006, | |
| 124 | + 0x00822805, 0x008 0x003E6424, | |
| 125 | + 849C01, 0x0084A401, | |
| 126 | + 0x00415804, | |
| 127 | + 86426F, 0x00900027, | |
| 128 | + 0x0042080C, | |
| 129 | + 6, 0x003AEC02C80331, 0x004E400A, | |
| 130 | + 0x00BC00D6, | |
| 131 | + 0x00 0x005BAC03, | |
| 132 | + 0x0137005, 0x00BA001 0x005ED023, | |
| 133 | + 0x00C64002, | |
| 134 | + A401, 0x0064800C, | |
| 135 | + 0x00677822, 0x00685C05, | |
| 136 | + 0x0069FC01, 0x006A8007, | |
| 137 | + 0x006CD011, 0x006D6823, | |
| 138 | + 0x006FF004, 0x007090140442C012, | |
| 139 | +/* | |
| 140 | +*8028020F606809F8C0B, 0x0360809F8C0B, 0x03600001, | |
| 141 | + 0x 0x0077F004, 0x007EF401, | |
| 142 | + 0x007FB403, 0x007FF402, | |
| 143 | + 0x00822805, 0x0082801F, | |
| 144 | + 0x00842002, 0x00845001, | |
| 145 | + 0x00849C01, 0x0084A401, | |
| 146 | + 0x00852804, 0x00853C016C011, 0x00672002, | |
| 147 | + | |
| 148 | + 0x0069FC01, 0x006A8007, | |
| 149 | + 0x006CD011, 0x006D6823, | |
| 150 | + 0x006FF004, 0x00709014, | |
| 151 | + 0x00734019, 0x0073B401,, 0x03600001, | |
| 152 | + 0x03ECA401 | |
| 153 | + 0x007FB403, 0x007FFEC01, 0x0 0x02A6CC1B, 0x02A77802, | |
| 154 | + | |
| 155 | + 0x00822805, 0x0082801E,05BE3C000842002, 0x00845001, | |
| 156 | + 0x00849C01, 0x0084A401, | |
| 157 | + 0x00852804, 0x00853C01 0x040400 | |
| 158 | + 0x0092704E, 0x0406400C, 0x040F4 | |
| 159 | + 0x00AEF40C, 0x00AF28082CE407, | |
| 160 | + 0x0441FC04, 0x0442C012, | |
| 161 | + 0x0445CC03, 0x04460003, | |
| 162 | + 0x04477403, 0x0448B012, | |
| 163 | + 0F606809F8C0B, 0x03600001, | |
| 164 | + 0x044D8802,8, 1168660, 186, 6}, | |
| 165 | + {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2}, | |
| 166 | + {8122,0, 1}, | |
| 167 | + {8136,86, 2}, | |
| 168 | + {8154, 15{8170, 154, 2}, | |
| 169 | + {8172, 18848, 2}, {81860, 112, 1}, | |
| 170 | + {8491, 1140836, 1}, | |
| 171 | + {11364, 1104, 1}, | |
| 172 | + {11374, 1060, 1}, {11376, 1029846209, 84, 0, 86}, | |
| 173 | +{42930, 86}, | |
| 174 | + {43888, 92 30204, | |
| 175 | + 54793, 54809, | |
| 176 | + 8028020F606809F020F606809F8C0B, 65268, 65341, | |
| 177 | + 65436, 65439, | |
| 178 | + 65482, 65488, | |
| 179 | + bRemoveDiacritic ));/446, 1}, | |
| 180 | + 4, 8}, | |
| 181 | + {7960, 184, 4980A, 0x02A51C0D, | |
| 182 | + , 184, 8}, {79 0x02A79401, | |
| 183 | + {8040,{8088, 184, 0x02A9DC03, | |
| 184 | + 2}, {8122, 16 0x02AAF802, | |
| 185 | + 0, 1}, {8136, 0x02AD6C01, | |
| 186 | + | |
| 187 | + {81868, 182 | |
| 188 | + 0x037FFC01, | |
| 189 | + | |
| 190 | + {11363, 136, 1}, 0x03F7F002, | |
| 191 | + 1506, 0, 1},*8028020F0E, 0x03F8C02 {42877, 94, 1}, | |
| 192 | + {42893, 86, 1}, | |
| 193 | + {42922, 80, 1}, | |
| 194 | + {42925, 82, 1}, | |
| 195 | + {42929, 840, 831, 68, 1}, | |
| 196 | + {429325268, 65341, 65373, | |
| 197 | + 65450, | |
| 198 | + 65506, | |
| 199 | + 8028020F606809F8C0B, 0x03600001, | |
| 200 | + 03600001, | |
| 201 | + 0x03ECA401, | |
| 202 | + 0x03F88033, | |
| 203 | + 0x03FC6807, | |
| 204 | + 0x03FFE405, | |
| 205 | + 0x0406400C, | |
| 206 | + 0x040E7C01, | |
| 207 | + 0x04247C01, | |
| 208 | + 0x0428E003, | |
| 209 | + 0x042B9402 0x043D18 0x0441FC04, 0x0442C012, | |
| 210 | + 0x04450004, 0x04451402, | |
| 211 | + 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401, | |
| 212 | + 0x00376008, | |
| 213 | + 0x00391C09, | |
| 214 | + 6, 0x003AEC02C80331, 0x00AF2835, | |
| 215 | + 0x00B39406, | |
| 216 | + 0x00B5F | |
| 217 | + 0x00B4, 0x04473401, 0x0448B012, 0x044B7C0C, | |
| 218 | + 0x044C0403, 0x044CF001, 0x044CF807, 0x044DC005, 0x0452C014, | |
| 219 | + 8687, 8}, {8040,86, 8}, 186, 8}, {8104, 1868 {8136,86, 2}, | |
| 220 | + {8154, 15{8170, 154, 2}, | |
| 221 | + {8172, 18848, 2}, {81860, 112, 1}, | |
| 222 | + {8491, 1140836, 1}, | |
| 223 | + {11364, 1104, 1}, | |
| 224 | + B5{11374, 1060, 1}, {11376, 1029846209, 84, 1}, | |
| 225 | + {42930, 86}, | |
| 226 | + {43888, 92 30204, | |
| 227 | + 54793, 54809, | |
| 228 | + 8028020F606809F020F606809F8C0B, 65268, 65341, | |
| 229 | + A34007, 0x07BBC002, | |
| 230 | + | |
| 231 | + 0x07C34425, 0x07C4401F, 0x04247C01, | |
| 232 | + 0x0428E003, | |
| 233 | + 0x042B9402 0x043D18 0x0441FC04, 0x0442C012, | |
| 234 | + 0x04450004, 0x04451402, | |
| 235 | + 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401, | |
| 236 | + 0x00376008, | |
| 237 | + 0x00391C09, | |
| 238 | + 6, 0x003AEC02C80331, 0x00AF2835, | |
| 239 | + 0x00B39406, | |
| 240 | + 0x00B5F | |
| 241 | + 0x00BC00D6, | |
| 242 | + 0x00C0D802, | |
| 243 | + 0x00C64002, | |
| 244 | + 0x00C94001, | |
| 245 | + 0x01370040, | |
| 246 | + 0x029A7802, | |
| 247 | + 0x02A00801, | |
| 248 | + 0x02A1D004,2A3E003, | |
| 249 | + 0x02A57C01, | |
| 250 | + 0x02A8A40E, | |
| 251 | + 0x02A9EC03, | |
| 252 | + 0x02AB0401, | |
| 253 | + 0x02AF8C0B, | |
| 254 | + 0x03EC7801, 0x03ECA | |
| 255 | + 0x03F8001A, | |
| 256 | + 0x03FC040F, | |
| 257 | + 0x03FFA007, | |
| 258 | + 0x04063003, | |
| 259 | + 0x040DD805, | |
| 260 | + 0x0421DC02, | |
| 261 | + 0x04283004, | |
| 262 | + 0x042B2001, | |
| 263 | + 0x04349004, | |
| 264 | + 0x0441FC04, | |
| 265 | + 0x04450004, | |
| 266 | + 0x04471409,* | |
| 267 | +*8028020F606809F8C0, 0x03600001, | |
| 268 | + | |
| 269 | + 0x044D2C03, | |
| 270 | + 0x0450D412, | |
| 271 | + 0x04531801, | |
| 272 | + 0x0459800D, | |
| 273 | + 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E, | |
| 274 | + 0x0474FC07, 0x04751C01, | |
| 275 | + 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010, | |
| 276 | + 442E, 0x05BE3C04, 0x06F27008, | |
| 277 | + | |
| 278 | + 0x075B0401, 0x075B6C01, | |
| 279 | + 0x075D3C01, 0x075DBC01, | |
| 280 | + 0x0760028C, 0x076A6C05, | |
| 281 | + 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007, | |
| 282 | + | |
| 283 | + 0x07C0C064, 0x07C2800F, | |
| 284 | + 0x07C4405C, 0x07C5C03D, | |
| 285 | + 0x07C94A, | |
| 286 | + 0x07DC0074, 0x07DE0059 | |
| 287 | + 0x07E18028,402F, 0x07E50031, | |
| 288 | + 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003, | |
| 289 | + 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928, | |
| 290 | + | |
| 291 | + 4408, 4424, 447 | |
| 292 | + 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, | |
| 293 | + 36, 61880, 61914, 61948, 61998, 62122, | |
| 294 | + 62154, 62200, 62218, 62302, 62364 | |
| 295 | + 62554, | |
| 296 | + 62924char aChar[] = { | |
| 297 | + '\0', '/* | |
| 298 | +*8028'u', 'y', 'y', 'a', 'c', | |
| 299 | + 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', | |
| 300 | + 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', | |
| 301 | + 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', | |
| 302 | + 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0', | |
| 303 | + '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h', | |
| 304 | + 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't', | |
| 305 | + 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a', | |
| 306 | + 'e', 'i', 'o', 'u', return ( | |
| 307 | +*8028020F606809F8C0B,09F8C0B, 0x0360b2058, 1}, | |
| 308 | + {503, 1704627678, 1}, | |
| 309 | + {981, 1828284, 1, 24}, | |
| 310 | + {10081009, 174, 1}, {108846862, 1}, | |
| 311 | + {7297,*8028020F606809F8C0B, 0x03600001, | |
| 312 | + sizeof(aDia)/sizeof(aDia[0] | |
| 313 | + 0x040DD805, | |
| 314 | + 0x0421DC02, | |
| 315 | + 0x04283004, | |
| 316 | + 0x042B2001, | |
| 317 | + 0x04349004, | |
| 318 | + 0x0441FC04, | |
| 319 | + 0x04450004, | |
| 320 | + 0x04471409,* | |
| 321 | +*8028020F606809F8C0, 0x03600001, | |
| 322 | + | |
| 323 | + 0x044D2C03, | |
| 324 | + 0x0450D412, | |
| 325 | + 0x04531801, | |
| 326 | + 0x0459800D, | |
| 327 | + 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E, | |
| 328 | + 0x0474FC07, 0x04751C01, | |
| 329 | + 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010, | |
| 330 | + 442E, 0x05BE3C04, 0x06F27008, | |
| 331 | + | |
| 332 | + 0x075B0401, 0x075B6C01, | |
| 333 | + 0x075D3C01, 0x075DBC01, | |
| 334 | + 0x0760028C, 0x076A6C05, | |
| 335 | + 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007, | |
| 336 | + | |
| 337 | + 0x07C0C064, 0x07C2800F, | |
| 338 | + 0x07C4405C, 0x07C5C03D, | |
| 339 | + 0x07C94A, | |
| 340 | + 0x07DC0074, 0x07DE0059 | |
| 341 | + 0x07E18028,402F, 0x07E50031, | |
| 342 | + 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003, | |
| 343 | + 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928, | |
| 344 | + | |
| 345 | + 4408, 4424, 447 | |
| 346 | + 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, | |
| 347 | + 36, 61880, 61914, 61948, 61998, 62122, | |
| 348 | + 62154, 62200, 62218, 62302, 62364 | |
| 349 | + 62554, | |
| 350 | + 62924char aChar[] = { | |
| 351 | + '\0', '/* | |
| 352 | +*8028'u', 'y', 'y', 'a', 'c', | |
| 353 | + 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', | |
| 354 | + 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', | |
| 355 | + 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', | |
| 356 | + 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0', | |
| 357 | + '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h', | |
| 358 | + 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't', | |
| 359 | + 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a', | |
| 360 | + ';e', 'i', 'o', 'u', return ( | |
| 361 | +*8028020F606809F8C0B,09F8C0B, 0x0360b2058, 1}, | |
| 362 | + {503, 1704627678, 1}, | |
| 363 | + {981, 1828284, 1, 24}, | |
| 364 | + {10081009, 174, 1}, {108846862, 1}, | |
| 365 | + {7297,*8028020F606809F8C0B, 0x03600001, | |
| 366 | + 0x03ECA401, | |
| 367 | + 0x03F88033, | |
| 368 | + 0x03FC6807, | |
| 369 | + 0x03FFE405, | |
| 370 | + 0x0406400C, | |
| 371 | + 0x040E7C01, | |
| 372 | + 0x04247C01, | |
| 373 | + 0x0428E003, | |
| 374 | + 0x042B9402 0x043D18 0x0441FC04, 0x0442C012, | |
| 375 | + 0x04450004, 0x04451402, | |
| 376 | + 0x044B7C0C, 0x044C0004, | |
| 377 | + 0x044D2C03, 0x0600001, | |
| 378 | + 0x03ECA402, 1324, 1}, | |
| 379 | + {7304, 96, 1}, {7312, 138, 43}, {7357, 13867838, 1168660, 186, 6}, | |
| 380 | + {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2}, | |
| 381 | + {8122,0, 1}, | |
| 382 | + {8136,86, 2}, | |
| 383 | + {8154, 15{8170, 154, 2}, | |
| 384 | + {8172, 18848, 2}, {81860, 112, 1}, | |
| 385 | + {8491, 1140836, 1}, | |
| 386 | + {11364, 1104, 1}, | |
| 387 | + {11374, 1060, 1}, {11376, 1029846209, 84, 1}, | |
| 388 | + {42930, 86}, | |
| 389 | + {43888, 92 30204, | |
| 390 | + 54793, 54809, | |
| 391 | + 8028020F606809F020F606809F8C0B, 65268, 65341, | |
| 392 | + 65436, 65439, | |
| 393 | + 65482, 65488, | |
| 394 | + bRemoveDiacritic ));count(aEntry | |
| 395 | + {42925, 82, 1}, | |
| 396 | +sizeof(aEntry)/sizeof(aEntry[0] 0x0456E020, | |
| 397 | + 7976, 18686, 8}, {8008,AAC0D, 0x045C740F, 0x045CF004, | |
| 398 | + | |
| 399 | + 0x05BD442E, 0x05BE3C04, | |
| 400 | + 0x0744A4C0, 0x07480046, | |
| 401 | + 0x075BEC01, 0x075C5401, 'm', 75E2401, 0x075EA401,05BE3C0076A840F, 0x07A340078}, | |
| 402 | + {8120, 184, 2}, {8122, 160, 2}, {8124, 182, 1}, | |
| 403 | + {8126, 120, 1}, {82B}, | |
| 404 | + {8170,6, 2}, | |
| 405 | + B{81868, 1827A, 0x07D5EC29, 0x07D6952C, 0x07DB800D, | |
| 406 | + 0x07DBC004, 0x07DC0074,247C01, | |
| 407 | +7E1400A, 0x07E18028, 0x07E24, | |
| 408 | + 0x044D2C03, 0x0600001, | |
| 409 | + 0x03ECA402, 1324, 1}, | |
| 410 | + {7304, 96, 1}, {7312, 138, 43}, {7357, 13867838, 1168660, 186, 6}, | |
| 411 | + {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2}, | |
| 412 | + {8122,0, 1}, | |
| 413 | + {8136,86, 2}, | |
| 414 | + {8154, 15{8170, 154, 2}, | |
| 415 | + {8172, 18848, 2}, {81860, 112, 1}, | |
| 416 | + {8491, 1140836, 1}, | |
| 417 | + {11364, 1104, 1}, | |
| 418 | + {11374, 1060, 1}, {11376, 1029846209, 84, 1}, | |
| 419 | + {42930, 86}, | |
| 420 | + {43888, 92 30204, | |
| 421 | + 54793, 54809, | |
| 422 | + 8028020F606809F020F606809F8C0B, 65268, 65341, | |
| 423 | + 65436, 65439, | |
| 424 | + 65482, 65488, | |
| 425 | + bRemoveDiacritic ));/446, 1}, | |
| 426 | + 4, 8}, | |
| 427 | + {7960, 184, 6},7976, 184, 8}, {7992, 184, 88008, 184, 6},{8025, 185, 8}, {8040,{8088, 184, 8}, {8104, 184, 8}, | |
| 428 | + {8120, 184, 2}, {8122, 160, 2}, {8124, 182, 1}, | |
| 429 | + {8126, 120, 1}, {8136, 1582, 1}, | |
| 430 | + {8152,4, 2}, | |
| 431 | + {8170,6, 2}, | |
| 432 | + {81868, 182 | |
| 433 | + | |
| 434 | + {8544, 8, 16}, | |
| 435 | + {11264, 24, 47}, | |
| 436 | + {11363, 136, 1}, | |
| 437 | + {11373, 104, 1}, | |
| 438 | + | |
| 439 | + | |
| 440 | + {11506, 0, 1},*8028020F606606809F8C0B, 0x03600001, | |
| 441 | + {42877, 94, 1}, | |
| 442 | + {42893, 86, 1}, | |
| 443 | + {42922, 80, 1}, | |
| 444 | + {42925, 82, 1}, | |
| 445 | + {42929, 840, 831, 68, 1}, | |
| 446 | + {429325268, 65341, 65373, | |
| 447 | + 65450, | |
| 448 | + 65506, | |
| 449 | + 8028020F606809F8C0B, 0x03600001, | |
| 450 | + 03600001, | |
| 451 | + 0x03ECA401, | |
| 452 | + 0x03F88033, | |
| 453 | + 0x03FC6807, | |
| 454 | + 0x03FFE405, | |
| 455 | + 0x0406400C, | |
| 456 | + 0x040E7C01, | |
| 457 | + 0x04247C01, | |
| 458 | + 0x0428E003, | |
| 459 | + 0x042B9402 0x043D18 0x0441FC04, 0x0442C012, | |
| 460 | + 0x04450004, 0x04451402, | |
| 461 | + 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401, | |
| 462 | + 0x00376008, | |
| 463 | + 0x00391C09, | |
| 464 | + 6, 0x003AEC02C80331, 0x00AF2835, | |
| 465 | + 0x00B39406, | |
| 466 | + 0x00B5F | |
| 467 | + 0x00BC00D6, | |
| 468 | + 0x00C0D802, | |
| 469 | + 0x00C64002, | |
| 470 | + 0x00C94001, | |
| 471 | + 0x01370040, | |
| 472 | + 0x029A7802, | |
| 473 | + 0x02A00801, | |
| 474 | + 0x02A1D004,2A3E003, | |
| 475 | + 0x02A57C01, | |
| 476 | + 0x02A8A40E, | |
| 477 | + 0x02A9EC03, | |
| 478 | + 0x02AB0401, | |
| 479 | + 0x02AF8C0B, | |
| 480 | + 0x03EC7801, 0x03ECA | |
| 481 | + 0x03F8001A, | |
| 482 | + 0x03FC040F, | |
| 483 | + 0x03FFA007, | |
| 484 | + 0x04063003, | |
| 485 | + 0x040DD805, | |
| 486 | + 0x0421DC02, | |
| 487 | + 0x04283004, | |
| 488 | + 0x042B2001, | |
| 489 | + 0x04349004, | |
| 490 | + 0x0441FC04, | |
| 491 | + 0x04450004, | |
| 492 | + 0x04471409,* | |
| 493 | +*8028020F606809F8C0, 0x03600001, | |
| 494 | + | |
| 495 | + 0x044D2C03, | |
| 496 | + 0x0450D412, | |
| 497 | + 0x04531801, | |
| 498 | + 0x0459800D, | |
| 499 | + 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E, | |
| 500 | + 0x0474FC07, 0x04751C01, | |
| 501 | + 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010, | |
| 502 | + 442E, 0x05BE3C04, 0x06F27008, | |
| 503 | + | |
| 504 | + 0x075B0401, 0x075B6C01, | |
| 505 | + 0x075D3C01, 0x075DBC01, | |
| 506 | + 0x0760028C, 0x076A6C05, | |
| 507 | + 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007, | |
| 508 | + | |
| 509 | + 0x07C0C064, 0x07C2800F, | |
| 510 | + 0x07C4405C, 0x07C5C03D, | |
| 511 | + 0x07C94A, | |
| 512 | + 0x07DC0074, 0x07DE0059 | |
| 513 | + 0x07E18028,402F, 0x07E50031, | |
| 514 | + 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003, | |
| 515 | + 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928, | |
| 516 | + | |
| 517 | + 4408, 4424, 447 | |
| 518 | + 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, | |
| 519 | + 36, 61880, 61914, 61948, 61998, 62122, | |
| 520 | + 62154, 62200, 62218, 62302, 62364 | |
| 521 | + 62554, | |
| 522 | + 62924char aChar[] = { | |
| 523 | + '\0', '/* | |
| 524 | +*8028'u', 'y', 'y', 'a', 'c', | |
| 525 | + 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', | |
| 526 | + 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', | |
| 527 | + 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', | |
| 528 | + 'u', 's', 't', 'h' |
| --- a/src/unicode.c | |
| +++ b/src/unicode.c | |
| @@ -0,0 +1,528 @@ | |
| --- a/src/unicode.c | |
| +++ b/src/unicode.c | |
| @@ -0,0 +1,528 @@ | |
| 1 | /* |
| 2 | *8028020F606809F8C0B, 0x03600001, |
| 3 | 0x03ECA401, |
| 4 | 0x03F88033, |
| 5 | 0x03FC6807, |
| 6 | 0x03FFE405, |
| 7 | 0x0406400C, |
| 8 | 0x040E7C01, |
| 9 | 0x04247C01, |
| 10 | 0x0428E003, |
| 11 | 0x042B9402 0x043D18 0x0441FC04, 0x0442C012, |
| 12 | 0x04450004, 0x04451402, |
| 13 | 0x044B7C0C, 0x044C0004, |
| 14 | 0x044D2C03, 0x0FC01, 0x00320404, |
| 15 | 0x00335402, |
| 16 | 0x00351803, |
| 17 | 0x0035E401, |
| 18 | 0x00376008, |
| 19 | 0x00391C09, |
| 20 | 6, 0x003AEC02C80331, 0x00AF2835, |
| 21 | 0x00B39406, |
| 22 | 0x00B5F |
| 23 | 0x00BC00D6, |
| 24 | 0x00C0D802, |
| 25 | 0x00C64002, |
| 26 | 0x00C94001, |
| 27 | 0x01370040, |
| 28 | 0x029A7802, |
| 29 | 0x02A00801, |
| 30 | 0x02A1D004,2A3E003, |
| 31 | 0x02A57C01, |
| 32 | 3/fts302A8A40E, |
| 33 | 0x02A9EC03, |
| 34 | 0x02AB0401, |
| 35 | 0x02AF8C0B, |
| 36 | 0x03EC7801, 0x03ECA |
| 37 | 0x03F8001A, |
| 38 | 0x03FC040F, |
| 39 | 0x03FFA 0x0421DC02, |
| 40 | 0x00292C03, |
| 41 | 0x042B2001, |
| 42 | 0x 0x002AF001, |
| 43 | 0x04471409,* |
| 44 | *8028 0x002BC002, |
| 45 | 0x002D1C02, 0x002D2C03, |
| 46 | 0x002E0801, 0x002EF805, |
| 47 | 0x002FCC08, 0x00300004, |
| 48 | 0x00315402, 0x00318802, |
| 49 | 0x0032F807, 0x00331803, |
| 50 | 0x00340403, 0x0034F807688, 61700351803, 0x00352804, |
| 51 | 0x0035E401, 0x00360802, |
| 52 | 0x00376008, 0x0037C803, |
| 53 | 0x00391C09, 0x00396802, |
| 54 | 0x003B2006, 0x003C041F, |
| 55 | 0x003E6424, 0x003EF80F, |
| 56 | 0x00415804, 0x00417803, |
| 57 | 0x0042080C, 0x00423C01, |
| 58 | 0x004E400A, 0 |
| 59 | **, 'y', 'y', 'a', 'c0x005F6004, |
| 60 | 0x0062A401, 0x0064800C, |
| 61 | 0x00677822, 0x00685C05, |
| 62 | 0x0069FC01, 0x006A8007, |
| 63 | |
| 64 | 0x006FF004, 0x00709014,, 0x03600001, |
| 65 | 0x03ECA401, |
| 66 | 0x03F88033, |
| 67 | 0x03FC6807, |
| 68 | 0x03FFE405, |
| 69 | 0x0406400C |
| 70 | 0x007FB403, 0x007FF402, |
| 71 | 0 007FB403, 0x007FF402, |
| 72 | 0x00822805, 0x0082801F, |
| 73 | 0x00842002, 0x00845001, |
| 74 | 0x00const static84A401, |
| 75 | 0x00852804, 0x00853C01, 0x00862802, 0x0086426F, 0x00900027, |
| 76 | 0x009E53E0, 0x00ADD820, |
| 77 | 00391C09, |
| 78 | 6, 0x003AEC02C80331, 8, 0x00AFB004, 0x00B394060x05BE3C000B5F |
| 79 | 0x00BC00D6, |
| 80 | 0x00C0 0x00B5C001, 0x00B5FC01, |
| 81 | 00C94001, |
| 82 | 0x0137005, 0x00BA001A, 0x00C0A807, 0x00C0DC01, |
| 83 | 0x00C05, 0x00181816, |
| 84 | 0x001B9C07,2A00801, |
| 85 | 0x02A0D8 |
| 86 | 0x001CC01B,x0472A40E, |
| 87 | 0x02A380 |
| 88 | 0x00206C09, |
| 89 | 0x02A8A40E, 0x02 |
| 90 | 0x00217x03600001, |
| 91 | 0x03EC7801, 0x03ECA401, |
| 92 | 0x03F8001A, 0x03F88033, |
| 93 | 0x03FC040F, 0x03FC6807, |
| 94 | 0x03FFA007, 0x03FFE405, |
| 95 | 0x04063003, 0x0406400C, |
| 96 | 0x040DD805, 0x040E7C01, |
| 97 | 0x0421DC02, 0x04247C01, |
| 98 | 0x04d', 'e', 'e', 'g', 'h', 'i 0x04283004, 0x0428E003, |
| 99 | 0x042B2001, 0x042B9402, |
| 100 | 0x04400003, 0x0440E016, |
| 101 | 0x04449C0E, 0x04450004, |
| 102 | 0x04471409, 0x04476C01, |
| 103 | 0F606809F8C0B, 0x03600001, |
| 104 | 0x044D2C03, 0x044D5C01, |
| 105 | 0x0450D412, 0x04512C05, |
| 106 | 0x04531801, 0x0456BC07, |
| 107 | 0x0459800D, 0x045AAC0D, |
| 108 | 040DD805, |
| 109 | 0x0421DC02, |
| 110 | 41FC04, |
| 111 | 0x04450004, |
| 112 | 0x0 |
| 113 | 0x0471C9800D, |
| 114 | 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E, |
| 115 | 0x0474FC07, 0x04751C01, |
| 116 | 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC05C01, 0x00358802, 0x0035E401, |
| 117 | 01, 0x006A8007, |
| 118 | 0 0x00376008, |
| 119 | 709014,, 0x03600001, |
| 120 | 0x00391C09, |
| 121 | 807, |
| 122 | 0x03FFE405, |
| 123 | 0x003B2006, |
| 124 | 0x00822805, 0x008 0x003E6424, |
| 125 | 849C01, 0x0084A401, |
| 126 | 0x00415804, |
| 127 | 86426F, 0x00900027, |
| 128 | 0x0042080C, |
| 129 | 6, 0x003AEC02C80331, 0x004E400A, |
| 130 | 0x00BC00D6, |
| 131 | 0x00 0x005BAC03, |
| 132 | 0x0137005, 0x00BA001 0x005ED023, |
| 133 | 0x00C64002, |
| 134 | A401, 0x0064800C, |
| 135 | 0x00677822, 0x00685C05, |
| 136 | 0x0069FC01, 0x006A8007, |
| 137 | 0x006CD011, 0x006D6823, |
| 138 | 0x006FF004, 0x007090140442C012, |
| 139 | /* |
| 140 | *8028020F606809F8C0B, 0x0360809F8C0B, 0x03600001, |
| 141 | 0x 0x0077F004, 0x007EF401, |
| 142 | 0x007FB403, 0x007FF402, |
| 143 | 0x00822805, 0x0082801F, |
| 144 | 0x00842002, 0x00845001, |
| 145 | 0x00849C01, 0x0084A401, |
| 146 | 0x00852804, 0x00853C016C011, 0x00672002, |
| 147 | |
| 148 | 0x0069FC01, 0x006A8007, |
| 149 | 0x006CD011, 0x006D6823, |
| 150 | 0x006FF004, 0x00709014, |
| 151 | 0x00734019, 0x0073B401,, 0x03600001, |
| 152 | 0x03ECA401 |
| 153 | 0x007FB403, 0x007FFEC01, 0x0 0x02A6CC1B, 0x02A77802, |
| 154 | |
| 155 | 0x00822805, 0x0082801E,05BE3C000842002, 0x00845001, |
| 156 | 0x00849C01, 0x0084A401, |
| 157 | 0x00852804, 0x00853C01 0x040400 |
| 158 | 0x0092704E, 0x0406400C, 0x040F4 |
| 159 | 0x00AEF40C, 0x00AF28082CE407, |
| 160 | 0x0441FC04, 0x0442C012, |
| 161 | 0x0445CC03, 0x04460003, |
| 162 | 0x04477403, 0x0448B012, |
| 163 | 0F606809F8C0B, 0x03600001, |
| 164 | 0x044D8802,8, 1168660, 186, 6}, |
| 165 | {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2}, |
| 166 | {8122,0, 1}, |
| 167 | {8136,86, 2}, |
| 168 | {8154, 15{8170, 154, 2}, |
| 169 | {8172, 18848, 2}, {81860, 112, 1}, |
| 170 | {8491, 1140836, 1}, |
| 171 | {11364, 1104, 1}, |
| 172 | {11374, 1060, 1}, {11376, 1029846209, 84, 0, 86}, |
| 173 | {42930, 86}, |
| 174 | {43888, 92 30204, |
| 175 | 54793, 54809, |
| 176 | 8028020F606809F020F606809F8C0B, 65268, 65341, |
| 177 | 65436, 65439, |
| 178 | 65482, 65488, |
| 179 | bRemoveDiacritic ));/446, 1}, |
| 180 | 4, 8}, |
| 181 | {7960, 184, 4980A, 0x02A51C0D, |
| 182 | , 184, 8}, {79 0x02A79401, |
| 183 | {8040,{8088, 184, 0x02A9DC03, |
| 184 | 2}, {8122, 16 0x02AAF802, |
| 185 | 0, 1}, {8136, 0x02AD6C01, |
| 186 | |
| 187 | {81868, 182 |
| 188 | 0x037FFC01, |
| 189 | |
| 190 | {11363, 136, 1}, 0x03F7F002, |
| 191 | 1506, 0, 1},*8028020F0E, 0x03F8C02 {42877, 94, 1}, |
| 192 | {42893, 86, 1}, |
| 193 | {42922, 80, 1}, |
| 194 | {42925, 82, 1}, |
| 195 | {42929, 840, 831, 68, 1}, |
| 196 | {429325268, 65341, 65373, |
| 197 | 65450, |
| 198 | 65506, |
| 199 | 8028020F606809F8C0B, 0x03600001, |
| 200 | 03600001, |
| 201 | 0x03ECA401, |
| 202 | 0x03F88033, |
| 203 | 0x03FC6807, |
| 204 | 0x03FFE405, |
| 205 | 0x0406400C, |
| 206 | 0x040E7C01, |
| 207 | 0x04247C01, |
| 208 | 0x0428E003, |
| 209 | 0x042B9402 0x043D18 0x0441FC04, 0x0442C012, |
| 210 | 0x04450004, 0x04451402, |
| 211 | 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401, |
| 212 | 0x00376008, |
| 213 | 0x00391C09, |
| 214 | 6, 0x003AEC02C80331, 0x00AF2835, |
| 215 | 0x00B39406, |
| 216 | 0x00B5F |
| 217 | 0x00B4, 0x04473401, 0x0448B012, 0x044B7C0C, |
| 218 | 0x044C0403, 0x044CF001, 0x044CF807, 0x044DC005, 0x0452C014, |
| 219 | 8687, 8}, {8040,86, 8}, 186, 8}, {8104, 1868 {8136,86, 2}, |
| 220 | {8154, 15{8170, 154, 2}, |
| 221 | {8172, 18848, 2}, {81860, 112, 1}, |
| 222 | {8491, 1140836, 1}, |
| 223 | {11364, 1104, 1}, |
| 224 | B5{11374, 1060, 1}, {11376, 1029846209, 84, 1}, |
| 225 | {42930, 86}, |
| 226 | {43888, 92 30204, |
| 227 | 54793, 54809, |
| 228 | 8028020F606809F020F606809F8C0B, 65268, 65341, |
| 229 | A34007, 0x07BBC002, |
| 230 | |
| 231 | 0x07C34425, 0x07C4401F, 0x04247C01, |
| 232 | 0x0428E003, |
| 233 | 0x042B9402 0x043D18 0x0441FC04, 0x0442C012, |
| 234 | 0x04450004, 0x04451402, |
| 235 | 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401, |
| 236 | 0x00376008, |
| 237 | 0x00391C09, |
| 238 | 6, 0x003AEC02C80331, 0x00AF2835, |
| 239 | 0x00B39406, |
| 240 | 0x00B5F |
| 241 | 0x00BC00D6, |
| 242 | 0x00C0D802, |
| 243 | 0x00C64002, |
| 244 | 0x00C94001, |
| 245 | 0x01370040, |
| 246 | 0x029A7802, |
| 247 | 0x02A00801, |
| 248 | 0x02A1D004,2A3E003, |
| 249 | 0x02A57C01, |
| 250 | 0x02A8A40E, |
| 251 | 0x02A9EC03, |
| 252 | 0x02AB0401, |
| 253 | 0x02AF8C0B, |
| 254 | 0x03EC7801, 0x03ECA |
| 255 | 0x03F8001A, |
| 256 | 0x03FC040F, |
| 257 | 0x03FFA007, |
| 258 | 0x04063003, |
| 259 | 0x040DD805, |
| 260 | 0x0421DC02, |
| 261 | 0x04283004, |
| 262 | 0x042B2001, |
| 263 | 0x04349004, |
| 264 | 0x0441FC04, |
| 265 | 0x04450004, |
| 266 | 0x04471409,* |
| 267 | *8028020F606809F8C0, 0x03600001, |
| 268 | |
| 269 | 0x044D2C03, |
| 270 | 0x0450D412, |
| 271 | 0x04531801, |
| 272 | 0x0459800D, |
| 273 | 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E, |
| 274 | 0x0474FC07, 0x04751C01, |
| 275 | 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010, |
| 276 | 442E, 0x05BE3C04, 0x06F27008, |
| 277 | |
| 278 | 0x075B0401, 0x075B6C01, |
| 279 | 0x075D3C01, 0x075DBC01, |
| 280 | 0x0760028C, 0x076A6C05, |
| 281 | 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007, |
| 282 | |
| 283 | 0x07C0C064, 0x07C2800F, |
| 284 | 0x07C4405C, 0x07C5C03D, |
| 285 | 0x07C94A, |
| 286 | 0x07DC0074, 0x07DE0059 |
| 287 | 0x07E18028,402F, 0x07E50031, |
| 288 | 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003, |
| 289 | 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928, |
| 290 | |
| 291 | 4408, 4424, 447 |
| 292 | 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, |
| 293 | 36, 61880, 61914, 61948, 61998, 62122, |
| 294 | 62154, 62200, 62218, 62302, 62364 |
| 295 | 62554, |
| 296 | 62924char aChar[] = { |
| 297 | '\0', '/* |
| 298 | *8028'u', 'y', 'y', 'a', 'c', |
| 299 | 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', |
| 300 | 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', |
| 301 | 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', |
| 302 | 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0', |
| 303 | '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h', |
| 304 | 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't', |
| 305 | 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a', |
| 306 | 'e', 'i', 'o', 'u', return ( |
| 307 | *8028020F606809F8C0B,09F8C0B, 0x0360b2058, 1}, |
| 308 | {503, 1704627678, 1}, |
| 309 | {981, 1828284, 1, 24}, |
| 310 | {10081009, 174, 1}, {108846862, 1}, |
| 311 | {7297,*8028020F606809F8C0B, 0x03600001, |
| 312 | sizeof(aDia)/sizeof(aDia[0] |
| 313 | 0x040DD805, |
| 314 | 0x0421DC02, |
| 315 | 0x04283004, |
| 316 | 0x042B2001, |
| 317 | 0x04349004, |
| 318 | 0x0441FC04, |
| 319 | 0x04450004, |
| 320 | 0x04471409,* |
| 321 | *8028020F606809F8C0, 0x03600001, |
| 322 | |
| 323 | 0x044D2C03, |
| 324 | 0x0450D412, |
| 325 | 0x04531801, |
| 326 | 0x0459800D, |
| 327 | 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E, |
| 328 | 0x0474FC07, 0x04751C01, |
| 329 | 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010, |
| 330 | 442E, 0x05BE3C04, 0x06F27008, |
| 331 | |
| 332 | 0x075B0401, 0x075B6C01, |
| 333 | 0x075D3C01, 0x075DBC01, |
| 334 | 0x0760028C, 0x076A6C05, |
| 335 | 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007, |
| 336 | |
| 337 | 0x07C0C064, 0x07C2800F, |
| 338 | 0x07C4405C, 0x07C5C03D, |
| 339 | 0x07C94A, |
| 340 | 0x07DC0074, 0x07DE0059 |
| 341 | 0x07E18028,402F, 0x07E50031, |
| 342 | 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003, |
| 343 | 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928, |
| 344 | |
| 345 | 4408, 4424, 447 |
| 346 | 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, |
| 347 | 36, 61880, 61914, 61948, 61998, 62122, |
| 348 | 62154, 62200, 62218, 62302, 62364 |
| 349 | 62554, |
| 350 | 62924char aChar[] = { |
| 351 | '\0', '/* |
| 352 | *8028'u', 'y', 'y', 'a', 'c', |
| 353 | 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', |
| 354 | 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', |
| 355 | 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', |
| 356 | 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0', |
| 357 | '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h', |
| 358 | 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't', |
| 359 | 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a', |
| 360 | ';e', 'i', 'o', 'u', return ( |
| 361 | *8028020F606809F8C0B,09F8C0B, 0x0360b2058, 1}, |
| 362 | {503, 1704627678, 1}, |
| 363 | {981, 1828284, 1, 24}, |
| 364 | {10081009, 174, 1}, {108846862, 1}, |
| 365 | {7297,*8028020F606809F8C0B, 0x03600001, |
| 366 | 0x03ECA401, |
| 367 | 0x03F88033, |
| 368 | 0x03FC6807, |
| 369 | 0x03FFE405, |
| 370 | 0x0406400C, |
| 371 | 0x040E7C01, |
| 372 | 0x04247C01, |
| 373 | 0x0428E003, |
| 374 | 0x042B9402 0x043D18 0x0441FC04, 0x0442C012, |
| 375 | 0x04450004, 0x04451402, |
| 376 | 0x044B7C0C, 0x044C0004, |
| 377 | 0x044D2C03, 0x0600001, |
| 378 | 0x03ECA402, 1324, 1}, |
| 379 | {7304, 96, 1}, {7312, 138, 43}, {7357, 13867838, 1168660, 186, 6}, |
| 380 | {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2}, |
| 381 | {8122,0, 1}, |
| 382 | {8136,86, 2}, |
| 383 | {8154, 15{8170, 154, 2}, |
| 384 | {8172, 18848, 2}, {81860, 112, 1}, |
| 385 | {8491, 1140836, 1}, |
| 386 | {11364, 1104, 1}, |
| 387 | {11374, 1060, 1}, {11376, 1029846209, 84, 1}, |
| 388 | {42930, 86}, |
| 389 | {43888, 92 30204, |
| 390 | 54793, 54809, |
| 391 | 8028020F606809F020F606809F8C0B, 65268, 65341, |
| 392 | 65436, 65439, |
| 393 | 65482, 65488, |
| 394 | bRemoveDiacritic ));count(aEntry |
| 395 | {42925, 82, 1}, |
| 396 | sizeof(aEntry)/sizeof(aEntry[0] 0x0456E020, |
| 397 | 7976, 18686, 8}, {8008,AAC0D, 0x045C740F, 0x045CF004, |
| 398 | |
| 399 | 0x05BD442E, 0x05BE3C04, |
| 400 | 0x0744A4C0, 0x07480046, |
| 401 | 0x075BEC01, 0x075C5401, 'm', 75E2401, 0x075EA401,05BE3C0076A840F, 0x07A340078}, |
| 402 | {8120, 184, 2}, {8122, 160, 2}, {8124, 182, 1}, |
| 403 | {8126, 120, 1}, {82B}, |
| 404 | {8170,6, 2}, |
| 405 | B{81868, 1827A, 0x07D5EC29, 0x07D6952C, 0x07DB800D, |
| 406 | 0x07DBC004, 0x07DC0074,247C01, |
| 407 | 7E1400A, 0x07E18028, 0x07E24, |
| 408 | 0x044D2C03, 0x0600001, |
| 409 | 0x03ECA402, 1324, 1}, |
| 410 | {7304, 96, 1}, {7312, 138, 43}, {7357, 13867838, 1168660, 186, 6}, |
| 411 | {7976, 18686, 8}, {8008, 18687, 8}, {8040,86, 8}, {8104, 18686, 2}, |
| 412 | {8122,0, 1}, |
| 413 | {8136,86, 2}, |
| 414 | {8154, 15{8170, 154, 2}, |
| 415 | {8172, 18848, 2}, {81860, 112, 1}, |
| 416 | {8491, 1140836, 1}, |
| 417 | {11364, 1104, 1}, |
| 418 | {11374, 1060, 1}, {11376, 1029846209, 84, 1}, |
| 419 | {42930, 86}, |
| 420 | {43888, 92 30204, |
| 421 | 54793, 54809, |
| 422 | 8028020F606809F020F606809F8C0B, 65268, 65341, |
| 423 | 65436, 65439, |
| 424 | 65482, 65488, |
| 425 | bRemoveDiacritic ));/446, 1}, |
| 426 | 4, 8}, |
| 427 | {7960, 184, 6},7976, 184, 8}, {7992, 184, 88008, 184, 6},{8025, 185, 8}, {8040,{8088, 184, 8}, {8104, 184, 8}, |
| 428 | {8120, 184, 2}, {8122, 160, 2}, {8124, 182, 1}, |
| 429 | {8126, 120, 1}, {8136, 1582, 1}, |
| 430 | {8152,4, 2}, |
| 431 | {8170,6, 2}, |
| 432 | {81868, 182 |
| 433 | |
| 434 | {8544, 8, 16}, |
| 435 | {11264, 24, 47}, |
| 436 | {11363, 136, 1}, |
| 437 | {11373, 104, 1}, |
| 438 | |
| 439 | |
| 440 | {11506, 0, 1},*8028020F606606809F8C0B, 0x03600001, |
| 441 | {42877, 94, 1}, |
| 442 | {42893, 86, 1}, |
| 443 | {42922, 80, 1}, |
| 444 | {42925, 82, 1}, |
| 445 | {42929, 840, 831, 68, 1}, |
| 446 | {429325268, 65341, 65373, |
| 447 | 65450, |
| 448 | 65506, |
| 449 | 8028020F606809F8C0B, 0x03600001, |
| 450 | 03600001, |
| 451 | 0x03ECA401, |
| 452 | 0x03F88033, |
| 453 | 0x03FC6807, |
| 454 | 0x03FFE405, |
| 455 | 0x0406400C, |
| 456 | 0x040E7C01, |
| 457 | 0x04247C01, |
| 458 | 0x0428E003, |
| 459 | 0x042B9402 0x043D18 0x0441FC04, 0x0442C012, |
| 460 | 0x04450004, 0x04451402, |
| 461 | 0x044B7C0C, 0x044C00sizeof(aEntry)/sizeof(aEntry[0] 0x0035E401, |
| 462 | 0x00376008, |
| 463 | 0x00391C09, |
| 464 | 6, 0x003AEC02C80331, 0x00AF2835, |
| 465 | 0x00B39406, |
| 466 | 0x00B5F |
| 467 | 0x00BC00D6, |
| 468 | 0x00C0D802, |
| 469 | 0x00C64002, |
| 470 | 0x00C94001, |
| 471 | 0x01370040, |
| 472 | 0x029A7802, |
| 473 | 0x02A00801, |
| 474 | 0x02A1D004,2A3E003, |
| 475 | 0x02A57C01, |
| 476 | 0x02A8A40E, |
| 477 | 0x02A9EC03, |
| 478 | 0x02AB0401, |
| 479 | 0x02AF8C0B, |
| 480 | 0x03EC7801, 0x03ECA |
| 481 | 0x03F8001A, |
| 482 | 0x03FC040F, |
| 483 | 0x03FFA007, |
| 484 | 0x04063003, |
| 485 | 0x040DD805, |
| 486 | 0x0421DC02, |
| 487 | 0x04283004, |
| 488 | 0x042B2001, |
| 489 | 0x04349004, |
| 490 | 0x0441FC04, |
| 491 | 0x04450004, |
| 492 | 0x04471409,* |
| 493 | *8028020F606809F8C0, 0x03600001, |
| 494 | |
| 495 | 0x044D2C03, |
| 496 | 0x0450D412, |
| 497 | 0x04531801, |
| 498 | 0x0459800D, |
| 499 | 0x0468040A, 0x0468CC07,46A7805, 0x0470BC08,4724816, 0x0472A40E, |
| 500 | 0x0474FC07, 0x04751C01, |
| 501 | 0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010, |
| 502 | 442E, 0x05BE3C04, 0x06F27008, |
| 503 | |
| 504 | 0x075B0401, 0x075B6C01, |
| 505 | 0x075D3C01, 0x075DBC01, |
| 506 | 0x0760028C, 0x076A6C05, |
| 507 | 0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007, |
| 508 | |
| 509 | 0x07C0C064, 0x07C2800F, |
| 510 | 0x07C4405C, 0x07C5C03D, |
| 511 | 0x07C94A, |
| 512 | 0x07DC0074, 0x07DE0059 |
| 513 | 0x07E18028,402F, 0x07E50031, |
| 514 | 0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003, |
| 515 | 0x07E74030, 0x07E9800E, 0x38000401, 0x38008060,){896, 3912, 3928, |
| 516 | |
| 517 | 4408, 4424, 447 |
| 518 | 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, |
| 519 | 36, 61880, 61914, 61948, 61998, 62122, |
| 520 | 62154, 62200, 62218, 62302, 62364 |
| 521 | 62554, |
| 522 | 62924char aChar[] = { |
| 523 | '\0', '/* |
| 524 | *8028'u', 'y', 'y', 'a', 'c', |
| 525 | 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', |
| 526 | 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', |
| 527 | 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', |
| 528 | 'u', 's', 't', 'h' |
+10
-5
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -715,14 +715,18 @@ | ||
| 715 | 715 | int vid; |
| 716 | 716 | vid = db_lget_int("checkout", 0); |
| 717 | 717 | vfile_check_signature(vid, 0); |
| 718 | 718 | db_multi_exec( |
| 719 | 719 | "DELETE FROM vmerge;" |
| 720 | - "INSERT INTO torevert " | |
| 721 | - "SELECT pathname" | |
| 722 | - " FROM vfile " | |
| 723 | - " WHERE chnged OR deleted OR rid=0 OR pathname!=origname;" | |
| 720 | + "INSERT OR IGNORE INTO torevert " | |
| 721 | + " SELECT pathname" | |
| 722 | + " FROM vfile " | |
| 723 | + " WHERE chnged OR deleted OR rid=0 OR pathname!=origname " | |
| 724 | + " UNION ALL " | |
| 725 | + " SELECT origname" | |
| 726 | + " FROM vfile" | |
| 727 | + " WHERE origname!=pathname;" | |
| 724 | 728 | ); |
| 725 | 729 | } |
| 726 | 730 | blob_zero(&record); |
| 727 | 731 | db_prepare(&q, "SELECT name FROM torevert"); |
| 728 | 732 | if( zRevision==0 ){ |
| @@ -736,11 +740,12 @@ | ||
| 736 | 740 | zFile = db_column_text(&q, 0); |
| 737 | 741 | zFull = mprintf("%/%/", g.zLocalRoot, zFile); |
| 738 | 742 | errCode = historical_version_of_file(zRevision, zFile, &record, |
| 739 | 743 | &isLink, &isExe, 0, 2); |
| 740 | 744 | if( errCode==2 ){ |
| 741 | - if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){ | |
| 745 | + if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q OR origname=%Q", | |
| 746 | + zFile, zFile)==0 ){ | |
| 742 | 747 | fossil_print("UNMANAGE: %s\n", zFile); |
| 743 | 748 | }else{ |
| 744 | 749 | undo_save(zFile); |
| 745 | 750 | file_delete(zFull); |
| 746 | 751 | fossil_print("DELETE: %s\n", zFile); |
| 747 | 752 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -715,14 +715,18 @@ | |
| 715 | int vid; |
| 716 | vid = db_lget_int("checkout", 0); |
| 717 | vfile_check_signature(vid, 0); |
| 718 | db_multi_exec( |
| 719 | "DELETE FROM vmerge;" |
| 720 | "INSERT INTO torevert " |
| 721 | "SELECT pathname" |
| 722 | " FROM vfile " |
| 723 | " WHERE chnged OR deleted OR rid=0 OR pathname!=origname;" |
| 724 | ); |
| 725 | } |
| 726 | blob_zero(&record); |
| 727 | db_prepare(&q, "SELECT name FROM torevert"); |
| 728 | if( zRevision==0 ){ |
| @@ -736,11 +740,12 @@ | |
| 736 | zFile = db_column_text(&q, 0); |
| 737 | zFull = mprintf("%/%/", g.zLocalRoot, zFile); |
| 738 | errCode = historical_version_of_file(zRevision, zFile, &record, |
| 739 | &isLink, &isExe, 0, 2); |
| 740 | if( errCode==2 ){ |
| 741 | if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){ |
| 742 | fossil_print("UNMANAGE: %s\n", zFile); |
| 743 | }else{ |
| 744 | undo_save(zFile); |
| 745 | file_delete(zFull); |
| 746 | fossil_print("DELETE: %s\n", zFile); |
| 747 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -715,14 +715,18 @@ | |
| 715 | int vid; |
| 716 | vid = db_lget_int("checkout", 0); |
| 717 | vfile_check_signature(vid, 0); |
| 718 | db_multi_exec( |
| 719 | "DELETE FROM vmerge;" |
| 720 | "INSERT OR IGNORE INTO torevert " |
| 721 | " SELECT pathname" |
| 722 | " FROM vfile " |
| 723 | " WHERE chnged OR deleted OR rid=0 OR pathname!=origname " |
| 724 | " UNION ALL " |
| 725 | " SELECT origname" |
| 726 | " FROM vfile" |
| 727 | " WHERE origname!=pathname;" |
| 728 | ); |
| 729 | } |
| 730 | blob_zero(&record); |
| 731 | db_prepare(&q, "SELECT name FROM torevert"); |
| 732 | if( zRevision==0 ){ |
| @@ -736,11 +740,12 @@ | |
| 740 | zFile = db_column_text(&q, 0); |
| 741 | zFull = mprintf("%/%/", g.zLocalRoot, zFile); |
| 742 | errCode = historical_version_of_file(zRevision, zFile, &record, |
| 743 | &isLink, &isExe, 0, 2); |
| 744 | if( errCode==2 ){ |
| 745 | if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q OR origname=%Q", |
| 746 | zFile, zFile)==0 ){ |
| 747 | fossil_print("UNMANAGE: %s\n", zFile); |
| 748 | }else{ |
| 749 | undo_save(zFile); |
| 750 | file_delete(zFull); |
| 751 | fossil_print("DELETE: %s\n", zFile); |
| 752 |
+7
-3
| --- src/user.c | ||
| +++ src/user.c | ||
| @@ -303,15 +303,17 @@ | ||
| 303 | 303 | ** |
| 304 | 304 | ** (2) If the local database is open, check in VVAR. |
| 305 | 305 | ** |
| 306 | 306 | ** (3) Check the default user in the repository |
| 307 | 307 | ** |
| 308 | -** (4) Try the USER environment variable. | |
| 308 | +** (4) Try the FOSSIL_USER environment variable. | |
| 309 | +** | |
| 310 | +** (5) Try the USER environment variable. | |
| 309 | 311 | ** |
| 310 | -** (5) Try the USERNAME environment variable. | |
| 312 | +** (6) Try the USERNAME environment variable. | |
| 311 | 313 | ** |
| 312 | -** (6) Check if the user can be extracted from the remote URL. | |
| 314 | +** (7) Check if the user can be extracted from the remote URL. | |
| 313 | 315 | ** |
| 314 | 316 | ** The user name is stored in g.zLogin. The uid is in g.userUid. |
| 315 | 317 | */ |
| 316 | 318 | void user_select(void){ |
| 317 | 319 | char *zUrl; |
| @@ -326,10 +328,12 @@ | ||
| 326 | 328 | } |
| 327 | 329 | |
| 328 | 330 | if( g.localOpen && attempt_user(db_lget("default-user",0)) ) return; |
| 329 | 331 | |
| 330 | 332 | if( attempt_user(db_get("default-user", 0)) ) return; |
| 333 | + | |
| 334 | + if( attempt_user(fossil_getenv("FOSSIL_USER")) ) return; | |
| 331 | 335 | |
| 332 | 336 | if( attempt_user(fossil_getenv("USER")) ) return; |
| 333 | 337 | |
| 334 | 338 | if( attempt_user(fossil_getenv("USERNAME")) ) return; |
| 335 | 339 | |
| 336 | 340 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -303,15 +303,17 @@ | |
| 303 | ** |
| 304 | ** (2) If the local database is open, check in VVAR. |
| 305 | ** |
| 306 | ** (3) Check the default user in the repository |
| 307 | ** |
| 308 | ** (4) Try the USER environment variable. |
| 309 | ** |
| 310 | ** (5) Try the USERNAME environment variable. |
| 311 | ** |
| 312 | ** (6) Check if the user can be extracted from the remote URL. |
| 313 | ** |
| 314 | ** The user name is stored in g.zLogin. The uid is in g.userUid. |
| 315 | */ |
| 316 | void user_select(void){ |
| 317 | char *zUrl; |
| @@ -326,10 +328,12 @@ | |
| 326 | } |
| 327 | |
| 328 | if( g.localOpen && attempt_user(db_lget("default-user",0)) ) return; |
| 329 | |
| 330 | if( attempt_user(db_get("default-user", 0)) ) return; |
| 331 | |
| 332 | if( attempt_user(fossil_getenv("USER")) ) return; |
| 333 | |
| 334 | if( attempt_user(fossil_getenv("USERNAME")) ) return; |
| 335 | |
| 336 |
| --- src/user.c | |
| +++ src/user.c | |
| @@ -303,15 +303,17 @@ | |
| 303 | ** |
| 304 | ** (2) If the local database is open, check in VVAR. |
| 305 | ** |
| 306 | ** (3) Check the default user in the repository |
| 307 | ** |
| 308 | ** (4) Try the FOSSIL_USER environment variable. |
| 309 | ** |
| 310 | ** (5) Try the USER environment variable. |
| 311 | ** |
| 312 | ** (6) Try the USERNAME environment variable. |
| 313 | ** |
| 314 | ** (7) Check if the user can be extracted from the remote URL. |
| 315 | ** |
| 316 | ** The user name is stored in g.zLogin. The uid is in g.userUid. |
| 317 | */ |
| 318 | void user_select(void){ |
| 319 | char *zUrl; |
| @@ -326,10 +328,12 @@ | |
| 328 | } |
| 329 | |
| 330 | if( g.localOpen && attempt_user(db_lget("default-user",0)) ) return; |
| 331 | |
| 332 | if( attempt_user(db_get("default-user", 0)) ) return; |
| 333 | |
| 334 | if( attempt_user(fossil_getenv("FOSSIL_USER")) ) return; |
| 335 | |
| 336 | if( attempt_user(fossil_getenv("USER")) ) return; |
| 337 | |
| 338 | if( attempt_user(fossil_getenv("USERNAME")) ) return; |
| 339 | |
| 340 |
+3
-3
| --- src/utf8.c | ||
| +++ src/utf8.c | ||
| @@ -101,11 +101,11 @@ | ||
| 101 | 101 | #else |
| 102 | 102 | /* No-op on unix */ |
| 103 | 103 | #endif |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | -#if defined(__APPLE__) | |
| 106 | +#if defined(__APPLE__) && !defined(WITHOUT_ICONV) | |
| 107 | 107 | # include <iconv.h> |
| 108 | 108 | #endif |
| 109 | 109 | |
| 110 | 110 | /* |
| 111 | 111 | ** Translate text from the filename character set into |
| @@ -120,11 +120,11 @@ | ||
| 120 | 120 | if( zUtf==0 ){ |
| 121 | 121 | return 0; |
| 122 | 122 | } |
| 123 | 123 | WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0); |
| 124 | 124 | return zUtf; |
| 125 | -#elif defined(__APPLE__) | |
| 125 | +#elif defined(__APPLE__) && !defined(WITHOUT_ICONV) | |
| 126 | 126 | char *zIn = (char*)zFilename; |
| 127 | 127 | char *zOut; |
| 128 | 128 | iconv_t cd; |
| 129 | 129 | size_t n, x; |
| 130 | 130 | for(n=0; zIn[n]>0 && zIn[n]<=0x7f; n++){} |
| @@ -157,11 +157,11 @@ | ||
| 157 | 157 | ** fossil_filename_to_utf8(). |
| 158 | 158 | */ |
| 159 | 159 | void fossil_filename_free(char *pOld){ |
| 160 | 160 | #if defined(_WIN32) |
| 161 | 161 | sqlite3_free(pOld); |
| 162 | -#elif defined(__APPLE__) | |
| 162 | +#elif defined(__APPLE__) && !defined(WITHOUT_ICONV) | |
| 163 | 163 | fossil_free(pOld); |
| 164 | 164 | #else |
| 165 | 165 | /* No-op on all other unix */ |
| 166 | 166 | #endif |
| 167 | 167 | } |
| 168 | 168 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -101,11 +101,11 @@ | |
| 101 | #else |
| 102 | /* No-op on unix */ |
| 103 | #endif |
| 104 | } |
| 105 | |
| 106 | #if defined(__APPLE__) |
| 107 | # include <iconv.h> |
| 108 | #endif |
| 109 | |
| 110 | /* |
| 111 | ** Translate text from the filename character set into |
| @@ -120,11 +120,11 @@ | |
| 120 | if( zUtf==0 ){ |
| 121 | return 0; |
| 122 | } |
| 123 | WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0); |
| 124 | return zUtf; |
| 125 | #elif defined(__APPLE__) |
| 126 | char *zIn = (char*)zFilename; |
| 127 | char *zOut; |
| 128 | iconv_t cd; |
| 129 | size_t n, x; |
| 130 | for(n=0; zIn[n]>0 && zIn[n]<=0x7f; n++){} |
| @@ -157,11 +157,11 @@ | |
| 157 | ** fossil_filename_to_utf8(). |
| 158 | */ |
| 159 | void fossil_filename_free(char *pOld){ |
| 160 | #if defined(_WIN32) |
| 161 | sqlite3_free(pOld); |
| 162 | #elif defined(__APPLE__) |
| 163 | fossil_free(pOld); |
| 164 | #else |
| 165 | /* No-op on all other unix */ |
| 166 | #endif |
| 167 | } |
| 168 |
| --- src/utf8.c | |
| +++ src/utf8.c | |
| @@ -101,11 +101,11 @@ | |
| 101 | #else |
| 102 | /* No-op on unix */ |
| 103 | #endif |
| 104 | } |
| 105 | |
| 106 | #if defined(__APPLE__) && !defined(WITHOUT_ICONV) |
| 107 | # include <iconv.h> |
| 108 | #endif |
| 109 | |
| 110 | /* |
| 111 | ** Translate text from the filename character set into |
| @@ -120,11 +120,11 @@ | |
| 120 | if( zUtf==0 ){ |
| 121 | return 0; |
| 122 | } |
| 123 | WideCharToMultiByte(CP_UTF8, 0, zFilename, -1, zUtf, nByte, 0, 0); |
| 124 | return zUtf; |
| 125 | #elif defined(__APPLE__) && !defined(WITHOUT_ICONV) |
| 126 | char *zIn = (char*)zFilename; |
| 127 | char *zOut; |
| 128 | iconv_t cd; |
| 129 | size_t n, x; |
| 130 | for(n=0; zIn[n]>0 && zIn[n]<=0x7f; n++){} |
| @@ -157,11 +157,11 @@ | |
| 157 | ** fossil_filename_to_utf8(). |
| 158 | */ |
| 159 | void fossil_filename_free(char *pOld){ |
| 160 | #if defined(_WIN32) |
| 161 | sqlite3_free(pOld); |
| 162 | #elif defined(__APPLE__) && !defined(WITHOUT_ICONV) |
| 163 | fossil_free(pOld); |
| 164 | #else |
| 165 | /* No-op on all other unix */ |
| 166 | #endif |
| 167 | } |
| 168 |
+1
-1
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -667,11 +667,11 @@ | ||
| 667 | 667 | if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){ |
| 668 | 668 | blob_init(&w2, pW2->zWiki, -1); |
| 669 | 669 | } |
| 670 | 670 | blob_zero(&d); |
| 671 | 671 | diffFlags = construct_diff_flags(1,0); |
| 672 | - text_diff(&w2, &w1, &d, diffFlags | DIFF_HTML | DIFF_LINENO); | |
| 672 | + text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO); | |
| 673 | 673 | @ <div class="udiff"> |
| 674 | 674 | @ %s(blob_str(&d)) |
| 675 | 675 | @ </div> |
| 676 | 676 | manifest_destroy(pW1); |
| 677 | 677 | manifest_destroy(pW2); |
| 678 | 678 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -667,11 +667,11 @@ | |
| 667 | if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){ |
| 668 | blob_init(&w2, pW2->zWiki, -1); |
| 669 | } |
| 670 | blob_zero(&d); |
| 671 | diffFlags = construct_diff_flags(1,0); |
| 672 | text_diff(&w2, &w1, &d, diffFlags | DIFF_HTML | DIFF_LINENO); |
| 673 | @ <div class="udiff"> |
| 674 | @ %s(blob_str(&d)) |
| 675 | @ </div> |
| 676 | manifest_destroy(pW1); |
| 677 | manifest_destroy(pW2); |
| 678 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -667,11 +667,11 @@ | |
| 667 | if( rid2 && (pW2 = manifest_get(rid2, CFTYPE_WIKI))!=0 ){ |
| 668 | blob_init(&w2, pW2->zWiki, -1); |
| 669 | } |
| 670 | blob_zero(&d); |
| 671 | diffFlags = construct_diff_flags(1,0); |
| 672 | text_diff(&w2, &w1, &d, 0, diffFlags | DIFF_HTML | DIFF_LINENO); |
| 673 | @ <div class="udiff"> |
| 674 | @ %s(blob_str(&d)) |
| 675 | @ </div> |
| 676 | manifest_destroy(pW1); |
| 677 | manifest_destroy(pW2); |
| 678 |
+23
| --- test/diff-test-1.wiki | ||
| +++ test/diff-test-1.wiki | ||
| @@ -18,10 +18,33 @@ | ||
| 18 | 18 | * <a href="../../../fdiff?v1=57b0d8183cab0e3d&v2=37b3ef49d73cdfe6" |
| 19 | 19 | target="testwindow">Large diff of sqlite3.c</a>. This diff was very |
| 20 | 20 | slow prior to the preformance enhancement change [9e15437e97]. |
| 21 | 21 | * <a href="../../../info/bda00cbada#chunk42" target="testwindow"> |
| 22 | 22 | A difficult indentation change. |
| 23 | + * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk13" | |
| 24 | + target="testwindow">Another tricky indentation.</a> Notice especially | |
| 25 | + lines 59398 and 59407 on the left. | |
| 26 | + * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk13" | |
| 27 | + target="testwindow">Inverse of the previous.</a> | |
| 28 | + * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk24" | |
| 29 | + target="testwindow">A complex change</a> that is difficult to align, and | |
| 30 | + hence falls back to the "delete left and insert right" strategy. | |
| 31 | + * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk24" | |
| 32 | + target="testwindow">Inverse of the previous.</a> | |
| 33 | + * <a href="../../../fdiff?v1=21f9a00fe2fa4a17&v2=d5c4ff0532bd89c3#chunk5" | |
| 34 | + target="testwindow">sqlite3.c changes</a> | |
| 35 | + that are difficult to align. | |
| 36 | + * <a href="../../../fdiff?v2=21f9a00fe2fa4a17&v1=d5c4ff0532bd89c3#chunk5" | |
| 37 | + target="testwindow">sqlite3.c changes inverted.</a> | |
| 23 | 38 | |
| 24 | 39 | External: |
| 25 | 40 | |
| 26 | 41 | * <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow"> |
| 27 | 42 | Code indentation change.</a> |
| 43 | + * <a href="http://www.sqlite.org/src/info/52e755943f" target="testwindow"> | |
| 44 | + A complex change (chunk 1) in which the alignment becomes so complex | |
| 45 | + that it is better for clarity to abandon it and just show the left | |
| 46 | + and right sides contiguously.</a> | |
| 47 | + * <a href="http://www.sqlite.org/src/info/3d65c70343#chunk5" | |
| 48 | + target="testwindow"> | |
| 49 | + An indentation change. See especially lines 2313 and 2317 on the right, | |
| 50 | + that their green indentation addition is left-justified.</a> | |
| 28 | 51 |
| --- test/diff-test-1.wiki | |
| +++ test/diff-test-1.wiki | |
| @@ -18,10 +18,33 @@ | |
| 18 | * <a href="../../../fdiff?v1=57b0d8183cab0e3d&v2=37b3ef49d73cdfe6" |
| 19 | target="testwindow">Large diff of sqlite3.c</a>. This diff was very |
| 20 | slow prior to the preformance enhancement change [9e15437e97]. |
| 21 | * <a href="../../../info/bda00cbada#chunk42" target="testwindow"> |
| 22 | A difficult indentation change. |
| 23 | |
| 24 | External: |
| 25 | |
| 26 | * <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow"> |
| 27 | Code indentation change.</a> |
| 28 |
| --- test/diff-test-1.wiki | |
| +++ test/diff-test-1.wiki | |
| @@ -18,10 +18,33 @@ | |
| 18 | * <a href="../../../fdiff?v1=57b0d8183cab0e3d&v2=37b3ef49d73cdfe6" |
| 19 | target="testwindow">Large diff of sqlite3.c</a>. This diff was very |
| 20 | slow prior to the preformance enhancement change [9e15437e97]. |
| 21 | * <a href="../../../info/bda00cbada#chunk42" target="testwindow"> |
| 22 | A difficult indentation change. |
| 23 | * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk13" |
| 24 | target="testwindow">Another tricky indentation.</a> Notice especially |
| 25 | lines 59398 and 59407 on the left. |
| 26 | * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk13" |
| 27 | target="testwindow">Inverse of the previous.</a> |
| 28 | * <a href="../../../fdiff?v1=955cc67ace8fb622&v2=e2e1c87b86664b45#chunk24" |
| 29 | target="testwindow">A complex change</a> that is difficult to align, and |
| 30 | hence falls back to the "delete left and insert right" strategy. |
| 31 | * <a href="../../../fdiff?v2=955cc67ace8fb622&v1=e2e1c87b86664b45#chunk24" |
| 32 | target="testwindow">Inverse of the previous.</a> |
| 33 | * <a href="../../../fdiff?v1=21f9a00fe2fa4a17&v2=d5c4ff0532bd89c3#chunk5" |
| 34 | target="testwindow">sqlite3.c changes</a> |
| 35 | that are difficult to align. |
| 36 | * <a href="../../../fdiff?v2=21f9a00fe2fa4a17&v1=d5c4ff0532bd89c3#chunk5" |
| 37 | target="testwindow">sqlite3.c changes inverted.</a> |
| 38 | |
| 39 | External: |
| 40 | |
| 41 | * <a href="http://www.sqlite.org/src/fdiff?v1=aafcb21a74e41f9a&v2=a6d127dd05daf0f9#chunk3" target="testwindow"> |
| 42 | Code indentation change.</a> |
| 43 | * <a href="http://www.sqlite.org/src/info/52e755943f" target="testwindow"> |
| 44 | A complex change (chunk 1) in which the alignment becomes so complex |
| 45 | that it is better for clarity to abandon it and just show the left |
| 46 | and right sides contiguously.</a> |
| 47 | * <a href="http://www.sqlite.org/src/info/3d65c70343#chunk5" |
| 48 | target="testwindow"> |
| 49 | An indentation change. See especially lines 2313 and 2317 on the right, |
| 50 | that their green indentation addition is left-justified.</a> |
| 51 |
+16
-4
| --- win/Makefile.dmc | ||
| +++ win/Makefile.dmc | ||
| @@ -26,13 +26,13 @@ | ||
| 26 | 26 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) |
| 27 | 27 | LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 |
| 28 | 28 | |
| 29 | 29 | SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 |
| 30 | 30 | |
| 31 | -SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c | |
| 31 | +SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c | |
| 32 | 32 | |
| 33 | -OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O | |
| 33 | +OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O | |
| 34 | 34 | |
| 35 | 35 | |
| 36 | 36 | RC=$(DMDIR)\bin\rcc |
| 37 | 37 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 38 | 38 | |
| @@ -46,11 +46,11 @@ | ||
| 46 | 46 | |
| 47 | 47 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 48 | 48 | $(RC) $(RCFLAGS) -o$@ $** |
| 49 | 49 | |
| 50 | 50 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 51 | - +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ | |
| 51 | + +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ | |
| 52 | 52 | +echo fossil >> $@ |
| 53 | 53 | +echo fossil >> $@ |
| 54 | 54 | +echo $(LIBS) >> $@ |
| 55 | 55 | +echo. >> $@ |
| 56 | 56 | +echo fossil >> $@ |
| @@ -523,10 +523,16 @@ | ||
| 523 | 523 | $(OBJDIR)\rebuild$O : rebuild_.c rebuild.h |
| 524 | 524 | $(TCC) -o$@ -c rebuild_.c |
| 525 | 525 | |
| 526 | 526 | rebuild_.c : $(SRCDIR)\rebuild.c |
| 527 | 527 | +translate$E $** > $@ |
| 528 | + | |
| 529 | +$(OBJDIR)\regexp$O : regexp_.c regexp.h | |
| 530 | + $(TCC) -o$@ -c regexp_.c | |
| 531 | + | |
| 532 | +regexp_.c : $(SRCDIR)\regexp.c | |
| 533 | + +translate$E $** > $@ | |
| 528 | 534 | |
| 529 | 535 | $(OBJDIR)\report$O : report_.c report.h |
| 530 | 536 | $(TCC) -o$@ -c report_.c |
| 531 | 537 | |
| 532 | 538 | report_.c : $(SRCDIR)\report.c |
| @@ -643,10 +649,16 @@ | ||
| 643 | 649 | $(OBJDIR)\undo$O : undo_.c undo.h |
| 644 | 650 | $(TCC) -o$@ -c undo_.c |
| 645 | 651 | |
| 646 | 652 | undo_.c : $(SRCDIR)\undo.c |
| 647 | 653 | +translate$E $** > $@ |
| 654 | + | |
| 655 | +$(OBJDIR)\unicode$O : unicode_.c unicode.h | |
| 656 | + $(TCC) -o$@ -c unicode_.c | |
| 657 | + | |
| 658 | +unicode_.c : $(SRCDIR)\unicode.c | |
| 659 | + +translate$E $** > $@ | |
| 648 | 660 | |
| 649 | 661 | $(OBJDIR)\update$O : update_.c update.h |
| 650 | 662 | $(TCC) -o$@ -c update_.c |
| 651 | 663 | |
| 652 | 664 | update_.c : $(SRCDIR)\update.c |
| @@ -723,7 +735,7 @@ | ||
| 723 | 735 | |
| 724 | 736 | zip_.c : $(SRCDIR)\zip.c |
| 725 | 737 | +translate$E $** > $@ |
| 726 | 738 | |
| 727 | 739 | headers: makeheaders$E page_index.h VERSION.h |
| 728 | - +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h | |
| 740 | + +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h | |
| 729 | 741 | @copy /Y nul: headers |
| 730 | 742 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -26,13 +26,13 @@ | |
| 26 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) |
| 27 | LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 |
| 28 | |
| 29 | SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 |
| 30 | |
| 31 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 32 | |
| 33 | OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O |
| 34 | |
| 35 | |
| 36 | RC=$(DMDIR)\bin\rcc |
| 37 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 38 | |
| @@ -46,11 +46,11 @@ | |
| 46 | |
| 47 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 48 | $(RC) $(RCFLAGS) -o$@ $** |
| 49 | |
| 50 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 51 | +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| 52 | +echo fossil >> $@ |
| 53 | +echo fossil >> $@ |
| 54 | +echo $(LIBS) >> $@ |
| 55 | +echo. >> $@ |
| 56 | +echo fossil >> $@ |
| @@ -523,10 +523,16 @@ | |
| 523 | $(OBJDIR)\rebuild$O : rebuild_.c rebuild.h |
| 524 | $(TCC) -o$@ -c rebuild_.c |
| 525 | |
| 526 | rebuild_.c : $(SRCDIR)\rebuild.c |
| 527 | +translate$E $** > $@ |
| 528 | |
| 529 | $(OBJDIR)\report$O : report_.c report.h |
| 530 | $(TCC) -o$@ -c report_.c |
| 531 | |
| 532 | report_.c : $(SRCDIR)\report.c |
| @@ -643,10 +649,16 @@ | |
| 643 | $(OBJDIR)\undo$O : undo_.c undo.h |
| 644 | $(TCC) -o$@ -c undo_.c |
| 645 | |
| 646 | undo_.c : $(SRCDIR)\undo.c |
| 647 | +translate$E $** > $@ |
| 648 | |
| 649 | $(OBJDIR)\update$O : update_.c update.h |
| 650 | $(TCC) -o$@ -c update_.c |
| 651 | |
| 652 | update_.c : $(SRCDIR)\update.c |
| @@ -723,7 +735,7 @@ | |
| 723 | |
| 724 | zip_.c : $(SRCDIR)\zip.c |
| 725 | +translate$E $** > $@ |
| 726 | |
| 727 | headers: makeheaders$E page_index.h VERSION.h |
| 728 | +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h |
| 729 | @copy /Y nul: headers |
| 730 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -26,13 +26,13 @@ | |
| 26 | TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) |
| 27 | LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 |
| 28 | |
| 29 | SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 |
| 30 | |
| 31 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 32 | |
| 33 | OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O |
| 34 | |
| 35 | |
| 36 | RC=$(DMDIR)\bin\rcc |
| 37 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 38 | |
| @@ -46,11 +46,11 @@ | |
| 46 | |
| 47 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 48 | $(RC) $(RCFLAGS) -o$@ $** |
| 49 | |
| 50 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 51 | +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| 52 | +echo fossil >> $@ |
| 53 | +echo fossil >> $@ |
| 54 | +echo $(LIBS) >> $@ |
| 55 | +echo. >> $@ |
| 56 | +echo fossil >> $@ |
| @@ -523,10 +523,16 @@ | |
| 523 | $(OBJDIR)\rebuild$O : rebuild_.c rebuild.h |
| 524 | $(TCC) -o$@ -c rebuild_.c |
| 525 | |
| 526 | rebuild_.c : $(SRCDIR)\rebuild.c |
| 527 | +translate$E $** > $@ |
| 528 | |
| 529 | $(OBJDIR)\regexp$O : regexp_.c regexp.h |
| 530 | $(TCC) -o$@ -c regexp_.c |
| 531 | |
| 532 | regexp_.c : $(SRCDIR)\regexp.c |
| 533 | +translate$E $** > $@ |
| 534 | |
| 535 | $(OBJDIR)\report$O : report_.c report.h |
| 536 | $(TCC) -o$@ -c report_.c |
| 537 | |
| 538 | report_.c : $(SRCDIR)\report.c |
| @@ -643,10 +649,16 @@ | |
| 649 | $(OBJDIR)\undo$O : undo_.c undo.h |
| 650 | $(TCC) -o$@ -c undo_.c |
| 651 | |
| 652 | undo_.c : $(SRCDIR)\undo.c |
| 653 | +translate$E $** > $@ |
| 654 | |
| 655 | $(OBJDIR)\unicode$O : unicode_.c unicode.h |
| 656 | $(TCC) -o$@ -c unicode_.c |
| 657 | |
| 658 | unicode_.c : $(SRCDIR)\unicode.c |
| 659 | +translate$E $** > $@ |
| 660 | |
| 661 | $(OBJDIR)\update$O : update_.c update.h |
| 662 | $(TCC) -o$@ -c update_.c |
| 663 | |
| 664 | update_.c : $(SRCDIR)\update.c |
| @@ -723,7 +735,7 @@ | |
| 735 | |
| 736 | zip_.c : $(SRCDIR)\zip.c |
| 737 | +translate$E $** > $@ |
| 738 | |
| 739 | headers: makeheaders$E page_index.h VERSION.h |
| 740 | +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h |
| 741 | @copy /Y nul: headers |
| 742 |
+25
-1
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -73,11 +73,11 @@ | ||
| 73 | 73 | |
| 74 | 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | 75 | # be enabled by default. |
| 76 | 76 | # |
| 77 | 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | -ifeq ($(PREFIX),) | |
| 78 | +ifeq (,$(findstring w64-mingw32,$(PREFIX))) | |
| 79 | 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | 80 | endif |
| 81 | 81 | endif |
| 82 | 82 | |
| 83 | 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | ||
| 331 | 331 | $(SRCDIR)/pivot.c \ |
| 332 | 332 | $(SRCDIR)/popen.c \ |
| 333 | 333 | $(SRCDIR)/pqueue.c \ |
| 334 | 334 | $(SRCDIR)/printf.c \ |
| 335 | 335 | $(SRCDIR)/rebuild.c \ |
| 336 | + $(SRCDIR)/regexp.c \ | |
| 336 | 337 | $(SRCDIR)/report.c \ |
| 337 | 338 | $(SRCDIR)/rss.c \ |
| 338 | 339 | $(SRCDIR)/schema.c \ |
| 339 | 340 | $(SRCDIR)/search.c \ |
| 340 | 341 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | ||
| 351 | 352 | $(SRCDIR)/th_main.c \ |
| 352 | 353 | $(SRCDIR)/timeline.c \ |
| 353 | 354 | $(SRCDIR)/tkt.c \ |
| 354 | 355 | $(SRCDIR)/tktsetup.c \ |
| 355 | 356 | $(SRCDIR)/undo.c \ |
| 357 | + $(SRCDIR)/unicode.c \ | |
| 356 | 358 | $(SRCDIR)/update.c \ |
| 357 | 359 | $(SRCDIR)/url.c \ |
| 358 | 360 | $(SRCDIR)/user.c \ |
| 359 | 361 | $(SRCDIR)/utf8.c \ |
| 360 | 362 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | ||
| 435 | 437 | $(OBJDIR)/pivot_.c \ |
| 436 | 438 | $(OBJDIR)/popen_.c \ |
| 437 | 439 | $(OBJDIR)/pqueue_.c \ |
| 438 | 440 | $(OBJDIR)/printf_.c \ |
| 439 | 441 | $(OBJDIR)/rebuild_.c \ |
| 442 | + $(OBJDIR)/regexp_.c \ | |
| 440 | 443 | $(OBJDIR)/report_.c \ |
| 441 | 444 | $(OBJDIR)/rss_.c \ |
| 442 | 445 | $(OBJDIR)/schema_.c \ |
| 443 | 446 | $(OBJDIR)/search_.c \ |
| 444 | 447 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | ||
| 455 | 458 | $(OBJDIR)/th_main_.c \ |
| 456 | 459 | $(OBJDIR)/timeline_.c \ |
| 457 | 460 | $(OBJDIR)/tkt_.c \ |
| 458 | 461 | $(OBJDIR)/tktsetup_.c \ |
| 459 | 462 | $(OBJDIR)/undo_.c \ |
| 463 | + $(OBJDIR)/unicode_.c \ | |
| 460 | 464 | $(OBJDIR)/update_.c \ |
| 461 | 465 | $(OBJDIR)/url_.c \ |
| 462 | 466 | $(OBJDIR)/user_.c \ |
| 463 | 467 | $(OBJDIR)/utf8_.c \ |
| 464 | 468 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | ||
| 539 | 543 | $(OBJDIR)/pivot.o \ |
| 540 | 544 | $(OBJDIR)/popen.o \ |
| 541 | 545 | $(OBJDIR)/pqueue.o \ |
| 542 | 546 | $(OBJDIR)/printf.o \ |
| 543 | 547 | $(OBJDIR)/rebuild.o \ |
| 548 | + $(OBJDIR)/regexp.o \ | |
| 544 | 549 | $(OBJDIR)/report.o \ |
| 545 | 550 | $(OBJDIR)/rss.o \ |
| 546 | 551 | $(OBJDIR)/schema.o \ |
| 547 | 552 | $(OBJDIR)/search.o \ |
| 548 | 553 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | ||
| 559 | 564 | $(OBJDIR)/th_main.o \ |
| 560 | 565 | $(OBJDIR)/timeline.o \ |
| 561 | 566 | $(OBJDIR)/tkt.o \ |
| 562 | 567 | $(OBJDIR)/tktsetup.o \ |
| 563 | 568 | $(OBJDIR)/undo.o \ |
| 569 | + $(OBJDIR)/unicode.o \ | |
| 564 | 570 | $(OBJDIR)/update.o \ |
| 565 | 571 | $(OBJDIR)/url.o \ |
| 566 | 572 | $(OBJDIR)/user.o \ |
| 567 | 573 | $(OBJDIR)/utf8.o \ |
| 568 | 574 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | ||
| 756 | 762 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 757 | 763 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 758 | 764 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 759 | 765 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 760 | 766 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 767 | + $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ | |
| 761 | 768 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 762 | 769 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 763 | 770 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 764 | 771 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 765 | 772 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | ||
| 776 | 783 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 777 | 784 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 778 | 785 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 779 | 786 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 780 | 787 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 788 | + $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \ | |
| 781 | 789 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 782 | 790 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 783 | 791 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 784 | 792 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 785 | 793 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | ||
| 1349 | 1357 | |
| 1350 | 1358 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1351 | 1359 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1352 | 1360 | |
| 1353 | 1361 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1362 | + | |
| 1363 | +$(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate | |
| 1364 | + $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c | |
| 1365 | + | |
| 1366 | +$(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h | |
| 1367 | + $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c | |
| 1368 | + | |
| 1369 | +$(OBJDIR)/regexp.h: $(OBJDIR)/headers | |
| 1354 | 1370 | |
| 1355 | 1371 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1356 | 1372 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1357 | 1373 | |
| 1358 | 1374 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | ||
| 1509 | 1525 | |
| 1510 | 1526 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1511 | 1527 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1512 | 1528 | |
| 1513 | 1529 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1530 | + | |
| 1531 | +$(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate | |
| 1532 | + $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c | |
| 1533 | + | |
| 1534 | +$(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h | |
| 1535 | + $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c | |
| 1536 | + | |
| 1537 | +$(OBJDIR)/unicode.h: $(OBJDIR)/headers | |
| 1514 | 1538 | |
| 1515 | 1539 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1516 | 1540 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1517 | 1541 | |
| 1518 | 1542 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1519 | 1543 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -73,11 +73,11 @@ | |
| 73 | |
| 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | # be enabled by default. |
| 76 | # |
| 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | ifeq ($(PREFIX),) |
| 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | endif |
| 81 | endif |
| 82 | |
| 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | |
| 331 | $(SRCDIR)/pivot.c \ |
| 332 | $(SRCDIR)/popen.c \ |
| 333 | $(SRCDIR)/pqueue.c \ |
| 334 | $(SRCDIR)/printf.c \ |
| 335 | $(SRCDIR)/rebuild.c \ |
| 336 | $(SRCDIR)/report.c \ |
| 337 | $(SRCDIR)/rss.c \ |
| 338 | $(SRCDIR)/schema.c \ |
| 339 | $(SRCDIR)/search.c \ |
| 340 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | |
| 351 | $(SRCDIR)/th_main.c \ |
| 352 | $(SRCDIR)/timeline.c \ |
| 353 | $(SRCDIR)/tkt.c \ |
| 354 | $(SRCDIR)/tktsetup.c \ |
| 355 | $(SRCDIR)/undo.c \ |
| 356 | $(SRCDIR)/update.c \ |
| 357 | $(SRCDIR)/url.c \ |
| 358 | $(SRCDIR)/user.c \ |
| 359 | $(SRCDIR)/utf8.c \ |
| 360 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | |
| 435 | $(OBJDIR)/pivot_.c \ |
| 436 | $(OBJDIR)/popen_.c \ |
| 437 | $(OBJDIR)/pqueue_.c \ |
| 438 | $(OBJDIR)/printf_.c \ |
| 439 | $(OBJDIR)/rebuild_.c \ |
| 440 | $(OBJDIR)/report_.c \ |
| 441 | $(OBJDIR)/rss_.c \ |
| 442 | $(OBJDIR)/schema_.c \ |
| 443 | $(OBJDIR)/search_.c \ |
| 444 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | |
| 455 | $(OBJDIR)/th_main_.c \ |
| 456 | $(OBJDIR)/timeline_.c \ |
| 457 | $(OBJDIR)/tkt_.c \ |
| 458 | $(OBJDIR)/tktsetup_.c \ |
| 459 | $(OBJDIR)/undo_.c \ |
| 460 | $(OBJDIR)/update_.c \ |
| 461 | $(OBJDIR)/url_.c \ |
| 462 | $(OBJDIR)/user_.c \ |
| 463 | $(OBJDIR)/utf8_.c \ |
| 464 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | |
| 539 | $(OBJDIR)/pivot.o \ |
| 540 | $(OBJDIR)/popen.o \ |
| 541 | $(OBJDIR)/pqueue.o \ |
| 542 | $(OBJDIR)/printf.o \ |
| 543 | $(OBJDIR)/rebuild.o \ |
| 544 | $(OBJDIR)/report.o \ |
| 545 | $(OBJDIR)/rss.o \ |
| 546 | $(OBJDIR)/schema.o \ |
| 547 | $(OBJDIR)/search.o \ |
| 548 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | |
| 559 | $(OBJDIR)/th_main.o \ |
| 560 | $(OBJDIR)/timeline.o \ |
| 561 | $(OBJDIR)/tkt.o \ |
| 562 | $(OBJDIR)/tktsetup.o \ |
| 563 | $(OBJDIR)/undo.o \ |
| 564 | $(OBJDIR)/update.o \ |
| 565 | $(OBJDIR)/url.o \ |
| 566 | $(OBJDIR)/user.o \ |
| 567 | $(OBJDIR)/utf8.o \ |
| 568 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | |
| 756 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 757 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 758 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 759 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 760 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 761 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 762 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 763 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 764 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 765 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | |
| 776 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 777 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 778 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 779 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 780 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 781 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 782 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 783 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 784 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 785 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | |
| 1349 | |
| 1350 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1351 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1352 | |
| 1353 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1354 | |
| 1355 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1356 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1357 | |
| 1358 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | |
| 1509 | |
| 1510 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1511 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1512 | |
| 1513 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1514 | |
| 1515 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1516 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1517 | |
| 1518 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1519 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -73,11 +73,11 @@ | |
| 73 | |
| 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | # be enabled by default. |
| 76 | # |
| 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | endif |
| 81 | endif |
| 82 | |
| 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | |
| 331 | $(SRCDIR)/pivot.c \ |
| 332 | $(SRCDIR)/popen.c \ |
| 333 | $(SRCDIR)/pqueue.c \ |
| 334 | $(SRCDIR)/printf.c \ |
| 335 | $(SRCDIR)/rebuild.c \ |
| 336 | $(SRCDIR)/regexp.c \ |
| 337 | $(SRCDIR)/report.c \ |
| 338 | $(SRCDIR)/rss.c \ |
| 339 | $(SRCDIR)/schema.c \ |
| 340 | $(SRCDIR)/search.c \ |
| 341 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | |
| 352 | $(SRCDIR)/th_main.c \ |
| 353 | $(SRCDIR)/timeline.c \ |
| 354 | $(SRCDIR)/tkt.c \ |
| 355 | $(SRCDIR)/tktsetup.c \ |
| 356 | $(SRCDIR)/undo.c \ |
| 357 | $(SRCDIR)/unicode.c \ |
| 358 | $(SRCDIR)/update.c \ |
| 359 | $(SRCDIR)/url.c \ |
| 360 | $(SRCDIR)/user.c \ |
| 361 | $(SRCDIR)/utf8.c \ |
| 362 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | |
| 437 | $(OBJDIR)/pivot_.c \ |
| 438 | $(OBJDIR)/popen_.c \ |
| 439 | $(OBJDIR)/pqueue_.c \ |
| 440 | $(OBJDIR)/printf_.c \ |
| 441 | $(OBJDIR)/rebuild_.c \ |
| 442 | $(OBJDIR)/regexp_.c \ |
| 443 | $(OBJDIR)/report_.c \ |
| 444 | $(OBJDIR)/rss_.c \ |
| 445 | $(OBJDIR)/schema_.c \ |
| 446 | $(OBJDIR)/search_.c \ |
| 447 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | |
| 458 | $(OBJDIR)/th_main_.c \ |
| 459 | $(OBJDIR)/timeline_.c \ |
| 460 | $(OBJDIR)/tkt_.c \ |
| 461 | $(OBJDIR)/tktsetup_.c \ |
| 462 | $(OBJDIR)/undo_.c \ |
| 463 | $(OBJDIR)/unicode_.c \ |
| 464 | $(OBJDIR)/update_.c \ |
| 465 | $(OBJDIR)/url_.c \ |
| 466 | $(OBJDIR)/user_.c \ |
| 467 | $(OBJDIR)/utf8_.c \ |
| 468 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | |
| 543 | $(OBJDIR)/pivot.o \ |
| 544 | $(OBJDIR)/popen.o \ |
| 545 | $(OBJDIR)/pqueue.o \ |
| 546 | $(OBJDIR)/printf.o \ |
| 547 | $(OBJDIR)/rebuild.o \ |
| 548 | $(OBJDIR)/regexp.o \ |
| 549 | $(OBJDIR)/report.o \ |
| 550 | $(OBJDIR)/rss.o \ |
| 551 | $(OBJDIR)/schema.o \ |
| 552 | $(OBJDIR)/search.o \ |
| 553 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | |
| 564 | $(OBJDIR)/th_main.o \ |
| 565 | $(OBJDIR)/timeline.o \ |
| 566 | $(OBJDIR)/tkt.o \ |
| 567 | $(OBJDIR)/tktsetup.o \ |
| 568 | $(OBJDIR)/undo.o \ |
| 569 | $(OBJDIR)/unicode.o \ |
| 570 | $(OBJDIR)/update.o \ |
| 571 | $(OBJDIR)/url.o \ |
| 572 | $(OBJDIR)/user.o \ |
| 573 | $(OBJDIR)/utf8.o \ |
| 574 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | |
| 762 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 763 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 764 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 765 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 766 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 767 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 768 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 769 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 770 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 771 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 772 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | |
| 783 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 784 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 785 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 786 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 787 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 788 | $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \ |
| 789 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 790 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 791 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 792 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 793 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | |
| 1357 | |
| 1358 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1359 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1360 | |
| 1361 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1362 | |
| 1363 | $(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate |
| 1364 | $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c |
| 1365 | |
| 1366 | $(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h |
| 1367 | $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c |
| 1368 | |
| 1369 | $(OBJDIR)/regexp.h: $(OBJDIR)/headers |
| 1370 | |
| 1371 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1372 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1373 | |
| 1374 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | |
| 1525 | |
| 1526 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1527 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1528 | |
| 1529 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1530 | |
| 1531 | $(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate |
| 1532 | $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c |
| 1533 | |
| 1534 | $(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h |
| 1535 | $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c |
| 1536 | |
| 1537 | $(OBJDIR)/unicode.h: $(OBJDIR)/headers |
| 1538 | |
| 1539 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1540 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1541 | |
| 1542 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1543 |
+25
-1
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -73,11 +73,11 @@ | ||
| 73 | 73 | |
| 74 | 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | 75 | # be enabled by default. |
| 76 | 76 | # |
| 77 | 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | -ifeq ($(PREFIX),) | |
| 78 | +ifeq (,$(findstring w64-mingw32,$(PREFIX))) | |
| 79 | 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | 80 | endif |
| 81 | 81 | endif |
| 82 | 82 | |
| 83 | 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | ||
| 331 | 331 | $(SRCDIR)/pivot.c \ |
| 332 | 332 | $(SRCDIR)/popen.c \ |
| 333 | 333 | $(SRCDIR)/pqueue.c \ |
| 334 | 334 | $(SRCDIR)/printf.c \ |
| 335 | 335 | $(SRCDIR)/rebuild.c \ |
| 336 | + $(SRCDIR)/regexp.c \ | |
| 336 | 337 | $(SRCDIR)/report.c \ |
| 337 | 338 | $(SRCDIR)/rss.c \ |
| 338 | 339 | $(SRCDIR)/schema.c \ |
| 339 | 340 | $(SRCDIR)/search.c \ |
| 340 | 341 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | ||
| 351 | 352 | $(SRCDIR)/th_main.c \ |
| 352 | 353 | $(SRCDIR)/timeline.c \ |
| 353 | 354 | $(SRCDIR)/tkt.c \ |
| 354 | 355 | $(SRCDIR)/tktsetup.c \ |
| 355 | 356 | $(SRCDIR)/undo.c \ |
| 357 | + $(SRCDIR)/unicode.c \ | |
| 356 | 358 | $(SRCDIR)/update.c \ |
| 357 | 359 | $(SRCDIR)/url.c \ |
| 358 | 360 | $(SRCDIR)/user.c \ |
| 359 | 361 | $(SRCDIR)/utf8.c \ |
| 360 | 362 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | ||
| 435 | 437 | $(OBJDIR)/pivot_.c \ |
| 436 | 438 | $(OBJDIR)/popen_.c \ |
| 437 | 439 | $(OBJDIR)/pqueue_.c \ |
| 438 | 440 | $(OBJDIR)/printf_.c \ |
| 439 | 441 | $(OBJDIR)/rebuild_.c \ |
| 442 | + $(OBJDIR)/regexp_.c \ | |
| 440 | 443 | $(OBJDIR)/report_.c \ |
| 441 | 444 | $(OBJDIR)/rss_.c \ |
| 442 | 445 | $(OBJDIR)/schema_.c \ |
| 443 | 446 | $(OBJDIR)/search_.c \ |
| 444 | 447 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | ||
| 455 | 458 | $(OBJDIR)/th_main_.c \ |
| 456 | 459 | $(OBJDIR)/timeline_.c \ |
| 457 | 460 | $(OBJDIR)/tkt_.c \ |
| 458 | 461 | $(OBJDIR)/tktsetup_.c \ |
| 459 | 462 | $(OBJDIR)/undo_.c \ |
| 463 | + $(OBJDIR)/unicode_.c \ | |
| 460 | 464 | $(OBJDIR)/update_.c \ |
| 461 | 465 | $(OBJDIR)/url_.c \ |
| 462 | 466 | $(OBJDIR)/user_.c \ |
| 463 | 467 | $(OBJDIR)/utf8_.c \ |
| 464 | 468 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | ||
| 539 | 543 | $(OBJDIR)/pivot.o \ |
| 540 | 544 | $(OBJDIR)/popen.o \ |
| 541 | 545 | $(OBJDIR)/pqueue.o \ |
| 542 | 546 | $(OBJDIR)/printf.o \ |
| 543 | 547 | $(OBJDIR)/rebuild.o \ |
| 548 | + $(OBJDIR)/regexp.o \ | |
| 544 | 549 | $(OBJDIR)/report.o \ |
| 545 | 550 | $(OBJDIR)/rss.o \ |
| 546 | 551 | $(OBJDIR)/schema.o \ |
| 547 | 552 | $(OBJDIR)/search.o \ |
| 548 | 553 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | ||
| 559 | 564 | $(OBJDIR)/th_main.o \ |
| 560 | 565 | $(OBJDIR)/timeline.o \ |
| 561 | 566 | $(OBJDIR)/tkt.o \ |
| 562 | 567 | $(OBJDIR)/tktsetup.o \ |
| 563 | 568 | $(OBJDIR)/undo.o \ |
| 569 | + $(OBJDIR)/unicode.o \ | |
| 564 | 570 | $(OBJDIR)/update.o \ |
| 565 | 571 | $(OBJDIR)/url.o \ |
| 566 | 572 | $(OBJDIR)/user.o \ |
| 567 | 573 | $(OBJDIR)/utf8.o \ |
| 568 | 574 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | ||
| 756 | 762 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 757 | 763 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 758 | 764 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 759 | 765 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 760 | 766 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 767 | + $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ | |
| 761 | 768 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 762 | 769 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 763 | 770 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 764 | 771 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 765 | 772 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | ||
| 776 | 783 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 777 | 784 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 778 | 785 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 779 | 786 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 780 | 787 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 788 | + $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \ | |
| 781 | 789 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 782 | 790 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 783 | 791 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 784 | 792 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 785 | 793 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | ||
| 1349 | 1357 | |
| 1350 | 1358 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1351 | 1359 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1352 | 1360 | |
| 1353 | 1361 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1362 | + | |
| 1363 | +$(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate | |
| 1364 | + $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c | |
| 1365 | + | |
| 1366 | +$(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h | |
| 1367 | + $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c | |
| 1368 | + | |
| 1369 | +$(OBJDIR)/regexp.h: $(OBJDIR)/headers | |
| 1354 | 1370 | |
| 1355 | 1371 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1356 | 1372 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1357 | 1373 | |
| 1358 | 1374 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | ||
| 1509 | 1525 | |
| 1510 | 1526 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1511 | 1527 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1512 | 1528 | |
| 1513 | 1529 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1530 | + | |
| 1531 | +$(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate | |
| 1532 | + $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c | |
| 1533 | + | |
| 1534 | +$(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h | |
| 1535 | + $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c | |
| 1536 | + | |
| 1537 | +$(OBJDIR)/unicode.h: $(OBJDIR)/headers | |
| 1514 | 1538 | |
| 1515 | 1539 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1516 | 1540 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1517 | 1541 | |
| 1518 | 1542 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1519 | 1543 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -73,11 +73,11 @@ | |
| 73 | |
| 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | # be enabled by default. |
| 76 | # |
| 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | ifeq ($(PREFIX),) |
| 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | endif |
| 81 | endif |
| 82 | |
| 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | |
| 331 | $(SRCDIR)/pivot.c \ |
| 332 | $(SRCDIR)/popen.c \ |
| 333 | $(SRCDIR)/pqueue.c \ |
| 334 | $(SRCDIR)/printf.c \ |
| 335 | $(SRCDIR)/rebuild.c \ |
| 336 | $(SRCDIR)/report.c \ |
| 337 | $(SRCDIR)/rss.c \ |
| 338 | $(SRCDIR)/schema.c \ |
| 339 | $(SRCDIR)/search.c \ |
| 340 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | |
| 351 | $(SRCDIR)/th_main.c \ |
| 352 | $(SRCDIR)/timeline.c \ |
| 353 | $(SRCDIR)/tkt.c \ |
| 354 | $(SRCDIR)/tktsetup.c \ |
| 355 | $(SRCDIR)/undo.c \ |
| 356 | $(SRCDIR)/update.c \ |
| 357 | $(SRCDIR)/url.c \ |
| 358 | $(SRCDIR)/user.c \ |
| 359 | $(SRCDIR)/utf8.c \ |
| 360 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | |
| 435 | $(OBJDIR)/pivot_.c \ |
| 436 | $(OBJDIR)/popen_.c \ |
| 437 | $(OBJDIR)/pqueue_.c \ |
| 438 | $(OBJDIR)/printf_.c \ |
| 439 | $(OBJDIR)/rebuild_.c \ |
| 440 | $(OBJDIR)/report_.c \ |
| 441 | $(OBJDIR)/rss_.c \ |
| 442 | $(OBJDIR)/schema_.c \ |
| 443 | $(OBJDIR)/search_.c \ |
| 444 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | |
| 455 | $(OBJDIR)/th_main_.c \ |
| 456 | $(OBJDIR)/timeline_.c \ |
| 457 | $(OBJDIR)/tkt_.c \ |
| 458 | $(OBJDIR)/tktsetup_.c \ |
| 459 | $(OBJDIR)/undo_.c \ |
| 460 | $(OBJDIR)/update_.c \ |
| 461 | $(OBJDIR)/url_.c \ |
| 462 | $(OBJDIR)/user_.c \ |
| 463 | $(OBJDIR)/utf8_.c \ |
| 464 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | |
| 539 | $(OBJDIR)/pivot.o \ |
| 540 | $(OBJDIR)/popen.o \ |
| 541 | $(OBJDIR)/pqueue.o \ |
| 542 | $(OBJDIR)/printf.o \ |
| 543 | $(OBJDIR)/rebuild.o \ |
| 544 | $(OBJDIR)/report.o \ |
| 545 | $(OBJDIR)/rss.o \ |
| 546 | $(OBJDIR)/schema.o \ |
| 547 | $(OBJDIR)/search.o \ |
| 548 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | |
| 559 | $(OBJDIR)/th_main.o \ |
| 560 | $(OBJDIR)/timeline.o \ |
| 561 | $(OBJDIR)/tkt.o \ |
| 562 | $(OBJDIR)/tktsetup.o \ |
| 563 | $(OBJDIR)/undo.o \ |
| 564 | $(OBJDIR)/update.o \ |
| 565 | $(OBJDIR)/url.o \ |
| 566 | $(OBJDIR)/user.o \ |
| 567 | $(OBJDIR)/utf8.o \ |
| 568 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | |
| 756 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 757 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 758 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 759 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 760 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 761 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 762 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 763 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 764 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 765 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | |
| 776 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 777 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 778 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 779 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 780 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 781 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 782 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 783 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 784 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 785 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | |
| 1349 | |
| 1350 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1351 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1352 | |
| 1353 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1354 | |
| 1355 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1356 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1357 | |
| 1358 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | |
| 1509 | |
| 1510 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1511 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1512 | |
| 1513 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1514 | |
| 1515 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1516 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1517 | |
| 1518 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1519 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -73,11 +73,11 @@ | |
| 73 | |
| 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | # be enabled by default. |
| 76 | # |
| 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | endif |
| 81 | endif |
| 82 | |
| 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | |
| 331 | $(SRCDIR)/pivot.c \ |
| 332 | $(SRCDIR)/popen.c \ |
| 333 | $(SRCDIR)/pqueue.c \ |
| 334 | $(SRCDIR)/printf.c \ |
| 335 | $(SRCDIR)/rebuild.c \ |
| 336 | $(SRCDIR)/regexp.c \ |
| 337 | $(SRCDIR)/report.c \ |
| 338 | $(SRCDIR)/rss.c \ |
| 339 | $(SRCDIR)/schema.c \ |
| 340 | $(SRCDIR)/search.c \ |
| 341 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | |
| 352 | $(SRCDIR)/th_main.c \ |
| 353 | $(SRCDIR)/timeline.c \ |
| 354 | $(SRCDIR)/tkt.c \ |
| 355 | $(SRCDIR)/tktsetup.c \ |
| 356 | $(SRCDIR)/undo.c \ |
| 357 | $(SRCDIR)/unicode.c \ |
| 358 | $(SRCDIR)/update.c \ |
| 359 | $(SRCDIR)/url.c \ |
| 360 | $(SRCDIR)/user.c \ |
| 361 | $(SRCDIR)/utf8.c \ |
| 362 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | |
| 437 | $(OBJDIR)/pivot_.c \ |
| 438 | $(OBJDIR)/popen_.c \ |
| 439 | $(OBJDIR)/pqueue_.c \ |
| 440 | $(OBJDIR)/printf_.c \ |
| 441 | $(OBJDIR)/rebuild_.c \ |
| 442 | $(OBJDIR)/regexp_.c \ |
| 443 | $(OBJDIR)/report_.c \ |
| 444 | $(OBJDIR)/rss_.c \ |
| 445 | $(OBJDIR)/schema_.c \ |
| 446 | $(OBJDIR)/search_.c \ |
| 447 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | |
| 458 | $(OBJDIR)/th_main_.c \ |
| 459 | $(OBJDIR)/timeline_.c \ |
| 460 | $(OBJDIR)/tkt_.c \ |
| 461 | $(OBJDIR)/tktsetup_.c \ |
| 462 | $(OBJDIR)/undo_.c \ |
| 463 | $(OBJDIR)/unicode_.c \ |
| 464 | $(OBJDIR)/update_.c \ |
| 465 | $(OBJDIR)/url_.c \ |
| 466 | $(OBJDIR)/user_.c \ |
| 467 | $(OBJDIR)/utf8_.c \ |
| 468 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | |
| 543 | $(OBJDIR)/pivot.o \ |
| 544 | $(OBJDIR)/popen.o \ |
| 545 | $(OBJDIR)/pqueue.o \ |
| 546 | $(OBJDIR)/printf.o \ |
| 547 | $(OBJDIR)/rebuild.o \ |
| 548 | $(OBJDIR)/regexp.o \ |
| 549 | $(OBJDIR)/report.o \ |
| 550 | $(OBJDIR)/rss.o \ |
| 551 | $(OBJDIR)/schema.o \ |
| 552 | $(OBJDIR)/search.o \ |
| 553 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | |
| 564 | $(OBJDIR)/th_main.o \ |
| 565 | $(OBJDIR)/timeline.o \ |
| 566 | $(OBJDIR)/tkt.o \ |
| 567 | $(OBJDIR)/tktsetup.o \ |
| 568 | $(OBJDIR)/undo.o \ |
| 569 | $(OBJDIR)/unicode.o \ |
| 570 | $(OBJDIR)/update.o \ |
| 571 | $(OBJDIR)/url.o \ |
| 572 | $(OBJDIR)/user.o \ |
| 573 | $(OBJDIR)/utf8.o \ |
| 574 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | |
| 762 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 763 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 764 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 765 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 766 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 767 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 768 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 769 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 770 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 771 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 772 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | |
| 783 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 784 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 785 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 786 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 787 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 788 | $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \ |
| 789 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 790 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 791 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 792 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 793 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | |
| 1357 | |
| 1358 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1359 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1360 | |
| 1361 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1362 | |
| 1363 | $(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate |
| 1364 | $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c |
| 1365 | |
| 1366 | $(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h |
| 1367 | $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c |
| 1368 | |
| 1369 | $(OBJDIR)/regexp.h: $(OBJDIR)/headers |
| 1370 | |
| 1371 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1372 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1373 | |
| 1374 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | |
| 1525 | |
| 1526 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1527 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1528 | |
| 1529 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1530 | |
| 1531 | $(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate |
| 1532 | $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c |
| 1533 | |
| 1534 | $(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h |
| 1535 | $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c |
| 1536 | |
| 1537 | $(OBJDIR)/unicode.h: $(OBJDIR)/headers |
| 1538 | |
| 1539 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1540 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1541 | |
| 1542 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1543 |
+25
-1
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -73,11 +73,11 @@ | ||
| 73 | 73 | |
| 74 | 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | 75 | # be enabled by default. |
| 76 | 76 | # |
| 77 | 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | -ifeq ($(PREFIX),) | |
| 78 | +ifeq (,$(findstring w64-mingw32,$(PREFIX))) | |
| 79 | 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | 80 | endif |
| 81 | 81 | endif |
| 82 | 82 | |
| 83 | 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | ||
| 331 | 331 | $(SRCDIR)/pivot.c \ |
| 332 | 332 | $(SRCDIR)/popen.c \ |
| 333 | 333 | $(SRCDIR)/pqueue.c \ |
| 334 | 334 | $(SRCDIR)/printf.c \ |
| 335 | 335 | $(SRCDIR)/rebuild.c \ |
| 336 | + $(SRCDIR)/regexp.c \ | |
| 336 | 337 | $(SRCDIR)/report.c \ |
| 337 | 338 | $(SRCDIR)/rss.c \ |
| 338 | 339 | $(SRCDIR)/schema.c \ |
| 339 | 340 | $(SRCDIR)/search.c \ |
| 340 | 341 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | ||
| 351 | 352 | $(SRCDIR)/th_main.c \ |
| 352 | 353 | $(SRCDIR)/timeline.c \ |
| 353 | 354 | $(SRCDIR)/tkt.c \ |
| 354 | 355 | $(SRCDIR)/tktsetup.c \ |
| 355 | 356 | $(SRCDIR)/undo.c \ |
| 357 | + $(SRCDIR)/unicode.c \ | |
| 356 | 358 | $(SRCDIR)/update.c \ |
| 357 | 359 | $(SRCDIR)/url.c \ |
| 358 | 360 | $(SRCDIR)/user.c \ |
| 359 | 361 | $(SRCDIR)/utf8.c \ |
| 360 | 362 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | ||
| 435 | 437 | $(OBJDIR)/pivot_.c \ |
| 436 | 438 | $(OBJDIR)/popen_.c \ |
| 437 | 439 | $(OBJDIR)/pqueue_.c \ |
| 438 | 440 | $(OBJDIR)/printf_.c \ |
| 439 | 441 | $(OBJDIR)/rebuild_.c \ |
| 442 | + $(OBJDIR)/regexp_.c \ | |
| 440 | 443 | $(OBJDIR)/report_.c \ |
| 441 | 444 | $(OBJDIR)/rss_.c \ |
| 442 | 445 | $(OBJDIR)/schema_.c \ |
| 443 | 446 | $(OBJDIR)/search_.c \ |
| 444 | 447 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | ||
| 455 | 458 | $(OBJDIR)/th_main_.c \ |
| 456 | 459 | $(OBJDIR)/timeline_.c \ |
| 457 | 460 | $(OBJDIR)/tkt_.c \ |
| 458 | 461 | $(OBJDIR)/tktsetup_.c \ |
| 459 | 462 | $(OBJDIR)/undo_.c \ |
| 463 | + $(OBJDIR)/unicode_.c \ | |
| 460 | 464 | $(OBJDIR)/update_.c \ |
| 461 | 465 | $(OBJDIR)/url_.c \ |
| 462 | 466 | $(OBJDIR)/user_.c \ |
| 463 | 467 | $(OBJDIR)/utf8_.c \ |
| 464 | 468 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | ||
| 539 | 543 | $(OBJDIR)/pivot.o \ |
| 540 | 544 | $(OBJDIR)/popen.o \ |
| 541 | 545 | $(OBJDIR)/pqueue.o \ |
| 542 | 546 | $(OBJDIR)/printf.o \ |
| 543 | 547 | $(OBJDIR)/rebuild.o \ |
| 548 | + $(OBJDIR)/regexp.o \ | |
| 544 | 549 | $(OBJDIR)/report.o \ |
| 545 | 550 | $(OBJDIR)/rss.o \ |
| 546 | 551 | $(OBJDIR)/schema.o \ |
| 547 | 552 | $(OBJDIR)/search.o \ |
| 548 | 553 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | ||
| 559 | 564 | $(OBJDIR)/th_main.o \ |
| 560 | 565 | $(OBJDIR)/timeline.o \ |
| 561 | 566 | $(OBJDIR)/tkt.o \ |
| 562 | 567 | $(OBJDIR)/tktsetup.o \ |
| 563 | 568 | $(OBJDIR)/undo.o \ |
| 569 | + $(OBJDIR)/unicode.o \ | |
| 564 | 570 | $(OBJDIR)/update.o \ |
| 565 | 571 | $(OBJDIR)/url.o \ |
| 566 | 572 | $(OBJDIR)/user.o \ |
| 567 | 573 | $(OBJDIR)/utf8.o \ |
| 568 | 574 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | ||
| 756 | 762 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 757 | 763 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 758 | 764 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 759 | 765 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 760 | 766 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 767 | + $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ | |
| 761 | 768 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 762 | 769 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 763 | 770 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 764 | 771 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 765 | 772 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | ||
| 776 | 783 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 777 | 784 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 778 | 785 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 779 | 786 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 780 | 787 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 788 | + $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \ | |
| 781 | 789 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 782 | 790 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 783 | 791 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 784 | 792 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 785 | 793 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | ||
| 1349 | 1357 | |
| 1350 | 1358 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1351 | 1359 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1352 | 1360 | |
| 1353 | 1361 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1362 | + | |
| 1363 | +$(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate | |
| 1364 | + $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c | |
| 1365 | + | |
| 1366 | +$(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h | |
| 1367 | + $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c | |
| 1368 | + | |
| 1369 | +$(OBJDIR)/regexp.h: $(OBJDIR)/headers | |
| 1354 | 1370 | |
| 1355 | 1371 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1356 | 1372 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1357 | 1373 | |
| 1358 | 1374 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | ||
| 1509 | 1525 | |
| 1510 | 1526 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1511 | 1527 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1512 | 1528 | |
| 1513 | 1529 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1530 | + | |
| 1531 | +$(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate | |
| 1532 | + $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c | |
| 1533 | + | |
| 1534 | +$(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h | |
| 1535 | + $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c | |
| 1536 | + | |
| 1537 | +$(OBJDIR)/unicode.h: $(OBJDIR)/headers | |
| 1514 | 1538 | |
| 1515 | 1539 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1516 | 1540 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1517 | 1541 | |
| 1518 | 1542 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1519 | 1543 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -73,11 +73,11 @@ | |
| 73 | |
| 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | # be enabled by default. |
| 76 | # |
| 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | ifeq ($(PREFIX),) |
| 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | endif |
| 81 | endif |
| 82 | |
| 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | |
| 331 | $(SRCDIR)/pivot.c \ |
| 332 | $(SRCDIR)/popen.c \ |
| 333 | $(SRCDIR)/pqueue.c \ |
| 334 | $(SRCDIR)/printf.c \ |
| 335 | $(SRCDIR)/rebuild.c \ |
| 336 | $(SRCDIR)/report.c \ |
| 337 | $(SRCDIR)/rss.c \ |
| 338 | $(SRCDIR)/schema.c \ |
| 339 | $(SRCDIR)/search.c \ |
| 340 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | |
| 351 | $(SRCDIR)/th_main.c \ |
| 352 | $(SRCDIR)/timeline.c \ |
| 353 | $(SRCDIR)/tkt.c \ |
| 354 | $(SRCDIR)/tktsetup.c \ |
| 355 | $(SRCDIR)/undo.c \ |
| 356 | $(SRCDIR)/update.c \ |
| 357 | $(SRCDIR)/url.c \ |
| 358 | $(SRCDIR)/user.c \ |
| 359 | $(SRCDIR)/utf8.c \ |
| 360 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | |
| 435 | $(OBJDIR)/pivot_.c \ |
| 436 | $(OBJDIR)/popen_.c \ |
| 437 | $(OBJDIR)/pqueue_.c \ |
| 438 | $(OBJDIR)/printf_.c \ |
| 439 | $(OBJDIR)/rebuild_.c \ |
| 440 | $(OBJDIR)/report_.c \ |
| 441 | $(OBJDIR)/rss_.c \ |
| 442 | $(OBJDIR)/schema_.c \ |
| 443 | $(OBJDIR)/search_.c \ |
| 444 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | |
| 455 | $(OBJDIR)/th_main_.c \ |
| 456 | $(OBJDIR)/timeline_.c \ |
| 457 | $(OBJDIR)/tkt_.c \ |
| 458 | $(OBJDIR)/tktsetup_.c \ |
| 459 | $(OBJDIR)/undo_.c \ |
| 460 | $(OBJDIR)/update_.c \ |
| 461 | $(OBJDIR)/url_.c \ |
| 462 | $(OBJDIR)/user_.c \ |
| 463 | $(OBJDIR)/utf8_.c \ |
| 464 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | |
| 539 | $(OBJDIR)/pivot.o \ |
| 540 | $(OBJDIR)/popen.o \ |
| 541 | $(OBJDIR)/pqueue.o \ |
| 542 | $(OBJDIR)/printf.o \ |
| 543 | $(OBJDIR)/rebuild.o \ |
| 544 | $(OBJDIR)/report.o \ |
| 545 | $(OBJDIR)/rss.o \ |
| 546 | $(OBJDIR)/schema.o \ |
| 547 | $(OBJDIR)/search.o \ |
| 548 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | |
| 559 | $(OBJDIR)/th_main.o \ |
| 560 | $(OBJDIR)/timeline.o \ |
| 561 | $(OBJDIR)/tkt.o \ |
| 562 | $(OBJDIR)/tktsetup.o \ |
| 563 | $(OBJDIR)/undo.o \ |
| 564 | $(OBJDIR)/update.o \ |
| 565 | $(OBJDIR)/url.o \ |
| 566 | $(OBJDIR)/user.o \ |
| 567 | $(OBJDIR)/utf8.o \ |
| 568 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | |
| 756 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 757 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 758 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 759 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 760 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 761 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 762 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 763 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 764 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 765 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | |
| 776 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 777 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 778 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 779 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 780 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 781 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 782 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 783 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 784 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 785 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | |
| 1349 | |
| 1350 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1351 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1352 | |
| 1353 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1354 | |
| 1355 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1356 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1357 | |
| 1358 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | |
| 1509 | |
| 1510 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1511 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1512 | |
| 1513 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1514 | |
| 1515 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1516 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1517 | |
| 1518 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1519 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -73,11 +73,11 @@ | |
| 73 | |
| 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | # be enabled by default. |
| 76 | # |
| 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | endif |
| 81 | endif |
| 82 | |
| 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | |
| 331 | $(SRCDIR)/pivot.c \ |
| 332 | $(SRCDIR)/popen.c \ |
| 333 | $(SRCDIR)/pqueue.c \ |
| 334 | $(SRCDIR)/printf.c \ |
| 335 | $(SRCDIR)/rebuild.c \ |
| 336 | $(SRCDIR)/regexp.c \ |
| 337 | $(SRCDIR)/report.c \ |
| 338 | $(SRCDIR)/rss.c \ |
| 339 | $(SRCDIR)/schema.c \ |
| 340 | $(SRCDIR)/search.c \ |
| 341 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | |
| 352 | $(SRCDIR)/th_main.c \ |
| 353 | $(SRCDIR)/timeline.c \ |
| 354 | $(SRCDIR)/tkt.c \ |
| 355 | $(SRCDIR)/tktsetup.c \ |
| 356 | $(SRCDIR)/undo.c \ |
| 357 | $(SRCDIR)/unicode.c \ |
| 358 | $(SRCDIR)/update.c \ |
| 359 | $(SRCDIR)/url.c \ |
| 360 | $(SRCDIR)/user.c \ |
| 361 | $(SRCDIR)/utf8.c \ |
| 362 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | |
| 437 | $(OBJDIR)/pivot_.c \ |
| 438 | $(OBJDIR)/popen_.c \ |
| 439 | $(OBJDIR)/pqueue_.c \ |
| 440 | $(OBJDIR)/printf_.c \ |
| 441 | $(OBJDIR)/rebuild_.c \ |
| 442 | $(OBJDIR)/regexp_.c \ |
| 443 | $(OBJDIR)/report_.c \ |
| 444 | $(OBJDIR)/rss_.c \ |
| 445 | $(OBJDIR)/schema_.c \ |
| 446 | $(OBJDIR)/search_.c \ |
| 447 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | |
| 458 | $(OBJDIR)/th_main_.c \ |
| 459 | $(OBJDIR)/timeline_.c \ |
| 460 | $(OBJDIR)/tkt_.c \ |
| 461 | $(OBJDIR)/tktsetup_.c \ |
| 462 | $(OBJDIR)/undo_.c \ |
| 463 | $(OBJDIR)/unicode_.c \ |
| 464 | $(OBJDIR)/update_.c \ |
| 465 | $(OBJDIR)/url_.c \ |
| 466 | $(OBJDIR)/user_.c \ |
| 467 | $(OBJDIR)/utf8_.c \ |
| 468 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | |
| 543 | $(OBJDIR)/pivot.o \ |
| 544 | $(OBJDIR)/popen.o \ |
| 545 | $(OBJDIR)/pqueue.o \ |
| 546 | $(OBJDIR)/printf.o \ |
| 547 | $(OBJDIR)/rebuild.o \ |
| 548 | $(OBJDIR)/regexp.o \ |
| 549 | $(OBJDIR)/report.o \ |
| 550 | $(OBJDIR)/rss.o \ |
| 551 | $(OBJDIR)/schema.o \ |
| 552 | $(OBJDIR)/search.o \ |
| 553 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | |
| 564 | $(OBJDIR)/th_main.o \ |
| 565 | $(OBJDIR)/timeline.o \ |
| 566 | $(OBJDIR)/tkt.o \ |
| 567 | $(OBJDIR)/tktsetup.o \ |
| 568 | $(OBJDIR)/undo.o \ |
| 569 | $(OBJDIR)/unicode.o \ |
| 570 | $(OBJDIR)/update.o \ |
| 571 | $(OBJDIR)/url.o \ |
| 572 | $(OBJDIR)/user.o \ |
| 573 | $(OBJDIR)/utf8.o \ |
| 574 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | |
| 762 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 763 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 764 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 765 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 766 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 767 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 768 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 769 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 770 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 771 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 772 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | |
| 783 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 784 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 785 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 786 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 787 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 788 | $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \ |
| 789 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 790 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 791 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 792 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 793 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | |
| 1357 | |
| 1358 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1359 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1360 | |
| 1361 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1362 | |
| 1363 | $(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate |
| 1364 | $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c |
| 1365 | |
| 1366 | $(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h |
| 1367 | $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c |
| 1368 | |
| 1369 | $(OBJDIR)/regexp.h: $(OBJDIR)/headers |
| 1370 | |
| 1371 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1372 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1373 | |
| 1374 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | |
| 1525 | |
| 1526 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1527 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1528 | |
| 1529 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1530 | |
| 1531 | $(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate |
| 1532 | $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c |
| 1533 | |
| 1534 | $(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h |
| 1535 | $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c |
| 1536 | |
| 1537 | $(OBJDIR)/unicode.h: $(OBJDIR)/headers |
| 1538 | |
| 1539 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1540 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1541 | |
| 1542 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1543 |
+25
-1
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -73,11 +73,11 @@ | ||
| 73 | 73 | |
| 74 | 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | 75 | # be enabled by default. |
| 76 | 76 | # |
| 77 | 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | -ifeq ($(PREFIX),) | |
| 78 | +ifeq (,$(findstring w64-mingw32,$(PREFIX))) | |
| 79 | 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | 80 | endif |
| 81 | 81 | endif |
| 82 | 82 | |
| 83 | 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | ||
| 331 | 331 | $(SRCDIR)/pivot.c \ |
| 332 | 332 | $(SRCDIR)/popen.c \ |
| 333 | 333 | $(SRCDIR)/pqueue.c \ |
| 334 | 334 | $(SRCDIR)/printf.c \ |
| 335 | 335 | $(SRCDIR)/rebuild.c \ |
| 336 | + $(SRCDIR)/regexp.c \ | |
| 336 | 337 | $(SRCDIR)/report.c \ |
| 337 | 338 | $(SRCDIR)/rss.c \ |
| 338 | 339 | $(SRCDIR)/schema.c \ |
| 339 | 340 | $(SRCDIR)/search.c \ |
| 340 | 341 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | ||
| 351 | 352 | $(SRCDIR)/th_main.c \ |
| 352 | 353 | $(SRCDIR)/timeline.c \ |
| 353 | 354 | $(SRCDIR)/tkt.c \ |
| 354 | 355 | $(SRCDIR)/tktsetup.c \ |
| 355 | 356 | $(SRCDIR)/undo.c \ |
| 357 | + $(SRCDIR)/unicode.c \ | |
| 356 | 358 | $(SRCDIR)/update.c \ |
| 357 | 359 | $(SRCDIR)/url.c \ |
| 358 | 360 | $(SRCDIR)/user.c \ |
| 359 | 361 | $(SRCDIR)/utf8.c \ |
| 360 | 362 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | ||
| 435 | 437 | $(OBJDIR)/pivot_.c \ |
| 436 | 438 | $(OBJDIR)/popen_.c \ |
| 437 | 439 | $(OBJDIR)/pqueue_.c \ |
| 438 | 440 | $(OBJDIR)/printf_.c \ |
| 439 | 441 | $(OBJDIR)/rebuild_.c \ |
| 442 | + $(OBJDIR)/regexp_.c \ | |
| 440 | 443 | $(OBJDIR)/report_.c \ |
| 441 | 444 | $(OBJDIR)/rss_.c \ |
| 442 | 445 | $(OBJDIR)/schema_.c \ |
| 443 | 446 | $(OBJDIR)/search_.c \ |
| 444 | 447 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | ||
| 455 | 458 | $(OBJDIR)/th_main_.c \ |
| 456 | 459 | $(OBJDIR)/timeline_.c \ |
| 457 | 460 | $(OBJDIR)/tkt_.c \ |
| 458 | 461 | $(OBJDIR)/tktsetup_.c \ |
| 459 | 462 | $(OBJDIR)/undo_.c \ |
| 463 | + $(OBJDIR)/unicode_.c \ | |
| 460 | 464 | $(OBJDIR)/update_.c \ |
| 461 | 465 | $(OBJDIR)/url_.c \ |
| 462 | 466 | $(OBJDIR)/user_.c \ |
| 463 | 467 | $(OBJDIR)/utf8_.c \ |
| 464 | 468 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | ||
| 539 | 543 | $(OBJDIR)/pivot.o \ |
| 540 | 544 | $(OBJDIR)/popen.o \ |
| 541 | 545 | $(OBJDIR)/pqueue.o \ |
| 542 | 546 | $(OBJDIR)/printf.o \ |
| 543 | 547 | $(OBJDIR)/rebuild.o \ |
| 548 | + $(OBJDIR)/regexp.o \ | |
| 544 | 549 | $(OBJDIR)/report.o \ |
| 545 | 550 | $(OBJDIR)/rss.o \ |
| 546 | 551 | $(OBJDIR)/schema.o \ |
| 547 | 552 | $(OBJDIR)/search.o \ |
| 548 | 553 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | ||
| 559 | 564 | $(OBJDIR)/th_main.o \ |
| 560 | 565 | $(OBJDIR)/timeline.o \ |
| 561 | 566 | $(OBJDIR)/tkt.o \ |
| 562 | 567 | $(OBJDIR)/tktsetup.o \ |
| 563 | 568 | $(OBJDIR)/undo.o \ |
| 569 | + $(OBJDIR)/unicode.o \ | |
| 564 | 570 | $(OBJDIR)/update.o \ |
| 565 | 571 | $(OBJDIR)/url.o \ |
| 566 | 572 | $(OBJDIR)/user.o \ |
| 567 | 573 | $(OBJDIR)/utf8.o \ |
| 568 | 574 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | ||
| 756 | 762 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 757 | 763 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 758 | 764 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 759 | 765 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 760 | 766 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 767 | + $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ | |
| 761 | 768 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 762 | 769 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 763 | 770 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 764 | 771 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 765 | 772 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | ||
| 776 | 783 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 777 | 784 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 778 | 785 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 779 | 786 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 780 | 787 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 788 | + $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \ | |
| 781 | 789 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 782 | 790 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 783 | 791 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 784 | 792 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 785 | 793 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | ||
| 1349 | 1357 | |
| 1350 | 1358 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1351 | 1359 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1352 | 1360 | |
| 1353 | 1361 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1362 | + | |
| 1363 | +$(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate | |
| 1364 | + $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c | |
| 1365 | + | |
| 1366 | +$(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h | |
| 1367 | + $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c | |
| 1368 | + | |
| 1369 | +$(OBJDIR)/regexp.h: $(OBJDIR)/headers | |
| 1354 | 1370 | |
| 1355 | 1371 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1356 | 1372 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1357 | 1373 | |
| 1358 | 1374 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | ||
| 1509 | 1525 | |
| 1510 | 1526 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1511 | 1527 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1512 | 1528 | |
| 1513 | 1529 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1530 | + | |
| 1531 | +$(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate | |
| 1532 | + $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c | |
| 1533 | + | |
| 1534 | +$(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h | |
| 1535 | + $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c | |
| 1536 | + | |
| 1537 | +$(OBJDIR)/unicode.h: $(OBJDIR)/headers | |
| 1514 | 1538 | |
| 1515 | 1539 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1516 | 1540 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1517 | 1541 | |
| 1518 | 1542 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1519 | 1543 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -73,11 +73,11 @@ | |
| 73 | |
| 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | # be enabled by default. |
| 76 | # |
| 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | ifeq ($(PREFIX),) |
| 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | endif |
| 81 | endif |
| 82 | |
| 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | |
| 331 | $(SRCDIR)/pivot.c \ |
| 332 | $(SRCDIR)/popen.c \ |
| 333 | $(SRCDIR)/pqueue.c \ |
| 334 | $(SRCDIR)/printf.c \ |
| 335 | $(SRCDIR)/rebuild.c \ |
| 336 | $(SRCDIR)/report.c \ |
| 337 | $(SRCDIR)/rss.c \ |
| 338 | $(SRCDIR)/schema.c \ |
| 339 | $(SRCDIR)/search.c \ |
| 340 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | |
| 351 | $(SRCDIR)/th_main.c \ |
| 352 | $(SRCDIR)/timeline.c \ |
| 353 | $(SRCDIR)/tkt.c \ |
| 354 | $(SRCDIR)/tktsetup.c \ |
| 355 | $(SRCDIR)/undo.c \ |
| 356 | $(SRCDIR)/update.c \ |
| 357 | $(SRCDIR)/url.c \ |
| 358 | $(SRCDIR)/user.c \ |
| 359 | $(SRCDIR)/utf8.c \ |
| 360 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | |
| 435 | $(OBJDIR)/pivot_.c \ |
| 436 | $(OBJDIR)/popen_.c \ |
| 437 | $(OBJDIR)/pqueue_.c \ |
| 438 | $(OBJDIR)/printf_.c \ |
| 439 | $(OBJDIR)/rebuild_.c \ |
| 440 | $(OBJDIR)/report_.c \ |
| 441 | $(OBJDIR)/rss_.c \ |
| 442 | $(OBJDIR)/schema_.c \ |
| 443 | $(OBJDIR)/search_.c \ |
| 444 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | |
| 455 | $(OBJDIR)/th_main_.c \ |
| 456 | $(OBJDIR)/timeline_.c \ |
| 457 | $(OBJDIR)/tkt_.c \ |
| 458 | $(OBJDIR)/tktsetup_.c \ |
| 459 | $(OBJDIR)/undo_.c \ |
| 460 | $(OBJDIR)/update_.c \ |
| 461 | $(OBJDIR)/url_.c \ |
| 462 | $(OBJDIR)/user_.c \ |
| 463 | $(OBJDIR)/utf8_.c \ |
| 464 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | |
| 539 | $(OBJDIR)/pivot.o \ |
| 540 | $(OBJDIR)/popen.o \ |
| 541 | $(OBJDIR)/pqueue.o \ |
| 542 | $(OBJDIR)/printf.o \ |
| 543 | $(OBJDIR)/rebuild.o \ |
| 544 | $(OBJDIR)/report.o \ |
| 545 | $(OBJDIR)/rss.o \ |
| 546 | $(OBJDIR)/schema.o \ |
| 547 | $(OBJDIR)/search.o \ |
| 548 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | |
| 559 | $(OBJDIR)/th_main.o \ |
| 560 | $(OBJDIR)/timeline.o \ |
| 561 | $(OBJDIR)/tkt.o \ |
| 562 | $(OBJDIR)/tktsetup.o \ |
| 563 | $(OBJDIR)/undo.o \ |
| 564 | $(OBJDIR)/update.o \ |
| 565 | $(OBJDIR)/url.o \ |
| 566 | $(OBJDIR)/user.o \ |
| 567 | $(OBJDIR)/utf8.o \ |
| 568 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | |
| 756 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 757 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 758 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 759 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 760 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 761 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 762 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 763 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 764 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 765 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | |
| 776 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 777 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 778 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 779 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 780 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 781 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 782 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 783 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 784 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 785 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | |
| 1349 | |
| 1350 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1351 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1352 | |
| 1353 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1354 | |
| 1355 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1356 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1357 | |
| 1358 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | |
| 1509 | |
| 1510 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1511 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1512 | |
| 1513 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1514 | |
| 1515 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1516 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1517 | |
| 1518 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1519 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -73,11 +73,11 @@ | |
| 73 | |
| 74 | #### Check if the workaround for the MinGW command line handling needs to |
| 75 | # be enabled by default. |
| 76 | # |
| 77 | ifndef BROKEN_MINGW_CMDLINE |
| 78 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 79 | BROKEN_MINGW_CMDLINE = 1 |
| 80 | endif |
| 81 | endif |
| 82 | |
| 83 | #### The directories where the zlib include and library files are located. |
| @@ -331,10 +331,11 @@ | |
| 331 | $(SRCDIR)/pivot.c \ |
| 332 | $(SRCDIR)/popen.c \ |
| 333 | $(SRCDIR)/pqueue.c \ |
| 334 | $(SRCDIR)/printf.c \ |
| 335 | $(SRCDIR)/rebuild.c \ |
| 336 | $(SRCDIR)/regexp.c \ |
| 337 | $(SRCDIR)/report.c \ |
| 338 | $(SRCDIR)/rss.c \ |
| 339 | $(SRCDIR)/schema.c \ |
| 340 | $(SRCDIR)/search.c \ |
| 341 | $(SRCDIR)/setup.c \ |
| @@ -351,10 +352,11 @@ | |
| 352 | $(SRCDIR)/th_main.c \ |
| 353 | $(SRCDIR)/timeline.c \ |
| 354 | $(SRCDIR)/tkt.c \ |
| 355 | $(SRCDIR)/tktsetup.c \ |
| 356 | $(SRCDIR)/undo.c \ |
| 357 | $(SRCDIR)/unicode.c \ |
| 358 | $(SRCDIR)/update.c \ |
| 359 | $(SRCDIR)/url.c \ |
| 360 | $(SRCDIR)/user.c \ |
| 361 | $(SRCDIR)/utf8.c \ |
| 362 | $(SRCDIR)/verify.c \ |
| @@ -435,10 +437,11 @@ | |
| 437 | $(OBJDIR)/pivot_.c \ |
| 438 | $(OBJDIR)/popen_.c \ |
| 439 | $(OBJDIR)/pqueue_.c \ |
| 440 | $(OBJDIR)/printf_.c \ |
| 441 | $(OBJDIR)/rebuild_.c \ |
| 442 | $(OBJDIR)/regexp_.c \ |
| 443 | $(OBJDIR)/report_.c \ |
| 444 | $(OBJDIR)/rss_.c \ |
| 445 | $(OBJDIR)/schema_.c \ |
| 446 | $(OBJDIR)/search_.c \ |
| 447 | $(OBJDIR)/setup_.c \ |
| @@ -455,10 +458,11 @@ | |
| 458 | $(OBJDIR)/th_main_.c \ |
| 459 | $(OBJDIR)/timeline_.c \ |
| 460 | $(OBJDIR)/tkt_.c \ |
| 461 | $(OBJDIR)/tktsetup_.c \ |
| 462 | $(OBJDIR)/undo_.c \ |
| 463 | $(OBJDIR)/unicode_.c \ |
| 464 | $(OBJDIR)/update_.c \ |
| 465 | $(OBJDIR)/url_.c \ |
| 466 | $(OBJDIR)/user_.c \ |
| 467 | $(OBJDIR)/utf8_.c \ |
| 468 | $(OBJDIR)/verify_.c \ |
| @@ -539,10 +543,11 @@ | |
| 543 | $(OBJDIR)/pivot.o \ |
| 544 | $(OBJDIR)/popen.o \ |
| 545 | $(OBJDIR)/pqueue.o \ |
| 546 | $(OBJDIR)/printf.o \ |
| 547 | $(OBJDIR)/rebuild.o \ |
| 548 | $(OBJDIR)/regexp.o \ |
| 549 | $(OBJDIR)/report.o \ |
| 550 | $(OBJDIR)/rss.o \ |
| 551 | $(OBJDIR)/schema.o \ |
| 552 | $(OBJDIR)/search.o \ |
| 553 | $(OBJDIR)/setup.o \ |
| @@ -559,10 +564,11 @@ | |
| 564 | $(OBJDIR)/th_main.o \ |
| 565 | $(OBJDIR)/timeline.o \ |
| 566 | $(OBJDIR)/tkt.o \ |
| 567 | $(OBJDIR)/tktsetup.o \ |
| 568 | $(OBJDIR)/undo.o \ |
| 569 | $(OBJDIR)/unicode.o \ |
| 570 | $(OBJDIR)/update.o \ |
| 571 | $(OBJDIR)/url.o \ |
| 572 | $(OBJDIR)/user.o \ |
| 573 | $(OBJDIR)/utf8.o \ |
| 574 | $(OBJDIR)/verify.o \ |
| @@ -756,10 +762,11 @@ | |
| 762 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 763 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 764 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 765 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 766 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 767 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 768 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 769 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 770 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 771 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 772 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| @@ -776,10 +783,11 @@ | |
| 783 | $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \ |
| 784 | $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h \ |
| 785 | $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h \ |
| 786 | $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h \ |
| 787 | $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h \ |
| 788 | $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \ |
| 789 | $(OBJDIR)/update_.c:$(OBJDIR)/update.h \ |
| 790 | $(OBJDIR)/url_.c:$(OBJDIR)/url.h \ |
| 791 | $(OBJDIR)/user_.c:$(OBJDIR)/user.h \ |
| 792 | $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \ |
| 793 | $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \ |
| @@ -1349,10 +1357,18 @@ | |
| 1357 | |
| 1358 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| 1359 | $(XTCC) -o $(OBJDIR)/rebuild.o -c $(OBJDIR)/rebuild_.c |
| 1360 | |
| 1361 | $(OBJDIR)/rebuild.h: $(OBJDIR)/headers |
| 1362 | |
| 1363 | $(OBJDIR)/regexp_.c: $(SRCDIR)/regexp.c $(OBJDIR)/translate |
| 1364 | $(TRANSLATE) $(SRCDIR)/regexp.c >$(OBJDIR)/regexp_.c |
| 1365 | |
| 1366 | $(OBJDIR)/regexp.o: $(OBJDIR)/regexp_.c $(OBJDIR)/regexp.h $(SRCDIR)/config.h |
| 1367 | $(XTCC) -o $(OBJDIR)/regexp.o -c $(OBJDIR)/regexp_.c |
| 1368 | |
| 1369 | $(OBJDIR)/regexp.h: $(OBJDIR)/headers |
| 1370 | |
| 1371 | $(OBJDIR)/report_.c: $(SRCDIR)/report.c $(OBJDIR)/translate |
| 1372 | $(TRANSLATE) $(SRCDIR)/report.c >$(OBJDIR)/report_.c |
| 1373 | |
| 1374 | $(OBJDIR)/report.o: $(OBJDIR)/report_.c $(OBJDIR)/report.h $(SRCDIR)/config.h |
| @@ -1509,10 +1525,18 @@ | |
| 1525 | |
| 1526 | $(OBJDIR)/undo.o: $(OBJDIR)/undo_.c $(OBJDIR)/undo.h $(SRCDIR)/config.h |
| 1527 | $(XTCC) -o $(OBJDIR)/undo.o -c $(OBJDIR)/undo_.c |
| 1528 | |
| 1529 | $(OBJDIR)/undo.h: $(OBJDIR)/headers |
| 1530 | |
| 1531 | $(OBJDIR)/unicode_.c: $(SRCDIR)/unicode.c $(OBJDIR)/translate |
| 1532 | $(TRANSLATE) $(SRCDIR)/unicode.c >$(OBJDIR)/unicode_.c |
| 1533 | |
| 1534 | $(OBJDIR)/unicode.o: $(OBJDIR)/unicode_.c $(OBJDIR)/unicode.h $(SRCDIR)/config.h |
| 1535 | $(XTCC) -o $(OBJDIR)/unicode.o -c $(OBJDIR)/unicode_.c |
| 1536 | |
| 1537 | $(OBJDIR)/unicode.h: $(OBJDIR)/headers |
| 1538 | |
| 1539 | $(OBJDIR)/update_.c: $(SRCDIR)/update.c $(OBJDIR)/translate |
| 1540 | $(TRANSLATE) $(SRCDIR)/update.c >$(OBJDIR)/update_.c |
| 1541 | |
| 1542 | $(OBJDIR)/update.o: $(OBJDIR)/update_.c $(OBJDIR)/update.h $(SRCDIR)/config.h |
| 1543 |
+20
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -107,10 +107,11 @@ | ||
| 107 | 107 | pivot_.c \ |
| 108 | 108 | popen_.c \ |
| 109 | 109 | pqueue_.c \ |
| 110 | 110 | printf_.c \ |
| 111 | 111 | rebuild_.c \ |
| 112 | + regexp_.c \ | |
| 112 | 113 | report_.c \ |
| 113 | 114 | rss_.c \ |
| 114 | 115 | schema_.c \ |
| 115 | 116 | search_.c \ |
| 116 | 117 | setup_.c \ |
| @@ -127,10 +128,11 @@ | ||
| 127 | 128 | th_main_.c \ |
| 128 | 129 | timeline_.c \ |
| 129 | 130 | tkt_.c \ |
| 130 | 131 | tktsetup_.c \ |
| 131 | 132 | undo_.c \ |
| 133 | + unicode_.c \ | |
| 132 | 134 | update_.c \ |
| 133 | 135 | url_.c \ |
| 134 | 136 | user_.c \ |
| 135 | 137 | utf8_.c \ |
| 136 | 138 | verify_.c \ |
| @@ -210,10 +212,11 @@ | ||
| 210 | 212 | $(OX)\pivot$O \ |
| 211 | 213 | $(OX)\popen$O \ |
| 212 | 214 | $(OX)\pqueue$O \ |
| 213 | 215 | $(OX)\printf$O \ |
| 214 | 216 | $(OX)\rebuild$O \ |
| 217 | + $(OX)\regexp$O \ | |
| 215 | 218 | $(OX)\report$O \ |
| 216 | 219 | $(OX)\rss$O \ |
| 217 | 220 | $(OX)\schema$O \ |
| 218 | 221 | $(OX)\search$O \ |
| 219 | 222 | $(OX)\setup$O \ |
| @@ -230,10 +233,11 @@ | ||
| 230 | 233 | $(OX)\th_main$O \ |
| 231 | 234 | $(OX)\timeline$O \ |
| 232 | 235 | $(OX)\tkt$O \ |
| 233 | 236 | $(OX)\tktsetup$O \ |
| 234 | 237 | $(OX)\undo$O \ |
| 238 | + $(OX)\unicode$O \ | |
| 235 | 239 | $(OX)\update$O \ |
| 236 | 240 | $(OX)\url$O \ |
| 237 | 241 | $(OX)\user$O \ |
| 238 | 242 | $(OX)\utf8$O \ |
| 239 | 243 | $(OX)\verify$O \ |
| @@ -330,10 +334,11 @@ | ||
| 330 | 334 | echo $(OX)\pivot.obj >> $@ |
| 331 | 335 | echo $(OX)\popen.obj >> $@ |
| 332 | 336 | echo $(OX)\pqueue.obj >> $@ |
| 333 | 337 | echo $(OX)\printf.obj >> $@ |
| 334 | 338 | echo $(OX)\rebuild.obj >> $@ |
| 339 | + echo $(OX)\regexp.obj >> $@ | |
| 335 | 340 | echo $(OX)\report.obj >> $@ |
| 336 | 341 | echo $(OX)\rss.obj >> $@ |
| 337 | 342 | echo $(OX)\schema.obj >> $@ |
| 338 | 343 | echo $(OX)\search.obj >> $@ |
| 339 | 344 | echo $(OX)\setup.obj >> $@ |
| @@ -354,10 +359,11 @@ | ||
| 354 | 359 | echo $(OX)\th_main.obj >> $@ |
| 355 | 360 | echo $(OX)\timeline.obj >> $@ |
| 356 | 361 | echo $(OX)\tkt.obj >> $@ |
| 357 | 362 | echo $(OX)\tktsetup.obj >> $@ |
| 358 | 363 | echo $(OX)\undo.obj >> $@ |
| 364 | + echo $(OX)\unicode.obj >> $@ | |
| 359 | 365 | echo $(OX)\update.obj >> $@ |
| 360 | 366 | echo $(OX)\url.obj >> $@ |
| 361 | 367 | echo $(OX)\user.obj >> $@ |
| 362 | 368 | echo $(OX)\utf8.obj >> $@ |
| 363 | 369 | echo $(OX)\verify.obj >> $@ |
| @@ -853,10 +859,16 @@ | ||
| 853 | 859 | $(OX)\rebuild$O : rebuild_.c rebuild.h |
| 854 | 860 | $(TCC) /Fo$@ -c rebuild_.c |
| 855 | 861 | |
| 856 | 862 | rebuild_.c : $(SRCDIR)\rebuild.c |
| 857 | 863 | translate$E $** > $@ |
| 864 | + | |
| 865 | +$(OX)\regexp$O : regexp_.c regexp.h | |
| 866 | + $(TCC) /Fo$@ -c regexp_.c | |
| 867 | + | |
| 868 | +regexp_.c : $(SRCDIR)\regexp.c | |
| 869 | + translate$E $** > $@ | |
| 858 | 870 | |
| 859 | 871 | $(OX)\report$O : report_.c report.h |
| 860 | 872 | $(TCC) /Fo$@ -c report_.c |
| 861 | 873 | |
| 862 | 874 | report_.c : $(SRCDIR)\report.c |
| @@ -973,10 +985,16 @@ | ||
| 973 | 985 | $(OX)\undo$O : undo_.c undo.h |
| 974 | 986 | $(TCC) /Fo$@ -c undo_.c |
| 975 | 987 | |
| 976 | 988 | undo_.c : $(SRCDIR)\undo.c |
| 977 | 989 | translate$E $** > $@ |
| 990 | + | |
| 991 | +$(OX)\unicode$O : unicode_.c unicode.h | |
| 992 | + $(TCC) /Fo$@ -c unicode_.c | |
| 993 | + | |
| 994 | +unicode_.c : $(SRCDIR)\unicode.c | |
| 995 | + translate$E $** > $@ | |
| 978 | 996 | |
| 979 | 997 | $(OX)\update$O : update_.c update.h |
| 980 | 998 | $(TCC) /Fo$@ -c update_.c |
| 981 | 999 | |
| 982 | 1000 | update_.c : $(SRCDIR)\update.c |
| @@ -1122,10 +1140,11 @@ | ||
| 1122 | 1140 | pivot_.c:pivot.h \ |
| 1123 | 1141 | popen_.c:popen.h \ |
| 1124 | 1142 | pqueue_.c:pqueue.h \ |
| 1125 | 1143 | printf_.c:printf.h \ |
| 1126 | 1144 | rebuild_.c:rebuild.h \ |
| 1145 | + regexp_.c:regexp.h \ | |
| 1127 | 1146 | report_.c:report.h \ |
| 1128 | 1147 | rss_.c:rss.h \ |
| 1129 | 1148 | schema_.c:schema.h \ |
| 1130 | 1149 | search_.c:search.h \ |
| 1131 | 1150 | setup_.c:setup.h \ |
| @@ -1142,10 +1161,11 @@ | ||
| 1142 | 1161 | th_main_.c:th_main.h \ |
| 1143 | 1162 | timeline_.c:timeline.h \ |
| 1144 | 1163 | tkt_.c:tkt.h \ |
| 1145 | 1164 | tktsetup_.c:tktsetup.h \ |
| 1146 | 1165 | undo_.c:undo.h \ |
| 1166 | + unicode_.c:unicode.h \ | |
| 1147 | 1167 | update_.c:update.h \ |
| 1148 | 1168 | url_.c:url.h \ |
| 1149 | 1169 | user_.c:user.h \ |
| 1150 | 1170 | utf8_.c:utf8.h \ |
| 1151 | 1171 | verify_.c:verify.h \ |
| 1152 | 1172 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -107,10 +107,11 @@ | |
| 107 | pivot_.c \ |
| 108 | popen_.c \ |
| 109 | pqueue_.c \ |
| 110 | printf_.c \ |
| 111 | rebuild_.c \ |
| 112 | report_.c \ |
| 113 | rss_.c \ |
| 114 | schema_.c \ |
| 115 | search_.c \ |
| 116 | setup_.c \ |
| @@ -127,10 +128,11 @@ | |
| 127 | th_main_.c \ |
| 128 | timeline_.c \ |
| 129 | tkt_.c \ |
| 130 | tktsetup_.c \ |
| 131 | undo_.c \ |
| 132 | update_.c \ |
| 133 | url_.c \ |
| 134 | user_.c \ |
| 135 | utf8_.c \ |
| 136 | verify_.c \ |
| @@ -210,10 +212,11 @@ | |
| 210 | $(OX)\pivot$O \ |
| 211 | $(OX)\popen$O \ |
| 212 | $(OX)\pqueue$O \ |
| 213 | $(OX)\printf$O \ |
| 214 | $(OX)\rebuild$O \ |
| 215 | $(OX)\report$O \ |
| 216 | $(OX)\rss$O \ |
| 217 | $(OX)\schema$O \ |
| 218 | $(OX)\search$O \ |
| 219 | $(OX)\setup$O \ |
| @@ -230,10 +233,11 @@ | |
| 230 | $(OX)\th_main$O \ |
| 231 | $(OX)\timeline$O \ |
| 232 | $(OX)\tkt$O \ |
| 233 | $(OX)\tktsetup$O \ |
| 234 | $(OX)\undo$O \ |
| 235 | $(OX)\update$O \ |
| 236 | $(OX)\url$O \ |
| 237 | $(OX)\user$O \ |
| 238 | $(OX)\utf8$O \ |
| 239 | $(OX)\verify$O \ |
| @@ -330,10 +334,11 @@ | |
| 330 | echo $(OX)\pivot.obj >> $@ |
| 331 | echo $(OX)\popen.obj >> $@ |
| 332 | echo $(OX)\pqueue.obj >> $@ |
| 333 | echo $(OX)\printf.obj >> $@ |
| 334 | echo $(OX)\rebuild.obj >> $@ |
| 335 | echo $(OX)\report.obj >> $@ |
| 336 | echo $(OX)\rss.obj >> $@ |
| 337 | echo $(OX)\schema.obj >> $@ |
| 338 | echo $(OX)\search.obj >> $@ |
| 339 | echo $(OX)\setup.obj >> $@ |
| @@ -354,10 +359,11 @@ | |
| 354 | echo $(OX)\th_main.obj >> $@ |
| 355 | echo $(OX)\timeline.obj >> $@ |
| 356 | echo $(OX)\tkt.obj >> $@ |
| 357 | echo $(OX)\tktsetup.obj >> $@ |
| 358 | echo $(OX)\undo.obj >> $@ |
| 359 | echo $(OX)\update.obj >> $@ |
| 360 | echo $(OX)\url.obj >> $@ |
| 361 | echo $(OX)\user.obj >> $@ |
| 362 | echo $(OX)\utf8.obj >> $@ |
| 363 | echo $(OX)\verify.obj >> $@ |
| @@ -853,10 +859,16 @@ | |
| 853 | $(OX)\rebuild$O : rebuild_.c rebuild.h |
| 854 | $(TCC) /Fo$@ -c rebuild_.c |
| 855 | |
| 856 | rebuild_.c : $(SRCDIR)\rebuild.c |
| 857 | translate$E $** > $@ |
| 858 | |
| 859 | $(OX)\report$O : report_.c report.h |
| 860 | $(TCC) /Fo$@ -c report_.c |
| 861 | |
| 862 | report_.c : $(SRCDIR)\report.c |
| @@ -973,10 +985,16 @@ | |
| 973 | $(OX)\undo$O : undo_.c undo.h |
| 974 | $(TCC) /Fo$@ -c undo_.c |
| 975 | |
| 976 | undo_.c : $(SRCDIR)\undo.c |
| 977 | translate$E $** > $@ |
| 978 | |
| 979 | $(OX)\update$O : update_.c update.h |
| 980 | $(TCC) /Fo$@ -c update_.c |
| 981 | |
| 982 | update_.c : $(SRCDIR)\update.c |
| @@ -1122,10 +1140,11 @@ | |
| 1122 | pivot_.c:pivot.h \ |
| 1123 | popen_.c:popen.h \ |
| 1124 | pqueue_.c:pqueue.h \ |
| 1125 | printf_.c:printf.h \ |
| 1126 | rebuild_.c:rebuild.h \ |
| 1127 | report_.c:report.h \ |
| 1128 | rss_.c:rss.h \ |
| 1129 | schema_.c:schema.h \ |
| 1130 | search_.c:search.h \ |
| 1131 | setup_.c:setup.h \ |
| @@ -1142,10 +1161,11 @@ | |
| 1142 | th_main_.c:th_main.h \ |
| 1143 | timeline_.c:timeline.h \ |
| 1144 | tkt_.c:tkt.h \ |
| 1145 | tktsetup_.c:tktsetup.h \ |
| 1146 | undo_.c:undo.h \ |
| 1147 | update_.c:update.h \ |
| 1148 | url_.c:url.h \ |
| 1149 | user_.c:user.h \ |
| 1150 | utf8_.c:utf8.h \ |
| 1151 | verify_.c:verify.h \ |
| 1152 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -107,10 +107,11 @@ | |
| 107 | pivot_.c \ |
| 108 | popen_.c \ |
| 109 | pqueue_.c \ |
| 110 | printf_.c \ |
| 111 | rebuild_.c \ |
| 112 | regexp_.c \ |
| 113 | report_.c \ |
| 114 | rss_.c \ |
| 115 | schema_.c \ |
| 116 | search_.c \ |
| 117 | setup_.c \ |
| @@ -127,10 +128,11 @@ | |
| 128 | th_main_.c \ |
| 129 | timeline_.c \ |
| 130 | tkt_.c \ |
| 131 | tktsetup_.c \ |
| 132 | undo_.c \ |
| 133 | unicode_.c \ |
| 134 | update_.c \ |
| 135 | url_.c \ |
| 136 | user_.c \ |
| 137 | utf8_.c \ |
| 138 | verify_.c \ |
| @@ -210,10 +212,11 @@ | |
| 212 | $(OX)\pivot$O \ |
| 213 | $(OX)\popen$O \ |
| 214 | $(OX)\pqueue$O \ |
| 215 | $(OX)\printf$O \ |
| 216 | $(OX)\rebuild$O \ |
| 217 | $(OX)\regexp$O \ |
| 218 | $(OX)\report$O \ |
| 219 | $(OX)\rss$O \ |
| 220 | $(OX)\schema$O \ |
| 221 | $(OX)\search$O \ |
| 222 | $(OX)\setup$O \ |
| @@ -230,10 +233,11 @@ | |
| 233 | $(OX)\th_main$O \ |
| 234 | $(OX)\timeline$O \ |
| 235 | $(OX)\tkt$O \ |
| 236 | $(OX)\tktsetup$O \ |
| 237 | $(OX)\undo$O \ |
| 238 | $(OX)\unicode$O \ |
| 239 | $(OX)\update$O \ |
| 240 | $(OX)\url$O \ |
| 241 | $(OX)\user$O \ |
| 242 | $(OX)\utf8$O \ |
| 243 | $(OX)\verify$O \ |
| @@ -330,10 +334,11 @@ | |
| 334 | echo $(OX)\pivot.obj >> $@ |
| 335 | echo $(OX)\popen.obj >> $@ |
| 336 | echo $(OX)\pqueue.obj >> $@ |
| 337 | echo $(OX)\printf.obj >> $@ |
| 338 | echo $(OX)\rebuild.obj >> $@ |
| 339 | echo $(OX)\regexp.obj >> $@ |
| 340 | echo $(OX)\report.obj >> $@ |
| 341 | echo $(OX)\rss.obj >> $@ |
| 342 | echo $(OX)\schema.obj >> $@ |
| 343 | echo $(OX)\search.obj >> $@ |
| 344 | echo $(OX)\setup.obj >> $@ |
| @@ -354,10 +359,11 @@ | |
| 359 | echo $(OX)\th_main.obj >> $@ |
| 360 | echo $(OX)\timeline.obj >> $@ |
| 361 | echo $(OX)\tkt.obj >> $@ |
| 362 | echo $(OX)\tktsetup.obj >> $@ |
| 363 | echo $(OX)\undo.obj >> $@ |
| 364 | echo $(OX)\unicode.obj >> $@ |
| 365 | echo $(OX)\update.obj >> $@ |
| 366 | echo $(OX)\url.obj >> $@ |
| 367 | echo $(OX)\user.obj >> $@ |
| 368 | echo $(OX)\utf8.obj >> $@ |
| 369 | echo $(OX)\verify.obj >> $@ |
| @@ -853,10 +859,16 @@ | |
| 859 | $(OX)\rebuild$O : rebuild_.c rebuild.h |
| 860 | $(TCC) /Fo$@ -c rebuild_.c |
| 861 | |
| 862 | rebuild_.c : $(SRCDIR)\rebuild.c |
| 863 | translate$E $** > $@ |
| 864 | |
| 865 | $(OX)\regexp$O : regexp_.c regexp.h |
| 866 | $(TCC) /Fo$@ -c regexp_.c |
| 867 | |
| 868 | regexp_.c : $(SRCDIR)\regexp.c |
| 869 | translate$E $** > $@ |
| 870 | |
| 871 | $(OX)\report$O : report_.c report.h |
| 872 | $(TCC) /Fo$@ -c report_.c |
| 873 | |
| 874 | report_.c : $(SRCDIR)\report.c |
| @@ -973,10 +985,16 @@ | |
| 985 | $(OX)\undo$O : undo_.c undo.h |
| 986 | $(TCC) /Fo$@ -c undo_.c |
| 987 | |
| 988 | undo_.c : $(SRCDIR)\undo.c |
| 989 | translate$E $** > $@ |
| 990 | |
| 991 | $(OX)\unicode$O : unicode_.c unicode.h |
| 992 | $(TCC) /Fo$@ -c unicode_.c |
| 993 | |
| 994 | unicode_.c : $(SRCDIR)\unicode.c |
| 995 | translate$E $** > $@ |
| 996 | |
| 997 | $(OX)\update$O : update_.c update.h |
| 998 | $(TCC) /Fo$@ -c update_.c |
| 999 | |
| 1000 | update_.c : $(SRCDIR)\update.c |
| @@ -1122,10 +1140,11 @@ | |
| 1140 | pivot_.c:pivot.h \ |
| 1141 | popen_.c:popen.h \ |
| 1142 | pqueue_.c:pqueue.h \ |
| 1143 | printf_.c:printf.h \ |
| 1144 | rebuild_.c:rebuild.h \ |
| 1145 | regexp_.c:regexp.h \ |
| 1146 | report_.c:report.h \ |
| 1147 | rss_.c:rss.h \ |
| 1148 | schema_.c:schema.h \ |
| 1149 | search_.c:search.h \ |
| 1150 | setup_.c:setup.h \ |
| @@ -1142,10 +1161,11 @@ | |
| 1161 | th_main_.c:th_main.h \ |
| 1162 | timeline_.c:timeline.h \ |
| 1163 | tkt_.c:tkt.h \ |
| 1164 | tktsetup_.c:tktsetup.h \ |
| 1165 | undo_.c:undo.h \ |
| 1166 | unicode_.c:unicode.h \ |
| 1167 | update_.c:update.h \ |
| 1168 | url_.c:url.h \ |
| 1169 | user_.c:user.h \ |
| 1170 | utf8_.c:utf8.h \ |
| 1171 | verify_.c:verify.h \ |
| 1172 |
+3
| --- win/fossil.rc | ||
| +++ win/fossil.rc | ||
| @@ -109,10 +109,13 @@ | ||
| 109 | 109 | #endif |
| 110 | 110 | #endif |
| 111 | 111 | #ifdef FOSSIL_ENABLE_JSON |
| 112 | 112 | VALUE "JsonEnabled", "Yes, cson\0" |
| 113 | 113 | #endif |
| 114 | +#ifdef FOSSIL_ENABLE_MARKDOWN | |
| 115 | + VALUE "MarkdownEnabled", "Yes\0" | |
| 116 | +#endif | |
| 114 | 117 | END |
| 115 | 118 | END |
| 116 | 119 | BLOCK "VarFileInfo" |
| 117 | 120 | BEGIN |
| 118 | 121 | VALUE "Translation", 0x409, 0x4B0 |
| 119 | 122 |
| --- win/fossil.rc | |
| +++ win/fossil.rc | |
| @@ -109,10 +109,13 @@ | |
| 109 | #endif |
| 110 | #endif |
| 111 | #ifdef FOSSIL_ENABLE_JSON |
| 112 | VALUE "JsonEnabled", "Yes, cson\0" |
| 113 | #endif |
| 114 | END |
| 115 | END |
| 116 | BLOCK "VarFileInfo" |
| 117 | BEGIN |
| 118 | VALUE "Translation", 0x409, 0x4B0 |
| 119 |
| --- win/fossil.rc | |
| +++ win/fossil.rc | |
| @@ -109,10 +109,13 @@ | |
| 109 | #endif |
| 110 | #endif |
| 111 | #ifdef FOSSIL_ENABLE_JSON |
| 112 | VALUE "JsonEnabled", "Yes, cson\0" |
| 113 | #endif |
| 114 | #ifdef FOSSIL_ENABLE_MARKDOWN |
| 115 | VALUE "MarkdownEnabled", "Yes\0" |
| 116 | #endif |
| 117 | END |
| 118 | END |
| 119 | BLOCK "VarFileInfo" |
| 120 | BEGIN |
| 121 | VALUE "Translation", 0x409, 0x4B0 |
| 122 |
+3
| --- win/fossil.rc | ||
| +++ win/fossil.rc | ||
| @@ -109,10 +109,13 @@ | ||
| 109 | 109 | #endif |
| 110 | 110 | #endif |
| 111 | 111 | #ifdef FOSSIL_ENABLE_JSON |
| 112 | 112 | VALUE "JsonEnabled", "Yes, cson\0" |
| 113 | 113 | #endif |
| 114 | +#ifdef FOSSIL_ENABLE_MARKDOWN | |
| 115 | + VALUE "MarkdownEnabled", "Yes\0" | |
| 116 | +#endif | |
| 114 | 117 | END |
| 115 | 118 | END |
| 116 | 119 | BLOCK "VarFileInfo" |
| 117 | 120 | BEGIN |
| 118 | 121 | VALUE "Translation", 0x409, 0x4B0 |
| 119 | 122 |
| --- win/fossil.rc | |
| +++ win/fossil.rc | |
| @@ -109,10 +109,13 @@ | |
| 109 | #endif |
| 110 | #endif |
| 111 | #ifdef FOSSIL_ENABLE_JSON |
| 112 | VALUE "JsonEnabled", "Yes, cson\0" |
| 113 | #endif |
| 114 | END |
| 115 | END |
| 116 | BLOCK "VarFileInfo" |
| 117 | BEGIN |
| 118 | VALUE "Translation", 0x409, 0x4B0 |
| 119 |
| --- win/fossil.rc | |
| +++ win/fossil.rc | |
| @@ -109,10 +109,13 @@ | |
| 109 | #endif |
| 110 | #endif |
| 111 | #ifdef FOSSIL_ENABLE_JSON |
| 112 | VALUE "JsonEnabled", "Yes, cson\0" |
| 113 | #endif |
| 114 | #ifdef FOSSIL_ENABLE_MARKDOWN |
| 115 | VALUE "MarkdownEnabled", "Yes\0" |
| 116 | #endif |
| 117 | END |
| 118 | END |
| 119 | BLOCK "VarFileInfo" |
| 120 | BEGIN |
| 121 | VALUE "Translation", 0x409, 0x4B0 |
| 122 |
+398
-204
| --- win/include/dirent.h | ||
| +++ win/include/dirent.h | ||
| @@ -20,21 +20,24 @@ | ||
| 20 | 20 | * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| 21 | 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| 22 | 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 23 | 23 | * OTHER DEALINGS IN THE SOFTWARE. |
| 24 | 24 | * |
| 25 | + * | |
| 26 | + * Version 1.13, Dec 12 2012, Toni Ronkko | |
| 27 | + * Use traditional 8+3 file name if the name cannot be represented in the | |
| 28 | + * default ANSI code page. Now compiles again with MSVC 6.0. Thanks to | |
| 29 | + * Konstantin Khomoutov for testing. | |
| 25 | 30 | * |
| 26 | 31 | * Version 1.12.1, Oct 1 2012, Toni Ronkko |
| 27 | 32 | * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with |
| 28 | 33 | * capital W) in order to maintain compatibility with MingW. |
| 29 | 34 | * |
| 30 | 35 | * Version 1.12, Sep 30 2012, Toni Ronkko |
| 31 | - * Define PATH_MAX and NAME_MAX. | |
| 32 | - * | |
| 33 | - * Added wide-character variants _wDIR, _wdirent, _wopendir(), | |
| 34 | - * _wreaddir(), _wclosedir() and _wrewinddir(). Thanks to Edgar Buerkle | |
| 35 | - * and Jan Nijtmans for ideas and code. | |
| 36 | + * Define PATH_MAX and NAME_MAX. Added wide-character variants _wDIR, | |
| 37 | + * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir(). | |
| 38 | + * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code. | |
| 36 | 39 | * |
| 37 | 40 | * Do not include windows.h. This allows dirent.h to be integrated more |
| 38 | 41 | * easily into programs using winsock. Thanks to Fernando Azaldegui. |
| 39 | 42 | * |
| 40 | 43 | * Version 1.11, Mar 15, 2011, Toni Ronkko |
| @@ -88,48 +91,72 @@ | ||
| 88 | 91 | *****************************************************************************/ |
| 89 | 92 | #ifndef DIRENT_H |
| 90 | 93 | #define DIRENT_H |
| 91 | 94 | |
| 92 | 95 | #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86) |
| 93 | -#define _X86_ | |
| 96 | +# define _X86_ | |
| 94 | 97 | #endif |
| 95 | 98 | #include <stdio.h> |
| 96 | 99 | #include <stdarg.h> |
| 97 | 100 | #include <windef.h> |
| 98 | 101 | #include <winbase.h> |
| 99 | 102 | #include <wchar.h> |
| 100 | -#include <winnls.h> | |
| 101 | 103 | #include <string.h> |
| 102 | 104 | #include <stdlib.h> |
| 105 | +#include <malloc.h> | |
| 103 | 106 | #include <sys/types.h> |
| 104 | 107 | #include <sys/stat.h> |
| 105 | 108 | #include <errno.h> |
| 106 | 109 | |
| 107 | -/* Windows 8 wide-character string functions */ | |
| 108 | -#if (_WIN32_WINNT >= 0x0602) | |
| 109 | -# include <stringapiset.h> | |
| 110 | -#endif | |
| 110 | +/* Indicates that d_type field is available in dirent structure */ | |
| 111 | +#define _DIRENT_HAVE_D_TYPE | |
| 112 | + | |
| 113 | +/* Indicates that d_namlen field is available in dirent structure */ | |
| 114 | +#define _DIRENT_HAVE_D_NAMLEN | |
| 111 | 115 | |
| 112 | 116 | /* Entries missing from MSVC 6.0 */ |
| 113 | 117 | #if !defined(FILE_ATTRIBUTE_DEVICE) |
| 114 | -# define FILE_ATTRIBUTE_DEVICE 0x40 | |
| 118 | +# define FILE_ATTRIBUTE_DEVICE 0x40 | |
| 115 | 119 | #endif |
| 116 | 120 | |
| 117 | 121 | /* File type and permission flags for stat() */ |
| 118 | -#if defined(_MSC_VER) && !defined(S_IREAD) | |
| 122 | +#if !defined(S_IFMT) | |
| 119 | 123 | # define S_IFMT _S_IFMT /* File type mask */ |
| 124 | +#endif | |
| 125 | +#if !defined(S_IFDIR) | |
| 120 | 126 | # define S_IFDIR _S_IFDIR /* Directory */ |
| 127 | +#endif | |
| 128 | +#if !defined(S_IFCHR) | |
| 121 | 129 | # define S_IFCHR _S_IFCHR /* Character device */ |
| 130 | +#endif | |
| 131 | +#if !defined(S_IFFIFO) | |
| 122 | 132 | # define S_IFFIFO _S_IFFIFO /* Pipe */ |
| 133 | +#endif | |
| 134 | +#if !defined(S_IFREG) | |
| 123 | 135 | # define S_IFREG _S_IFREG /* Regular file */ |
| 136 | +#endif | |
| 137 | +#if !defined(S_IREAD) | |
| 124 | 138 | # define S_IREAD _S_IREAD /* Read permission */ |
| 139 | +#endif | |
| 140 | +#if !defined(S_IWRITE) | |
| 125 | 141 | # define S_IWRITE _S_IWRITE /* Write permission */ |
| 142 | +#endif | |
| 143 | +#if !defined(S_IEXEC) | |
| 126 | 144 | # define S_IEXEC _S_IEXEC /* Execute permission */ |
| 127 | 145 | #endif |
| 128 | -#define S_IFBLK 0 /* Block device */ | |
| 129 | -#define S_IFLNK 0 /* Link */ | |
| 130 | -#define S_IFSOCK 0 /* Socket */ | |
| 146 | +#if !defined(S_IFIFO) | |
| 147 | +# define S_IFIFO _S_IFIFO /* Pipe */ | |
| 148 | +#endif | |
| 149 | +#if !defined(S_IFBLK) | |
| 150 | +# define S_IFBLK 0 /* Block device */ | |
| 151 | +#endif | |
| 152 | +#if !defined(S_IFLNK) | |
| 153 | +# define S_IFLNK 0 /* Link */ | |
| 154 | +#endif | |
| 155 | +#if !defined(S_IFSOCK) | |
| 156 | +# define S_IFSOCK 0 /* Socket */ | |
| 157 | +#endif | |
| 131 | 158 | |
| 132 | 159 | #if defined(_MSC_VER) |
| 133 | 160 | # define S_IRUSR S_IREAD /* Read user */ |
| 134 | 161 | # define S_IWUSR S_IWRITE /* Write user */ |
| 135 | 162 | # define S_IXUSR 0 /* Execute user */ |
| @@ -139,18 +166,26 @@ | ||
| 139 | 166 | # define S_IROTH 0 /* Read others */ |
| 140 | 167 | # define S_IWOTH 0 /* Write others */ |
| 141 | 168 | # define S_IXOTH 0 /* Execute others */ |
| 142 | 169 | #endif |
| 143 | 170 | |
| 144 | -/* Indicates that d_type field is available in dirent structure */ | |
| 145 | -#define _DIRENT_HAVE_D_TYPE | |
| 171 | +/* Maximum length of file name */ | |
| 172 | +#if !defined(PATH_MAX) | |
| 173 | +# define PATH_MAX MAX_PATH | |
| 174 | +#endif | |
| 175 | +#if !defined(FILENAME_MAX) | |
| 176 | +# define FILENAME_MAX MAX_PATH | |
| 177 | +#endif | |
| 178 | +#if !defined(NAME_MAX) | |
| 179 | +# define NAME_MAX FILENAME_MAX | |
| 180 | +#endif | |
| 146 | 181 | |
| 147 | 182 | /* File type flags for d_type */ |
| 148 | 183 | #define DT_UNKNOWN 0 |
| 149 | 184 | #define DT_REG S_IFREG |
| 150 | 185 | #define DT_DIR S_IFDIR |
| 151 | -#define DT_FIFO S_IFFIFO | |
| 186 | +#define DT_FIFO S_IFIFO | |
| 152 | 187 | #define DT_SOCK S_IFSOCK |
| 153 | 188 | #define DT_CHR S_IFCHR |
| 154 | 189 | #define DT_BLK S_IFBLK |
| 155 | 190 | |
| 156 | 191 | /* Macros for converting between st_mode and d_type */ |
| @@ -161,41 +196,31 @@ | ||
| 161 | 196 | * File type macros. Note that block devices, sockets and links cannot be |
| 162 | 197 | * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are |
| 163 | 198 | * only defined for compatibility. These macros should always return false |
| 164 | 199 | * on Windows. |
| 165 | 200 | */ |
| 166 | -#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO) | |
| 201 | +#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) | |
| 167 | 202 | #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) |
| 168 | 203 | #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) |
| 169 | 204 | #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) |
| 170 | 205 | #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) |
| 171 | 206 | #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) |
| 172 | 207 | #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) |
| 173 | 208 | |
| 174 | -/* For compatiblity with Unix */ | |
| 175 | -#if !defined(PATH_MAX) | |
| 176 | -# define PATH_MAX MAX_PATH | |
| 177 | -#endif | |
| 178 | -#if !defined(FILENAME_MAX) | |
| 179 | -# define FILENAME_MAX MAX_PATH | |
| 180 | -#endif | |
| 181 | -#if !defined(NAME_MAX) | |
| 182 | -# define NAME_MAX FILENAME_MAX | |
| 183 | -#endif | |
| 184 | - | |
| 185 | -/* Set errno variable */ | |
| 186 | -#if defined(_MSC_VER) | |
| 187 | -#define DIRENT_SET_ERRNO(x) _set_errno (x) | |
| 188 | -#else | |
| 189 | -#define DIRENT_SET_ERRNO(x) (errno = (x)) | |
| 190 | -#endif | |
| 209 | +/* Return the exact length of d_namlen without zero terminator */ | |
| 210 | +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) | |
| 211 | + | |
| 212 | +/* Return number of bytes needed to store d_namlen */ | |
| 213 | +#define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1) | |
| 214 | + | |
| 191 | 215 | |
| 192 | 216 | #ifdef __cplusplus |
| 193 | 217 | extern "C" { |
| 194 | 218 | #endif |
| 195 | 219 | |
| 196 | -/* Wide-character versions */ | |
| 220 | + | |
| 221 | +/* Wide-character version */ | |
| 197 | 222 | struct _wdirent { |
| 198 | 223 | long d_ino; /* Always zero */ |
| 199 | 224 | unsigned short d_reclen; /* Structure size */ |
| 200 | 225 | size_t d_namlen; /* Length of name without \0 */ |
| 201 | 226 | int d_type; /* File type */ |
| @@ -203,11 +228,11 @@ | ||
| 203 | 228 | }; |
| 204 | 229 | typedef struct _wdirent _wdirent; |
| 205 | 230 | |
| 206 | 231 | struct _WDIR { |
| 207 | 232 | struct _wdirent ent; /* Current directory entry */ |
| 208 | - WIN32_FIND_DATAW find_data; /* Private file data */ | |
| 233 | + WIN32_FIND_DATAW data; /* Private file data */ | |
| 209 | 234 | int cached; /* True if data is valid */ |
| 210 | 235 | HANDLE handle; /* Win32 search handle */ |
| 211 | 236 | wchar_t *patt; /* Initial directory name */ |
| 212 | 237 | }; |
| 213 | 238 | typedef struct _WDIR _WDIR; |
| @@ -214,10 +239,11 @@ | ||
| 214 | 239 | |
| 215 | 240 | static _WDIR *_wopendir (const wchar_t *dirname); |
| 216 | 241 | static struct _wdirent *_wreaddir (_WDIR *dirp); |
| 217 | 242 | static int _wclosedir (_WDIR *dirp); |
| 218 | 243 | static void _wrewinddir (_WDIR* dirp); |
| 244 | + | |
| 219 | 245 | |
| 220 | 246 | /* For compatibility with Symbian */ |
| 221 | 247 | #define wdirent _wdirent |
| 222 | 248 | #define WDIR _WDIR |
| 223 | 249 | #define wopendir _wopendir |
| @@ -246,10 +272,30 @@ | ||
| 246 | 272 | static struct dirent *readdir (DIR *dirp); |
| 247 | 273 | static int closedir (DIR *dirp); |
| 248 | 274 | static void rewinddir (DIR* dirp); |
| 249 | 275 | |
| 250 | 276 | |
| 277 | +/* Internal utility functions */ | |
| 278 | +static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); | |
| 279 | +static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); | |
| 280 | + | |
| 281 | +static int dirent_mbstowcs_s( | |
| 282 | + size_t *pReturnValue, | |
| 283 | + wchar_t *wcstr, | |
| 284 | + size_t sizeInWords, | |
| 285 | + const char *mbstr, | |
| 286 | + size_t count); | |
| 287 | + | |
| 288 | +static int dirent_wcstombs_s( | |
| 289 | + size_t *pReturnValue, | |
| 290 | + char *mbstr, | |
| 291 | + size_t sizeInBytes, | |
| 292 | + const wchar_t *wcstr, | |
| 293 | + size_t count); | |
| 294 | + | |
| 295 | +static void dirent_set_errno (int error); | |
| 296 | + | |
| 251 | 297 | /* |
| 252 | 298 | * Open directory stream DIRNAME for read and return a pointer to the |
| 253 | 299 | * internal working area that is used to retrieve individual directory |
| 254 | 300 | * entries. |
| 255 | 301 | */ |
| @@ -256,31 +302,38 @@ | ||
| 256 | 302 | static _WDIR* |
| 257 | 303 | _wopendir( |
| 258 | 304 | const wchar_t *dirname) |
| 259 | 305 | { |
| 260 | 306 | _WDIR *dirp = NULL; |
| 261 | - int error = 0; | |
| 307 | + int error; | |
| 308 | + | |
| 309 | + /* Must have directory name */ | |
| 310 | + if (dirname == NULL || dirname[0] == '\0') { | |
| 311 | + dirent_set_errno (ENOENT); | |
| 312 | + return NULL; | |
| 313 | + } | |
| 262 | 314 | |
| 263 | 315 | /* Allocate new _WDIR structure */ |
| 264 | 316 | dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); |
| 265 | 317 | if (dirp != NULL) { |
| 266 | 318 | DWORD n; |
| 267 | 319 | |
| 268 | 320 | /* Reset _WDIR structure */ |
| 269 | 321 | dirp->handle = INVALID_HANDLE_VALUE; |
| 270 | 322 | dirp->patt = NULL; |
| 323 | + dirp->cached = 0; | |
| 271 | 324 | |
| 272 | 325 | /* Compute the length of full path plus zero terminator */ |
| 273 | 326 | n = GetFullPathNameW (dirname, 0, NULL, NULL); |
| 274 | 327 | |
| 275 | - /* Allocate room for full path and search patterns */ | |
| 328 | + /* Allocate room for absolute directory name and search pattern */ | |
| 276 | 329 | dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); |
| 277 | 330 | if (dirp->patt) { |
| 278 | 331 | |
| 279 | 332 | /* |
| 280 | 333 | * Convert relative directory name to an absolute one. This |
| 281 | - * allows rewinddir() to function correctly when the current | |
| 334 | + * allows rewinddir() to function correctly even when current | |
| 282 | 335 | * working directory is changed between opendir() and rewinddir(). |
| 283 | 336 | */ |
| 284 | 337 | n = GetFullPathNameW (dirname, n, dirp->patt, NULL); |
| 285 | 338 | if (n > 0) { |
| 286 | 339 | wchar_t *p; |
| @@ -303,25 +356,22 @@ | ||
| 303 | 356 | } |
| 304 | 357 | *p++ = '*'; |
| 305 | 358 | *p = '\0'; |
| 306 | 359 | |
| 307 | 360 | /* Open directory stream and retrieve the first entry */ |
| 308 | - dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data); | |
| 309 | - if (dirp->handle != INVALID_HANDLE_VALUE) { | |
| 310 | - | |
| 311 | - /* Directory entry is now waiting in memory */ | |
| 312 | - dirp->cached = 1; | |
| 313 | - | |
| 361 | + if (dirent_first (dirp)) { | |
| 362 | + /* Directory stream opened successfully */ | |
| 363 | + error = 0; | |
| 314 | 364 | } else { |
| 315 | - /* Search pattern is not a directory name? */ | |
| 316 | - DIRENT_SET_ERRNO (ENOENT); | |
| 365 | + /* Cannot retrieve first entry */ | |
| 317 | 366 | error = 1; |
| 367 | + dirent_set_errno (ENOENT); | |
| 318 | 368 | } |
| 319 | 369 | |
| 320 | 370 | } else { |
| 321 | - /* Cannot convert directory name to wide character string */ | |
| 322 | - DIRENT_SET_ERRNO (ENOENT); | |
| 371 | + /* Cannot retrieve full path name */ | |
| 372 | + dirent_set_errno (ENOENT); | |
| 323 | 373 | error = 1; |
| 324 | 374 | } |
| 325 | 375 | |
| 326 | 376 | } else { |
| 327 | 377 | /* Cannot allocate memory for search pattern */ |
| @@ -350,70 +400,59 @@ | ||
| 350 | 400 | */ |
| 351 | 401 | static struct _wdirent* |
| 352 | 402 | _wreaddir( |
| 353 | 403 | _WDIR *dirp) |
| 354 | 404 | { |
| 355 | - DWORD attr; | |
| 356 | - errno_t error; | |
| 357 | - | |
| 358 | - /* Get next directory entry */ | |
| 359 | - if (dirp->cached != 0) { | |
| 360 | - /* A valid directory entry already in memory */ | |
| 361 | - dirp->cached = 0; | |
| 362 | - } else { | |
| 363 | - /* Get the next directory entry from stream */ | |
| 364 | - if (dirp->handle == INVALID_HANDLE_VALUE) { | |
| 365 | - return NULL; | |
| 366 | - } | |
| 367 | - if (FindNextFileW (dirp->handle, &dirp->find_data) == FALSE) { | |
| 368 | - /* The very last entry has been processed or an error occured */ | |
| 369 | - FindClose (dirp->handle); | |
| 370 | - dirp->handle = INVALID_HANDLE_VALUE; | |
| 371 | - return NULL; | |
| 372 | - } | |
| 373 | - } | |
| 374 | - | |
| 375 | - /* Copy file name as a wide-character string */ | |
| 376 | - error = wcsncpy_s( | |
| 377 | - dirp->ent.d_name, /* Destination string */ | |
| 378 | - PATH_MAX, /* Size of dest in words */ | |
| 379 | - dirp->find_data.cFileName, /* Source string */ | |
| 380 | - PATH_MAX + 1); /* Max # of chars to copy */ | |
| 381 | - if (!error) { | |
| 382 | - | |
| 383 | - /* Compute the length of name */ | |
| 384 | - dirp->ent.d_namlen = wcsnlen (dirp->ent.d_name, PATH_MAX); | |
| 385 | - | |
| 386 | - /* Determine file type */ | |
| 387 | - attr = dirp->find_data.dwFileAttributes; | |
| 405 | + WIN32_FIND_DATAW *datap; | |
| 406 | + struct _wdirent *entp; | |
| 407 | + | |
| 408 | + /* Read next directory entry */ | |
| 409 | + datap = dirent_next (dirp); | |
| 410 | + if (datap) { | |
| 411 | + size_t n; | |
| 412 | + DWORD attr; | |
| 413 | + | |
| 414 | + /* Pointer to directory entry to return */ | |
| 415 | + entp = &dirp->ent; | |
| 416 | + | |
| 417 | + /* | |
| 418 | + * Copy file name as wide-character string. If the file name is too | |
| 419 | + * long to fit in to the destination buffer, then truncate file name | |
| 420 | + * to PATH_MAX characters and zero-terminate the buffer. | |
| 421 | + */ | |
| 422 | + n = 0; | |
| 423 | + while (n < PATH_MAX && datap->cFileName[n] != 0) { | |
| 424 | + entp->d_name[n] = datap->cFileName[n]; | |
| 425 | + n++; | |
| 426 | + } | |
| 427 | + dirp->ent.d_name[n] = 0; | |
| 428 | + | |
| 429 | + /* Length of file name excluding zero terminator */ | |
| 430 | + entp->d_namlen = n; | |
| 431 | + | |
| 432 | + /* File type */ | |
| 433 | + attr = datap->dwFileAttributes; | |
| 388 | 434 | if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { |
| 389 | - dirp->ent.d_type = DT_CHR; | |
| 435 | + entp->d_type = DT_CHR; | |
| 390 | 436 | } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 391 | - dirp->ent.d_type = DT_DIR; | |
| 437 | + entp->d_type = DT_DIR; | |
| 392 | 438 | } else { |
| 393 | - dirp->ent.d_type = DT_REG; | |
| 439 | + entp->d_type = DT_REG; | |
| 394 | 440 | } |
| 395 | 441 | |
| 396 | 442 | /* Reset dummy fields */ |
| 397 | - dirp->ent.d_ino = 0; | |
| 398 | - dirp->ent.d_reclen = sizeof (dirp->ent); | |
| 443 | + entp->d_ino = 0; | |
| 444 | + entp->d_reclen = sizeof (struct _wdirent); | |
| 399 | 445 | |
| 400 | 446 | } else { |
| 401 | 447 | |
| 402 | - /* | |
| 403 | - * Cannot copy file name from find_data to ent. Construct a | |
| 404 | - * dummy _wdirent structure to pass error to caller. | |
| 405 | - */ | |
| 406 | - dirp->ent.d_name[0] = '?'; | |
| 407 | - dirp->ent.d_name[1] = '\0'; | |
| 408 | - dirp->ent.d_namlen = 1; | |
| 409 | - dirp->ent.d_type = DT_UNKNOWN; | |
| 410 | - dirp->ent.d_ino = 0; | |
| 411 | - dirp->ent.d_reclen = 0; | |
| 448 | + /* Last directory entry read */ | |
| 449 | + entp = NULL; | |
| 450 | + | |
| 412 | 451 | } |
| 413 | 452 | |
| 414 | - return &dirp->ent; | |
| 453 | + return entp; | |
| 415 | 454 | } |
| 416 | 455 | |
| 417 | 456 | /* |
| 418 | 457 | * Close directory stream opened by opendir() function. This invalidates the |
| 419 | 458 | * DIR structure as well as any directory entry read previously by |
| @@ -442,11 +481,11 @@ | ||
| 442 | 481 | free (dirp); |
| 443 | 482 | ok = /*success*/0; |
| 444 | 483 | |
| 445 | 484 | } else { |
| 446 | 485 | /* Invalid directory stream */ |
| 447 | - DIRENT_SET_ERRNO (EBADF); | |
| 486 | + dirent_set_errno (EBADF); | |
| 448 | 487 | ok = /*failure*/-1; |
| 449 | 488 | } |
| 450 | 489 | return ok; |
| 451 | 490 | } |
| 452 | 491 | |
| @@ -456,26 +495,81 @@ | ||
| 456 | 495 | */ |
| 457 | 496 | static void |
| 458 | 497 | _wrewinddir( |
| 459 | 498 | _WDIR* dirp) |
| 460 | 499 | { |
| 461 | - if (dirp != NULL) { | |
| 462 | - /* release search handle */ | |
| 500 | + if (dirp) { | |
| 501 | + /* Release existing search handle */ | |
| 463 | 502 | if (dirp->handle != INVALID_HANDLE_VALUE) { |
| 464 | 503 | FindClose (dirp->handle); |
| 465 | 504 | } |
| 466 | 505 | |
| 467 | - /* Open new search handle and retrieve the first directory entry */ | |
| 468 | - dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data); | |
| 469 | - if (dirp->handle != INVALID_HANDLE_VALUE) { | |
| 470 | - /* a directory entry is now waiting in memory */ | |
| 471 | - dirp->cached = 1; | |
| 506 | + /* Open new search handle */ | |
| 507 | + dirent_first (dirp); | |
| 508 | + } | |
| 509 | +} | |
| 510 | + | |
| 511 | +/* Get first directory entry (internal) */ | |
| 512 | +static WIN32_FIND_DATAW* | |
| 513 | +dirent_first( | |
| 514 | + _WDIR *dirp) | |
| 515 | +{ | |
| 516 | + WIN32_FIND_DATAW *datap; | |
| 517 | + | |
| 518 | + /* Open directory and retrieve the first entry */ | |
| 519 | + dirp->handle = FindFirstFileW (dirp->patt, &dirp->data); | |
| 520 | + if (dirp->handle != INVALID_HANDLE_VALUE) { | |
| 521 | + | |
| 522 | + /* a directory entry is now waiting in memory */ | |
| 523 | + datap = &dirp->data; | |
| 524 | + dirp->cached = 1; | |
| 525 | + | |
| 526 | + } else { | |
| 527 | + | |
| 528 | + /* Failed to re-open directory: no directory entry in memory */ | |
| 529 | + dirp->cached = 0; | |
| 530 | + datap = NULL; | |
| 531 | + | |
| 532 | + } | |
| 533 | + return datap; | |
| 534 | +} | |
| 535 | + | |
| 536 | +/* Get next directory entry (internal) */ | |
| 537 | +static WIN32_FIND_DATAW* | |
| 538 | +dirent_next( | |
| 539 | + _WDIR *dirp) | |
| 540 | +{ | |
| 541 | + WIN32_FIND_DATAW *p; | |
| 542 | + | |
| 543 | + /* Get next directory entry */ | |
| 544 | + if (dirp->cached != 0) { | |
| 545 | + | |
| 546 | + /* A valid directory entry already in memory */ | |
| 547 | + p = &dirp->data; | |
| 548 | + dirp->cached = 0; | |
| 549 | + | |
| 550 | + } else if (dirp->handle != INVALID_HANDLE_VALUE) { | |
| 551 | + | |
| 552 | + /* Get the next directory entry from stream */ | |
| 553 | + if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { | |
| 554 | + /* Got a file */ | |
| 555 | + p = &dirp->data; | |
| 472 | 556 | } else { |
| 473 | - /* Failed to re-open directory: no directory entry in memory */ | |
| 474 | - dirp->cached = 0; | |
| 557 | + /* The very last entry has been processed or an error occured */ | |
| 558 | + FindClose (dirp->handle); | |
| 559 | + dirp->handle = INVALID_HANDLE_VALUE; | |
| 560 | + p = NULL; | |
| 475 | 561 | } |
| 562 | + | |
| 563 | + } else { | |
| 564 | + | |
| 565 | + /* End of directory stream reached */ | |
| 566 | + p = NULL; | |
| 567 | + | |
| 476 | 568 | } |
| 569 | + | |
| 570 | + return p; | |
| 477 | 571 | } |
| 478 | 572 | |
| 479 | 573 | /* |
| 480 | 574 | * Open directory stream using plain old C-string. |
| 481 | 575 | */ |
| @@ -482,58 +576,34 @@ | ||
| 482 | 576 | static DIR* |
| 483 | 577 | opendir( |
| 484 | 578 | const char *dirname) |
| 485 | 579 | { |
| 486 | 580 | struct DIR *dirp; |
| 487 | - errno_t error = 0; | |
| 581 | + int error; | |
| 488 | 582 | |
| 489 | 583 | /* Must have directory name */ |
| 490 | - if (dirname == NULL) { | |
| 491 | - DIRENT_SET_ERRNO (ENOENT); | |
| 584 | + if (dirname == NULL || dirname[0] == '\0') { | |
| 585 | + dirent_set_errno (ENOENT); | |
| 492 | 586 | return NULL; |
| 493 | 587 | } |
| 494 | 588 | |
| 495 | - /* Allocate memory for multi-byte string directory structures */ | |
| 589 | + /* Allocate memory for DIR structure */ | |
| 496 | 590 | dirp = (DIR*) malloc (sizeof (struct DIR)); |
| 497 | 591 | if (dirp) { |
| 498 | 592 | wchar_t wname[PATH_MAX + 1]; |
| 499 | 593 | size_t n; |
| 500 | 594 | |
| 501 | - /* | |
| 502 | - * Convert directory name to wide-character string. | |
| 503 | - * | |
| 504 | - * Be ware of the return schemantics of MultiByteToWideChar() -- | |
| 505 | - * the function basically returns the number of characters written to | |
| 506 | - * output buffer or zero if the conversion fails. However, the | |
| 507 | - * function does not necessarily zero-terminate the output | |
| 508 | - * buffer and may return 0xFFFD if the string contains invalid | |
| 509 | - * characters! | |
| 510 | - */ | |
| 511 | - n = MultiByteToWideChar( | |
| 512 | - CP_ACP, /* Input code page */ | |
| 513 | - MB_PRECOMPOSED, /* Conversion flags */ | |
| 514 | - dirname, /* Input string */ | |
| 515 | - -1, /* Length of input string */ | |
| 516 | - wname, /* Output buffer */ | |
| 517 | - PATH_MAX); /* Size of output buffer */ | |
| 518 | - if (n > 0 && n < PATH_MAX) { | |
| 519 | - | |
| 520 | - /* Zero-terminate output buffer */ | |
| 521 | - wname[n] = '\0'; | |
| 522 | - | |
| 523 | - /* Open directory stream with wide-character string file name */ | |
| 595 | + /* Convert directory name to wide-character string */ | |
| 596 | + error = dirent_mbstowcs_s( | |
| 597 | + &n, wname, PATH_MAX + 1, dirname, PATH_MAX); | |
| 598 | + if (!error) { | |
| 599 | + | |
| 600 | + /* Open directory stream using wide-character name */ | |
| 524 | 601 | dirp->wdirp = _wopendir (wname); |
| 525 | 602 | if (dirp->wdirp) { |
| 526 | - | |
| 527 | - /* Initialize directory structure */ | |
| 528 | - dirp->ent.d_name[0] = '\0'; | |
| 529 | - dirp->ent.d_namlen = 0; | |
| 530 | - dirp->ent.d_type = 0; | |
| 531 | - dirp->ent.d_ino = 0; | |
| 532 | - dirp->ent.d_reclen = 0; | |
| 533 | - | |
| 534 | - | |
| 603 | + /* Directory stream opened */ | |
| 604 | + error = 0; | |
| 535 | 605 | } else { |
| 536 | 606 | /* Failed to open directory stream */ |
| 537 | 607 | error = 1; |
| 538 | 608 | } |
| 539 | 609 | |
| @@ -562,95 +632,99 @@ | ||
| 562 | 632 | } |
| 563 | 633 | |
| 564 | 634 | /* |
| 565 | 635 | * Read next directory entry. |
| 566 | 636 | * |
| 567 | - * When working with console, please note that file names returned by | |
| 568 | - * readdir() are represented in the default ANSI code page while the | |
| 569 | - * console typically runs on another code page. Thus, non-ASCII characters | |
| 570 | - * will not usually display correctly. The problem can be fixed in two ways: | |
| 571 | - * (1) change the character set of console to 1252 using chcp utility and use | |
| 572 | - * Lucida Console font, or (2) always use _cprintf function when writing to | |
| 573 | - * console. The _cprinf() will re-encode ANSI strings to the console code | |
| 574 | - * page so non-ASCII characters will display correcly. | |
| 637 | + * When working with text consoles, please note that file names returned by | |
| 638 | + * readdir() are represented in the default ANSI code page while any output to | |
| 639 | + * console is typically formatted on another code page. Thus, non-ASCII | |
| 640 | + * characters in file names will not usually display correctly on console. The | |
| 641 | + * problem can be fixed in two ways: (1) change the character set of console | |
| 642 | + * to 1252 using chcp utility and use Lucida Console font, or (2) use | |
| 643 | + * _cprintf function when writing to console. The _cprinf() will re-encode | |
| 644 | + * ANSI strings to the console code page so many non-ASCII characters will | |
| 645 | + * display correcly. | |
| 575 | 646 | */ |
| 576 | 647 | static struct dirent* |
| 577 | 648 | readdir( |
| 578 | 649 | DIR *dirp) |
| 579 | 650 | { |
| 580 | - struct dirent *p; | |
| 581 | - struct _wdirent *wp; | |
| 651 | + WIN32_FIND_DATAW *datap; | |
| 652 | + struct dirent *entp; | |
| 582 | 653 | |
| 583 | - /* Read next directory entry using wide-character string functions */ | |
| 584 | - wp = _wreaddir (dirp->wdirp); | |
| 585 | - if (wp) { | |
| 654 | + /* Read next directory entry */ | |
| 655 | + datap = dirent_next (dirp->wdirp); | |
| 656 | + if (datap) { | |
| 586 | 657 | size_t n; |
| 658 | + int error; | |
| 659 | + | |
| 660 | + /* Attempt to convert file name to multi-byte string */ | |
| 661 | + error = dirent_wcstombs_s( | |
| 662 | + &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH); | |
| 587 | 663 | |
| 588 | 664 | /* |
| 589 | - * Convert file name to multi-byte string. | |
| 590 | - * | |
| 591 | - * Be ware of the return schemantics of WideCharToMultiByte() -- | |
| 592 | - * the function basically returns the number of bytes | |
| 593 | - * written to output buffer or zero if the conversion fails. | |
| 594 | - * However, the function does not necessarily zero-terminate the | |
| 595 | - * buffer and it may even return 0xFFFD the string contains | |
| 596 | - * invalid characters! | |
| 665 | + * If the file name cannot be represented by a multi-byte string, | |
| 666 | + * then attempt to use old 8+3 file name. This allows traditional | |
| 667 | + * Unix-code to access some file names despite of unicode | |
| 668 | + * characters, although file names may seem unfamiliar to the user. | |
| 669 | + * | |
| 670 | + * Be ware that the code below cannot come up with a short file | |
| 671 | + * name unless the file system provides one. At least | |
| 672 | + * VirtualBox shared folders fail to do this. | |
| 597 | 673 | */ |
| 598 | - n = WideCharToMultiByte( | |
| 599 | - CP_ACP, /* Output code page */ | |
| 600 | - 0, /* Conversion flags */ | |
| 601 | - wp->d_name, /* Input string */ | |
| 602 | - wp->d_namlen, /* Length of input string */ | |
| 603 | - dirp->ent.d_name, /* Output buffer */ | |
| 604 | - PATH_MAX, /* Size of output buffer */ | |
| 605 | - NULL, /* Replacement character */ | |
| 606 | - NULL); /* If chars were replaced */ | |
| 607 | - if (n > 0 && n < PATH_MAX) { | |
| 608 | - | |
| 609 | - /* Zero-terminate buffer */ | |
| 610 | - dirp->ent.d_name[n] = '\0'; | |
| 674 | + if (error && datap->cAlternateFileName[0] != '\0') { | |
| 675 | + error = dirent_wcstombs_s( | |
| 676 | + &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName, | |
| 677 | + sizeof (datap->cAlternateFileName) / | |
| 678 | + sizeof (datap->cAlternateFileName[0])); | |
| 679 | + } | |
| 680 | + | |
| 681 | + if (!error) { | |
| 682 | + DWORD attr; | |
| 611 | 683 | |
| 612 | 684 | /* Initialize directory entry for return */ |
| 613 | - p = &dirp->ent; | |
| 685 | + entp = &dirp->ent; | |
| 614 | 686 | |
| 615 | - /* Compute length */ | |
| 616 | - p->d_namlen = strnlen (dirp->ent.d_name, PATH_MAX); | |
| 687 | + /* Length of file name excluding zero terminator */ | |
| 688 | + entp->d_namlen = n - 1; | |
| 617 | 689 | |
| 618 | - /* Copy file attributes */ | |
| 619 | - p->d_type = wp->d_type; | |
| 690 | + /* File attributes */ | |
| 691 | + attr = datap->dwFileAttributes; | |
| 692 | + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { | |
| 693 | + entp->d_type = DT_CHR; | |
| 694 | + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { | |
| 695 | + entp->d_type = DT_DIR; | |
| 696 | + } else { | |
| 697 | + entp->d_type = DT_REG; | |
| 698 | + } | |
| 620 | 699 | |
| 621 | 700 | /* Reset dummy fields */ |
| 622 | - p->d_ino = 0; | |
| 623 | - p->d_reclen = sizeof (dirp->ent); | |
| 624 | - | |
| 701 | + entp->d_ino = 0; | |
| 702 | + entp->d_reclen = sizeof (struct dirent); | |
| 625 | 703 | |
| 626 | 704 | } else { |
| 627 | - | |
| 628 | 705 | /* |
| 629 | 706 | * Cannot convert file name to multi-byte string so construct |
| 630 | 707 | * an errornous directory entry and return that. Note that |
| 631 | 708 | * we cannot return NULL as that would stop the processing |
| 632 | 709 | * of directory entries completely. |
| 633 | 710 | */ |
| 634 | - p = &dirp->ent; | |
| 635 | - p->d_name[0] = '?'; | |
| 636 | - p->d_name[1] = '\0'; | |
| 637 | - p->d_namlen = 1; | |
| 638 | - p->d_type = DT_UNKNOWN; | |
| 639 | - p->d_ino = 0; | |
| 640 | - p->d_reclen = 0; | |
| 641 | - | |
| 711 | + entp = &dirp->ent; | |
| 712 | + entp->d_name[0] = '?'; | |
| 713 | + entp->d_name[1] = '\0'; | |
| 714 | + entp->d_namlen = 1; | |
| 715 | + entp->d_type = DT_UNKNOWN; | |
| 716 | + entp->d_ino = 0; | |
| 717 | + entp->d_reclen = 0; | |
| 642 | 718 | } |
| 643 | 719 | |
| 644 | 720 | } else { |
| 645 | - | |
| 646 | - /* End of directory stream */ | |
| 647 | - p = NULL; | |
| 648 | - | |
| 721 | + /* No more directory entries */ | |
| 722 | + entp = NULL; | |
| 649 | 723 | } |
| 650 | 724 | |
| 651 | - return p; | |
| 725 | + return entp; | |
| 652 | 726 | } |
| 653 | 727 | |
| 654 | 728 | /* |
| 655 | 729 | * Close directory stream. |
| 656 | 730 | */ |
| @@ -667,13 +741,15 @@ | ||
| 667 | 741 | |
| 668 | 742 | /* Release multi-byte character version */ |
| 669 | 743 | free (dirp); |
| 670 | 744 | |
| 671 | 745 | } else { |
| 746 | + | |
| 672 | 747 | /* Invalid directory stream */ |
| 673 | - DIRENT_SET_ERRNO (EBADF); | |
| 748 | + dirent_set_errno (EBADF); | |
| 674 | 749 | ok = /*failure*/-1; |
| 750 | + | |
| 675 | 751 | } |
| 676 | 752 | return ok; |
| 677 | 753 | } |
| 678 | 754 | |
| 679 | 755 | /* |
| @@ -684,12 +760,130 @@ | ||
| 684 | 760 | DIR* dirp) |
| 685 | 761 | { |
| 686 | 762 | /* Rewind wide-character string directory stream */ |
| 687 | 763 | _wrewinddir (dirp->wdirp); |
| 688 | 764 | } |
| 765 | + | |
| 766 | +/* Convert multi-byte string to wide character string */ | |
| 767 | +static int | |
| 768 | +dirent_mbstowcs_s( | |
| 769 | + size_t *pReturnValue, | |
| 770 | + wchar_t *wcstr, | |
| 771 | + size_t sizeInWords, | |
| 772 | + const char *mbstr, | |
| 773 | + size_t count) | |
| 774 | +{ | |
| 775 | + int error; | |
| 776 | + | |
| 777 | +#if defined(_MSC_VER) && _MSC_VER >= 1400 | |
| 778 | + | |
| 779 | + /* Microsoft Visual Studio 2005 or later */ | |
| 780 | + error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); | |
| 781 | + | |
| 782 | +#else | |
| 783 | + | |
| 784 | + /* Older Visual Studio or non-Microsoft compiler */ | |
| 785 | + size_t n; | |
| 786 | + | |
| 787 | + /* Convert to wide-character string */ | |
| 788 | + n = mbstowcs (wcstr, mbstr, count); | |
| 789 | + if (n < sizeInWords) { | |
| 790 | + | |
| 791 | + /* Zero-terminate output buffer */ | |
| 792 | + if (wcstr) { | |
| 793 | + wcstr[n] = 0; | |
| 794 | + } | |
| 795 | + | |
| 796 | + /* Length of resuting multi-byte string WITH zero terminator */ | |
| 797 | + if (pReturnValue) { | |
| 798 | + *pReturnValue = n + 1; | |
| 799 | + } | |
| 800 | + | |
| 801 | + /* Success */ | |
| 802 | + error = 0; | |
| 803 | + | |
| 804 | + } else { | |
| 805 | + | |
| 806 | + /* Could not convert string */ | |
| 807 | + error = 1; | |
| 808 | + | |
| 809 | + } | |
| 810 | + | |
| 811 | +#endif | |
| 812 | + | |
| 813 | + return error; | |
| 814 | +} | |
| 815 | + | |
| 816 | +/* Convert wide-character string to multi-byte string */ | |
| 817 | +static int | |
| 818 | +dirent_wcstombs_s( | |
| 819 | + size_t *pReturnValue, | |
| 820 | + char *mbstr, | |
| 821 | + size_t sizeInBytes, | |
| 822 | + const wchar_t *wcstr, | |
| 823 | + size_t count) | |
| 824 | +{ | |
| 825 | + int error; | |
| 826 | + | |
| 827 | +#if defined(_MSC_VER) && _MSC_VER >= 1400 | |
| 828 | + | |
| 829 | + /* Microsoft Visual Studio 2005 or later */ | |
| 830 | + error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); | |
| 831 | + | |
| 832 | +#else | |
| 833 | + | |
| 834 | + /* Older Visual Studio or non-Microsoft compiler */ | |
| 835 | + size_t n; | |
| 836 | + | |
| 837 | + /* Convert to multi-byte string */ | |
| 838 | + n = wcstombs (mbstr, wcstr, count); | |
| 839 | + if (n < sizeInBytes) { | |
| 840 | + | |
| 841 | + /* Zero-terminate output buffer */ | |
| 842 | + if (mbstr) { | |
| 843 | + mbstr[n] = '\0'; | |
| 844 | + } | |
| 845 | + | |
| 846 | + /* Lenght of resulting multi-bytes string WITH zero-terminator */ | |
| 847 | + if (pReturnValue) { | |
| 848 | + *pReturnValue = n + 1; | |
| 849 | + } | |
| 850 | + | |
| 851 | + /* Success */ | |
| 852 | + error = 0; | |
| 853 | + | |
| 854 | + } else { | |
| 855 | + | |
| 856 | + /* Cannot convert string */ | |
| 857 | + error = 1; | |
| 858 | + | |
| 859 | + } | |
| 860 | + | |
| 861 | +#endif | |
| 862 | + | |
| 863 | + return error; | |
| 864 | +} | |
| 865 | + | |
| 866 | +/* Set errno variable */ | |
| 867 | +static void | |
| 868 | +dirent_set_errno( | |
| 869 | + int error) | |
| 870 | +{ | |
| 871 | +#if defined(_MSC_VER) | |
| 872 | + | |
| 873 | + /* Microsoft Visual Studio */ | |
| 874 | + _set_errno (error); | |
| 875 | + | |
| 876 | +#else | |
| 877 | + | |
| 878 | + /* Non-Microsoft compiler */ | |
| 879 | + errno = error; | |
| 880 | + | |
| 881 | +#endif | |
| 882 | +} | |
| 689 | 883 | |
| 690 | 884 | |
| 691 | 885 | #ifdef __cplusplus |
| 692 | 886 | } |
| 693 | 887 | #endif |
| 694 | 888 | #endif /*DIRENT_H*/ |
| 695 | 889 | |
| 696 | 890 |
| --- win/include/dirent.h | |
| +++ win/include/dirent.h | |
| @@ -20,21 +20,24 @@ | |
| 20 | * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 23 | * OTHER DEALINGS IN THE SOFTWARE. |
| 24 | * |
| 25 | * |
| 26 | * Version 1.12.1, Oct 1 2012, Toni Ronkko |
| 27 | * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with |
| 28 | * capital W) in order to maintain compatibility with MingW. |
| 29 | * |
| 30 | * Version 1.12, Sep 30 2012, Toni Ronkko |
| 31 | * Define PATH_MAX and NAME_MAX. |
| 32 | * |
| 33 | * Added wide-character variants _wDIR, _wdirent, _wopendir(), |
| 34 | * _wreaddir(), _wclosedir() and _wrewinddir(). Thanks to Edgar Buerkle |
| 35 | * and Jan Nijtmans for ideas and code. |
| 36 | * |
| 37 | * Do not include windows.h. This allows dirent.h to be integrated more |
| 38 | * easily into programs using winsock. Thanks to Fernando Azaldegui. |
| 39 | * |
| 40 | * Version 1.11, Mar 15, 2011, Toni Ronkko |
| @@ -88,48 +91,72 @@ | |
| 88 | *****************************************************************************/ |
| 89 | #ifndef DIRENT_H |
| 90 | #define DIRENT_H |
| 91 | |
| 92 | #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86) |
| 93 | #define _X86_ |
| 94 | #endif |
| 95 | #include <stdio.h> |
| 96 | #include <stdarg.h> |
| 97 | #include <windef.h> |
| 98 | #include <winbase.h> |
| 99 | #include <wchar.h> |
| 100 | #include <winnls.h> |
| 101 | #include <string.h> |
| 102 | #include <stdlib.h> |
| 103 | #include <sys/types.h> |
| 104 | #include <sys/stat.h> |
| 105 | #include <errno.h> |
| 106 | |
| 107 | /* Windows 8 wide-character string functions */ |
| 108 | #if (_WIN32_WINNT >= 0x0602) |
| 109 | # include <stringapiset.h> |
| 110 | #endif |
| 111 | |
| 112 | /* Entries missing from MSVC 6.0 */ |
| 113 | #if !defined(FILE_ATTRIBUTE_DEVICE) |
| 114 | # define FILE_ATTRIBUTE_DEVICE 0x40 |
| 115 | #endif |
| 116 | |
| 117 | /* File type and permission flags for stat() */ |
| 118 | #if defined(_MSC_VER) && !defined(S_IREAD) |
| 119 | # define S_IFMT _S_IFMT /* File type mask */ |
| 120 | # define S_IFDIR _S_IFDIR /* Directory */ |
| 121 | # define S_IFCHR _S_IFCHR /* Character device */ |
| 122 | # define S_IFFIFO _S_IFFIFO /* Pipe */ |
| 123 | # define S_IFREG _S_IFREG /* Regular file */ |
| 124 | # define S_IREAD _S_IREAD /* Read permission */ |
| 125 | # define S_IWRITE _S_IWRITE /* Write permission */ |
| 126 | # define S_IEXEC _S_IEXEC /* Execute permission */ |
| 127 | #endif |
| 128 | #define S_IFBLK 0 /* Block device */ |
| 129 | #define S_IFLNK 0 /* Link */ |
| 130 | #define S_IFSOCK 0 /* Socket */ |
| 131 | |
| 132 | #if defined(_MSC_VER) |
| 133 | # define S_IRUSR S_IREAD /* Read user */ |
| 134 | # define S_IWUSR S_IWRITE /* Write user */ |
| 135 | # define S_IXUSR 0 /* Execute user */ |
| @@ -139,18 +166,26 @@ | |
| 139 | # define S_IROTH 0 /* Read others */ |
| 140 | # define S_IWOTH 0 /* Write others */ |
| 141 | # define S_IXOTH 0 /* Execute others */ |
| 142 | #endif |
| 143 | |
| 144 | /* Indicates that d_type field is available in dirent structure */ |
| 145 | #define _DIRENT_HAVE_D_TYPE |
| 146 | |
| 147 | /* File type flags for d_type */ |
| 148 | #define DT_UNKNOWN 0 |
| 149 | #define DT_REG S_IFREG |
| 150 | #define DT_DIR S_IFDIR |
| 151 | #define DT_FIFO S_IFFIFO |
| 152 | #define DT_SOCK S_IFSOCK |
| 153 | #define DT_CHR S_IFCHR |
| 154 | #define DT_BLK S_IFBLK |
| 155 | |
| 156 | /* Macros for converting between st_mode and d_type */ |
| @@ -161,41 +196,31 @@ | |
| 161 | * File type macros. Note that block devices, sockets and links cannot be |
| 162 | * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are |
| 163 | * only defined for compatibility. These macros should always return false |
| 164 | * on Windows. |
| 165 | */ |
| 166 | #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO) |
| 167 | #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) |
| 168 | #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) |
| 169 | #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) |
| 170 | #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) |
| 171 | #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) |
| 172 | #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) |
| 173 | |
| 174 | /* For compatiblity with Unix */ |
| 175 | #if !defined(PATH_MAX) |
| 176 | # define PATH_MAX MAX_PATH |
| 177 | #endif |
| 178 | #if !defined(FILENAME_MAX) |
| 179 | # define FILENAME_MAX MAX_PATH |
| 180 | #endif |
| 181 | #if !defined(NAME_MAX) |
| 182 | # define NAME_MAX FILENAME_MAX |
| 183 | #endif |
| 184 | |
| 185 | /* Set errno variable */ |
| 186 | #if defined(_MSC_VER) |
| 187 | #define DIRENT_SET_ERRNO(x) _set_errno (x) |
| 188 | #else |
| 189 | #define DIRENT_SET_ERRNO(x) (errno = (x)) |
| 190 | #endif |
| 191 | |
| 192 | #ifdef __cplusplus |
| 193 | extern "C" { |
| 194 | #endif |
| 195 | |
| 196 | /* Wide-character versions */ |
| 197 | struct _wdirent { |
| 198 | long d_ino; /* Always zero */ |
| 199 | unsigned short d_reclen; /* Structure size */ |
| 200 | size_t d_namlen; /* Length of name without \0 */ |
| 201 | int d_type; /* File type */ |
| @@ -203,11 +228,11 @@ | |
| 203 | }; |
| 204 | typedef struct _wdirent _wdirent; |
| 205 | |
| 206 | struct _WDIR { |
| 207 | struct _wdirent ent; /* Current directory entry */ |
| 208 | WIN32_FIND_DATAW find_data; /* Private file data */ |
| 209 | int cached; /* True if data is valid */ |
| 210 | HANDLE handle; /* Win32 search handle */ |
| 211 | wchar_t *patt; /* Initial directory name */ |
| 212 | }; |
| 213 | typedef struct _WDIR _WDIR; |
| @@ -214,10 +239,11 @@ | |
| 214 | |
| 215 | static _WDIR *_wopendir (const wchar_t *dirname); |
| 216 | static struct _wdirent *_wreaddir (_WDIR *dirp); |
| 217 | static int _wclosedir (_WDIR *dirp); |
| 218 | static void _wrewinddir (_WDIR* dirp); |
| 219 | |
| 220 | /* For compatibility with Symbian */ |
| 221 | #define wdirent _wdirent |
| 222 | #define WDIR _WDIR |
| 223 | #define wopendir _wopendir |
| @@ -246,10 +272,30 @@ | |
| 246 | static struct dirent *readdir (DIR *dirp); |
| 247 | static int closedir (DIR *dirp); |
| 248 | static void rewinddir (DIR* dirp); |
| 249 | |
| 250 | |
| 251 | /* |
| 252 | * Open directory stream DIRNAME for read and return a pointer to the |
| 253 | * internal working area that is used to retrieve individual directory |
| 254 | * entries. |
| 255 | */ |
| @@ -256,31 +302,38 @@ | |
| 256 | static _WDIR* |
| 257 | _wopendir( |
| 258 | const wchar_t *dirname) |
| 259 | { |
| 260 | _WDIR *dirp = NULL; |
| 261 | int error = 0; |
| 262 | |
| 263 | /* Allocate new _WDIR structure */ |
| 264 | dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); |
| 265 | if (dirp != NULL) { |
| 266 | DWORD n; |
| 267 | |
| 268 | /* Reset _WDIR structure */ |
| 269 | dirp->handle = INVALID_HANDLE_VALUE; |
| 270 | dirp->patt = NULL; |
| 271 | |
| 272 | /* Compute the length of full path plus zero terminator */ |
| 273 | n = GetFullPathNameW (dirname, 0, NULL, NULL); |
| 274 | |
| 275 | /* Allocate room for full path and search patterns */ |
| 276 | dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); |
| 277 | if (dirp->patt) { |
| 278 | |
| 279 | /* |
| 280 | * Convert relative directory name to an absolute one. This |
| 281 | * allows rewinddir() to function correctly when the current |
| 282 | * working directory is changed between opendir() and rewinddir(). |
| 283 | */ |
| 284 | n = GetFullPathNameW (dirname, n, dirp->patt, NULL); |
| 285 | if (n > 0) { |
| 286 | wchar_t *p; |
| @@ -303,25 +356,22 @@ | |
| 303 | } |
| 304 | *p++ = '*'; |
| 305 | *p = '\0'; |
| 306 | |
| 307 | /* Open directory stream and retrieve the first entry */ |
| 308 | dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data); |
| 309 | if (dirp->handle != INVALID_HANDLE_VALUE) { |
| 310 | |
| 311 | /* Directory entry is now waiting in memory */ |
| 312 | dirp->cached = 1; |
| 313 | |
| 314 | } else { |
| 315 | /* Search pattern is not a directory name? */ |
| 316 | DIRENT_SET_ERRNO (ENOENT); |
| 317 | error = 1; |
| 318 | } |
| 319 | |
| 320 | } else { |
| 321 | /* Cannot convert directory name to wide character string */ |
| 322 | DIRENT_SET_ERRNO (ENOENT); |
| 323 | error = 1; |
| 324 | } |
| 325 | |
| 326 | } else { |
| 327 | /* Cannot allocate memory for search pattern */ |
| @@ -350,70 +400,59 @@ | |
| 350 | */ |
| 351 | static struct _wdirent* |
| 352 | _wreaddir( |
| 353 | _WDIR *dirp) |
| 354 | { |
| 355 | DWORD attr; |
| 356 | errno_t error; |
| 357 | |
| 358 | /* Get next directory entry */ |
| 359 | if (dirp->cached != 0) { |
| 360 | /* A valid directory entry already in memory */ |
| 361 | dirp->cached = 0; |
| 362 | } else { |
| 363 | /* Get the next directory entry from stream */ |
| 364 | if (dirp->handle == INVALID_HANDLE_VALUE) { |
| 365 | return NULL; |
| 366 | } |
| 367 | if (FindNextFileW (dirp->handle, &dirp->find_data) == FALSE) { |
| 368 | /* The very last entry has been processed or an error occured */ |
| 369 | FindClose (dirp->handle); |
| 370 | dirp->handle = INVALID_HANDLE_VALUE; |
| 371 | return NULL; |
| 372 | } |
| 373 | } |
| 374 | |
| 375 | /* Copy file name as a wide-character string */ |
| 376 | error = wcsncpy_s( |
| 377 | dirp->ent.d_name, /* Destination string */ |
| 378 | PATH_MAX, /* Size of dest in words */ |
| 379 | dirp->find_data.cFileName, /* Source string */ |
| 380 | PATH_MAX + 1); /* Max # of chars to copy */ |
| 381 | if (!error) { |
| 382 | |
| 383 | /* Compute the length of name */ |
| 384 | dirp->ent.d_namlen = wcsnlen (dirp->ent.d_name, PATH_MAX); |
| 385 | |
| 386 | /* Determine file type */ |
| 387 | attr = dirp->find_data.dwFileAttributes; |
| 388 | if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { |
| 389 | dirp->ent.d_type = DT_CHR; |
| 390 | } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 391 | dirp->ent.d_type = DT_DIR; |
| 392 | } else { |
| 393 | dirp->ent.d_type = DT_REG; |
| 394 | } |
| 395 | |
| 396 | /* Reset dummy fields */ |
| 397 | dirp->ent.d_ino = 0; |
| 398 | dirp->ent.d_reclen = sizeof (dirp->ent); |
| 399 | |
| 400 | } else { |
| 401 | |
| 402 | /* |
| 403 | * Cannot copy file name from find_data to ent. Construct a |
| 404 | * dummy _wdirent structure to pass error to caller. |
| 405 | */ |
| 406 | dirp->ent.d_name[0] = '?'; |
| 407 | dirp->ent.d_name[1] = '\0'; |
| 408 | dirp->ent.d_namlen = 1; |
| 409 | dirp->ent.d_type = DT_UNKNOWN; |
| 410 | dirp->ent.d_ino = 0; |
| 411 | dirp->ent.d_reclen = 0; |
| 412 | } |
| 413 | |
| 414 | return &dirp->ent; |
| 415 | } |
| 416 | |
| 417 | /* |
| 418 | * Close directory stream opened by opendir() function. This invalidates the |
| 419 | * DIR structure as well as any directory entry read previously by |
| @@ -442,11 +481,11 @@ | |
| 442 | free (dirp); |
| 443 | ok = /*success*/0; |
| 444 | |
| 445 | } else { |
| 446 | /* Invalid directory stream */ |
| 447 | DIRENT_SET_ERRNO (EBADF); |
| 448 | ok = /*failure*/-1; |
| 449 | } |
| 450 | return ok; |
| 451 | } |
| 452 | |
| @@ -456,26 +495,81 @@ | |
| 456 | */ |
| 457 | static void |
| 458 | _wrewinddir( |
| 459 | _WDIR* dirp) |
| 460 | { |
| 461 | if (dirp != NULL) { |
| 462 | /* release search handle */ |
| 463 | if (dirp->handle != INVALID_HANDLE_VALUE) { |
| 464 | FindClose (dirp->handle); |
| 465 | } |
| 466 | |
| 467 | /* Open new search handle and retrieve the first directory entry */ |
| 468 | dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data); |
| 469 | if (dirp->handle != INVALID_HANDLE_VALUE) { |
| 470 | /* a directory entry is now waiting in memory */ |
| 471 | dirp->cached = 1; |
| 472 | } else { |
| 473 | /* Failed to re-open directory: no directory entry in memory */ |
| 474 | dirp->cached = 0; |
| 475 | } |
| 476 | } |
| 477 | } |
| 478 | |
| 479 | /* |
| 480 | * Open directory stream using plain old C-string. |
| 481 | */ |
| @@ -482,58 +576,34 @@ | |
| 482 | static DIR* |
| 483 | opendir( |
| 484 | const char *dirname) |
| 485 | { |
| 486 | struct DIR *dirp; |
| 487 | errno_t error = 0; |
| 488 | |
| 489 | /* Must have directory name */ |
| 490 | if (dirname == NULL) { |
| 491 | DIRENT_SET_ERRNO (ENOENT); |
| 492 | return NULL; |
| 493 | } |
| 494 | |
| 495 | /* Allocate memory for multi-byte string directory structures */ |
| 496 | dirp = (DIR*) malloc (sizeof (struct DIR)); |
| 497 | if (dirp) { |
| 498 | wchar_t wname[PATH_MAX + 1]; |
| 499 | size_t n; |
| 500 | |
| 501 | /* |
| 502 | * Convert directory name to wide-character string. |
| 503 | * |
| 504 | * Be ware of the return schemantics of MultiByteToWideChar() -- |
| 505 | * the function basically returns the number of characters written to |
| 506 | * output buffer or zero if the conversion fails. However, the |
| 507 | * function does not necessarily zero-terminate the output |
| 508 | * buffer and may return 0xFFFD if the string contains invalid |
| 509 | * characters! |
| 510 | */ |
| 511 | n = MultiByteToWideChar( |
| 512 | CP_ACP, /* Input code page */ |
| 513 | MB_PRECOMPOSED, /* Conversion flags */ |
| 514 | dirname, /* Input string */ |
| 515 | -1, /* Length of input string */ |
| 516 | wname, /* Output buffer */ |
| 517 | PATH_MAX); /* Size of output buffer */ |
| 518 | if (n > 0 && n < PATH_MAX) { |
| 519 | |
| 520 | /* Zero-terminate output buffer */ |
| 521 | wname[n] = '\0'; |
| 522 | |
| 523 | /* Open directory stream with wide-character string file name */ |
| 524 | dirp->wdirp = _wopendir (wname); |
| 525 | if (dirp->wdirp) { |
| 526 | |
| 527 | /* Initialize directory structure */ |
| 528 | dirp->ent.d_name[0] = '\0'; |
| 529 | dirp->ent.d_namlen = 0; |
| 530 | dirp->ent.d_type = 0; |
| 531 | dirp->ent.d_ino = 0; |
| 532 | dirp->ent.d_reclen = 0; |
| 533 | |
| 534 | |
| 535 | } else { |
| 536 | /* Failed to open directory stream */ |
| 537 | error = 1; |
| 538 | } |
| 539 | |
| @@ -562,95 +632,99 @@ | |
| 562 | } |
| 563 | |
| 564 | /* |
| 565 | * Read next directory entry. |
| 566 | * |
| 567 | * When working with console, please note that file names returned by |
| 568 | * readdir() are represented in the default ANSI code page while the |
| 569 | * console typically runs on another code page. Thus, non-ASCII characters |
| 570 | * will not usually display correctly. The problem can be fixed in two ways: |
| 571 | * (1) change the character set of console to 1252 using chcp utility and use |
| 572 | * Lucida Console font, or (2) always use _cprintf function when writing to |
| 573 | * console. The _cprinf() will re-encode ANSI strings to the console code |
| 574 | * page so non-ASCII characters will display correcly. |
| 575 | */ |
| 576 | static struct dirent* |
| 577 | readdir( |
| 578 | DIR *dirp) |
| 579 | { |
| 580 | struct dirent *p; |
| 581 | struct _wdirent *wp; |
| 582 | |
| 583 | /* Read next directory entry using wide-character string functions */ |
| 584 | wp = _wreaddir (dirp->wdirp); |
| 585 | if (wp) { |
| 586 | size_t n; |
| 587 | |
| 588 | /* |
| 589 | * Convert file name to multi-byte string. |
| 590 | * |
| 591 | * Be ware of the return schemantics of WideCharToMultiByte() -- |
| 592 | * the function basically returns the number of bytes |
| 593 | * written to output buffer or zero if the conversion fails. |
| 594 | * However, the function does not necessarily zero-terminate the |
| 595 | * buffer and it may even return 0xFFFD the string contains |
| 596 | * invalid characters! |
| 597 | */ |
| 598 | n = WideCharToMultiByte( |
| 599 | CP_ACP, /* Output code page */ |
| 600 | 0, /* Conversion flags */ |
| 601 | wp->d_name, /* Input string */ |
| 602 | wp->d_namlen, /* Length of input string */ |
| 603 | dirp->ent.d_name, /* Output buffer */ |
| 604 | PATH_MAX, /* Size of output buffer */ |
| 605 | NULL, /* Replacement character */ |
| 606 | NULL); /* If chars were replaced */ |
| 607 | if (n > 0 && n < PATH_MAX) { |
| 608 | |
| 609 | /* Zero-terminate buffer */ |
| 610 | dirp->ent.d_name[n] = '\0'; |
| 611 | |
| 612 | /* Initialize directory entry for return */ |
| 613 | p = &dirp->ent; |
| 614 | |
| 615 | /* Compute length */ |
| 616 | p->d_namlen = strnlen (dirp->ent.d_name, PATH_MAX); |
| 617 | |
| 618 | /* Copy file attributes */ |
| 619 | p->d_type = wp->d_type; |
| 620 | |
| 621 | /* Reset dummy fields */ |
| 622 | p->d_ino = 0; |
| 623 | p->d_reclen = sizeof (dirp->ent); |
| 624 | |
| 625 | |
| 626 | } else { |
| 627 | |
| 628 | /* |
| 629 | * Cannot convert file name to multi-byte string so construct |
| 630 | * an errornous directory entry and return that. Note that |
| 631 | * we cannot return NULL as that would stop the processing |
| 632 | * of directory entries completely. |
| 633 | */ |
| 634 | p = &dirp->ent; |
| 635 | p->d_name[0] = '?'; |
| 636 | p->d_name[1] = '\0'; |
| 637 | p->d_namlen = 1; |
| 638 | p->d_type = DT_UNKNOWN; |
| 639 | p->d_ino = 0; |
| 640 | p->d_reclen = 0; |
| 641 | |
| 642 | } |
| 643 | |
| 644 | } else { |
| 645 | |
| 646 | /* End of directory stream */ |
| 647 | p = NULL; |
| 648 | |
| 649 | } |
| 650 | |
| 651 | return p; |
| 652 | } |
| 653 | |
| 654 | /* |
| 655 | * Close directory stream. |
| 656 | */ |
| @@ -667,13 +741,15 @@ | |
| 667 | |
| 668 | /* Release multi-byte character version */ |
| 669 | free (dirp); |
| 670 | |
| 671 | } else { |
| 672 | /* Invalid directory stream */ |
| 673 | DIRENT_SET_ERRNO (EBADF); |
| 674 | ok = /*failure*/-1; |
| 675 | } |
| 676 | return ok; |
| 677 | } |
| 678 | |
| 679 | /* |
| @@ -684,12 +760,130 @@ | |
| 684 | DIR* dirp) |
| 685 | { |
| 686 | /* Rewind wide-character string directory stream */ |
| 687 | _wrewinddir (dirp->wdirp); |
| 688 | } |
| 689 | |
| 690 | |
| 691 | #ifdef __cplusplus |
| 692 | } |
| 693 | #endif |
| 694 | #endif /*DIRENT_H*/ |
| 695 | |
| 696 |
| --- win/include/dirent.h | |
| +++ win/include/dirent.h | |
| @@ -20,21 +20,24 @@ | |
| 20 | * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 23 | * OTHER DEALINGS IN THE SOFTWARE. |
| 24 | * |
| 25 | * |
| 26 | * Version 1.13, Dec 12 2012, Toni Ronkko |
| 27 | * Use traditional 8+3 file name if the name cannot be represented in the |
| 28 | * default ANSI code page. Now compiles again with MSVC 6.0. Thanks to |
| 29 | * Konstantin Khomoutov for testing. |
| 30 | * |
| 31 | * Version 1.12.1, Oct 1 2012, Toni Ronkko |
| 32 | * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with |
| 33 | * capital W) in order to maintain compatibility with MingW. |
| 34 | * |
| 35 | * Version 1.12, Sep 30 2012, Toni Ronkko |
| 36 | * Define PATH_MAX and NAME_MAX. Added wide-character variants _wDIR, |
| 37 | * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir(). |
| 38 | * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code. |
| 39 | * |
| 40 | * Do not include windows.h. This allows dirent.h to be integrated more |
| 41 | * easily into programs using winsock. Thanks to Fernando Azaldegui. |
| 42 | * |
| 43 | * Version 1.11, Mar 15, 2011, Toni Ronkko |
| @@ -88,48 +91,72 @@ | |
| 91 | *****************************************************************************/ |
| 92 | #ifndef DIRENT_H |
| 93 | #define DIRENT_H |
| 94 | |
| 95 | #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86) |
| 96 | # define _X86_ |
| 97 | #endif |
| 98 | #include <stdio.h> |
| 99 | #include <stdarg.h> |
| 100 | #include <windef.h> |
| 101 | #include <winbase.h> |
| 102 | #include <wchar.h> |
| 103 | #include <string.h> |
| 104 | #include <stdlib.h> |
| 105 | #include <malloc.h> |
| 106 | #include <sys/types.h> |
| 107 | #include <sys/stat.h> |
| 108 | #include <errno.h> |
| 109 | |
| 110 | /* Indicates that d_type field is available in dirent structure */ |
| 111 | #define _DIRENT_HAVE_D_TYPE |
| 112 | |
| 113 | /* Indicates that d_namlen field is available in dirent structure */ |
| 114 | #define _DIRENT_HAVE_D_NAMLEN |
| 115 | |
| 116 | /* Entries missing from MSVC 6.0 */ |
| 117 | #if !defined(FILE_ATTRIBUTE_DEVICE) |
| 118 | # define FILE_ATTRIBUTE_DEVICE 0x40 |
| 119 | #endif |
| 120 | |
| 121 | /* File type and permission flags for stat() */ |
| 122 | #if !defined(S_IFMT) |
| 123 | # define S_IFMT _S_IFMT /* File type mask */ |
| 124 | #endif |
| 125 | #if !defined(S_IFDIR) |
| 126 | # define S_IFDIR _S_IFDIR /* Directory */ |
| 127 | #endif |
| 128 | #if !defined(S_IFCHR) |
| 129 | # define S_IFCHR _S_IFCHR /* Character device */ |
| 130 | #endif |
| 131 | #if !defined(S_IFFIFO) |
| 132 | # define S_IFFIFO _S_IFFIFO /* Pipe */ |
| 133 | #endif |
| 134 | #if !defined(S_IFREG) |
| 135 | # define S_IFREG _S_IFREG /* Regular file */ |
| 136 | #endif |
| 137 | #if !defined(S_IREAD) |
| 138 | # define S_IREAD _S_IREAD /* Read permission */ |
| 139 | #endif |
| 140 | #if !defined(S_IWRITE) |
| 141 | # define S_IWRITE _S_IWRITE /* Write permission */ |
| 142 | #endif |
| 143 | #if !defined(S_IEXEC) |
| 144 | # define S_IEXEC _S_IEXEC /* Execute permission */ |
| 145 | #endif |
| 146 | #if !defined(S_IFIFO) |
| 147 | # define S_IFIFO _S_IFIFO /* Pipe */ |
| 148 | #endif |
| 149 | #if !defined(S_IFBLK) |
| 150 | # define S_IFBLK 0 /* Block device */ |
| 151 | #endif |
| 152 | #if !defined(S_IFLNK) |
| 153 | # define S_IFLNK 0 /* Link */ |
| 154 | #endif |
| 155 | #if !defined(S_IFSOCK) |
| 156 | # define S_IFSOCK 0 /* Socket */ |
| 157 | #endif |
| 158 | |
| 159 | #if defined(_MSC_VER) |
| 160 | # define S_IRUSR S_IREAD /* Read user */ |
| 161 | # define S_IWUSR S_IWRITE /* Write user */ |
| 162 | # define S_IXUSR 0 /* Execute user */ |
| @@ -139,18 +166,26 @@ | |
| 166 | # define S_IROTH 0 /* Read others */ |
| 167 | # define S_IWOTH 0 /* Write others */ |
| 168 | # define S_IXOTH 0 /* Execute others */ |
| 169 | #endif |
| 170 | |
| 171 | /* Maximum length of file name */ |
| 172 | #if !defined(PATH_MAX) |
| 173 | # define PATH_MAX MAX_PATH |
| 174 | #endif |
| 175 | #if !defined(FILENAME_MAX) |
| 176 | # define FILENAME_MAX MAX_PATH |
| 177 | #endif |
| 178 | #if !defined(NAME_MAX) |
| 179 | # define NAME_MAX FILENAME_MAX |
| 180 | #endif |
| 181 | |
| 182 | /* File type flags for d_type */ |
| 183 | #define DT_UNKNOWN 0 |
| 184 | #define DT_REG S_IFREG |
| 185 | #define DT_DIR S_IFDIR |
| 186 | #define DT_FIFO S_IFIFO |
| 187 | #define DT_SOCK S_IFSOCK |
| 188 | #define DT_CHR S_IFCHR |
| 189 | #define DT_BLK S_IFBLK |
| 190 | |
| 191 | /* Macros for converting between st_mode and d_type */ |
| @@ -161,41 +196,31 @@ | |
| 196 | * File type macros. Note that block devices, sockets and links cannot be |
| 197 | * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are |
| 198 | * only defined for compatibility. These macros should always return false |
| 199 | * on Windows. |
| 200 | */ |
| 201 | #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) |
| 202 | #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) |
| 203 | #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) |
| 204 | #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) |
| 205 | #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) |
| 206 | #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) |
| 207 | #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) |
| 208 | |
| 209 | /* Return the exact length of d_namlen without zero terminator */ |
| 210 | #define _D_EXACT_NAMLEN(p) ((p)->d_namlen) |
| 211 | |
| 212 | /* Return number of bytes needed to store d_namlen */ |
| 213 | #define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1) |
| 214 | |
| 215 | |
| 216 | #ifdef __cplusplus |
| 217 | extern "C" { |
| 218 | #endif |
| 219 | |
| 220 | |
| 221 | /* Wide-character version */ |
| 222 | struct _wdirent { |
| 223 | long d_ino; /* Always zero */ |
| 224 | unsigned short d_reclen; /* Structure size */ |
| 225 | size_t d_namlen; /* Length of name without \0 */ |
| 226 | int d_type; /* File type */ |
| @@ -203,11 +228,11 @@ | |
| 228 | }; |
| 229 | typedef struct _wdirent _wdirent; |
| 230 | |
| 231 | struct _WDIR { |
| 232 | struct _wdirent ent; /* Current directory entry */ |
| 233 | WIN32_FIND_DATAW data; /* Private file data */ |
| 234 | int cached; /* True if data is valid */ |
| 235 | HANDLE handle; /* Win32 search handle */ |
| 236 | wchar_t *patt; /* Initial directory name */ |
| 237 | }; |
| 238 | typedef struct _WDIR _WDIR; |
| @@ -214,10 +239,11 @@ | |
| 239 | |
| 240 | static _WDIR *_wopendir (const wchar_t *dirname); |
| 241 | static struct _wdirent *_wreaddir (_WDIR *dirp); |
| 242 | static int _wclosedir (_WDIR *dirp); |
| 243 | static void _wrewinddir (_WDIR* dirp); |
| 244 | |
| 245 | |
| 246 | /* For compatibility with Symbian */ |
| 247 | #define wdirent _wdirent |
| 248 | #define WDIR _WDIR |
| 249 | #define wopendir _wopendir |
| @@ -246,10 +272,30 @@ | |
| 272 | static struct dirent *readdir (DIR *dirp); |
| 273 | static int closedir (DIR *dirp); |
| 274 | static void rewinddir (DIR* dirp); |
| 275 | |
| 276 | |
| 277 | /* Internal utility functions */ |
| 278 | static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); |
| 279 | static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); |
| 280 | |
| 281 | static int dirent_mbstowcs_s( |
| 282 | size_t *pReturnValue, |
| 283 | wchar_t *wcstr, |
| 284 | size_t sizeInWords, |
| 285 | const char *mbstr, |
| 286 | size_t count); |
| 287 | |
| 288 | static int dirent_wcstombs_s( |
| 289 | size_t *pReturnValue, |
| 290 | char *mbstr, |
| 291 | size_t sizeInBytes, |
| 292 | const wchar_t *wcstr, |
| 293 | size_t count); |
| 294 | |
| 295 | static void dirent_set_errno (int error); |
| 296 | |
| 297 | /* |
| 298 | * Open directory stream DIRNAME for read and return a pointer to the |
| 299 | * internal working area that is used to retrieve individual directory |
| 300 | * entries. |
| 301 | */ |
| @@ -256,31 +302,38 @@ | |
| 302 | static _WDIR* |
| 303 | _wopendir( |
| 304 | const wchar_t *dirname) |
| 305 | { |
| 306 | _WDIR *dirp = NULL; |
| 307 | int error; |
| 308 | |
| 309 | /* Must have directory name */ |
| 310 | if (dirname == NULL || dirname[0] == '\0') { |
| 311 | dirent_set_errno (ENOENT); |
| 312 | return NULL; |
| 313 | } |
| 314 | |
| 315 | /* Allocate new _WDIR structure */ |
| 316 | dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); |
| 317 | if (dirp != NULL) { |
| 318 | DWORD n; |
| 319 | |
| 320 | /* Reset _WDIR structure */ |
| 321 | dirp->handle = INVALID_HANDLE_VALUE; |
| 322 | dirp->patt = NULL; |
| 323 | dirp->cached = 0; |
| 324 | |
| 325 | /* Compute the length of full path plus zero terminator */ |
| 326 | n = GetFullPathNameW (dirname, 0, NULL, NULL); |
| 327 | |
| 328 | /* Allocate room for absolute directory name and search pattern */ |
| 329 | dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); |
| 330 | if (dirp->patt) { |
| 331 | |
| 332 | /* |
| 333 | * Convert relative directory name to an absolute one. This |
| 334 | * allows rewinddir() to function correctly even when current |
| 335 | * working directory is changed between opendir() and rewinddir(). |
| 336 | */ |
| 337 | n = GetFullPathNameW (dirname, n, dirp->patt, NULL); |
| 338 | if (n > 0) { |
| 339 | wchar_t *p; |
| @@ -303,25 +356,22 @@ | |
| 356 | } |
| 357 | *p++ = '*'; |
| 358 | *p = '\0'; |
| 359 | |
| 360 | /* Open directory stream and retrieve the first entry */ |
| 361 | if (dirent_first (dirp)) { |
| 362 | /* Directory stream opened successfully */ |
| 363 | error = 0; |
| 364 | } else { |
| 365 | /* Cannot retrieve first entry */ |
| 366 | error = 1; |
| 367 | dirent_set_errno (ENOENT); |
| 368 | } |
| 369 | |
| 370 | } else { |
| 371 | /* Cannot retrieve full path name */ |
| 372 | dirent_set_errno (ENOENT); |
| 373 | error = 1; |
| 374 | } |
| 375 | |
| 376 | } else { |
| 377 | /* Cannot allocate memory for search pattern */ |
| @@ -350,70 +400,59 @@ | |
| 400 | */ |
| 401 | static struct _wdirent* |
| 402 | _wreaddir( |
| 403 | _WDIR *dirp) |
| 404 | { |
| 405 | WIN32_FIND_DATAW *datap; |
| 406 | struct _wdirent *entp; |
| 407 | |
| 408 | /* Read next directory entry */ |
| 409 | datap = dirent_next (dirp); |
| 410 | if (datap) { |
| 411 | size_t n; |
| 412 | DWORD attr; |
| 413 | |
| 414 | /* Pointer to directory entry to return */ |
| 415 | entp = &dirp->ent; |
| 416 | |
| 417 | /* |
| 418 | * Copy file name as wide-character string. If the file name is too |
| 419 | * long to fit in to the destination buffer, then truncate file name |
| 420 | * to PATH_MAX characters and zero-terminate the buffer. |
| 421 | */ |
| 422 | n = 0; |
| 423 | while (n < PATH_MAX && datap->cFileName[n] != 0) { |
| 424 | entp->d_name[n] = datap->cFileName[n]; |
| 425 | n++; |
| 426 | } |
| 427 | dirp->ent.d_name[n] = 0; |
| 428 | |
| 429 | /* Length of file name excluding zero terminator */ |
| 430 | entp->d_namlen = n; |
| 431 | |
| 432 | /* File type */ |
| 433 | attr = datap->dwFileAttributes; |
| 434 | if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { |
| 435 | entp->d_type = DT_CHR; |
| 436 | } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 437 | entp->d_type = DT_DIR; |
| 438 | } else { |
| 439 | entp->d_type = DT_REG; |
| 440 | } |
| 441 | |
| 442 | /* Reset dummy fields */ |
| 443 | entp->d_ino = 0; |
| 444 | entp->d_reclen = sizeof (struct _wdirent); |
| 445 | |
| 446 | } else { |
| 447 | |
| 448 | /* Last directory entry read */ |
| 449 | entp = NULL; |
| 450 | |
| 451 | } |
| 452 | |
| 453 | return entp; |
| 454 | } |
| 455 | |
| 456 | /* |
| 457 | * Close directory stream opened by opendir() function. This invalidates the |
| 458 | * DIR structure as well as any directory entry read previously by |
| @@ -442,11 +481,11 @@ | |
| 481 | free (dirp); |
| 482 | ok = /*success*/0; |
| 483 | |
| 484 | } else { |
| 485 | /* Invalid directory stream */ |
| 486 | dirent_set_errno (EBADF); |
| 487 | ok = /*failure*/-1; |
| 488 | } |
| 489 | return ok; |
| 490 | } |
| 491 | |
| @@ -456,26 +495,81 @@ | |
| 495 | */ |
| 496 | static void |
| 497 | _wrewinddir( |
| 498 | _WDIR* dirp) |
| 499 | { |
| 500 | if (dirp) { |
| 501 | /* Release existing search handle */ |
| 502 | if (dirp->handle != INVALID_HANDLE_VALUE) { |
| 503 | FindClose (dirp->handle); |
| 504 | } |
| 505 | |
| 506 | /* Open new search handle */ |
| 507 | dirent_first (dirp); |
| 508 | } |
| 509 | } |
| 510 | |
| 511 | /* Get first directory entry (internal) */ |
| 512 | static WIN32_FIND_DATAW* |
| 513 | dirent_first( |
| 514 | _WDIR *dirp) |
| 515 | { |
| 516 | WIN32_FIND_DATAW *datap; |
| 517 | |
| 518 | /* Open directory and retrieve the first entry */ |
| 519 | dirp->handle = FindFirstFileW (dirp->patt, &dirp->data); |
| 520 | if (dirp->handle != INVALID_HANDLE_VALUE) { |
| 521 | |
| 522 | /* a directory entry is now waiting in memory */ |
| 523 | datap = &dirp->data; |
| 524 | dirp->cached = 1; |
| 525 | |
| 526 | } else { |
| 527 | |
| 528 | /* Failed to re-open directory: no directory entry in memory */ |
| 529 | dirp->cached = 0; |
| 530 | datap = NULL; |
| 531 | |
| 532 | } |
| 533 | return datap; |
| 534 | } |
| 535 | |
| 536 | /* Get next directory entry (internal) */ |
| 537 | static WIN32_FIND_DATAW* |
| 538 | dirent_next( |
| 539 | _WDIR *dirp) |
| 540 | { |
| 541 | WIN32_FIND_DATAW *p; |
| 542 | |
| 543 | /* Get next directory entry */ |
| 544 | if (dirp->cached != 0) { |
| 545 | |
| 546 | /* A valid directory entry already in memory */ |
| 547 | p = &dirp->data; |
| 548 | dirp->cached = 0; |
| 549 | |
| 550 | } else if (dirp->handle != INVALID_HANDLE_VALUE) { |
| 551 | |
| 552 | /* Get the next directory entry from stream */ |
| 553 | if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { |
| 554 | /* Got a file */ |
| 555 | p = &dirp->data; |
| 556 | } else { |
| 557 | /* The very last entry has been processed or an error occured */ |
| 558 | FindClose (dirp->handle); |
| 559 | dirp->handle = INVALID_HANDLE_VALUE; |
| 560 | p = NULL; |
| 561 | } |
| 562 | |
| 563 | } else { |
| 564 | |
| 565 | /* End of directory stream reached */ |
| 566 | p = NULL; |
| 567 | |
| 568 | } |
| 569 | |
| 570 | return p; |
| 571 | } |
| 572 | |
| 573 | /* |
| 574 | * Open directory stream using plain old C-string. |
| 575 | */ |
| @@ -482,58 +576,34 @@ | |
| 576 | static DIR* |
| 577 | opendir( |
| 578 | const char *dirname) |
| 579 | { |
| 580 | struct DIR *dirp; |
| 581 | int error; |
| 582 | |
| 583 | /* Must have directory name */ |
| 584 | if (dirname == NULL || dirname[0] == '\0') { |
| 585 | dirent_set_errno (ENOENT); |
| 586 | return NULL; |
| 587 | } |
| 588 | |
| 589 | /* Allocate memory for DIR structure */ |
| 590 | dirp = (DIR*) malloc (sizeof (struct DIR)); |
| 591 | if (dirp) { |
| 592 | wchar_t wname[PATH_MAX + 1]; |
| 593 | size_t n; |
| 594 | |
| 595 | /* Convert directory name to wide-character string */ |
| 596 | error = dirent_mbstowcs_s( |
| 597 | &n, wname, PATH_MAX + 1, dirname, PATH_MAX); |
| 598 | if (!error) { |
| 599 | |
| 600 | /* Open directory stream using wide-character name */ |
| 601 | dirp->wdirp = _wopendir (wname); |
| 602 | if (dirp->wdirp) { |
| 603 | /* Directory stream opened */ |
| 604 | error = 0; |
| 605 | } else { |
| 606 | /* Failed to open directory stream */ |
| 607 | error = 1; |
| 608 | } |
| 609 | |
| @@ -562,95 +632,99 @@ | |
| 632 | } |
| 633 | |
| 634 | /* |
| 635 | * Read next directory entry. |
| 636 | * |
| 637 | * When working with text consoles, please note that file names returned by |
| 638 | * readdir() are represented in the default ANSI code page while any output to |
| 639 | * console is typically formatted on another code page. Thus, non-ASCII |
| 640 | * characters in file names will not usually display correctly on console. The |
| 641 | * problem can be fixed in two ways: (1) change the character set of console |
| 642 | * to 1252 using chcp utility and use Lucida Console font, or (2) use |
| 643 | * _cprintf function when writing to console. The _cprinf() will re-encode |
| 644 | * ANSI strings to the console code page so many non-ASCII characters will |
| 645 | * display correcly. |
| 646 | */ |
| 647 | static struct dirent* |
| 648 | readdir( |
| 649 | DIR *dirp) |
| 650 | { |
| 651 | WIN32_FIND_DATAW *datap; |
| 652 | struct dirent *entp; |
| 653 | |
| 654 | /* Read next directory entry */ |
| 655 | datap = dirent_next (dirp->wdirp); |
| 656 | if (datap) { |
| 657 | size_t n; |
| 658 | int error; |
| 659 | |
| 660 | /* Attempt to convert file name to multi-byte string */ |
| 661 | error = dirent_wcstombs_s( |
| 662 | &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH); |
| 663 | |
| 664 | /* |
| 665 | * If the file name cannot be represented by a multi-byte string, |
| 666 | * then attempt to use old 8+3 file name. This allows traditional |
| 667 | * Unix-code to access some file names despite of unicode |
| 668 | * characters, although file names may seem unfamiliar to the user. |
| 669 | * |
| 670 | * Be ware that the code below cannot come up with a short file |
| 671 | * name unless the file system provides one. At least |
| 672 | * VirtualBox shared folders fail to do this. |
| 673 | */ |
| 674 | if (error && datap->cAlternateFileName[0] != '\0') { |
| 675 | error = dirent_wcstombs_s( |
| 676 | &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName, |
| 677 | sizeof (datap->cAlternateFileName) / |
| 678 | sizeof (datap->cAlternateFileName[0])); |
| 679 | } |
| 680 | |
| 681 | if (!error) { |
| 682 | DWORD attr; |
| 683 | |
| 684 | /* Initialize directory entry for return */ |
| 685 | entp = &dirp->ent; |
| 686 | |
| 687 | /* Length of file name excluding zero terminator */ |
| 688 | entp->d_namlen = n - 1; |
| 689 | |
| 690 | /* File attributes */ |
| 691 | attr = datap->dwFileAttributes; |
| 692 | if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { |
| 693 | entp->d_type = DT_CHR; |
| 694 | } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 695 | entp->d_type = DT_DIR; |
| 696 | } else { |
| 697 | entp->d_type = DT_REG; |
| 698 | } |
| 699 | |
| 700 | /* Reset dummy fields */ |
| 701 | entp->d_ino = 0; |
| 702 | entp->d_reclen = sizeof (struct dirent); |
| 703 | |
| 704 | } else { |
| 705 | /* |
| 706 | * Cannot convert file name to multi-byte string so construct |
| 707 | * an errornous directory entry and return that. Note that |
| 708 | * we cannot return NULL as that would stop the processing |
| 709 | * of directory entries completely. |
| 710 | */ |
| 711 | entp = &dirp->ent; |
| 712 | entp->d_name[0] = '?'; |
| 713 | entp->d_name[1] = '\0'; |
| 714 | entp->d_namlen = 1; |
| 715 | entp->d_type = DT_UNKNOWN; |
| 716 | entp->d_ino = 0; |
| 717 | entp->d_reclen = 0; |
| 718 | } |
| 719 | |
| 720 | } else { |
| 721 | /* No more directory entries */ |
| 722 | entp = NULL; |
| 723 | } |
| 724 | |
| 725 | return entp; |
| 726 | } |
| 727 | |
| 728 | /* |
| 729 | * Close directory stream. |
| 730 | */ |
| @@ -667,13 +741,15 @@ | |
| 741 | |
| 742 | /* Release multi-byte character version */ |
| 743 | free (dirp); |
| 744 | |
| 745 | } else { |
| 746 | |
| 747 | /* Invalid directory stream */ |
| 748 | dirent_set_errno (EBADF); |
| 749 | ok = /*failure*/-1; |
| 750 | |
| 751 | } |
| 752 | return ok; |
| 753 | } |
| 754 | |
| 755 | /* |
| @@ -684,12 +760,130 @@ | |
| 760 | DIR* dirp) |
| 761 | { |
| 762 | /* Rewind wide-character string directory stream */ |
| 763 | _wrewinddir (dirp->wdirp); |
| 764 | } |
| 765 | |
| 766 | /* Convert multi-byte string to wide character string */ |
| 767 | static int |
| 768 | dirent_mbstowcs_s( |
| 769 | size_t *pReturnValue, |
| 770 | wchar_t *wcstr, |
| 771 | size_t sizeInWords, |
| 772 | const char *mbstr, |
| 773 | size_t count) |
| 774 | { |
| 775 | int error; |
| 776 | |
| 777 | #if defined(_MSC_VER) && _MSC_VER >= 1400 |
| 778 | |
| 779 | /* Microsoft Visual Studio 2005 or later */ |
| 780 | error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); |
| 781 | |
| 782 | #else |
| 783 | |
| 784 | /* Older Visual Studio or non-Microsoft compiler */ |
| 785 | size_t n; |
| 786 | |
| 787 | /* Convert to wide-character string */ |
| 788 | n = mbstowcs (wcstr, mbstr, count); |
| 789 | if (n < sizeInWords) { |
| 790 | |
| 791 | /* Zero-terminate output buffer */ |
| 792 | if (wcstr) { |
| 793 | wcstr[n] = 0; |
| 794 | } |
| 795 | |
| 796 | /* Length of resuting multi-byte string WITH zero terminator */ |
| 797 | if (pReturnValue) { |
| 798 | *pReturnValue = n + 1; |
| 799 | } |
| 800 | |
| 801 | /* Success */ |
| 802 | error = 0; |
| 803 | |
| 804 | } else { |
| 805 | |
| 806 | /* Could not convert string */ |
| 807 | error = 1; |
| 808 | |
| 809 | } |
| 810 | |
| 811 | #endif |
| 812 | |
| 813 | return error; |
| 814 | } |
| 815 | |
| 816 | /* Convert wide-character string to multi-byte string */ |
| 817 | static int |
| 818 | dirent_wcstombs_s( |
| 819 | size_t *pReturnValue, |
| 820 | char *mbstr, |
| 821 | size_t sizeInBytes, |
| 822 | const wchar_t *wcstr, |
| 823 | size_t count) |
| 824 | { |
| 825 | int error; |
| 826 | |
| 827 | #if defined(_MSC_VER) && _MSC_VER >= 1400 |
| 828 | |
| 829 | /* Microsoft Visual Studio 2005 or later */ |
| 830 | error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); |
| 831 | |
| 832 | #else |
| 833 | |
| 834 | /* Older Visual Studio or non-Microsoft compiler */ |
| 835 | size_t n; |
| 836 | |
| 837 | /* Convert to multi-byte string */ |
| 838 | n = wcstombs (mbstr, wcstr, count); |
| 839 | if (n < sizeInBytes) { |
| 840 | |
| 841 | /* Zero-terminate output buffer */ |
| 842 | if (mbstr) { |
| 843 | mbstr[n] = '\0'; |
| 844 | } |
| 845 | |
| 846 | /* Lenght of resulting multi-bytes string WITH zero-terminator */ |
| 847 | if (pReturnValue) { |
| 848 | *pReturnValue = n + 1; |
| 849 | } |
| 850 | |
| 851 | /* Success */ |
| 852 | error = 0; |
| 853 | |
| 854 | } else { |
| 855 | |
| 856 | /* Cannot convert string */ |
| 857 | error = 1; |
| 858 | |
| 859 | } |
| 860 | |
| 861 | #endif |
| 862 | |
| 863 | return error; |
| 864 | } |
| 865 | |
| 866 | /* Set errno variable */ |
| 867 | static void |
| 868 | dirent_set_errno( |
| 869 | int error) |
| 870 | { |
| 871 | #if defined(_MSC_VER) |
| 872 | |
| 873 | /* Microsoft Visual Studio */ |
| 874 | _set_errno (error); |
| 875 | |
| 876 | #else |
| 877 | |
| 878 | /* Non-Microsoft compiler */ |
| 879 | errno = error; |
| 880 | |
| 881 | #endif |
| 882 | } |
| 883 | |
| 884 | |
| 885 | #ifdef __cplusplus |
| 886 | } |
| 887 | #endif |
| 888 | #endif /*DIRENT_H*/ |
| 889 | |
| 890 |
+29
-28
| --- www/build.wiki | ||
| +++ www/build.wiki | ||
| @@ -1,6 +1,6 @@ | ||
| 1 | -<title>Building and Installing Fossil</title> | |
| 1 | +<title>Compiling and Installing Fossil</title> | |
| 2 | 2 | |
| 3 | 3 | <h2>0.0 Using A Pre-compiled Binary</h2> |
| 4 | 4 | |
| 5 | 5 | <p>Released versions of fossil come with |
| 6 | 6 | <a href="http://www.fossil-scm.org/download.html">pre-compiled binaries and |
| @@ -25,33 +25,29 @@ | ||
| 25 | 25 | |
| 26 | 26 | <p><hr> |
| 27 | 27 | |
| 28 | 28 | <h2>1.0 Obtaining The Source Code</h2> |
| 29 | 29 | |
| 30 | -<p>Fossil is self-hosting, so you can obtain a ZIP archive containing | |
| 31 | -a snapshot of the <em>latest</em> version directly from fossil's own fossil | |
| 32 | -repository. Additionally, source archives of <em>released</em> versions of | |
| 30 | +<p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball | |
| 31 | +containing a snapshot of the <em>latest</em> version directly from | |
| 32 | +Fossil's own fossil repository. Additionally, source archives of | |
| 33 | +<em>released</em> versions of | |
| 33 | 34 | fossil are available from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>. |
| 34 | 35 | To obtain a development version of fossil, follow these steps:</p> |
| 35 | 36 | |
| 36 | 37 | <ol> |
| 37 | 38 | <li><p>Point your web browser at |
| 38 | 39 | <a href="http://www.fossil-scm.org/"> |
| 39 | -http://www.fossil-scm.org/</a>. Click on the "Login" menu button.</p></li> | |
| 40 | - | |
| 41 | -<li><p>Log in as anonymous. The password is shown on screen. | |
| 42 | -The reason for requiring this login is to prevent spiders from | |
| 43 | -walking the entire website, downloading ZIP archives | |
| 44 | -of every historical version, and thereby soaking up all our bandwidth.</p></li> | |
| 40 | +http://www.fossil-scm.org/</a>.</p></li> | |
| 45 | 41 | |
| 46 | 42 | <li><p>Click on the |
| 47 | 43 | <a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> |
| 48 | 44 | link at the top of the page.</p></li> |
| 49 | 45 | |
| 50 | -<li><p>Select a version of of fossil you want to download. Click on its | |
| 51 | -link. Note that you must successfully log in as "anonymous" in step 1 | |
| 52 | -above in order to see the link to the detailed version information.</p></li> | |
| 46 | +<li><p>Select a version of of Fossil you want to download. The latest | |
| 47 | +version on the trunk branch is usually a good choice. Click on its | |
| 48 | +link.</p></li> | |
| 53 | 49 | |
| 54 | 50 | <li><p>Finally, click on one of the |
| 55 | 51 | "Zip Archive" or "Tarball" links, according to your preference. |
| 56 | 52 | These link will build a ZIP archive or a gzip-compressed tarball of the |
| 57 | 53 | complete source code and download it to your browser. |
| @@ -59,11 +55,11 @@ | ||
| 59 | 55 | |
| 60 | 56 | <h2>2.0 Compiling</h2> |
| 61 | 57 | |
| 62 | 58 | <ol> |
| 63 | 59 | <li value="6"> |
| 64 | -<p>Unpack the ZIP or tarball you downloaded into that directory then | |
| 60 | +<p>Unpack the ZIP or tarball you downloaded then | |
| 65 | 61 | <b>cd</b> into the directory created.</p></li> |
| 66 | 62 | |
| 67 | 63 | <li><i>(Optional, unix only)</i> |
| 68 | 64 | Run <b>./configure</b> to construct a makefile. |
| 69 | 65 | |
| @@ -79,12 +75,12 @@ | ||
| 79 | 75 | <li><p> |
| 80 | 76 | Other configuration options can be seen by running |
| 81 | 77 | <b>./configure --help</b> |
| 82 | 78 | </ol> |
| 83 | 79 | |
| 84 | -<li><p>Run make to build the "fossil" or "fossil.exe" executable. The | |
| 85 | -details depend on your platform and compiler. | |
| 80 | +<li><p>Run "<b>make</b>" to build the "fossil" or "fossil.exe" executable. | |
| 81 | +The details depend on your platform and compiler. | |
| 86 | 82 | |
| 87 | 83 | <ol type="a"> |
| 88 | 84 | <li><p><i>Unix</i> → the configure-generated Makefile should work on |
| 89 | 85 | all unix and unix-like systems. Simply type "<b>make</b>". |
| 90 | 86 | |
| @@ -102,16 +98,10 @@ | ||
| 102 | 98 | change to the "win/" subdirectory ("<b>cd win</b>") then run |
| 103 | 99 | "<b>nmake /f Makefile.msc</b>". |
| 104 | 100 | </ol> |
| 105 | 101 | </ol> |
| 106 | 102 | |
| 107 | -<p>Note that Fossil requires the "zlib" compression library. This library | |
| 108 | -is available by default on most unix systems, but it will typically have to | |
| 109 | -be installed separately on windows systems. For windows builds, you may | |
| 110 | -need to edit the makefile to tell it exactly where zlib is located on your | |
| 111 | -system.</p> | |
| 112 | - | |
| 113 | 103 | <h2>3.0 Installing</h2> |
| 114 | 104 | |
| 115 | 105 | <ol> |
| 116 | 106 | <li value="9"> |
| 117 | 107 | <p>The finished binary is named "fossil" (or "fossil.exe" on windows). |
| @@ -124,11 +114,22 @@ | ||
| 124 | 114 | To uninstall, just delete the binary.</p> |
| 125 | 115 | </ol> |
| 126 | 116 | |
| 127 | 117 | <h2>4.0 Additional Considerations</h2> |
| 128 | 118 | |
| 129 | -</nowiki> | |
| 130 | - * If the makefiles that come with Fossil do not work for | |
| 131 | - you, or for some other reason you want to know how to build | |
| 132 | - Fossil manually, then refer to the | |
| 133 | - [./makefile.wiki | Fossil Build Process] document which describes | |
| 134 | - in detail what the makefiles do behind the scenes. | |
| 119 | +<ul> | |
| 120 | +<li><p> | |
| 121 | + If the makefiles that come with Fossil do not work for | |
| 122 | + you, or for some other reason you want to know how to build | |
| 123 | + Fossil manually, then refer to the | |
| 124 | + [./makefile.wiki | Fossil Build Process] document which describes | |
| 125 | + in detail what the makefiles do behind the scenes. | |
| 126 | + | |
| 127 | +<li><p> | |
| 128 | + To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile | |
| 129 | + generated by configure to add the following lines: | |
| 130 | + <blockquote><pre> | |
| 131 | + TCC += -DSQLITE_WITHOUT_ZONEMALLOC | |
| 132 | + TCC += -DWITHOUT_ICONV | |
| 133 | + TCC += -Dsocketlen_t=int | |
| 134 | + </pre></blockquote> | |
| 135 | +</ul> | |
| 135 | 136 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -1,6 +1,6 @@ | |
| 1 | <title>Building and Installing Fossil</title> |
| 2 | |
| 3 | <h2>0.0 Using A Pre-compiled Binary</h2> |
| 4 | |
| 5 | <p>Released versions of fossil come with |
| 6 | <a href="http://www.fossil-scm.org/download.html">pre-compiled binaries and |
| @@ -25,33 +25,29 @@ | |
| 25 | |
| 26 | <p><hr> |
| 27 | |
| 28 | <h2>1.0 Obtaining The Source Code</h2> |
| 29 | |
| 30 | <p>Fossil is self-hosting, so you can obtain a ZIP archive containing |
| 31 | a snapshot of the <em>latest</em> version directly from fossil's own fossil |
| 32 | repository. Additionally, source archives of <em>released</em> versions of |
| 33 | fossil are available from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>. |
| 34 | To obtain a development version of fossil, follow these steps:</p> |
| 35 | |
| 36 | <ol> |
| 37 | <li><p>Point your web browser at |
| 38 | <a href="http://www.fossil-scm.org/"> |
| 39 | http://www.fossil-scm.org/</a>. Click on the "Login" menu button.</p></li> |
| 40 | |
| 41 | <li><p>Log in as anonymous. The password is shown on screen. |
| 42 | The reason for requiring this login is to prevent spiders from |
| 43 | walking the entire website, downloading ZIP archives |
| 44 | of every historical version, and thereby soaking up all our bandwidth.</p></li> |
| 45 | |
| 46 | <li><p>Click on the |
| 47 | <a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> |
| 48 | link at the top of the page.</p></li> |
| 49 | |
| 50 | <li><p>Select a version of of fossil you want to download. Click on its |
| 51 | link. Note that you must successfully log in as "anonymous" in step 1 |
| 52 | above in order to see the link to the detailed version information.</p></li> |
| 53 | |
| 54 | <li><p>Finally, click on one of the |
| 55 | "Zip Archive" or "Tarball" links, according to your preference. |
| 56 | These link will build a ZIP archive or a gzip-compressed tarball of the |
| 57 | complete source code and download it to your browser. |
| @@ -59,11 +55,11 @@ | |
| 59 | |
| 60 | <h2>2.0 Compiling</h2> |
| 61 | |
| 62 | <ol> |
| 63 | <li value="6"> |
| 64 | <p>Unpack the ZIP or tarball you downloaded into that directory then |
| 65 | <b>cd</b> into the directory created.</p></li> |
| 66 | |
| 67 | <li><i>(Optional, unix only)</i> |
| 68 | Run <b>./configure</b> to construct a makefile. |
| 69 | |
| @@ -79,12 +75,12 @@ | |
| 79 | <li><p> |
| 80 | Other configuration options can be seen by running |
| 81 | <b>./configure --help</b> |
| 82 | </ol> |
| 83 | |
| 84 | <li><p>Run make to build the "fossil" or "fossil.exe" executable. The |
| 85 | details depend on your platform and compiler. |
| 86 | |
| 87 | <ol type="a"> |
| 88 | <li><p><i>Unix</i> → the configure-generated Makefile should work on |
| 89 | all unix and unix-like systems. Simply type "<b>make</b>". |
| 90 | |
| @@ -102,16 +98,10 @@ | |
| 102 | change to the "win/" subdirectory ("<b>cd win</b>") then run |
| 103 | "<b>nmake /f Makefile.msc</b>". |
| 104 | </ol> |
| 105 | </ol> |
| 106 | |
| 107 | <p>Note that Fossil requires the "zlib" compression library. This library |
| 108 | is available by default on most unix systems, but it will typically have to |
| 109 | be installed separately on windows systems. For windows builds, you may |
| 110 | need to edit the makefile to tell it exactly where zlib is located on your |
| 111 | system.</p> |
| 112 | |
| 113 | <h2>3.0 Installing</h2> |
| 114 | |
| 115 | <ol> |
| 116 | <li value="9"> |
| 117 | <p>The finished binary is named "fossil" (or "fossil.exe" on windows). |
| @@ -124,11 +114,22 @@ | |
| 124 | To uninstall, just delete the binary.</p> |
| 125 | </ol> |
| 126 | |
| 127 | <h2>4.0 Additional Considerations</h2> |
| 128 | |
| 129 | </nowiki> |
| 130 | * If the makefiles that come with Fossil do not work for |
| 131 | you, or for some other reason you want to know how to build |
| 132 | Fossil manually, then refer to the |
| 133 | [./makefile.wiki | Fossil Build Process] document which describes |
| 134 | in detail what the makefiles do behind the scenes. |
| 135 |
| --- www/build.wiki | |
| +++ www/build.wiki | |
| @@ -1,6 +1,6 @@ | |
| 1 | <title>Compiling and Installing Fossil</title> |
| 2 | |
| 3 | <h2>0.0 Using A Pre-compiled Binary</h2> |
| 4 | |
| 5 | <p>Released versions of fossil come with |
| 6 | <a href="http://www.fossil-scm.org/download.html">pre-compiled binaries and |
| @@ -25,33 +25,29 @@ | |
| 25 | |
| 26 | <p><hr> |
| 27 | |
| 28 | <h2>1.0 Obtaining The Source Code</h2> |
| 29 | |
| 30 | <p>Fossil is self-hosting, so you can obtain a ZIP archive or tarball |
| 31 | containing a snapshot of the <em>latest</em> version directly from |
| 32 | Fossil's own fossil repository. Additionally, source archives of |
| 33 | <em>released</em> versions of |
| 34 | fossil are available from the <a href="http://www.fossil-scm.org/download.html">downloads page</a>. |
| 35 | To obtain a development version of fossil, follow these steps:</p> |
| 36 | |
| 37 | <ol> |
| 38 | <li><p>Point your web browser at |
| 39 | <a href="http://www.fossil-scm.org/"> |
| 40 | http://www.fossil-scm.org/</a>.</p></li> |
| 41 | |
| 42 | <li><p>Click on the |
| 43 | <a href="http://www.fossil-scm.org/fossil/timeline">Timeline</a> |
| 44 | link at the top of the page.</p></li> |
| 45 | |
| 46 | <li><p>Select a version of of Fossil you want to download. The latest |
| 47 | version on the trunk branch is usually a good choice. Click on its |
| 48 | link.</p></li> |
| 49 | |
| 50 | <li><p>Finally, click on one of the |
| 51 | "Zip Archive" or "Tarball" links, according to your preference. |
| 52 | These link will build a ZIP archive or a gzip-compressed tarball of the |
| 53 | complete source code and download it to your browser. |
| @@ -59,11 +55,11 @@ | |
| 55 | |
| 56 | <h2>2.0 Compiling</h2> |
| 57 | |
| 58 | <ol> |
| 59 | <li value="6"> |
| 60 | <p>Unpack the ZIP or tarball you downloaded then |
| 61 | <b>cd</b> into the directory created.</p></li> |
| 62 | |
| 63 | <li><i>(Optional, unix only)</i> |
| 64 | Run <b>./configure</b> to construct a makefile. |
| 65 | |
| @@ -79,12 +75,12 @@ | |
| 75 | <li><p> |
| 76 | Other configuration options can be seen by running |
| 77 | <b>./configure --help</b> |
| 78 | </ol> |
| 79 | |
| 80 | <li><p>Run "<b>make</b>" to build the "fossil" or "fossil.exe" executable. |
| 81 | The details depend on your platform and compiler. |
| 82 | |
| 83 | <ol type="a"> |
| 84 | <li><p><i>Unix</i> → the configure-generated Makefile should work on |
| 85 | all unix and unix-like systems. Simply type "<b>make</b>". |
| 86 | |
| @@ -102,16 +98,10 @@ | |
| 98 | change to the "win/" subdirectory ("<b>cd win</b>") then run |
| 99 | "<b>nmake /f Makefile.msc</b>". |
| 100 | </ol> |
| 101 | </ol> |
| 102 | |
| 103 | <h2>3.0 Installing</h2> |
| 104 | |
| 105 | <ol> |
| 106 | <li value="9"> |
| 107 | <p>The finished binary is named "fossil" (or "fossil.exe" on windows). |
| @@ -124,11 +114,22 @@ | |
| 114 | To uninstall, just delete the binary.</p> |
| 115 | </ol> |
| 116 | |
| 117 | <h2>4.0 Additional Considerations</h2> |
| 118 | |
| 119 | <ul> |
| 120 | <li><p> |
| 121 | If the makefiles that come with Fossil do not work for |
| 122 | you, or for some other reason you want to know how to build |
| 123 | Fossil manually, then refer to the |
| 124 | [./makefile.wiki | Fossil Build Process] document which describes |
| 125 | in detail what the makefiles do behind the scenes. |
| 126 | |
| 127 | <li><p> |
| 128 | To build on older Macs (circa 2002, MacOS 10.2) edit the Makefile |
| 129 | generated by configure to add the following lines: |
| 130 | <blockquote><pre> |
| 131 | TCC += -DSQLITE_WITHOUT_ZONEMALLOC |
| 132 | TCC += -DWITHOUT_ICONV |
| 133 | TCC += -Dsocketlen_t=int |
| 134 | </pre></blockquote> |
| 135 | </ul> |
| 136 |
+3
-4
| --- www/checkin_names.wiki | ||
| +++ www/checkin_names.wiki | ||
| @@ -14,12 +14,11 @@ | ||
| 14 | 14 | <li> Special names: |
| 15 | 15 | <ul> |
| 16 | 16 | <li> <b>tip</b> |
| 17 | 17 | <li> <b>current</b> |
| 18 | 18 | <li> <b>next</b> |
| 19 | -<li> <b>previous</b> | |
| 20 | -<li> <b>ckout</b> | |
| 19 | +<li> <b>previous</b> or <b>prev</b> | |
| 21 | 20 | </ul> |
| 22 | 21 | </ul> |
| 23 | 22 | </td></tr> |
| 24 | 23 | </table> |
| 25 | 24 | Many Fossil [/help|commands] and [./webui.wiki | web-interface] URLs accept |
| @@ -194,12 +193,12 @@ | ||
| 194 | 193 | equivalent to the timestamp tag "5000-01-01". |
| 195 | 194 | |
| 196 | 195 | If the command is being run from a working check-out (not against a bare |
| 197 | 196 | repository) then a few extra tags apply. The "current" tag means the |
| 198 | 197 | current check-out. The "next" tag means the youngest child of the |
| 199 | -current check-out. And the "previous" tag means the primary (non-merge) | |
| 200 | -parent of the current check-out. | |
| 198 | +current check-out. And the "previous" or "prev" tag means the primary | |
| 199 | +(non-merge) parent of the current check-out. | |
| 201 | 200 | |
| 202 | 201 | <h2>Additional Examples</h2> |
| 203 | 202 | |
| 204 | 203 | To view the changes in the most recent check-in prior to the version currently |
| 205 | 204 | checked out: |
| 206 | 205 |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -14,12 +14,11 @@ | |
| 14 | <li> Special names: |
| 15 | <ul> |
| 16 | <li> <b>tip</b> |
| 17 | <li> <b>current</b> |
| 18 | <li> <b>next</b> |
| 19 | <li> <b>previous</b> |
| 20 | <li> <b>ckout</b> |
| 21 | </ul> |
| 22 | </ul> |
| 23 | </td></tr> |
| 24 | </table> |
| 25 | Many Fossil [/help|commands] and [./webui.wiki | web-interface] URLs accept |
| @@ -194,12 +193,12 @@ | |
| 194 | equivalent to the timestamp tag "5000-01-01". |
| 195 | |
| 196 | If the command is being run from a working check-out (not against a bare |
| 197 | repository) then a few extra tags apply. The "current" tag means the |
| 198 | current check-out. The "next" tag means the youngest child of the |
| 199 | current check-out. And the "previous" tag means the primary (non-merge) |
| 200 | parent of the current check-out. |
| 201 | |
| 202 | <h2>Additional Examples</h2> |
| 203 | |
| 204 | To view the changes in the most recent check-in prior to the version currently |
| 205 | checked out: |
| 206 |
| --- www/checkin_names.wiki | |
| +++ www/checkin_names.wiki | |
| @@ -14,12 +14,11 @@ | |
| 14 | <li> Special names: |
| 15 | <ul> |
| 16 | <li> <b>tip</b> |
| 17 | <li> <b>current</b> |
| 18 | <li> <b>next</b> |
| 19 | <li> <b>previous</b> or <b>prev</b> |
| 20 | </ul> |
| 21 | </ul> |
| 22 | </td></tr> |
| 23 | </table> |
| 24 | Many Fossil [/help|commands] and [./webui.wiki | web-interface] URLs accept |
| @@ -194,12 +193,12 @@ | |
| 193 | equivalent to the timestamp tag "5000-01-01". |
| 194 | |
| 195 | If the command is being run from a working check-out (not against a bare |
| 196 | repository) then a few extra tags apply. The "current" tag means the |
| 197 | current check-out. The "next" tag means the youngest child of the |
| 198 | current check-out. And the "previous" or "prev" tag means the primary |
| 199 | (non-merge) parent of the current check-out. |
| 200 | |
| 201 | <h2>Additional Examples</h2> |
| 202 | |
| 203 | To view the changes in the most recent check-in prior to the version currently |
| 204 | checked out: |
| 205 |
+1
-1
| --- www/contribute.wiki | ||
| +++ www/contribute.wiki | ||
| @@ -75,8 +75,8 @@ | ||
| 75 | 75 | the checklist and/or the automated test scripts to cover their additions. |
| 76 | 76 | |
| 77 | 77 | |
| 78 | 78 | <h2>5.0 See Also</h2> |
| 79 | 79 | |
| 80 | - * [./build.wiki | How To Build And Install Fossil] | |
| 80 | + * [./build.wiki | How To Compile And Install Fossil] | |
| 81 | 81 | * [./makefile.wiki | The Fossil Build Process] |
| 82 | 82 | * [./tech_overview.wiki | A Technical Overview of Fossil] |
| 83 | 83 |
| --- www/contribute.wiki | |
| +++ www/contribute.wiki | |
| @@ -75,8 +75,8 @@ | |
| 75 | the checklist and/or the automated test scripts to cover their additions. |
| 76 | |
| 77 | |
| 78 | <h2>5.0 See Also</h2> |
| 79 | |
| 80 | * [./build.wiki | How To Build And Install Fossil] |
| 81 | * [./makefile.wiki | The Fossil Build Process] |
| 82 | * [./tech_overview.wiki | A Technical Overview of Fossil] |
| 83 |
| --- www/contribute.wiki | |
| +++ www/contribute.wiki | |
| @@ -75,8 +75,8 @@ | |
| 75 | the checklist and/or the automated test scripts to cover their additions. |
| 76 | |
| 77 | |
| 78 | <h2>5.0 See Also</h2> |
| 79 | |
| 80 | * [./build.wiki | How To Compile And Install Fossil] |
| 81 | * [./makefile.wiki | The Fossil Build Process] |
| 82 | * [./tech_overview.wiki | A Technical Overview of Fossil] |
| 83 |
+1
-1
| --- www/index.wiki | ||
| +++ www/index.wiki | ||
| @@ -115,11 +115,11 @@ | ||
| 115 | 115 | [./quotes.wiki | Quotes] about Fossil and other DVCSes. |
| 116 | 116 | * [./faq.wiki | FAQ] |
| 117 | 117 | * The [./concepts.wiki | concepts] behind fossil |
| 118 | 118 | * [./quickstart.wiki | Quick Start] guide to using fossil |
| 119 | 119 | * [./qandc.wiki | Questions & Criticisms] directed at fossil. |
| 120 | - * [./build.wiki | Building And Installing] | |
| 120 | + * [./build.wiki | Compiling and Installing] | |
| 121 | 121 | * Fossil supports [./embeddeddoc.wiki | embedded documentation] |
| 122 | 122 | that is versioned along with project source code. |
| 123 | 123 | * Fossil uses an [./fileformat.wiki | enduring file format] that is |
| 124 | 124 | designed to be readable, searchable, and extensible by people |
| 125 | 125 | not yet born. |
| 126 | 126 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -115,11 +115,11 @@ | |
| 115 | [./quotes.wiki | Quotes] about Fossil and other DVCSes. |
| 116 | * [./faq.wiki | FAQ] |
| 117 | * The [./concepts.wiki | concepts] behind fossil |
| 118 | * [./quickstart.wiki | Quick Start] guide to using fossil |
| 119 | * [./qandc.wiki | Questions & Criticisms] directed at fossil. |
| 120 | * [./build.wiki | Building And Installing] |
| 121 | * Fossil supports [./embeddeddoc.wiki | embedded documentation] |
| 122 | that is versioned along with project source code. |
| 123 | * Fossil uses an [./fileformat.wiki | enduring file format] that is |
| 124 | designed to be readable, searchable, and extensible by people |
| 125 | not yet born. |
| 126 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -115,11 +115,11 @@ | |
| 115 | [./quotes.wiki | Quotes] about Fossil and other DVCSes. |
| 116 | * [./faq.wiki | FAQ] |
| 117 | * The [./concepts.wiki | concepts] behind fossil |
| 118 | * [./quickstart.wiki | Quick Start] guide to using fossil |
| 119 | * [./qandc.wiki | Questions & Criticisms] directed at fossil. |
| 120 | * [./build.wiki | Compiling and Installing] |
| 121 | * Fossil supports [./embeddeddoc.wiki | embedded documentation] |
| 122 | that is versioned along with project source code. |
| 123 | * Fossil uses an [./fileformat.wiki | enduring file format] that is |
| 124 | designed to be readable, searchable, and extensible by people |
| 125 | not yet born. |
| 126 |
+2
-2
| --- www/mkindex.tcl | ||
| +++ www/mkindex.tcl | ||
| @@ -7,11 +7,11 @@ | ||
| 7 | 7 | # |
| 8 | 8 | |
| 9 | 9 | set doclist { |
| 10 | 10 | bugtheory.wiki {Bug Tracking In Fossil} |
| 11 | 11 | branching.wiki {Branching, Forking, Merging, and Tagging} |
| 12 | - build.wiki {Building and Installing Fossil} | |
| 12 | + build.wiki {Compiling and Installing Fossil} | |
| 13 | 13 | checkin_names.wiki {Checkin And Version Names} |
| 14 | 14 | checkin.wiki {Check-in Checklist} |
| 15 | 15 | changes.wiki {Fossil Changelog} |
| 16 | 16 | copyright-release.html {Contributor License Agreement} |
| 17 | 17 | concepts.wiki {Fossil Core Concepts} |
| @@ -77,11 +77,11 @@ | ||
| 77 | 77 | puts $out { |
| 78 | 78 | <h2>Primary Documents:</h2> |
| 79 | 79 | <ul> |
| 80 | 80 | <li> [./quickstart.wiki | Quick-start Guide] |
| 81 | 81 | <li> [./faq.wiki | FAQ] |
| 82 | -<li> [./build.wiki | Building and installing Fossil] | |
| 82 | +<li> [./build.wiki | Compiling and installing Fossil] | |
| 83 | 83 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 84 | 84 | <li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book] |
| 85 | 85 | <li> [/help | Command-line help] |
| 86 | 86 | </ul> |
| 87 | 87 | <a name="pindex"></a> |
| 88 | 88 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -7,11 +7,11 @@ | |
| 7 | # |
| 8 | |
| 9 | set doclist { |
| 10 | bugtheory.wiki {Bug Tracking In Fossil} |
| 11 | branching.wiki {Branching, Forking, Merging, and Tagging} |
| 12 | build.wiki {Building and Installing Fossil} |
| 13 | checkin_names.wiki {Checkin And Version Names} |
| 14 | checkin.wiki {Check-in Checklist} |
| 15 | changes.wiki {Fossil Changelog} |
| 16 | copyright-release.html {Contributor License Agreement} |
| 17 | concepts.wiki {Fossil Core Concepts} |
| @@ -77,11 +77,11 @@ | |
| 77 | puts $out { |
| 78 | <h2>Primary Documents:</h2> |
| 79 | <ul> |
| 80 | <li> [./quickstart.wiki | Quick-start Guide] |
| 81 | <li> [./faq.wiki | FAQ] |
| 82 | <li> [./build.wiki | Building and installing Fossil] |
| 83 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 84 | <li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book] |
| 85 | <li> [/help | Command-line help] |
| 86 | </ul> |
| 87 | <a name="pindex"></a> |
| 88 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -7,11 +7,11 @@ | |
| 7 | # |
| 8 | |
| 9 | set doclist { |
| 10 | bugtheory.wiki {Bug Tracking In Fossil} |
| 11 | branching.wiki {Branching, Forking, Merging, and Tagging} |
| 12 | build.wiki {Compiling and Installing Fossil} |
| 13 | checkin_names.wiki {Checkin And Version Names} |
| 14 | checkin.wiki {Check-in Checklist} |
| 15 | changes.wiki {Fossil Changelog} |
| 16 | copyright-release.html {Contributor License Agreement} |
| 17 | concepts.wiki {Fossil Core Concepts} |
| @@ -77,11 +77,11 @@ | |
| 77 | puts $out { |
| 78 | <h2>Primary Documents:</h2> |
| 79 | <ul> |
| 80 | <li> [./quickstart.wiki | Quick-start Guide] |
| 81 | <li> [./faq.wiki | FAQ] |
| 82 | <li> [./build.wiki | Compiling and installing Fossil] |
| 83 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 84 | <li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book] |
| 85 | <li> [/help | Command-line help] |
| 86 | </ul> |
| 87 | <a name="pindex"></a> |
| 88 |
+3
-3
| --- www/permutedindex.wiki | ||
| +++ www/permutedindex.wiki | ||
| @@ -2,11 +2,11 @@ | ||
| 2 | 2 | |
| 3 | 3 | <h2>Primary Documents:</h2> |
| 4 | 4 | <ul> |
| 5 | 5 | <li> [./quickstart.wiki | Quick-start Guide] |
| 6 | 6 | <li> [./faq.wiki | FAQ] |
| 7 | -<li> [./build.wiki | Building and installing Fossil] | |
| 7 | +<li> [./build.wiki | Compiling and installing Fossil] | |
| 8 | 8 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 9 | 9 | <li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book] |
| 10 | 10 | <li> [/help | Command-line help] |
| 11 | 11 | </ul> |
| 12 | 12 | <a name="pindex"></a> |
| @@ -19,20 +19,20 @@ | ||
| 19 | 19 | <li><a href="password.wiki">Authentication — Password Management And</a></li> |
| 20 | 20 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 21 | 21 | <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li> |
| 22 | 22 | <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li> |
| 23 | 23 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| 24 | -<li><a href="build.wiki">Building and Installing Fossil</a></li> | |
| 25 | 24 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 26 | 25 | <li><a href="checkin.wiki">Check-in Checklist</a></li> |
| 27 | 26 | <li><a href="checkin_names.wiki">Checkin And Version Names</a></li> |
| 28 | 27 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 29 | 28 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 30 | 29 | <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> |
| 31 | 30 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 32 | 31 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| 33 | 32 | <li><a href="style.wiki">Code Style Guidelines — Source</a></li> |
| 33 | +<li><a href="build.wiki">Compiling and Installing Fossil</a></li> | |
| 34 | 34 | <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> |
| 35 | 35 | <li><a href="server.wiki">Configure A Fossil Server — How To</a></li> |
| 36 | 36 | <li><a href="shunning.wiki">Content From Fossil — Shunning: Deleting</a></li> |
| 37 | 37 | <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li> |
| 38 | 38 | <li><a href="copyright-release.html">Contributor License Agreement</a></li> |
| @@ -84,11 +84,11 @@ | ||
| 84 | 84 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 85 | 85 | <li><a href="server.wiki">How To Configure A Fossil Server</a></li> |
| 86 | 86 | <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> |
| 87 | 87 | <li><a href="tech_overview.wiki">Implementation Of Fossil — A Technical Overview Of The Design And</a></li> |
| 88 | 88 | <li><a href="inout.wiki">Import And Export To And From Git</a></li> |
| 89 | -<li><a href="build.wiki">Installing Fossil — Building and</a></li> | |
| 89 | +<li><a href="build.wiki">Installing Fossil — Compiling and</a></li> | |
| 90 | 90 | <li><a href="selfcheck.wiki">Integrity Self Checks — Fossil Repository</a></li> |
| 91 | 91 | <li><a href="webui.wiki">Interface — The Fossil Web</a></li> |
| 92 | 92 | <li><a href="copyright-release.html">License Agreement — Contributor</a></li> |
| 93 | 93 | <li><a href="password.wiki">Management And Authentication — Password</a></li> |
| 94 | 94 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> |
| 95 | 95 |
| --- www/permutedindex.wiki | |
| +++ www/permutedindex.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | |
| 3 | <h2>Primary Documents:</h2> |
| 4 | <ul> |
| 5 | <li> [./quickstart.wiki | Quick-start Guide] |
| 6 | <li> [./faq.wiki | FAQ] |
| 7 | <li> [./build.wiki | Building and installing Fossil] |
| 8 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 9 | <li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book] |
| 10 | <li> [/help | Command-line help] |
| 11 | </ul> |
| 12 | <a name="pindex"></a> |
| @@ -19,20 +19,20 @@ | |
| 19 | <li><a href="password.wiki">Authentication — Password Management And</a></li> |
| 20 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 21 | <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li> |
| 22 | <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li> |
| 23 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| 24 | <li><a href="build.wiki">Building and Installing Fossil</a></li> |
| 25 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 26 | <li><a href="checkin.wiki">Check-in Checklist</a></li> |
| 27 | <li><a href="checkin_names.wiki">Checkin And Version Names</a></li> |
| 28 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 29 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 30 | <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> |
| 31 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 32 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| 33 | <li><a href="style.wiki">Code Style Guidelines — Source</a></li> |
| 34 | <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> |
| 35 | <li><a href="server.wiki">Configure A Fossil Server — How To</a></li> |
| 36 | <li><a href="shunning.wiki">Content From Fossil — Shunning: Deleting</a></li> |
| 37 | <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li> |
| 38 | <li><a href="copyright-release.html">Contributor License Agreement</a></li> |
| @@ -84,11 +84,11 @@ | |
| 84 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 85 | <li><a href="server.wiki">How To Configure A Fossil Server</a></li> |
| 86 | <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> |
| 87 | <li><a href="tech_overview.wiki">Implementation Of Fossil — A Technical Overview Of The Design And</a></li> |
| 88 | <li><a href="inout.wiki">Import And Export To And From Git</a></li> |
| 89 | <li><a href="build.wiki">Installing Fossil — Building and</a></li> |
| 90 | <li><a href="selfcheck.wiki">Integrity Self Checks — Fossil Repository</a></li> |
| 91 | <li><a href="webui.wiki">Interface — The Fossil Web</a></li> |
| 92 | <li><a href="copyright-release.html">License Agreement — Contributor</a></li> |
| 93 | <li><a href="password.wiki">Management And Authentication — Password</a></li> |
| 94 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> |
| 95 |
| --- www/permutedindex.wiki | |
| +++ www/permutedindex.wiki | |
| @@ -2,11 +2,11 @@ | |
| 2 | |
| 3 | <h2>Primary Documents:</h2> |
| 4 | <ul> |
| 5 | <li> [./quickstart.wiki | Quick-start Guide] |
| 6 | <li> [./faq.wiki | FAQ] |
| 7 | <li> [./build.wiki | Compiling and installing Fossil] |
| 8 | <li> [../COPYRIGHT-BSD2.txt | License] |
| 9 | <li> [http://www.fossil-scm.org/schimpf-book/home | Jim Schimpf's book] |
| 10 | <li> [/help | Command-line help] |
| 11 | </ul> |
| 12 | <a name="pindex"></a> |
| @@ -19,20 +19,20 @@ | |
| 19 | <li><a href="password.wiki">Authentication — Password Management And</a></li> |
| 20 | <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> |
| 21 | <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li> |
| 22 | <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li> |
| 23 | <li><a href="makefile.wiki">Build Process — The Fossil</a></li> |
| 24 | <li><a href="changes.wiki">Changelog — Fossil</a></li> |
| 25 | <li><a href="checkin.wiki">Check-in Checklist</a></li> |
| 26 | <li><a href="checkin_names.wiki">Checkin And Version Names</a></li> |
| 27 | <li><a href="checkin.wiki">Checklist — Check-in</a></li> |
| 28 | <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> |
| 29 | <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> |
| 30 | <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> |
| 31 | <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> |
| 32 | <li><a href="style.wiki">Code Style Guidelines — Source</a></li> |
| 33 | <li><a href="build.wiki">Compiling and Installing Fossil</a></li> |
| 34 | <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> |
| 35 | <li><a href="server.wiki">Configure A Fossil Server — How To</a></li> |
| 36 | <li><a href="shunning.wiki">Content From Fossil — Shunning: Deleting</a></li> |
| 37 | <li><a href="contribute.wiki">Contributing Code or Documentation To The Fossil Project</a></li> |
| 38 | <li><a href="copyright-release.html">Contributor License Agreement</a></li> |
| @@ -84,11 +84,11 @@ | |
| 84 | <li><a href="selfhost.wiki">Hosting Repositories — Fossil Self</a></li> |
| 85 | <li><a href="server.wiki">How To Configure A Fossil Server</a></li> |
| 86 | <li><a href="newrepo.wiki">How To Create A New Fossil Repository</a></li> |
| 87 | <li><a href="tech_overview.wiki">Implementation Of Fossil — A Technical Overview Of The Design And</a></li> |
| 88 | <li><a href="inout.wiki">Import And Export To And From Git</a></li> |
| 89 | <li><a href="build.wiki">Installing Fossil — Compiling and</a></li> |
| 90 | <li><a href="selfcheck.wiki">Integrity Self Checks — Fossil Repository</a></li> |
| 91 | <li><a href="webui.wiki">Interface — The Fossil Web</a></li> |
| 92 | <li><a href="copyright-release.html">License Agreement — Contributor</a></li> |
| 93 | <li><a href="password.wiki">Management And Authentication — Password</a></li> |
| 94 | <li><a href="branching.wiki">Merging, and Tagging — Branching, Forking,</a></li> |
| 95 |
+1
-1
| --- www/quickstart.wiki | ||
| +++ www/quickstart.wiki | ||
| @@ -7,11 +7,11 @@ | ||
| 7 | 7 | <h2>Installing</h2> |
| 8 | 8 | |
| 9 | 9 | <p>Fossil is a single self-contained C program. You need to |
| 10 | 10 | either download a |
| 11 | 11 | <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> |
| 12 | - or <a href="build.wiki">build it yourself</a> from sources. | |
| 12 | + or <a href="build.wiki">compile it yourself</a> from sources. | |
| 13 | 13 | Install fossil by putting the fossil binary |
| 14 | 14 | someplace on your $PATH.</p> |
| 15 | 15 | |
| 16 | 16 | <a name="fslclone"></a> |
| 17 | 17 | <h2>General Work Flow</h2> |
| 18 | 18 |
| --- www/quickstart.wiki | |
| +++ www/quickstart.wiki | |
| @@ -7,11 +7,11 @@ | |
| 7 | <h2>Installing</h2> |
| 8 | |
| 9 | <p>Fossil is a single self-contained C program. You need to |
| 10 | either download a |
| 11 | <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> |
| 12 | or <a href="build.wiki">build it yourself</a> from sources. |
| 13 | Install fossil by putting the fossil binary |
| 14 | someplace on your $PATH.</p> |
| 15 | |
| 16 | <a name="fslclone"></a> |
| 17 | <h2>General Work Flow</h2> |
| 18 |
| --- www/quickstart.wiki | |
| +++ www/quickstart.wiki | |
| @@ -7,11 +7,11 @@ | |
| 7 | <h2>Installing</h2> |
| 8 | |
| 9 | <p>Fossil is a single self-contained C program. You need to |
| 10 | either download a |
| 11 | <a href="http://www.fossil-scm.org/download.html">precompiled binary</a> |
| 12 | or <a href="build.wiki">compile it yourself</a> from sources. |
| 13 | Install fossil by putting the fossil binary |
| 14 | someplace on your $PATH.</p> |
| 15 | |
| 16 | <a name="fslclone"></a> |
| 17 | <h2>General Work Flow</h2> |
| 18 |