l2-unlegits/l2packets/l2data/L2Data_db.cpp
2012-02-01 05:25:08 +00:00

378 lines
11 KiB
C++

#include "stdafx.h"
#include "L2Data.h"
#include "sqlite3.h"
//char l2data_db_filename
int l2data_sqlite3_was_init = 0;
sqlite3 *l2data_sqlite3_conn_items = NULL;
sqlite3 *l2data_sqlite3_conn_npcs = NULL;
sqlite3 *l2data_sqlite3_conn_skills = NULL;
// synchronisation
#ifdef L2PACKETS_WINDOWS
CRITICAL_SECTION l2data_db_cs;
#endif
bool L2Data_DB_Init( char *outErrMsg,
const char *items_db_filename,
const char *mobs_db_filename,
const char *skills_db_filename )
{
if( outErrMsg ) outErrMsg[0] = 0;
if( !l2data_sqlite3_was_init )
{
// test for threadsafe
if( sqlite3_threadsafe() == 0 )
{
fprintf( stderr, "WARNING: sqlite3 is not configured to use thread-safe operations!\n" );
if( outErrMsg ) strcat( outErrMsg, "sqlite3 is not configured threadsafe! " );
}
//
int r = 0;
const char *errmsg = NULL;
// items
r = sqlite3_open( items_db_filename, &l2data_sqlite3_conn_items );
if( r != SQLITE_OK )
{
errmsg = sqlite3_errmsg( l2data_sqlite3_conn_items );
if( outErrMsg && errmsg ) strcat( outErrMsg, errmsg );
sqlite3_close( l2data_sqlite3_conn_items );
l2data_sqlite3_conn_items = NULL;
return false;
}
// npcs
r = sqlite3_open( mobs_db_filename, &l2data_sqlite3_conn_npcs );
if( r != SQLITE_OK )
{
errmsg = sqlite3_errmsg( l2data_sqlite3_conn_npcs );
if( outErrMsg && errmsg ) strcat( outErrMsg, errmsg );
sqlite3_close( l2data_sqlite3_conn_items );
l2data_sqlite3_conn_items = NULL;
sqlite3_close( l2data_sqlite3_conn_npcs );
l2data_sqlite3_conn_npcs = NULL;
return false;
}
// skills
r = sqlite3_open( skills_db_filename, &l2data_sqlite3_conn_skills );
if( r != SQLITE_OK )
{
errmsg = sqlite3_errmsg( l2data_sqlite3_conn_skills );
if( outErrMsg && errmsg ) strcat( outErrMsg, errmsg );
sqlite3_close( l2data_sqlite3_conn_items );
l2data_sqlite3_conn_items = NULL;
sqlite3_close( l2data_sqlite3_conn_npcs );
l2data_sqlite3_conn_npcs = NULL;
sqlite3_close( l2data_sqlite3_conn_skills );
l2data_sqlite3_conn_skills = NULL;
return false;
}
//
l2data_sqlite3_was_init = 1;
#ifdef L2PACKETS_WINDOWS
InitializeCriticalSection( &l2data_db_cs );
#endif
return true;
}
return true;
}
#ifdef L2PACKETS_WINDOWS
void L2Data_DB_Lock() { EnterCriticalSection( &l2data_db_cs ); }
void L2Data_DB_UnLock() { LeaveCriticalSection( &l2data_db_cs ); }
#endif
#ifdef L2PACKETS_LINUX
// TODO: lock/unlock semaphore (mutex?)
// FIXED: (?) uses SQLITE_THREADSAFE definition to sqlite3 library
void L2Data_DB_Lock()
{
}
void L2Data_DB_UnLock()
{
}
#endif
void L2Data_DB_Free()
{
if( l2data_sqlite3_was_init )
{
L2Data_DB_Lock();
sqlite3_close( l2data_sqlite3_conn_items );
l2data_sqlite3_conn_items = NULL;
sqlite3_close( l2data_sqlite3_conn_npcs );
l2data_sqlite3_conn_npcs = NULL;
sqlite3_close( l2data_sqlite3_conn_skills );
l2data_sqlite3_conn_skills = NULL;
l2data_sqlite3_was_init = 0;
L2Data_DB_UnLock();
#ifdef L2PACKETS_WINDOWS
DeleteCriticalSection( &l2data_db_cs );
#endif
#ifdef L2PACKETS_LINUX
// TODO: linux: delete sync object
#endif
}
}
typedef struct st_L2DATA_2PARAM
{
char *param1;
char *param2;
} L2DATA_2PARAM, *PL2DATA_2PARAM;
int L2Data_sqlite_callback_2param( void *arg, int argc, char **argv, char **argvCol )
{
argvCol = NULL; // unreferenced formal parameter
PL2DATA_2PARAM pst = (PL2DATA_2PARAM)arg;
if( !pst ) return 0;
if( !argv ) return 0;
if( argc == 1 )
{
if( pst->param1 ) pst->param1[0] = 0;
if( argv[0] && pst->param1 ) strcpy( pst->param1, argv[0] );
}
else if( argc == 2 )
{
if( pst->param1 ) pst->param1[0] = 0;
if( pst->param2 ) pst->param2[0] = 0;
if( argv[0] && pst->param1 ) strcpy( pst->param1, argv[0] );
if( argv[1] && pst->param2 ) strcpy( pst->param2, argv[1] );
}
return 0;
}
// title can be NULL
bool L2Data_DB_GetNPCNameTitleByID( unsigned int npcID, char *name, char *title )
{
if( !l2data_sqlite3_conn_npcs ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[128];
L2DATA_2PARAM st;
st.param1 = name;
st.param2 = title;
sprintf( query, "SELECT name,title FROM mobs WHERE id=%u", npcID );
int r = sqlite3_exec( l2data_sqlite3_conn_npcs, query, L2Data_sqlite_callback_2param, (void *)&st, &errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (get NPC by ID)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (get NPC by ID): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
// desc can be NULL
bool L2Data_DB_GetItemNamePicByID( unsigned int itemID, char *name, char *pic )
{
if( !l2data_sqlite3_conn_items ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[128];
L2DATA_2PARAM st;
st.param1 = name;
st.param2 = pic;
sprintf( query, "SELECT name,pic FROM items WHERE id=%u", itemID );
int r = sqlite3_exec( l2data_sqlite3_conn_items, query, L2Data_sqlite_callback_2param, (void *)&st, &errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (get item by id)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (get item by ID): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
bool L2Data_DB_GetSkillNameByID( unsigned int skillID, char *name )
{
if( !l2data_sqlite3_conn_skills ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[128];
L2DATA_2PARAM st;
st.param1 = name;
st.param2 = NULL;
sprintf( query, "SELECT name FROM skills WHERE id=%u", skillID );
int r = sqlite3_exec( l2data_sqlite3_conn_skills, query, L2Data_sqlite_callback_2param, (void *)&st, &errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (get skill by ID)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (get skill by ID): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
//#define L2DATA_RESULT_MAX_ROWS 64
int L2Data_sqlite_result_callback( void *pvResult, int colCount, char **colData, char **colName )
{
colName = NULL; // unreferenced formal parameter
L2Data_DB_Result *pResult = (L2Data_DB_Result *)pvResult;
if( !pResult ) return 0;
if( pResult->rowCount == 0 ) // current row number is 0, func called first time
{
pResult->colCount = colCount; // set column count in result set
// allocate row pointers array (maximum rows count limited :( )
pResult->rows = (char ***)malloc( pResult->inMaxRowsToGet * sizeof(char **) );
if( !pResult->rows ) return 0; // malloc() failed!
int i;
for( i=0; i<pResult->inMaxRowsToGet; i++ ) pResult->rows[i] = NULL;
}
if( pResult->rowCount >= pResult->inMaxRowsToGet ) return 0; // maximum reached, no more place
// allocate space for current row (colCount columns)
pResult->rows[ pResult->rowCount ] = (char **)malloc( colCount * sizeof( char* ) );
if( !pResult->rows[ pResult->rowCount ] ) return 0; // malloc failed! :(
// copy all coumns data to current row
int iCol;
for( iCol = 0; iCol < colCount; iCol++ )
{
if( colData[iCol] != NULL )
#ifdef L2PACKETS_WINDOWS
pResult->rows[ pResult->rowCount ][ iCol ] = _strdup( colData[iCol] ); // copy string to result set
#else // write own strdup() :)
pResult->rows[ pResult->rowCount ][ iCol ] = (char *)malloc( strlen( colData[iCol] ) + 1 );
if( pResult->rows[ pResult->rowCount ][ iCol ] ) strcpy( pResult->rows[ pResult->rowCount ][ iCol ], colData[iCol] );
#endif
else
pResult->rows[ pResult->rowCount ][ iCol ] = NULL; // NULL column value
}
//
pResult->rowCount++; // inc current row count in result set
return 0;
}
bool L2Data_DB_Query_NPCs_ByName( const char *request, L2Data_DB_Result *pResult )
{
if( !request || !pResult ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[256];
sprintf( query, "SELECT id,name,title,level FROM mobs WHERE name LIKE '%s' ORDER BY name", request );
// zero result set
pResult->colCount = 0;
pResult->rowCount = 0;
pResult->rows = NULL;
// run query
int r = sqlite3_exec( l2data_sqlite3_conn_npcs, query,
L2Data_sqlite_result_callback,
(void *)pResult, // pass pointer to result set to callback
&errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (L2Data_DB_Query_NPCs_ByName)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (L2Data_DB_Query_NPCs_ByName): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
bool L2Data_DB_Query_Items_ByName( const char *request, L2Data_DB_Result *pResult )
{
if( !request || !pResult ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[256];
sprintf( query, "SELECT id,name,pic FROM items WHERE name LIKE '%s' ORDER BY name", request );
// zero result set
pResult->colCount = 0;
pResult->rowCount = 0;
pResult->rows = NULL;
// run query
int r = sqlite3_exec( l2data_sqlite3_conn_items, query,
L2Data_sqlite_result_callback,
(void *)pResult, // pass pointer to result set to callback
&errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (L2Data_DB_Query_Items_ByName)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (L2Data_DB_Query_Items_ByName): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
bool L2Data_DB_Query_Skills_ByName( const char *request, L2Data_DB_Result *pResult )
{
if( !request || !pResult ) return false;
L2Data_DB_Lock(); // lock
char *errmsg = NULL;
char query[256];
sprintf( query, "SELECT id,name FROM skills WHERE name LIKE '%s' ORDER BY name", request );
// zero result set
pResult->colCount = 0;
pResult->rowCount = 0;
pResult->rows = NULL;
// run query
int r = sqlite3_exec( l2data_sqlite3_conn_skills, query,
L2Data_sqlite_result_callback,
(void *)pResult, // pass pointer to result set to callback
&errmsg );
if( errmsg )
{
#if defined(_DEBUG) && defined(L2PACKETS_WINDOWS)
MessageBoxA( NULL, errmsg, "sqlite3 error (L2Data_DB_Query_Skills_ByName)", MB_ICONSTOP );
#endif
#if defined(_DEBUG) && defined(L2PACKETS_LINUX)
fprintf( stderr, "sqlite3 error (L2Data_DB_Query_Skills_ByName): %s\n", errmsg );
#endif
sqlite3_free( errmsg );
}
L2Data_DB_UnLock(); // unlock
return (r == SQLITE_OK);
}
void L2Data_DB_Free_Result( L2Data_DB_Result *pResult )
{
if( !pResult ) return;
int rowCount = pResult->rowCount;
int colCount = pResult->colCount;
int ir, ic;
for( ir = 0; ir < rowCount; ir++ )
{
if( pResult->rows[ir] )
{
for( ic = 0; ic < colCount; ic++ )
{
if( pResult->rows[ir][ic] ) free( pResult->rows[ir][ic] );
}
free( pResult->rows[ir] );
}
}
free( pResult->rows );
pResult->rows = NULL;
pResult->colCount = 0;
pResult->rowCount = 0;
pResult->inMaxRowsToGet = 0;
}