#include #include #include #include static int cmp ( const void *pa, const void *pb) { int *p1 = (int *) pa; int *p2 = (int *) pb; if( *p1 < *p2 ) return -1; if( *p1 > *p2 ) return 1; return 0; } static int cmpcat ( const void *pa, const void *pb) { dbCatVal *p1 = (dbCatVal *) pa; dbCatVal *p2 = (dbCatVal *) pb; if( p1->cat < p2->cat ) return -1; if( p1->cat > p2->cat ) return 1; return 0; } static int cmpcatkey ( const void *pa, const void *pb) { int *p1 = (int *) pa; dbCatVal *p2 = (dbCatVal *) pb; if( *p1 < p2->cat ) return -1; if( *p1 > p2->cat ) return 1; return 0; } /*! \fn \brief \return \param */ /* selet array of ordered integers * * return: number of selected values * -1 on error */ int db_select_int (dbDriver *driver, char *tab, char *col, char *where, int **pval) { int type, more, alloc, count; int *val; char buf[1024], *sval; dbString stmt; dbCursor cursor; dbColumn *column; dbValue *value; dbTable *table; G_debug (3, "db_select_int()" ); /* allocate */ alloc = 1000; val = (int *) G_malloc ( alloc * sizeof(int)); if ( where == NULL || strlen(where) == 0 ) G_snprintf(buf,1023, "SELECT %s FROM %s", col, tab); else G_snprintf(buf,1023, "SELECT %s FROM %s WHERE %s", col, tab, where); G_debug (3, " SQL: %s", buf ); db_init_string ( &stmt); db_append_string ( &stmt, buf); if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK) return (-1); table = db_get_cursor_table (&cursor); column = db_get_table_column(table, 0); /* first column */ value = db_get_column_value(column); type = db_get_column_sqltype(column); type = db_sqltype_to_Ctype(type); /* fetch the data */ count = 0; while(1) { if(db_fetch (&cursor, DB_NEXT, &more) != DB_OK) return (-1); if (!more) break; if ( count == alloc ) { alloc += 1000; val = (int *) G_realloc ( val, alloc * sizeof(int)); } switch ( type ) { case ( DB_C_TYPE_INT ): val[count] = db_get_value_int(value); break; case ( DB_C_TYPE_STRING ): sval = db_get_value_string(value); val[count] = atoi(sval); break; case ( DB_C_TYPE_DOUBLE ): val[count] = (int) db_get_value_double(value); break; default: return (-1); } count++; } db_close_cursor(&cursor); db_free_string ( &stmt ); qsort( (void *)val, count, sizeof(int), cmp); *pval = val; return (count); } /*! \fn \brief \return \param */ /* selet one (first) value from table/column for key/id * * return: number of selected values * -1 on error */ int db_select_value (dbDriver *driver, char *tab, /* table name */ char *key, /* key column name (integer) */ int id, /* identifier in key column */ char *col, /* the name of column to select the value from */ dbValue *val) /* pointer to existing dbValue to store within */ { int more, count; char buf[1024]; dbString stmt; dbCursor cursor; dbColumn *column; dbValue *value; dbTable *table; sprintf( buf, "SELECT %s FROM %s WHERE %s = %d\n", col, tab, key, id); db_init_string ( &stmt); db_append_string ( &stmt, buf); if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK) return (-1); table = db_get_cursor_table (&cursor); column = db_get_table_column(table, 0); /* first column */ value = db_get_column_value(column); /* fetch the data */ count = 0; while(1) { if(db_fetch (&cursor, DB_NEXT, &more) != DB_OK) return (-1); if (!more) break; if ( count == 0 ) db_copy_value ( val, value ); count++; } db_close_cursor(&cursor); db_free_string ( &stmt ); return (count); } /*! \fn \brief \return \param */ /* selet pairs key/value to array, values are sorted by key * * return: number of selected values * -1 on error */ int db_select_CatValArray ( dbDriver *driver, char *tab, char *key, char *col, char *where, dbCatValArray *cvarr ) { int i, type, more, nrows; char buf[1024]; dbString stmt; dbCursor cursor; dbColumn *column; dbValue *value; dbTable *table; G_debug (3, "db_select_db_select_CatValArray ()" ); db_init_string ( &stmt); sprintf( buf, "SELECT %s, %s FROM %s", key, col, tab); db_set_string ( &stmt, buf); if ( where != NULL && strlen(where) > 0 ) { db_append_string ( &stmt, " WHERE "); db_append_string ( &stmt, where ); } G_debug (3, " SQL: %s", db_get_string ( &stmt ) ); if (db_open_select_cursor(driver, &stmt, &cursor, DB_SEQUENTIAL) != DB_OK) return (-1); nrows = db_get_num_rows ( &cursor ); G_debug (3, " %d rows selected", nrows ); if ( nrows < 0 ) G_fatal_error ( "Cannot select rows from database"); db_CatValArray_alloc( cvarr, nrows ); table = db_get_cursor_table (&cursor); /* Check if key column is integer */ column = db_get_table_column(table, 0); type = db_sqltype_to_Ctype( db_get_column_sqltype(column) ); G_debug (3, " key type = %d", type ); if ( type != DB_C_TYPE_INT ) { G_fatal_error ( "Key column type is not integer" ); } column = db_get_table_column(table, 1); type = db_sqltype_to_Ctype( db_get_column_sqltype(column) ); G_debug (3, " col type = %d", type ); /* if ( type != DB_C_TYPE_INT && type != DB_C_TYPE_DOUBLE ) { G_fatal_error ( "Column type not supported by db_select_to_array()" ); } */ cvarr->ctype = type; /* fetch the data */ for ( i = 0; i < nrows; i++ ) { if(db_fetch (&cursor, DB_NEXT, &more) != DB_OK) return (-1); column = db_get_table_column(table, 0); /* first column */ value = db_get_column_value(column); cvarr->value[i].cat = db_get_value_int(value); column = db_get_table_column(table, 1); value = db_get_column_value(column); cvarr->value[i].isNull = value->isNull; switch ( type ) { case ( DB_C_TYPE_INT ): if ( value->isNull ) cvarr->value[i].val.i = 0; else cvarr->value[i].val.i = db_get_value_int(value); break; case ( DB_C_TYPE_DOUBLE ): if ( value->isNull ) cvarr->value[i].val.d = 0.0; else cvarr->value[i].val.d = db_get_value_double(value); break; case ( DB_C_TYPE_STRING ): cvarr->value[i].val.s = (dbString *)malloc(sizeof(dbString)); db_init_string ( cvarr->value[i].val.s ); if ( !(value->isNull) ) db_set_string ( cvarr->value[i].val.s, db_get_value_string(value) ); break; case ( DB_C_TYPE_DATETIME ): cvarr->value[i].val.t = (dbDateTime *) calloc(1, sizeof(dbDateTime)); if ( !(value->isNull) ) memcpy ( cvarr->value[i].val.t, &(value->t), sizeof(dbDateTime) ); break; default: return (-1); } } cvarr->n_values = nrows; db_close_cursor(&cursor); db_free_string ( &stmt ); db_CatValArray_sort ( cvarr ); return (nrows); } /* Sort dbCatValArray by category */ void db_CatValArray_sort ( dbCatValArray *arr ) { qsort( (void *) arr->value, arr->n_values, sizeof(dbCatVal), cmpcat); } /* find value by key * returns: DB_FAILED, DB_OK */ int db_CatValArray_get_value ( dbCatValArray *arr, int key, dbCatVal **cv ) { dbCatVal *catval; catval = bsearch ( (void *) &key, arr->value, arr->n_values, sizeof ( dbCatVal ), cmpcat ); if ( catval == NULL ) { return DB_FAILED; } *cv = catval; return DB_OK; } /* find value by key * returns: DB_FAILED, DB_OK */ int db_CatValArray_get_value_int ( dbCatValArray *arr, int key, int *val ) { dbCatVal *catval; catval = bsearch ( (void *) &key, arr->value, arr->n_values, sizeof ( dbCatVal ), cmpcat ); if ( catval == NULL ) { return DB_FAILED; } *val = catval->val.i; return DB_OK; } /* find value by key * returns: 0 not found, 1 OK */ int db_CatValArray_get_value_double ( dbCatValArray *arr, int key, double *val ) { dbCatVal *catval; G_debug (3, "db_CatValArray_get_value_double(), key = %d", key ); catval = bsearch ( (void *) &key, arr->value, arr->n_values, sizeof ( dbCatVal ), cmpcatkey ); if ( catval == NULL ) { return DB_FAILED; } *val = catval->val.d; return DB_OK; }