virtualdbf.c   virtualdbf.c 
/* /*
virtualdbf.c -- SQLite3 extension [VIRTUAL TABLE accessing DBF] virtualdbf.c -- SQLite3 extension [VIRTUAL TABLE accessing DBF]
version 2.4, 2009 December 12 version 3.0, 2011 July 20
Author: Sandro Furieri a.furieri@lqt.it Author: Sandro Furieri a.furieri@lqt.it
-------------------------------------------------------------------------- --- -------------------------------------------------------------------------- ---
Version: MPL 1.1/GPL 2.0/LGPL 2.1 Version: MPL 1.1/GPL 2.0/LGPL 2.1
The contents of this file are subject to the Mozilla Public License Versio n The contents of this file are subject to the Mozilla Public License Versio n
1.1 (the "License"); you may not use this file except in compliance with 1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at the License. You may obtain a copy of the License at
skipping to change at line 51 skipping to change at line 51
the provisions above, a recipient may use your version of this file under the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL. the terms of any one of the MPL, the GPL or the LGPL.
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#ifdef SPL_AMALGAMATION /* spatialite-amalgamation */ #ifdef SPL_AMALGAMATION /* spatialite-amalgamation */
#include <spatialite/sqlite3.h> #include <spatialite/sqlite3.h>
#else #else
#include <sqlite3.h> #include <sqlite3.h>
#endif #endif
#include <spatialite/spatialite.h> #include <spatialite/spatialite.h>
#include <spatialite/gaiaaux.h> #include <spatialite/gaiaaux.h>
#include <spatialite/gaiageo.h> #include <spatialite/gaiageo.h>
#ifdef _WIN32 #ifdef _WIN32
#define strcasecmp _stricmp #define strcasecmp _stricmp
#endif /* not WIN32 */ #endif /* not WIN32 */
#if OMIT_ICONV == 0 /* if ICONV is disabled no DBF support is available */ #ifndef OMIT_ICONV /* if ICONV is disabled no DBF support is av ailable */
static struct sqlite3_module my_dbf_module; static struct sqlite3_module my_dbf_module;
typedef struct VirtualDbfStruct typedef struct VirtualDbfStruct
{ {
/* extends the sqlite3_vtab struct */ /* extends the sqlite3_vtab struct */
const sqlite3_module *pModule; /* ptr to sqlite module: USED INTERN ALLY BY SQLITE */ const sqlite3_module *pModule; /* ptr to sqlite module: USED INTERN ALLY BY SQLITE */
int nRef; /* # references: USED INTERNALLY BY SQLITE * / int nRef; /* # references: USED INTERNALLY BY SQLITE * /
char *zErrMsg; /* error message: USE INTERNALLY BY SQLITE * / char *zErrMsg; /* error message: USE INTERNALLY BY SQLITE * /
sqlite3 *db; /* the sqlite db holding the virtual table * / sqlite3 *db; /* the sqlite db holding the virtual table * /
gaiaDbfPtr dbf; /* the DBF struct */ gaiaDbfPtr dbf; /* the DBF struct */
} VirtualDbf; } VirtualDbf;
typedef VirtualDbf *VirtualDbfPtr; typedef VirtualDbf *VirtualDbfPtr;
typedef struct VirtualDbfConstraintStruct
{
/* a constraint to be verified for xFilter */
int iColumn; /* Column on left-hand side of constraint */
int op; /* Constraint operator */
char valueType; /* value Type ('I'=int,'D'=double,'T'=text)
*/
sqlite3_int64 intValue; /* Int64 comparison value */
double dblValue; /* Double comparison value */
char *txtValue; /* Text comparison value */
struct VirtualDbfConstraintStruct *next;
} VirtualDbfConstraint;
typedef VirtualDbfConstraint *VirtualDbfConstraintPtr;
typedef struct VirtualDbfCursorStruct typedef struct VirtualDbfCursorStruct
{ {
/* extends the sqlite3_vtab_cursor struct */ /* extends the sqlite3_vtab_cursor struct */
VirtualDbfPtr pVtab; /* Virtual table of this cursor */ VirtualDbfPtr pVtab; /* Virtual table of this cursor */
long current_row; /* the current row ID */ long current_row; /* the current row ID */
int eof; /* the EOF marker */ int eof; /* the EOF marker */
VirtualDbfConstraintPtr firstConstraint;
VirtualDbfConstraintPtr lastConstraint;
} VirtualDbfCursor; } VirtualDbfCursor;
typedef VirtualDbfCursor *VirtualDbfCursorPtr; typedef VirtualDbfCursor *VirtualDbfCursorPtr;
static void static void
vdbf_double_quoted_sql (char *buf) vdbf_double_quoted_sql (char *buf)
{ {
/* well-formatting a string to be used as an SQL name */ /* well-formatting a string to be used as an SQL name */
char tmp[1024]; char tmp[1024];
char *in = tmp; char *in = tmp;
char *out = buf; char *out = buf;
strcpy (tmp, buf); strcpy (tmp, buf);
skipping to change at line 280 skipping to change at line 296
sqlite3_vtab ** ppVTab, char **pzErr) sqlite3_vtab ** ppVTab, char **pzErr)
{ {
/* connects the virtual table to some DBF - simply aliases vdbf_create() */ /* connects the virtual table to some DBF - simply aliases vdbf_create() */
return vdbf_create (db, pAux, argc, argv, ppVTab, pzErr); return vdbf_create (db, pAux, argc, argv, ppVTab, pzErr);
} }
static int static int
vdbf_best_index (sqlite3_vtab * pVTab, sqlite3_index_info * pIndex) vdbf_best_index (sqlite3_vtab * pVTab, sqlite3_index_info * pIndex)
{ {
/* best index selection */ /* best index selection */
if (pVTab || pIndex) int i;
int iArg = 0;
char str[2048];
char buf[64];
if (pVTab)
pVTab = pVTab; /* unused arg warning suppression */ pVTab = pVTab; /* unused arg warning suppression */
*str = '\0';
for (i = 0; i < pIndex->nConstraint; i++)
{
if (pIndex->aConstraint[i].usable)
{
iArg++;
pIndex->aConstraintUsage[i].argvIndex = iArg;
pIndex->aConstraintUsage[i].omit = 1;
sprintf (buf, "%d:%d,", pIndex->aConstraint[i].iColumn,
pIndex->aConstraint[i].op);
strcat (str, buf);
}
}
if (*str != '\0')
{
pIndex->idxStr = sqlite3_mprintf ("%s", str);
pIndex->needToFreeIdxStr = 1;
}
return SQLITE_OK; return SQLITE_OK;
} }
static int static int
vdbf_disconnect (sqlite3_vtab * pVTab) vdbf_disconnect (sqlite3_vtab * pVTab)
{ {
/* disconnects the virtual table */ /* disconnects the virtual table */
VirtualDbfPtr p_vt = (VirtualDbfPtr) pVTab; VirtualDbfPtr p_vt = (VirtualDbfPtr) pVTab;
if (p_vt->dbf) if (p_vt->dbf)
gaiaFreeDbf (p_vt->dbf); gaiaFreeDbf (p_vt->dbf);
skipping to change at line 340 skipping to change at line 381
static int static int
vdbf_open (sqlite3_vtab * pVTab, sqlite3_vtab_cursor ** ppCursor) vdbf_open (sqlite3_vtab * pVTab, sqlite3_vtab_cursor ** ppCursor)
{ {
/* opening a new cursor */ /* opening a new cursor */
int deleted; int deleted;
VirtualDbfCursorPtr cursor = VirtualDbfCursorPtr cursor =
(VirtualDbfCursorPtr) sqlite3_malloc (sizeof (VirtualDbfCursor)); (VirtualDbfCursorPtr) sqlite3_malloc (sizeof (VirtualDbfCursor));
if (cursor == NULL) if (cursor == NULL)
return SQLITE_ERROR; return SQLITE_ERROR;
cursor->firstConstraint = NULL;
cursor->lastConstraint = NULL;
cursor->pVtab = (VirtualDbfPtr) pVTab; cursor->pVtab = (VirtualDbfPtr) pVTab;
cursor->current_row = 0; cursor->current_row = 0;
cursor->eof = 0; cursor->eof = 0;
*ppCursor = (sqlite3_vtab_cursor *) cursor; *ppCursor = (sqlite3_vtab_cursor *) cursor;
while (1) while (1)
{ {
vdbf_read_row (cursor, &deleted); vdbf_read_row (cursor, &deleted);
if (!deleted)
break;
if (cursor->eof) if (cursor->eof)
break; break;
if (!deleted)
break;
} }
return SQLITE_OK; return SQLITE_OK;
} }
static void
vdbf_free_constraints (VirtualDbfCursorPtr cursor)
{
/* memory cleanup - cursor constraints */
VirtualDbfConstraintPtr pC;
VirtualDbfConstraintPtr pCn;
pC = cursor->firstConstraint;
while (pC)
{
pCn = pC->next;
if (pC->txtValue)
sqlite3_free (pC->txtValue);
sqlite3_free (pC);
pC = pCn;
}
cursor->firstConstraint = NULL;
cursor->lastConstraint = NULL;
}
static int static int
vdbf_close (sqlite3_vtab_cursor * pCursor) vdbf_close (sqlite3_vtab_cursor * pCursor)
{ {
/* closing the cursor */ /* closing the cursor */
VirtualDbfCursorPtr cursor = (VirtualDbfCursorPtr) pCursor;
vdbf_free_constraints (cursor);
sqlite3_free (pCursor); sqlite3_free (pCursor);
return SQLITE_OK; return SQLITE_OK;
} }
static int static int
vdbf_parse_constraint (const char *str, int index, int *iColumn, int *op)
{
/* parsing a constraint string */
char buf[64];
const char *in = str;
char *out = buf;
int i = 0;
int found = 0;
*out = '\0';
while (*in != '\0')
{
if (*in == ',')
{
if (index == i)
{
*out = '\0';
found = 1;
break;
}
i++;
in++;
continue;
}
if (index == i)
*out++ = *in;
in++;
}
if (!found)
return 0;
in = buf;
for (i = 0; i < (int) strlen (buf); i++)
{
if (buf[i] == ':')
{
buf[i] = '\0';
*iColumn = atoi (buf);
*op = atoi (buf + i + 1);
return 1;
}
in++;
}
return 0;
}
static int
vdbf_eval_constraints (VirtualDbfCursorPtr cursor)
{
/* evaluating Filter constraints */
int nCol;
gaiaDbfFieldPtr pFld;
VirtualDbfConstraintPtr pC = cursor->firstConstraint;
if (pC == NULL)
return 1;
while (pC)
{
int ok = 0;
if (pC->iColumn == 0)
{
/* the PRIMARY KEY column */
if (pC->valueType == 'I')
{
switch (pC->op)
{
case SQLITE_INDEX_CONSTRAINT_EQ:
if (cursor->current_row == pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_GT:
if (cursor->current_row > pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_LE:
if (cursor->current_row <= pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_LT:
if (cursor->current_row < pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_GE:
if (cursor->current_row >= pC->intValue)
ok = 1;
break;
};
}
goto done;
}
nCol = 1;
pFld = cursor->pVtab->dbf->Dbf->First;
while (pFld)
{
if (nCol == pC->iColumn)
{
if ((pFld->Value))
{
switch (pFld->Value->Type)
{
case GAIA_INT_VALUE:
if (pC->valueType == 'I')
{
switch (pC->op)
{
case SQLITE_INDEX_CONSTRAINT_EQ:
if (pFld->Value->IntValue ==
pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_GT:
if (pFld->Value->IntValue >
pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_LE:
if (pFld->Value->IntValue <=
pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_LT:
if (pFld->Value->IntValue <
pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_GE:
if (pFld->Value->IntValue >=
pC->intValue)
ok = 1;
break;
};
}
break;
case GAIA_DOUBLE_VALUE:
if (pC->valueType == 'I')
{
switch (pC->op)
{
case SQLITE_INDEX_CONSTRAINT_EQ:
if (pFld->Value->DblValue ==
pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_GT:
if (pFld->Value->DblValue >
pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_LE:
if (pFld->Value->DblValue <=
pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_LT:
if (pFld->Value->DblValue <
pC->intValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_GE:
if (pFld->Value->DblValue >=
pC->intValue)
ok = 1;
break;
};
}
if (pC->valueType == 'D')
{
switch (pC->op)
{
case SQLITE_INDEX_CONSTRAINT_EQ:
if (pFld->Value->DblValue ==
pC->dblValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_GT:
if (pFld->Value->DblValue >
pC->dblValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_LE:
if (pFld->Value->DblValue <=
pC->dblValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_LT:
if (pFld->Value->DblValue <
pC->dblValue)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_GE:
if (pFld->Value->DblValue >=
pC->dblValue)
ok = 1;
break;
}
}
break;
case GAIA_TEXT_VALUE:
if (pC->valueType == 'T' && pC->txtValue)
{
int ret;
ret =
strcmp (pFld->Value->TxtValue,
pC->txtValue);
switch (pC->op)
{
case SQLITE_INDEX_CONSTRAINT_EQ:
if (ret == 0)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_GT:
if (ret > 0)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_LE:
if (ret <= 0)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_LT:
if (ret < 0)
ok = 1;
break;
case SQLITE_INDEX_CONSTRAINT_GE:
if (ret >= 0)
ok = 1;
break;
};
}
break;
};
}
goto done;
}
nCol++;
pFld = pFld->Next;
}
done:
if (!ok)
return 0;
pC = pC->next;
}
return 1;
}
static int
vdbf_filter (sqlite3_vtab_cursor * pCursor, int idxNum, const char *idxStr, vdbf_filter (sqlite3_vtab_cursor * pCursor, int idxNum, const char *idxStr,
int argc, sqlite3_value ** argv) int argc, sqlite3_value ** argv)
{ {
/* setting up a cursor filter */ /* setting up a cursor filter */
if (pCursor || idxNum || idxStr || argc || argv) int i;
pCursor = pCursor; /* unused arg warning suppression */ int iColumn;
int op;
int len;
int deleted;
VirtualDbfConstraintPtr pC;
VirtualDbfCursorPtr cursor = (VirtualDbfCursorPtr) pCursor;
if (idxNum)
idxNum = idxNum; /* unused arg warning suppression */
/* resetting any previously set filter constraint */
vdbf_free_constraints (cursor);
for (i = 0; i < argc; i++)
{
if (!vdbf_parse_constraint (idxStr, i, &iColumn, &op))
continue;
pC = sqlite3_malloc (sizeof (VirtualDbfConstraint));
if (!pC)
continue;
pC->iColumn = iColumn;
pC->op = op;
pC->valueType = '\0';
pC->txtValue = NULL;
pC->next = NULL;
if (sqlite3_value_type (argv[i]) == SQLITE_INTEGER)
{
pC->valueType = 'I';
pC->intValue = sqlite3_value_int64 (argv[i]);
}
if (sqlite3_value_type (argv[i]) == SQLITE_FLOAT)
{
pC->valueType = 'D';
pC->dblValue = sqlite3_value_double (argv[i]);
}
if (sqlite3_value_type (argv[i]) == SQLITE_TEXT)
{
pC->valueType = 'T';
len = sqlite3_value_bytes (argv[i]) + 1;
pC->txtValue = (char *) sqlite3_malloc (len);
if (pC->txtValue)
strcpy (pC->txtValue,
(char *) sqlite3_value_text (argv[i]));
}
if (cursor->firstConstraint == NULL)
cursor->firstConstraint = pC;
if (cursor->lastConstraint != NULL)
cursor->lastConstraint->next = pC;
cursor->lastConstraint = pC;
}
cursor->current_row = 0;
cursor->eof = 0;
while (1)
{
vdbf_read_row (cursor, &deleted);
if (cursor->eof)
break;
if (deleted)
continue;
if (vdbf_eval_constraints (cursor))
break;
}
return SQLITE_OK; return SQLITE_OK;
} }
static int static int
vdbf_next (sqlite3_vtab_cursor * pCursor) vdbf_next (sqlite3_vtab_cursor * pCursor)
{ {
/* fetching a next row from cursor */ /* fetching a next row from cursor */
int deleted; int deleted;
VirtualDbfCursorPtr cursor = (VirtualDbfCursorPtr) pCursor; VirtualDbfCursorPtr cursor = (VirtualDbfCursorPtr) pCursor;
while (1) while (1)
{ {
vdbf_read_row (cursor, &deleted); vdbf_read_row (cursor, &deleted);
if (!deleted)
break;
if (cursor->eof) if (cursor->eof)
break; break;
if (deleted)
continue;
if (vdbf_eval_constraints (cursor))
break;
} }
return SQLITE_OK; return SQLITE_OK;
} }
static int static int
vdbf_eof (sqlite3_vtab_cursor * pCursor) vdbf_eof (sqlite3_vtab_cursor * pCursor)
{ {
/* cursor EOF */ /* cursor EOF */
VirtualDbfCursorPtr cursor = (VirtualDbfCursorPtr) pCursor; VirtualDbfCursorPtr cursor = (VirtualDbfCursorPtr) pCursor;
return cursor->eof; return cursor->eof;
skipping to change at line 539 skipping to change at line 914
sqlite3_create_module_v2 (db, "VirtualDbf", &my_dbf_module, NULL, 0); sqlite3_create_module_v2 (db, "VirtualDbf", &my_dbf_module, NULL, 0);
return rc; return rc;
} }
int int
virtualdbf_extension_init (sqlite3 * db) virtualdbf_extension_init (sqlite3 * db)
{ {
return sqlite3VirtualDbfInit (db); return sqlite3VirtualDbfInit (db);
} }
#endif /* ICONV enabled/disabled */ #endif /* ICONV enabled/disabled */
 End of changes. 18 change blocks. 
10 lines changed or deleted 386 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/