// Called by executeUpdate() and IB_ResultSet::open() void IB_Statement::dsqlExecute () { if (isc_dsql_execute (status_->vector(), transaction_->trHandleP(), &stmtHandle_, // CJL-IB6 add support for SQLDialect, obsolete sqldaVersion__ connection_->attachmentSQLDialect_, // sqldaVersion__, // CJL-IB6 end sqldaIn_)) throw new IB_SQLException (IB_SQLException::engine__default_0__, status_); }
int fb_sql_query(rlm_sql_firebird_conn_t *conn, char const *query) { if (fb_prepare(conn, query)) { return fb_error(conn); } switch (conn->statement_type) { case isc_info_sql_stmt_exec_procedure: isc_dsql_execute2(conn->status, &conn->trh, &conn->stmt, SQL_DIALECT_V6, 0, conn->sqlda_out); break; default: isc_dsql_execute(conn->status, &conn->trh, &conn->stmt, SQL_DIALECT_V6, 0); break; } return fb_error(conn); }
/* ** 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; }
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 */ } }