summaryrefslogtreecommitdiffstats
path: root/src/sql/drivers/oci/qsql_oci.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sql/drivers/oci/qsql_oci.cpp')
-rw-r--r--src/sql/drivers/oci/qsql_oci.cpp262
1 files changed, 150 insertions, 112 deletions
diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp
index f0c0b224bd..47d6db7ea4 100644
--- a/src/sql/drivers/oci/qsql_oci.cpp
+++ b/src/sql/drivers/oci/qsql_oci.cpp
@@ -1,31 +1,37 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtSql module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -155,42 +161,62 @@ QT_BEGIN_INCLUDE_NAMESPACE
Q_DECLARE_METATYPE(QOCIRowIdPointer)
QT_END_INCLUDE_NAMESPACE
+class QOCIDriverPrivate : public QSqlDriverPrivate
+{
+ Q_DECLARE_PUBLIC(QOCIDriver)
+
+public:
+ QOCIDriverPrivate();
+
+ OCIEnv *env;
+ OCISvcCtx *svc;
+ OCIServer *srvhp;
+ OCISession *authp;
+ OCIError *err;
+ bool transaction;
+ int serverVersion;
+ int prefetchRows;
+ int prefetchMem;
+ QString user;
+
+ void allocErrorHandle();
+};
+
class QOCICols;
-struct QOCIResultPrivate;
+class QOCIResultPrivate;
-class Q_EXPORT_SQLDRIVER_OCI QOCIResult : public QSqlCachedResult
+class QOCIResult: public QSqlCachedResult
{
+ Q_DECLARE_PRIVATE(QOCIResult)
friend class QOCIDriver;
- friend struct QOCIResultPrivate;
friend class QOCICols;
public:
- QOCIResult(const QOCIDriver * db, const QOCIDriverPrivate* p);
+ QOCIResult(const QOCIDriver *db);
~QOCIResult();
- bool prepare(const QString& query);
- bool exec();
- QVariant handle() const;
+ bool prepare(const QString &query) Q_DECL_OVERRIDE;
+ bool exec() Q_DECL_OVERRIDE;
+ QVariant handle() const Q_DECL_OVERRIDE;
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);
-
-private:
- QOCIResultPrivate *d;
+ bool gotoNext(ValueCache &values, int index) Q_DECL_OVERRIDE;
+ bool reset(const QString &query) Q_DECL_OVERRIDE;
+ int size() Q_DECL_OVERRIDE;
+ int numRowsAffected() Q_DECL_OVERRIDE;
+ QSqlRecord record() const Q_DECL_OVERRIDE;
+ QVariant lastInsertId() const Q_DECL_OVERRIDE;
+ bool execBatch(bool arrayBind = false) Q_DECL_OVERRIDE;
+ void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
};
-struct QOCIResultPrivate
+class QOCIResultPrivate: public QSqlCachedResultPrivate
{
- QOCIResultPrivate(QOCIResult *result, const QOCIDriverPrivate *driver);
+public:
+ Q_DECLARE_PUBLIC(QOCIResult)
+ Q_DECLARE_SQLDRIVER_PRIVATE(QOCIDriver)
+ QOCIResultPrivate(QOCIResult *q, const QOCIDriver *drv);
~QOCIResultPrivate();
QOCICols *cols;
- QOCIResult *q;
OCIEnv *env;
OCIError *err;
OCISvcCtx *&svc;
@@ -207,9 +233,9 @@ struct QOCIResultPrivate
void outValues(QVector<QVariant> &values, IndicatorArray &indicators,
QList<QByteArray> &tmpStorage);
inline bool isOutValue(int i) const
- { return q->bindValueType(i) & QSql::Out; }
+ { Q_Q(const QOCIResult); return q->bindValueType(i) & QSql::Out; }
inline bool isBinaryValue(int i) const
- { return q->bindValueType(i) & QSql::Binary; }
+ { Q_Q(const QOCIResult); return q->bindValueType(i) & QSql::Binary; }
void setCharset(dvoid* handle, ub4 type) const
{
@@ -485,25 +511,6 @@ void QOCIResultPrivate::outValues(QVector<QVariant> &values, IndicatorArray &ind
}
-class QOCIDriverPrivate : public QSqlDriverPrivate
-{
-public:
- QOCIDriverPrivate();
-
- OCIEnv *env;
- OCISvcCtx *svc;
- OCIServer *srvhp;
- OCISession *authp;
- OCIError *err;
- bool transaction;
- int serverVersion;
- ub4 prefetchRows;
- ub2 prefetchMem;
- QString user;
-
- void allocErrorHandle();
-};
-
QOCIDriverPrivate::QOCIDriverPrivate()
: QSqlDriverPrivate(), env(0), svc(0), srvhp(0), authp(0), err(0), transaction(false),
serverVersion(-1), prefetchRows(-1), prefetchMem(QOCI_PREFETCH_MEM)
@@ -1221,7 +1228,7 @@ OraFieldInfo QOCICols::qMakeOraField(const QOCIResultPrivate* p, OCIParam* param
if (r != 0)
qOraWarning("qMakeOraField:", p->err);
- type = qDecodeOCIType(colType, p->q->numericalPrecisionPolicy());
+ type = qDecodeOCIType(colType, p->q_func()->numericalPrecisionPolicy());
if (type == QVariant::Int) {
if (colLength == 22 && colPrecision == 0 && colScale == 0)
@@ -1232,16 +1239,16 @@ OraFieldInfo QOCICols::qMakeOraField(const QOCIResultPrivate* p, OCIParam* param
// bind as double if the precision policy asks for it
if (((colType == SQLT_FLT) || (colType == SQLT_NUM))
- && (p->q->numericalPrecisionPolicy() == QSql::LowPrecisionDouble)) {
+ && (p->q_func()->numericalPrecisionPolicy() == QSql::LowPrecisionDouble)) {
type = QVariant::Double;
}
// bind as int32 or int64 if the precision policy asks for it
if ((colType == SQLT_NUM) || (colType == SQLT_VNU) || (colType == SQLT_UIN)
|| (colType == SQLT_INT)) {
- if (p->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
+ if (p->q_func()->numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
type = QVariant::LongLong;
- else if (p->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
+ else if (p->q_func()->numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
type = QVariant::Int;
}
@@ -1336,7 +1343,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
if (r != OCI_SUCCESS && r != OCI_SUCCESS_WITH_INFO) {
qOraWarning("QOCIPrivate::execBatch: unable to bind column:", d->err);
- d->q->setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
+ d->q_func()->setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
"Unable to bind column for batch execute"),
QSqlError::StatementError, d->err));
return false;
@@ -1530,7 +1537,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
if (r != OCI_SUCCESS && r != OCI_SUCCESS_WITH_INFO) {
qOraWarning("QOCIPrivate::execBatch: unable to bind column:", d->err);
- d->q->setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
+ d->q_func()->setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
"Unable to bind column for batch execute"),
QSqlError::StatementError, d->err));
return false;
@@ -1545,7 +1552,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
if (r != OCI_SUCCESS && r != OCI_SUCCESS_WITH_INFO) {
qOraWarning("QOCIPrivate::execBatch: unable to bind column:", d->err);
- d->q->setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
+ d->q_func()->setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
"Unable to bind column for batch execute"),
QSqlError::StatementError, d->err));
return false;
@@ -1560,7 +1567,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
if (r != OCI_SUCCESS && r != OCI_SUCCESS_WITH_INFO) {
qOraWarning("QOCIPrivate::execBatch: unable to execute batch statement:", d->err);
- d->q->setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
+ d->q_func()->setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
"Unable to execute batch statement"),
QSqlError::StatementError, d->err));
return false;
@@ -1635,9 +1642,9 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b
}
}
- d->q->setSelect(false);
- d->q->setAt(QSql::BeforeFirstRow);
- d->q->setActive(true);
+ d->q_func()->setSelect(false);
+ d->q_func()->setAt(QSql::BeforeFirstRow);
+ d->q_func()->setActive(true);
return true;
}
@@ -1752,12 +1759,12 @@ void QOCICols::getValues(QVector<QVariant> &v, int index)
case QVariant::Double:
case QVariant::Int:
case QVariant::LongLong:
- if (d->q->numericalPrecisionPolicy() != QSql::HighPrecision) {
- if ((d->q->numericalPrecisionPolicy() == QSql::LowPrecisionDouble)
+ if (d->q_func()->numericalPrecisionPolicy() != QSql::HighPrecision) {
+ if ((d->q_func()->numericalPrecisionPolicy() == QSql::LowPrecisionDouble)
&& (fld.typ == QVariant::Double)) {
v[index + i] = *reinterpret_cast<double *>(fld.data);
break;
- } else if ((d->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
+ } else if ((d->q_func()->numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
&& (fld.typ == QVariant::LongLong)) {
qint64 qll = 0;
int r = OCINumberToInt(d->err, reinterpret_cast<OCINumber *>(fld.data), sizeof(qint64),
@@ -1767,7 +1774,7 @@ void QOCICols::getValues(QVector<QVariant> &v, int index)
else
v[index + i] = QVariant();
break;
- } else if ((d->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
+ } else if ((d->q_func()->numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
&& (fld.typ == QVariant::Int)) {
v[index + i] = *reinterpret_cast<int *>(fld.data);
break;
@@ -1790,10 +1797,17 @@ void QOCICols::getValues(QVector<QVariant> &v, int index)
}
}
-QOCIResultPrivate::QOCIResultPrivate(QOCIResult *result, const QOCIDriverPrivate *driver)
- : cols(0), q(result), env(driver->env), err(0), svc(const_cast<OCISvcCtx*&>(driver->svc)),
- sql(0), transaction(driver->transaction), serverVersion(driver->serverVersion),
- prefetchRows(driver->prefetchRows), prefetchMem(driver->prefetchMem)
+QOCIResultPrivate::QOCIResultPrivate(QOCIResult *q, const QOCIDriver *drv)
+ : QSqlCachedResultPrivate(q, drv),
+ cols(0),
+ env(drv_d_func()->env),
+ err(0),
+ svc(const_cast<OCISvcCtx*&>(drv_d_func()->svc)),
+ sql(0),
+ transaction(drv_d_func()->transaction),
+ serverVersion(drv_d_func()->serverVersion),
+ prefetchRows(drv_d_func()->prefetchRows),
+ prefetchMem(drv_d_func()->prefetchMem)
{
int r = OCIHandleAlloc(env,
reinterpret_cast<void **>(&err),
@@ -1816,24 +1830,24 @@ QOCIResultPrivate::~QOCIResultPrivate()
////////////////////////////////////////////////////////////////////////////
-QOCIResult::QOCIResult(const QOCIDriver * db, const QOCIDriverPrivate* p)
- : QSqlCachedResult(db)
+QOCIResult::QOCIResult(const QOCIDriver *db)
+ : QSqlCachedResult(*new QOCIResultPrivate(this, db))
{
- d = new QOCIResultPrivate(this, p);
}
QOCIResult::~QOCIResult()
{
+ Q_D(QOCIResult);
if (d->sql) {
int r = OCIHandleFree(d->sql, OCI_HTYPE_STMT);
if (r != 0)
qWarning("~QOCIResult: unable to free statement handle");
}
- delete d;
}
QVariant QOCIResult::handle() const
{
+ Q_D(const QOCIResult);
return QVariant::fromValue(d->sql);
}
@@ -1846,6 +1860,7 @@ bool QOCIResult::reset (const QString& query)
bool QOCIResult::gotoNext(QSqlCachedResult::ValueCache &values, int index)
{
+ Q_D(QOCIResult);
if (at() == QSql::AfterLastRow)
return false;
@@ -1905,6 +1920,7 @@ int QOCIResult::size()
int QOCIResult::numRowsAffected()
{
+ Q_D(QOCIResult);
int rowCount;
OCIAttrGet(d->sql,
OCI_HTYPE_STMT,
@@ -1917,6 +1933,7 @@ int QOCIResult::numRowsAffected()
bool QOCIResult::prepare(const QString& query)
{
+ Q_D(QOCIResult);
int r = 0;
QSqlResult::prepare(query);
@@ -1962,6 +1979,7 @@ bool QOCIResult::prepare(const QString& query)
bool QOCIResult::exec()
{
+ Q_D(QOCIResult);
int r = 0;
ub2 stmtType=0;
ub4 iters;
@@ -2043,6 +2061,7 @@ bool QOCIResult::exec()
QSqlRecord QOCIResult::record() const
{
+ Q_D(const QOCIResult);
QSqlRecord inf;
if (!isActive() || !isSelect() || !d->cols)
return inf;
@@ -2051,6 +2070,7 @@ QSqlRecord QOCIResult::record() const
QVariant QOCIResult::lastInsertId() const
{
+ Q_D(const QOCIResult);
if (isActive()) {
QOCIRowIdPointer ptr(new QOCIRowId(d->env));
@@ -2064,6 +2084,7 @@ QVariant QOCIResult::lastInsertId() const
bool QOCIResult::execBatch(bool arrayBind)
{
+ Q_D(QOCIResult);
QOCICols::execBatch(d, boundValues(), arrayBind);
resetBindCount();
return lastError().type() == QSqlError::NoError;
@@ -2301,8 +2322,7 @@ void QOCIDriver::close()
QSqlResult *QOCIDriver::createResult() const
{
- Q_D(const QOCIDriver);
- return new QOCIResult(this, d);
+ return new QOCIResult(this);
}
bool QOCIDriver::beginTransaction()
@@ -2366,17 +2386,46 @@ bool QOCIDriver::rollbackTransaction()
return true;
}
+enum Expression {
+ OrExpression,
+ AndExpression
+};
+
+static QString make_where_clause(const QString &user, Expression e)
+{
+ static const char sysUsers[][8] = {
+ "MDSYS",
+ "LBACSYS",
+ "SYS",
+ "SYSTEM",
+ "WKSYS",
+ "CTXSYS",
+ "WMSYS",
+ };
+ static const char joinC[][4] = { "or" , "and" };
+ static Q_CONSTEXPR QLatin1Char bang[] = { QLatin1Char(' '), QLatin1Char('!') };
+
+ const QLatin1String join(joinC[e], -1); // -1: force strlen call
+
+ QString result;
+ result.reserve(sizeof sysUsers / sizeof *sysUsers *
+ // max-sizeof(owner != <sysuser> and )
+ (9 + sizeof *sysUsers + 5));
+ for (const auto &sysUser : sysUsers) {
+ const QLatin1String l1(sysUser, -1); // -1: force strlen call
+ if (l1 != user)
+ result += QLatin1String("owner ") + bang[e] + QLatin1String("= '") + l1 + QLatin1Char(' ') + join + QLatin1Char(' ');
+ }
+
+ result.chop(join.size() + 2); // remove final " <join> "
+
+ return result;
+}
+
QStringList QOCIDriver::tables(QSql::TableType type) const
{
Q_D(const QOCIDriver);
QStringList tl;
- QStringList sysUsers = QStringList() << QLatin1String("MDSYS")
- << QLatin1String("LBACSYS")
- << QLatin1String("SYS")
- << QLatin1String("SYSTEM")
- << QLatin1String("WKSYS")
- << QLatin1String("CTXSYS")
- << QLatin1String("WMSYS");
QString user = d->user;
if ( isIdentifierEscaped(user, QSqlDriver::TableName))
@@ -2384,21 +2433,15 @@ QStringList QOCIDriver::tables(QSql::TableType type) const
else
user = user.toUpper();
- if(sysUsers.contains(user))
- sysUsers.removeAll(user);;
-
if (!isOpen())
return tl;
QSqlQuery t(createResult());
t.setForwardOnly(true);
if (type & QSql::Tables) {
- QString query = QLatin1String("select owner, table_name from all_tables where ");
- QStringList whereList;
- foreach(const QString &sysUserName, sysUsers)
- whereList << QLatin1String("owner != '") + sysUserName + QLatin1String("' ");
- t.exec(query + whereList.join(QLatin1String(" and ")));
-
+ const QLatin1String tableQuery("select owner, table_name from all_tables where ");
+ const QString where = make_where_clause(user, AndExpression);
+ t.exec(tableQuery + where);
while (t.next()) {
if (t.value(0).toString().toUpper() != user.toUpper())
tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());
@@ -2407,8 +2450,8 @@ QStringList QOCIDriver::tables(QSql::TableType type) const
}
// list all table synonyms as well
- query = QLatin1String("select owner, synonym_name from all_synonyms where ");
- t.exec(query + whereList.join(QLatin1String(" and ")));
+ const QLatin1String synonymQuery("select owner, synonym_name from all_synonyms where ");
+ t.exec(synonymQuery + where);
while (t.next()) {
if (t.value(0).toString() != d->user)
tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());
@@ -2417,11 +2460,9 @@ QStringList QOCIDriver::tables(QSql::TableType type) const
}
}
if (type & QSql::Views) {
- QString query = QLatin1String("select owner, view_name from all_views where ");
- QStringList whereList;
- foreach(const QString &sysUserName, sysUsers)
- whereList << QLatin1String("owner != '") + sysUserName + QLatin1String("' ");
- t.exec(query + whereList.join(QLatin1String(" and ")));
+ const QLatin1String query("select owner, view_name from all_views where ");
+ const QString where = make_where_clause(user, AndExpression);
+ t.exec(query + where);
while (t.next()) {
if (t.value(0).toString().toUpper() != d->user.toUpper())
tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());
@@ -2434,12 +2475,9 @@ QStringList QOCIDriver::tables(QSql::TableType type) const
while (t.next()) {
tl.append(t.value(0).toString());
}
- QString query = QLatin1String("select owner, table_name from all_tables where ");
- QStringList whereList;
- foreach(const QString &sysUserName, sysUsers)
- whereList << QLatin1String("owner = '") + sysUserName + QLatin1String("' ");
- t.exec(query + whereList.join(QLatin1String(" or ")));
-
+ const QLatin1String tableQuery("select owner, table_name from all_tables where ");
+ const QString where = make_where_clause(user, OrExpression);
+ t.exec(tableQuery + where);
while (t.next()) {
if (t.value(0).toString().toUpper() != user.toUpper())
tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());
@@ -2448,8 +2486,8 @@ QStringList QOCIDriver::tables(QSql::TableType type) const
}
// list all table synonyms as well
- query = QLatin1String("select owner, synonym_name from all_synonyms where ");
- t.exec(query + whereList.join(QLatin1String(" or ")));
+ const QLatin1String synonymQuery("select owner, synonym_name from all_synonyms where ");
+ t.exec(synonymQuery + where);
while (t.next()) {
if (t.value(0).toString() != d->user)
tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());