st/code/sql/sql_search.c
2008-04-04 00:00:00 +00:00

360 lines
8.4 KiB
C

/*
===========================================================================
Copyright (C) 2007 HermitWorks Entertainment Corporation
This file is part of Space Trader source code.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
===========================================================================
*/
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
#include "sql.h"
int CompareTableByName( const void * a, const void * b ) {
return Q_stricmp( (*(tableInfo_t**)a)->name, (char*)b );
}
int CompareTables( const void * a, const void * b ) {
return Q_stricmp( (*(tableInfo_t**)a)->name, (*(tableInfo_t**)b)->name );
}
int CompareColumnByName( const void * a, const void * b ) {
return Q_stricmp( ((columnInfo_t*)a)->name, (char*)b );
}
int CompareStmtByName( const void * a, const void * b ) {
return Q_stricmp( (*(stmtInfo_t**)a)->src, (char*)b );
}
int CompareStmts( const void * a, const void * b ) {
return Q_stricmp( (*(stmtInfo_t**)a)->src, (*(stmtInfo_t**)b)->src );
}
void * search( const void * base, int count, int sizeOfElement, const void * key, int( *compare)(const void*, const void*) )
{
int i;
int lower = 0;
int upper = count-1;
if ( count==0 )
return 0;
for ( i=(lower+upper)>>1; ( lower<=upper ); )
{
int c = compare( ((char*)base) + sizeOfElement * i, key );
if ( c == 0 )
break;
if ( c > 0 )
upper = i-1;
else
lower = i+1;
i = (lower+upper)>>1;
}
if ( lower <= upper )
return ((char*)base) + sizeOfElement * i;
return 0;
}
int insert( void * base, int * count, int sizeOfElement, const void * element, int( *compare)(const void*, const void*) ) {
int lower = 0;
int upper = *count-1;
int i;
if ( *count > 0 ) {
for ( i=(lower+upper)>>1; ( lower<=upper ); )
{
int c = compare( ((char*)base) + sizeOfElement * i, element );
if ( c == 0 )
break;
if ( c > 0 )
upper = i-1;
else
lower = i+1;
i = (lower+upper)>>1;
}
if ( lower > upper )
i++;
memmove ( ((char*)base) + (i+1) * sizeOfElement, ((char*)base) + i * sizeOfElement, (*count-i) * sizeOfElement );
} else
i = 0;
Com_Memcpy ( ((char*)base) + i * sizeOfElement, element, sizeOfElement );
(*count)++;
return i;
}
tableInfo_t * find_table( sqlInfo_t * db, const char * name ) {
tableInfo_t** t = (tableInfo_t**)search( db->tables, db->table_count, sizeof(tableInfo_t*), name, CompareTableByName );
return ( t )?*t:0;
}
columnInfo_t * find_column( tableInfo_t * table, const char * name ) {
int i;
for ( i=0; i<table->column_count; i++ ) {
if ( Q_stricmp( table->columns[ i ].name, name ) == 0 ) {
return table->columns + i;
}
}
return 0;
}
stmtInfo_t * find_stmt( sqlInfo_t * db, const char * src ) {
stmtInfo_t** s = (stmtInfo_t**)search( db->stmts, db->stmt_count, sizeof(stmtInfo_t*), src, CompareStmtByName );
return ( s )?*s:0;
}
void insert_stmt( sqlInfo_t * db, stmtInfo_t * stmt ) {
ASSERT( db->stmt_count < MAX_STMTS_PER_DB );
insert( db->stmts, &db->stmt_count, sizeof(stmtInfo_t*), &stmt, CompareStmts );
}
void insert_table( sqlInfo_t * db, tableInfo_t * table ) {
ASSERT( db->table_count < MAX_TABLES_PER_DB );
insert( db->tables, &db->table_count, sizeof(tableInfo_t*), &table, CompareTables );
}
void insert_index_i( short * index, int count, cellInfo_t * rows, int column_count, int column, short row_index ) {
int lower = 0;
int upper = count-1;
cellInfo_t key = rows[ row_index * column_count + column ];
int i;
if ( count > 0 ) {
for ( i=(lower+upper)>>1; ( lower<=upper ); )
{
int c = rows[ index[ i ] * column_count + column ].integer - key.integer;
if ( c <= 0 )
lower = i+1;
else
upper = i-1;
i = (lower+upper)>>1;
}
if ( lower > upper )
i++;
memmove( &index[ i + 1 ], &index[ i ], sizeof(index[ 0 ]) * (count-i) );
} else
i = 0;
index[ i ] = row_index;
}
void insert_index_s( short * index, int count, cellInfo_t * rows, int column_count, int column, short row_index ) {
int lower = 0;
int upper = count-1;
cellInfo_t key = rows[ row_index * column_count + column ];
int i;
if ( count > 0 ) {
for ( i=(lower+upper)>>1; ( lower<=upper ); )
{
int c = Q_stricmp( rows[ index[ i ] * column_count + column ].string, key.string );
if ( c == 0 )
break;
if ( c > 0 )
upper = i-1;
else
lower = i+1;
i = (lower+upper)>>1;
}
if ( lower > upper )
i++;
memmove( &index[ i + 1 ], &index[ i ], sizeof(index[ 0 ]) * (count-i) );
} else
i = 0;
index[ i ] = row_index;
}
int search_index_i( short * index, int count, cellInfo_t * rows, int column_count, int column, cellInfo_t key ) {
int lower = 0;
int upper = count-1;
int i;
if ( count > 0 ) {
for ( i=(lower+upper)>>1; ( lower<=upper ); )
{
int c = rows[ index[ i ] * column_count + column ].integer - key.integer;
if ( c == 0 )
break;
if ( c > 0 )
upper = i-1;
else
lower = i+1;
i = (lower+upper)>>1;
}
if ( lower <= upper )
return i;
}
return -1;
}
int search_index_i_first( short * index, int count, cellInfo_t * rows, int column_count, int column, cellInfo_t key ) {
int lower = 0;
int upper = count-1;
int i;
if ( count > 0 ) {
for ( i=(lower+upper)>>1; ( lower<=upper ); )
{
if ( key.integer <= rows[ index[ i ] * column_count + column ].integer )
upper = i-1;
else
lower = i+1;
i = (lower+upper)>>1;
}
return lower;
}
return -1;
}
int search_index_i_last( short * index, int count, cellInfo_t * rows, int column_count, int column, cellInfo_t key ) {
int lower = 0;
int upper = count-1;
int i;
if ( count > 0 ) {
for ( i=(lower+upper)>>1; ( lower<=upper ); )
{
if ( key.integer >= rows[ index[ i ] * column_count + column ].integer )
lower = i+1;
else
upper = i-1;
i = (lower+upper)>>1;
}
return upper;
}
return -1;
}
int search_index_s( short * index, int count, cellInfo_t * rows, int column_count, int column, cellInfo_t key ) {
int lower = 0;
int upper = count-1;
int i;
if ( count > 0 ) {
for ( i=(lower+upper)>>1; ( lower<=upper ); )
{
int c = Q_stricmp( rows[ index[ i ] * column_count + column ].string, key.string );
if ( c == 0 )
break;
if ( c > 0 )
upper = i-1;
else
lower = i+1;
i = (lower+upper)>>1;
}
if ( lower <= upper )
return i;
}
return -1;
}
int search_index_s_first( short * index, int count, cellInfo_t * rows, int column_count, int column, cellInfo_t key ) {
int lower = 0;
int upper = count-1;
int i;
if ( count > 0 ) {
for ( i=(lower+upper)>>1; ( lower<=upper ); )
{
if ( Q_stricmp( key.string, rows[ index[ i ] * column_count + column ].string ) <= 0 )
upper = i-1;
else
lower = i+1;
i = (lower+upper)>>1;
}
return lower;
}
return -1;
}
int search_index_s_last( short * index, int count, cellInfo_t * rows, int column_count, int column, cellInfo_t key ) {
int lower = 0;
int upper = count-1;
int i;
if ( count > 0 ) {
for ( i=(lower+upper)>>1; ( lower<=upper ); )
{
if ( Q_stricmp( key.string, rows[ index[ i ] * column_count + column ].string ) >= 0 )
lower = i+1;
else
upper = i-1;
i = (lower+upper)>>1;
}
return upper;
}
return -1;
}
void sql_table_reindex( tableInfo_t * table )
{
int i;
// update index
for ( i=0; i<table->column_count; i++ ) {
columnInfo_t * column = table->columns + i;
if ( column->index ) {
short j;
for ( j=0; j<table->row_count; j++ ) {
((column->format==STRING)?insert_index_s:insert_index_i)( column->index, j, table->rows, table->column_count, column->num, j );
}
}
}
table->last_indexed = table->last_changed;
}