SQLite

Check-in [e08e2ddafe]
Login

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: e08e2ddafe909ae6073ec56dfa3fdca23e36bf2e
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
Unified Diff Ignore Whitespace Patch
Changes to src/func.c.
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.130 2006/06/13 19:26:11 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
/* #include <math.h> */
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"







|







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
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.2 2006/06/17 13:21:33 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"} {













|







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
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.112 2006/05/31 11:12:01 drh Exp $}
source common.tcl

if {[llength $argv]>0} {
  set outputdir [lindex $argv 0]
} else {
  set outputdir ""
}



|







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
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
}

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>







|







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 {&lt;&gt;}].
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 {&lt;&gt;}].
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
1130
1131







1132
1133
1134
1135
1136
1137
1138
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 defined at run-time, that function will be called in order
to implement the REGEXP operator.</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.







|

>
>
>
>
>
>
>







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
1297
1298
1299
1300
1301
1302
1303
1304
1305
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 random integer between -2147483648 and
+2147483647.</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>







|
|







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>