Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,20 @@ PGAPI_BindParameter(HSTMT hstmt,
}


/* Associate a user-supplied buffer with a database column. */
/**
* @brief a user-supplied buffer with a database column.
* @param hstmt Statement handle
* @param icol Column number (zero-based)
* @param fCType Column data type
* @param rgbValue Column data
* @param cbValueMax Maximum column data size
* @param pcbValue Actual column data size
* @return RETCODE
* SQL_SUCCESS
* SQL_SUCCESS_WITH_INFO
* SQL_ERROR
* SQL_INVALID_HANDLE
*/
RETCODE SQL_API
PGAPI_BindCol(HSTMT hstmt,
SQLUSMALLINT icol,
Expand Down
22 changes: 17 additions & 5 deletions connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -1695,6 +1695,19 @@ CC_from_PGresult(QResultClass *res, StatementClass *stmt,
return success;
}

/**
* @param[in] *self
* @param[in] rollback_type
* PER_STATEMENT_ROLLBACK
*
* PER_QUERY_ROLLBACK
* sends ROLLBACK TO _per_query_svp_; RELEASE _per_query_svp_
* @param[in] ignore_abort
* @return
* 1: success
* 0: failure
*
*/
int
CC_internal_rollback(ConnectionClass *self, int rollback_type, BOOL ignore_abort)
{
Expand Down Expand Up @@ -2014,9 +2027,9 @@ CC_send_query_append(ConnectionClass *self, const char *query, QueryInfo *qi, UD
}
/*
* There are 2 risks to RELEASE an internal savepoint.
* One is to RELEASE the savepoint invalitated
* One is to RELEASE the savepoint invalidated
* due to manually issued ROLLBACK or RELEASE.
* Another is to invalitate manual SAVEPOINTs unexpectedly
* Another is to invalidate manual SAVEPOINTs unexpectedly
* by RELEASing the internal savepoint.
*/
else if (strnicmp(cmdbuffer, svpcmd, strlen(svpcmd)) == 0)
Expand Down Expand Up @@ -2762,7 +2775,7 @@ LIBPQ_connect(ConnectionClass *self)
int pversion;
const char *opts[PROTOCOL3_OPTS_MAX], *vals[PROTOCOL3_OPTS_MAX];
PQconninfoOption *conninfoOption = NULL, *pqopt;
int i, cnt;
int cnt;
char login_timeout_str[20];
char keepalive_idle_str[20];
char keepalive_interval_str[20];
Expand Down Expand Up @@ -2848,8 +2861,7 @@ LIBPQ_connect(ConnectionClass *self)
{
const char *keyword, *val;
int j;

for (i = 0, pqopt = conninfoOption; (keyword = pqopt->keyword) != NULL; i++, pqopt++)
for (pqopt = conninfoOption; (keyword = pqopt->keyword) != NULL; pqopt++)
{
if ((val = pqopt->val) != NULL)
{
Expand Down
78 changes: 68 additions & 10 deletions execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@
#include "lobj.h"
#include "pgapifunc.h"

/* Perform a Prepare on the SQL statement */
/**
* @brief Perform a Prepare on the SQL statement
*
* @param hstmt Handle to the statement
* @param szSqlStr SQL statement
* @param cbSqlStr Length of the SQL statement
*
*/
RETCODE SQL_API
PGAPI_Prepare(HSTMT hstmt,
const SQLCHAR * szSqlStr,
Expand Down Expand Up @@ -133,7 +140,14 @@ MYLOG(DETAIL_LOG_LEVEL, "leaving %d\n", retval);
}


/* Performs the equivalent of SQLPrepare, followed by SQLExecute. */
/**
* Performs the equivalent of SQLPrepare, followed by SQLExecute.
* @param hstmt Handle to the statement
* @param szSqlStr SQL statement
* @param cbSqlStr Length of the SQL statement
* @param flag Flags to control the execution of the statement
*
*/
RETCODE SQL_API
PGAPI_ExecDirect(HSTMT hstmt,
const SQLCHAR * szSqlStr,
Expand Down Expand Up @@ -393,6 +407,15 @@ int HowToPrepareBeforeExec(StatementClass *stmt, BOOL checkOnly)
return nCallParse;
}

/**
* Generate a name for the SVP (Savepoint) for the given
* connection.
*
* @param conn The connection.
* @param wrk The buffer to store the name in.
* @param wrksize The size of the buffer.
* @return The name of the Savepoint.
*/
static
const char *GetSvpName(const ConnectionClass *conn, char *wrk, int wrksize)
{
Expand Down Expand Up @@ -438,7 +461,7 @@ RETCODE Exec_with_parameters_resolved(StatementClass *stmt, EXEC_TYPE exec_type,
BOOL prepare_before_exec = FALSE;
char *stmt_with_params;
SQLLEN status_row = stmt->exec_current_row;
int count_of_deffered;
int count_of_deferred;

*exec_end = FALSE;
conn = SC_get_conn(stmt);
Expand Down Expand Up @@ -512,7 +535,7 @@ MYLOG(0, "about to begin SC_execute exec_type=%d\n", exec_type);
}
}
}
count_of_deffered = stmt->count_of_deffered;
count_of_deferred = stmt->count_of_deffered;
if (DIRECT_EXEC == exec_type)
{
retval = SC_execute(stmt);
Expand Down Expand Up @@ -561,8 +584,8 @@ MYLOG(0, "about to begin SC_execute exec_type=%d\n", exec_type);
}
if (retval == SQL_ERROR)
{
MYLOG(0, "count_of_deffered=%d\n", count_of_deffered);
param_status_batch_update(ipdopts, SQL_PARAM_ERROR, stmt->exec_current_row, count_of_deffered);
MYLOG(0, "count_of_deferred=%d\n", count_of_deferred);
param_status_batch_update(ipdopts, SQL_PARAM_ERROR, stmt->exec_current_row, count_of_deferred);
stmt->exec_current_row = -1;
*exec_end = TRUE;
RETURN(retval)
Expand Down Expand Up @@ -593,11 +616,11 @@ MYLOG(0, "count_of_deffered=%d\n", count_of_deffered);
ipdopts->param_status_ptr[status_row] = SQL_PARAM_SUCCESS;
break;
case SQL_SUCCESS_WITH_INFO:
MYLOG(0, "count_of_deffered=%d has_notice=%d\n", count_of_deffered, stmt->has_notice);
param_status_batch_update(ipdopts, (count_of_deffered > 0 && !stmt->has_notice) ? SQL_PARAM_SUCCESS : SQL_PARAM_SUCCESS_WITH_INFO, status_row, count_of_deffered);
MYLOG(0, "count_of_deffered=%d has_notice=%d\n", count_of_deferred, stmt->has_notice);
param_status_batch_update(ipdopts, (count_of_deferred > 0 && !stmt->has_notice) ? SQL_PARAM_SUCCESS : SQL_PARAM_SUCCESS_WITH_INFO, status_row, count_of_deferred);
break;
default:
param_status_batch_update(ipdopts, SQL_PARAM_ERROR, status_row, count_of_deffered);
param_status_batch_update(ipdopts, SQL_PARAM_ERROR, status_row, count_of_deferred);
break;
}
}
Expand Down Expand Up @@ -651,6 +674,12 @@ MYLOG(0, "count_of_deffered=%d has_notice=%d\n", count_of_deffered, stmt->has_no
return retval;
}

/**
* @param[in] stmt
* @return
* 1: transaction rollback
* 2: statement rollback
*/
int
StartRollbackState(StatementClass *stmt)
{
Expand All @@ -665,6 +694,7 @@ MYLOG(DETAIL_LOG_LEVEL, "entering %p->external=%d\n", stmt, stmt->external);

if (!ci || ci->rollback_on_error < 0) /* default */
{
/* server version greater than or equal to 8.0 ?*/
if (conn && PG_VERSION_GE(conn, 8.0))
ret = 2; /* statement rollback */
else
Expand All @@ -689,6 +719,20 @@ MYLOG(DETAIL_LOG_LEVEL, "entering %p->external=%d\n", stmt, stmt->external);
return ret;
}

/**
* @param[in] *conn
* @param[in] type
* INTERNAL_SAVEPOINT_OPERATION or INTERNAL_ROLLBACK_OPERATION
* if type is INTERNAL_SAVEPOINT_OPERATION and conn->internal_svp is FALSE
* then the command is "SAVEPOINT" instead of "RELEASE SAVEPOINT"
* if type is INTERNAL_ROLLBACK_OPERATION and conn->internal_svp is FALSE
* then the command is "ROLLBACK" instead of "ROLLBACK TO SAVEPOINT"
* @param[out] *cmd
* buffer to hold command to be sent
* @param[in] buflen
* @return less than zero if an error or number of characters in command
*
*/
int
GenerateSvpCommand(ConnectionClass *conn, int type, char *cmd, int buflen)
{
Expand Down Expand Up @@ -790,6 +834,14 @@ MYLOG(DETAIL_LOG_LEVEL, "leaving %p->accessed=%d\n", conn, CC_accessed_db(conn))
return ret;
}


/**
* @brief Discards the statement savepoint
* @param stmt
* @param ret
* @param errorOnly
* @return ret
*/
RETCODE
DiscardStatementSvp(StatementClass *stmt, RETCODE ret, BOOL errorOnly)
{
Expand Down Expand Up @@ -920,7 +972,13 @@ SC_setInsertedTable(StatementClass *stmt, RETCODE retval)
NULL_THE_NAME(conn->schemaIns);
}

/* Execute a prepared SQL statement */
/**
* @brief Execute a prepared SQL statement
* @param hstmt
* @param flag
* @return SQL_SUCCESS if successful
*
*/
RETCODE SQL_API
PGAPI_Execute(HSTMT hstmt, UWORD flag)
{
Expand Down
98 changes: 85 additions & 13 deletions info.c
Original file line number Diff line number Diff line change
Expand Up @@ -2901,6 +2901,20 @@ MYLOG(0, " and the data=%s\n", attdef);
}


/** @brief Retrieve the optimal set of columns that uniquely identifies a row in the specified table (when IdentifierType is SQL_BEST_ROWID)
* The columns that are automatically updated when any value in the row is updated (when IdentifierType is SQL_ROWVER)
* @param hstmt
* @param fColType
* @param szTableQualifier
* @param cbTableQualifier
* @param szTableOwner
* @param cbTableOwner
* @param szTableName
* @param cbTableName
* @param fScope
* @param fNullable
* @return
*/
RETCODE SQL_API
PGAPI_SpecialColumns(HSTMT hstmt,
SQLUSMALLINT fColType,
Expand Down Expand Up @@ -3103,27 +3117,85 @@ MYLOG(DETAIL_LOG_LEVEL, "Add ctid\n");
}
else
{
/* use the oid value for the rowid */

if (fColType == SQL_BEST_ROWID)
{
Int2 the_type = PG_TYPE_OID;
int atttypmod = -1;

if (relhasoids[0] != '1')
if (relhasoids[0] == '1')
{
ret = SQL_SUCCESS;
goto cleanup;
tuple = QR_AddNew(res);

set_tuplefield_int2(&tuple[SPECOLS_SCOPE], SQL_SCOPE_SESSION);
set_tuplefield_string(&tuple[SPECOLS_COLUMN_NAME], OID_NAME);
set_tuplefield_int2(&tuple[SPECOLS_DATA_TYPE], PGTYPE_ATTR_TO_CONCISE_TYPE(conn, the_type, atttypmod));
set_tuplefield_string(&tuple[SPECOLS_TYPE_NAME], pgtype_attr_to_name(conn, the_type, atttypmod, TRUE));
set_tuplefield_int4(&tuple[SPECOLS_COLUMN_SIZE], PGTYPE_ATTR_COLUMN_SIZE(conn, the_type, atttypmod));
set_tuplefield_int4(&tuple[SPECOLS_BUFFER_LENGTH], PGTYPE_ATTR_BUFFER_LENGTH(conn, the_type, atttypmod));
set_tuplefield_int2(&tuple[SPECOLS_DECIMAL_DIGITS], PGTYPE_ATTR_DECIMAL_DIGITS(conn, the_type, atttypmod));
set_tuplefield_int2(&tuple[SPECOLS_PSEUDO_COLUMN], SQL_PC_PSEUDO);
} else {
/*

SELECT NULL as \"SCOPE\",
n.nspname AS \"SCHEMA_NAME\"",
c.relname AS \"TABLE_NAME\"",
a.attname AS \"COLUMN_NAME\"",
t.typname AS \"DATA_TYPE\",
t.typename AS \"TYPE_NAME\"",
i.indisunique,i.indisprimary
FROM pg_class c
INNER JOIN pg_namespace n ON n.oid = c.relnamespace
INNER JOIN pg_attribute a ON a.attrelid = c.oid
INNER JOIN pg_type t on a.atttypid = t.oid
LEFT JOIN pg_index i
ON i.indrelid = c.oid
AND a.attnum = ANY (i.indkey[0:(i.indnkeyatts - 1)])
WHERE a.attnum > 0 and c.relname like 'testuktab';
*/
initPQExpBuffer(&columns_query);
printfPQExpBuffer(&columns_query, "select NULL as \"SCOPE\","
"n.nspname as \"SCHEMA_NAME\","
"c.relname as \"TABLE_NAME\","
"a.attname AS \"COLUMN_NAME\","
"t.typname AS \"DATA_TYPE\","
"t.typname AS \"TYPE_NAME\","
"t.typlen AS \"COLUMN_SIZE\","
"a.attlen AS \"BUFFER_LENGTH\","
"case "
"when t.typname = 'numeric' then"
" case when a.atttypmod > -1 then 6"
" else a.atttypmod::int4"
" end"
" else 0"
" end AS \"DECIMAL_DIGITS\","
"1 AS \"PSEUDO_COLUMN\" "
"FROM pg_class c "
"INNER JOIN pg_namespace n ON n.oid = c.relnamespace "
"INNER JOIN pg_attribute a ON a.attrelid = c.oid "
"INNER JOIN pg_type t on a.atttypid = t.oid "
"LEFT JOIN pg_index i ON i.indrelid = c.oid "
"AND a.attnum = ANY (i.indkey[0:(i.indnkeyatts - 1)]) "
"WHERE i.indisunique and a.attnum > 0 and c.relname ='%s'" , szTableName );


if (szTableQualifier != NULL)
appendPQExpBuffer(&columns_query, " and c.relnamespace = %s" , szSchemaName);

result = PGAPI_ExecDirect(stmt, (SQLCHAR *) columns_query.data, SQL_NTS, PODBC_RDONLY);
if (!SQL_SUCCEEDED(result))
{
/*
* "Couldn't execute index query (w/SQLExecDirect) in
* SpecialColumns";
*/
SC_full_error_copy(stmt, stmt, FALSE);
goto cleanup;
}
res = SC_get_Result(stmt);
}
tuple = QR_AddNew(res);

set_tuplefield_int2(&tuple[SPECOLS_SCOPE], SQL_SCOPE_SESSION);
set_tuplefield_string(&tuple[SPECOLS_COLUMN_NAME], OID_NAME);
set_tuplefield_int2(&tuple[SPECOLS_DATA_TYPE], PGTYPE_ATTR_TO_CONCISE_TYPE(conn, the_type, atttypmod));
set_tuplefield_string(&tuple[SPECOLS_TYPE_NAME], pgtype_attr_to_name(conn, the_type, atttypmod, TRUE));
set_tuplefield_int4(&tuple[SPECOLS_COLUMN_SIZE], PGTYPE_ATTR_COLUMN_SIZE(conn, the_type, atttypmod));
set_tuplefield_int4(&tuple[SPECOLS_BUFFER_LENGTH], PGTYPE_ATTR_BUFFER_LENGTH(conn, the_type, atttypmod));
set_tuplefield_int2(&tuple[SPECOLS_DECIMAL_DIGITS], PGTYPE_ATTR_DECIMAL_DIGITS(conn, the_type, atttypmod));
set_tuplefield_int2(&tuple[SPECOLS_PSEUDO_COLUMN], SQL_PC_PSEUDO);
}
else if (fColType == SQL_ROWVER)
{
Expand Down
Loading