/ Check-in [3ffa51b5]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Change the pModule parameter of the xCreate and xConnect methods to a void*. (CVS 3236)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3ffa51b50a7831ef359bc40acf605decc922c498
User & Date: danielk1977 2006-06-14 06:58:16
Context
2006-06-14
07:41
Add a test case for ORDER BY using the echo module. (CVS 3237) check-in: f459f034 user: danielk1977 tags: trunk
06:58
Change the pModule parameter of the xCreate and xConnect methods to a void*. (CVS 3236) check-in: 3ffa51b5 user: danielk1977 tags: trunk
06:31
Add tests for error conditions surrounding the creation/connection of virtual tables. (CVS 3235) check-in: 5e592c42 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/sqlite.h.in.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.174 2006/06/13 23:51:34 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
** by an instance of the following structure.  This structure consists
** mostly of methods for the module.
*/
struct sqlite3_module {
  int iVersion;
  const char *zName;
  void *pAux;
  int (*xCreate)(sqlite3*, const sqlite3_module *pModule,
               int argc, char **argv,
               sqlite3_vtab **ppVTab);
  int (*xConnect)(sqlite3*, const sqlite3_module *pModule,
               int argc, char **argv,
               sqlite3_vtab **ppVTab);
  int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
  int (*xDisconnect)(sqlite3_vtab *pVTab);
  int (*xDestroy)(sqlite3_vtab *pVTab);
  int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
  int (*xClose)(sqlite3_vtab_cursor*);







|







 







|


|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.175 2006/06/14 06:58:16 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
** by an instance of the following structure.  This structure consists
** mostly of methods for the module.
*/
struct sqlite3_module {
  int iVersion;
  const char *zName;
  void *pAux;
  int (*xCreate)(sqlite3*, void *pAux,
               int argc, char **argv,
               sqlite3_vtab **ppVTab);
  int (*xConnect)(sqlite3*, void *pAux,
               int argc, char **argv,
               sqlite3_vtab **ppVTab);
  int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
  int (*xDisconnect)(sqlite3_vtab *pVTab);
  int (*xDestroy)(sqlite3_vtab *pVTab);
  int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
  int (*xClose)(sqlite3_vtab_cursor*);

Changes to src/test8.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
...
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
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the virtual table interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test8.c,v 1.12 2006/06/14 06:31:28 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  sqliteFree(p->zTableName);
  sqliteFree(p);
  return 0;
}

static int echoConstructor(
  sqlite3 *db,
  const sqlite3_module *pModule,
  int argc, char **argv,
  sqlite3_vtab **ppVtab
){
  int i;
  echo_vtab *pVtab;

  pVtab = sqliteMalloc( sizeof(*pVtab) );
  pVtab->base.pModule = pModule;
  pVtab->interp = pModule->pAux;
  pVtab->db = db;
  pVtab->zTableName = sqlite3MPrintf("%s", argv[1]);
  for(i=0; i<argc; i++){
    appendToEchoModule(pVtab->interp, argv[i]);
  }

  if( echoDeclareVtab(pVtab, db, argc, argv) ){
................................................................................
  *ppVtab = &pVtab->base;
  return SQLITE_OK;
}

/* Methods for the echo module */
static int echoCreate(
  sqlite3 *db,
  const sqlite3_module *pModule,
  int argc, char **argv,
  sqlite3_vtab **ppVtab
){
  appendToEchoModule((Tcl_Interp *)(pModule->pAux), "xCreate");
  return echoConstructor(db, pModule, argc, argv, ppVtab);
}
static int echoConnect(
  sqlite3 *db,
  const sqlite3_module *pModule,
  int argc, char **argv,
  sqlite3_vtab **ppVtab
){
  appendToEchoModule((Tcl_Interp *)(pModule->pAux), "xConnect");
  return echoConstructor(db, pModule, argc, argv, ppVtab);
}

static int echoDisconnect(sqlite3_vtab *pVtab){
  appendToEchoModule(((echo_vtab *)pVtab)->interp, "xDisconnect");
  return echoDestructor(pVtab);
}
static int echoDestroy(sqlite3_vtab *pVtab){







|







 







|







<
|







 







|



|
|



|



|
|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241
...
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
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the virtual table interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test8.c,v 1.13 2006/06/14 06:58:16 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  sqliteFree(p->zTableName);
  sqliteFree(p);
  return 0;
}

static int echoConstructor(
  sqlite3 *db,
  void *pAux,
  int argc, char **argv,
  sqlite3_vtab **ppVtab
){
  int i;
  echo_vtab *pVtab;

  pVtab = sqliteMalloc( sizeof(*pVtab) );

  pVtab->interp = (Tcl_Interp *)pAux;
  pVtab->db = db;
  pVtab->zTableName = sqlite3MPrintf("%s", argv[1]);
  for(i=0; i<argc; i++){
    appendToEchoModule(pVtab->interp, argv[i]);
  }

  if( echoDeclareVtab(pVtab, db, argc, argv) ){
................................................................................
  *ppVtab = &pVtab->base;
  return SQLITE_OK;
}

/* Methods for the echo module */
static int echoCreate(
  sqlite3 *db,
  void *pAux,
  int argc, char **argv,
  sqlite3_vtab **ppVtab
){
  appendToEchoModule((Tcl_Interp *)(pAux), "xCreate");
  return echoConstructor(db, pAux, argc, argv, ppVtab);
}
static int echoConnect(
  sqlite3 *db,
  void *pAux,
  int argc, char **argv,
  sqlite3_vtab **ppVtab
){
  appendToEchoModule((Tcl_Interp *)(pAux), "xConnect");
  return echoConstructor(db, pAux, argc, argv, ppVtab);
}

static int echoDisconnect(sqlite3_vtab *pVtab){
  appendToEchoModule(((echo_vtab *)pVtab)->interp, "xDisconnect");
  return echoDestructor(pVtab);
}
static int echoDestroy(sqlite3_vtab *pVtab){

Changes to src/test_tclvar.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
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
** Code for testing the virtual table interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** The emphasis of this file is a virtual table that provides
** access to TCL variables.
**
** $Id: test_tclvar.c,v 1.1 2006/06/13 23:51:35 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  Tcl_Obj *pList1, *pList2;
  int i, j;
};

/* Methods for the tclvar module */
static int tclvarConnect(
  sqlite3 *db,
  const sqlite3_module *pModule,
  int argc, char **argv,
  sqlite3_vtab **ppVtab
){
  tclvar_vtab *pVtab;
  static const char zSchema[] = 
     "CREATE TABLE whatever(name TEXT, arrayname TEXT, value TEXT)";
  pVtab = sqliteMalloc( sizeof(*pVtab) );
  if( pVtab==0 ) return SQLITE_NOMEM;
  *ppVtab = &pVtab->base;
  pVtab->base.pModule = pModule;
  pVtab->interp = pModule->pAux;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3_declare_vtab(db, zSchema);
#endif
  return SQLITE_OK;
}
/* Note that for this virtual table, the xCreate and xConnect
** methods are identical. */







|







 







|









<
|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
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
** Code for testing the virtual table interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** The emphasis of this file is a virtual table that provides
** access to TCL variables.
**
** $Id: test_tclvar.c,v 1.2 2006/06/14 06:58:16 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
  Tcl_Obj *pList1, *pList2;
  int i, j;
};

/* Methods for the tclvar module */
static int tclvarConnect(
  sqlite3 *db,
  void *pAux,
  int argc, char **argv,
  sqlite3_vtab **ppVtab
){
  tclvar_vtab *pVtab;
  static const char zSchema[] = 
     "CREATE TABLE whatever(name TEXT, arrayname TEXT, value TEXT)";
  pVtab = sqliteMalloc( sizeof(*pVtab) );
  if( pVtab==0 ) return SQLITE_NOMEM;
  *ppVtab = &pVtab->base;

  pVtab->interp = (Tcl_Interp *)pAux;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3_declare_vtab(db, zSchema);
#endif
  return SQLITE_OK;
}
/* Note that for this virtual table, the xCreate and xConnect
** methods are identical. */

Changes to src/vtab.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
229
230
231
232
233
234
235











































236
237
238
239
240
241
242
...
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
279
































280
281
282
283
284
285
286
...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
**    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 contains code used to help implement virtual tables.
**
** $Id: vtab.c,v 1.9 2006/06/14 06:31:28 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"

/*
** External API function used to create a new virtual-table module.
*/
................................................................................
  if( pParse->nArgUsed ){
    pParse->zArg[pParse->nArgUsed++] = ' ';
  }
  memcpy(&pParse->zArg[pParse->nArgUsed], p->z, p->n);
  pParse->nArgUsed += p->n;
  pParse->zArg[pParse->nArgUsed] = 0;
}












































/*
** This function is invoked by the parser to call the xConnect() method
** of the virtual table pTab. If an error occurs, an error code is returned 
** and an error left in pParse.
**
** This call is a no-op if table pTab is not a virtual table.
................................................................................

  if( !pTab || !pTab->isVirtual || pTab->pVtab ){
    return SQLITE_OK;
  }

  pModule = pTab->pModule;
  zModule = pTab->azModuleArg[0];
  if( !pModule || !pModule->xConnect ){
    const char *zModule = pTab->azModuleArg[0];
    sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
    rc = SQLITE_ERROR;
  } else {
    char **azArg = pTab->azModuleArg;
    int nArg = pTab->nModuleArg;
    sqlite3 *db = pParse->db;
    assert( !db->pVTab );
    db->pVTab = pTab;
    rc = sqlite3SafetyOff(db);
    assert( rc==SQLITE_OK );
    rc = pModule->xConnect(db, pModule, nArg, azArg, &pTab->pVtab);
    db->pVTab = 0;
    if( rc ){
      sqlite3ErrorMsg(pParse, "module connect failed: %s", zModule);
      sqlite3SafetyOn(db);
    } else {
      rc = sqlite3SafetyOn(db);
    }

  }

  return rc;
}


































/*
** This function is used to set the schema of a virtual table.  It is only
** valid to call this function from within the xCreate() or xConnect() of a
** virtual table module.
*/
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
................................................................................
  sParse.declareVtab = 0;

  sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
  sqlite3DeleteTable(0, sParse.pNewTable);
  sParse.pNewTable = 0;
  db->pVTab = 0;

  return rc;
}

/*
** This function is invoked by the vdbe to call the xCreate method
** of the virtual table named zTab in database iDb. 
**
** If an error occurs, *pzErr is set to point an an English language
** description of the error and an SQLITE_XXX error code is returned.
** In this case the caller must call sqliteFree() on *pzErr.
*/
int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
  int rc = SQLITE_OK;
  Table *pTab;
  sqlite3_module *pModule;
  const char *zModule;

  pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
  assert(pTab && pTab->isVirtual && !pTab->pVtab);
  pModule = pTab->pModule;
  zModule = pTab->azModuleArg[0];

  /* If the module has been registered and includes a Create method, 
  ** invoke it now. If the module has not been registered, return an 
  ** error. Otherwise, do nothing.
  */
  if( !pModule ){
    *pzErr = sqlite3MPrintf("no such module: %s", zModule);
    rc = SQLITE_ERROR;
  }else{
    int rc2;
    char **azArg = pTab->azModuleArg;
    int nArg = pTab->nModuleArg;

    assert( !db->pVTab );
    assert( pModule->xCreate );
    db->pVTab = pTab;
    rc = sqlite3SafetyOff(db);
    assert( rc==SQLITE_OK );
    rc = pModule->xCreate(db, pModule, nArg, azArg, &pTab->pVtab);
    rc2 = sqlite3SafetyOn(db);

    if( SQLITE_OK!=rc ){
      *pzErr = sqlite3MPrintf("vtable constructor failed: %s", zTab);
    } else if( db->pVTab ){
      const char *zFormat = "vtable constructor did not declare schema: %s";
      *pzErr = sqlite3MPrintf(zFormat, zTab);
      rc = SQLITE_ERROR;
    } 
    db->pVTab = 0;
    if( rc==SQLITE_OK ){
      rc = rc2;
    }
  }

  return rc;
}

/*
** This function is invoked by the vdbe to call the xDestroy method
** of the virtual table named zTab in database iDb. This occurs
** when a DROP TABLE is mentioned.







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|




|
|
<
<
<
<
|
<
<
<
|
<
<
<

>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
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
279
280
281
282
283
284
285
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304




305



306



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
...
384
385
386
387
388
389
390























































391
392
393
394
395
396
397
**    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 contains code used to help implement virtual tables.
**
** $Id: vtab.c,v 1.10 2006/06/14 06:58:16 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"

/*
** External API function used to create a new virtual-table module.
*/
................................................................................
  if( pParse->nArgUsed ){
    pParse->zArg[pParse->nArgUsed++] = ' ';
  }
  memcpy(&pParse->zArg[pParse->nArgUsed], p->z, p->n);
  pParse->nArgUsed += p->n;
  pParse->zArg[pParse->nArgUsed] = 0;
}

/*
** Invoke a virtual table constructor (either xCreate or xConnect). The
** pointer to the function to invoke is passed as the fourth parameter
** to this procedure.
*/
static int vtabCallConstructor(
  sqlite3 *db, 
  Table *pTab,
  sqlite3_module *pModule,
  int (*xConstruct)(sqlite3*, void *, int, char **, sqlite3_vtab **),
  char **pzErr
){
  int rc;
  int rc2;
  char **azArg = pTab->azModuleArg;
  int nArg = pTab->nModuleArg;

  assert( !db->pVTab );
  assert( xConstruct );

  db->pVTab = pTab;
  rc = sqlite3SafetyOff(db);
  assert( rc==SQLITE_OK );
  rc = xConstruct(db, pModule->pAux, nArg, azArg, &pTab->pVtab);
  rc2 = sqlite3SafetyOn(db);
  if( pTab->pVtab ){
    pTab->pVtab->pModule = pModule;
  }

  if( SQLITE_OK!=rc ){
    *pzErr = sqlite3MPrintf("vtable constructor failed: %s", pTab->zName);
  } else if( db->pVTab ){
    const char *zFormat = "vtable constructor did not declare schema: %s";
    *pzErr = sqlite3MPrintf(zFormat, pTab->zName);
    rc = SQLITE_ERROR;
  } 
  if( rc==SQLITE_OK ){
    rc = rc2;
  }
  db->pVTab = 0;
  return rc;
}

/*
** This function is invoked by the parser to call the xConnect() method
** of the virtual table pTab. If an error occurs, an error code is returned 
** and an error left in pParse.
**
** This call is a no-op if table pTab is not a virtual table.
................................................................................

  if( !pTab || !pTab->isVirtual || pTab->pVtab ){
    return SQLITE_OK;
  }

  pModule = pTab->pModule;
  zModule = pTab->azModuleArg[0];
  if( !pModule ){
    const char *zModule = pTab->azModuleArg[0];
    sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
    rc = SQLITE_ERROR;
  } else {
    char *zErr = 0;
    rc = vtabCallConstructor(pParse->db,pTab,pModule,pModule->xConnect,&zErr);




    if( rc!=SQLITE_OK ){



      sqlite3ErrorMsg(pParse, "%s", zErr);



    }
    sqliteFree(zErr);
  }

  return rc;
}

/*
** This function is invoked by the vdbe to call the xCreate method
** of the virtual table named zTab in database iDb. 
**
** If an error occurs, *pzErr is set to point an an English language
** description of the error and an SQLITE_XXX error code is returned.
** In this case the caller must call sqliteFree() on *pzErr.
*/
int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
  int rc = SQLITE_OK;
  Table *pTab;
  sqlite3_module *pModule;
  const char *zModule;

  pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
  assert(pTab && pTab->isVirtual && !pTab->pVtab);
  pModule = pTab->pModule;
  zModule = pTab->azModuleArg[0];

  /* If the module has been registered and includes a Create method, 
  ** invoke it now. If the module has not been registered, return an 
  ** error. Otherwise, do nothing.
  */
  if( !pModule ){
    *pzErr = sqlite3MPrintf("no such module: %s", zModule);
    rc = SQLITE_ERROR;
  }else{
    rc = vtabCallConstructor(db, pTab, pModule, pModule->xCreate, pzErr);
  }

  return rc;
}

/*
** This function is used to set the schema of a virtual table.  It is only
** valid to call this function from within the xCreate() or xConnect() of a
** virtual table module.
*/
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
................................................................................
  sParse.declareVtab = 0;

  sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
  sqlite3DeleteTable(0, sParse.pNewTable);
  sParse.pNewTable = 0;
  db->pVTab = 0;
























































  return rc;
}

/*
** This function is invoked by the vdbe to call the xDestroy method
** of the virtual table named zTab in database iDb. This occurs
** when a DROP TABLE is mentioned.