Ejemplo n.º 1
0
/*
** Closes a cursor object
** Lua Returns:
**   1 if close was sucsessful, 0 if already closed
**   nil and error message otherwise.
*/
static int cur_close (lua_State *L) {
    cur_data *cur = (cur_data *)luaL_checkudata(L,1,LUASQL_CURSOR_FIREBIRD);
    luaL_argcheck (L, cur != NULL, 1, "cursor expected");

    if(cur->closed == 0) {
        isc_dsql_free_statement(cur->env->status_vector, &cur->stmt, DSQL_drop);
        if ( CHECK_DB_ERROR(cur->env->status_vector) )
            return return_db_error(L, cur->env->status_vector);

        /* free the cursor data */
        free_cur(cur);

        /* remove cursor from lock count */
        cur->closed = 1;
        --cur->conn->lock;

        /* check if connection can be unregistered */
        if(cur->conn->lock == 0)
            lua_unregisterobj(L, cur->conn);

        /* return sucsess */
        lua_pushboolean(L, 1);
        return 1;
    }

    lua_pushboolean(L, 0);
    return 1;
}
Ejemplo n.º 2
0
// Called by close()
void
IB_Statement::dsqlDropStatement ()
{
  if (isc_dsql_free_statement (status_->vector(), 
			       &stmtHandle_, 
			       DSQL_drop))
    throw new IB_SQLException (IB_SQLException::engine__default_0__, status_);
}
Ejemplo n.º 3
0
EXPORT RM_ENTRY(rmc_dsql_free_statement)
{
	ClearParamPool();
	ISC_STATUS *stat = AllocStatusPool();
	isc_dsql_free_statement(stat,
							(isc_stmt_handle *)arg_vector[1].a_address,
							*CobolToShort(&arg_vector[2]));
	StatusToCobol(&arg_vector[0], stat);

	return (0);
}
Ejemplo n.º 4
0
int qclose( void )
{
   long status[ 20 ];

   if( isc_dsql_free_statement( status, &stmt, DSQL_drop ) )
      ERREXIT( status, 1 );

   if( trans )
      if( isc_commit_transaction( status, &trans ) )
         ERREXIT( status, 1 );

   if( sqlda )
      free( sqlda );

   return 1;
}
Ejemplo n.º 5
0
/*
** GCs a cursor object
*/
static int cur_gc (lua_State *L) {
    cur_data *cur = (cur_data *)luaL_checkudata(L,1,LUASQL_CURSOR_FIREBIRD);
    luaL_argcheck (L, cur != NULL, 1, "cursor expected");

    if(cur->closed == 0) {
        isc_dsql_free_statement(cur->env->status_vector, &cur->stmt, DSQL_drop);

        /* free the cursor data */
        free_cur(cur);

        /* remove cursor from lock count */
        cur->closed = 1;
        --cur->conn->lock;

        /* check if connection can be unregistered */
        if(cur->conn->lock == 0)
            lua_unregisterobj(L, cur->conn);
    }

    return 0;
}
Ejemplo n.º 6
0
void fb_free_statement(rlm_sql_firebird_conn_t *conn) {
	if (conn->stmt) {
		isc_dsql_free_statement(conn->status, &conn->stmt, DSQL_drop);
		conn->stmt = 0;
	}
}
Ejemplo n.º 7
0
int fb_close_cursor(rlm_sql_firebird_conn_t *conn) {
	isc_dsql_free_statement(conn->status, &conn->stmt, DSQL_close);

	return fb_error(conn);
}
Ejemplo n.º 8
0
/*
** Returns a row of data from the query
** Lua Returns:
**   list of results or table of results depending on call
**   nil and error message otherwise.
*/
static int cur_fetch (lua_State *L) {
    ISC_STATUS fetch_stat;
    int i;
    cur_data *cur = getcursor(L,1);
    const char *opts = luaL_optstring (L, 3, "n");
    int num = strchr(opts, 'n') != NULL;
    int alpha = strchr(opts, 'a') != NULL;

    if ((fetch_stat = isc_dsql_fetch(cur->env->status_vector, &cur->stmt, 1, cur->out_sqlda)) == 0) {
        if (lua_istable (L, 2)) {
            /* remove the option string */
            lua_settop(L, 2);

            /* loop through the columns */
            for (i = 0; i < cur->out_sqlda->sqld; i++) {
                push_column(L, i, cur);

                if( num ) {
                    lua_pushnumber(L, i+1);
                    lua_pushvalue(L, -2);
                    lua_settable(L, 2);
                }

                if( alpha ) {
                    lua_pushlstring(L, cur->out_sqlda->sqlvar[i].aliasname, cur->out_sqlda->sqlvar[i].aliasname_length);
                    lua_pushvalue(L, -2);
                    lua_settable(L, 2);
                }

                lua_pop(L, 1);
            }

            /* returning given table */
            return 1;
        } else {
            for (i = 0; i < cur->out_sqlda->sqld; i++)
                push_column(L, i, cur);

            /* returning a list of values */
            return cur->out_sqlda->sqld;
        }
    }

    /* isc_dsql_fetch returns 100 if no more rows remain to be retrieved
       so this can be ignored */
    if (fetch_stat != 100L)
        return return_db_error(L, cur->env->status_vector);

    /* last row has been fetched, close cursor */
    isc_dsql_free_statement(cur->env->status_vector, &cur->stmt, DSQL_drop);
    if ( CHECK_DB_ERROR(cur->env->status_vector) )
        return return_db_error(L, cur->env->status_vector);

    /* free the cursor data */
    free_cur(cur);

    cur->closed = 1;

    /* remove cursor from lock count */
    --cur->conn->lock;

    /* return sucsess */
    return 0;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
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 */
    }
}