Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge trunk. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | skin-ardoise |
Files: | files | file ages | folders |
SHA3-256: |
9cd063dc388af63098c888945dba7bcc |
User & Date: | achavasse 2018-01-11 23:03:11.083 |
Context
2018-01-11
| ||
23:07 | Reskinned the ticket view and switched to black text in the ticket reports so that they are readable with the default colors. ... (check-in: 77f23cbe user: achavasse tags: skin-ardoise) | |
23:03 | Merge trunk. ... (check-in: 9cd063dc user: achavasse tags: skin-ardoise) | |
02:37 | Add all recommended compile-time options for the SQLite shell. ... (check-in: a5c48cdf user: drh tags: trunk) | |
2018-01-08
| ||
23:20 | Enlarge the diff view font and tweak the diff highlight colors. The skin was globally widened to accomodate more space for the diff view. ... (check-in: 34ab58c2 user: achavasse tags: skin-ardoise) | |
Changes
Changes to src/cson_amalgamation.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 | # ifdef _MSC_VER # ifdef JSON_PARSER_DLL_EXPORTS # define JSON_PARSER_DLL_API __declspec(dllexport) # else # define JSON_PARSER_DLL_API __declspec(dllimport) # endif # else | | | | | | | | | | | | | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | # ifdef _MSC_VER # ifdef JSON_PARSER_DLL_EXPORTS # define JSON_PARSER_DLL_API __declspec(dllexport) # else # define JSON_PARSER_DLL_API __declspec(dllimport) # endif # else # define JSON_PARSER_DLL_API # endif #else # define JSON_PARSER_DLL_API #endif /* Determine the integer type use to parse non-floating point numbers */ #ifdef _WIN32 typedef __int64 JSON_int_t; #define JSON_PARSER_INTEGER_SSCANF_TOKEN "%I64d" #define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%I64d" #elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1) typedef long long JSON_int_t; #define JSON_PARSER_INTEGER_SSCANF_TOKEN "%lld" #define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%lld" #else typedef long JSON_int_t; #define JSON_PARSER_INTEGER_SSCANF_TOKEN "%ld" #define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%ld" #endif #ifdef __cplusplus extern "C" { #endif typedef enum { JSON_E_NONE = 0, JSON_E_INVALID_CHAR, JSON_E_INVALID_KEYWORD, JSON_E_INVALID_ESCAPE_SEQUENCE, JSON_E_INVALID_UNICODE_SEQUENCE, JSON_E_INVALID_NUMBER, JSON_E_NESTING_DEPTH_REACHED, JSON_E_UNBALANCED_COLLECTION, JSON_E_EXPECTED_KEY, JSON_E_EXPECTED_COLON, JSON_E_OUT_OF_MEMORY } JSON_error; typedef enum { JSON_T_NONE = 0, JSON_T_ARRAY_BEGIN, JSON_T_ARRAY_END, JSON_T_OBJECT_BEGIN, JSON_T_OBJECT_END, JSON_T_INTEGER, JSON_T_FLOAT, JSON_T_NULL, JSON_T_TRUE, JSON_T_FALSE, JSON_T_STRING, JSON_T_KEY, JSON_T_MAX } JSON_type; typedef struct JSON_value_struct { union { JSON_int_t integer_value; double float_value; struct { const char* value; size_t length; } str; } vu; } JSON_value; typedef struct JSON_parser_struct* JSON_parser; /*! \brief JSON parser callback \param ctx The pointer passed to new_JSON_parser. \param type An element of JSON_type but not JSON_T_NONE. \param value A representation of the parsed value. This parameter is NULL for JSON_T_ARRAY_BEGIN, JSON_T_ARRAY_END, JSON_T_OBJECT_BEGIN, JSON_T_OBJECT_END, JSON_T_NULL, JSON_T_TRUE, and JSON_T_FALSE. String values are always returned as zero-terminated C strings. \return Non-zero if parsing should continue, else zero. */ typedef int (*JSON_parser_callback)(void* ctx, int type, const JSON_value* value); /** A typedef for allocator functions semantically compatible with malloc(). */ typedef void* (*JSON_malloc_t)(size_t n); /** A typedef for deallocator functions semantically compatible with free(). */ typedef void (*JSON_free_t)(void* mem); /*! \brief The structure used to configure a JSON parser object */ typedef struct { /** Pointer to a callback, called when the parser has something to tell the user. This parameter may be NULL. In this case the input is merely checked for validity. */ JSON_parser_callback callback; |
︙ | ︙ | |||
174 175 176 177 178 179 180 | - no comments - Uses realloc() for memory de/allocation. \param config. Used to configure the parser. */ JSON_PARSER_DLL_API void init_JSON_config(JSON_config * config); | | | | | | | | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | - no comments - Uses realloc() for memory de/allocation. \param config. Used to configure the parser. */ JSON_PARSER_DLL_API void init_JSON_config(JSON_config * config); /*! \brief Create a JSON parser object \param config. Used to configure the parser. Set to NULL to use the default configuration. See init_JSON_config. Its contents are copied by this function, so it need not outlive the returned object. \return The parser object, which is owned by the caller and must eventually be freed by calling delete_JSON_parser(). */ JSON_PARSER_DLL_API JSON_parser new_JSON_parser(JSON_config const* config); /*! \brief Destroy a previously created JSON parser object. */ JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc); /*! \brief Parse a character. \return Non-zero, if all characters passed to this function are part of are valid JSON. */ JSON_PARSER_DLL_API int JSON_parser_char(JSON_parser jc, int next_char); /*! \brief Finalize parsing. Call this method once after all input characters have been consumed. \return Non-zero, if all parsed characters are valid JSON, zero otherwise. */ JSON_PARSER_DLL_API int JSON_parser_done(JSON_parser jc); /*! \brief Determine if a given string is valid JSON white space \return Non-zero if the string is valid, zero otherwise. */ JSON_PARSER_DLL_API int JSON_parser_is_legal_white_space_string(const char* s); /*! \brief Gets the last error that occurred during the use of JSON_parser. \return A value from the JSON_error enum. */ JSON_PARSER_DLL_API int JSON_parser_get_last_error(JSON_parser jc); /*! \brief Re-sets the parser to prepare it for another parse run. \return True (non-zero) on success, 0 on error (e.g. !jc). */ JSON_PARSER_DLL_API int JSON_parser_reset(JSON_parser jc); #ifdef __cplusplus } #endif #endif /* JSON_PARSER_H */ /* end file parser/JSON_parser.h */ /* begin file parser/JSON_parser.c */ /* Copyright (c) 2007-2013 Jean Gressmann (jean@0x42.de) |
︙ | ︙ | |||
1429 1430 1431 1432 1433 1434 1435 | #endif #if defined(__cplusplus) extern "C" { #endif | | | 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 | #endif #if defined(__cplusplus) extern "C" { #endif /** This type holds the "vtbl" for type-specific operations when working with cson_value objects. All cson_values of a given logical type share a pointer to a single library-internal instance of this class. */ |
︙ | ︙ | |||
1581 1582 1583 1584 1585 1586 1587 | Assumes V is a (cson_value*) ans V->value is a (T*). Returns V->value cast to a (T*). */ #define CSON_CAST(T,V) ((T*)((V)->value)) /** Assumes V is a pointer to memory which is allocated as part of a cson_value instance (the bytes immediately after that part). | | | 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 | Assumes V is a (cson_value*) ans V->value is a (T*). Returns V->value cast to a (T*). */ #define CSON_CAST(T,V) ((T*)((V)->value)) /** Assumes V is a pointer to memory which is allocated as part of a cson_value instance (the bytes immediately after that part). Returns a pointer a a cson_value by subtracting sizeof(cson_value) from that address and casting it to a (cson_value*) */ #define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value))) /** CSON_INT(V) assumes that V is a (cson_value*) of type CSON_TYPE_INTEGER. This macro returns a (cson_int_t*) representing |
︙ | ︙ | |||
1605 1606 1607 1608 1609 1610 1611 | #define CSON_DBL(V) CSON_CAST(cson_double_t,(V)) #define CSON_STR(V) CSON_CAST(cson_string,(V)) #define CSON_OBJ(V) CSON_CAST(cson_object,(V)) #define CSON_ARRAY(V) CSON_CAST(cson_array,(V)) /** Holds special shared "constant" (though they are non-const) | | | | | | 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 | #define CSON_DBL(V) CSON_CAST(cson_double_t,(V)) #define CSON_STR(V) CSON_CAST(cson_string,(V)) #define CSON_OBJ(V) CSON_CAST(cson_object,(V)) #define CSON_ARRAY(V) CSON_CAST(cson_array,(V)) /** Holds special shared "constant" (though they are non-const) values. */ static struct CSON_EMPTY_HOLDER_ { char trueValue; cson_string stringValue; } CSON_EMPTY_HOLDER = { 1/*trueValue*/, cson_string_empty_m }; /** Indexes into the CSON_SPECIAL_VALUES array. If this enum changes in any way, makes damned sure that CSON_SPECIAL_VALUES is updated to match!!! */ enum CSON_INTERNAL_VALUES { CSON_VAL_UNDEF = 0, CSON_VAL_NULL = 1, CSON_VAL_TRUE = 2, CSON_VAL_FALSE = 3, CSON_VAL_INT_0 = 4, CSON_VAL_DBL_0 = 5, CSON_VAL_STR_EMPTY = 6, CSON_INTERNAL_VALUES_LENGTH }; /** Some "special" shared cson_value instances. These values MUST be initialized in the order specified by the CSON_INTERNAL_VALUES enum. Note that they are not const because they are used as shared-allocation objects in non-const contexts. However, the public API provides no way to modifying them, and clients who modify values directly are subject to The Wrath of Undefined Behaviour. */ static cson_value CSON_SPECIAL_VALUES[] = { |
︙ | ︙ | |||
1663 1664 1665 1666 1667 1668 1669 | }; /** Returns non-0 (true) if m is one of our special "built-in" values, e.g. from CSON_SPECIAL_VALUES and some "empty" values. | | | 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 | }; /** Returns non-0 (true) if m is one of our special "built-in" values, e.g. from CSON_SPECIAL_VALUES and some "empty" values. If this returns true, m MUST NOT be free()d! */ static char cson_value_is_builtin( void const * m ) { if((m >= (void const *)&CSON_EMPTY_HOLDER) && ( m < (void const *)(&CSON_EMPTY_HOLDER+1))) return 1; |
︙ | ︙ | |||
2181 2182 2183 2184 2185 2186 2187 | int (*visitor)(cson_kvp * obj, void * visitorState ), void * visitorState ); static int cson_value_list_visit( cson_value_list * self, int (*visitor)(cson_value * obj, void * visitorState ), void * visitorState ); #endif #endif | | | 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 | int (*visitor)(cson_kvp * obj, void * visitorState ), void * visitorState ); static int cson_value_list_visit( cson_value_list * self, int (*visitor)(cson_value * obj, void * visitorState ), void * visitorState ); #endif #endif #if 0 # define LIST_T cson_value_list # define VALUE_T cson_value * # define VALUE_T_IS_PTR 1 # define LIST_T cson_kvp_list # define VALUE_T cson_kvp * # define VALUE_T_IS_PTR 1 |
︙ | ︙ | |||
2360 2361 2362 2363 2364 2365 2366 | cson_value * cson_value_new_object() { return cson_value_object_alloc(); } cson_object * cson_new_object() { | | | 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 | cson_value * cson_value_new_object() { return cson_value_object_alloc(); } cson_object * cson_new_object() { return cson_value_get_object( cson_value_new_object() ); } cson_value * cson_value_new_array() { return cson_value_array_alloc(); } |
︙ | ︙ | |||
2606 2607 2608 2609 2610 2611 2612 | if( ! val || !val->api ) return cson_rc.ArgError; else { cson_int_t i = 0; int rc = 0; switch(val->api->typeID) { | | | 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 | if( ! val || !val->api ) return cson_rc.ArgError; else { cson_int_t i = 0; int rc = 0; switch(val->api->typeID) { case CSON_TYPE_UNDEF: case CSON_TYPE_NULL: i = 0; break; case CSON_TYPE_BOOL: { char b = 0; cson_value_fetch_bool( val, &b ); i = b; |
︙ | ︙ | |||
2659 2660 2661 2662 2663 2664 2665 | if( ! val || !val->api ) return cson_rc.ArgError; else { cson_double_t d = 0.0; int rc = 0; switch(val->api->typeID) { | | | 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 | if( ! val || !val->api ) return cson_rc.ArgError; else { cson_double_t d = 0.0; int rc = 0; switch(val->api->typeID) { case CSON_TYPE_UNDEF: case CSON_TYPE_NULL: d = 0; break; case CSON_TYPE_BOOL: { char b = 0; cson_value_fetch_bool( val, &b ); d = b ? 1.0 : 0.0; |
︙ | ︙ | |||
2789 2790 2791 2792 2793 2794 2795 | } #if 0 /** Removes and returns the last value from the given array, shrinking its size by 1. Returns NULL if ar is NULL, ar->list.count is 0, or the element at that index is NULL. | | | 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 | } #if 0 /** Removes and returns the last value from the given array, shrinking its size by 1. Returns NULL if ar is NULL, ar->list.count is 0, or the element at that index is NULL. If removeRef is true then cson_value_free() is called to remove ar's reference count for the value. In that case NULL is returned, even if the object still has live references. If removeRef is false then the caller takes over ownership of that reference count point. If removeRef is false then the caller takes over ownership |
︙ | ︙ | |||
2856 2857 2858 2859 2860 2861 2862 | { cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0); #if !defined(NDEBUG) && CSON_VOID_PTR_IS_BIG assert( sizeof(cson_int_t) <= sizeof(void *) ); #endif if( c ) { | | | | 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 | { cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0); #if !defined(NDEBUG) && CSON_VOID_PTR_IS_BIG assert( sizeof(cson_int_t) <= sizeof(void *) ); #endif if( c ) { memcpy( CSON_INT(c), &v, sizeof(v) ); } return c; } } cson_value * cson_new_double( cson_double_t v ) { return cson_value_new_double(v); } cson_value * cson_value_new_double( cson_double_t v ) { if( 0.0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0]; else { cson_value * c = cson_value_new(CSON_TYPE_DOUBLE,0); if( c ) { memcpy( CSON_DBL(c), &v, sizeof(v) ); } return c; } } cson_string * cson_new_string(char const * str, unsigned int len) { |
︙ | ︙ | |||
3066 3067 3068 3069 3070 3071 3072 | if( obj->kvp.count ) { qsort( obj->kvp.list, obj->kvp.count, sizeof(cson_kvp*), cson_kvp_cmp ); } } | | | 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 | if( obj->kvp.count ) { qsort( obj->kvp.list, obj->kvp.count, sizeof(cson_kvp*), cson_kvp_cmp ); } } #endif int cson_object_unset( cson_object * obj, char const * key ) { if( ! obj || !key || !*key ) return cson_rc.ArgError; else { unsigned int ndx = 0; |
︙ | ︙ | |||
3236 3237 3238 3239 3240 3241 3242 | If p->node is-a Object then value is inserted into the object using p->key. In any other case cson_rc.InternalError is returned. Returns cson_rc.AllocError if an allocation fails. Returns 0 on success. On error, parsing must be ceased immediately. | | | 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 | If p->node is-a Object then value is inserted into the object using p->key. In any other case cson_rc.InternalError is returned. Returns cson_rc.AllocError if an allocation fails. Returns 0 on success. On error, parsing must be ceased immediately. Ownership of val is ALWAYS TRANSFERED to this function. If this function fails, val will be cleaned up and destroyed. (This simplifies error handling in the core parser.) */ static int cson_parser_set_key( cson_parser * p, cson_value * val ) { assert( p && val ); |
︙ | ︙ | |||
3483 3484 3485 3486 3487 3488 3489 | break; } ++p->totalKeyCount; break; } case JSON_T_STRING: { cson_value * v = cson_value_new_string( value->vu.str.value, value->vu.str.length ); | | | 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 | break; } ++p->totalKeyCount; break; } case JSON_T_STRING: { cson_value * v = cson_value_new_string( value->vu.str.value, value->vu.str.length ); rc = ( NULL == v ) ? cson_rc.AllocError : cson_parser_push_value( p, v ); break; } default: assert(0); rc = cson_rc.InternalError; |
︙ | ︙ | |||
3530 3531 3532 3533 3534 3535 3536 | Cleans up all contents of p but does not free p. To properly take over ownership of the parser's root node on a successful parse: - Copy p->root's pointer and set p->root to NULL. - Eventually free up p->root with cson_value_free(). | | | 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 | Cleans up all contents of p but does not free p. To properly take over ownership of the parser's root node on a successful parse: - Copy p->root's pointer and set p->root to NULL. - Eventually free up p->root with cson_value_free(). If you do not set p->root to NULL, p->root will be freed along with any other items inserted into it (or under it) during the parsing process. */ static int cson_parser_clean( cson_parser * p ) { if( ! p ) return cson_rc.ArgError; |
︙ | ︙ | |||
3569 3570 3571 3572 3573 3574 3575 | unsigned char ch[2] = {0,0}; cson_parse_opt const opt = opt_ ? *opt_ : cson_parse_opt_empty; int rc = 0; unsigned int len = 1; cson_parse_info info = info_ ? *info_ : cson_parse_info_empty; cson_parser p = cson_parser_empty; if( ! tgt || ! src ) return cson_rc.ArgError; | | | 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 | unsigned char ch[2] = {0,0}; cson_parse_opt const opt = opt_ ? *opt_ : cson_parse_opt_empty; int rc = 0; unsigned int len = 1; cson_parse_info info = info_ ? *info_ : cson_parse_info_empty; cson_parser p = cson_parser_empty; if( ! tgt || ! src ) return cson_rc.ArgError; { JSON_config jopt = {0}; init_JSON_config( &jopt ); jopt.allow_comments = opt.allowComments; jopt.depth = opt.maxDepth; jopt.callback_ctx = &p; jopt.handle_floats_manually = 0; |
︙ | ︙ | |||
3778 3779 3780 3781 3782 3783 3784 | { unsigned char const * pos = (unsigned char const *)str; unsigned char const * end = (unsigned char const *)(str ? (str + len) : NULL); unsigned char const * next = NULL; int ch; unsigned char clen = 0; char escChar[3] = {'\\',0,0}; | | | 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 | { unsigned char const * pos = (unsigned char const *)str; unsigned char const * end = (unsigned char const *)(str ? (str + len) : NULL); unsigned char const * next = NULL; int ch; unsigned char clen = 0; char escChar[3] = {'\\',0,0}; enum { UBLen = 20 }; char ubuf[UBLen]; int rc = 0; rc = f(state, "\"", 1 ); for( ; (pos < end) && (0 == rc); pos += clen ) { ch = cson_utf8Read(pos, end, &next); if( 0 == ch ) break; |
︙ | ︙ | |||
4638 4639 4640 4641 4642 4643 4644 | #else rc = cson_value_clone(v); #endif #undef TRY_SHARING cson_value_add_reference(rc); return rc; } | | | 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 | #else rc = cson_value_clone(v); #endif #undef TRY_SHARING cson_value_add_reference(rc); return rc; } static cson_value * cson_value_clone_array( cson_value const * orig ) { unsigned int i = 0; cson_array const * asrc = cson_value_get_array( orig ); unsigned int alen = cson_array_length_get( asrc ); cson_value * destV = NULL; cson_array * destA = NULL; |
︙ | ︙ | |||
4678 4679 4680 4681 4682 4683 4684 | return NULL; } cson_value_free(cl)/*remove our artificial reference */; } } return destV; } | | | 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 | return NULL; } cson_value_free(cl)/*remove our artificial reference */; } } return destV; } static cson_value * cson_value_clone_object( cson_value const * orig ) { cson_object const * src = cson_value_get_object( orig ); cson_value * destV = NULL; cson_object * dest = NULL; cson_kvp const * kvp = NULL; cson_object_iterator iter = cson_object_iterator_empty; |
︙ | ︙ | |||
4832 4833 4834 4835 4836 4837 4838 | v = cson_strdup( "null", 4 ); break; } case CSON_TYPE_STRING: { cson_string const * jstr = cson_value_get_string(orig); unsigned const int slen = cson_string_length_bytes( jstr ); assert( NULL != jstr ); | | | 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 | v = cson_strdup( "null", 4 ); break; } case CSON_TYPE_STRING: { cson_string const * jstr = cson_value_get_string(orig); unsigned const int slen = cson_string_length_bytes( jstr ); assert( NULL != jstr ); v = cson_strdup( cson_string_cstr( jstr ), slen ); break; } case CSON_TYPE_INTEGER: { char buf[BufSize] = {0}; if( 0 < sprintf( v, "%"CSON_INT_T_PFMT, cson_value_get_integer(orig)) ) { v = cson_strdup( buf, strlen(buf) ); |
︙ | ︙ | |||
4885 4886 4887 4888 4889 4890 4891 | v = cson_strdup( "null", 4 ); break; } case CSON_TYPE_STRING: { cson_string const * jstr = cson_value_get_string(orig); unsigned const int slen = cson_string_length_bytes( jstr ); assert( NULL != jstr ); | | | 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 | v = cson_strdup( "null", 4 ); break; } case CSON_TYPE_STRING: { cson_string const * jstr = cson_value_get_string(orig); unsigned const int slen = cson_string_length_bytes( jstr ); assert( NULL != jstr ); v = cson_strdup( cson_string_cstr( jstr ), slen ); break; } case CSON_TYPE_INTEGER: { char buf[BufSize] = {0}; if( 0 < sprintf( v, "%"CSON_INT_T_PFMT, cson_value_get_integer(orig)) ) { v = cson_strdup( buf, strlen(buf) ); |
︙ | ︙ | |||
5349 5350 5351 5352 5353 5354 5355 | char const * colName = NULL; int i = 0; int rc = 0; int colCount = 0; assert(st); colCount = sqlite3_column_count(st); if( colCount <= 0 ) return NULL; | | | 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 | char const * colName = NULL; int i = 0; int rc = 0; int colCount = 0; assert(st); colCount = sqlite3_column_count(st); if( colCount <= 0 ) return NULL; aryV = cson_value_new_array(); if( ! aryV ) return NULL; ary = cson_value_get_array(aryV); assert(ary); for( i = 0; (0 ==rc) && (i < colCount); ++i ) { colName = sqlite3_column_name( st, i ); |
︙ | ︙ | |||
5489 5490 5491 5492 5493 5494 5495 | error: cson_value_free(aryV); aryV = NULL; end: return aryV; } | | | 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 | error: cson_value_free(aryV); aryV = NULL; end: return aryV; } /** Internal impl of cson_sqlite3_stmt_to_json() when the 'fat' parameter is non-0. */ static int cson_sqlite3_stmt_to_json_fat( sqlite3_stmt * st, cson_value ** tgt ) { #define RETURN(RC) { if(rootV) cson_value_free(rootV); return RC; } |
︙ | ︙ | |||
5634 5635 5636 5637 5638 5639 5640 | { sqlite3_stmt * st = NULL; int rc = sqlite3_prepare_v2( db, sql, -1, &st, NULL ); if( 0 != rc ) return cson_rc.IOError /* FIXME: Better error code? */; rc = cson_sqlite3_stmt_to_json( st, tgt, fat ); sqlite3_finalize( st ); return rc; | | | 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 | { sqlite3_stmt * st = NULL; int rc = sqlite3_prepare_v2( db, sql, -1, &st, NULL ); if( 0 != rc ) return cson_rc.IOError /* FIXME: Better error code? */; rc = cson_sqlite3_stmt_to_json( st, tgt, fat ); sqlite3_finalize( st ); return rc; } } int cson_sqlite3_bind_value( sqlite3_stmt * st, int ndx, cson_value const * v ) { int rc = 0; char convertErr = 0; if(!st) return cson_rc.ArgError; |
︙ | ︙ |
Changes to src/cson_amalgamation.h.
︙ | ︙ | |||
57 58 59 60 61 62 63 | typedef __int64 cson_int_t; #define CSON_INT_T_SFMT "I64d" #define CSON_INT_T_PFMT "I64d" #elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1) typedef long long cson_int_t; #define CSON_INT_T_SFMT "lld" #define CSON_INT_T_PFMT "lld" | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | typedef __int64 cson_int_t; #define CSON_INT_T_SFMT "I64d" #define CSON_INT_T_PFMT "I64d" #elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1) typedef long long cson_int_t; #define CSON_INT_T_SFMT "lld" #define CSON_INT_T_PFMT "lld" #else typedef long cson_int_t; #define CSON_INT_T_SFMT "ld" #define CSON_INT_T_PFMT "ld" #endif /** @typedef double_or_long_double cson_double_t |
︙ | ︙ | |||
213 214 215 216 217 218 219 | /** Convenience typedef. */ typedef struct cson_value cson_value; /** @struct cson_value | | | | | | | | | | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | /** Convenience typedef. */ typedef struct cson_value cson_value; /** @struct cson_value The core value type of this API. It is opaque to clients, and only the cson public API should be used for setting or inspecting their values. This class is opaque because stack-based usage can easily cause leaks if one does not intimately understand the underlying internal memory management (which sometimes changes). It is (as of 20110323) legal to insert a given value instance into multiple containers (they will share ownership using reference counting) as long as those insertions do not cause cycles. However, be very aware that such value re-use uses a reference to the original copy, meaning that if its value is changed once, it is changed everywhere. Also beware that multi-threaded write operations on such references leads to undefined behaviour. PLEASE read the ACHTUNGEN below... ACHTUNG #1: cson_values MUST NOT form cycles (e.g. via object or array entries). Not abiding th Holy Law Of No Cycles will lead to double-frees and the like (i.e. undefined behaviour, likely crashes due to infinite recursion or stepping on invalid (freed) pointers). ACHTUNG #2: ALL cson_values returned as non-const cson_value pointers from any public functions in the cson API are to be treated as if they are heap-allocated, and MUST be freed by client by doing ONE of: - Passing it to cson_value_free(). - Adding it to an Object or Array, in which case the object/array takes over ownership. As of 20110323, a value may be inserted into a single container multiple times, or into multiple containers, in which case they all share ownership (via reference counting) of the original value (meaning any changes to it are visible in all references to it). Each call to cson_value_new_xxx() MUST eventually be followed up by one of those options. Some cson_value_new_XXX() implementations do not actually allocate memory, but this is an internal implementation detail. Client code MUST NOT rely on this behaviour and MUST treat each object returned by such a function as if it was a freshly-allocated copy (even if their pointer addresses are the same). ACHTUNG #3: Note that ACHTUNG #2 tells us that we must always free (or transfer ownership of) all pointers returned bycson_value_new_xxx(), but that two calls to (e.g.) cson_value_new_bool(1) will (or might) return the same address. The client must not rely on the "non-allocation" policy of such special cases, and must pass each |
︙ | ︙ | |||
313 314 315 316 317 318 319 | @code int rc = cson_some_func(...); if( 0 == rc ) {...success...} else if( cson_rc.ArgError == rc ) { ... some argument was wrong ... } else if( cson_rc.AllocError == rc ) { ... allocation error ... } ... @endcode | | | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | @code int rc = cson_some_func(...); if( 0 == rc ) {...success...} else if( cson_rc.ArgError == rc ) { ... some argument was wrong ... } else if( cson_rc.AllocError == rc ) { ... allocation error ... } ... @endcode The entries named Parse_XXX are generally only returned by cson_parse() and friends. */ /** @struct cson_rc_ See \ref cson_rc for details. */ |
︙ | ︙ | |||
470 471 472 473 474 475 476 | */ unsigned int col; /** Length, in bytes. */ unsigned int length; | | | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | */ unsigned int col; /** Length, in bytes. */ unsigned int length; /** Error code of the parse run (0 for no error). */ int errorCode; /** The total number of object keys successfully processed by the |
︙ | ︙ | |||
521 522 523 524 525 526 527 | struct cson_output_opt { /** Specifies how to indent (or not) output. The values are: (0) == no extra indentation. | | | | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | struct cson_output_opt { /** Specifies how to indent (or not) output. The values are: (0) == no extra indentation. (1) == 1 TAB character for each level. (>1) == that number of SPACES for each level. */ unsigned char indentation; /** Maximum object/array depth to traverse. Traversing deeply can be indicative of cycles in the object/array tree, and this value is used to figure out when to abort the traversal. */ unsigned short maxDepth; /** If true, a newline will be added to generated output, else not. */ char addNewline; /** |
︙ | ︙ | |||
634 635 636 637 638 639 640 | returns, so the implementation must copy or ignore the data, but not hold a copy of the src pointer. Must return 0 on success, non-0 on error (preferably a value from cson_rc). These functions are called relatively often during the JSON-output | | | 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 | returns, so the implementation must copy or ignore the data, but not hold a copy of the src pointer. Must return 0 on success, non-0 on error (preferably a value from cson_rc). These functions are called relatively often during the JSON-output process, and should try to be fast. */ typedef int (*cson_data_dest_f)( void * state, void const * src, unsigned int n ); /** Reads JSON-formatted string data (in ASCII, UTF8, or UTF16), using the src function to fetch all input. This function fetches each input character from the source function, which is calls like src(srcState, buffer, bufferSize), |
︙ | ︙ | |||
662 663 664 665 666 667 668 | which contains any settings the caller wants. If it is NULL then default settings (the values defined in cson_parse_opt_empty) are used. The info argument may be NULL. If it is not NULL then the parser populates it with information which is useful in error reporting. Namely, it contains the line/column of parse errors. | | | | 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | which contains any settings the caller wants. If it is NULL then default settings (the values defined in cson_parse_opt_empty) are used. The info argument may be NULL. If it is not NULL then the parser populates it with information which is useful in error reporting. Namely, it contains the line/column of parse errors. The srcState argument is ignored by this function but is passed on to src, so any output-destination-specific state can be stored there and accessed via the src callback. Non-parse error conditions include: - (!tgt) or !src: cson_rc.ArgError - cson_rc.AllocError can happen at any time during the input phase Here's a complete example of using a custom input source: |
︙ | ︙ | |||
723 724 725 726 727 728 729 | cson_parse_FILE() or cson_parse_string(). TODOs: - Buffer the input in larger chunks. We currently read byte-by-byte, but i'm too tired to write/test the looping code for the buffering. | | | 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | cson_parse_FILE() or cson_parse_string(). TODOs: - Buffer the input in larger chunks. We currently read byte-by-byte, but i'm too tired to write/test the looping code for the buffering. @see cson_parse_FILE() @see cson_parse_string() */ int cson_parse( cson_value ** tgt, cson_data_source_f src, void * srcState, cson_parse_opt const * opt, cson_parse_info * info ); /** A cson_data_source_f() implementation which requires the state argument |
︙ | ︙ | |||
784 785 786 787 788 789 790 | cson_rc.RangeError is returned. The destState parameter is ignored by this function and is passed on to the dest function. Returns 0 on success. On error, any amount of output might have been generated before the error was triggered. | | | 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 | cson_rc.RangeError is returned. The destState parameter is ignored by this function and is passed on to the dest function. Returns 0 on success. On error, any amount of output might have been generated before the error was triggered. Example: @code int rc = cson_output( myValue, cson_data_dest_FILE, stdout, NULL ); // basically equivalent to: cson_output_FILE( myValue, stdout, NULL ); // but note that cson_output_FILE() actually uses different defaults // for the output options. |
︙ | ︙ | |||
923 924 925 926 927 928 929 | typedef struct cson_string cson_string; /** Converts the given value to a boolean, using JavaScript semantics depending on the concrete type of val: undef or null: false | | | | | | | 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 | typedef struct cson_string cson_string; /** Converts the given value to a boolean, using JavaScript semantics depending on the concrete type of val: undef or null: false boolean: same integer, double: 0 or 0.0 == false, else true object, array: true string: length-0 string is false, else true. Returns 0 on success and assigns *v (if v is not NULL) to either 0 or 1. On error (val is NULL) then v is not modified. */ int cson_value_fetch_bool( cson_value const * val, char * v ); /** Similar to cson_value_fetch_bool(), but fetches an integer value. The conversion, if any, depends on the concrete type of val: NULL, null, undefined: *v is set to 0 and 0 is returned. string, object, array: *v is set to 0 and cson_rc.TypeError is returned. The error may normally be safely ignored, but it is provided for those wanted to know whether a direct conversion was possible. integer: *v is set to the int value and 0 is returned. double: *v is set to the value truncated to int and 0 is returned. */ int cson_value_fetch_integer( cson_value const * val, cson_int_t * v ); /** The same conversions and return values as cson_value_fetch_integer(), except that the roles of int/double are |
︙ | ︙ | |||
1082 1083 1084 1085 1086 1087 1088 | they are equivalent, or a positive number if lhs is greater-than rhs. It has the following rules for equivalence: - The maximum number of bytes compared is the lesser of rhsLen and the length of lhs. If the strings do not match, but compare equal up to the just-described comparison length, the shorter string is considered to be less-than the longer one. | | | 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 | they are equivalent, or a positive number if lhs is greater-than rhs. It has the following rules for equivalence: - The maximum number of bytes compared is the lesser of rhsLen and the length of lhs. If the strings do not match, but compare equal up to the just-described comparison length, the shorter string is considered to be less-than the longer one. - If lhs and rhs are both NULL, or both have a length of 0 then they will compare equal. - If lhs is null/length-0 but rhs is not then lhs is considered to be less-than rhs. - If rhs is null/length-0 but lhs is not then rhs is considered to be less-than |
︙ | ︙ | |||
1108 1109 1110 1111 1112 1113 1114 | /** Returns the length, in bytes, of str, or 0 if str is NULL. This is an O(1) operation. TODO: add cson_string_length_chars() (is O(N) unless we add another member to store the char length). | | | 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 | /** Returns the length, in bytes, of str, or 0 if str is NULL. This is an O(1) operation. TODO: add cson_string_length_chars() (is O(N) unless we add another member to store the char length). @see cson_string_cstr() */ unsigned int cson_string_length_bytes( cson_string const * str ); /** Returns the number of UTF8 characters in str. This value will be at most as long as cson_string_length_bytes() for the |
︙ | ︙ | |||
1205 1206 1207 1208 1209 1210 1211 | freed before inserting the new item. ar is expanded, if needed, to be able to hold at least (ndx+1) items, and any new entries created by that expansion are empty (NULL values). On success, 0 is returned and ownership of v is transfered to ar. | | | 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 | freed before inserting the new item. ar is expanded, if needed, to be able to hold at least (ndx+1) items, and any new entries created by that expansion are empty (NULL values). On success, 0 is returned and ownership of v is transfered to ar. On error ownership of v is NOT modified, and the caller may still need to clean it up. For example, the following code will introduce a leak if this function fails: @code cson_array_append( myArray, cson_value_new_integer(42) ); @endcode |
︙ | ︙ | |||
1238 1239 1240 1241 1242 1243 1244 | v to ar. On error, ownership of v is not modified. Ownership of ar is never changed by this function. This is functionally equivalent to cson_array_set(ar,cson_array_length_get(ar),v), but this implementation has slightly different array-preallocation policy (it grows more eagerly). | | | 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 | v to ar. On error, ownership of v is not modified. Ownership of ar is never changed by this function. This is functionally equivalent to cson_array_set(ar,cson_array_length_get(ar),v), but this implementation has slightly different array-preallocation policy (it grows more eagerly). Returns 0 on success, non-zero on error. Error cases include: - ar or v are NULL: cson_rc.ArgError - Array cannot be expanded to hold enough elements: cson_rc.AllocError. - Appending would cause a numeric overlow in the array's size: |
︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 | Alias for cson_value_new_bool(v). */ cson_value * cson_new_bool(char v); /** Returns the special JSON "null" value. When outputing JSON, its string representation is "null" (without the quotes). | | | 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 | Alias for cson_value_new_bool(v). */ cson_value * cson_new_bool(char v); /** Returns the special JSON "null" value. When outputing JSON, its string representation is "null" (without the quotes). See cson_value_new_bool() for notes regarding the returned value's memory. */ cson_value * cson_value_null(); /** Equivalent to cson_value_new_bool(1). |
︙ | ︙ | |||
1321 1322 1323 1324 1325 1326 1327 | */ cson_value * cson_new_double(cson_double_t v); /** Semantically the same as cson_value_new_bool(), but for strings. This creates a JSON value which copies the first n bytes of str. The string will automatically be NUL-terminated. | | | | | 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 | */ cson_value * cson_new_double(cson_double_t v); /** Semantically the same as cson_value_new_bool(), but for strings. This creates a JSON value which copies the first n bytes of str. The string will automatically be NUL-terminated. Note that if str is NULL or n is 0, this function still returns non-NULL value representing that empty string. Returns NULL on allocation error. See cson_value_new_bool() for important information about the returned memory. */ cson_value * cson_value_new_string( char const * str, unsigned int n ); /** Allocates a new "object" value and transfers ownership of it to the |
︙ | ︙ | |||
1352 1353 1354 1355 1356 1357 1358 | /** This works like cson_value_new_object() but returns an Object handle directly. The value handle for the returned object can be fetched with cson_object_value(theObject). | | | 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 | /** This works like cson_value_new_object() but returns an Object handle directly. The value handle for the returned object can be fetched with cson_object_value(theObject). Ownership is transfered to the caller, who must eventually free it by passing the Value handle (NOT the Object handle) to cson_value_free() or passing ownership to a parent container. Returns NULL on error (out of memory). */ cson_object * cson_new_object(); |
︙ | ︙ | |||
1417 1418 1419 1420 1421 1422 1423 | value if its reference count drops to 0. Reference counts are increased by either inserting the value into a container or via cson_value_add_reference(). Even if this function does not immediately destroy the value, the value must be considered, from the perspective of that client code, to have been destroyed/invalidated by this call. | | | 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 | value if its reference count drops to 0. Reference counts are increased by either inserting the value into a container or via cson_value_add_reference(). Even if this function does not immediately destroy the value, the value must be considered, from the perspective of that client code, to have been destroyed/invalidated by this call. @see cson_value_new_object() @see cson_value_new_array() @see cson_value_add_reference() */ void cson_value_free(cson_value * v); /** |
︙ | ︙ | |||
1443 1444 1445 1446 1447 1448 1449 | cson_object_unset(obj,key). Note that (v==NULL) is treated differently from v having the special null value. In the latter case, the key is set to the special null value. The key may be encoded as ASCII or UTF8. Results are undefined with other encodings, and the errors won't show up here, but may show up later, e.g. during output. | | | 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 | cson_object_unset(obj,key). Note that (v==NULL) is treated differently from v having the special null value. In the latter case, the key is set to the special null value. The key may be encoded as ASCII or UTF8. Results are undefined with other encodings, and the errors won't show up here, but may show up later, e.g. during output. Returns 0 on success, non-0 on error. It has the following error cases: - cson_rc.ArgError: obj or key are NULL or strlen(key) is 0. - cson_rc.AllocError: an out-of-memory error |
︙ | ︙ | |||
1496 1497 1498 1499 1500 1501 1502 | increased refcounts unless they are replacing themselves (which is a harmless no-op). */ int cson_object_set_s( cson_object * obj, cson_string * key, cson_value * v ); /** Removes a property from an object. | | | 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 | increased refcounts unless they are replacing themselves (which is a harmless no-op). */ int cson_object_set_s( cson_object * obj, cson_string * key, cson_value * v ); /** Removes a property from an object. If obj contains the given key, it is removed and 0 is returned. If it is not found, cson_rc.NotFoundError is returned (which can normally be ignored by client code). cson_rc.ArgError is returned if obj or key are NULL or key has a length of 0. |
︙ | ︙ | |||
1567 1568 1569 1570 1571 1572 1573 | and traversing its properties as the path specifies. If a given part of the path is not found, then this function fails with cson_rc.NotFoundError. If it finds the given path, it returns the value by assiging *tgt to it. If tgt is NULL then this function has no side-effects but will return 0 if the given path is found within the object, so it can be used to test for existence without fetching it. | | | | | | 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 | and traversing its properties as the path specifies. If a given part of the path is not found, then this function fails with cson_rc.NotFoundError. If it finds the given path, it returns the value by assiging *tgt to it. If tgt is NULL then this function has no side-effects but will return 0 if the given path is found within the object, so it can be used to test for existence without fetching it. Returns 0 if it finds an entry, cson_rc.NotFoundError if it finds no item, and any other non-zero error code on a "real" error. Errors include: - obj or path are NULL: cson_rc.ArgError - separator is 0, or path is an empty string or contains only separator characters: cson_rc.RangeError - There is an upper limit on how long a single path component may be (some "reasonable" internal size), and cson_rc.RangeError is returned if that length is violated. Limitations: - It has no way to fetch data from arrays this way. i could imagine, e.g., a path of "subobj.subArray.0" for subobj.subArray[0], or "0.3.1" for [0][3][1]. But i'm too lazy/tired to add this. Example usage: Assume we have a JSON structure which abstractly looks like: @code {"subobj":{"subsubobj":{"myValue":[1,2,3]}}} @endcode |
︙ | ︙ | |||
1611 1612 1613 1614 1615 1616 1617 | Note that because keys in JSON may legally contain a '.', the separator must be specified by the caller. e.g. the path "subobj/subsubobj/myValue" with separator='/' is equivalent the path "subobj.subsubobj.myValue" with separator='.'. The value of 0 is not legal as a separator character because we cannot distinguish that use from the real end-of-string without requiring the caller to also pass in the length of the string. | | | 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 | Note that because keys in JSON may legally contain a '.', the separator must be specified by the caller. e.g. the path "subobj/subsubobj/myValue" with separator='/' is equivalent the path "subobj.subsubobj.myValue" with separator='.'. The value of 0 is not legal as a separator character because we cannot distinguish that use from the real end-of-string without requiring the caller to also pass in the length of the string. Multiple successive separators in the list are collapsed into a single separator for parsing purposes. e.g. the path "a...b...c" (separator='.') is equivalent to "a.b.c". @see cson_object_get_sub() @see cson_object_get_sub2() */ |
︙ | ︙ | |||
1698 1699 1700 1701 1702 1703 1704 | code. @see cson_object_iter_init() @see cson_object_iter_next() */ struct cson_object_iterator { | | | 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 | code. @see cson_object_iter_init() @see cson_object_iter_next() */ struct cson_object_iterator { /** @internal The underlying object. */ cson_object const * obj; /** @internal Current position in the property list. */ |
︙ | ︙ | |||
1769 1770 1771 1772 1773 1774 1775 | key = cson_kvp_key(kvp); val = cson_kvp_value(kvp); ... } @endcode There is no need to clean up an iterator, as it holds no dynamic resources. | | | 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 | key = cson_kvp_key(kvp); val = cson_kvp_value(kvp); ... } @endcode There is no need to clean up an iterator, as it holds no dynamic resources. @see cson_kvp_key() @see cson_kvp_value() */ cson_kvp * cson_object_iter_next( cson_object_iterator * iter ); /** |
︙ | ︙ | |||
1861 1862 1863 1864 1865 1866 1867 | @code void * myptr = buf.mem; buf = cson_buffer_empty; @endcode (You might also need to store buf.used and buf.capacity, depending on what you want to do with the memory.) | | | 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 | @code void * myptr = buf.mem; buf = cson_buffer_empty; @endcode (You might also need to store buf.used and buf.capacity, depending on what you want to do with the memory.) When doing so, the memory must eventually be passed to free() to deallocate it. */ unsigned char * mem; }; /** Convenience typedef. */ typedef struct cson_buffer cson_buffer; |
︙ | ︙ | |||
1892 1893 1894 1895 1896 1897 1898 | contents, and it should not be used except to free its contents. On error non-zero is returned. Errors include: - Invalid arguments: cson_rc.ArgError - Buffer cannot be expanded (runs out of memory): cson_rc.AllocError | | | 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 | contents, and it should not be used except to free its contents. On error non-zero is returned. Errors include: - Invalid arguments: cson_rc.ArgError - Buffer cannot be expanded (runs out of memory): cson_rc.AllocError Example usage: @code cson_buffer buf = cson_buffer_empty; // optional: cson_buffer_reserve(&buf, 1024 * 10); int rc = cson_output_buffer( myValue, &buf, NULL ); if( 0 != rc ) { |
︙ | ︙ | |||
1916 1917 1918 1919 1920 1921 1922 | { char * mem = (char *)buf.mem; buf = cson_buffer_empty; ... free(mem); } @endcode | | | | 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 | { char * mem = (char *)buf.mem; buf = cson_buffer_empty; ... free(mem); } @endcode @see cson_output() */ int cson_output_buffer( cson_value const * v, cson_buffer * buf, cson_output_opt const * opt ); /** This works identically to cson_parse_string(), but takes a cson_buffer object as its input. buf->used bytes of buf->mem are |
︙ | ︙ | |||
1991 1992 1993 1994 1995 1996 1997 | Whether or not this function succeeds, dest still owns any memory pointed to by dest->mem, and the client must eventually free it by calling cson_buffer_reserve(dest,0). dest->mem might (and possibly will) be (re)allocated by this function, so any pointers to it held from before this call might be invalidated by this call. | | | 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 | Whether or not this function succeeds, dest still owns any memory pointed to by dest->mem, and the client must eventually free it by calling cson_buffer_reserve(dest,0). dest->mem might (and possibly will) be (re)allocated by this function, so any pointers to it held from before this call might be invalidated by this call. On error non-0 is returned and dest has almost certainly been modified but its state must be considered incomplete. Errors include: - dest or src are NULL (cson_rc.ArgError) |
︙ | ︙ | |||
2040 2041 2042 2043 2044 2045 2046 | @code void * mem = buf.mem; buf = cson_buffer_empty; @endcode In which case the memory must eventually be passed to free() to | | | 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 | @code void * mem = buf.mem; buf = cson_buffer_empty; @endcode In which case the memory must eventually be passed to free() to free it. */ int cson_buffer_fill_from( cson_buffer * dest, cson_data_source_f src, void * state ); /** Increments the reference count for the given value. This is a low-level operation and should not normally be used by client code |
︙ | ︙ | |||
2070 2071 2072 2073 2074 2075 2076 | point adds a reference and simply passed the value to cson_value_free() when they're done. The object will be kept alive for other sharing points which added a reference. Normally any such value handles would be invalidated when the parent container(s) is/are cleaned up, but this function can be used to effectively delay the cleanup. | | | | 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 | point adds a reference and simply passed the value to cson_value_free() when they're done. The object will be kept alive for other sharing points which added a reference. Normally any such value handles would be invalidated when the parent container(s) is/are cleaned up, but this function can be used to effectively delay the cleanup. This function, at its lowest level, increments the value's reference count by 1. To decrement the reference count, pass the value to cson_value_free(), after which the value must be considered, from the perspective of that client code, to be destroyed (though it will not be if there are still other live references to it). cson_value_free() will not _actually_ destroy the value until its reference count drops to 0. Returns 0 on success. The only error conditions are if v is NULL (cson_rc.ArgError) or if the reference increment would overflow (cson_rc.RangeError). In theory a client would get allocation errors long before the reference count could overflow (assuming those reference counts come from container insertions, as opposed to via this function). Insider notes which clients really need to know: For shared/constant value instances, such as those returned by cson_value_true() and cson_value_null(), this function has no side effects - it does not actually modify the reference count because (A) those instances are shared across all client code and (B) those objects are static and never get cleaned up. However, that is an implementation detail which client code should not rely on. In other words, if you call cson_value_add_reference() 3 times using |
︙ | ︙ | |||
2171 2172 2173 2174 2175 2176 2177 | eventually free the value using cson_value_free() or add it to a container object/array to transfer ownership to the container. The returned object will be of the same logical type as orig. ACHTUNG: if orig contains any cyclic references at any depth level this function will endlessly recurse. (Having _any_ cyclic references violates this library's requirements.) | | | 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 | eventually free the value using cson_value_free() or add it to a container object/array to transfer ownership to the container. The returned object will be of the same logical type as orig. ACHTUNG: if orig contains any cyclic references at any depth level this function will endlessly recurse. (Having _any_ cyclic references violates this library's requirements.) Returns NULL if orig is NULL or if cloning fails. Assuming that orig is in a valid state, the only "likely" error case is that an allocation fails while constructing the clone. In other words, if cloning fails due to something other than an allocation error then either orig is in an invalid state or there is a bug. When this function clones Objects or Arrays it shares any immutable |
︙ | ︙ | |||
2276 2277 2278 2279 2280 2281 2282 | --key : Treats key as a boolean with a true value. --key=VAL : Treats VAL as either a double, integer, or string. --key= : Treats key as a JSON null (not literal NULL) value. Arguments not starting with a dash are skipped. | | | 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 | --key : Treats key as a boolean with a true value. --key=VAL : Treats VAL as either a double, integer, or string. --key= : Treats key as a JSON null (not literal NULL) value. Arguments not starting with a dash are skipped. Each key/value pair is inserted into an object. If a given key appears more than once then only the final entry is actually stored. argc and argv are expected to be values from main() (or similar, possibly adjusted to remove argv[0]). |
︙ | ︙ | |||
2432 2433 2434 2435 2436 2437 2438 | type depending on the field type reported by sqlite3_column_type(st,col): Integer, double, null, or string (TEXT and BLOB data, though not all blob data is legal for a JSON string). st must be a sqlite3_step()'d row and col must be a 0-based column index within that result row. | | | | | | 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 | type depending on the field type reported by sqlite3_column_type(st,col): Integer, double, null, or string (TEXT and BLOB data, though not all blob data is legal for a JSON string). st must be a sqlite3_step()'d row and col must be a 0-based column index within that result row. */ cson_value * cson_sqlite3_column_to_value( sqlite3_stmt * st, int col ); /** Creates a JSON Array object containing the names of all columns of the given prepared statement handle. Returns a new array value on success, which the caller owns. Its elements are in the same order as in the underlying query. On error NULL is returned. st is not traversed or freed by this function - only the column count and names are read. */ cson_value * cson_sqlite3_column_names( sqlite3_stmt * st ); /** Creates a JSON Object containing key/value pairs corresponding |
︙ | ︙ | |||
2492 2493 2494 2495 2496 2497 2498 | value which contains the JSON-form values of the given result set row. */ cson_value * cson_sqlite3_row_to_array( sqlite3_stmt * st ); /** Converts the results of an sqlite3 SELECT statement to JSON, in the form of a cson_value object tree. | | | | | | | | | | 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 | value which contains the JSON-form values of the given result set row. */ cson_value * cson_sqlite3_row_to_array( sqlite3_stmt * st ); /** Converts the results of an sqlite3 SELECT statement to JSON, in the form of a cson_value object tree. st must be a prepared, but not yet traversed, SELECT query. tgt must be a pointer to NULL (see the example below). If either of those arguments are NULL, cson_rc.ArgError is returned. This walks the query results and returns a JSON object which has a different structure depending on the value of the 'fat' argument. If 'fat' is 0 then the structure is: @code { "columns":["colName1",..."colNameN"], "rows":[ [colVal0, ... colValN], [colVal0, ... colValN], ... ] } @endcode In the "non-fat" format the order of the columns and row values is guaranteed to be the same as that of the underlying query. If 'fat' is not 0 then the structure is: @code { "columns":["colName1",..."colNameN"], "rows":[ {"colName1":value1,..."colNameN":valueN}, {"colName1":value1,..."colNameN":valueN}, ... |
︙ | ︙ | |||
2541 2542 2543 2544 2545 2546 2547 | change when passed through different JSON implementations, depending on how they implement object key/value pairs. On success it returns 0 and assigns *tgt to a newly-allocated JSON object tree (using the above structure), which the caller owns. If the query returns no rows, the "rows" value will be an empty array, as opposed to null. | | | | | | | | | | 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 | change when passed through different JSON implementations, depending on how they implement object key/value pairs. On success it returns 0 and assigns *tgt to a newly-allocated JSON object tree (using the above structure), which the caller owns. If the query returns no rows, the "rows" value will be an empty array, as opposed to null. On error non-0 is returned and *tgt is not modified. The error code cson_rc.IOError is used to indicate a db-level error, and cson_rc.TypeError is returned if sqlite3_column_count(st) returns 0 or less (indicating an invalid or non-SELECT statement). The JSON data types are determined by the column type as reported by sqlite3_column_type(): SQLITE_INTEGER: integer SQLITE_FLOAT: double SQLITE_TEXT or SQLITE_BLOB: string, and this will only work if the data is UTF8 compatible. If the db returns a literal or SQL NULL for a value it is converted to a JSON null. If it somehow finds a column type it cannot handle, the value is also converted to a NULL in the output. Example @code cson_value * json = NULL; int rc = cson_sqlite3_stmt_to_json( myStatement, &json, 1 ); if( 0 != rc ) { ... error ... } else { cson_output_FILE( json, stdout, NULL ); cson_value_free( json ); |
︙ | ︙ | |||
2601 2602 2603 2604 2605 2606 2607 | position (starting and ndx, though the array uses 0-based offsets). TODO: add Object support for named parameters. Returns 0 on success, non-0 on error. */ int cson_sqlite3_bind_value( sqlite3_stmt * st, int ndx, cson_value const * v ); | | | | 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 | position (starting and ndx, though the array uses 0-based offsets). TODO: add Object support for named parameters. Returns 0 on success, non-0 on error. */ int cson_sqlite3_bind_value( sqlite3_stmt * st, int ndx, cson_value const * v ); #if defined(__cplusplus) } /*extern "C"*/ #endif #endif /* CSON_ENABLE_SQLITE3 */ #endif /* WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED */ /* end file include/wh/cson/cson_sqlite3.h */ #endif /* FOSSIL_ENABLE_JSON */ |
Changes to src/main.mk.
︙ | ︙ | |||
549 550 551 552 553 554 555 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ -DSQLITE_ENABLE_FTS4 \ -DSQLITE_ENABLE_FTS3_PARENTHESIS \ -DSQLITE_ENABLE_DBSTAT_VTAB \ -DSQLITE_ENABLE_JSON1 \ -DSQLITE_ENABLE_FTS5 \ | | > > > | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 | -DSQLITE_DEFAULT_FILE_FORMAT=4 \ -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ -DSQLITE_ENABLE_FTS4 \ -DSQLITE_ENABLE_FTS3_PARENTHESIS \ -DSQLITE_ENABLE_DBSTAT_VTAB \ -DSQLITE_ENABLE_JSON1 \ -DSQLITE_ENABLE_FTS5 \ -DSQLITE_ENABLE_STMTVTAB \ -DSQLITE_USE_ZLIB \ -DSQLITE_INTROSPECTION_PRAGMAS \ -DSQLITE_ENABLE_DBPAGE_VTAB # Setup the options used to compile the included SQLite shell. SHELL_OPTIONS = -Dmain=sqlite3_shell \ -DSQLITE_SHELL_IS_UTF8=1 \ -DSQLITE_OMIT_LOAD_EXTENSION=1 \ -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \ -DSQLITE_SHELL_DBNAME_PROC=fossil_open |
︙ | ︙ |
Changes to src/makemake.tcl.
︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB } #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1 #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4 #lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI #lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096 # Options used to compile the included SQLite shell. | > > > | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_USE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB } #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_FTS3=1 #lappend SQLITE_OPTIONS -DSQLITE_ENABLE_STAT4 #lappend SQLITE_OPTIONS -DSQLITE_WIN32_NO_ANSI #lappend SQLITE_OPTIONS -DSQLITE_WINNT_MAX_PATH_CHARS=4096 # Options used to compile the included SQLite shell. |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
90 91 92 93 94 95 96 | #if !defined(_WIN32) && !defined(WIN32) # include <signal.h> # if !defined(__RTP__) && !defined(_WRS_KERNEL) # include <pwd.h> # endif #endif | | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | #if !defined(_WIN32) && !defined(WIN32) # include <signal.h> # if !defined(__RTP__) && !defined(_WRS_KERNEL) # include <pwd.h> # endif #endif #if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__) # include <unistd.h> # include <dirent.h> # if defined(__MINGW32__) # define DIRENT dirent # ifndef S_ISLNK # define S_ISLNK(mode) (0) # endif # endif #endif #include <sys/types.h> |
︙ | ︙ | |||
366 367 368 369 370 371 372 373 374 375 376 377 378 379 | #endif /* ** Used to prevent warnings about unused parameters */ #define UNUSED_PARAMETER(x) (void)(x) /* ** If the following flag is set, then command execution stops ** at an error if we are not interactive. */ static int bail_on_error = 0; /* | > > > > > | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | #endif /* ** Used to prevent warnings about unused parameters */ #define UNUSED_PARAMETER(x) (void)(x) /* ** Number of elements in an array */ #define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) /* ** If the following flag is set, then command execution stops ** at an error if we are not interactive. */ static int bail_on_error = 0; /* |
︙ | ︙ | |||
638 639 640 641 642 643 644 645 646 647 648 649 650 651 | free(zPrior); zResult = shell_readline(zPrompt); if( zResult && *zResult ) shell_add_history(zResult); #endif } return zResult; } /* ** A variable length string to which one can append text. */ typedef struct ShellText ShellText; struct ShellText { char *z; int n; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | free(zPrior); zResult = shell_readline(zPrompt); if( zResult && *zResult ) shell_add_history(zResult); #endif } return zResult; } /* ** Return the value of a hexadecimal digit. Return -1 if the input ** is not a hex digit. */ static int hexDigitValue(char c){ if( c>='0' && c<='9' ) return c - '0'; if( c>='a' && c<='f' ) return c - 'a' + 10; if( c>='A' && c<='F' ) return c - 'A' + 10; return -1; } /* ** Interpret zArg as an integer value, possibly with suffixes. */ static sqlite3_int64 integerValue(const char *zArg){ sqlite3_int64 v = 0; static const struct { char *zSuffix; int iMult; } aMult[] = { { "KiB", 1024 }, { "MiB", 1024*1024 }, { "GiB", 1024*1024*1024 }, { "KB", 1000 }, { "MB", 1000000 }, { "GB", 1000000000 }, { "K", 1000 }, { "M", 1000000 }, { "G", 1000000000 }, }; int i; int isNeg = 0; if( zArg[0]=='-' ){ isNeg = 1; zArg++; }else if( zArg[0]=='+' ){ zArg++; } if( zArg[0]=='0' && zArg[1]=='x' ){ int x; zArg += 2; while( (x = hexDigitValue(zArg[0]))>=0 ){ v = (v<<4) + x; zArg++; } }else{ while( IsDigit(zArg[0]) ){ v = v*10 + zArg[0] - '0'; zArg++; } } for(i=0; i<ArraySize(aMult); i++){ if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){ v *= aMult[i].iMult; break; } } return isNeg? -v : v; } /* ** A variable length string to which one can append text. */ typedef struct ShellText ShellText; struct ShellText { char *z; int n; |
︙ | ︙ | |||
816 817 818 819 820 821 822 | sqlite3_context *pCtx, int nVal, sqlite3_value **apVal ){ const char *zName = (const char*)sqlite3_value_text(apVal[0]); char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName); if( zFake ){ | | > | 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 | sqlite3_context *pCtx, int nVal, sqlite3_value **apVal ){ const char *zName = (const char*)sqlite3_value_text(apVal[0]); char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName); if( zFake ){ sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake), -1, sqlite3_free); free(zFake); } } /* ** SQL function: shell_add_schema(S,X) ** ** Add the schema name X to the CREATE statement in S and return the result. |
︙ | ︙ | |||
877 878 879 880 881 882 883 | } } if( zName && aPrefix[i][0]=='V' && (zFake = shellFakeSchema(db, zSchema, zName))!=0 ){ if( z==0 ){ | | | > | 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 | } } if( zName && aPrefix[i][0]=='V' && (zFake = shellFakeSchema(db, zSchema, zName))!=0 ){ if( z==0 ){ z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake); }else{ z = sqlite3_mprintf("%z\n/* %s */", z, zFake); } free(zFake); } if( z ){ sqlite3_result_text(pCtx, z, -1, sqlite3_free); return; } } } |
︙ | ︙ | |||
2066 2067 2068 2069 2070 2071 2072 | # include <utime.h> #else # include "windows.h" # include <io.h> # include <direct.h> /* # include "test_windirent.h" */ # define dirent DIRENT | | | > | | 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 | # include <utime.h> #else # include "windows.h" # include <io.h> # include <direct.h> /* # include "test_windirent.h" */ # define dirent DIRENT # ifndef stat # define stat _stat # endif # define mkdir(path,mode) _mkdir(path) # define lstat(path,buf) stat(path,buf) #endif #include <time.h> #include <errno.h> #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)" |
︙ | ︙ | |||
2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 | }else if( S_ISDIR(mode) ){ ctxErrorMsg(context, "failed to create directory: %s", zFile); }else{ ctxErrorMsg(context, "failed to write file: %s", zFile); } } } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Cursor type for recursively iterating through a directory structure. */ typedef struct fsdir_cursor fsdir_cursor; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 | }else if( S_ISDIR(mode) ){ ctxErrorMsg(context, "failed to create directory: %s", zFile); }else{ ctxErrorMsg(context, "failed to write file: %s", zFile); } } } /* ** SQL function: lsmode(MODE) ** ** Given a numberic st_mode from stat(), convert it into a human-readable ** text string in the style of "ls -l". */ static void lsModeFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ int i; int iMode = sqlite3_value_int(argv[0]); char z[16]; if( S_ISLNK(iMode) ){ z[0] = 'l'; }else if( S_ISREG(iMode) ){ z[0] = '-'; }else if( S_ISDIR(iMode) ){ z[0] = 'd'; }else{ z[0] = '?'; } for(i=0; i<3; i++){ int m = (iMode >> ((2-i)*3)); char *a = &z[1 + i*3]; a[0] = (m & 0x4) ? 'r' : '-'; a[1] = (m & 0x2) ? 'w' : '-'; a[2] = (m & 0x1) ? 'x' : '-'; } z[10] = '\0'; sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Cursor type for recursively iterating through a directory structure. */ typedef struct fsdir_cursor fsdir_cursor; |
︙ | ︙ | |||
2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 | (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0, readfileFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0, writefileFunc, 0, 0); } if( rc==SQLITE_OK ){ rc = fsdirRegister(db); } return rc; } /************************* End ../ext/misc/fileio.c ********************/ | > > > > | 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 | (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0, readfileFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0, writefileFunc, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0, lsModeFunc, 0, 0); } if( rc==SQLITE_OK ){ rc = fsdirRegister(db); } return rc; } /************************* End ../ext/misc/fileio.c ********************/ |
︙ | ︙ | |||
3883 3884 3885 3886 3887 3888 3889 | /* typedef sqlite3_int64 i64; */ /* typedef unsigned char u8; */ typedef unsigned short u16; typedef unsigned long u32; #define MIN(a,b) ((a)<(b) ? (a) : (b)) #endif | | | | | | > | | | | | 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 | /* typedef sqlite3_int64 i64; */ /* typedef unsigned char u8; */ typedef unsigned short u16; typedef unsigned long u32; #define MIN(a,b) ((a)<(b) ? (a) : (b)) #endif #define ZIPFILE_SCHEMA "CREATE TABLE y(" \ "name, /* 0: Name of file in zip archive */" \ "mode, /* 1: POSIX mode for file */" \ "mtime, /* 2: Last modification time in seconds since epoch */" \ "sz, /* 3: Size of object */" \ "rawdata, /* 4: Raw data */" \ "data, /* 5: Uncompressed data */" \ "method, /* 6: Compression method (integer) */" \ "file HIDDEN /* Name of zip file */" \ ");" #define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "f" in the above */ #define ZIPFILE_BUFFER_SIZE (64*1024) /* ** Magic numbers used to read and write zip files. ** ** ZIPFILE_NEWENTRY_MADEBY: |
︙ | ︙ | |||
4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 | (res.tm_hour << 11)); pCds->mDate = (u16)( (res.tm_mday-1) + ((res.tm_mon+1) << 5) + ((res.tm_year-80) << 9)); } /* ** Return values of columns for the row at which the series_cursor ** is currently pointing. */ static int zipfileColumn( sqlite3_vtab_cursor *cur, /* The cursor */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 | (res.tm_hour << 11)); pCds->mDate = (u16)( (res.tm_mday-1) + ((res.tm_mon+1) << 5) + ((res.tm_year-80) << 9)); } static void zipfileInflate( sqlite3_context *pCtx, /* Store error here, if any */ const u8 *aIn, /* Compressed data */ int nIn, /* Size of buffer aIn[] in bytes */ int nOut /* Expected output size */ ){ u8 *aRes = sqlite3_malloc(nOut); if( aRes==0 ){ sqlite3_result_error_nomem(pCtx); }else{ int err; z_stream str; memset(&str, 0, sizeof(str)); str.next_in = (Byte*)aIn; str.avail_in = nIn; str.next_out = (Byte*)aRes; str.avail_out = nOut; err = inflateInit2(&str, -15); if( err!=Z_OK ){ zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err); }else{ err = inflate(&str, Z_NO_FLUSH); if( err!=Z_STREAM_END ){ zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err); }else{ sqlite3_result_blob(pCtx, aRes, nOut, SQLITE_TRANSIENT); } } sqlite3_free(aRes); inflateEnd(&str); } } static int zipfileDeflate( ZipfileTab *pTab, /* Set error message here */ const u8 *aIn, int nIn, /* Input */ u8 **ppOut, int *pnOut /* Output */ ){ int nAlloc = (int)compressBound(nIn); u8 *aOut; int rc = SQLITE_OK; aOut = (u8*)sqlite3_malloc(nAlloc); if( aOut==0 ){ rc = SQLITE_NOMEM; }else{ int res; z_stream str; memset(&str, 0, sizeof(str)); str.next_in = (z_const Bytef*)aIn; str.avail_in = nIn; str.next_out = aOut; str.avail_out = nAlloc; deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); res = deflate(&str, Z_FINISH); if( res==Z_STREAM_END ){ *ppOut = aOut; *pnOut = (int)str.total_out; }else{ sqlite3_free(aOut); pTab->base.zErrMsg = sqlite3_mprintf("zipfile: deflate() error"); rc = SQLITE_ERROR; } deflateEnd(&str); } return rc; } /* ** Return values of columns for the row at which the series_cursor ** is currently pointing. */ static int zipfileColumn( sqlite3_vtab_cursor *cur, /* The cursor */ |
︙ | ︙ | |||
4544 4545 4546 4547 4548 4549 4550 | } break; } case 3: { /* sz */ sqlite3_result_int64(ctx, pCsr->cds.szUncompressed); break; } | > | > | | | | | | | | | | | | > > > | > | | | > | | 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 | } break; } case 3: { /* sz */ sqlite3_result_int64(ctx, pCsr->cds.szUncompressed); break; } case 4: /* rawdata */ case 5: { /* data */ if( i==4 || pCsr->cds.iCompression==0 || pCsr->cds.iCompression==8 ){ int sz = pCsr->cds.szCompressed; if( sz>0 ){ u8 *aBuf = sqlite3_malloc(sz); if( aBuf==0 ){ rc = SQLITE_NOMEM; }else{ FILE *pFile = zipfileGetFd(pCsr); rc = zipfileReadData(pFile, aBuf, sz, pCsr->iDataOff, &pCsr->base.pVtab->zErrMsg ); } if( rc==SQLITE_OK ){ if( i==5 && pCsr->cds.iCompression ){ zipfileInflate(ctx, aBuf, sz, pCsr->cds.szUncompressed); }else{ sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT); } sqlite3_free(aBuf); } } } break; } case 6: /* method */ sqlite3_result_int(ctx, pCsr->cds.iCompression); break; } return SQLITE_OK; } |
︙ | ︙ | |||
4792 4793 4794 4795 4796 4797 4798 | + ZIPFILE_CDS_FIXED_SZ+nFile+nExtra+nComment ); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ memset(pNew, 0, sizeof(ZipfileEntry)); pNew->zPath = (char*)&pNew[1]; | | | 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 | + ZIPFILE_CDS_FIXED_SZ+nFile+nExtra+nComment ); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ memset(pNew, 0, sizeof(ZipfileEntry)); pNew->zPath = (char*)&pNew[1]; memcpy(pNew->zPath, &aRec[ZIPFILE_CDS_FIXED_SZ], nFile); pNew->zPath[nFile] = '\0'; pNew->aCdsEntry = (u8*)&pNew->zPath[nFile+1]; pNew->nCdsEntry = ZIPFILE_CDS_FIXED_SZ+nFile+nExtra+nComment; memcpy(pNew->aCdsEntry, aRec, pNew->nCdsEntry); zipfileAddEntry(pTab, pNew); } |
︙ | ︙ | |||
4911 4912 4913 4914 4915 4916 4917 | if( rc==SQLITE_OK ){ rc = zipfileAppendData(pTab, pData, nData); } return rc; } | | > > > > > | | > > | | 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 | if( rc==SQLITE_OK ){ rc = zipfileAppendData(pTab, pData, nData); } return rc; } static int zipfileGetMode( ZipfileTab *pTab, sqlite3_value *pVal, u32 defaultMode, /* Value to use if pVal IS NULL */ u32 *pMode ){ const char *z = (const char*)sqlite3_value_text(pVal); u32 mode = 0; if( z==0 ){ mode = defaultMode; }else if( z[0]>=0 && z[0]<=9 ){ mode = (unsigned int)sqlite3_value_int(pVal); }else{ const char zTemplate[11] = "-rwxrwxrwx"; int i; if( strlen(z)!=10 ) goto parse_error; switch( z[0] ){ case '-': mode |= S_IFREG; break; case 'd': mode |= S_IFDIR; break; |
︙ | ︙ | |||
4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 | *pMode = mode; return SQLITE_OK; parse_error: pTab->base.zErrMsg = sqlite3_mprintf("zipfile: parse error in mode: %s", z); return SQLITE_ERROR; } /* ** xUpdate method. */ static int zipfileUpdate( sqlite3_vtab *pVtab, int nVal, sqlite3_value **apVal, sqlite_int64 *pRowid ){ ZipfileTab *pTab = (ZipfileTab*)pVtab; int rc = SQLITE_OK; /* Return Code */ ZipfileEntry *pNew = 0; /* New in-memory CDS entry */ | > > > > > > > > > > > > | | | | | | | > > > > > > > > | | | | | | | | | | | | | < | | | > > > > > > > | | > > > > | < < < < < | | > | < < | | | < < < < > | | < < < < | < | > > | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 | *pMode = mode; return SQLITE_OK; parse_error: pTab->base.zErrMsg = sqlite3_mprintf("zipfile: parse error in mode: %s", z); return SQLITE_ERROR; } /* ** Both (const char*) arguments point to nul-terminated strings. Argument ** nB is the value of strlen(zB). This function returns 0 if the strings are ** identical, ignoring any trailing '/' character in either path. */ static int zipfileComparePath(const char *zA, const char *zB, int nB){ int nA = (int)strlen(zA); if( zA[nA-1]=='/' ) nA--; if( zB[nB-1]=='/' ) nB--; if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0; return 1; } /* ** xUpdate method. */ static int zipfileUpdate( sqlite3_vtab *pVtab, int nVal, sqlite3_value **apVal, sqlite_int64 *pRowid ){ ZipfileTab *pTab = (ZipfileTab*)pVtab; int rc = SQLITE_OK; /* Return Code */ ZipfileEntry *pNew = 0; /* New in-memory CDS entry */ u32 mode = 0; /* Mode for new entry */ i64 mTime = 0; /* Modification time for new entry */ i64 sz = 0; /* Uncompressed size */ const char *zPath = 0; /* Path for new entry */ int nPath = 0; /* strlen(zPath) */ const u8 *pData = 0; /* Pointer to buffer containing content */ int nData = 0; /* Size of pData buffer in bytes */ int iMethod = 0; /* Compression method for new entry */ u8 *pFree = 0; /* Free this */ char *zFree = 0; /* Also free this */ ZipfileCDS cds; /* New Central Directory Structure entry */ int bIsDir = 0; int mNull; assert( pTab->zFile ); assert( pTab->pWriteFd ); if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ if( nVal>1 ){ return SQLITE_CONSTRAINT; }else{ i64 iDelete = sqlite3_value_int64(apVal[0]); ZipfileEntry *p; for(p=pTab->pFirstEntry; p; p=p->pNext){ if( p->iRowid==iDelete ){ p->bDeleted = 1; break; } } return SQLITE_OK; } } mNull = (sqlite3_value_type(apVal[5])==SQLITE_NULL ? 0x0 : 0x8) /* sz */ + (sqlite3_value_type(apVal[6])==SQLITE_NULL ? 0x0 : 0x4) /* rawdata */ + (sqlite3_value_type(apVal[7])==SQLITE_NULL ? 0x0 : 0x2) /* data */ + (sqlite3_value_type(apVal[8])==SQLITE_NULL ? 0x0 : 0x1); /* method */ if( mNull==0x00 ){ /* All four are NULL - this must be a directory */ bIsDir = 1; } else if( mNull==0x2 || mNull==0x3 ){ /* Value specified for "data", and possibly "method". This must be ** a regular file or a symlink. */ const u8 *aIn = sqlite3_value_blob(apVal[7]); int nIn = sqlite3_value_bytes(apVal[7]); int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL; iMethod = sqlite3_value_int(apVal[8]); sz = nIn; if( iMethod!=0 && iMethod!=8 ){ rc = SQLITE_CONSTRAINT; }else if( bAuto || iMethod ){ rc = zipfileDeflate(pTab, aIn, nIn, &pFree, &nData); if( rc==SQLITE_OK ){ if( iMethod || nData<nIn ){ iMethod = 8; pData = pFree; }else{ pData = aIn; nData = nIn; } } } } else if( mNull==0x0D ){ /* Values specified for "sz", "rawdata" and "method". In other words, ** pre-compressed data is being inserted. */ pData = sqlite3_value_blob(apVal[6]); nData = sqlite3_value_bytes(apVal[6]); sz = sqlite3_value_int(apVal[5]); iMethod = sqlite3_value_int(apVal[8]); if( iMethod<0 || iMethod>65535 ){ pTab->base.zErrMsg = sqlite3_mprintf( "zipfile: invalid compression method: %d", iMethod ); rc = SQLITE_ERROR; } } else{ rc = SQLITE_CONSTRAINT; } if( rc==SQLITE_OK ){ rc = zipfileGetMode(pTab, apVal[3], (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644)), &mode ); if( rc==SQLITE_OK && (bIsDir == ((mode & S_IFDIR)==0)) ){ /* The "mode" attribute is a directory, but data has been specified. ** Or vice-versa - no data but "mode" is a file or symlink. */ rc = SQLITE_CONSTRAINT; } } if( rc==SQLITE_OK ){ zPath = (const char*)sqlite3_value_text(apVal[2]); nPath = (int)strlen(zPath); if( sqlite3_value_type(apVal[4])==SQLITE_NULL ){ mTime = (sqlite3_int64)time(0); }else{ mTime = sqlite3_value_int64(apVal[4]); } } if( rc==SQLITE_OK && bIsDir ){ /* For a directory, check that the last character in the path is a ** '/'. This appears to be required for compatibility with info-zip ** (the unzip command on unix). It does not create directories ** otherwise. */ if( zPath[nPath-1]!='/' ){ zFree = sqlite3_mprintf("%s/", zPath); if( zFree==0 ){ rc = SQLITE_NOMEM; } zPath = (const char*)zFree; nPath++; } } /* Check that we're not inserting a duplicate entry */ if( rc==SQLITE_OK ){ ZipfileEntry *p; for(p=pTab->pFirstEntry; p; p=p->pNext){ if( zipfileComparePath(p->zPath, zPath, nPath)==0 ){ rc = SQLITE_CONSTRAINT; break; } } } if( rc==SQLITE_OK ){ /* Create the new CDS record. */ memset(&cds, 0, sizeof(cds)); cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY; cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED; |
︙ | ︙ | |||
5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 | /* Append the new header+file to the archive */ if( rc==SQLITE_OK ){ rc = zipfileAppendEntry(pTab, &cds, zPath, nPath, pData, nData, (u32)mTime); } sqlite3_free(pFree); return rc; } static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){ u8 *aBuf = pTab->aBuffer; zipfileWrite32(aBuf, ZIPFILE_SIGNATURE_EOCD); | > | 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 | /* Append the new header+file to the archive */ if( rc==SQLITE_OK ){ rc = zipfileAppendEntry(pTab, &cds, zPath, nPath, pData, nData, (u32)mTime); } sqlite3_free(pFree); sqlite3_free(zFree); return rc; } static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){ u8 *aBuf = pTab->aBuffer; zipfileWrite32(aBuf, ZIPFILE_SIGNATURE_EOCD); |
︙ | ︙ | |||
5193 5194 5195 5196 5197 5198 5199 | int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0); return rc; } #else /* SQLITE_OMIT_VIRTUALTABLE */ # define zipfileRegister(x) SQLITE_OK #endif | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 | int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0); return rc; } #else /* SQLITE_OMIT_VIRTUALTABLE */ # define zipfileRegister(x) SQLITE_OK #endif #ifdef _WIN32 #endif int sqlite3_zipfile_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused parameter */ return zipfileRegister(db); } /************************* End ../ext/misc/zipfile.c ********************/ /************************* Begin ../ext/misc/sqlar.c ******************/ /* ** 2017-12-17 ** ** The author disclaims copyright to this source code. In place of |
︙ | ︙ | |||
5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 | ** May you share freely, never taking more than you give. ** ************************************************************************* */ #include <assert.h> #include <string.h> #include <stdio.h> /* typedef sqlite3_int64 i64; */ /* typedef sqlite3_uint64 u64; */ typedef struct IdxColumn IdxColumn; typedef struct IdxConstraint IdxConstraint; typedef struct IdxScan IdxScan; | > > | 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 | ** May you share freely, never taking more than you give. ** ************************************************************************* */ #include <assert.h> #include <string.h> #include <stdio.h> #ifndef SQLITE_OMIT_VIRTUALTABLE /* typedef sqlite3_int64 i64; */ /* typedef sqlite3_uint64 u64; */ typedef struct IdxColumn IdxColumn; typedef struct IdxConstraint IdxConstraint; typedef struct IdxScan IdxScan; |
︙ | ︙ | |||
6050 6051 6052 6053 6054 6055 6056 | pScan->pOrder = pNew; n++; } } } } | | | 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 | pScan->pOrder = pNew; n++; } } } } pIdxInfo->estimatedCost = 1000000.0 / (n+1); return rc; } static int expertUpdate( sqlite3_vtab *pVtab, int nData, sqlite3_value **azData, |
︙ | ︙ | |||
6309 6310 6311 6312 6313 6314 6315 | if( *pRc==SQLITE_OK ){ zAppend = sqlite3_vmprintf(zFmt, ap); if( zAppend ){ nAppend = STRLEN(zAppend); zRet = (char*)sqlite3_malloc(nIn + nAppend + 1); } if( zAppend && zRet ){ | | | 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 | if( *pRc==SQLITE_OK ){ zAppend = sqlite3_vmprintf(zFmt, ap); if( zAppend ){ nAppend = STRLEN(zAppend); zRet = (char*)sqlite3_malloc(nIn + nAppend + 1); } if( zAppend && zRet ){ if( nIn ) memcpy(zRet, zIn, nIn); memcpy(&zRet[nIn], zAppend, nAppend+1); }else{ sqlite3_free(zRet); zRet = 0; *pRc = SQLITE_NOMEM; } sqlite3_free(zAppend); |
︙ | ︙ | |||
6463 6464 6465 6466 6467 6468 6469 | sqlite3 *dbm = p->dbm; int rc = SQLITE_OK; if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){ IdxTable *pTab = pScan->pTab; char *zCols = 0; char *zIdx = 0; IdxConstraint *pCons; | | | 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 | sqlite3 *dbm = p->dbm; int rc = SQLITE_OK; if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){ IdxTable *pTab = pScan->pTab; char *zCols = 0; char *zIdx = 0; IdxConstraint *pCons; unsigned int h = 0; const char *zFmt; for(pCons=pEq; pCons; pCons=pCons->pLink){ zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); } for(pCons=pTail; pCons; pCons=pCons->pLink){ zCols = idxAppendColDefn(&rc, zCols, pTab, pCons); |
︙ | ︙ | |||
7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 | const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0); const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1); zCols = idxAppendText(&rc, zCols, "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl ); zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol); } if( rc==SQLITE_OK ){ if( p->iSample==100 ){ zQuery = sqlite3_mprintf( "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder ); }else{ zQuery = sqlite3_mprintf( | > | 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 | const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0); const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1); zCols = idxAppendText(&rc, zCols, "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl ); zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol); } sqlite3_reset(pIndexXInfo); if( rc==SQLITE_OK ){ if( p->iSample==100 ){ zQuery = sqlite3_mprintf( "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder ); }else{ zQuery = sqlite3_mprintf( |
︙ | ︙ | |||
7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 | idxTableFree(p->pTable); idxWriteFree(p->pWrite); idxHashClear(&p->hIdx); sqlite3_free(p->zCandidates); sqlite3_free(p); } } /************************* End ../ext/expert/sqlite3expert.c ********************/ #if defined(SQLITE_ENABLE_SESSION) /* ** State information for a single open session */ | > > | 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 | idxTableFree(p->pTable); idxWriteFree(p->pWrite); idxHashClear(&p->hIdx); sqlite3_free(p->zCandidates); sqlite3_free(p); } } #endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */ /************************* End ../ext/expert/sqlite3expert.c ********************/ #if defined(SQLITE_ENABLE_SESSION) /* ** State information for a single open session */ |
︙ | ︙ | |||
7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 | struct ShellState { sqlite3 *db; /* The database */ u8 autoExplain; /* Automatically turn on .explain mode */ u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ u8 statsOn; /* True to display memory stats before each finalize */ u8 scanstatsOn; /* True to display scan stats before each finalize */ u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int cMode; /* temporary output mode for the current query */ int normalMode; /* Output mode before ".explain on" */ int writableSchema; /* True if PRAGMA writable_schema=ON */ int showHeader; /* True to show column names in List or Column mode */ int nCheck; /* Number of ".check" commands run */ unsigned shellFlgs; /* Various flags */ char *zDestTable; /* Name of destination table when MODE_Insert */ char zTestcase[30]; /* Name of current test case */ char colSeparator[20]; /* Column separator character for several modes */ char rowSeparator[20]; /* Row separator character for MODE_Ascii */ int colWidth[100]; /* Requested width of each column when in column mode*/ int actualWidth[100]; /* Actual width of each column */ char nullValue[20]; /* The text to print when a NULL comes back from ** the database */ char outfile[FILENAME_MAX]; /* Filename for *out */ const char *zDbFilename; /* name of the database file */ char *zFreeOnClose; /* Filename to free when closing */ | > > > > > | 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 | struct ShellState { sqlite3 *db; /* The database */ u8 autoExplain; /* Automatically turn on .explain mode */ u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ u8 statsOn; /* True to display memory stats before each finalize */ u8 scanstatsOn; /* True to display scan stats before each finalize */ u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */ u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int modePrior; /* Saved mode */ int cMode; /* temporary output mode for the current query */ int normalMode; /* Output mode before ".explain on" */ int writableSchema; /* True if PRAGMA writable_schema=ON */ int showHeader; /* True to show column names in List or Column mode */ int nCheck; /* Number of ".check" commands run */ unsigned shellFlgs; /* Various flags */ char *zDestTable; /* Name of destination table when MODE_Insert */ char *zTempFile; /* Temporary file that might need deleting */ char zTestcase[30]; /* Name of current test case */ char colSeparator[20]; /* Column separator character for several modes */ char rowSeparator[20]; /* Row separator character for MODE_Ascii */ char colSepPrior[20]; /* Saved column separator */ char rowSepPrior[20]; /* Saved row separator */ int colWidth[100]; /* Requested width of each column when in column mode*/ int actualWidth[100]; /* Actual width of each column */ char nullValue[20]; /* The text to print when a NULL comes back from ** the database */ char outfile[FILENAME_MAX]; /* Filename for *out */ const char *zDbFilename; /* name of the database file */ char *zFreeOnClose; /* Filename to free when closing */ |
︙ | ︙ | |||
7646 7647 7648 7649 7650 7651 7652 | #define SEP_Tab "\t" #define SEP_Space " " #define SEP_Comma "," #define SEP_CrLf "\r\n" #define SEP_Unit "\x1F" #define SEP_Record "\x1E" | < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 | #define SEP_Tab "\t" #define SEP_Space " " #define SEP_Comma "," #define SEP_CrLf "\r\n" #define SEP_Unit "\x1F" #define SEP_Record "\x1E" /* ** A callback for the sqlite3_log() interface. */ static void shellLog(void *pArg, int iErrCode, const char *zMsg){ ShellState *p = (ShellState*)pArg; if( p->pLog==0 ) return; utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg); fflush(p->pLog); } /* ** SQL function: shell_putsnl(X) ** ** Write the text X to the screen (or whatever output is being directed) ** adding a newline at the end, and then return X. */ static void shellPutsFunc( sqlite3_context *pCtx, int nVal, sqlite3_value **apVal ){ ShellState *p = (ShellState*)sqlite3_user_data(pCtx); utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0])); sqlite3_result_value(pCtx, apVal[0]); } /* ** SQL function: edit(VALUE) ** edit(VALUE,EDITOR) ** ** These steps: ** ** (1) Write VALUE into a temporary file. ** (2) Run program EDITOR on that temporary file. ** (3) Read the temporary file back and return its content as the result. ** (4) Delete the temporary file ** ** If the EDITOR argument is omitted, use the value in the VISUAL ** environment variable. If still there is no EDITOR, through an error. ** ** Also throw an error if the EDITOR program returns a non-zero exit code. */ static void editFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *zEditor; char *zTempFile = 0; sqlite3 *db; char *zCmd = 0; int bBin; int rc; FILE *f = 0; sqlite3_int64 sz; sqlite3_int64 x; unsigned char *p = 0; if( argc==2 ){ zEditor = (const char*)sqlite3_value_text(argv[1]); }else{ zEditor = getenv("VISUAL"); } if( zEditor==0 ){ sqlite3_result_error(context, "no editor for edit()", -1); return; } if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ sqlite3_result_error(context, "NULL input to edit()", -1); return; } db = sqlite3_context_db_handle(context); zTempFile = 0; sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile); if( zTempFile==0 ){ sqlite3_uint64 r = 0; sqlite3_randomness(sizeof(r), &r); zTempFile = sqlite3_mprintf("temp%llx", r); if( zTempFile==0 ){ sqlite3_result_error_nomem(context); return; } } bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB; f = fopen(zTempFile, bBin ? "wb" : "w"); if( f==0 ){ sqlite3_result_error(context, "edit() cannot open temp file", -1); goto edit_func_end; } sz = sqlite3_value_bytes(argv[0]); if( bBin ){ x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f); }else{ x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f); } fclose(f); f = 0; if( x!=sz ){ sqlite3_result_error(context, "edit() could not write the whole file", -1); goto edit_func_end; } zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile); if( zCmd==0 ){ sqlite3_result_error_nomem(context); goto edit_func_end; } rc = system(zCmd); sqlite3_free(zCmd); if( rc ){ sqlite3_result_error(context, "EDITOR returned non-zero", -1); goto edit_func_end; } f = fopen(zTempFile, bBin ? "rb" : "r"); if( f==0 ){ sqlite3_result_error(context, "edit() cannot reopen temp file after edit", -1); goto edit_func_end; } fseek(f, 0, SEEK_END); sz = ftell(f); rewind(f); p = sqlite3_malloc64( sz+(bBin==0) ); if( p==0 ){ sqlite3_result_error_nomem(context); goto edit_func_end; } if( bBin ){ x = fread(p, 1, sz, f); }else{ x = fread(p, 1, sz, f); p[sz] = 0; } fclose(f); f = 0; if( x!=sz ){ sqlite3_result_error(context, "could not read back the whole file", -1); goto edit_func_end; } if( bBin ){ sqlite3_result_blob(context, p, sz, sqlite3_free); }else{ sqlite3_result_text(context, (const char*)p, sz, sqlite3_free); } p = 0; edit_func_end: if( f ) fclose(f); unlink(zTempFile); sqlite3_free(zTempFile); sqlite3_free(p); } /* ** Save or restore the current output mode */ static void outputModePush(ShellState *p){ p->modePrior = p->mode; memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator)); memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator)); } static void outputModePop(ShellState *p){ p->mode = p->modePrior; memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator)); memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator)); } /* ** Output the given string as a hex-encoded blob (eg. X'1234' ) */ static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ int i; char *zBlob = (char *)pBlob; |
︙ | ︙ | |||
8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 | do{ rc = sqlite3_step(pStmt); } while( rc == SQLITE_ROW ); } } } /* ** This function is called to process SQL if the previous shell command ** was ".expert". It passes the SQL in the second argument directly to ** the sqlite3expert object. ** ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error ** code. In this case, (*pzErr) may be set to point to a buffer containing | > | 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 | do{ rc = sqlite3_step(pStmt); } while( rc == SQLITE_ROW ); } } } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** This function is called to process SQL if the previous shell command ** was ".expert". It passes the SQL in the second argument directly to ** the sqlite3expert object. ** ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error ** code. In this case, (*pzErr) may be set to point to a buffer containing |
︙ | ︙ | |||
9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 | } } sqlite3_expert_destroy(p); pState->expert.pExpert = 0; return rc; } /* ** Execute a statement or set of statements. Print ** any result rows/columns depending on the current mode ** set via the supplied callback. ** ** This is very similar to SQLite's built-in sqlite3_exec() | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 | } } sqlite3_expert_destroy(p); pState->expert.pExpert = 0; return rc; } /* ** Implementation of ".expert" dot command. */ static int expertDotCommand( ShellState *pState, /* Current shell tool state */ char **azArg, /* Array of arguments passed to dot command */ int nArg /* Number of entries in azArg[] */ ){ int rc = SQLITE_OK; char *zErr = 0; int i; int iSample = 0; assert( pState->expert.pExpert==0 ); memset(&pState->expert, 0, sizeof(ExpertInfo)); for(i=1; rc==SQLITE_OK && i<nArg; i++){ char *z = azArg[i]; int n; if( z[0]=='-' && z[1]=='-' ) z++; n = strlen30(z); if( n>=2 && 0==strncmp(z, "-verbose", n) ){ pState->expert.bVerbose = 1; } else if( n>=2 && 0==strncmp(z, "-sample", n) ){ if( i==(nArg-1) ){ raw_printf(stderr, "option requires an argument: %s\n", z); rc = SQLITE_ERROR; }else{ iSample = (int)integerValue(azArg[++i]); if( iSample<0 || iSample>100 ){ raw_printf(stderr, "value out of range: %s\n", azArg[i]); rc = SQLITE_ERROR; } } } else{ raw_printf(stderr, "unknown option: %s\n", z); rc = SQLITE_ERROR; } } if( rc==SQLITE_OK ){ pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr); if( pState->expert.pExpert==0 ){ raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr); rc = SQLITE_ERROR; }else{ sqlite3_expert_config( pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample ); } } return rc; } #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ /* ** Execute a statement or set of statements. Print ** any result rows/columns depending on the current mode ** set via the supplied callback. ** ** This is very similar to SQLite's built-in sqlite3_exec() |
︙ | ︙ | |||
9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 | int rc2; const char *zLeftover; /* Tail of unprocessed SQL */ if( pzErrMsg ){ *pzErrMsg = NULL; } if( pArg->expert.pExpert ){ rc = expertHandleSQL(pArg, zSql, pzErrMsg); return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg); } while( zSql[0] && (SQLITE_OK == rc) ){ static const char *zStmtSql; rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); if( SQLITE_OK != rc ){ if( pzErrMsg ){ *pzErrMsg = save_err_msg(db); | > > | 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 | int rc2; const char *zLeftover; /* Tail of unprocessed SQL */ if( pzErrMsg ){ *pzErrMsg = NULL; } #ifndef SQLITE_OMIT_VIRTUALTABLE if( pArg->expert.pExpert ){ rc = expertHandleSQL(pArg, zSql, pzErrMsg); return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg); } #endif while( zSql[0] && (SQLITE_OK == rc) ){ static const char *zStmtSql; rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); if( SQLITE_OK != rc ){ if( pzErrMsg ){ *pzErrMsg = save_err_msg(db); |
︙ | ︙ | |||
9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 | ".databases List names and files of attached databases\n" ".dbinfo ?DB? Show status information about the database\n" ".dump ?TABLE? ... Dump the database in an SQL text format\n" " If TABLE specified, only dump tables matching\n" " LIKE pattern TABLE.\n" ".echo on|off Turn command echo on or off\n" ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n" ".exit Exit this program\n" ".expert EXPERIMENTAL. Suggest indexes for specified queries\n" /* Because explain mode comes on automatically now, the ".explain" mode ** is removed from the help screen. It is still supported for legacy, however */ /*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/ ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n" ".headers on|off Turn display of headers on or off\n" | > | 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 9962 9963 | ".databases List names and files of attached databases\n" ".dbinfo ?DB? Show status information about the database\n" ".dump ?TABLE? ... Dump the database in an SQL text format\n" " If TABLE specified, only dump tables matching\n" " LIKE pattern TABLE.\n" ".echo on|off Turn command echo on or off\n" ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n" ".excel Display the output of next command in a spreadsheet\n" ".exit Exit this program\n" ".expert EXPERIMENTAL. Suggest indexes for specified queries\n" /* Because explain mode comes on automatically now, the ".explain" mode ** is removed from the help screen. It is still supported for legacy, however */ /*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/ ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n" ".headers on|off Turn display of headers on or off\n" |
︙ | ︙ | |||
9551 9552 9553 9554 9555 9556 9557 | " insert SQL insert statements for TABLE\n" " line One value per line\n" " list Values delimited by \"|\"\n" " quote Escape answers as for SQL\n" " tabs Tab-separated values\n" " tcl TCL list elements\n" ".nullvalue STRING Use STRING in place of NULL values\n" | | > > | | 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002 10003 10004 10005 10006 | " insert SQL insert statements for TABLE\n" " line One value per line\n" " list Values delimited by \"|\"\n" " quote Escape answers as for SQL\n" " tabs Tab-separated values\n" " tcl TCL list elements\n" ".nullvalue STRING Use STRING in place of NULL values\n" ".once (-e|-x|FILE) Output for the next SQL command only to FILE\n" " or invoke system text editor (-e) or spreadsheet (-x)\n" " on the output.\n" ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n" " The --new option starts with an empty file\n" ".output ?FILE? Send output to FILE or stdout\n" ".print STRING... Print literal STRING\n" ".prompt MAIN CONTINUE Replace the standard prompts\n" ".quit Exit this program\n" ".read FILENAME Execute SQL in FILENAME\n" ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" ".save FILE Write in-memory database into FILE\n" ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" |
︙ | ︙ | |||
9773 9774 9775 9776 9777 9778 9779 9780 9781 9782 9783 9784 9785 9786 | sqlite3_zipfile_init(p->db, 0, 0); sqlite3_sqlar_init(p->db, 0, 0); #endif sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0, shellAddSchemaName, 0, 0); sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0, shellModuleSchema, 0, 0); if( p->openMode==SHELL_OPEN_ZIPFILE ){ char *zSql = sqlite3_mprintf( "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename); sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_free(zSql); } } | > > > > > > | 10211 10212 10213 10214 10215 10216 10217 10218 10219 10220 10221 10222 10223 10224 10225 10226 10227 10228 10229 10230 | sqlite3_zipfile_init(p->db, 0, 0); sqlite3_sqlar_init(p->db, 0, 0); #endif sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0, shellAddSchemaName, 0, 0); sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0, shellModuleSchema, 0, 0); sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p, shellPutsFunc, 0, 0); sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0, editFunc, 0, 0); sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0, editFunc, 0, 0); if( p->openMode==SHELL_OPEN_ZIPFILE ){ char *zSql = sqlite3_mprintf( "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename); sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_free(zSql); } } |
︙ | ︙ | |||
9906 9907 9908 9909 9910 9911 9912 | } } z[j] = c; } if( j<i ) z[j] = 0; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 10350 10351 10352 10353 10354 10355 10356 10357 10358 10359 10360 10361 10362 10363 | } } z[j] = c; } if( j<i ) z[j] = 0; } /* ** Interpret zArg as either an integer or a boolean value. Return 1 or 0 ** for TRUE and FALSE. Return the integer value if appropriate. */ static int booleanValue(const char *zArg){ int i; if( zArg[0]=='0' && zArg[1]=='x' ){ |
︙ | ︙ | |||
10009 10010 10011 10012 10013 10014 10015 | } /* ** Try to open an output file. The names "stdout" and "stderr" are ** recognized and do the right thing. NULL is returned if the output ** filename is "off". */ | | | | 10396 10397 10398 10399 10400 10401 10402 10403 10404 10405 10406 10407 10408 10409 10410 10411 10412 10413 10414 10415 10416 10417 10418 10419 | } /* ** Try to open an output file. The names "stdout" and "stderr" are ** recognized and do the right thing. NULL is returned if the output ** filename is "off". */ static FILE *output_file_open(const char *zFile, int bTextMode){ FILE *f; if( strcmp(zFile,"stdout")==0 ){ f = stdout; }else if( strcmp(zFile, "stderr")==0 ){ f = stderr; }else if( strcmp(zFile, "off")==0 ){ f = 0; }else{ f = fopen(zFile, bTextMode ? "w" : "wb"); if( f==0 ){ utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile); } } return f; } |
︙ | ︙ | |||
10431 10432 10433 10434 10435 10436 10437 | sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); } sqlite3_close(newDb); } /* | | > > > > > > > > > > > > > > > > > > > > > > | 10818 10819 10820 10821 10822 10823 10824 10825 10826 10827 10828 10829 10830 10831 10832 10833 10834 10835 10836 10837 10838 10839 10840 10841 10842 10843 10844 10845 10846 10847 10848 10849 10850 10851 10852 10853 10854 10855 10856 10857 10858 10859 10860 10861 10862 | sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); } sqlite3_close(newDb); } /* ** Change the output file back to stdout. ** ** If the p->doXdgOpen flag is set, that means the output was being ** redirected to a temporary file named by p->zTempFile. In that case, ** launch start/open/xdg-open on that temporary file. */ static void output_reset(ShellState *p){ if( p->outfile[0]=='|' ){ #ifndef SQLITE_OMIT_POPEN pclose(p->out); #endif }else{ output_file_close(p->out); if( p->doXdgOpen ){ const char *zXdgOpenCmd = #if defined(_WIN32) "start"; #elif defined(__APPLE__) "open"; #else "xdg-open"; #endif char *zCmd; zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile); if( system(zCmd) ){ utf8_printf(stderr, "Failed: [%s]\n", zCmd); } sqlite3_free(zCmd); outputModePop(p); p->doXdgOpen = 0; } } p->outfile[0] = 0; p->out = stdout; } /* ** Run an SQL command and return the single integer result. |
︙ | ︙ | |||
10697 10698 10699 10700 10701 10702 10703 10704 10705 10706 10707 10708 10709 10710 | rc = _wunlink(z); sqlite3_free(z); #else rc = unlink(zFilename); #endif return rc; } /* ** The implementation of SQL scalar function fkey_collate_clause(), used ** by the ".lint fkey-indexes" command. This scalar function is always ** called with four arguments - the parent table name, the parent column name, ** the child table name and the child column name. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 11106 11107 11108 11109 11110 11111 11112 11113 11114 11115 11116 11117 11118 11119 11120 11121 11122 11123 11124 11125 11126 11127 11128 11129 11130 11131 11132 11133 11134 11135 11136 11137 11138 11139 11140 11141 11142 11143 11144 11145 11146 11147 11148 11149 11150 11151 11152 11153 11154 | rc = _wunlink(z); sqlite3_free(z); #else rc = unlink(zFilename); #endif return rc; } /* ** Try to delete the temporary file (if there is one) and free the ** memory used to hold the name of the temp file. */ static void clearTempFile(ShellState *p){ if( p->zTempFile==0 ) return; if( p->doXdgOpen ) return; if( shellDeleteFile(p->zTempFile) ) return; sqlite3_free(p->zTempFile); p->zTempFile = 0; } /* ** Create a new temp file name with the given suffix. */ static void newTempFile(ShellState *p, const char *zSuffix){ clearTempFile(p); sqlite3_free(p->zTempFile); p->zTempFile = 0; if( p->db ){ sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile); } if( p->zTempFile==0 ){ sqlite3_uint64 r; sqlite3_randomness(sizeof(r), &r); p->zTempFile = sqlite3_mprintf("temp%llx.%s", r, zSuffix); }else{ p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix); } if( p->zTempFile==0 ){ raw_printf(stderr, "out of memory\n"); exit(1); } } /* ** The implementation of SQL scalar function fkey_collate_clause(), used ** by the ".lint fkey-indexes" command. This scalar function is always ** called with four arguments - the parent table name, the parent column name, ** the child table name and the child column name. |
︙ | ︙ | |||
11026 11027 11028 11029 11030 11031 11032 | } } /* ** Structure representing a single ".ar" command. */ typedef struct ArCommand ArCommand; struct ArCommand { | | | | | | > > > > > | 11470 11471 11472 11473 11474 11475 11476 11477 11478 11479 11480 11481 11482 11483 11484 11485 11486 11487 11488 11489 11490 11491 11492 11493 11494 11495 | } } /* ** Structure representing a single ".ar" command. */ typedef struct ArCommand ArCommand; struct ArCommand { u8 eCmd; /* An AR_CMD_* value */ u8 bVerbose; /* True if --verbose */ u8 bZip; /* True if the archive is a ZIP */ u8 bDryRun; /* True if --dry-run */ u8 bAppend; /* True if --append */ int nArg; /* Number of command arguments */ char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */ const char *zFile; /* --file argument, or NULL */ const char *zDir; /* --directory argument, or NULL */ char **azArg; /* Array of command arguments */ ShellState *p; /* Shell state */ sqlite3 *db; /* Database containing the archive */ }; /* ** Print a usage message for the .ar command to stderr and return SQLITE_ERROR. */ static int arUsage(FILE *f){ raw_printf(f, |
︙ | ︙ | |||
11058 11059 11060 11061 11062 11063 11064 11065 11066 11067 11068 11069 11070 11071 11072 | " -u, --update Update or add files to an existing archive\n" " -t, --list List contents of archive\n" " -x, --extract Extract files from archive\n" "\n" "And zero or more optional options:\n" " -v, --verbose Print each filename as it is processed\n" " -f FILE, --file FILE Operate on archive FILE (default is current db)\n" " -C DIR, --directory DIR Change to directory DIR to read/extract files\n" "\n" "See also: http://sqlite.org/cli.html#sqlar_archive_support\n" "\n" ); return SQLITE_ERROR; } | > > | 11507 11508 11509 11510 11511 11512 11513 11514 11515 11516 11517 11518 11519 11520 11521 11522 11523 | " -u, --update Update or add files to an existing archive\n" " -t, --list List contents of archive\n" " -x, --extract Extract files from archive\n" "\n" "And zero or more optional options:\n" " -v, --verbose Print each filename as it is processed\n" " -f FILE, --file FILE Operate on archive FILE (default is current db)\n" " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS\n" " -C DIR, --directory DIR Change to directory DIR to read/extract files\n" " -n, --dryrun Show the SQL that would have occurred\n" "\n" "See also: http://sqlite.org/cli.html#sqlar_archive_support\n" "\n" ); return SQLITE_ERROR; } |
︙ | ︙ | |||
11093 11094 11095 11096 11097 11098 11099 | #define AR_CMD_LIST 3 #define AR_CMD_UPDATE 4 #define AR_CMD_HELP 5 /* ** Other (non-command) switches. */ | | | | | > > > > | | < | | 11544 11545 11546 11547 11548 11549 11550 11551 11552 11553 11554 11555 11556 11557 11558 11559 11560 11561 11562 11563 11564 11565 11566 11567 11568 11569 11570 11571 11572 11573 11574 11575 11576 11577 11578 11579 11580 11581 11582 11583 11584 11585 | #define AR_CMD_LIST 3 #define AR_CMD_UPDATE 4 #define AR_CMD_HELP 5 /* ** Other (non-command) switches. */ #define AR_SWITCH_VERBOSE 6 #define AR_SWITCH_FILE 7 #define AR_SWITCH_DIRECTORY 8 #define AR_SWITCH_APPEND 9 #define AR_SWITCH_DRYRUN 10 static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){ switch( eSwitch ){ case AR_CMD_CREATE: case AR_CMD_EXTRACT: case AR_CMD_LIST: case AR_CMD_UPDATE: case AR_CMD_HELP: if( pAr->eCmd ){ return arErrorMsg("multiple command options"); } pAr->eCmd = eSwitch; break; case AR_SWITCH_DRYRUN: pAr->bDryRun = 1; break; case AR_SWITCH_VERBOSE: pAr->bVerbose = 1; break; case AR_SWITCH_APPEND: pAr->bAppend = 1; /* Fall thru into --file */ case AR_SWITCH_FILE: pAr->zFile = zArg; break; case AR_SWITCH_DIRECTORY: pAr->zDir = zArg; break; } |
︙ | ︙ | |||
11141 11142 11143 11144 11145 11146 11147 | */ static int arParseCommand( char **azArg, /* Array of arguments passed to dot command */ int nArg, /* Number of entries in azArg[] */ ArCommand *pAr /* Populate this object */ ){ struct ArSwitch { | < > | | | | | | | | | > | | | 11595 11596 11597 11598 11599 11600 11601 11602 11603 11604 11605 11606 11607 11608 11609 11610 11611 11612 11613 11614 11615 11616 11617 11618 11619 11620 11621 11622 11623 | */ static int arParseCommand( char **azArg, /* Array of arguments passed to dot command */ int nArg, /* Number of entries in azArg[] */ ArCommand *pAr /* Populate this object */ ){ struct ArSwitch { const char *zLong; char cShort; u8 eSwitch; u8 bArg; } aSwitch[] = { { "create", 'c', AR_CMD_CREATE, 0 }, { "extract", 'x', AR_CMD_EXTRACT, 0 }, { "list", 't', AR_CMD_LIST, 0 }, { "update", 'u', AR_CMD_UPDATE, 0 }, { "help", 'h', AR_CMD_HELP, 0 }, { "verbose", 'v', AR_SWITCH_VERBOSE, 0 }, { "file", 'f', AR_SWITCH_FILE, 1 }, { "append", 'a', AR_SWITCH_APPEND, 1 }, { "directory", 'C', AR_SWITCH_DIRECTORY, 1 }, { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 }, }; int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch); struct ArSwitch *pEnd = &aSwitch[nSwitch]; if( nArg<=1 ){ return arUsage(stderr); }else{ |
︙ | ︙ | |||
11281 11282 11283 11284 11285 11286 11287 | ** code returned. Otherwise, if all specified arguments are present in ** the archive, SQLITE_OK is returned. ** ** This function strips any trailing '/' characters from each argument. ** This is consistent with the way the [tar] command seems to work on ** Linux. */ | | | > | | < | < | | < | 11736 11737 11738 11739 11740 11741 11742 11743 11744 11745 11746 11747 11748 11749 11750 11751 11752 11753 11754 11755 11756 11757 11758 11759 11760 11761 11762 11763 11764 11765 11766 11767 11768 11769 11770 11771 11772 11773 11774 11775 11776 11777 11778 | ** code returned. Otherwise, if all specified arguments are present in ** the archive, SQLITE_OK is returned. ** ** This function strips any trailing '/' characters from each argument. ** This is consistent with the way the [tar] command seems to work on ** Linux. */ static int arCheckEntries(ArCommand *pAr){ int rc = SQLITE_OK; if( pAr->nArg ){ int i, j; sqlite3_stmt *pTest = 0; shellPreparePrintf(pAr->db, &rc, &pTest, "SELECT name FROM %s WHERE name=$name", pAr->zSrcTable ); j = sqlite3_bind_parameter_index(pTest, "$name"); for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){ char *z = pAr->azArg[i]; int n = strlen30(z); int bOk = 0; while( n>0 && z[n-1]=='/' ) n--; z[n] = '\0'; sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC); if( SQLITE_ROW==sqlite3_step(pTest) ){ bOk = 1; } shellReset(&rc, pTest); if( rc==SQLITE_OK && bOk==0 ){ utf8_printf(stderr, "not found in archive: %s\n", z); rc = SQLITE_ERROR; } } shellFinalize(&rc, pTest); } return rc; } /* ** Format a WHERE clause that can be used against the "sqlar" table to ** identify all archive members that match the command arguments held ** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning. |
︙ | ︙ | |||
11337 11338 11339 11340 11341 11342 11343 | zWhere = sqlite3_mprintf("1"); }else{ int i; const char *zSep = ""; for(i=0; i<pAr->nArg; i++){ const char *z = pAr->azArg[i]; zWhere = sqlite3_mprintf( | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | | | > | | | | | < < < | > | | | | | | | | | | | | | | < < < < < | | | | | < | < > | > > > | | | > > > > > > > > > > > > > > > > > > > > | < < | < | | > > > > > > | | > > > < < | < | | < < < < < < < < < < < | | < < | < < < | < < | < < < < < < < | < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > | > > | | | < | > > | | > | > > > > > > | > | | | < | | > > | > > > > > > | > > > | | | | | > | | | > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > | 11790 11791 11792 11793 11794 11795 11796 11797 11798 11799 11800 11801 11802 11803 11804 11805 11806 11807 11808 11809 11810 11811 11812 11813 11814 11815 11816 11817 11818 11819 11820 11821 11822 11823 11824 11825 11826 11827 11828 11829 11830 11831 11832 11833 11834 11835 11836 11837 11838 11839 11840 11841 11842 11843 11844 11845 11846 11847 11848 11849 11850 11851 11852 11853 11854 11855 11856 11857 11858 11859 11860 11861 11862 11863 11864 11865 11866 11867 11868 11869 11870 11871 11872 11873 11874 11875 11876 11877 11878 11879 11880 11881 11882 11883 11884 11885 11886 11887 11888 11889 11890 11891 11892 11893 11894 11895 11896 11897 11898 11899 11900 11901 11902 11903 11904 11905 11906 11907 11908 11909 11910 11911 11912 11913 11914 11915 11916 11917 11918 11919 11920 11921 11922 11923 11924 11925 11926 11927 11928 11929 11930 11931 11932 11933 11934 11935 11936 11937 11938 11939 11940 11941 11942 11943 11944 11945 11946 11947 11948 11949 11950 11951 11952 11953 11954 11955 11956 11957 11958 11959 11960 11961 11962 11963 11964 11965 11966 11967 11968 11969 11970 11971 11972 11973 11974 11975 11976 11977 11978 11979 11980 11981 11982 11983 11984 11985 11986 11987 11988 11989 11990 11991 11992 11993 11994 11995 11996 11997 11998 11999 12000 12001 12002 12003 12004 12005 12006 12007 12008 12009 12010 12011 12012 12013 12014 12015 12016 12017 12018 12019 12020 12021 12022 12023 12024 12025 12026 12027 12028 12029 12030 12031 12032 12033 12034 12035 12036 12037 12038 12039 12040 12041 12042 12043 12044 12045 12046 12047 12048 12049 12050 12051 12052 12053 12054 12055 12056 12057 12058 12059 12060 12061 12062 12063 12064 12065 12066 12067 12068 12069 12070 12071 12072 12073 12074 12075 12076 12077 12078 12079 12080 12081 12082 12083 12084 12085 12086 12087 12088 12089 12090 12091 12092 12093 12094 12095 12096 12097 12098 12099 12100 12101 12102 12103 12104 12105 12106 12107 12108 12109 12110 12111 12112 12113 12114 12115 12116 12117 12118 12119 12120 12121 12122 12123 12124 12125 12126 12127 12128 12129 12130 12131 12132 12133 12134 12135 12136 12137 | zWhere = sqlite3_mprintf("1"); }else{ int i; const char *zSep = ""; for(i=0; i<pAr->nArg; i++){ const char *z = pAr->azArg[i]; zWhere = sqlite3_mprintf( "%z%s name = '%q' OR substr(name,1,%d) = '%q/'", zWhere, zSep, z, strlen30(z)+1, z ); if( zWhere==0 ){ *pRc = SQLITE_NOMEM; break; } zSep = " OR "; } } } *pzWhere = zWhere; } /* ** Implementation of .ar "lisT" command. */ static int arListCommand(ArCommand *pAr){ const char *zSql = "SELECT %s FROM %s WHERE %s"; const char *azCols[] = { "name", "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name" }; char *zWhere = 0; sqlite3_stmt *pSql = 0; int rc; rc = arCheckEntries(pAr); arWhereClause(&rc, pAr, &zWhere); shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose], pAr->zSrcTable, zWhere); if( pAr->bDryRun ){ utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); }else{ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ if( pAr->bVerbose ){ utf8_printf(pAr->p->out, "%s % 10d %s %s\n", sqlite3_column_text(pSql, 0), sqlite3_column_int(pSql, 1), sqlite3_column_text(pSql, 2), sqlite3_column_text(pSql, 3) ); }else{ utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); } } } shellFinalize(&rc, pSql); return rc; } /* ** Implementation of .ar "eXtract" command. */ static int arExtractCommand(ArCommand *pAr){ const char *zSql1 = "SELECT " " ($dir || name)," " writefile(($dir || name), %s, mode, mtime) " "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"; const char *azExtraArg[] = { "sqlar_uncompress(data, sz)", "data" }; sqlite3_stmt *pSql = 0; int rc = SQLITE_OK; char *zDir = 0; char *zWhere = 0; int i, j; /* If arguments are specified, check that they actually exist within ** the archive before proceeding. And formulate a WHERE clause to ** match them. */ rc = arCheckEntries(pAr); arWhereClause(&rc, pAr, &zWhere); if( rc==SQLITE_OK ){ if( pAr->zDir ){ zDir = sqlite3_mprintf("%s/", pAr->zDir); }else{ zDir = sqlite3_mprintf(""); } if( zDir==0 ) rc = SQLITE_NOMEM; } shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere ); if( rc==SQLITE_OK ){ j = sqlite3_bind_parameter_index(pSql, "$dir"); sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC); /* Run the SELECT statement twice. The first time, writefile() is called ** for all archive members that should be extracted. The second time, ** only for the directories. This is because the timestamps for ** extracted directories must be reset after they are populated (as ** populating them changes the timestamp). */ for(i=0; i<2; i++){ j = sqlite3_bind_parameter_index(pSql, "$dirOnly"); sqlite3_bind_int(pSql, j, i); if( pAr->bDryRun ){ utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql)); }else{ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ if( i==0 && pAr->bVerbose ){ utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0)); } } } shellReset(&rc, pSql); } shellFinalize(&rc, pSql); } sqlite3_free(zDir); sqlite3_free(zWhere); return rc; } /* ** Run the SQL statement in zSql. Or if doing a --dryrun, merely print it out. */ static int arExecSql(ArCommand *pAr, const char *zSql){ int rc; if( pAr->bDryRun ){ utf8_printf(pAr->p->out, "%s\n", zSql); rc = SQLITE_OK; }else{ char *zErr = 0; rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr); if( zErr ){ utf8_printf(stdout, "ERROR: %s\n", zErr); sqlite3_free(zErr); } } return rc; } /* ** Implementation of .ar "create" and "update" commands. ** ** Create the "sqlar" table in the database if it does not already exist. ** Then add each file in the azFile[] array to the archive. Directories ** are added recursively. If argument bVerbose is non-zero, a message is ** printed on stdout for each file archived. ** ** The create command is the same as update, except that it drops ** any existing "sqlar" table before beginning. */ static int arCreateOrUpdateCommand( ArCommand *pAr, /* Command arguments and options */ int bUpdate /* true for a --create. false for --update */ ){ const char *zCreate = "CREATE TABLE IF NOT EXISTS sqlar(\n" " name TEXT PRIMARY KEY, -- name of the file\n" " mode INT, -- access permissions\n" " mtime INT, -- last modification time\n" " sz INT, -- original file size\n" " data BLOB -- compressed content\n" ")"; const char *zDrop = "DROP TABLE IF EXISTS sqlar"; const char *zInsertFmt = "REPLACE INTO sqlar(name,mode,mtime,sz,data)\n" " SELECT\n" " %s,\n" " mode,\n" " mtime,\n" " CASE substr(lsmode(mode),1,1)\n" " WHEN '-' THEN length(data)\n" " WHEN 'd' THEN 0\n" " ELSE -1 END,\n" " CASE WHEN lsmode(mode) LIKE 'd%%' THEN NULL else data END\n" " FROM fsdir(%Q,%Q)\n" " WHERE lsmode(mode) NOT LIKE '?%%';"; int i; /* For iterating through azFile[] */ int rc; /* Return code */ rc = arExecSql(pAr, "SAVEPOINT ar;"); if( rc!=SQLITE_OK ) return rc; if( bUpdate==0 ){ rc = arExecSql(pAr, zDrop); if( rc!=SQLITE_OK ) return rc; } rc = arExecSql(pAr, zCreate); for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){ char *zSql = sqlite3_mprintf(zInsertFmt, pAr->bVerbose ? "shell_putsnl(name)" : "name", pAr->azArg[i], pAr->zDir); rc = arExecSql(pAr, zSql); sqlite3_free(zSql); } if( rc!=SQLITE_OK ){ arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;"); }else{ rc = arExecSql(pAr, "RELEASE ar;"); } return rc; } /* ** Implementation of ".ar" dot command. */ static int arDotCommand( ShellState *pState, /* Current shell tool state */ char **azArg, /* Array of arguments passed to dot command */ int nArg /* Number of entries in azArg[] */ ){ ArCommand cmd; int rc; memset(&cmd, 0, sizeof(cmd)); rc = arParseCommand(azArg, nArg, &cmd); if( rc==SQLITE_OK ){ int eDbType = SHELL_OPEN_UNSPEC; cmd.p = pState; cmd.db = pState->db; if( cmd.zFile ){ eDbType = deduceDatabaseType(cmd.zFile); }else{ eDbType = pState->openMode; } if( eDbType==SHELL_OPEN_ZIPFILE ){ if( cmd.zFile==0 ){ cmd.zSrcTable = sqlite3_mprintf("zip"); }else{ cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile); } if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){ utf8_printf(stderr, "zip archives are read-only\n"); rc = SQLITE_ERROR; goto end_ar_command; } cmd.bZip = 1; }else if( cmd.zFile ){ int flags; if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS; if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){ flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; }else{ flags = SQLITE_OPEN_READONLY; } cmd.db = 0; if( cmd.bDryRun ){ utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile, eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : ""); } rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0); if( rc!=SQLITE_OK ){ utf8_printf(stderr, "cannot open file: %s (%s)\n", cmd.zFile, sqlite3_errmsg(cmd.db) ); goto end_ar_command; } sqlite3_fileio_init(cmd.db, 0, 0); #ifdef SQLITE_HAVE_ZLIB sqlite3_sqlar_init(cmd.db, 0, 0); #endif sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p, shellPutsFunc, 0, 0); } if( cmd.zSrcTable==0 ){ if( cmd.eCmd!=AR_CMD_CREATE && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0) ){ utf8_printf(stderr, "database does not contain an 'sqlar' table\n"); rc = SQLITE_ERROR; goto end_ar_command; } cmd.zSrcTable = sqlite3_mprintf("sqlar"); } switch( cmd.eCmd ){ case AR_CMD_CREATE: rc = arCreateOrUpdateCommand(&cmd, 0); break; case AR_CMD_EXTRACT: rc = arExtractCommand(&cmd); break; case AR_CMD_LIST: rc = arListCommand(&cmd); break; case AR_CMD_HELP: arUsage(pState->out); break; default: assert( cmd.eCmd==AR_CMD_UPDATE ); rc = arCreateOrUpdateCommand(&cmd, 1); break; } } end_ar_command: if( cmd.db!=pState->db ){ sqlite3_close(cmd.db); } sqlite3_free(cmd.zSrcTable); return rc; } /* End of the ".archive" or ".ar" command logic **********************************************************************************/ #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */ /* ** If an input line begins with "." then invoke this routine to ** process that line. ** ** Return 1 on error, 2 to exit, and 0 otherwise. */ static int do_meta_command(char *zLine, ShellState *p){ int h = 1; int nArg = 0; int n, c; int rc = 0; char *azArg[50]; #ifndef SQLITE_OMIT_VIRTUALTABLE if( p->expert.pExpert ){ expertFinish(p, 1, 0); } #endif /* Parse the input line into tokens. */ while( zLine[h] && nArg<ArraySize(azArg) ){ while( IsSpace(zLine[h]) ){ h++; } if( zLine[h]==0 ) break; if( zLine[h]=='\'' || zLine[h]=='"' ){ |
︙ | ︙ | |||
11797 11798 11799 11800 11801 11802 11803 11804 11805 11806 11807 11808 11809 11810 | } /* Process the input line. */ if( nArg==0 ) return 0; /* no tokens, no error */ n = strlen30(azArg[0]); c = azArg[0][0]; #ifndef SQLITE_OMIT_AUTHORIZATION if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){ if( nArg!=2 ){ raw_printf(stderr, "Usage: .auth ON|OFF\n"); rc = 1; goto meta_command_exit; | > | 12154 12155 12156 12157 12158 12159 12160 12161 12162 12163 12164 12165 12166 12167 12168 | } /* Process the input line. */ if( nArg==0 ) return 0; /* no tokens, no error */ n = strlen30(azArg[0]); c = azArg[0][0]; clearTempFile(p); #ifndef SQLITE_OMIT_AUTHORIZATION if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){ if( nArg!=2 ){ raw_printf(stderr, "Usage: .auth ON|OFF\n"); rc = 1; goto meta_command_exit; |
︙ | ︙ | |||
12131 12132 12133 12134 12135 12136 12137 12138 12139 12140 12141 12142 12143 12144 12145 12146 12147 12148 | p->autoExplain = 0; }else if( val==99 ){ if( p->mode==MODE_Explain ) p->mode = p->normalMode; p->autoExplain = 1; } }else if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){ open_db(p, 0); expertDotCommand(p, azArg, nArg); }else if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ ShellState data; char *zErrMsg = 0; int doStats = 0; memcpy(&data, p, sizeof(data)); data.showHeader = 0; | > > | 12489 12490 12491 12492 12493 12494 12495 12496 12497 12498 12499 12500 12501 12502 12503 12504 12505 12506 12507 12508 | p->autoExplain = 0; }else if( val==99 ){ if( p->mode==MODE_Explain ) p->mode = p->normalMode; p->autoExplain = 1; } }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){ open_db(p, 0); expertDotCommand(p, azArg, nArg); }else #endif if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){ ShellState data; char *zErrMsg = 0; int doStats = 0; memcpy(&data, p, sizeof(data)); data.showHeader = 0; |
︙ | ︙ | |||
12590 12591 12592 12593 12594 12595 12596 | if( c=='l' && strncmp(azArg[0], "log", n)==0 ){ if( nArg!=2 ){ raw_printf(stderr, "Usage: .log FILENAME\n"); rc = 1; }else{ const char *zFile = azArg[1]; output_file_close(p->pLog); | | | 12950 12951 12952 12953 12954 12955 12956 12957 12958 12959 12960 12961 12962 12963 12964 | if( c=='l' && strncmp(azArg[0], "log", n)==0 ){ if( nArg!=2 ){ raw_printf(stderr, "Usage: .log FILENAME\n"); rc = 1; }else{ const char *zFile = azArg[1]; output_file_close(p->pLog); p->pLog = output_file_open(zFile, 0); } }else if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ const char *zMode = nArg>=2 ? azArg[1] : ""; int n2 = strlen30(zMode); int c2 = zMode[0]; |
︙ | ︙ | |||
12699 12700 12701 12702 12703 12704 12705 | if( p->db==0 ){ /* As a fall-back open a TEMP database */ p->zDbFilename = 0; open_db(p, 0); } }else | | | > > > > > > > > > | | > > > > > > > > > > > > > > > | | 13059 13060 13061 13062 13063 13064 13065 13066 13067 13068 13069 13070 13071 13072 13073 13074 13075 13076 13077 13078 13079 13080 13081 13082 13083 13084 13085 13086 13087 13088 13089 13090 13091 13092 13093 13094 13095 13096 13097 13098 13099 13100 13101 13102 13103 13104 13105 13106 13107 13108 13109 13110 13111 13112 13113 13114 13115 13116 13117 13118 13119 13120 13121 13122 13123 13124 13125 13126 13127 13128 13129 13130 13131 13132 13133 | if( p->db==0 ){ /* As a fall-back open a TEMP database */ p->zDbFilename = 0; open_db(p, 0); } }else if( (c=='o' && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0)) || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0) ){ const char *zFile = nArg>=2 ? azArg[1] : "stdout"; int bTxtMode = 0; if( azArg[0][0]=='e' ){ /* Transform the ".excel" command into ".once -x" */ nArg = 2; azArg[0] = "once"; zFile = azArg[1] = "-x"; n = 4; } if( nArg>2 ){ utf8_printf(stderr, "Usage: .%s [-e|-x|FILE]\n", azArg[0]); rc = 1; goto meta_command_exit; } if( n>1 && strncmp(azArg[0], "once", n)==0 ){ if( nArg<2 ){ raw_printf(stderr, "Usage: .once (-e|-x|FILE)\n"); rc = 1; goto meta_command_exit; } p->outCount = 2; }else{ p->outCount = 0; } output_reset(p); if( zFile[0]=='-' && zFile[1]=='-' ) zFile++; if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){ p->doXdgOpen = 1; outputModePush(p); if( zFile[1]=='x' ){ newTempFile(p, "csv"); p->mode = MODE_Csv; sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma); sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf); }else{ newTempFile(p, "txt"); bTxtMode = 1; } zFile = p->zTempFile; } if( zFile[0]=='|' ){ #ifdef SQLITE_OMIT_POPEN raw_printf(stderr, "Error: pipes are not supported in this OS\n"); rc = 1; p->out = stdout; #else p->out = popen(zFile + 1, "w"); if( p->out==0 ){ utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1); p->out = stdout; rc = 1; }else{ sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); } #endif }else{ p->out = output_file_open(zFile, bTxtMode); if( p->out==0 ){ if( strcmp(zFile,"off")!=0 ){ utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile); } p->out = stdout; rc = 1; } else { |
︙ | ︙ | |||
13612 13613 13614 13615 13616 13617 13618 | for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); sqlite3_free(azResult); }else /* Begin redirecting output to the file "testcase-out.txt" */ if( c=='t' && strcmp(azArg[0],"testcase")==0 ){ output_reset(p); | | | 13996 13997 13998 13999 14000 14001 14002 14003 14004 14005 14006 14007 14008 14009 14010 | for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]); sqlite3_free(azResult); }else /* Begin redirecting output to the file "testcase-out.txt" */ if( c=='t' && strcmp(azArg[0],"testcase")==0 ){ output_reset(p); p->out = output_file_open("testcase-out.txt", 0); if( p->out==0 ){ raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n"); } if( nArg>=2 ){ sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]); }else{ sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?"); |
︙ | ︙ | |||
13818 13819 13820 13821 13822 13823 13824 | open_db(p, 0); if( nArg!=2 ){ raw_printf(stderr, "Usage: .trace FILE|off\n"); rc = 1; goto meta_command_exit; } output_file_close(p->traceOut); | | | 14202 14203 14204 14205 14206 14207 14208 14209 14210 14211 14212 14213 14214 14215 14216 | open_db(p, 0); if( nArg!=2 ){ raw_printf(stderr, "Usage: .trace FILE|off\n"); rc = 1; goto meta_command_exit; } output_file_close(p->traceOut); p->traceOut = output_file_open(azArg[1], 0); #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) if( p->traceOut==0 ){ sqlite3_trace_v2(p->db, 0, 0, 0); }else{ sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut); } #endif |
︙ | ︙ | |||
14148 14149 14150 14151 14152 14153 14154 14155 14156 14157 14158 14159 14160 14161 | if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) && sqlite3_complete(zSql) ){ errCnt += runOneSqlLine(p, zSql, in, startline); nSql = 0; if( p->outCount ){ output_reset(p); p->outCount = 0; } }else if( nSql && _all_whitespace(zSql) ){ if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql); nSql = 0; } } if( nSql && !_all_whitespace(zSql) ){ | > > | 14532 14533 14534 14535 14536 14537 14538 14539 14540 14541 14542 14543 14544 14545 14546 14547 | if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) && sqlite3_complete(zSql) ){ errCnt += runOneSqlLine(p, zSql, in, startline); nSql = 0; if( p->outCount ){ output_reset(p); p->outCount = 0; }else{ clearTempFile(p); } }else if( nSql && _all_whitespace(zSql) ){ if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql); nSql = 0; } } if( nSql && !_all_whitespace(zSql) ){ |
︙ | ︙ | |||
14770 14771 14772 14773 14774 14775 14776 14777 14778 14779 14780 14781 14782 | set_table_name(&data, 0); if( data.db ){ session_close_all(&data); sqlite3_close(data.db); } sqlite3_free(data.zFreeOnClose); find_home_dir(1); #if !SQLITE_SHELL_IS_UTF8 for(i=0; i<argc; i++) sqlite3_free(argv[i]); sqlite3_free(argv); #endif return rc; } | > > > | 15156 15157 15158 15159 15160 15161 15162 15163 15164 15165 15166 15167 15168 15169 15170 15171 | set_table_name(&data, 0); if( data.db ){ session_close_all(&data); sqlite3_close(data.db); } sqlite3_free(data.zFreeOnClose); find_home_dir(1); output_reset(&data); data.doXdgOpen = 0; clearTempFile(&data); #if !SQLITE_SHELL_IS_UTF8 for(i=0; i<argc; i++) sqlite3_free(argv[i]); sqlite3_free(argv); #endif return rc; } |
Changes to src/sqlite3.c.
︙ | ︙ | |||
1145 1146 1147 1148 1149 1150 1151 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.22.0" #define SQLITE_VERSION_NUMBER 3022000 | | | 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.22.0" #define SQLITE_VERSION_NUMBER 3022000 #define SQLITE_SOURCE_ID "2018-01-11 00:38:39 b8d92d8dc239597c6f01a6e572b047f98ce374a8f48257683fa839dde3ec993f" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ | |||
25704 25705 25706 25707 25708 25709 25710 | ** SQL statement. Make a copy of this phrase in space obtained form ** sqlite3DbMalloc(). Omit leading and trailing whitespace. */ SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ int n; while( sqlite3Isspace(zStart[0]) ) zStart++; n = (int)(zEnd - zStart); | | | 25704 25705 25706 25707 25708 25709 25710 25711 25712 25713 25714 25715 25716 25717 25718 | ** SQL statement. Make a copy of this phrase in space obtained form ** sqlite3DbMalloc(). Omit leading and trailing whitespace. */ SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ int n; while( sqlite3Isspace(zStart[0]) ) zStart++; n = (int)(zEnd - zStart); while( ALWAYS(n>0) && sqlite3Isspace(zStart[n-1]) ) n--; return sqlite3DbStrNDup(db, zStart, n); } /* ** Free any prior content in *pz and replace it with a copy of zNew. */ SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ |
︙ | ︙ | |||
36555 36556 36557 36558 36559 36560 36561 | assert( !p->pPreallocatedUnused ); assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); return rc; } fd = robust_open(zName, openFlags, openMode); OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); assert( !isExclusive || (openFlags & O_CREAT)!=0 ); | > > > > > | | | | | | | | | > | < < | | 36555 36556 36557 36558 36559 36560 36561 36562 36563 36564 36565 36566 36567 36568 36569 36570 36571 36572 36573 36574 36575 36576 36577 36578 36579 36580 36581 36582 36583 36584 36585 36586 | assert( !p->pPreallocatedUnused ); assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); return rc; } fd = robust_open(zName, openFlags, openMode); OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); assert( !isExclusive || (openFlags & O_CREAT)!=0 ); if( fd<0 ){ if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){ /* If unable to create a journal because the directory is not ** writable, change the error code to indicate that. */ rc = SQLITE_READONLY_DIRECTORY; }else if( errno!=EISDIR && isReadWrite ){ /* Failed to open the file for read/write access. Try read-only. */ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); openFlags &= ~(O_RDWR|O_CREAT); flags |= SQLITE_OPEN_READONLY; openFlags |= O_RDONLY; isReadonly = 1; fd = robust_open(zName, openFlags, openMode); } } if( fd<0 ){ int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); if( rc==SQLITE_OK ) rc = rc2; goto open_finished; } /* If this process is running as root and if creating a new rollback ** journal or WAL file, set the ownership of the journal or WAL to be ** the same as the original database. */ |
︙ | ︙ | |||
103558 103559 103560 103561 103562 103563 103564 | p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE); if( db->mallocFailed ) goto create_view_fail; /* Locate the end of the CREATE VIEW statement. Make sEnd point to ** the end. */ sEnd = pParse->sLastToken; | | | 103562 103563 103564 103565 103566 103567 103568 103569 103570 103571 103572 103573 103574 103575 103576 | p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE); if( db->mallocFailed ) goto create_view_fail; /* Locate the end of the CREATE VIEW statement. Make sEnd point to ** the end. */ sEnd = pParse->sLastToken; assert( sEnd.z[0]!=0 || sEnd.n==0 ); if( sEnd.z[0]!=';' ){ sEnd.z += sEnd.n; } sEnd.n = 0; n = (int)(sEnd.z - pBegin->z); assert( n>0 ); z = pBegin->z; |
︙ | ︙ | |||
141610 141611 141612 141613 141614 141615 141616 | sqlite3ParserTOKENTYPE yyminor /* The minor type of the error token */ ){ sqlite3ParserARG_FETCH; #define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ | | | > > > | 141614 141615 141616 141617 141618 141619 141620 141621 141622 141623 141624 141625 141626 141627 141628 141629 141630 141631 141632 | sqlite3ParserTOKENTYPE yyminor /* The minor type of the error token */ ){ sqlite3ParserARG_FETCH; #define TOKEN yyminor /************ Begin %syntax_error code ****************************************/ UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */ if( TOKEN.z[0] ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); }else{ sqlite3ErrorMsg(pParse, "incomplete input"); } /************ End %syntax_error code ******************************************/ sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* ** The following is executed when the parser accepts */ |
︙ | ︙ | |||
142656 142657 142658 142659 142660 142661 142662 | if( lastTokenParsed==TK_SEMI ){ tokenType = 0; }else if( lastTokenParsed==0 ){ break; }else{ tokenType = TK_SEMI; } | | | 142663 142664 142665 142666 142667 142668 142669 142670 142671 142672 142673 142674 142675 142676 142677 | if( lastTokenParsed==TK_SEMI ){ tokenType = 0; }else if( lastTokenParsed==0 ){ break; }else{ tokenType = TK_SEMI; } n = 0; } if( tokenType>=TK_SPACE ){ assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); if( db->u1.isInterrupted ){ pParse->rc = SQLITE_INTERRUPT; break; } |
︙ | ︙ | |||
144451 144452 144453 144454 144455 144456 144457 144458 144459 144460 144461 144462 144463 144464 | case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break; case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; case SQLITE_READONLY_CANTINIT: zName = "SQLITE_READONLY_CANTINIT"; break; case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break; case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break; case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break; case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break; case SQLITE_IOERR_FSYNC: zName = "SQLITE_IOERR_FSYNC"; break; case SQLITE_IOERR_DIR_FSYNC: zName = "SQLITE_IOERR_DIR_FSYNC"; break; | > | 144458 144459 144460 144461 144462 144463 144464 144465 144466 144467 144468 144469 144470 144471 144472 | case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break; case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; case SQLITE_READONLY_CANTINIT: zName = "SQLITE_READONLY_CANTINIT"; break; case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break; case SQLITE_READONLY_DIRECTORY: zName = "SQLITE_READONLY_DIRECTORY";break; case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break; case SQLITE_IOERR: zName = "SQLITE_IOERR"; break; case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break; case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break; case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break; case SQLITE_IOERR_FSYNC: zName = "SQLITE_IOERR_FSYNC"; break; case SQLITE_IOERR_DIR_FSYNC: zName = "SQLITE_IOERR_DIR_FSYNC"; break; |
︙ | ︙ | |||
202939 202940 202941 202942 202943 202944 202945 | static void fts5SourceIdFunc( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); | | | 202947 202948 202949 202950 202951 202952 202953 202954 202955 202956 202957 202958 202959 202960 202961 | static void fts5SourceIdFunc( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); sqlite3_result_text(pCtx, "fts5: 2018-01-11 00:38:39 b8d92d8dc239597c6f01a6e572b047f98ce374a8f48257683fa839dde3ec993f", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ static const sqlite3_module fts5Mod = { /* iVersion */ 2, /* xCreate */ fts5CreateMethod, /* xConnect */ fts5ConnectMethod, |
︙ | ︙ | |||
207207 207208 207209 207210 207211 207212 207213 | #endif return rc; } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ | | | | 207215 207216 207217 207218 207219 207220 207221 207222 207223 207224 207225 207226 207227 207228 | #endif return rc; } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ #if __LINE__!=207222 #undef SQLITE_SOURCE_ID #define SQLITE_SOURCE_ID "2018-01-11 00:38:39 b8d92d8dc239597c6f01a6e572b047f98ce374a8f48257683fa839dde3ecalt2" #endif /* Return the source-id for this library */ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } /************************** End of sqlite3.c ******************************/ |
Changes to src/sqlite3.h.
︙ | ︙ | |||
121 122 123 124 125 126 127 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.22.0" #define SQLITE_VERSION_NUMBER 3022000 | | | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.22.0" #define SQLITE_VERSION_NUMBER 3022000 #define SQLITE_SOURCE_ID "2018-01-11 00:38:39 b8d92d8dc239597c6f01a6e572b047f98ce374a8f48257683fa839dde3ec993f" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
︙ | ︙ |
Changes to win/Makefile.PellesCGMake.
︙ | ︙ | |||
81 82 83 84 85 86 87 | UTILS_OBJ=$(UTILS:.exe=.obj) UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c)) # define the SQLite files, which need special flags on compile SQLITESRC=sqlite3.c ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) | | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | UTILS_OBJ=$(UTILS:.exe=.obj) UTILS_SRC=$(foreach uf,$(UTILS),$(SRCDIR)$(uf:.exe=.c)) # define the SQLite files, which need special flags on compile SQLITESRC=sqlite3.c ORIGSQLITESRC=$(foreach sf,$(SQLITESRC),$(SRCDIR)$(sf)) SQLITEOBJ=$(foreach sf,$(SQLITESRC),$(sf:.c=.obj)) SQLITEDEFINES=-DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_USE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_WIN32_NO_ANSI # define the SQLite shell files, which need special flags on compile SQLITESHELLSRC=shell.c ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf)) SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj)) SQLITESHELLDEFINES=-Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
︙ | ︙ |
Changes to win/Makefile.dmc.
︙ | ︙ | |||
22 23 24 25 26 27 28 | SSL = CFLAGS = -o BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | SSL = CFLAGS = -o BCC = $(DMDIR)\bin\dmc $(CFLAGS) TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL) LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_USE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c hname_.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_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c 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)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$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)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$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_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$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)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$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)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$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 |
︙ | ︙ |
Changes to win/Makefile.mingw.
︙ | ︙ | |||
2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ -DSQLITE_ENABLE_FTS4 \ -DSQLITE_ENABLE_FTS3_PARENTHESIS \ -DSQLITE_ENABLE_DBSTAT_VTAB \ -DSQLITE_ENABLE_JSON1 \ -DSQLITE_ENABLE_FTS5 \ -DSQLITE_ENABLE_STMTVTAB \ -DSQLITE_WIN32_NO_ANSI \ $(MINGW_OPTIONS) \ -DSQLITE_USE_MALLOC_H \ -DSQLITE_USE_MSIZE SHELL_OPTIONS = -Dmain=sqlite3_shell \ -DSQLITE_SHELL_IS_UTF8=1 \ | > > > | 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 | -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ -DSQLITE_ENABLE_FTS4 \ -DSQLITE_ENABLE_FTS3_PARENTHESIS \ -DSQLITE_ENABLE_DBSTAT_VTAB \ -DSQLITE_ENABLE_JSON1 \ -DSQLITE_ENABLE_FTS5 \ -DSQLITE_ENABLE_STMTVTAB \ -DSQLITE_USE_ZLIB \ -DSQLITE_INTROSPECTION_PRAGMAS \ -DSQLITE_ENABLE_DBPAGE_VTAB \ -DSQLITE_WIN32_NO_ANSI \ $(MINGW_OPTIONS) \ -DSQLITE_USE_MALLOC_H \ -DSQLITE_USE_MSIZE SHELL_OPTIONS = -Dmain=sqlite3_shell \ -DSQLITE_SHELL_IS_UTF8=1 \ |
︙ | ︙ |
Changes to win/Makefile.msc.
︙ | ︙ | |||
331 332 333 334 335 336 337 338 339 340 341 342 343 344 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ /DSQLITE_ENABLE_FTS4 \ /DSQLITE_ENABLE_FTS3_PARENTHESIS \ /DSQLITE_ENABLE_DBSTAT_VTAB \ /DSQLITE_ENABLE_JSON1 \ /DSQLITE_ENABLE_FTS5 \ /DSQLITE_ENABLE_STMTVTAB \ /DSQLITE_WIN32_NO_ANSI SHELL_OPTIONS = /Dmain=sqlite3_shell \ /DSQLITE_SHELL_IS_UTF8=1 \ /DSQLITE_OMIT_LOAD_EXTENSION=1 \ /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \ /DSQLITE_SHELL_DBNAME_PROC=fossil_open \ | > > > | 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | /DSQLITE_ENABLE_EXPLAIN_COMMENTS \ /DSQLITE_ENABLE_FTS4 \ /DSQLITE_ENABLE_FTS3_PARENTHESIS \ /DSQLITE_ENABLE_DBSTAT_VTAB \ /DSQLITE_ENABLE_JSON1 \ /DSQLITE_ENABLE_FTS5 \ /DSQLITE_ENABLE_STMTVTAB \ /DSQLITE_USE_ZLIB \ /DSQLITE_INTROSPECTION_PRAGMAS \ /DSQLITE_ENABLE_DBPAGE_VTAB \ /DSQLITE_WIN32_NO_ANSI SHELL_OPTIONS = /Dmain=sqlite3_shell \ /DSQLITE_SHELL_IS_UTF8=1 \ /DSQLITE_OMIT_LOAD_EXTENSION=1 \ /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \ /DSQLITE_SHELL_DBNAME_PROC=fossil_open \ |
︙ | ︙ |
Changes to www/quotes.wiki.
︙ | ︙ | |||
125 126 127 128 129 130 131 132 133 134 135 136 137 138 | </ol> <h2>On Git Versus Fossil</h2> <ol> <li value=15> Just want to say thanks for fossil making my life easier.... Also <nowiki>[for]</nowiki> not having a misanthropic command line interface. <blockquote> <i>Joshua Paine at [http://www.mail-archive.com/fossil-users@lists.fossil-scm.org/msg02736.html]</i> </blockquote> | > > > > > > > > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | </ol> <h2>On Git Versus Fossil</h2> <ol> <li value=15> After prolonged exposure to fossil, i tend to get the jitters when I work with git... <blockquote> <i>sriku - at [https://news.ycombinator.com/item?id=16104427]</i> </blockquote> <li> Just want to say thanks for fossil making my life easier.... Also <nowiki>[for]</nowiki> not having a misanthropic command line interface. <blockquote> <i>Joshua Paine at [http://www.mail-archive.com/fossil-users@lists.fossil-scm.org/msg02736.html]</i> </blockquote> |
︙ | ︙ |