#include "my_postgres.h" #include struct st_refbuf { struct st_refbuf *prev, *next; }; void _refbuf_add( struct st_refbuf *rbs, struct st_refbuf *rbd ); void _refbuf_rem( struct st_refbuf *rb ); #define refbuf_add(rbs,rbd) _refbuf_add( (struct st_refbuf *) (rbs), (struct st_refbuf *) (rbd) ) #define refbuf_rem(rb) _refbuf_rem( (struct st_refbuf *) (rb) ) void my_set_error( my_cxt_t *cxt, const char *tpl, ... ) { va_list ap; MY_CON *con = my_con_find_by_tid( cxt, get_current_thread_id() ); va_start( ap, tpl ); if( con != NULL ) vsprintf( con->my_error, tpl, ap ); else vsprintf( cxt->lasterror, tpl, ap ); va_end( ap ); } void my_cleanup( my_cxt_t *cxt ) { MY_CON *c1, *c2; c1 = cxt->firstcon; while( c1 != NULL ) { c2 = c1->next; my_con_free( c1 ); c1 = c2; } cxt->firstcon = cxt->lastcon = NULL; } void my_cleanup_session( my_cxt_t *cxt ) { MY_CON *c1; for( c1 = cxt->firstcon; c1 != NULL; c1 = c1->next ) { my_con_cleanup( c1 ); } } int my_get_type( my_cxt_t *cxt, UPTR *ptr ) { MY_STMT *s1; MY_CON *c1; MY_RES *r1; void *pp; if( ! *ptr ) { *ptr = (UPTR) my_con_verify( cxt, *ptr ); return *ptr != 0 ? MY_TYPE_CON : 0; } pp = (void *) *ptr; for( c1 = cxt->firstcon; c1 != NULL; c1 = c1->next ) { if( c1 == pp ) return MY_TYPE_CON; for( r1 = c1->firstres; r1 != NULL; r1 = r1->next ) if( r1 == pp ) return MY_TYPE_RES; for( s1 = c1->first_stmt; s1 != NULL; s1 = s1->next ) if( s1 == pp ) return MY_TYPE_STMT; } my_set_error( cxt, "Unknown link ID 0x%07X", *ptr ); return 0; } MY_CON *my_con_add( my_cxt_t *cxt, PGconn *conn ) { MY_CON *con; Newz( 1, con, 1, MY_CON ); con->con = conn; con->tid = get_current_thread_id(); if( cxt->firstcon == NULL ) cxt->firstcon = con; else refbuf_add( cxt->lastcon, con ); cxt->lastcon = con; return con; } void my_con_cleanup( MY_CON *con ) { MY_RES *r1, *r2; MY_STMT *s1, *s2; r1 = con->firstres; while( r1 ) { r2 = r1->next; my_result_free( r1 ); r1 = r2; } con->firstres = con->lastres = NULL; s1 = con->first_stmt; while( s1 ) { s2 = s1->next; my_stmt_free( s1 ); s1 = s2; } con->first_stmt = con->last_stmt = NULL; } void my_con_free( MY_CON *con ) { my_con_cleanup( con ); PQfinish( con->con ); Safefree( con->charset ); Safefree( con ); } void my_con_rem( my_cxt_t *cxt, MY_CON *con ) { if( con == cxt->firstcon ) cxt->firstcon = con->next; if( con == cxt->lastcon ) cxt->lastcon = con->prev; refbuf_rem( con ); my_con_free( con ); } int my_con_exists( my_cxt_t *cxt, UPTR ptr ) { MY_CON *c1; for( c1 = cxt->firstcon; c1 != NULL; c1 = c1->next ) { if( (UPTR) c1 == ptr ) return MY_TYPE_CON; } my_set_error( cxt, "Unknown connection ID 0x%07X", ptr ); return 0; } MY_CON *my_con_find_by_tid( my_cxt_t *cxt, DWORD tid ) { MY_CON *c1; for( c1 = cxt->firstcon; c1 != NULL; c1 = c1->next ) { if( c1->tid == tid ) return c1; } return NULL; } MY_CON *_my_con_verify( my_cxt_t *cxt, UPTR linkid, int error ) { if( linkid ) { return my_con_exists( cxt, linkid ) ? (MY_CON *) linkid : NULL; } #ifdef USE_THREADS else { linkid = (UPTR) my_con_find_by_tid( cxt, get_current_thread_id() ); if( linkid ) return (MY_CON *) linkid; if( error ) sprintf( cxt->lasterror, "No connection found" ); return NULL; } #endif if( cxt->lastcon ) return cxt->lastcon; if( error ) sprintf( cxt->lasterror, "No connection found" ); return NULL; } MY_RES *my_result_add( MY_CON *con, PGresult *pres ) { MY_RES *res; Newz( 1, res, 1, MY_RES ); res->con = con; res->res = pres; res->numfields = PQnfields( pres ); res->numrows = PQntuples( pres ); if( con->firstres == NULL ) con->firstres = res; else refbuf_add( con->lastres, res ); con->lastres = res; return res; } void my_result_free( MY_RES *res ) { PQclear( res->res ); if( res->stmt != NULL ) res->stmt->res = NULL; Safefree( res ); } void my_result_rem( MY_RES *res ) { MY_CON *con = res->con; if( res == con->firstres ) con->firstres = res->next; if( res == con->lastres ) con->lastres = res->prev; refbuf_rem( res ); my_result_free( res ); } int my_result_exists( my_cxt_t *cxt, UPTR ptr ) { MY_CON *con; MY_RES *r1; for( con = cxt->lastcon; con != NULL; con = con->prev ) { for( r1 = con->lastres; r1 != NULL; r1 = r1->prev ) { if( (UPTR) r1 == ptr ) return MY_TYPE_RES; } } my_set_error( cxt, "Unknown result ID 0x%07X", ptr ); return 0; } char *my_stmt_convert( const char *sql, DWORD sqllen, DWORD *plen, DWORD *slen ) { const char *p1; char *tmp, *p2, ch; DWORD i, ccp = 0, php = 1; int step = 0; New( 1, tmp, sqllen * 2, char ); for( i = 0, p1 = sql, p2 = tmp; i < sqllen; i ++, p1 ++ ) { switch( ( ch = *p1 ) ) { case '\'': if( ccp < i ) { if( step == 0 ) { step = 1; ccp = i + 1; } else if( step == 1 ) { step = 0; } } *p2 ++ = '\''; break; case '"': if( ccp < i ) { if( step == 0 ) { step = 2; ccp = i + 1; } else if( step == 2 ) { step = 0; } } *p2 ++ = '"'; break; case '\\': ccp = i + 1; *p2 ++ = '\\'; break; case '?': if( step == 0 ) { // replace ? with $1, $2, $3, ... *p2 ++ = '$'; p2 = my_itoa( p2, php ++, 10 ); } else *p2 ++ = '?'; break; default: *p2 ++ = ch; } } *p2 = '\0'; if( plen != NULL ) *plen = php - 1; if( slen != NULL ) *slen = p2 - tmp; return tmp; } MY_STMT *my_stmt_add( MY_CON *con, char *stmtname, DWORD plen ) { MY_STMT *stmt; Newz( 1, stmt, 1, MY_STMT ); if( plen > 0 ) { Newz( 1, stmt->param_values, plen, char * ); Newz( 1, stmt->param_lengths, plen, int ); Newz( 1, stmt->param_formats, plen, int ); Newz( 1, stmt->param_types, plen, char ); stmt->param_count = plen; } stmt->con = con; stmt->id = stmtname; if( con->first_stmt == NULL ) con->first_stmt = stmt; else refbuf_add( con->last_stmt, stmt ); con->last_stmt = stmt; return stmt; } void my_stmt_free( MY_STMT *stmt ) { int i; Safefree( stmt->id ); Safefree( stmt->param_lengths ); Safefree( stmt->param_formats ); for( i = stmt->param_count - 1; i >= 0; i -- ) Safefree( stmt->param_values[i] ); Safefree( stmt->param_values ); Safefree( stmt->param_types ); if( stmt->res != NULL ) { if( stmt->res->bound ) my_result_rem( stmt->res ); else stmt->res->stmt = NULL; } Safefree( stmt ); } void my_stmt_rem( MY_STMT *stmt ) { MY_CON *con = stmt->con; if( con->first_stmt == stmt ) con->first_stmt = stmt->next; if( con->last_stmt == stmt ) con->last_stmt = stmt->prev; refbuf_rem( stmt ); my_stmt_free( stmt ); } int my_stmt_exists( my_cxt_t *cxt, UPTR ptr ) { MY_CON *con; MY_STMT *s1; for( con = cxt->lastcon; con != NULL; con = con->prev ) { for( s1 = con->last_stmt; s1 != NULL; s1 = s1->prev ) if( (UPTR) s1 == ptr ) return MY_TYPE_STMT; } my_set_error( cxt, "Unknown statement ID 0x%07X", ptr ); return 0; } int my_stmt_or_result( my_cxt_t *cxt, UPTR ptr ) { MY_CON *con; MY_RES *r1; MY_STMT *s1; for( con = cxt->lastcon; con != NULL; con = con->prev ) { for( r1 = con->lastres; r1 != NULL; r1 = r1->prev ) if( (UPTR) r1 == ptr ) return MY_TYPE_RES; for( s1 = con->last_stmt; s1 != NULL; s1 = s1->prev ) if( (UPTR) s1 == ptr ) return MY_TYPE_STMT; } my_set_error( cxt, "Unknown result or statement ID 0x%07X", ptr ); return 0; } int my_stmt_or_con( my_cxt_t *cxt, UPTR *ptr ) { MY_CON *con; MY_STMT *stmt; if( *ptr == 0 ) { *ptr = (UPTR) my_con_verify( cxt, *ptr ); return *ptr != 0 ? MY_TYPE_CON : 0; } for( con = cxt->lastcon; con != NULL; con = con->prev ) { if( (UPTR) con == *ptr ) return MY_TYPE_CON; for( stmt = con->last_stmt; stmt != NULL; stmt = stmt->prev ) if( (UPTR) stmt == *ptr ) return MY_TYPE_STMT; } my_set_error( cxt, "Unknown statement or connection ID 0x%07X", *ptr ); return 0; } int my_stmt_bind_param( MY_STMT *stmt, DWORD p_num, SV *val, char type ) { STRLEN vl; DWORD i; char *str; if( p_num == 0 || stmt->param_count < p_num ) { sprintf( stmt->con->my_error, "Parameter %lu out of range (%lu)", p_num, stmt->param_count ); return 0; } i = p_num - 1; if( type != 0 ) stmt->param_types[i] = type; if( ! SvOK( val ) ) { if( stmt->param_values[i] != NULL ) Safefree( stmt->param_values[i] ); stmt->param_values[i] = NULL; stmt->param_lengths[i] = 0; return 1; } switch( stmt->param_types[i] ) { case 'b': str = SvPVbytex( val, vl ); stmt->param_formats[i] = 1; // set binary Renew( stmt->param_values[i], vl, char ); Copy( str, stmt->param_values[i], vl, char ); stmt->param_lengths[i] = vl; return 1; } str = SvPVx( val, vl ); //printf( "bind_param %d [%s]\n", p_num, str ); Renew( stmt->param_values[i], vl + 1, char ); Copy( str, stmt->param_values[i], vl, char ); stmt->param_values[i][vl] = '\0'; stmt->param_lengths[i] = vl; stmt->param_formats[i] = 0; // not binary return 1; } DWORD get_current_thread_id() { #ifdef USE_THREADS #ifdef _WIN32 return GetCurrentThreadId(); #else return (DWORD) pthread_self(); #endif #else return 0; #endif } void _refbuf_add( struct st_refbuf *rbs, struct st_refbuf *rbd ) { while( rbs ) { if( rbs->next == NULL ) { rbs->next = rbd; rbd->prev = rbs; return; } rbs = rbs->next; } } void _refbuf_rem( struct st_refbuf *rb ) { if( rb ) { struct st_refbuf *rbp = rb->prev; struct st_refbuf *rbn = rb->next; if( rbp ) { rbp->next = rbn; } if( rbn ) { rbn->prev = rbp; } } } char *my_strncpy( char *dst, const char *src, DWORD len ) { char ch; for( ; len > 0; len -- ) { if( ( ch = *src ++ ) == '\0' ) { *dst = '\0'; return dst; } *dst ++ = ch; } *dst = '\0'; return dst; } char *my_strcpy( char *dst, const char *src ) { char ch; while( 1 ) { if( ( ch = *src ++ ) == '\0' ) { *dst = '\0'; return dst; } *dst ++ = ch; } *dst = '\0'; return dst; } char *my_strcpyl( char *dst, const char *src ) { char ch; while( 1 ) { if( ( ch = *src ++ ) == '\0' ) { *dst = '\0'; return dst; } *dst ++ = tolower( ch ); } *dst = '\0'; return dst; } int my_stricmp( const char *cs, const char *ct ) { register signed char __res; while( 1 ) { if( ( __res = toupper( *cs ) - toupper( *ct ++ ) ) != 0 || ! *cs ++ ) break; } return __res; } char *my_stristr( const char *str1, const char *str2 ) { char *pptr, *sptr, *start; for( start = (char *) str1; *start != '\0'; start ++ ) { /* find start of pattern in string */ for ( ; ( ( *start != '\0' ) && ( toupper( *start ) != toupper( *str2 ) ) ); start ++ ) ; if( *start == '\0' ) return NULL; pptr = (char *) str2; sptr = (char *) start; while( toupper( *sptr ) == toupper( *pptr ) ) { sptr ++; pptr ++; /* if end of pattern then pattern was found */ if( *pptr == '\0' ) return start; } } return NULL; } char *my_strtolower( char *a ) { char *ret = a; while( *a != '\0' ) { if( isupper( *a ) ) *a = tolower( *a ); a ++; } return ret; } char *my_strrev( char *str, size_t len ) { char *p1, *p2; if( ! str || ! *str ) return str; for( p1 = str, p2 = str + len - 1; p2 > p1; ++ p1, -- p2 ) { *p1 ^= *p2; *p2 ^= *p1; *p1 ^= *p2; } return str; } char *my_itoa( char *str, int value, int radix ) { int rem; char *ret = str; switch( radix ) { case 16: do { rem = value % 16; value /= 16; switch( rem ) { case 10: *ret ++ = 'A'; break; case 11: *ret ++ = 'B'; break; case 12: *ret ++ = 'C'; break; case 13: *ret ++ = 'D'; break; case 14: *ret ++ = 'E'; break; case 15: *ret ++ = 'F'; break; default: *ret ++ = (char) ( rem + 0x30 ); break; } } while( value != 0 ); break; default: do { rem = value % radix; value /= radix; *ret ++ = (char) ( rem + 0x30 ); } while( value != 0 ); } *ret = '\0' ; my_strrev( str, ret - str ); return ret; }