mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Add tests (and modify test code) for writing to virtual tables. (CVS 3253)
FossilOrigin-Name: 6380a9b118cf972c3c7d4886ecdb62c44f2208ca
This commit is contained in:
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
|||||||
C Simple\stests\sand\sfixes\sfor\swriting\sto\svirtual\stables.\s(CVS\s3252)
|
C Add\stests\s(and\smodify\stest\scode)\sfor\swriting\sto\svirtual\stables.\s(CVS\s3253)
|
||||||
D 2006-06-15T07:29:01
|
D 2006-06-15T10:41:16
|
||||||
F Makefile.in 200f6dc376ecfd9b01e5359c4e0c10c02f649b34
|
F Makefile.in 200f6dc376ecfd9b01e5359c4e0c10c02f649b34
|
||||||
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||||
@ -84,7 +84,7 @@ F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
|
|||||||
F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
|
F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
|
||||||
F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de
|
F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de
|
||||||
F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3
|
F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3
|
||||||
F src/test8.c e88baeff5530fbf0d028a48fbffab71440a5b953
|
F src/test8.c f3082601d4eae6284b33a36fcfe00c8d8d17ee47
|
||||||
F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
|
F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
|
||||||
F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
|
F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
|
||||||
F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
|
F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
|
||||||
@ -290,7 +290,7 @@ F test/vacuum.test 37f998b841cb335397c26d9bbc3457182af2565f
|
|||||||
F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c
|
F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c
|
||||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||||
F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5
|
F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5
|
||||||
F test/vtab1.test 89937da89d774b9174b93a327330e4ea3fb0f03a
|
F test/vtab1.test 519f360d15b8009845e7957789801807346286ff
|
||||||
F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df
|
F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df
|
||||||
F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394
|
F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394
|
||||||
F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa
|
F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa
|
||||||
@ -366,7 +366,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||||
P 470a3a0b20775be1226fb4d477c798d8da2d5708
|
P 88fa510e4c684513bbb59031d034fdb5c51a6a15
|
||||||
R 2a51dd29d0ce74e2c7cf789f7bd17241
|
R 9f300784595c0ed5be31e8d13114f756
|
||||||
U danielk1977
|
U danielk1977
|
||||||
Z 0d507f27fec3f378ea4bc0c20801973d
|
Z 6d8c84f1329cd866e4eca1550fa6f4bb
|
||||||
|
@ -1 +1 @@
|
|||||||
88fa510e4c684513bbb59031d034fdb5c51a6a15
|
6380a9b118cf972c3c7d4886ecdb62c44f2208ca
|
189
src/test8.c
189
src/test8.c
@ -13,7 +13,7 @@
|
|||||||
** is not included in the SQLite library. It is used for automated
|
** is not included in the SQLite library. It is used for automated
|
||||||
** testing of the SQLite library.
|
** testing of the SQLite library.
|
||||||
**
|
**
|
||||||
** $Id: test8.c,v 1.21 2006/06/15 07:29:01 danielk1977 Exp $
|
** $Id: test8.c,v 1.22 2006/06/15 10:41:16 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "tcl.h"
|
#include "tcl.h"
|
||||||
@ -428,6 +428,9 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
|||||||
if( pVtab->aIndex[iCol] ){
|
if( pVtab->aIndex[iCol] ){
|
||||||
char *zCol = pVtab->aCol[iCol];
|
char *zCol = pVtab->aCol[iCol];
|
||||||
char *zOp = 0;
|
char *zOp = 0;
|
||||||
|
if( iCol<0 ){
|
||||||
|
zCol = "rowid";
|
||||||
|
}
|
||||||
switch( pConstraint->op ){
|
switch( pConstraint->op ){
|
||||||
case SQLITE_INDEX_CONSTRAINT_EQ:
|
case SQLITE_INDEX_CONSTRAINT_EQ:
|
||||||
zOp = "="; break;
|
zOp = "="; break;
|
||||||
@ -479,139 +482,121 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void string_concat(char **pzStr, char *zAppend, int doFree){
|
||||||
|
char *zIn = *pzStr;
|
||||||
|
if( zIn ){
|
||||||
|
char *zTemp = zIn;
|
||||||
|
zIn = sqlite3_mprintf("%s%s", zIn, zAppend);
|
||||||
|
sqlite3_free(zTemp);
|
||||||
|
}else{
|
||||||
|
zIn = sqlite3_mprintf("%s", zAppend);
|
||||||
|
}
|
||||||
|
*pzStr = zIn;
|
||||||
|
if( doFree ){
|
||||||
|
sqlite3_free(zAppend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** apData[0] apData[1] apData[2..]
|
||||||
|
**
|
||||||
|
** INTEGER DELETE
|
||||||
|
**
|
||||||
|
** INTEGER NULL (nCol args) UPDATE (do not set rowid)
|
||||||
|
** INTEGER INTEGER (nCol args) UPDATE (with SET rowid = <arg1>)
|
||||||
|
**
|
||||||
|
** NULL NULL (nCol args) INSERT INTO (automatic rowid value)
|
||||||
|
** NULL INTEGER (nCol args) INSERT (incl. rowid value)
|
||||||
|
**
|
||||||
|
*/
|
||||||
int echoUpdate(sqlite3_vtab *tab, int nData, sqlite3_value **apData){
|
int echoUpdate(sqlite3_vtab *tab, int nData, sqlite3_value **apData){
|
||||||
echo_vtab *pVtab = (echo_vtab *)tab;
|
echo_vtab *pVtab = (echo_vtab *)tab;
|
||||||
sqlite3 *db = pVtab->db;
|
sqlite3 *db = pVtab->db;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
|
|
||||||
|
sqlite3_stmt *pStmt;
|
||||||
|
char *z = 0; /* SQL statement to execute */
|
||||||
|
int bindArgZero = 0; /* True to bind apData[0] to sql var no. nData */
|
||||||
|
int bindArgOne = 0; /* True to bind apData[1] to sql var no. 1 */
|
||||||
|
int i; /* Counter variable used by for loops */
|
||||||
|
|
||||||
assert( nData==pVtab->nCol+2 || nData==1 );
|
assert( nData==pVtab->nCol+2 || nData==1 );
|
||||||
|
|
||||||
/* If apData[0] is an integer and nData>1 then do an UPDATE */
|
/* If apData[0] is an integer and nData>1 then do an UPDATE */
|
||||||
if( nData>1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){
|
if( nData>1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){
|
||||||
char *zUpdate = sqlite3_mprintf("UPDATE %Q", pVtab->zTableName);
|
z = sqlite3_mprintf("UPDATE %Q", pVtab->zTableName);
|
||||||
char *zSep = " SET";
|
char *zSep = " SET";
|
||||||
char *zTemp;
|
|
||||||
int i, j;
|
|
||||||
sqlite3_stmt *pStmt;
|
|
||||||
|
|
||||||
if( apData[1] && sqlite3_value_type(apData[1]) &&
|
bindArgOne = (apData[1] && sqlite3_value_type(apData[1])==SQLITE_INTEGER);
|
||||||
sqlite3_value_int64(apData[0])!=sqlite3_value_int64(apData[1]) ){
|
bindArgZero = 1;
|
||||||
zTemp = sqlite3_mprintf("%s SET rowid=%lld", zUpdate, zSep,
|
|
||||||
sqlite3_value_int64(apData[1]));
|
if( bindArgOne ){
|
||||||
sqlite3_free(zUpdate);
|
string_concat(&z, " SET rowid=?1 ", 0);
|
||||||
zUpdate = zTemp;
|
|
||||||
zSep = ",";
|
zSep = ",";
|
||||||
}
|
}
|
||||||
for(i=2; i<nData; i++){
|
for(i=2; i<nData; i++){
|
||||||
if( apData[i]==0 ) continue;
|
if( apData[i]==0 ) continue;
|
||||||
zTemp = sqlite3_mprintf("%s%s %Q=?", zUpdate, zSep, pVtab->aCol[i-2]);
|
string_concat(&z, sqlite3_mprintf(
|
||||||
sqlite3_free(zUpdate);
|
"%s %Q=?%d", zSep, pVtab->aCol[i-2], i), 1);
|
||||||
zUpdate = zTemp;
|
|
||||||
zSep = ",";
|
zSep = ",";
|
||||||
}
|
}
|
||||||
zTemp = sqlite3_mprintf("%s WHERE rowid=%lld", zUpdate,
|
string_concat(&z, sqlite3_mprintf(" WHERE rowid=?%d", nData), 0);
|
||||||
sqlite3_value_int64(apData[0]));
|
|
||||||
sqlite3_free(zUpdate);
|
|
||||||
zUpdate = zTemp;
|
|
||||||
rc = sqlite3_prepare(db, zUpdate, -1, &pStmt, 0);
|
|
||||||
assert( rc!=SQLITE_OK || pStmt );
|
|
||||||
if( rc ) return rc;
|
|
||||||
for(i=2, j=1; i<nData; i++){
|
|
||||||
if( apData[i]==0 ) continue;
|
|
||||||
switch( sqlite3_value_type(apData[i]) ){
|
|
||||||
case SQLITE_INTEGER: {
|
|
||||||
sqlite3_bind_int64(pStmt, j, sqlite3_value_int64(apData[i]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SQLITE_FLOAT: {
|
|
||||||
sqlite3_bind_double(pStmt, j, sqlite3_value_double(apData[i]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SQLITE_NULL: {
|
|
||||||
sqlite3_bind_null(pStmt, j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SQLITE_TEXT: {
|
|
||||||
sqlite3_bind_text(pStmt, j, sqlite3_value_text(apData[i]),
|
|
||||||
sqlite3_value_bytes(apData[i]), SQLITE_TRANSIENT);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SQLITE_BLOB: {
|
|
||||||
sqlite3_bind_blob(pStmt, j, sqlite3_value_blob(apData[i]),
|
|
||||||
sqlite3_value_bytes(apData[i]), SQLITE_TRANSIENT);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
sqlite3_step(pStmt);
|
|
||||||
rc = sqlite3_finalize(pStmt);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If apData[0] is an integer, delete the identified row */
|
/* If apData[0] is an integer and nData==1 then do a DELETE */
|
||||||
if( sqlite3_value_type(apData[0])==SQLITE_INTEGER ){
|
else if( nData==1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){
|
||||||
const char *zFormat = "DELETE FROM %Q WHERE rowid = ?";
|
z = sqlite3_mprintf("DELETE FROM %Q WHERE rowid = ?1", pVtab->zTableName);
|
||||||
char *zDelete = sqlite3_mprintf(zFormat, pVtab->zTableName);
|
bindArgZero = 1;
|
||||||
if( !zDelete ){
|
|
||||||
rc = SQLITE_NOMEM;
|
|
||||||
}else{
|
|
||||||
sqlite3_stmt *pStmt = 0;
|
|
||||||
rc = sqlite3_prepare(db, zDelete, -1, &pStmt, 0);
|
|
||||||
assert( rc!=SQLITE_OK || pStmt );
|
|
||||||
if( rc==SQLITE_OK ){
|
|
||||||
sqlite3_bind_value(pStmt, 1, apData[0]);
|
|
||||||
sqlite3_step(pStmt);
|
|
||||||
rc = sqlite3_finalize(pStmt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there is more than a single argument, INSERT a new row */
|
/* If the first argument is NULL and there are more than two args, INSERT */
|
||||||
if( rc==SQLITE_OK && nData>1 ){
|
else if( nData>2 && sqlite3_value_type(apData[0])==SQLITE_NULL ){
|
||||||
int ii;
|
int ii;
|
||||||
char *zInsert = 0;
|
char *zInsert = 0;
|
||||||
char *zValues = 0;
|
char *zValues = 0;
|
||||||
char *zQuery = 0;
|
|
||||||
const char *zTab = pVtab->zTableName;
|
|
||||||
|
|
||||||
zInsert = sqlite3_mprintf("INSERT OR REPLACE INTO %Q (rowid", zTab);
|
zInsert = sqlite3_mprintf("INSERT OR REPLACE INTO %Q (", pVtab->zTableName);
|
||||||
|
if( sqlite3_value_type(apData[1])==SQLITE_INTEGER ){
|
||||||
|
bindArgOne = 1;
|
||||||
zValues = sqlite3_mprintf("?");
|
zValues = sqlite3_mprintf("?");
|
||||||
|
string_concat(&zInsert, "rowid", 0);
|
||||||
for(ii=0; ii<pVtab->nCol && zInsert && zValues; ii++){
|
|
||||||
char *zNew = sqlite3_mprintf("%s, %Q", zInsert, pVtab->aCol[ii]);
|
|
||||||
sqlite3_free(zInsert);
|
|
||||||
zInsert = zNew;
|
|
||||||
|
|
||||||
zNew = sqlite3_mprintf("%s, ?", zValues);
|
|
||||||
sqlite3_free(zValues);
|
|
||||||
zValues = zNew;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( zInsert && zValues ){
|
assert((pVtab->nCol+2)==nData);
|
||||||
zQuery = sqlite3_mprintf("%s) VALUES(%s)", zInsert, zValues);
|
for(ii=2; ii<nData; ii++){
|
||||||
|
string_concat(&zInsert,
|
||||||
|
sqlite3_mprintf("%s%Q", zValues?", ":"", pVtab->aCol[ii-2]), 1);
|
||||||
|
string_concat(&zValues,
|
||||||
|
sqlite3_mprintf("%s?%d", zValues?", ":"", ii), 1);
|
||||||
}
|
}
|
||||||
if( zQuery ){
|
|
||||||
sqlite3_stmt *pStmt = 0;
|
string_concat(&z, zInsert, 1);
|
||||||
rc = sqlite3_prepare(db, zQuery, -1, &pStmt, 0);
|
string_concat(&z, ") VALUES(", 0);
|
||||||
for(ii=1; rc==SQLITE_OK && ii<nData; ii++){
|
string_concat(&z, zValues, 1);
|
||||||
rc = sqlite3_bind_value(pStmt, ii, apData[ii]);
|
string_concat(&z, ")", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Anything else is an error */
|
||||||
|
else{
|
||||||
|
assert(0);
|
||||||
|
return SQLITE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sqlite3_prepare(db, z, -1, &pStmt, 0);
|
||||||
|
assert( rc!=SQLITE_OK || pStmt );
|
||||||
|
sqlite3_free(z);
|
||||||
|
if( rc==SQLITE_OK ) {
|
||||||
|
if( bindArgZero ){
|
||||||
|
sqlite3_bind_value(pStmt, nData, apData[0]);
|
||||||
|
}
|
||||||
|
if( bindArgOne ){
|
||||||
|
sqlite3_bind_value(pStmt, 1, apData[1]);
|
||||||
|
}
|
||||||
|
for(i=2; i<nData; i++){
|
||||||
|
if( apData[i] ) sqlite3_bind_value(pStmt, i, apData[i]);
|
||||||
}
|
}
|
||||||
if( rc==SQLITE_OK ){
|
|
||||||
sqlite3_step(pStmt);
|
sqlite3_step(pStmt);
|
||||||
rc = sqlite3_finalize(pStmt);
|
rc = sqlite3_finalize(pStmt);
|
||||||
}else{
|
|
||||||
sqlite3_finalize(pStmt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlite3_free(zValues);
|
|
||||||
sqlite3_free(zInsert);
|
|
||||||
sqlite3_free(zQuery);
|
|
||||||
if( rc==SQLITE_OK && (!zValues || !zInsert || !zQuery) ){
|
|
||||||
sqlite3FailedMalloc();
|
|
||||||
rc = SQLITE_NOMEM;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is creating and dropping virtual tables.
|
# focus of this file is creating and dropping virtual tables.
|
||||||
#
|
#
|
||||||
# $Id: vtab1.test,v 1.16 2006/06/15 07:29:01 danielk1977 Exp $
|
# $Id: vtab1.test,v 1.17 2006/06/15 10:41:16 danielk1977 Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@ -434,13 +434,63 @@ do_test vtab1-6-4 {
|
|||||||
SELECT * FROM techo;
|
SELECT * FROM techo;
|
||||||
}
|
}
|
||||||
} {5 2 3}
|
} {5 2 3}
|
||||||
do_test vtab1-6-5 {
|
|
||||||
|
# TODO: This causes a crash at present.
|
||||||
|
#
|
||||||
|
# do_test vtab1-6-5 {
|
||||||
|
# explain {
|
||||||
|
# UPDATE techo set a = a||b||c;
|
||||||
|
# }
|
||||||
|
# execsql {
|
||||||
|
# UPDATE techo set a = a||b||c;
|
||||||
|
# SELECT * FROM techo;
|
||||||
|
# }
|
||||||
|
#} {523 2 3}
|
||||||
|
|
||||||
|
do_test vtab1-6-6 {
|
||||||
|
execsql {
|
||||||
|
UPDATE techo set rowid = 10;
|
||||||
|
SELECT rowid FROM techo;
|
||||||
|
}
|
||||||
|
} {10}
|
||||||
|
|
||||||
|
do_test vtab1-6-7 {
|
||||||
execsql {
|
execsql {
|
||||||
DELETE FROM techo;
|
DELETE FROM techo;
|
||||||
SELECT * FROM techo;
|
SELECT * FROM techo;
|
||||||
}
|
}
|
||||||
} {}
|
} {}
|
||||||
# check_echo_table vtab1-6.3 treal techo
|
|
||||||
|
|
||||||
|
file delete -force test2.db
|
||||||
|
file delete -force test2.db-journal
|
||||||
|
sqlite3 db2 test2.db
|
||||||
|
execsql {
|
||||||
|
CREATE TABLE techo(a PRIMARY KEY, b, c);
|
||||||
|
} db2
|
||||||
|
proc check_echo_table {tn} {
|
||||||
|
set ::data1 [execsql {SELECT rowid, * FROM techo}]
|
||||||
|
set ::data2 [execsql {SELECT rowid, * FROM techo} db2]
|
||||||
|
do_test $tn {
|
||||||
|
string equal $::data1 $::data2
|
||||||
|
} 1
|
||||||
|
}
|
||||||
|
set tn 0
|
||||||
|
foreach stmt [list \
|
||||||
|
{INSERT INTO techo VALUES('abc', 'def', 'ghi')} \
|
||||||
|
{INSERT INTO techo SELECT a||'.'||rowid, b, c FROM techo} \
|
||||||
|
{INSERT INTO techo SELECT a||'x'||rowid, b, c FROM techo} \
|
||||||
|
{INSERT INTO techo SELECT a||'y'||rowid, b, c FROM techo} \
|
||||||
|
{DELETE FROM techo WHERE (oid % 3) = 0} \
|
||||||
|
{UPDATE techo set rowid = 100 WHERE rowid = 1} \
|
||||||
|
{INSERT INTO techo(a, b) VALUES('hello', 'world')} \
|
||||||
|
{DELETE FROM techo} \
|
||||||
|
] {
|
||||||
|
execsql $stmt
|
||||||
|
execsql $stmt db2
|
||||||
|
check_echo_table vtab1-6.6.[incr tn]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
db2 close
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user