Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add the load_extension() SQL function. (CVS 3269) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
e08e2ddafe909ae6073ec56dfa3fdca2 |
User & Date: | drh 2006-06-17 14:12:48.000 |
Context
2006-06-19
| ||
03:05 | Add tests to ensure an INSERT/UPDATE/DELETE immediately after virtual table construction does not fail. (CVS 3270) (check-in: 144d0eb13a user: danielk1977 tags: trunk) | |
2006-06-17
| ||
14:12 | Add the load_extension() SQL function. (CVS 3269) (check-in: e08e2ddafe user: drh tags: trunk) | |
13:21 | The default entry point for loadable extensions is now always sqlite3_extension_init(). (CVS 3268) (check-in: 059b1f6140 user: drh tags: trunk) | |
Changes
Changes to src/func.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.131 2006/06/17 14:12:48 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* #include <math.h> */ #include <stdlib.h> #include <assert.h> #include "vdbeInt.h" |
︙ | ︙ | |||
671 672 673 674 675 676 677 678 679 680 681 682 683 684 | zResult[j] = 0; sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT); }else{ sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); } } #endif #ifdef SQLITE_TEST /* ** This function generates a string of random characters. Used for ** generating test data. */ static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ | > > > > > > > > > > > > > > > > > > > > | 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 | zResult[j] = 0; sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT); }else{ sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); } } #endif #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** A function that loads a shared-library extension then returns NULL. */ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *zFile = sqlite3_value_text(argv[0]); const char *zProc = 0; sqlite3 *db = sqlite3_user_data(context); char *zErrMsg = 0; if( argc==2 ){ zProc = sqlite3_value_text(argv[1]); } if( sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){ sqlite3_result_error(context, zErrMsg, -1); sqlite3_free(zErrMsg); } } #endif #ifdef SQLITE_TEST /* ** This function generates a string of random characters. Used for ** generating test data. */ static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ |
︙ | ︙ | |||
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 | { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, { "changes", 0, 1, SQLITE_UTF8, 0, changes }, { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, { "match", 2, 0, SQLITE_UTF8, 0, matchStub }, #ifdef SQLITE_SOUNDEX { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, #endif #ifdef SQLITE_TEST { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, { "test_destructor", 1, 1, SQLITE_UTF8, 0, test_destructor}, { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count}, { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata}, { "test_error", 1, 0, SQLITE_UTF8, 0, test_error}, #endif | > > > > | 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 | { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, { "changes", 0, 1, SQLITE_UTF8, 0, changes }, { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, { "match", 2, 0, SQLITE_UTF8, 0, matchStub }, #ifdef SQLITE_SOUNDEX { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, #endif #ifndef SQLITE_OMIT_LOAD_EXTENSION { "load_extension", 1, 1, SQLITE_UTF8, 0, loadExt }, { "load_extension", 2, 1, SQLITE_UTF8, 0, loadExt }, #endif #ifdef SQLITE_TEST { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, { "test_destructor", 1, 1, SQLITE_UTF8, 0, test_destructor}, { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count}, { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata}, { "test_error", 1, 0, SQLITE_UTF8, 0, test_error}, #endif |
︙ | ︙ |
Changes to test/loadext.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2006 July 14 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is in-memory database backend. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2006 July 14 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is in-memory database backend. # # $Id: loadext.test,v 1.3 2006/06/17 14:12:48 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # The name of the test extension varies by operating system. # if {$::tcl_platform(platform) eq "windows"} { |
︙ | ︙ | |||
125 126 127 128 129 130 131 132 133 | # do_test loadext-2.4 { set rc [catch { sqlite3_load_extension db $testextension testbrokenext_init } msg] list $rc $msg } {1 {error during initialization: broken!}} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | # do_test loadext-2.4 { set rc [catch { sqlite3_load_extension db $testextension testbrokenext_init } msg] list $rc $msg } {1 {error during initialization: broken!}} ############################################################################ # Tests for the load_extension() SQL function # db close sqlite3 db test.db do_test loadext-3.1 { catchsql { SELECT half(5); } } {1 {no such function: half}} do_test loadext-3.2 { catchsql { SELECT load_extension($::testextension) } } [list 1 "no entry point \[sqlite3_extension_init\]\ in shared library \[$testextension\]"] do_test loadext-3.3 { catchsql { SELECT load_extension($::testextension,'testloadext_init') } } {0 {{}}} do_test loadext-3.4 { catchsql { SELECT half(5); } } {0 2.5} finish_test |
Changes to www/lang.tcl.
1 2 3 | # # Run this Tcl script to generate the lang-*.html files. # | | | 1 2 3 4 5 6 7 8 9 10 11 | # # Run this Tcl script to generate the lang-*.html files. # set rcsid {$Id: lang.tcl,v 1.113 2006/06/17 14:12:48 drh Exp $} source common.tcl if {[llength $argv]>0} { set outputdir [lindex $argv 0] } else { set outputdir "" } |
︙ | ︙ | |||
958 959 960 961 962 963 964 | <expr> [NOT] IN ( <value-list> ) | <expr> [NOT] IN ( <select-statement> ) | <expr> [NOT] IN [<database-name> .] <table-name> | [EXISTS] ( <select-statement> ) | CASE [<expr>] LP WHEN <expr> THEN <expr> RPPLUS [ELSE <expr>] END | CAST ( <expr> AS <type> ) } {like-op} { | | | 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 | <expr> [NOT] IN ( <value-list> ) | <expr> [NOT] IN ( <select-statement> ) | <expr> [NOT] IN [<database-name> .] <table-name> | [EXISTS] ( <select-statement> ) | CASE [<expr>] LP WHEN <expr> THEN <expr> RPPLUS [ELSE <expr>] END | CAST ( <expr> AS <type> ) } {like-op} { LIKE | GLOB | REGEXP | MATCH } puts { <p>This section is different from the others. Most other sections of this document talks about a particular SQL command. This section does not talk about a standalone command but about "expressions" which are subcomponents of most other commands.</p> |
︙ | ︙ | |||
986 987 988 989 990 991 992 993 994 995 996 997 998 999 | </pre></blockquote> <p>Supported unary operators are these:</p> <blockquote><pre> <font color="#2c2cf0"><big>- + ! ~ NOT</big></font> </pre></blockquote> <p>Note that there are two variations of the equals and not equals operators. Equals can be either} puts "[Operator =] or [Operator ==]. The non-equals operator can be either [Operator !=] or [Operator {<>}]. The [Operator ||] operator is \"concatenate\" - it joins together | > > > > | 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 | </pre></blockquote> <p>Supported unary operators are these:</p> <blockquote><pre> <font color="#2c2cf0"><big>- + ! ~ NOT</big></font> </pre></blockquote> <p>The unary operator [Operator +] is a no-op. It can be applied to strings, numbers, or blobs and it always gives as its result the value of the operand.</p> <p>Note that there are two variations of the equals and not equals operators. Equals can be either} puts "[Operator =] or [Operator ==]. The non-equals operator can be either [Operator !=] or [Operator {<>}]. The [Operator ||] operator is \"concatenate\" - it joins together |
︙ | ︙ | |||
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 | <tr> <td align="right" valign="top"><b>:</b><i>AAAA</i></td><td width="20"></td> <td>A colon followed by an identifier name holds a spot for a named parameter with the name AAAA. Named parameters are also numbered. The number assigned is the next unused number. To avoid confusion, it is best to avoid mixing named and numbered parameters.</td> </tr> <tr> <td align="right" valign="top"><b>$</b><i>AAAA</i></td><td width="20"></td> <td>A dollar-sign followed by an identifier name also holds a spot for a named parameter with the name AAAA. The identifier name in this case can include one or more occurances of "::" and a suffix enclosed in "(...)" containing any text at all. This syntax is the form of a variable name in the Tcl programming language.</td> | > > > > | 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 | <tr> <td align="right" valign="top"><b>:</b><i>AAAA</i></td><td width="20"></td> <td>A colon followed by an identifier name holds a spot for a named parameter with the name AAAA. Named parameters are also numbered. The number assigned is the next unused number. To avoid confusion, it is best to avoid mixing named and numbered parameters.</td> </tr> <tr> <td align="right" valign="top"><b>@</b><i>AAAA</i></td><td width="20"></td> <td>An "at" sign works exactly like a colon.</td> </tr> <tr> <td align="right" valign="top"><b>$</b><i>AAAA</i></td><td width="20"></td> <td>A dollar-sign followed by an identifier name also holds a spot for a named parameter with the name AAAA. The identifier name in this case can include one or more occurances of "::" and a suffix enclosed in "(...)" containing any text at all. This syntax is the form of a variable name in the Tcl programming language.</td> |
︙ | ︙ | |||
1123 1124 1125 1126 1127 1128 1129 | that function.</p> <a name="regexp"></a> <p>The REGEXP operator is a special syntax for the regexp() user function. No regexp() user function is defined by default and so use of the REGEXP operator will normally result in an error message. If a user-defined function named "regexp" | | > > > > > > > | 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 | that function.</p> <a name="regexp"></a> <p>The REGEXP operator is a special syntax for the regexp() user function. No regexp() user function is defined by default and so use of the REGEXP operator will normally result in an error message. If a user-defined function named "regexp" is added at run-time, that function will be called in order to implement the REGEXP operator.</p> <a name="match"></a> <p>The MATCH operator is a special syntax for the match() user function. The default match() function implementation raises and exception and is not really useful for anything. But extensions can override the match() function with more helpful logic.</p> <p>A column name can be any of the names defined in the CREATE TABLE statement or one of the following special identifiers: "<b>ROWID</b>", "<b>OID</b>", or "<b>_ROWID_</b>". These special identifiers all describe the unique random integer key (the "row key") associated with every row of every table. |
︙ | ︙ | |||
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 | href= "#like">LIKE</a> operator. When doing this, it may be important to override both the two and three argument versions of the like() function. Otherwise, different code may be called to implement the LIKE operator depending on whether or not an ESCAPE clause was specified.</td> </tr> <tr> <td valign="top" align="right">lower(<i>X</i>)</td> <td valign="top">Return a copy of string <i>X</i> will all characters converted to lower case. The C library <b>tolower()</b> routine is used for the conversion, which means that this function might not work correctly on UTF-8 characters.</td> </tr> | > > > > > > > > > > | 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 | href= "#like">LIKE</a> operator. When doing this, it may be important to override both the two and three argument versions of the like() function. Otherwise, different code may be called to implement the LIKE operator depending on whether or not an ESCAPE clause was specified.</td> </tr> <tr> <td valign="top" align="right">load_extension(<i>X</i>)<br> load_extension(<i>X</i>,<i>Y</i>)</td> <td valign="top">Load SQLite extensions out of the shared library file named <i>X</i> using the entry point <i>Y</i>. The result is a NULL. If <i>Y</i> is omitted then the default entry point of <b>sqlite3_extension_init</b> is used. This function raises an exception if the extension fails to load or initialize correctly. </tr> <tr> <td valign="top" align="right">lower(<i>X</i>)</td> <td valign="top">Return a copy of string <i>X</i> will all characters converted to lower case. The C library <b>tolower()</b> routine is used for the conversion, which means that this function might not work correctly on UTF-8 characters.</td> </tr> |
︙ | ︙ | |||
1290 1291 1292 1293 1294 1295 1296 | The current implementation of VACUUM uses this function. The function is also useful when writing triggers to implement undo/redo functionality. </td> </tr> <tr> <td valign="top" align="right">random(*)</td> | | | | 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 | The current implementation of VACUUM uses this function. The function is also useful when writing triggers to implement undo/redo functionality. </td> </tr> <tr> <td valign="top" align="right">random(*)</td> <td valign="top">Return a pseudo-random integer between -9223372036854775808 and +9223372036854775807.</td> </tr> <tr> <td valign="top" align="right">round(<i>X</i>)<br>round(<i>X</i>,<i>Y</i>)</td> <td valign="top">Round off the number <i>X</i> to <i>Y</i> digits to the right of the decimal point. If the <i>Y</i> argument is omitted, 0 is assumed.</td> |
︙ | ︙ |