static int fb_prepare(rlm_sql_firebird_conn_t *conn, char const *query) { static char stmt_info[] = { isc_info_sql_stmt_type }; char info_buffer[128]; short l; if (!conn->trh) { isc_start_transaction(conn->status, &conn->trh, 1, &conn->dbh, conn->tpb_len, conn->tpb); if (!conn->trh) { return -4; } } fb_free_statement(conn); if (!conn->stmt) { isc_dsql_allocate_statement(conn->status, &conn->dbh, &conn->stmt); if (!conn->stmt) { return -1; } } fb_free_sqlda(conn->sqlda_out); isc_dsql_prepare(conn->status, &conn->trh, &conn->stmt, 0, query, conn->sql_dialect, conn->sqlda_out); if (IS_ISC_ERROR(conn->status)) { return -2; } if (conn->sqlda_out->sqln<conn->sqlda_out->sqld) { conn->sqlda_out->sqln = conn->sqlda_out->sqld; conn->sqlda_out = (XSQLDA ISC_FAR *) realloc(conn->sqlda_out, XSQLDA_LENGTH(conn->sqlda_out->sqld)); isc_dsql_describe(conn->status, &conn->stmt, SQL_DIALECT_V6, conn->sqlda_out); if (IS_ISC_ERROR(conn->status)) { return -3; } } /* * Get statement type */ isc_dsql_sql_info(conn->status, &conn->stmt, sizeof(stmt_info), stmt_info, sizeof(info_buffer), info_buffer); if (IS_ISC_ERROR(conn->status)) return -4; l = (short) isc_vax_integer((char ISC_FAR *) info_buffer + 1, 2); conn->statement_type = isc_vax_integer((char ISC_FAR *) info_buffer + 3, l); if (conn->sqlda_out->sqld) { fb_set_sqlda(conn->sqlda_out); //set out sqlda } return 0; }
int main (int argc, char** argv) { int num_cols, i; isc_stmt_handle stmt = NULL; XSQLDA *sqlda; char empdb[128]; if (argc > 1) strcpy(empdb, argv[1]); else strcpy(empdb, "employee.fdb"); if (isc_attach_database(status, 0, empdb, &DB, 0, NULL)) { ERREXIT(status, 1) } /* Allocate SQLDA of an arbitrary size. */ sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(3)); sqlda->sqln = 3; sqlda->version = 1; if (isc_start_transaction(status, &trans, 1, &DB, 0, NULL)) { ERREXIT(status, 1) } /* Allocate a statement. */ if (isc_dsql_allocate_statement(status, &DB, &stmt)) { ERREXIT(status, 1) } /* Prepare the statement. */ if (isc_dsql_prepare(status, &trans, &stmt, 0, sel_str, 1, sqlda)) { ERREXIT(status, 1) } /* Describe the statement. */ if (isc_dsql_describe(status, &stmt, 1, sqlda)) { ERREXIT(status, 1) } /* This is a select statement, print more information about it. */ printf("Query Type: SELECT\n\n"); num_cols = sqlda->sqld; printf("Number of columns selected: %d\n", num_cols); /* Reallocate SQLDA if necessary. */ if (sqlda->sqln < sqlda->sqld) { sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(num_cols)); sqlda->sqln = num_cols; sqlda->version = 1; /* Re-describe the statement. */ if (isc_dsql_describe(status, &stmt, 1, sqlda)) { ERREXIT(status, 1) } num_cols = sqlda->sqld; }
/* ** Executes a SQL statement. ** Returns ** cursor object: if there are results or ** row count: number of rows affected by statement if no results */ static int conn_execute (lua_State *L) { conn_data *conn = getconnection(L,1); const char *statement = luaL_checkstring(L, 2); int dialect = (int)luaL_optnumber(L, 3, 3); XSQLVAR *var; long dtype; int i, n, count, stmt_type; cur_data cur; cur.closed = 0; cur.env = conn->env; cur.conn = conn; cur.stmt = NULL; cur.out_sqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(CURSOR_PREALLOC)); cur.out_sqlda->version = SQLDA_VERSION1; cur.out_sqlda->sqln = CURSOR_PREALLOC; /* create a statement to handle the query */ isc_dsql_allocate_statement(conn->env->status_vector, &conn->db, &cur.stmt); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free(cur.out_sqlda); return return_db_error(L, conn->env->status_vector); } /* process the SQL ready to run the query */ isc_dsql_prepare(conn->env->status_vector, &conn->transaction, &cur.stmt, 0, (char*)statement, dialect, cur.out_sqlda); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free(cur.out_sqlda); return return_db_error(L, conn->env->status_vector); } /* what type of SQL statement is it? */ stmt_type = get_statement_type(&cur); if(stmt_type < 0) { free(cur.out_sqlda); return return_db_error(L, conn->env->status_vector); } /* an unsupported SQL statement (something like COMMIT) */ if(stmt_type > 5) { free(cur.out_sqlda); return luasql_faildirect(L, "unsupported SQL statement"); } /* resize the result set if needed */ if (cur.out_sqlda->sqld > cur.out_sqlda->sqln) { n = cur.out_sqlda->sqld; free(cur.out_sqlda); cur.out_sqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(n)); cur.out_sqlda->sqln = n; cur.out_sqlda->version = SQLDA_VERSION1; isc_dsql_describe(conn->env->status_vector, &cur.stmt, 1, cur.out_sqlda); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free(cur.out_sqlda); return return_db_error(L, conn->env->status_vector); } } /* prep the result set ready to handle the data */ for (i=0, var = cur.out_sqlda->sqlvar; i < cur.out_sqlda->sqld; i++, var++) { dtype = (var->sqltype & ~1); /* drop flag bit for now */ switch(dtype) { case SQL_VARYING: var->sqldata = (char *)malloc(sizeof(char)*var->sqllen + 2); break; case SQL_TEXT: var->sqldata = (char *)malloc(sizeof(char)*var->sqllen); break; case SQL_SHORT: var->sqldata = (char *)malloc(sizeof(short)); break; case SQL_LONG: var->sqldata = (char *)malloc(sizeof(long)); break; case SQL_INT64: var->sqldata = (char *)malloc(sizeof(ISC_INT64)); break; case SQL_FLOAT: var->sqldata = (char *)malloc(sizeof(float)); break; case SQL_DOUBLE: var->sqldata = (char *)malloc(sizeof(double)); break; case SQL_TYPE_TIME: var->sqldata = (char *)malloc(sizeof(ISC_TIME)); break; case SQL_TYPE_DATE: var->sqldata = (char *)malloc(sizeof(ISC_DATE)); break; case SQL_TIMESTAMP: var->sqldata = (char *)malloc(sizeof(ISC_TIMESTAMP)); break; case SQL_BLOB: var->sqldata = (char *)malloc(sizeof(ISC_QUAD)); break; /* TODO : add extra data type handles here */ } if (var->sqltype & 1) { /* allocate variable to hold NULL status */ var->sqlind = (short *)malloc(sizeof(short)); } else { var->sqlind = NULL; } } /* run the query */ isc_dsql_execute(conn->env->status_vector, &conn->transaction, &cur.stmt, 1, NULL); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free_cur(&cur); return return_db_error(L, conn->env->status_vector); } /* if autocommit is set and it's a non SELECT query, commit change */ if(conn->autocommit != 0 && stmt_type > 1) { isc_commit_retaining(conn->env->status_vector, &conn->transaction); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free_cur(&cur); return return_db_error(L, conn->env->status_vector); } } /* what do we return? a cursor or a count */ if(cur.out_sqlda->sqld > 0) { /* a cursor */ cur_data* user_cur; /* open the cursor ready for fetch cycles */ isc_dsql_set_cursor_name(cur.env->status_vector, &cur.stmt, "dyn_cursor", (unsigned short)NULL); if ( CHECK_DB_ERROR(conn->env->status_vector) ) { free_cur(&cur); return return_db_error(L, conn->env->status_vector); } /* copy the cursor into a new lua userdata object */ user_cur = (cur_data*)lua_newuserdata(L, sizeof(cur_data)); luasql_setmeta (L, LUASQL_CURSOR_FIREBIRD); memcpy((void*)user_cur, (void*)&cur, sizeof(cur_data)); /* add cursor to the lock count */ lua_registerobj(L, 1, conn); ++conn->lock; } else { /* a count */ if( (count = count_rows_affected(&cur)) < 0 ) { free(cur.out_sqlda); return return_db_error(L, conn->env->status_vector); } lua_pushnumber(L, count); /* totaly finnished with the cursor */ isc_dsql_free_statement(conn->env->status_vector, &cur.stmt, DSQL_drop); free(cur.out_sqlda); } return 1; }
int query( char * sel_str ) { ISC_STATUS status[ 20 ]; XSQLVAR * var; int n, i, dtype; if( isc_start_transaction( status, &trans, 1, &db, 0, NULL ) ) ERREXIT( status, 1 ); /* Allocate an output SQLDA. Just to check number of columns */ sqlda = ( XSQLDA * ) malloc( XSQLDA_LENGTH( 1 ) ); sqlda->sqln = 1; sqlda->version = 1; /* Allocate a statement */ if( isc_dsql_allocate_statement( status, &db, &stmt ) ) ERREXIT( status, 1 ); /* Prepare the statement. */ if( isc_dsql_prepare( status, &trans, &stmt, 0, sel_str, dialect, sqlda ) ) ERREXIT( status, 1 ); /* Describe sql contents */ if( isc_dsql_describe( status, &stmt, dialect, sqlda ) ) ERREXIT( status, 1 ); /* Relocate necessary number of columns */ if( sqlda->sqld > sqlda->sqln ) { free( sqlda ); n = sqlda->sqld; sqlda = ( XSQLDA * ) malloc( XSQLDA_LENGTH( n ) ); sqlda->sqln = n; sqlda->version = 1; if( isc_dsql_describe( status, &stmt, dialect, sqlda ) ) ERREXIT( status, 1 ); } for( i = 0, var = sqlda->sqlvar; i < sqlda->sqld; i++, var++ ) { dtype = ( var->sqltype & ~1 ); switch( dtype ) { case SQL_VARYING: var->sqltype = SQL_TEXT; var->sqldata = ( char * ) malloc( sizeof( char ) * var->sqllen + 2 ); break; case SQL_TEXT: var->sqldata = ( char * ) malloc( sizeof( char ) * var->sqllen + 2 ); break; case SQL_LONG: var->sqltype = SQL_LONG; var->sqldata = ( char * ) malloc( sizeof( long ) ); break; default: var->sqldata = ( char * ) malloc( sizeof( char ) * var->sqllen ); break; } if( var->sqltype & 1 ) { var->sqlind = ( short * ) malloc( sizeof( short ) ); } } if( ! sqlda->sqld ) { /* Execute and commit non-select querys */ if( isc_dsql_execute( status, &trans, &stmt, dialect, NULL ) ) ERREXIT( status, 1 ); if( isc_commit_transaction( status, &trans ) ) ERREXIT( status, 1 ); trans = NULL; } else { if( isc_dsql_execute( status, &trans, &stmt, dialect, sqlda ) ) ERREXIT( status, 1 ); } return 1; }
IB_ResultSet* IB_Statement::prepareNoInput (const IB_STRING sqlString, const IB_SSHORT16 suggestedResultCols, const IB_SSHORT16 maxFieldSize) { //david jencks 2-4-2001 sqlLog(sqlString); // logg all sql statements if (!stmtHandle_) open (); // If sqldaOut_ is already allocated, reuse it. // Otherwise, allocate space for a suggestedResultCols item select list. // If more space is needed, allocate more later. if (!sqldaOut_) sqldaOut_ = (XSQLDA *) malloc (XSQLDA_LENGTH(suggestedResultCols)); if (!sqldaOut_) throw new IB_SQLException (IB_SQLException::outOfMemory__, IB_SQLException::outOfMemoryException__); sqldaOut_->version = sqldaVersion__; sqldaOut_->sqln = suggestedResultCols; if (isc_dsql_prepare (status_->vector(), transaction_->trHandleP(), &stmtHandle_, 0, sqlString, // CJL-IB6 add SQLDialect support, and obsolete sqldaVersion connection_->attachmentSQLDialect_, // sqldaVersion__, // CJL-IB6 end sqldaOut_)) throw new IB_SQLException (IB_SQLException::engine__default_0__, status_); prepared_ = IB_TRUE; IB_SSHORT16 actualResultCols = sqldaOut_->sqld; stmtType_ = statementType (); // If its a non-select, just return. if (!actualResultCols) { return NULL; } // Check that actual number of result cols is not greater than allocated suggestedInputCols. // Realloc if necessary. if (sqldaOut_->sqln < actualResultCols) { sqldaOut_ = (XSQLDA *) realloc (sqldaOut_, XSQLDA_LENGTH (actualResultCols)); sqldaOut_->version = sqldaVersion__; sqldaOut_->sqln = actualResultCols; } // !!! MOVE THIS UP INSIDE IF STATEMENT // Describe the output sqlvars if (isc_dsql_describe (status_->vector(), &stmtHandle_, // CJL-IB6 add SQLDialect support, and obsolete sqldaVersion connection_->attachmentSQLDialect_, // sqldaVersion__, // CJL-IB6 end sqldaOut_)) throw new IB_SQLException (IB_SQLException::engine__default_0__, status_); // Its harmless to delete a NULL pointer. delete resultSet_; // Must always realloc since record size may change. // !!! future enhancement - make this a realloc resultSet_ = new IB_ResultSet (this, maxFieldSize); return resultSet_; }
static int perform_ibase_search(uschar * query, uschar * server, uschar ** resultptr, uschar ** errmsg, BOOL * defer_break) { isc_stmt_handle stmth = NULL; XSQLDA *out_sqlda; XSQLVAR *var; char buffer[256]; ISC_STATUS status[20], *statusp = status; int i; int ssize = 0; int offset = 0; int yield = DEFER; uschar *result = NULL; ibase_connection *cn; uschar *server_copy = NULL; uschar *sdata[3]; /* Disaggregate the parameters from the server argument. The order is host, database, user, password. We can write to the string, since it is in a nextinlist temporary buffer. The copy of the string that is used for caching has the password removed. This copy is also used for debugging output. */ for (i = 2; i > 0; i--) { uschar *pp = Ustrrchr(server, '|'); if (pp == NULL) { *errmsg = string_sprintf("incomplete Interbase server data: %s", (i == 3) ? server : server_copy); *defer_break = TRUE; return DEFER; } *pp++ = 0; sdata[i] = pp; if (i == 2) server_copy = string_copy(server); /* sans password */ } sdata[0] = server; /* What's left at the start */ /* See if we have a cached connection to the server */ for (cn = ibase_connections; cn != NULL; cn = cn->next) { if (Ustrcmp(cn->server, server_copy) == 0) { break; } } /* Use a previously cached connection ? */ if (cn != NULL) { static char db_info_options[] = { isc_info_base_level }; /* test if the connection is alive */ if (isc_database_info (status, &cn->dbh, sizeof(db_info_options), db_info_options, sizeof(buffer), buffer)) { /* error occurred: assume connection is down */ DEBUG(D_lookup) debug_printf ("Interbase cleaning up cached connection: %s\n", cn->server); isc_detach_database(status, &cn->dbh); } else { DEBUG(D_lookup) debug_printf("Interbase using cached connection for %s\n", server_copy); } } else { cn = store_get(sizeof(ibase_connection)); cn->server = server_copy; cn->dbh = NULL; cn->transh = NULL; cn->next = ibase_connections; ibase_connections = cn; } /* If no cached connection, we must set one up. */ if (cn->dbh == NULL || cn->transh == NULL) { char *dpb, *p; short dpb_length; static char trans_options[] = { isc_tpb_version3, isc_tpb_read, isc_tpb_read_committed, isc_tpb_rec_version }; /* Construct the database parameter buffer. */ dpb = buffer; *dpb++ = isc_dpb_version1; *dpb++ = isc_dpb_user_name; *dpb++ = strlen(sdata[1]); for (p = sdata[1]; *p;) *dpb++ = *p++; *dpb++ = isc_dpb_password; *dpb++ = strlen(sdata[2]); for (p = sdata[2]; *p;) *dpb++ = *p++; dpb_length = dpb - buffer; DEBUG(D_lookup) debug_printf("new Interbase connection: database=%s user=%s\n", sdata[0], sdata[1]); /* Connect to the database */ if (isc_attach_database (status, 0, sdata[0], &cn->dbh, dpb_length, buffer)) { isc_interprete(buffer, &statusp); *errmsg = string_sprintf("Interbase attach() failed: %s", buffer); *defer_break = FALSE; goto IBASE_EXIT; } /* Now start a read-only read-committed transaction */ if (isc_start_transaction (status, &cn->transh, 1, &cn->dbh, sizeof(trans_options), trans_options)) { isc_interprete(buffer, &statusp); isc_detach_database(status, &cn->dbh); *errmsg = string_sprintf("Interbase start_transaction() failed: %s", buffer); *defer_break = FALSE; goto IBASE_EXIT; } } /* Run the query */ if (isc_dsql_allocate_statement(status, &cn->dbh, &stmth)) { isc_interprete(buffer, &statusp); *errmsg = string_sprintf("Interbase alloc_statement() failed: %s", buffer); *defer_break = FALSE; goto IBASE_EXIT; } out_sqlda = store_get(XSQLDA_LENGTH(1)); out_sqlda->version = SQLDA_VERSION1; out_sqlda->sqln = 1; if (isc_dsql_prepare (status, &cn->transh, &stmth, 0, query, 1, out_sqlda)) { isc_interprete(buffer, &statusp); store_reset(out_sqlda); out_sqlda = NULL; *errmsg = string_sprintf("Interbase prepare_statement() failed: %s", buffer); *defer_break = FALSE; goto IBASE_EXIT; } /* re-allocate the output structure if there's more than one field */ if (out_sqlda->sqln < out_sqlda->sqld) { XSQLDA *new_sqlda = store_get(XSQLDA_LENGTH(out_sqlda->sqld)); if (isc_dsql_describe (status, &stmth, out_sqlda->version, new_sqlda)) { isc_interprete(buffer, &statusp); isc_dsql_free_statement(status, &stmth, DSQL_drop); store_reset(out_sqlda); out_sqlda = NULL; *errmsg = string_sprintf("Interbase describe_statement() failed: %s", buffer); *defer_break = FALSE; goto IBASE_EXIT; } out_sqlda = new_sqlda; } /* allocate storage for every returned field */ for (i = 0, var = out_sqlda->sqlvar; i < out_sqlda->sqld; i++, var++) { switch (var->sqltype & ~1) { case SQL_VARYING: var->sqldata = (char *) store_get(sizeof(char) * var->sqllen + 2); break; case SQL_TEXT: var->sqldata = (char *) store_get(sizeof(char) * var->sqllen); break; case SQL_SHORT: var->sqldata = (char *) store_get(sizeof(short)); break; case SQL_LONG: var->sqldata = (char *) store_get(sizeof(ISC_LONG)); break; #ifdef SQL_INT64 case SQL_INT64: var->sqldata = (char *) store_get(sizeof(ISC_INT64)); break; #endif case SQL_FLOAT: var->sqldata = (char *) store_get(sizeof(float)); break; case SQL_DOUBLE: var->sqldata = (char *) store_get(sizeof(double)); break; #ifdef SQL_TIMESTAMP case SQL_DATE: var->sqldata = (char *) store_get(sizeof(ISC_QUAD)); break; #else case SQL_TIMESTAMP: var->sqldata = (char *) store_get(sizeof(ISC_TIMESTAMP)); break; case SQL_TYPE_DATE: var->sqldata = (char *) store_get(sizeof(ISC_DATE)); break; case SQL_TYPE_TIME: var->sqldata = (char *) store_get(sizeof(ISC_TIME)); break; #endif } if (var->sqltype & 1) { var->sqlind = (short *) store_get(sizeof(short)); } } /* finally, we're ready to execute the statement */ if (isc_dsql_execute (status, &cn->transh, &stmth, out_sqlda->version, NULL)) { isc_interprete(buffer, &statusp); *errmsg = string_sprintf("Interbase describe_statement() failed: %s", buffer); isc_dsql_free_statement(status, &stmth, DSQL_drop); *defer_break = FALSE; goto IBASE_EXIT; } while (isc_dsql_fetch(status, &stmth, out_sqlda->version, out_sqlda) != 100L) { /* check if an error occurred */ if (status[0] & status[1]) { isc_interprete(buffer, &statusp); *errmsg = string_sprintf("Interbase fetch() failed: %s", buffer); isc_dsql_free_statement(status, &stmth, DSQL_drop); *defer_break = FALSE; goto IBASE_EXIT; } if (result != NULL) result = string_catn(result, &ssize, &offset, US "\n", 1); /* Find the number of fields returned. If this is one, we don't add field names to the data. Otherwise we do. */ if (out_sqlda->sqld == 1) { if (out_sqlda->sqlvar[0].sqlind == NULL || *out_sqlda->sqlvar[0].sqlind != -1) /* NULL value yields nothing */ result = string_catn(result, &ssize, &offset, US buffer, fetch_field(buffer, sizeof(buffer), &out_sqlda->sqlvar[0])); } else for (i = 0; i < out_sqlda->sqld; i++) { int len = fetch_field(buffer, sizeof(buffer), &out_sqlda->sqlvar[i]); result = string_cat(result, &ssize, &offset, US out_sqlda->sqlvar[i].aliasname, out_sqlda->sqlvar[i].aliasname_length); result = string_catn(result, &ssize, &offset, US "=", 1); /* Quote the value if it contains spaces or is empty */ if (*out_sqlda->sqlvar[i].sqlind == -1) { /* NULL value */ result = string_catn(result, &ssize, &offset, US "\"\"", 2); } else if (buffer[0] == 0 || Ustrchr(buffer, ' ') != NULL) { int j; result = string_catn(result, &ssize, &offset, US "\"", 1); for (j = 0; j < len; j++) { if (buffer[j] == '\"' || buffer[j] == '\\') result = string_cat(result, &ssize, &offset, US "\\", 1); result = string_cat(result, &ssize, &offset, US buffer + j, 1); } result = string_catn(result, &ssize, &offset, US "\"", 1); } else { result = string_catn(result, &ssize, &offset, US buffer, len); } result = string_catn(result, &ssize, &offset, US " ", 1); } } /* If result is NULL then no data has been found and so we return FAIL. Otherwise, we must terminate the string which has been built; string_cat() always leaves enough room for a terminating zero. */ if (result == NULL) { yield = FAIL; *errmsg = US "Interbase: no data found"; } else { result[offset] = 0; store_reset(result + offset + 1); } /* Get here by goto from various error checks. */ IBASE_EXIT: if (stmth != NULL) isc_dsql_free_statement(status, &stmth, DSQL_drop); /* Non-NULL result indicates a successful result */ if (result != NULL) { *resultptr = result; return OK; } else { DEBUG(D_lookup) debug_printf("%s\n", *errmsg); return yield; /* FAIL or DEFER */ } }