📄 firebirdconnection.c
字号:
// Copyright (c) 1999-2001 David Muse// See the file COPYING for more information#include <firebirdconnection.h>#include <rudiments/rawbuffer.h>#include <rudiments/snooze.h>#include <config.h>#include <datatypes.h>// for pow()#include <math.h>#include <stdlib.h>static char tpb[] = { isc_tpb_version3, isc_tpb_write, isc_tpb_read_committed, isc_tpb_rec_version, // FIXME: vladimir changed this to isc_tpb_nowait. why? isc_tpb_wait};firebirdconnection::firebirdconnection() : sqlrconnection_svr() { dbversion=NULL;}firebirdconnection::~firebirdconnection() { delete dbversion;}uint16_t firebirdconnection::getNumberOfConnectStringVars() { return NUM_CONNECT_STRING_VARS;}void firebirdconnection::handleConnectString() { // override legacy "database" parameter with modern "db" parameter database=connectStringValue("database"); const char *tmp=connectStringValue("db"); if (tmp && tmp[0]) { database=tmp; } const char *dialectstr=connectStringValue("dialect"); if (dialectstr) { dialect=charstring::toInteger(dialectstr); if (dialect<1) { dialect=1; } if (dialect>3) { dialect=3; } } else { dialect=3; } setUser(connectStringValue("user")); setPassword(connectStringValue("password")); const char *autocom=connectStringValue("autocommit"); setAutoCommitBehavior((autocom && !charstring::compareIgnoringCase(autocom,"yes")));}bool firebirdconnection::logIn(bool printerrors) { // initialize a dpb char *dpbptr=dpb; *dpbptr++=isc_dpb_version1; *dpbptr++=isc_dpb_num_buffers; *dpbptr++=1; *dpbptr++=90; dpblength=dpbptr-dpb; // handle user/password parameters const char *user=getUser(); if (user) { environment::setValue("ISC_USER",user); } const char *password=getPassword(); if (password) { environment::setValue("ISC_PASSWORD",password); } // attach to the database db=0L; tr=0L; if (isc_attach_database(error,charstring::length(database), const_cast<char *>(database),&db, //dpblength,dpb)) { 0,NULL)) { db=0L; return false; } // start a transaction if (isc_start_transaction(error,&tr,1,&db,(uint16_t)sizeof(tpb),&tpb)) { // print the error message char msg[512]; ISC_STATUS *err=error; while (isc_interprete(msg,&err)) { fprintf(stderr,"%s\n",msg); } fprintf(stderr,"\n"); return false; } return true;}sqlrcursor_svr *firebirdconnection::initCursor() { return (sqlrcursor_svr *)new firebirdcursor( (sqlrconnection_svr *)this);}void firebirdconnection::deleteCursor(sqlrcursor_svr *curs) { delete (firebirdcursor *)curs;}void firebirdconnection::logOut() { isc_detach_database(error,&db);}bool firebirdconnection::commit() { return (!isc_commit_retaining(error,&tr));}bool firebirdconnection::rollback() { return (!isc_rollback_retaining(error,&tr));}bool firebirdconnection::ping() { // call isc_database_info to get page_size and num_buffers, // this should always be available unless the db is down // if we get an error, then return 0, otherwise return 1 ISC_STATUS status[20]; char dbitems[]={isc_info_page_size, isc_info_num_buffers, isc_info_end}; char resbuffer[40]; isc_database_info(status,&db, sizeof(dbitems),dbitems, sizeof(resbuffer),resbuffer); return !(status[0]==1 && status[1]);}const char *firebirdconnection::identify() { return "firebird";}const char *firebirdconnection::dbVersion() { ISC_STATUS status[20]; char dbitems[]={isc_info_version, isc_info_end}; char resbuffer[256]; if (!isc_database_info(status,&db, sizeof(dbitems),dbitems, sizeof(resbuffer),resbuffer)) { char *ptr=resbuffer; // first byte is isc_info_version char dbitem=*ptr; ptr++; // next 2 bytes are length of the isc_info_version data uint16_t len=isc_vax_integer(ptr,sizeof(uint16_t)); ptr=ptr+sizeof(uint16_t); // the next byte is the number of lines of text stringbuffer dbvers; char linecount=*ptr; ptr++; for (char lineindex=0; lineindex<linecount; lineindex++) { // the first byte of each line is the length of the line char linelen=*ptr; ptr++; // then comes the line of text itself if (lineindex) { dbvers.append('\n'); } dbvers.append(ptr,linelen); } delete[] dbversion; dbversion=dbvers.detachString(); return dbversion; } return "";}const char *firebirdconnection::bindFormat() { return "?";}firebirdcursor::firebirdcursor(sqlrconnection_svr *conn) : sqlrcursor_svr(conn) { firebirdconn=(firebirdconnection *)conn; errormsg=NULL; outsqlda=(XSQLDA ISC_FAR *)malloc(XSQLDA_LENGTH(MAX_SELECT_LIST_SIZE)); outsqlda->version=SQLDA_VERSION1; outsqlda->sqln=(MAX_SELECT_LIST_SIZE>MAX_BIND_VARS)? MAX_SELECT_LIST_SIZE:MAX_BIND_VARS; insqlda=(XSQLDA ISC_FAR *)malloc(XSQLDA_LENGTH(MAX_BIND_VARS)); insqlda->version=SQLDA_VERSION1; insqlda->sqln=MAX_BIND_VARS; querytype=0; stmt=NULL; queryIsExecSP=false; outbindcount=0;}firebirdcursor::~firebirdcursor() { if (errormsg) { delete errormsg; } free(outsqlda); free(insqlda);}bool firebirdcursor::prepareQuery(const char *query, uint32_t length) { queryIsExecSP=false; // free the old statement if it exists if (stmt) { isc_dsql_free_statement(firebirdconn->error, &stmt,DSQL_drop); } // allocate a cursor handle stmt=NULL; if (isc_dsql_allocate_statement(firebirdconn->error, &firebirdconn->db,&stmt)) { return false; } // skip whitespace char *qptr=(char *)query; while (*qptr==' ' || *qptr=='\n' || *qptr==' '); // prepare the cursor if (isc_dsql_prepare(firebirdconn->error,&firebirdconn->tr, &stmt,length,(char *)query, firebirdconn->dialect,outsqlda)) { return false; } // get the cursor type char typeitem[]={isc_info_sql_stmt_type}; char resbuffer[1024]; if (isc_dsql_sql_info(firebirdconn->error,&stmt, sizeof(typeitem),typeitem, 1024,resbuffer)) { return false; } ISC_LONG len=isc_vax_integer(resbuffer+1,2); querytype=isc_vax_integer(resbuffer+3,len); // find bind parameters, if any insqlda->sqld=0; if (isc_dsql_describe_bind(firebirdconn->error,&stmt,1,insqlda)) { return false; } insqlda->sqln=insqlda->sqld; return true;}bool firebirdcursor::inputBindString(const char *variable, uint16_t variablesize, const char *value, uint16_t valuesize, int16_t *isnull) { // make bind vars 1 based like all other db's long index=charstring::toInteger(variable+1)-1; if (index<0) { return false; } insqlda->sqlvar[index].sqltype=SQL_TEXT+1; insqlda->sqlvar[index].sqlscale=0; insqlda->sqlvar[index].sqlsubtype=0; insqlda->sqlvar[index].sqllen=valuesize; insqlda->sqlvar[index].sqldata=(char *)value; insqlda->sqlvar[index].sqlind=isnull; insqlda->sqlvar[index].sqlname_length=0; insqlda->sqlvar[index].sqlname[0]=(char)NULL; insqlda->sqlvar[index].relname_length=0; insqlda->sqlvar[index].relname[0]=(char)NULL; insqlda->sqlvar[index].ownname_length=0; insqlda->sqlvar[index].ownname[0]=(char)NULL; insqlda->sqlvar[index].aliasname_length=0; insqlda->sqlvar[index].aliasname[0]=(char)NULL; return true;}bool firebirdcursor::inputBindInteger(const char *variable, uint16_t variablesize, int64_t *value) { // make bind vars 1 based like all other db's long index=charstring::toInteger(variable+1)-1; if (index<0) { return false; } insqlda->sqlvar[index].sqltype=SQL_INT64; insqlda->sqlvar[index].sqlscale=0; insqlda->sqlvar[index].sqlsubtype=0; insqlda->sqlvar[index].sqllen=sizeof(int64_t); insqlda->sqlvar[index].sqldata=(char *)value; insqlda->sqlvar[index].sqlind=(short *)NULL; insqlda->sqlvar[index].sqlname_length=0; insqlda->sqlvar[index].sqlname[0]=(char)NULL; insqlda->sqlvar[index].relname_length=0; insqlda->sqlvar[index].relname[0]=(char)NULL; insqlda->sqlvar[index].ownname_length=0; insqlda->sqlvar[index].ownname[0]=(char)NULL; insqlda->sqlvar[index].aliasname_length=0; insqlda->sqlvar[index].aliasname[0]=(char)NULL; return true;}bool firebirdcursor::inputBindDouble(const char *variable, uint16_t variablesize, double *value, uint32_t precision, uint32_t scale) { // make bind vars 1 based like all other db's long index=charstring::toInteger(variable+1)-1; if (index<0) { return false; } insqlda->sqlvar[index].sqltype=SQL_DOUBLE; insqlda->sqlvar[index].sqlscale=scale; insqlda->sqlvar[index].sqlsubtype=0; insqlda->sqlvar[index].sqllen=sizeof(double); insqlda->sqlvar[index].sqldata=(char *)value; insqlda->sqlvar[index].sqlind=(short *)NULL; insqlda->sqlvar[index].sqlname_length=0; insqlda->sqlvar[index].sqlname[0]=(char)NULL; insqlda->sqlvar[index].relname_length=0; insqlda->sqlvar[index].relname[0]=(char)NULL; insqlda->sqlvar[index].ownname_length=0; insqlda->sqlvar[index].ownname[0]=(char)NULL; insqlda->sqlvar[index].aliasname_length=0; insqlda->sqlvar[index].aliasname[0]=(char)NULL; return true;}bool firebirdcursor::outputBindString(const char *variable, uint16_t variablesize, char *value, uint16_t valuesize, int16_t *isnull) { outbindisstring[outbindcount]=true; outbindcount++; // if we're doing output binds then the // query must be a stored procedure queryIsExecSP=true; // make bind vars 1 based like all other db's long index=charstring::toInteger(variable+1)-1; if (index<0) { return false; } outsqlda->sqlvar[index].sqltype=SQL_TEXT+1; outsqlda->sqlvar[index].sqlscale=0; outsqlda->sqlvar[index].sqlsubtype=0; outsqlda->sqlvar[index].sqllen=valuesize; outsqlda->sqlvar[index].sqldata=value; outsqlda->sqlvar[index].sqlind=isnull; outsqlda->sqlvar[index].sqlname_length=0; outsqlda->sqlvar[index].sqlname[0]=(char)NULL; outsqlda->sqlvar[index].relname_length=0; outsqlda->sqlvar[index].relname[0]=(char)NULL; outsqlda->sqlvar[index].ownname_length=0; outsqlda->sqlvar[index].ownname[0]=(char)NULL; outsqlda->sqlvar[index].aliasname_length=0; outsqlda->sqlvar[index].aliasname[0]=(char)NULL; return true;}bool firebirdcursor::outputBindInteger(const char *variable, uint16_t variablesize, int64_t *value, int16_t *isnull) { outbindisstring[outbindcount]=false; outbindcount++; // if we're doing output binds then the // query must be a stored procedure queryIsExecSP=true; // make bind vars 1 based like all other db's long index=charstring::toInteger(variable+1)-1; if (index<0) { return false; } outsqlda->sqlvar[index].sqltype=SQL_INT64; outsqlda->sqlvar[index].sqlscale=0; outsqlda->sqlvar[index].sqlsubtype=0; outsqlda->sqlvar[index].sqllen=sizeof(int64_t); outsqlda->sqlvar[index].sqldata=(char *)value; outsqlda->sqlvar[index].sqlind=isnull; outsqlda->sqlvar[index].sqlname_length=0; outsqlda->sqlvar[index].sqlname[0]=(char)NULL; outsqlda->sqlvar[index].relname_length=0; outsqlda->sqlvar[index].relname[0]=(char)NULL; outsqlda->sqlvar[index].ownname_length=0; outsqlda->sqlvar[index].ownname[0]=(char)NULL; outsqlda->sqlvar[index].aliasname_length=0; outsqlda->sqlvar[index].aliasname[0]=(char)NULL; return true;}bool firebirdcursor::outputBindDouble(const char *variable, uint16_t variablesize, double *value, uint32_t *precision, uint32_t *scale, int16_t *isnull) { outbindisstring[outbindcount]=false; outbindcount++; // if we're doing output binds then the // query must be a stored procedure queryIsExecSP=true; // make bind vars 1 based like all other db's long index=charstring::toInteger(variable+1)-1; if (index<0) { return false; } outsqlda->sqlvar[index].sqltype=SQL_DOUBLE; outsqlda->sqlvar[index].sqlscale=*scale; outsqlda->sqlvar[index].sqlsubtype=0; outsqlda->sqlvar[index].sqllen=sizeof(double); outsqlda->sqlvar[index].sqldata=(char *)value; outsqlda->sqlvar[index].sqlind=isnull; outsqlda->sqlvar[index].sqlname_length=0; outsqlda->sqlvar[index].sqlname[0]=(char)NULL; outsqlda->sqlvar[index].relname_length=0; outsqlda->sqlvar[index].relname[0]=(char)NULL; outsqlda->sqlvar[index].ownname_length=0; outsqlda->sqlvar[index].ownname[0]=(char)NULL; outsqlda->sqlvar[index].aliasname_length=0; outsqlda->sqlvar[index].aliasname[0]=(char)NULL; return true;}bool firebirdcursor::executeQuery(const char *query, uint32_t length, bool execute) { // for commit or rollback, execute the API call and return if (querytype==isc_info_sql_stmt_commit) { return !isc_commit_retaining(firebirdconn->error, &firebirdconn->tr); } else if (querytype==isc_info_sql_stmt_rollback) { return !isc_rollback_retaining(firebirdconn->error, &firebirdconn->tr); } else if (queryIsExecSP) { // if the query is a stored procedure then execute it as such bool retval=!isc_dsql_execute2(firebirdconn->error, &firebirdconn->tr, &stmt,1,insqlda,outsqlda);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -