[GRASS-SVN] r32164 - grass/trunk/db/drivers/sqlite
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Jul 18 13:23:49 EDT 2008
Author: glynn
Date: 2008-07-18 13:23:49 -0400 (Fri, 18 Jul 2008)
New Revision: 32164
Modified:
grass/trunk/db/drivers/sqlite/create_table.c
grass/trunk/db/drivers/sqlite/describe.c
grass/trunk/db/drivers/sqlite/fetch.c
grass/trunk/db/drivers/sqlite/proto.h
Log:
Use SQL types in preference to SQLite affinity types
Modified: grass/trunk/db/drivers/sqlite/create_table.c
===================================================================
--- grass/trunk/db/drivers/sqlite/create_table.c 2008-07-18 17:22:57 UTC (rev 32163)
+++ grass/trunk/db/drivers/sqlite/create_table.c 2008-07-18 17:23:49 UTC (rev 32164)
@@ -29,9 +29,6 @@
db__driver_create_table (dbTable *table)
{
int col, ncols;
- dbColumn *column;
- const char *colname;
- int sqltype;
sqlite3_stmt *statement;
dbString sql;
const char *rest;
@@ -52,10 +49,12 @@
ncols = db_get_table_number_of_columns(table);
for ( col = 0; col < ncols; col++ ) {
- column = db_get_table_column (table, col);
- colname = db_get_column_name (column);
- sqltype = db_get_column_sqltype (column);
-
+ dbColumn *column = db_get_table_column (table, col);
+ const char *colname = db_get_column_name (column);
+ int sqltype = db_get_column_sqltype (column);
+ int collen = db_get_column_length (column);
+ char buf[32];
+
G_debug ( 3, "%s (%s)", colname, db_sqltype_name(sqltype) );
if ( col > 0 ) db_append_string ( &sql, ", " );
@@ -63,25 +62,45 @@
db_append_string ( &sql, " " );
switch ( sqltype ) {
case DB_SQL_TYPE_CHARACTER:
- case DB_SQL_TYPE_TEXT:
- db_append_string ( &sql, "text");
+ sprintf(buf, "varchar(%d)", collen);
+ db_append_string ( &sql, buf);
break;
case DB_SQL_TYPE_SMALLINT:
+ db_append_string ( &sql, "smallint");
+ break;
case DB_SQL_TYPE_INTEGER:
db_append_string ( &sql, "integer");
break;
case DB_SQL_TYPE_REAL:
+ db_append_string ( &sql, "real");
+ break;
case DB_SQL_TYPE_DOUBLE_PRECISION:
+ db_append_string ( &sql, "double precision");
+ break;
case DB_SQL_TYPE_DECIMAL:
+ db_append_string ( &sql, "decimal");
+ break;
case DB_SQL_TYPE_NUMERIC:
- case DB_SQL_TYPE_INTERVAL:
- db_append_string ( &sql, "real");
+ db_append_string ( &sql, "numeric");
break;
case DB_SQL_TYPE_DATE:
+ db_append_string ( &sql, "date");
+ break;
case DB_SQL_TYPE_TIME:
+ db_append_string ( &sql, "time");
+ break;
case DB_SQL_TYPE_TIMESTAMP:
+ db_append_string ( &sql, "timestamp");
+ break;
+ case DB_SQL_TYPE_INTERVAL:
+ db_append_string ( &sql, "interval");
+ break;
+ case DB_SQL_TYPE_TEXT:
db_append_string ( &sql, "text");
- break;
+ break;
+ case DB_SQL_TYPE_SERIAL:
+ db_append_string ( &sql, "serial");
+ break;
default:
G_warning ( "Unknown column type (%s)", colname);
return DB_FAILED;
Modified: grass/trunk/db/drivers/sqlite/describe.c
===================================================================
--- grass/trunk/db/drivers/sqlite/describe.c 2008-07-18 17:22:57 UTC (rev 32163)
+++ grass/trunk/db/drivers/sqlite/describe.c 2008-07-18 17:23:49 UTC (rev 32164)
@@ -20,8 +20,10 @@
/* function prototypes */
static int affinity_type (const char *);
+static int parse_type (const char *, int *);
+static void get_column_info ( sqlite3_stmt *statement, int col,
+ int *litetype, int *sqltype, int *length );
-
/**
* \fn int db__driver_describe_table (dbString *table_name, dbTable **table)
*
@@ -105,9 +107,9 @@
for (i = 0; i < ncols; i++)
{
- int litetype, sqltype;
+ int litetype, sqltype, length;
- get_column_info ( statement, i, &litetype, &sqltype );
+ get_column_info ( statement, i, &litetype, &sqltype, &length );
if ( sqltype == DB_SQL_TYPE_UNKNOWN ) continue;
@@ -150,7 +152,7 @@
fname = sqlite3_column_name ( statement, i );
- get_column_info ( statement, i, &litetype, &sqltype );
+ get_column_info ( statement, i, &litetype, &sqltype, &fsize );
G_debug(2, "col: %s, nkcols %d, litetype : %d, sqltype %d",
fname, nkcols, litetype, sqltype );
@@ -163,22 +165,38 @@
continue;
}
- switch ( litetype) {
- case SQLITE_INTEGER:
+ switch (sqltype) {
+ case DB_SQL_TYPE_SMALLINT:
+ case DB_SQL_TYPE_INTEGER:
+ case DB_SQL_TYPE_SERIAL:
fsize = 20;
break;
- case SQLITE_FLOAT:
+ case DB_SQL_TYPE_REAL:
+ case DB_SQL_TYPE_DOUBLE_PRECISION:
+ case DB_SQL_TYPE_DECIMAL:
+ case DB_SQL_TYPE_NUMERIC:
fsize = 20;
break;
- case SQLITE_TEXT:
- fsize = 255;
+ case DB_SQL_TYPE_DATE:
+ case DB_SQL_TYPE_TIME:
+ case DB_SQL_TYPE_TIMESTAMP:
+ case DB_SQL_TYPE_INTERVAL:
+ fsize = 20;
break;
+
+ case DB_SQL_TYPE_CHARACTER:
+ /* fsize is already correct */
+ break;
+
+ case DB_SQL_TYPE_TEXT:
+ /* fudge for clients which don't understand variable-size fields */
+ fsize = 1000;
+ break;
- /* SQLITE_BLOB, SQLITE_NULL needed here? */
-
default:
+ G_warning("SQLite driver: unknown type: %d", sqltype);
fsize = 99999; /* sqlite doesn't care, it must be long enough to
satisfy tests in GRASS */
}
@@ -223,6 +241,17 @@
}
+static int dbmi_type ( int litetype )
+{
+ switch (litetype) {
+ case SQLITE_INTEGER: return DB_SQL_TYPE_INTEGER;
+ case SQLITE_FLOAT: return DB_SQL_TYPE_DOUBLE_PRECISION;
+ case SQLITE_TEXT: return DB_SQL_TYPE_TEXT;
+ case SQLITE_NULL: return DB_SQL_TYPE_TEXT; /* good choice? */
+ default: return DB_SQL_TYPE_UNKNOWN;
+ }
+}
+
/**
* \fn void get_column_info (sqlite3_stmt *statement, int col, int *litetype, int *sqltype)
*
@@ -234,8 +263,8 @@
* \param[in,out] sqltype
*/
-void get_column_info ( sqlite3_stmt *statement, int col,
- int *litetype, int *sqltype )
+static void get_column_info ( sqlite3_stmt *statement, int col,
+ int *litetype, int *sqltype, int *length )
{
const char *decltype;
@@ -243,6 +272,7 @@
if ( decltype )
{
G_debug ( 4, "column: %s, decltype = %s", sqlite3_column_name ( statement, col), decltype );
+ *sqltype = parse_type ( decltype, length );
*litetype = affinity_type ( decltype );
}
else
@@ -251,54 +281,12 @@
/* If there are no results it gives 0 */
*litetype = sqlite3_column_type ( statement, col );
+ *sqltype = dbmi_type ( *litetype );
+ *length = 0;
}
+ G_debug ( 3, "sqltype = %d", *sqltype );
G_debug ( 3, "litetype = %d", *litetype );
-
- /* http://www.sqlite.org/capi3ref.html#sqlite3_column_type
- SQLITE_INTEGER 1
- SQLITE_FLOAT 2
- SQLITE_TEXT 3
- SQLITE_BLOB 4
- SQLITE_NULL 5
-
- lib/db/dbmi_base/sqltype.c:
- DB_SQL_TYPE_CHARACTER: 0 "CHARACTER"
- DB_SQL_TYPE_NUMERIC: 1 "NUMERIC"
- DB_SQL_TYPE_DECIMAL: 2 "DECIMAL"
- DB_SQL_TYPE_SMALLINT: 3 "SMALLINT"
- DB_SQL_TYPE_INTEGER: 4 "INTEGER"
- DB_SQL_TYPE_REAL: 5 "REAL"
- DB_SQL_TYPE_DOUBLE_PRECISION: 6 "DOUBLE PRECISION"
- DB_SQL_TYPE_DATE: 7 "DATE"
- DB_SQL_TYPE_TIME: 8 "TIME"
- DB_SQL_TYPE_SERIAL: 9 "SERIAL"
- DB_SQL_TYPE_TEXT: 10 "TEXT"
- DB_SQL_TYPE_TIMESTAMP: 11 "TIMESTAMP"
- DB_SQL_TYPE_INTERVAL: 12 "INTERVAL"
- default 13 "unknown"
- */
-
- switch ( *litetype) {
- case SQLITE_INTEGER:
- *sqltype = DB_SQL_TYPE_INTEGER;
- break;
-
- case SQLITE_FLOAT:
- *sqltype = DB_SQL_TYPE_DOUBLE_PRECISION;
- break;
-
- case SQLITE_TEXT:
- *sqltype = DB_SQL_TYPE_TEXT;
- break;
-
- case SQLITE_NULL:
- *sqltype = DB_SQL_TYPE_TEXT; /* good choice? */
- break;
-
- default:
- *sqltype = DB_SQL_TYPE_UNKNOWN;
- }
}
/* SQLite documentation:
@@ -325,7 +313,7 @@
char *lc;
int aff = SQLITE_FLOAT;
- lc = strdup ( declared );
+ lc = G_store ( declared );
G_tolcase ( lc );
G_debug(4, "affinity_type: %s", lc);
@@ -342,7 +330,131 @@
{
aff = SQLITE_BLOB;
}
-
+
+ G_free(lc);
+
return aff;
}
+static int parse_type (const char *declared, int *length)
+{
+ char buf[256];
+ char word[4][256];
+
+ strncpy(buf, declared, sizeof(buf));
+ buf[sizeof(buf)-1] = '\0';
+ G_chop(buf);
+ G_tolcase(buf);
+
+ *length = 1;
+
+#define streq(a,b) (strcmp((a),(b)) == 0)
+
+ if (streq(buf, "smallint") ||
+ streq(buf, "int2"))
+ return DB_SQL_TYPE_SMALLINT;
+
+ if (streq(buf, "integer") ||
+ streq(buf, "int") ||
+ streq(buf, "int4") ||
+ streq(buf, "bigint") ||
+ streq(buf, "int8"))
+ return DB_SQL_TYPE_INTEGER;
+
+ if (streq(buf, "real") ||
+ streq(buf, "float4"))
+ return DB_SQL_TYPE_REAL;
+
+ if (streq(buf, "double") ||
+ streq(buf, "float8"))
+ return DB_SQL_TYPE_DOUBLE_PRECISION;
+
+ if (streq(buf, "decimal"))
+ return DB_SQL_TYPE_DECIMAL;
+
+ if (streq(buf, "numeric"))
+ return DB_SQL_TYPE_NUMERIC;
+
+ if (streq(buf, "date"))
+ return DB_SQL_TYPE_DATE;
+ if (streq(buf, "time") ||
+ streq(buf, "timetz"))
+ return DB_SQL_TYPE_TIME;
+
+ if (streq(buf, "timestamp") ||
+ streq(buf, "timestamptz"))
+ return DB_SQL_TYPE_TIMESTAMP;
+
+ if (streq(buf, "interval"))
+ return DB_SQL_TYPE_INTERVAL;
+
+ if (streq(buf, "text"))
+ return DB_SQL_TYPE_TEXT;
+
+ if (streq(buf, "serial") ||
+ streq(buf, "serial4"))
+ return DB_SQL_TYPE_SERIAL;
+
+ if (streq(buf, "character")
+ || streq(buf, "char")
+ || streq(buf, "varchar"))
+ return DB_SQL_TYPE_CHARACTER;
+
+ if (sscanf(buf, "%s %s", word[0], word[1]) == 2)
+ {
+ if (streq(word[0], "double") && streq(word[1], "precision"))
+ return DB_SQL_TYPE_DOUBLE_PRECISION;
+ if (streq(word[0], "character") && streq(word[1], "varying"))
+ return DB_SQL_TYPE_CHARACTER;
+ }
+
+ if (sscanf(buf, "%s %s %s %s", word[0], word[1], word[2], word[3]) == 4 &&
+ (streq(word[1], "with") || streq(word[1], "without")) &&
+ streq(word[2], "time") &&
+ streq(word[3], "zone"))
+ {
+ if (streq(word[0], "time"))
+ return DB_SQL_TYPE_TIME;
+ if (streq(word[0], "timestamp"))
+ return DB_SQL_TYPE_TIMESTAMP;
+ }
+
+ if (sscanf(buf, "varchar ( %d )", length) == 1 ||
+ sscanf(buf, "character varying ( %d )", length) == 1 ||
+ sscanf(buf, "character ( %d )", length) == 1 ||
+ sscanf(buf, "char ( %d )", length) == 1)
+ return DB_SQL_TYPE_CHARACTER;
+
+ if (sscanf(buf, "interval ( %d )", length) == 1)
+ return DB_SQL_TYPE_INTERVAL;
+
+ if (sscanf(buf, "numeric ( %d , %d )", length, length) == 2)
+ return DB_SQL_TYPE_NUMERIC;
+
+ if (sscanf(buf, "decimal ( %d , %d )", length, length) == 2)
+ return DB_SQL_TYPE_DECIMAL;
+
+ if (sscanf(buf, "time ( %d )", length) == 1 ||
+ sscanf(buf, "timetz ( %d )", length) == 1)
+ return DB_SQL_TYPE_TIME;
+
+ if (sscanf(buf, "timestamp ( %d )", length) == 1 ||
+ sscanf(buf, "timestamptz ( %d )", length) == 1)
+ return DB_SQL_TYPE_TIMESTAMP;
+
+ if (sscanf(buf, "%s ( %d ) %s %s %s", word[0], length, word[1], word[2], word[3]) == 5 &&
+ (streq(word[1], "with") || streq(word[1], "without")) &&
+ streq(word[2], "time") &&
+ streq(word[3], "zone"))
+ {
+ if (streq(word[0], "time"))
+ return DB_SQL_TYPE_TIME;
+ if (streq(word[0], "timestamp"))
+ return DB_SQL_TYPE_TIMESTAMP;
+ }
+
+#undef streq
+
+ G_warning("SQLite driver: unable to parse decltype: %s", declared);
+ return DB_SQL_TYPE_UNKNOWN;
+}
Modified: grass/trunk/db/drivers/sqlite/fetch.c
===================================================================
--- grass/trunk/db/drivers/sqlite/fetch.c 2008-07-18 17:22:57 UTC (rev 32163)
+++ grass/trunk/db/drivers/sqlite/fetch.c 2008-07-18 17:23:49 UTC (rev 32164)
@@ -106,6 +106,8 @@
int col, litetype, sqltype;
dbColumn *column;
dbValue *value;
+ const char *text;
+ dbDateTime *dt;
col = c->kcols[i]; /* known cols */
@@ -115,6 +117,7 @@
litetype = db_get_column_host_type(column);
*/
litetype = sqlite3_column_type ( c->statement, col );
+ text = (const char *) sqlite3_column_text ( c->statement, col);
value = db_get_column_value (column);
db_zero_string (&value->s);
@@ -128,8 +131,7 @@
}
G_debug (3, "col %d, litetype %d, sqltype %d: val = '%s'",
- col, litetype, sqltype,
- sqlite3_column_text ( c->statement, col) );
+ col, litetype, sqltype, text );
/* http://www.sqlite.org/capi3ref.html#sqlite3_column_type
SQLITE_INTEGER 1
@@ -145,38 +147,88 @@
/* Note: we have set DATESTYLE TO ISO in db_driver_open_select_cursor() so datetime
* format should be ISO */
- switch ( litetype ) {
- case SQLITE_TEXT:
- if (sqltype == DB_SQL_TYPE_DATE ) { /* date string */
- /* Example: '1999-01-25' */
- G_debug(3, "sqlite fetched date: %s",sqlite3_column_text ( c->statement, col));
- ns = sscanf((char *) sqlite3_column_text ( c->statement, col), "%4d-%2d-%2d",
- &(value->t.year), &(value->t.month), &(value->t.day) );
- if ( ns != 3 ) {
- append_error ( "Cannot scan date:");
- append_error ((char *) sqlite3_column_text (c->statement, col));
- report_error();
- return DB_FAILED;
- }
- value->t.hour = 0;
- value->t.minute = 0;
- value->t.seconds = 0.0;
- } else { /* other string */
- db_set_string ( &(value->s), (char *) sqlite3_column_text ( c->statement, col));
- }
- break;
+ switch ( sqltype ) {
+ case DB_SQL_TYPE_INTEGER:
+ case DB_SQL_TYPE_SMALLINT:
+ case DB_SQL_TYPE_SERIAL:
+ value->i = sqlite3_column_int ( c->statement, col);
+ break;
- case SQLITE_INTEGER:
- value->i = sqlite3_column_int ( c->statement, col);
- break;
-
- case SQLITE_FLOAT:
- value->d = sqlite3_column_double ( c->statement, col);
- break;
+ case DB_SQL_TYPE_REAL:
+ case DB_SQL_TYPE_DOUBLE_PRECISION:
+ value->d = sqlite3_column_double ( c->statement, col);
+ break;
- case SQLITE_NULL:
- /* do nothing ? */
- break;
+ case DB_SQL_TYPE_DATE:
+ dt = &value->t;
+ dt->hour = 0;
+ dt->minute = 0;
+ dt->seconds = 0.0;
+ G_debug(3, "sqlite fetched date: %s", text);
+ ns = sscanf(text, "%4d-%2d-%2d",
+ &dt->year, &dt->month, &dt->day);
+ if ( ns != 3 ) {
+ append_error ( "Cannot scan date:");
+ append_error (text);
+ report_error();
+ return DB_FAILED;
+ }
+ break;
+
+ case DB_SQL_TYPE_TIME:
+ dt = &value->t;
+ dt->year = 0;
+ dt->month = 0;
+ dt->day = 0;
+ G_debug(3, "sqlite fetched date: %s", text);
+ ns = sscanf(text, "%2d:%2d:%lf",
+ &dt->hour, &dt->minute, &dt->seconds);
+ if ( ns != 3 ) {
+ append_error ( "Cannot scan time:");
+ append_error (text);
+ report_error();
+ return DB_FAILED;
+ }
+ break;
+
+ case DB_SQL_TYPE_TIMESTAMP:
+ dt = &value->t;
+ G_debug(3, "sqlite fetched timestamp: %s", text);
+ ns = sscanf(text, "%4d-%2d-%2d %2d:%2d:%lf",
+ &dt->year, &dt->month, &dt->day,
+ &dt->hour, &dt->minute, &dt->seconds);
+ if ( ns != 6 ) {
+ append_error ( "Cannot scan timestamp:");
+ append_error (text);
+ report_error();
+ return DB_FAILED;
+ }
+ break;
+
+ case DB_SQL_TYPE_INTERVAL:
+ dt = &value->t;
+ dt->year = 0;
+ dt->month = 0;
+ dt->day = 0;
+ dt->hour = 0;
+ dt->minute = 0;
+ G_debug(3, "sqlite fetched interval: %s", text);
+ G_warning("SQLite driver: parsing of interval values not implemented; assuming seconds");
+ ns = sscanf(text, "%lf", &dt->seconds);
+ if ( ns != 1 ) {
+ append_error ( "Cannot scan interval:");
+ append_error (text);
+ report_error();
+ return DB_FAILED;
+ }
+ break;
+
+ case DB_SQL_TYPE_DECIMAL:
+ case DB_SQL_TYPE_NUMERIC:
+ case DB_SQL_TYPE_CHARACTER:
+ case DB_SQL_TYPE_TEXT:
+ db_set_string ( &value->s, text);
+ break;
}
}
Modified: grass/trunk/db/drivers/sqlite/proto.h
===================================================================
--- grass/trunk/db/drivers/sqlite/proto.h 2008-07-18 17:22:57 UTC (rev 32163)
+++ grass/trunk/db/drivers/sqlite/proto.h 2008-07-18 17:23:49 UTC (rev 32164)
@@ -14,6 +14,5 @@
/* describe.c*/
int describe_table ( sqlite3_stmt *, dbTable **, cursor * );
-void get_column_info ( sqlite3_stmt *, int, int *, int * );
#endif /* __SQLITE_PROTO_H__ */
More information about the grass-commit
mailing list