Beispiel #1
0
void
IB_Statement::describeInput (const IB_SSHORT16 suggestedInputCols)
{
  // If sqldaIn_ is already allocated, reuse it.
  // Otherwise, allocate space for a suggestedInputCols parameter list.
  // If more space is needed, allocate more later.
  if (!sqldaIn_)
    sqldaIn_ = (XSQLDA *) malloc (XSQLDA_LENGTH (suggestedInputCols));
  if (!sqldaIn_)
    throw new IB_SQLException (IB_SQLException::outOfMemory__,
			       IB_SQLException::outOfMemoryException__);
  sqldaIn_->sqln = suggestedInputCols;
  sqldaIn_->version = sqldaVersion__;
    
  dsqlDescribeBind ();

  IB_SSHORT16 actualInputCols = sqldaIn_->sqld;
  if (actualInputCols > sqldaIn_->sqln) {
    sqldaIn_ = (XSQLDA *) realloc (sqldaIn_, 
				   XSQLDA_LENGTH (actualInputCols));
    sqldaIn_->version = sqldaVersion__;
    sqldaIn_->sqln = actualInputCols;
    dsqlDescribeBind ();
  }

  // Its harmless to delete a NULL pointer.
  // !!! future enhancement - make this a realloc
  delete inputBuffer_;
  inputBuffer_ = new IB_InputBuffer (this);
  
  // !!! do we really need to call clearParameters() here?
  clearParameters ();
}
Beispiel #2
0
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 fb_init_socket(rlm_sql_firebird_conn_t *conn)
{
	memset(conn, 0, sizeof(*conn));
	conn->sqlda_out = (XSQLDA ISC_FAR *) calloc(XSQLDA_LENGTH (5), 1);
	conn->sqlda_out->sqln = 5;
	conn->sqlda_out->version =  SQLDA_VERSION1;
	conn->sql_dialect = 3;

	pthread_mutex_init (&conn->mut, NULL);
	DEBUG("Init mutex %p\n", &conn->mut);

	/*
	 *	Set tpb to read_committed/wait/no_rec_version
	 */
	fb_set_tpb(conn, 5, isc_tpb_version3, isc_tpb_wait, isc_tpb_write,
		   isc_tpb_read_committed, isc_tpb_no_rec_version);
	if (!conn->tpb) {
		return -1;
	}

	return 0;
}
Beispiel #4
0
bool
FirebirdStmt::setCommand(const QString& cmd)
{
    clear();
    _command = cmd;
    ISC_STATUS status[20];
    _conn->startTransaction();

    _procs->isc_dsql_allocate_statement(status, &_conn->_db, &_stmt);
    if (status[0] == 1 && status[1]) {
	qWarning("Error in: " + cmd);
	_procs->isc_print_status(status);
	return error("isc_dsql_allocate_statement failed");
    }

    char* cmdString = strdup(_command);
    _procs->isc_dsql_prepare(status, &_conn->_tr, &_stmt, 0, cmdString,
			     SQL_DIALECT_V6, _outputDA);
    free(cmdString);
    if (status[0] == 1 && status[1]) {
	qWarning("Error in: " + cmd);
	_procs->isc_print_status(status);
	return error("isc_dsql_prepare failed");
    }

    int count = _outputDA->sqld;
    if (count > _outputDA->sqln) {
	_outputDA = (XSQLDA*)malloc(XSQLDA_LENGTH(count));
	_outputDA->version = SQLDA_VERSION1;
	_outputDA->sqln = count;

	_procs->isc_dsql_describe(status, &_stmt, SQL_DIALECT_V6, _outputDA);
	if (status[0] == 1 && status[1]) {
	    qWarning("Error in: " + cmd);
	    _procs->isc_print_status(status);
	    return error("isc_dsql_describe failed");
	}
    }

    _procs->isc_dsql_describe_bind(status, &_stmt, SQL_DIALECT_V6, _inputDA);
    if (status[0] == 1 && status[1]) {
	qWarning("Error in: " + cmd);
	_procs->isc_print_status(status);
	return error("isc_dsql_describe_bind failed");
    }

    count = _inputDA->sqld;
    if (count > _inputDA->sqln) {
	_inputDA = (XSQLDA*)malloc(XSQLDA_LENGTH(count));
	_inputDA->version = SQLDA_VERSION1;
	_inputDA->sqln = count;

	_procs->isc_dsql_describe_bind(status, &_stmt,SQL_DIALECT_V6,_inputDA);
	if (status[0] == 1 && status[1]) {
	    qWarning("Error in: " + cmd);
	    _procs->isc_print_status(status);
	    return error("isc_dsql_describe_bind failed");
	}
    }

    // Create the params
    for (int pnum = 0; pnum < _inputDA->sqld; ++pnum) {
	FirebirdParam* param = new FirebirdParam(this, pnum);
	_params.push_back(param);
    }

    // Create the columns
    for (int cnum = 0; cnum < _outputDA->sqld; ++cnum) {
	FirebirdColumn* column = new FirebirdColumn(this, cnum);
	_columns.push_back(column);
    }

    _nextParam = 0;
    return true;
}
Beispiel #5
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;
    }
Beispiel #6
0
/*
** 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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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_;
}
Beispiel #9
0
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 */
    }
}
Beispiel #10
0
int main (int argc, char** argv)
{
    char            dept_no[4];
    double          percent_inc;
    short           flag0 = 0, flag1 = 0;
    XSQLDA         *sqlda;
    long            sqlcode;
    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 an input SQLDA.  There are two unknown parameters. */
    sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(2));
    sqlda->sqln = 2;
    sqlda->sqld = 2;
    sqlda->version = 1;

    sqlda->sqlvar[0].sqldata = (char *) &percent_inc;
    sqlda->sqlvar[0].sqltype = SQL_DOUBLE + 1;
    sqlda->sqlvar[0].sqllen  = sizeof(percent_inc);
    sqlda->sqlvar[0].sqlind  = &flag0;
    flag0 = 0;

    sqlda->sqlvar[1].sqldata = dept_no;
    sqlda->sqlvar[1].sqltype = SQL_TEXT + 1;
    sqlda->sqlvar[1].sqllen  = 3;
    sqlda->sqlvar[1].sqlind  = &flag1;
    flag1 = 0;               

    /*
     *  Get the next department-percent increase input pair.
     */
    while (get_input(dept_no, &percent_inc))
    {
        printf("\nIncreasing budget for department:  %s  by %5.2lf percent.\n",
               dept_no, percent_inc);

        if (isc_start_transaction(status, &trans, 1, &DB, 0, NULL))
        {
            ERREXIT(status, 1)
        }

        /* Update the budget. */
        isc_dsql_execute_immediate(status, &DB, &trans, 0, updstr, 1, sqlda);
        sqlcode = isc_sqlcode(status);
        if (sqlcode)
        {
            /* Don't save the update, if the new budget exceeds the limit. */
            if (sqlcode == -625)
            {
                printf("\tExceeded budget limit -- not updated.\n");

                if (isc_rollback_transaction(status, &trans))
                {
                    ERREXIT(status, 1)
                }
                continue;
            }
            /* Undo all changes, in case of an error. */
            else
            {
                isc_print_status(status);
                printf("SQLCODE=%d\n", sqlcode);

                isc_rollback_transaction(status, &trans);
                ERREXIT(status, 1)
            }
        }
DatabaseResultSet* FirebirdDatabaseLayer::RunQueryWithResults(const wxString& strQuery)
{
  ResetErrorCodes();
  if (m_pDatabase != NULL)
  {
    wxCharBuffer sqlDebugBuffer = ConvertToUnicodeStream(strQuery);
    //wxLogDebug(_("Running query: \"%s\""), (const char*)sqlDebugBuffer);
    
    wxArrayString QueryArray = ParseQueries(strQuery);

    if (QueryArray.size() > 0)
    {
      bool bQuickieTransaction = false;
    
      if (m_pTransaction == NULL)
      {
        // If there's no transaction is progress, run this as a quick one-timer transaction
        bQuickieTransaction = true;
      }

      if (QueryArray.size() > 1)
      {
        if (bQuickieTransaction)
        {
          BeginTransaction();
          if (GetErrorCode() != DATABASE_LAYER_OK)
          {
            wxLogError(_("Unable to start transaction"));
            ThrowDatabaseException();
            return NULL;
          }
        }
      
        // Assume that only the last statement in the array returns the result set
        for (unsigned int i=0; i<QueryArray.size()-1; i++)
        {
          RunQuery(QueryArray[i], false);
          if (GetErrorCode() != DATABASE_LAYER_OK)
          {
            ThrowDatabaseException();
            return NULL;
          }
        }
      
        // Now commit all the previous queries before calling the query that returns a result set
        if (bQuickieTransaction)
        {
          Commit();
          if (GetErrorCode() != DATABASE_LAYER_OK)
          {
            ThrowDatabaseException();
            return NULL;
          }
        }
      } // End check if there are more than one query in the array
      
      isc_tr_handle pQueryTransaction = NULL;
      bool bManageTransaction = false;
      if (bQuickieTransaction)
      {
        bManageTransaction = true;
        isc_db_handle pDatabase = (isc_db_handle)m_pDatabase;
        int nReturn = m_pInterface->GetIscStartTransaction()(*(ISC_STATUS_ARRAY*)m_pStatus, &pQueryTransaction, 1, &pDatabase, 0 /*tpb_length*/, NULL/*tpb*/);
        m_pDatabase = pDatabase;
        if (nReturn != 0)
        {
          InterpretErrorCodes();
          ThrowDatabaseException();
        }
      }
      else
      {
        pQueryTransaction = m_pTransaction;
      }
      
      isc_stmt_handle pStatement = NULL;
      isc_db_handle pDatabase = (isc_db_handle)m_pDatabase;
      int nReturn = m_pInterface->GetIscDsqlAllocateStatement()(*(ISC_STATUS_ARRAY*)m_pStatus, &pDatabase, &pStatement);
      m_pDatabase = pDatabase;
      if (nReturn != 0)
      {
        InterpretErrorCodes();

        // Manually try to rollback the transaction rather than calling the member RollBack function
        //  so that we can ignore the error messages
        m_pInterface->GetIscRollbackTransaction()(*(ISC_STATUS_ARRAY*)m_pStatus, &pQueryTransaction);

        ThrowDatabaseException();
        return NULL;
      }
      
      wxCharBuffer sqlBuffer = ConvertToUnicodeStream(QueryArray[QueryArray.size()-1]);
      nReturn = m_pInterface->GetIscDsqlPrepare()(*(ISC_STATUS_ARRAY*)m_pStatus, &pQueryTransaction, &pStatement, 0, (char*)(const char*)sqlBuffer, SQL_DIALECT_CURRENT, NULL);
      if (nReturn != 0)
      {
        InterpretErrorCodes();

        // Manually try to rollback the transaction rather than calling the member RollBack function
        //  so that we can ignore the error messages
        m_pInterface->GetIscRollbackTransaction()(*(ISC_STATUS_ARRAY*)m_pStatus, &pQueryTransaction);

        ThrowDatabaseException();
        return NULL;
      }

//--------------------------------------------------------------

      XSQLDA* pOutputSqlda = (XSQLDA*)malloc(XSQLDA_LENGTH(1));
      pOutputSqlda->sqln = 1;
      pOutputSqlda->version = SQLDA_VERSION1;

      // Make sure that we have enough space allocated for the result set
      nReturn = m_pInterface->GetIscDsqlDescribe()(*(ISC_STATUS_ARRAY*)m_pStatus, &pStatement, SQL_DIALECT_CURRENT, pOutputSqlda);
      if (nReturn != 0)
      {
        free(pOutputSqlda);
        InterpretErrorCodes();

        // Manually try to rollback the transaction rather than calling the member RollBack function
        //  so that we can ignore the error messages
        m_pInterface->GetIscRollbackTransaction()(*(ISC_STATUS_ARRAY*)m_pStatus, &pQueryTransaction);

        ThrowDatabaseException();
        return NULL;
      }

      if (pOutputSqlda->sqld > pOutputSqlda->sqln)
      {
        int nColumns = pOutputSqlda->sqld;
        free(pOutputSqlda);
        pOutputSqlda = (XSQLDA*)malloc(XSQLDA_LENGTH(nColumns));
        pOutputSqlda->sqln = nColumns;
        pOutputSqlda->version = SQLDA_VERSION1;
        nReturn = m_pInterface->GetIscDsqlDescribe()(*(ISC_STATUS_ARRAY*)m_pStatus, &pStatement, SQL_DIALECT_CURRENT, pOutputSqlda);
        if (nReturn != 0)
        {
          free(pOutputSqlda);
          InterpretErrorCodes();

          // Manually try to rollback the transaction rather than calling the member RollBack function
          //  so that we can ignore the error messages
          m_pInterface->GetIscRollbackTransaction()(*(ISC_STATUS_ARRAY*)m_pStatus, &pQueryTransaction);

          ThrowDatabaseException();
          return NULL;
        }
      }

      // Create the result set object
      FirebirdResultSet* pResultSet = new FirebirdResultSet(m_pInterface, m_pDatabase, pQueryTransaction, pStatement, pOutputSqlda, true, bManageTransaction);
      pResultSet->SetEncoding(GetEncoding());
      if (pResultSet->GetErrorCode() != DATABASE_LAYER_OK)
      {
        SetErrorCode(pResultSet->GetErrorCode());
        SetErrorMessage(pResultSet->GetErrorMessage());
    
        // Manually try to rollback the transaction rather than calling the member RollBack function
        //  so that we can ignore the error messages
        m_pInterface->GetIscRollbackTransaction()(*(ISC_STATUS_ARRAY*)m_pStatus, &pQueryTransaction);

        // Wrap the result set deletion in try/catch block if using exceptions.
        //We want to make sure the original error gets to the user
#ifndef DONT_USE_DATABASE_LAYER_EXCEPTIONS
        try
        {
#endif
        delete pResultSet;
#ifndef DONT_USE_DATABASE_LAYER_EXCEPTIONS
        }
        catch (DatabaseLayerException& e)
        {
        }
#endif

        ThrowDatabaseException();
      }
  
      // Now execute the SQL
      nReturn = m_pInterface->GetIscDsqlExecute()(*(ISC_STATUS_ARRAY*)m_pStatus, &pQueryTransaction, &pStatement, SQL_DIALECT_CURRENT, NULL);
      if (nReturn != 0)
      {
        InterpretErrorCodes();

        // Manually try to rollback the transaction rather than calling the member RollBack function
        //  so that we can ignore the error messages
        m_pInterface->GetIscRollbackTransaction()(*(ISC_STATUS_ARRAY*)m_pStatus, &pQueryTransaction);

        // Wrap the result set deletion in try/catch block if using exceptions.
        //  We want to make sure the isc_dsql_execute error gets to the user
#ifndef DONT_USE_DATABASE_LAYER_EXCEPTIONS
        try
        {
#endif
        delete pResultSet;
#ifndef DONT_USE_DATABASE_LAYER_EXCEPTIONS
        }
        catch (DatabaseLayerException& e)
        {
        }
#endif
    
        ThrowDatabaseException();
        return NULL;
      }
      
//--------------------------------------------------------------

      LogResultSetForCleanup(pResultSet);
      return pResultSet;
    }
    else
      return NULL;
  }
  else
  {
    wxLogError(_("Database handle is NULL"));
    return NULL;
  }
}