#include "pgsql.h" #include "pgsql_wrapper.h" #include "clog.h" #include #include #include #include #include #include #include void map_to_cvars(mapf, CVars &rec) { map::iterator it; for(it = f.begin(); it != f.end(); it++) { logfmt( logINFO, "f[%s] = %s", it->first, it->second ); rec[it->first] = it->second; } } void load_db_record( const char * table, CVars &rec, const char * where, ... ) { logfmt( FLOG_MAX, "void load_db_record( const char * table, CVars &rec, const char * where, ... )"); size_t buf_size = 512; char *buffer = new char[buf_size]; va_list argPtr; size_t length; std::string cmd; while (true) { if (!buffer) { assert(buffer); // to stop when debugging cmd = std::string("", 16); break; } va_start(argPtr, where); length = vsnprintf(buffer, buf_size, where, argPtr); va_end(argPtr); if (length >= 0 && length < buf_size - 1) { // string fits into current buffer cmd = std::string(buffer, length); break; } // otherwise resize buffer : buf_size *= 2; // fprintf(stderr, "Reallocating vstrf-buffer to size=%u\n", buf_size); delete [] buffer; buffer = new char[buf_size]; } const PGresult* res = pgsql_query("SELECT * FROM %s WHERE %s", table, cmd.c_str() ); if( buffer ) delete [] buffer; if (!res || pgsql_num_rows(res)!=1) return; mapf = pgsql_fetch_assoc(res, 0); logfmt( FLOG_MAX, "load_db_record(%s) num_cols=%d", table, f.size() ); if (f.empty()) { return; } map::iterator it; for(it = f.begin(); it != f.end(); it++) { rec[ it->first ] = it->second; } } // This function now supports binary data long load_db_record( CVars &rec, const char * query, ... ) { logfmt( FLOG_MAX, "long load_db_record( CVars &rec, const char * query, ... )"); size_t buf_size = 512; char *buffer = new char[buf_size]; va_list argPtr; size_t length; std::string cmd; while (true) { if (!buffer) { assert(buffer); // to stop when debugging cmd = std::string("", 16); break; } va_start(argPtr, query); length = vsnprintf(buffer, buf_size, query, argPtr); va_end(argPtr); if (length >= 0 && length < buf_size - 1) { // string fits into current buffer cmd = std::string(buffer, length); break; } // otherwise resize buffer : buf_size *= 2; // fprintf(stderr, "Reallocating vstrf-buffer to size=%u\n", buf_size); delete [] buffer; buffer = new char[buf_size]; } const PGresult* res = pgsql_query("%s", cmd.c_str() ); if( buffer ) delete [] buffer; if (!res || pgsql_num_rows(res)!=1) return -1l; mapf = pgsql_fetch_assoc(res, 0); logfmt( FLOG_MAX, "load_db_record(%s) num_cols=%d", cmd.c_str(), f.size() ); if (f.empty()) { return 0l; } map::iterator it; for(it = f.begin(); it != f.end(); it++) { rec[ it->first ] = it->second; } return 1l; } #define MAX_BINARY_PARS 20 long insert_db_record( int mode, const char *table, const char *seq, CVars &rec ) { CVars::const_iterator i; char cmd[128]; /*cols[1024], vals[1024]; cols[0] = 0; vals[0] = 0;*/ bool first = true; string cols, vals; int bind_i = 0; long int sz[MAX_BINARY_PARS]; bzero( sz, sizeof(sz) ); // provides binding for all binary columns simultaneously int binary_i = 0; logfmt( FLOG_MAX, "insert_db_record()" ); snprintf( cmd, sizeof(cmd), "INSERT INTO %s (%%s) VALUES (%%s)", table ); for ( i=rec.begin(); i != rec.end(); i++ ) { NEED_ESC; // logfmt( FLOG_MAX, "'%s': i->second.valid()=%d, db()=%d", i->first.c_str(), i->second.valid(), i->second.db() ); if ( (DBS_VALID & mode) && !i->second.valid() ) continue; if ( (DBS_STREAM & mode ) && !i->second.db() ) continue; //logfmt( FLOG_MAX, "insert_db_record(): %s = %s", i->first.c_str(), i->second.c_str() ); cols += string(first?"":",") + i->first; if ( !first ) vals += ","; if ( i->second.binary() ) { /* vals += '?'; sz[binary_i] = i->second.size(); char *data = (char*)i->second.data(); //logfmt( FLOG_MAX, "saving binary parameter '%s', len = %d", i->first.c_str(), i->second.size() ); SQLBindParameter( st.hstmt, ++bind_i, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, sz[binary_i], 0, data, sz[binary_i], &sz[binary_i] ); if ( binary_i++ == MAX_BINARY_PARS ) { logfmt( FLOG_MAX, "Exceeded maximum allowed binary parameters" ); return 0; } */ throw err("Binary parameters are not supported"); } else vals += string("E'") + esc(i->second.c_str()) + "'"; /*strcatf( cols, sizeof(cols), "%s%s", first?"":",", i->first.c_str() ); strcatf( vals, sizeof(vals), "%s'%s'", first?"":",", i->second.c_str() );*/ first = false; } int res = pgsql_exec( cmd, cols.c_str(), vals.c_str() ); return curr_val( seq ); } void update_db_record( int mode, const char * table, CVars &rec, long id, const char * where, ... ) throw ( bad_parameter ) { va_list ap; va_start( ap, where ); v_update_db_record( mode, table, rec, "id", id, where, ap ); va_end( ap ); } void update_db_record( int mode, const char * table, CVars &rec, const char *index, long id, const char * where, ... ) throw ( bad_parameter ) { va_list ap; va_start( ap, where ); v_update_db_record( mode, table, rec, index, id, where, ap ); va_end( ap ); } void v_update_db_record( int mode, const char * table, CVars &rec, const char *index, long id, const char * where, va_list ap ) throw ( bad_parameter ) { logfmt( FLOG_MAX, "update_db_record()" ); int bind_i = 0; if ( !id ) throw bad_parameter( rec, "id" ); CVars::const_iterator i; char cmd[128]; bool first = true; string cols; char * wherestr; snprintf( cmd, sizeof(cmd), "UPDATE %s SET %%s WHERE %s=%lu AND %%s", table, index, id ); for ( i=rec.begin(); i != rec.end(); i++ ) { NEED_ESC; if ( !i->second.valid() ) continue; if ( (DBS_STREAM & mode) && !i->second.db() ) continue; cols += string(first?"":",") + i->first + "="; if ( ! i->second.binary() ) cols += string("E'") + esc(i->second.c_str()) + "'"; else { /* cols += "?"; long int sz = i->second.size(); char *data = (char*)i->second.data(); SQLBindParameter( st.hstmt, ++bind_i, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, sz, 0, data, sz, &sz ); */ throw err("Binary data is not supported"); } first = false; } if ( where ) { int size = vsnprintf( NULL, 0, where, ap ) + 1; wherestr = (char*)malloc( size ); if ( !wherestr ) throw err("malloc() error"); vsnprintf( wherestr, size, where, ap ); } int rows = pgsql_exec( cmd, cols.c_str(), where?wherestr:"true" ); if ( where ) free( wherestr ); if ( rows!=1 ) throw bad_parameter( rec, "id" ); } long curr_val( const char *seq ) { long size = 20+strlen(seq); char cmd[size]; snprintf( cmd, size, "SELECT currval('%s')", seq ); logfmt( FLOG_MAX, "%s", cmd); const PGresult* res = pgsql_query( cmd ); if (res && pgsql_num_rows(res)>0) { vectorf = pgsql_fetch_row(res,0); if (!f.empty() && f.size()>0) { return atol(f[0]); } } logfmt( FLOG_MAX, "SQL error" ); return -1l; } //---------------------------- class CEscape ---------------- char * CEscape::New( int sz ) { if ( ESCAPE_MAX_VARS==n ) { logfmt( FLOG_MAX, "CEscape::New() Maximum number of variables reached" ); return NULL; } vars[n] = new char[sz]; n++; return vars[n-1]; } CEscape::CEscape( char * st ) { n = 0; this->st = st; } CEscape::~CEscape() { for ( int i=0; iEscapeLength(param); return this->EscapeReal( param, New(len), len ); } int CEscape::EscapeLength( const char * par ) { if ( !par ) return 0; int i, len = strlen(par), extra = 0; for ( i=0; iesc; if (!sz) sz = sizeof(this->esc); c = (char*)cmd; esc[0] = 0; d = esc; dend = d+sz; if ( !cmd ) return esc; // LOG( cmd, LOG_MAX ); while ( c