Skip to content

Commit

Permalink
OCI: allow accessing results of PL/SQL procedure calls returning a RE…
Browse files Browse the repository at this point in the history
…F CURSOR

Move the QOCIResult implementation of QSqlCachedResult into the private
qsql_oci_p.h header, and register it as a meta type that we can pass
through QVariant. Add a field that indicates whether that results
represents a cursor variable, and bind it to the statement handle if so.

Fixes: QTBUG-166
Fixes: QTBUG-44643
Change-Id: Iafbf5474ad7efc6d24eb52a5c5a1b3d2b6842387
Reviewed-by: Andy Shaw <[email protected]>
  • Loading branch information
vohi committed Jun 19, 2024
1 parent 334d4c7 commit 82681fd
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 48 deletions.
101 changes: 53 additions & 48 deletions src/plugins/sqldrivers/oci/qsql_oci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@

//#define QOCI_DEBUG

Q_DECLARE_OPAQUE_POINTER(OCIEnv*);
Q_DECLARE_OPAQUE_POINTER(QOCIResult*)
Q_DECLARE_METATYPE(QOCIResult*)
Q_DECLARE_OPAQUE_POINTER(OCIEnv*)
Q_DECLARE_METATYPE(OCIEnv*)
Q_DECLARE_OPAQUE_POINTER(OCIStmt*);
Q_DECLARE_OPAQUE_POINTER(OCIStmt*)
Q_DECLARE_METATYPE(OCIStmt*)

QT_BEGIN_NAMESPACE
Expand Down Expand Up @@ -203,31 +205,6 @@ class QOCIDriverPrivate : public QSqlDriverPrivate
};

class QOCICols;
class QOCIResultPrivate;

class QOCIResult: public QSqlCachedResult
{
Q_DECLARE_PRIVATE(QOCIResult)
friend class QOCIDriver;
friend class QOCICols;
public:
QOCIResult(const QOCIDriver *db);
~QOCIResult();
bool prepare(const QString &query) override;
bool exec() override;
QVariant handle() const override;

protected:
bool gotoNext(ValueCache &values, int index) override;
bool reset(const QString &query) override;
int size() override;
int numRowsAffected() override;
QSqlRecord record() const override;
QVariant lastInsertId() const override;
bool execBatch(bool arrayBind = false) override;
void virtual_hook(int id, void *data) override;
bool fetchNext() override;
};

class QOCIResultPrivate: public QSqlCachedResultPrivate
{
Expand Down Expand Up @@ -435,6 +412,18 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in
const_cast<OCIRowid **>(&rptr->id),
-1,
SQLT_RDD, indPtr, 0, 0, 0, 0, OCI_DEFAULT);
} else if (val.canConvert<QOCIResult *>() && isOutValue(pos)) {
QOCIResult *res = qvariant_cast<QOCIResult *>(val);

if (res->internal_prepare()) {
r = OCIBindByPos(sql, hbnd, err,
pos + 1,
const_cast<OCIStmt **>(&res->d->sql),
(sb4)0,
SQLT_RSET, indPtr, 0, 0, 0, 0, OCI_DEFAULT);

res->isCursor = true;
}
} else {
qCWarning(lcOci, "Unknown bind variable");
r = OCI_ERROR;
Expand Down Expand Up @@ -1831,6 +1820,7 @@ QOCIResultPrivate::~QOCIResultPrivate()
QOCIResult::QOCIResult(const QOCIDriver *db)
: QSqlCachedResult(*new QOCIResultPrivate(this, db))
{
isCursor = false;
}

QOCIResult::~QOCIResult()
Expand Down Expand Up @@ -1923,11 +1913,12 @@ int QOCIResult::numRowsAffected()
return rowCount;
}

bool QOCIResult::prepare(const QString& query)
+bool QOCIResult::internal_prepare()
{
Q_D(QOCIResult);
int r = 0;
QSqlResult::prepare(query);
QString noStr;
QSqlResult::prepare(noStr);

delete d->cols;
d->cols = nullptr;
Expand All @@ -1940,8 +1931,7 @@ bool QOCIResult::prepare(const QString& query)
else
qOraWarning("QOCIResult::prepare: unable to free statement handle:", d->err);
}
if (query.isEmpty())
return false;

r = OCIHandleAlloc(d->env,
reinterpret_cast<void **>(&d->sql),
OCI_HTYPE_STMT,
Expand All @@ -1953,6 +1943,19 @@ bool QOCIResult::prepare(const QString& query)
return false;
}
d->setStatementAttributes();

return true;
}

bool QOCIResult::prepare(const QString& query)
{
if (query.isEmpty())
return false;

if (!internal_prepare())
return false;

int r;
const OraText *txt = reinterpret_cast<const OraText *>(query.utf16());
const int len = query.length() * sizeof(QChar);
r = OCIStmtPrepare(d->sql,
Expand Down Expand Up @@ -2013,23 +2016,25 @@ bool QOCIResult::exec()
return false;
}

// execute
r = OCIStmtExecute(d->svc,
d->sql,
d->err,
iters,
0,
0,
0,
mode);
if (r != OCI_SUCCESS && r != OCI_SUCCESS_WITH_INFO) {
qOraWarning("QOCIResult::exec: unable to execute statement:", d->err);
setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
"Unable to execute statement"), QSqlError::StatementError, d->err));
#ifdef QOCI_DEBUG
qCDebug(lcOci) << "lastQuery()" << lastQuery();
#endif
return false;
if (!isCursor()) {
// execute
r = OCIStmtExecute(d->svc,
d->sql,
d->err,
iters,
0,
0,
0,
mode);
if (r != OCI_SUCCESS && r != OCI_SUCCESS_WITH_INFO) {
qOraWarning("QOCIResult::exec: unable to execute statement:", d->err);
setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
"Unable to execute statement"), QSqlError::StatementError, d->err));
#ifdef QOCI_DEBUG
qCDebug(lcOci) << "lastQuery()" << lastQuery();
#endif
return false;
}
}

if (stmtType == OCI_STMT_SELECT) {
Expand Down
30 changes: 30 additions & 0 deletions src/plugins/sqldrivers/oci/qsql_oci_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
//

#include <QtSql/qsqldriver.h>
#include <QtSql/private/qsqlcachedresult_p.h>

#ifdef QT_PLUGIN
#define Q_EXPORT_SQLDRIVER_OCI
Expand All @@ -25,6 +26,7 @@

typedef struct OCIEnv OCIEnv;
typedef struct OCISvcCtx OCISvcCtx;
struct QOCIResultPrivate;

QT_BEGIN_NAMESPACE

Expand Down Expand Up @@ -66,6 +68,34 @@ class Q_EXPORT_SQLDRIVER_OCI QOCIDriver : public QSqlDriver
bool rollbackTransaction() override;
};

class Q_EXPORT_SQLDRIVER_OCI QOCIResult : public QSqlCachedResult
{
friend class QOCIDriver;
friend struct QOCIResultPrivate;
friend class QOCICols;
public:
QOCIResult(const QOCIDriver * db, const QOCIDriverPrivate* p);
~QOCIResult();
bool prepare(const QString& query);
bool exec();
QVariant handle() const;

protected:
bool gotoNext(ValueCache &values, int index);
bool reset (const QString& query);
int size();
int numRowsAffected();
QSqlRecord record() const;
QVariant lastInsertId() const;
bool execBatch(bool arrayBind = false);
void virtual_hook(int id, void *data);
bool isCursor;
bool internal_prepare();

private:
QOCIResultPrivate *d;
};

QT_END_NAMESPACE

#endif // QSQL_OCI_H

0 comments on commit 82681fd

Please sign in to comment.