]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Initial exploration of blocky APIs, starting with a variant of sqlite3_exec. blocky-exec
authornumist <numist@noemail.net>
Fri, 13 Dec 2019 22:59:38 +0000 (22:59 +0000)
committernumist <numist@noemail.net>
Fri, 13 Dec 2019 22:59:38 +0000 (22:59 +0000)
FossilOrigin-Name: fd849d5b6a891c57facbfbba1de855b4349577dbc7afaa7f503e23bc4ca74e8f

manifest
manifest.uuid
src/legacy.c
src/sqlite.h.in
src/sqliteInt.h

index 786d389eeb28d508cf5e6dc07501bd4249010b62..aa8a0c6e9d4591d0d20ce1ff583b0e13aab89ea2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Patch\sto\sthe\spage\scache\sto\savoid\sharmless\spointer\sarithmetic\sthat\sdue\sto\sbugs\nin\sthe\sSTD-C\sspec\sis\stechnically\sUB.\s\sThis\sis\sto\sfix\sa\sharmless\sUBSAN\ncomplaint\sthat\sOSSFuzz\sis\shitting.
-D 2019-12-13T21:24:46.081
+C Initial\sexploration\sof\sblocky\sAPIs,\sstarting\swith\sa\svariant\sof\ssqlite3_exec.
+D 2019-12-13T22:59:38.851
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -489,7 +489,7 @@ F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c 5de3fd62bd1a692353c8f9c7bbde658f0b579f195620ca3cde1948a53015dddd
-F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
+F src/legacy.c 70ff0890930967fa02a792d3b2c48208eb6a1c4d9f55a465a664b2ddc8b044a4
 F src/loadext.c d74f5e7bd51f3c9d283442473eb65aef359664efd6513591c03f01881c4ae2da
 F src/main.c 868ae7db7a54fe859bf2ca8b7a4f24e9fa03a6134abfb7c9801d08411ef5dacb
 F src/malloc.c 550021fcae36f0ffe9f8563d83e6385f9df307a854d55d7d0abb7241ee8dbcc6
@@ -529,10 +529,10 @@ F src/resolve.c 86a7773d2892227ba9ad1721c41bb03c501830f1bf6de5f78dd0062b82e10c9d
 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
 F src/select.c 0fe10579de20eb8dc04ec9ed29659fa782bee2bcc85a35734637f3e2cabc2762
 F src/shell.c.in 4a3a9e1c11847b1904f2b01d087af1c052f660902755abab457cab1756817ded
-F src/sqlite.h.in 2a23e8161775253d9cf383c2c6aa559005dc787d350dcb0be67a6c4cc3bd1d19
+F src/sqlite.h.in 44a53119d3fb6e2d855d8bfd4b94151338563a2fbe28638e3a24ee8d9e661ae1
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 72af51aa4e912e14cd495fb6e7fac65f0940db80ed950d90911aff292cc47ce2
-F src/sqliteInt.h 60d92fad64da7c3e77bbc35ee306340814cdaa5df32892b0ec58d306d99b5733
+F src/sqliteInt.h 6326f05f5924e779f5c3ba422f85adfdef38dbf1012be7d5e40a2d78d4d1a648
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -1852,7 +1852,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P c1014e80b26131200a115beb86929a8f0ded2dd65b075e47373346c0f170576a
-R b59b4afd4c4fcaeb80758977b1b63c0a
-U drh
-Z 4fa57844859159ee82f87f0f14b6814f
+P c29fc21288e37f81a1617c5e2961c575d3bca6a1d1b013b2e0a99774afb1dcdb
+R e55adf2fcddc384393004665528a6995
+T *branch * blocky-exec
+T *sym-blocky-exec *
+T -sym-trunk *
+U numist
+Z 7fe9b43d252eee701000e10996724092
index ab11a63e584741086eb4160908eb41cc6e67e09f..e930527d014c2b562438609914a2ddde032a1353 100644 (file)
@@ -1 +1 @@
-c29fc21288e37f81a1617c5e2961c575d3bca6a1d1b013b2e0a99774afb1dcdb
\ No newline at end of file
+fd849d5b6a891c57facbfbba1de855b4349577dbc7afaa7f503e23bc4ca74e8f
\ No newline at end of file
index 867587e5a2fb1a78ad7f84c557649553475557d0..f412e7c70d85b3e9f7a8946603ed4dc6affe4427 100644 (file)
@@ -139,3 +139,81 @@ exec_out:
   sqlite3_mutex_leave(db->mutex);
   return rc;
 }
+
+#if SQLITE_HAS_BLOCKS
+int sqlite3_exec_b(
+  sqlite3 *db,
+  const char *zSql,
+  int (^xCallback)(sqlite3_stmt *)
+){
+  int rc = SQLITE_OK;         /* Return code */
+  const char *zLeftover;      /* Tail of unprocessed SQL */
+  sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
+  const char **azCols = 0;          /* Names of result columns */
+
+  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
+  if( zSql==0 ) zSql = "";
+#ifdef SQLITE_ENABLE_SQLRR
+  SRRecExec(db, zSql);
+#endif
+  sqlite3_mutex_enter(db->mutex);
+  sqlite3Error(db, SQLITE_OK);
+  while( rc==SQLITE_OK && zSql[0] ){
+    int callbackIsInit = 0;
+
+    pStmt = 0;
+    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
+    assert( rc==SQLITE_OK || pStmt==0 );
+    if( rc!=SQLITE_OK ){
+      continue;
+    }
+    if( !pStmt ){
+      /* this happens for a comment or white-space */
+      zSql = zLeftover;
+      continue;
+    }
+
+    while( 1 ){
+      rc = sqlite3_step(pStmt);
+
+      /* Invoke the callback function if required */
+      if( xCallback && (SQLITE_ROW==rc ||
+          (SQLITE_DONE==rc && !callbackIsInit
+                           && db->flags&SQLITE_NullCallback)) ){
+        if( xCallback(pStmt) ){
+          /* EVIDENCE-OF: R-38229-40159 If the callback function to
+          ** sqlite3_exec() returns non-zero, then sqlite3_exec() will
+          ** return SQLITE_ABORT. */
+          rc = SQLITE_ABORT;
+          (void)sqlite3VdbeFinalize((Vdbe *)pStmt);
+          pStmt = 0;
+          sqlite3Error(db, rc);
+          goto exec_out;
+        }
+      }
+
+      if( rc!=SQLITE_ROW ){
+        rc = sqlite3VdbeFinalize((Vdbe *)pStmt);
+        pStmt = 0;
+        zSql = zLeftover;
+        while( sqlite3Isspace(zSql[0]) ) zSql++;
+        break;
+      }
+    }
+  }
+
+exec_out:
+  if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt);
+  sqlite3DbFree(db, azCols);
+#ifdef SQLITE_ENABLE_SQLRR
+  SRRecExecEnd(db);
+#endif
+
+  rc = sqlite3ApiExit(db, rc);
+
+  assert( (rc&db->errMask)==rc );
+  sqlite3_mutex_leave(db->mutex);
+  return rc;
+
+}
+#endif
index 944b5be3e530f1ef0ed8c03c3736cd8aabc2e873..496f08e4e54855fac9166a6b574c284aaa9cddf9 100644 (file)
 #define SQLITE3_H
 #include <stdarg.h>     /* Needed for the definition of va_list */
 
+/* Compatibility with non-clang compilers */
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+/* Compatibility with pre-3.0 versions of clang */
+#ifndef __has_extension
+# define __has_extension __has_feature
+#endif
+
 /*
 ** Make sure we can call this stuff from C++.
 */
@@ -66,6 +75,13 @@ extern "C" {
 #ifndef SQLITE_SYSAPI
 # define SQLITE_SYSAPI
 #endif
+#ifndef SQLITE_NOESCAPE
+# if __has_feature(noescape)
+#  define SQLITE_NOESCAPE __attribute__((noescape))
+# else
+#  define SQLITE_NOESCAPE
+# endif
+#endif
 
 /*
 ** These no-op macros are used in front of interfaces to mark those
@@ -345,21 +361,20 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 ** CAPI3REF: One-Step Query Execution Interface
 ** METHOD: sqlite3
 **
-** The sqlite3_exec() interface is a convenience wrapper around
-** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
+** The sqlite3_exec() and sqlite3_exec_b() interfaces are convenience wrappers
+** around [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
 ** that allows an application to run multiple statements of SQL
 ** without having to use a lot of C code. 
 **
-** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
-** semicolon-separate SQL statements passed into its 2nd argument,
-** in the context of the [database connection] passed in as its 1st
-** argument.  ^If the callback function of the 3rd argument to
-** sqlite3_exec() is not NULL, then it is invoked for each result row
+** ^The sqlite3_exec() and sqlite3_exec_b() interfaces run zero or more UTF-8
+** encoded, semicolon-separate SQL statements passed into their 2nd argument,
+** in the context of the [database connection] passed in to their 1st
+** argument.  ^If the callback function of the 3rd argument to sqlite3_exec()
+** or sqlite3_exec_b() is not NULL, then it is invoked for each result row
 ** coming out of the evaluated SQL statements.  ^The 4th argument to
-** sqlite3_exec() is relayed through to the 1st argument of each
-** callback invocation.  ^If the callback pointer to sqlite3_exec()
-** is NULL, then no callback is ever invoked and result rows are
-** ignored.
+** sqlite3_exec() is relayed through to the 1st argument of each callback
+** invocation.  ^If the callback pointer to sqlite3_exec() or sqlite3_exec_b()
+** is NULL, then no callback is ever invoked and result rows are ignored.
 **
 ** ^If an error occurs while evaluating the SQL statements passed into
 ** sqlite3_exec(), then execution of the current statement stops and
@@ -373,7 +388,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 ** occur, then sqlite3_exec() sets the pointer in its 5th parameter to
 ** NULL before returning.
 **
-** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec()
+** ^If an sqlite3_exec() or sqlite3_exec_b() callback returns non-zero, the
 ** routine returns SQLITE_ABORT without invoking the callback again and
 ** without running any subsequent SQL statements.
 **
@@ -387,20 +402,26 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
 ** entry represents the name of corresponding result column as obtained
 ** from [sqlite3_column_name()].
 **
-** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
-** to an empty string, or a pointer that contains only whitespace and/or 
-** SQL comments, then no SQL statements are evaluated and the database
-** is not changed.
+** ^The 1st argument to the sqlite3_exec_b() callback block is a prepared
+** statement object stopped at the current result row. The
+** [column access functions] may be used to extract the row's values.
+**
+** ^If the 2nd parameter to sqlite3_exec() or sqlite3_exec_b() is a NULL
+** pointer, a pointer to an empty string, or a pointer that contains only
+** whitespace and/or SQL comments, then no SQL statements are evaluated and
+** the database is not changed.
 **
 ** Restrictions:
 **
 ** <ul>
 ** <li> The application must ensure that the 1st parameter to sqlite3_exec()
-**      is a valid and open [database connection].
+**      or sqlite3_exec_b() is a valid and open [database connection].
 ** <li> The application must not close the [database connection] specified by
-**      the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
+**      the 1st parameter to sqlite3_exec() or sqlite3_exec_b() while the
+**      routine is running.
 ** <li> The application must not modify the SQL statement text passed into
-**      the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
+**      the 2nd parameter of sqlite3_exec() or sqlite3_exec_b() while the
+**      routine is running.
 ** </ul>
 */
 int sqlite3_exec(
@@ -410,6 +431,13 @@ int sqlite3_exec(
   void *,                                    /* 1st argument to callback */
   char **errmsg                              /* Error msg written here */
 );
+#if __has_extension(blocks)
+int sqlite3_exec_b(
+  sqlite3*,                                      /* An open database */
+  const char *sql,                               /* SQL to be evaluated */
+  SQLITE_NOESCAPE int (^callback)(sqlite3_stmt*) /* Callback block */
+);
+#endif
 
 /*
 ** CAPI3REF: Result Codes
index 4b4a9068cca2854d97454ef4b15d009a897c1d2c..7f8672b2d946fdb26543124350183659034de4cb 100644 (file)
 */
 #include "sqlite3.h"
 
+/*
+** SQLITE_HAS_BLOCKS controls block API availability
+*/
+#ifndef SQLITE_HAS_BLOCKS
+# if __has_extension(blocks)
+#  define SQLITE_HAS_BLOCKS 1
+# else
+#  define SQLITE_HAS_BLOCKS 0
+# endif
+#endif
+
 /*
 ** Include the configuration header output by 'configure' if we're using the
 ** autoconf-based build