/* ** This function is called from within the echo-modules xCreate and ** xConnect methods. The argc and argv arguments are copies of those ** passed to the calling method. This function is responsible for ** calling sqlite3_declare_vtab() to declare the schema of the virtual ** table being created or connected. ** ** If the constructor was passed just one argument, i.e.: ** ** CREATE TABLE t1 AS echo(t2); ** ** Then t2 is assumed to be the name of a *real* database table. The ** schema of the virtual table is declared by passing a copy of the ** CREATE TABLE statement for the real table to sqlite3_declare_vtab(). ** Hence, the virtual table should have exactly the same column names and ** types as the real table. */ static int echoDeclareVtab( echo_vtab pVtab, sqlite3 db ) { int rc = SQLITE_OK; if ( pVtab.zTableName != null ) { sqlite3_stmt pStmt = null; rc = sqlite3_prepare( db, "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?", -1, ref pStmt, 0 ); if ( rc == SQLITE_OK ) { sqlite3_bind_text( pStmt, 1, pVtab.zTableName, -1, null ); if ( sqlite3_step( pStmt ) == SQLITE_ROW ) { int rc2; string zCreateTable = (string)sqlite3_column_text( pStmt, 0 ); rc = sqlite3_declare_vtab( db, zCreateTable ); rc2 = sqlite3_finalize( pStmt ); if ( rc == SQLITE_OK ) { rc = rc2; } } else { rc = sqlite3_finalize( pStmt ); if ( rc == SQLITE_OK ) { rc = SQLITE_ERROR; } } if ( rc == SQLITE_OK ) { rc = getColumnNames( db, pVtab.zTableName, out pVtab.aCol, out pVtab.nCol ); } if ( rc == SQLITE_OK ) { rc = getIndexArray( db, pVtab.zTableName, pVtab.nCol, ref pVtab.aIndex ); } } } return rc; }
/* ** This function is called to do the work of the xConnect() method - ** to allocate the required in-memory structures for a newly connected ** virtual table. */ static int echoConstructor( sqlite3 db, object pAux, int argc, string[] argv, out sqlite3_vtab ppVtab, out string pzErr ) { int rc; int i; echo_vtab pVtab; pzErr = ""; /* Allocate the sqlite3_vtab/echo_vtab structure itself */ pVtab = new echo_vtab();//sqlite3MallocZero( sizeof(*pVtab) ); //if( null==pVtab ){ // return SQLITE_NOMEM; //} pVtab.interp = ( (EchoModule)pAux ).interp; pVtab.db = db; /* Allocate echo_vtab.zThis */ pVtab.zThis = sqlite3_mprintf( "%s", argv[2] ); //if( null==pVtab.zThis ){ // object obj = ppVtab; // echoDestructor( ref obj ); // obj = null; // return SQLITE_NOMEM; //} /* Allocate echo_vtab.zTableName */ if ( argc > 3 ) { pVtab.zTableName = sqlite3_mprintf( "%s", argv[3] ); dequoteString( ref pVtab.zTableName ); if ( !String.IsNullOrEmpty( pVtab.zTableName ) && pVtab.zTableName[0] == '*' ) { string z = sqlite3_mprintf( "%s%s", argv[2], ( pVtab.zTableName.Substring(1) ) ); //sqlite3_free(pVtab.zTableName); pVtab.zTableName = z; pVtab.isPattern = 1; } //if( null==pVtab.zTableName ){ // object obj = ppVtab; // echoDestructor( ref obj ); // obj = null; // return SQLITE_NOMEM; //} } /* Log the arguments to this function to Tcl var ::echo_module */ for ( i = 0; i < argc; i++ ) { appendToEchoModule( pVtab.interp, argv[i] ); } /* Invoke sqlite3_declare_vtab and set up other members of the echo_vtab ** structure. If an error occurs, delete the sqlite3_vtab structure and ** return an error code. */ rc = echoDeclareVtab( pVtab, db ); if ( rc != SQLITE_OK ) { //object obj = ppVtab; //echoDestructor( ref obj ); //obj = null; ppVtab = null; return rc; } /* Success. Set ppVtab and return */ ppVtab = pVtab;//.base; return SQLITE_OK; }
static int simulateVtabError( echo_vtab p, string zMethod ) { string zErr; StringBuilder zVarname = new StringBuilder( 128 ); //zVarname[127] = '\0'; sqlite3_snprintf( 127, zVarname, "echo_module_fail(%s,%s)", zMethod, p.zTableName ); zErr = TCL.Tcl_GetVar( p.interp, zVarname.ToString(), (TCL.VarFlag)TCL.TCL_GLOBAL_ONLY ).ToString(); if ( zErr != "" ) { p.zErrMsg = sqlite3_mprintf( "echo-vtab-error: %s", zErr ); } return ( zErr != "" ? 1 : 0 ); }