summaryrefslogtreecommitdiffstats
path: root/src/sql
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2009-06-15 09:57:36 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2009-06-15 09:57:36 (GMT)
commit336dfcef05cb63df0a6d550b59a4badc7a0f01c1 (patch)
treea218ec97413e0c8ebc9600ac5db9b2adea485b32 /src/sql
parente44d64510e019e5d3b379b704cfb824e0d7ccc9d (diff)
downloadQt-336dfcef05cb63df0a6d550b59a4badc7a0f01c1.zip
Qt-336dfcef05cb63df0a6d550b59a4badc7a0f01c1.tar.gz
Qt-336dfcef05cb63df0a6d550b59a4badc7a0f01c1.tar.bz2
Merge of master
Diffstat (limited to 'src/sql')
-rw-r--r--src/sql/drivers/db2/qsql_db2.cpp7
-rw-r--r--src/sql/drivers/mysql/qsql_mysql.cpp30
-rw-r--r--src/sql/drivers/mysql/qsql_mysql.h1
-rw-r--r--src/sql/drivers/oci/qsql_oci.cpp280
-rw-r--r--src/sql/drivers/odbc/qsql_odbc.cpp63
-rw-r--r--src/sql/drivers/psql/qsql_psql.cpp21
-rw-r--r--src/sql/drivers/sqlite/qsql_sqlite.cpp11
-rw-r--r--src/sql/drivers/sqlite2/qsql_sqlite2.cpp7
-rw-r--r--src/sql/kernel/qsqldatabase.cpp55
-rw-r--r--src/sql/kernel/qsqldatabase.h2
-rw-r--r--src/sql/kernel/qsqldriver.cpp28
-rw-r--r--src/sql/kernel/qsqldriver.h3
-rw-r--r--src/sql/kernel/qsqlquery.cpp23
-rw-r--r--src/sql/kernel/qsqlresult.cpp17
-rw-r--r--src/sql/kernel/qsqlresult.h1
15 files changed, 311 insertions, 238 deletions
diff --git a/src/sql/drivers/db2/qsql_db2.cpp b/src/sql/drivers/db2/qsql_db2.cpp
index c7cbc9b..b8f52f4 100644
--- a/src/sql/drivers/db2/qsql_db2.cpp
+++ b/src/sql/drivers/db2/qsql_db2.cpp
@@ -84,7 +84,7 @@ public:
class QDB2ResultPrivate
{
public:
- QDB2ResultPrivate(const QDB2DriverPrivate* d): dp(d), hStmt(0), precisionPolicy(QSql::HighPrecision)
+ QDB2ResultPrivate(const QDB2DriverPrivate* d): dp(d), hStmt(0)
{}
~QDB2ResultPrivate()
{
@@ -107,7 +107,6 @@ public:
SQLHANDLE hStmt;
QSqlRecord recInf;
QVector<QVariant*> valueCache;
- QSql::NumericalPrecisionPolicy precisionPolicy;
};
static QString qFromTChar(SQLTCHAR* str)
@@ -1147,10 +1146,6 @@ void QDB2Result::virtual_hook(int id, void *data)
Q_ASSERT(data);
*static_cast<bool*>(data) = nextResult();
break;
- case QSqlResult::SetNumericalPrecision:
- Q_ASSERT(data);
- d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
- break;
default:
QSqlResult::virtual_hook(id, data);
}
diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp
index 82ed124..0ea2f96 100644
--- a/src/sql/drivers/mysql/qsql_mysql.cpp
+++ b/src/sql/drivers/mysql/qsql_mysql.cpp
@@ -167,12 +167,11 @@ class QMYSQLResultPrivate : public QObject
{
Q_OBJECT
public:
- QMYSQLResultPrivate(const QMYSQLDriver* dp) : driver(dp), result(0),
+ QMYSQLResultPrivate(const QMYSQLDriver* dp, const QMYSQLResult* d) : driver(dp), result(0), q(d),
rowsAffected(0), hasBlobs(false)
#if MYSQL_VERSION_ID >= 40108
, stmt(0), meta(0), inBinds(0), outBinds(0)
#endif
- , precisionPolicy(QSql::HighPrecision)
{
connect(dp, SIGNAL(destroyed()), this, SLOT(driverDestroyed()));
}
@@ -180,6 +179,7 @@ public:
const QMYSQLDriver* driver;
MYSQL_RES *result;
MYSQL_ROW row;
+ const QMYSQLResult* q;
int rowsAffected;
@@ -209,7 +209,6 @@ public:
MYSQL_BIND *inBinds;
MYSQL_BIND *outBinds;
#endif
- QSql::NumericalPrecisionPolicy precisionPolicy;
private Q_SLOTS:
void driverDestroyed() { driver = NULL; }
};
@@ -254,6 +253,7 @@ static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags)
break;
case FIELD_TYPE_FLOAT :
case FIELD_TYPE_DOUBLE :
+ case FIELD_TYPE_DECIMAL :
type = QVariant::Double;
break;
case FIELD_TYPE_DATE :
@@ -277,7 +277,6 @@ static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags)
default:
case FIELD_TYPE_ENUM :
case FIELD_TYPE_SET :
- case FIELD_TYPE_DECIMAL :
type = QVariant::String;
break;
}
@@ -354,6 +353,7 @@ bool QMYSQLResultPrivate::bindInValues()
while((fieldInfo = mysql_fetch_field(meta))) {
QMyField &f = fields[i];
f.myField = fieldInfo;
+
f.type = qDecodeMYSQLType(fieldInfo->type, fieldInfo->flags);
if (qIsBlob(fieldInfo->type)) {
// the size of a blob-field is available as soon as we call
@@ -384,7 +384,7 @@ bool QMYSQLResultPrivate::bindInValues()
QMYSQLResult::QMYSQLResult(const QMYSQLDriver* db)
: QSqlResult(db)
{
- d = new QMYSQLResultPrivate(db);
+ d = new QMYSQLResultPrivate(db, this);
}
QMYSQLResult::~QMYSQLResult()
@@ -599,15 +599,16 @@ QVariant QMYSQLResult::data(int field)
case QVariant::Double: {
QVariant v;
bool ok=false;
- switch(d->precisionPolicy) {
+ double dbl = val.toDouble(&ok);
+ switch(numericalPrecisionPolicy()) {
case QSql::LowPrecisionInt32:
- v=val.toInt(&ok);
+ v=QVariant(dbl).toInt();
break;
case QSql::LowPrecisionInt64:
- v = val.toLongLong(&ok);
+ v = QVariant(dbl).toLongLong();
break;
case QSql::LowPrecisionDouble:
- v = val.toDouble(&ok);
+ v = QVariant(dbl);
break;
case QSql::HighPrecision:
default:
@@ -620,6 +621,7 @@ QVariant QMYSQLResult::data(int field)
else
return QVariant();
}
+ return QVariant(val.toDouble());
case QVariant::Date:
return qDateFromString(val);
case QVariant::Time:
@@ -679,6 +681,7 @@ bool QMYSQLResult::reset (const QString& query)
setSelect(numFields != 0);
d->fields.resize(numFields);
d->rowsAffected = mysql_affected_rows(d->driver->d->mysql);
+
if (isSelect()) {
for(int i = 0; i < numFields; i++) {
MYSQL_FIELD* field = mysql_fetch_field_direct(d->result, i);
@@ -813,10 +816,6 @@ void QMYSQLResult::virtual_hook(int id, void *data)
Q_ASSERT(data);
*static_cast<bool*>(data) = nextResult();
break;
- case QSqlResult::SetNumericalPrecision:
- Q_ASSERT(data);
- d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
- break;
default:
QSqlResult::virtual_hook(id, data);
}
@@ -1148,7 +1147,6 @@ bool QMYSQLDriver::hasFeature(DriverFeature f) const
case NamedPlaceholders:
case BatchOperations:
case SimpleLocking:
- case LowPrecisionNumbers:
case EventNotifications:
case FinishQuery:
return false;
@@ -1156,6 +1154,7 @@ bool QMYSQLDriver::hasFeature(DriverFeature f) const
case BLOB:
case LastInsertId:
case Unicode:
+ case LowPrecisionNumbers:
return true;
case PreparedQueries:
case PositionalPlaceholders:
@@ -1369,6 +1368,7 @@ QSqlRecord QMYSQLDriver::record(const QString& tablename) const
return info;
}
MYSQL_FIELD* field;
+
while ((field = mysql_fetch_field(r)))
info.append(qToField(field, d->tc));
mysql_free_result(r);
@@ -1485,4 +1485,4 @@ bool QMYSQLDriver::isIdentifierEscapedImplementation(const QString &identifier,
QT_END_NAMESPACE
-#include "qsql_mysql.moc" \ No newline at end of file
+#include "qsql_mysql.moc"
diff --git a/src/sql/drivers/mysql/qsql_mysql.h b/src/sql/drivers/mysql/qsql_mysql.h
index 31d9dcf..3c27d16 100644
--- a/src/sql/drivers/mysql/qsql_mysql.h
+++ b/src/sql/drivers/mysql/qsql_mysql.h
@@ -69,6 +69,7 @@ class QSqlRecordInfo;
class QMYSQLResult : public QSqlResult
{
friend class QMYSQLDriver;
+ friend class QMYSQLResultPrivate;
public:
explicit QMYSQLResult(const QMYSQLDriver* db);
~QMYSQLResult();
diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp
index e6ee63d..0f45aad 100644
--- a/src/sql/drivers/oci/qsql_oci.cpp
+++ b/src/sql/drivers/oci/qsql_oci.cpp
@@ -148,7 +148,6 @@ struct QOCIResultPrivate
bool transaction;
int serverVersion;
int prefetchRows, prefetchMem;
- QSql::NumericalPrecisionPolicy precisionPolicy;
void setCharset(OCIBind* hbnd);
void setStatementAttributes();
@@ -405,7 +404,6 @@ struct QOCIDriverPrivate
int serverVersion;
ub4 prefetchRows;
ub2 prefetchMem;
- QSql::NumericalPrecisionPolicy precisionPolicy;
QString user;
void allocErrorHandle();
@@ -413,7 +411,7 @@ struct QOCIDriverPrivate
QOCIDriverPrivate::QOCIDriverPrivate()
: env(0), svc(0), srvhp(0), authp(0), err(0), transaction(false), serverVersion(-1),
- prefetchRows(-1), prefetchMem(QOCI_PREFETCH_MEM), precisionPolicy(QSql::HighPrecision)
+ prefetchRows(-1), prefetchMem(QOCI_PREFETCH_MEM)
{
}
@@ -621,136 +619,6 @@ static QSqlField qFromOraInf(const OraFieldInfo &ofi)
return f;
}
-static OraFieldInfo qMakeOraField(const QOCIResultPrivate* p, OCIParam* param)
-{
- OraFieldInfo ofi;
- ub2 colType(0);
- text *colName = 0;
- ub4 colNameLen(0);
- sb1 colScale(0);
- ub2 colLength(0);
- ub2 colFieldLength(0);
- sb2 colPrecision(0);
- ub1 colIsNull(0);
- int r(0);
- QVariant::Type type(QVariant::Invalid);
-
- r = OCIAttrGet(param,
- OCI_DTYPE_PARAM,
- &colType,
- 0,
- OCI_ATTR_DATA_TYPE,
- p->err);
- if (r != 0)
- qOraWarning("qMakeOraField:", p->err);
-
- r = OCIAttrGet(param,
- OCI_DTYPE_PARAM,
- &colName,
- &colNameLen,
- OCI_ATTR_NAME,
- p->err);
- if (r != 0)
- qOraWarning("qMakeOraField:", p->err);
-
- r = OCIAttrGet(param,
- OCI_DTYPE_PARAM,
- &colLength,
- 0,
- OCI_ATTR_DATA_SIZE, /* in bytes */
- p->err);
- if (r != 0)
- qOraWarning("qMakeOraField:", p->err);
-
-#ifdef OCI_ATTR_CHAR_SIZE
- r = OCIAttrGet(param,
- OCI_DTYPE_PARAM,
- &colFieldLength,
- 0,
- OCI_ATTR_CHAR_SIZE,
- p->err);
- if (r != 0)
- qOraWarning("qMakeOraField:", p->err);
-#else
- // for Oracle8.
- colFieldLength = colLength;
-#endif
-
- r = OCIAttrGet(param,
- OCI_DTYPE_PARAM,
- &colPrecision,
- 0,
- OCI_ATTR_PRECISION,
- p->err);
- if (r != 0)
- qOraWarning("qMakeOraField:", p->err);
-
- r = OCIAttrGet(param,
- OCI_DTYPE_PARAM,
- &colScale,
- 0,
- OCI_ATTR_SCALE,
- p->err);
- if (r != 0)
- qOraWarning("qMakeOraField:", p->err);
- r = OCIAttrGet(param,
- OCI_DTYPE_PARAM,
- &colType,
- 0,
- OCI_ATTR_DATA_TYPE,
- p->err);
- if (r != 0)
- qOraWarning("qMakeOraField:", p->err);
- r = OCIAttrGet(param,
- OCI_DTYPE_PARAM,
- &colIsNull,
- 0,
- OCI_ATTR_IS_NULL,
- p->err);
- if (r != 0)
- qOraWarning("qMakeOraField:", p->err);
-
- type = qDecodeOCIType(colType, p->precisionPolicy);
-
- if (type == QVariant::Int) {
- if (colLength == 22 && colPrecision == 0 && colScale == 0)
- type = QVariant::String;
- if (colScale > 0)
- type = QVariant::String;
- }
-
- // bind as double if the precision policy asks for it
- if (((colType == SQLT_FLT) || (colType == SQLT_NUM))
- && (p->precisionPolicy == 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->precisionPolicy == QSql::LowPrecisionInt64)
- type = QVariant::LongLong;
- else if (p->precisionPolicy == QSql::LowPrecisionInt32)
- type = QVariant::Int;
- }
-
- if (colType == SQLT_BLOB)
- colLength = 0;
-
- // colNameLen is length in bytes
- ofi.name = QString(reinterpret_cast<const QChar*>(colName), colNameLen / 2);
- ofi.type = type;
- ofi.oraType = colType;
- ofi.oraFieldLength = colFieldLength;
- ofi.oraLength = colLength;
- ofi.oraScale = colScale;
- ofi.oraPrecision = colPrecision;
- ofi.oraIsNull = colIsNull;
-
- return ofi;
-}
-
-
/*!
\internal
@@ -806,6 +674,7 @@ public:
private:
char* create(int position, int size);
OCILobLocator ** createLobLocator(int position, OCIEnv* env);
+ OraFieldInfo qMakeOraField(const QOCIResultPrivate* p, OCIParam* param) const;
class OraFieldInf
{
@@ -1137,6 +1006,135 @@ int QOCICols::readPiecewise(QVector<QVariant> &values, int index)
return r;
}
+OraFieldInfo QOCICols::qMakeOraField(const QOCIResultPrivate* p, OCIParam* param) const
+{
+ OraFieldInfo ofi;
+ ub2 colType(0);
+ text *colName = 0;
+ ub4 colNameLen(0);
+ sb1 colScale(0);
+ ub2 colLength(0);
+ ub2 colFieldLength(0);
+ sb2 colPrecision(0);
+ ub1 colIsNull(0);
+ int r(0);
+ QVariant::Type type(QVariant::Invalid);
+
+ r = OCIAttrGet(param,
+ OCI_DTYPE_PARAM,
+ &colType,
+ 0,
+ OCI_ATTR_DATA_TYPE,
+ p->err);
+ if (r != 0)
+ qOraWarning("qMakeOraField:", p->err);
+
+ r = OCIAttrGet(param,
+ OCI_DTYPE_PARAM,
+ &colName,
+ &colNameLen,
+ OCI_ATTR_NAME,
+ p->err);
+ if (r != 0)
+ qOraWarning("qMakeOraField:", p->err);
+
+ r = OCIAttrGet(param,
+ OCI_DTYPE_PARAM,
+ &colLength,
+ 0,
+ OCI_ATTR_DATA_SIZE, /* in bytes */
+ p->err);
+ if (r != 0)
+ qOraWarning("qMakeOraField:", p->err);
+
+#ifdef OCI_ATTR_CHAR_SIZE
+ r = OCIAttrGet(param,
+ OCI_DTYPE_PARAM,
+ &colFieldLength,
+ 0,
+ OCI_ATTR_CHAR_SIZE,
+ p->err);
+ if (r != 0)
+ qOraWarning("qMakeOraField:", p->err);
+#else
+ // for Oracle8.
+ colFieldLength = colLength;
+#endif
+
+ r = OCIAttrGet(param,
+ OCI_DTYPE_PARAM,
+ &colPrecision,
+ 0,
+ OCI_ATTR_PRECISION,
+ p->err);
+ if (r != 0)
+ qOraWarning("qMakeOraField:", p->err);
+
+ r = OCIAttrGet(param,
+ OCI_DTYPE_PARAM,
+ &colScale,
+ 0,
+ OCI_ATTR_SCALE,
+ p->err);
+ if (r != 0)
+ qOraWarning("qMakeOraField:", p->err);
+ r = OCIAttrGet(param,
+ OCI_DTYPE_PARAM,
+ &colType,
+ 0,
+ OCI_ATTR_DATA_TYPE,
+ p->err);
+ if (r != 0)
+ qOraWarning("qMakeOraField:", p->err);
+ r = OCIAttrGet(param,
+ OCI_DTYPE_PARAM,
+ &colIsNull,
+ 0,
+ OCI_ATTR_IS_NULL,
+ p->err);
+ if (r != 0)
+ qOraWarning("qMakeOraField:", p->err);
+
+ type = qDecodeOCIType(colType, p->q->numericalPrecisionPolicy());
+
+ if (type == QVariant::Int) {
+ if (colLength == 22 && colPrecision == 0 && colScale == 0)
+ type = QVariant::String;
+ if (colScale > 0)
+ type = QVariant::String;
+ }
+
+ // bind as double if the precision policy asks for it
+ if (((colType == SQLT_FLT) || (colType == SQLT_NUM))
+ && (p->q->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)
+ type = QVariant::LongLong;
+ else if (p->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
+ type = QVariant::Int;
+ }
+
+ if (colType == SQLT_BLOB)
+ colLength = 0;
+
+ // colNameLen is length in bytes
+ ofi.name = QString(reinterpret_cast<const QChar*>(colName), colNameLen / 2);
+ ofi.type = type;
+ ofi.oraType = colType;
+ ofi.oraFieldLength = colFieldLength;
+ ofi.oraLength = colLength;
+ ofi.oraScale = colScale;
+ ofi.oraPrecision = colPrecision;
+ ofi.oraIsNull = colIsNull;
+
+ return ofi;
+}
+
struct QOCIBatchColumn
{
inline QOCIBatchColumn()
@@ -1580,19 +1578,19 @@ void QOCICols::getValues(QVector<QVariant> &v, int index)
case QVariant::Double:
case QVariant::Int:
case QVariant::LongLong:
- if (d->precisionPolicy != QSql::HighPrecision) {
- if ((d->precisionPolicy == QSql::LowPrecisionDouble)
+ if (d->q->numericalPrecisionPolicy() != QSql::HighPrecision) {
+ if ((d->q->numericalPrecisionPolicy() == QSql::LowPrecisionDouble)
&& (fld.typ == QVariant::Double)) {
v[index + i] = *reinterpret_cast<double *>(fld.data);
break;
- } else if ((d->precisionPolicy == QSql::LowPrecisionInt64)
+ } else if ((d->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
&& (fld.typ == QVariant::LongLong)) {
qint64 qll = 0;
OCINumberToInt(d->err, reinterpret_cast<OCINumber *>(fld.data), sizeof(qint64),
OCI_NUMBER_SIGNED, &qll);
v[index + i] = qll;
break;
- } else if ((d->precisionPolicy == QSql::LowPrecisionInt32)
+ } else if ((d->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
&& (fld.typ == QVariant::Int)) {
v[index + i] = *reinterpret_cast<int *>(fld.data);
break;
@@ -1618,8 +1616,7 @@ 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),
- precisionPolicy(driver->precisionPolicy)
+ prefetchRows(driver->prefetchRows), prefetchMem(driver->prefetchMem)
{
int r = OCIHandleAlloc(env,
reinterpret_cast<void **>(&err),
@@ -1901,9 +1898,6 @@ void QOCIResult::virtual_hook(int id, void *data)
case QSqlResult::BatchOperation:
QOCICols::execBatch(d, boundValues(), *reinterpret_cast<bool *>(data));
break;
- case QSqlResult::SetNumericalPrecision:
- d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
- break;
default:
QSqlResult::virtual_hook(id, data);
}
@@ -2314,7 +2308,7 @@ QSqlRecord QOCIDriver::record(const QString& tablename) const
<< QLatin1String("BINARY_DOUBLE");
if (buildRecordInfo) {
do {
- QVariant::Type ty = qDecodeOCIType(t.value(1).toString(),t.numericalPrecisionPolicy());
+ QVariant::Type ty = qDecodeOCIType(t.value(1).toString(), t.numericalPrecisionPolicy());
QSqlField f(t.value(0).toString(), ty);
f.setRequired(t.value(5).toString() == QLatin1String("N"));
f.setPrecision(t.value(4).toInt());
diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp
index 8eaa8bf..f60c33c 100644
--- a/src/sql/drivers/odbc/qsql_odbc.cpp
+++ b/src/sql/drivers/odbc/qsql_odbc.cpp
@@ -127,7 +127,7 @@ class QODBCPrivate
{
public:
QODBCPrivate()
- : hEnv(0), hDbc(0), hStmt(0), useSchema(false), hasSQLFetchScroll(true), precisionPolicy(QSql::HighPrecision)
+ : hEnv(0), hDbc(0), hStmt(0), useSchema(false), hasSQLFetchScroll(true)
{
sql_char_type = sql_varchar_type = sql_longvarchar_type = QVariant::ByteArray;
unicode = false;
@@ -151,7 +151,6 @@ public:
int fieldCacheIdx;
int disconnectCount;
bool hasSQLFetchScroll;
- QSql::NumericalPrecisionPolicy precisionPolicy;
bool isStmtHandleValid(const QSqlDriver *driver);
void updateStmtHandleState(const QSqlDriver *driver);
@@ -444,6 +443,26 @@ static QVariant qGetIntData(SQLHANDLE hStmt, int column, bool isSigned = true)
return uint(intbuf);
}
+static QVariant qGetDoubleData(SQLHANDLE hStmt, int column)
+{
+ SQLDOUBLE dblbuf;
+ SQLINTEGER lengthIndicator = 0;
+ SQLRETURN r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_DOUBLE,
+ (SQLPOINTER) &dblbuf,
+ 0,
+ &lengthIndicator);
+ if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
+ return QVariant(QVariant::Invalid);
+ }
+ if(lengthIndicator == SQL_NULL_DATA)
+ return QVariant(QVariant::Double);
+
+ return (double) dblbuf;
+}
+
+
static QVariant qGetBigIntData(SQLHANDLE hStmt, int column, bool isSigned = true)
{
SQLBIGINT lngbuf = 0;
@@ -1109,29 +1128,21 @@ QVariant QODBCResult::data(int field)
d->fieldCache[i] = qGetStringData(d->hStmt, i, info.length(), true);
break;
case QVariant::Double:
- {
- QString value=qGetStringData(d->hStmt, i, info.length(), false);
- bool ok=false;
- switch(d->precisionPolicy) {
- case QSql::LowPrecisionInt32:
- d->fieldCache[i] = value.toInt(&ok);
- break;
- case QSql::LowPrecisionInt64:
- d->fieldCache[i] = value.toLongLong(&ok);
- break;
- case QSql::LowPrecisionDouble:
- d->fieldCache[i] = value.toDouble(&ok);
- break;
- case QSql::HighPrecision:
- default:
- d->fieldCache[i] = value;
- ok=true;
- break;
- }
- if(ok==false)
- d->fieldCache[i] = QVariant();
- break;
+ switch(numericalPrecisionPolicy()) {
+ case QSql::LowPrecisionInt32:
+ d->fieldCache[i] = qGetIntData(d->hStmt, i);
+ break;
+ case QSql::LowPrecisionInt64:
+ d->fieldCache[i] = qGetBigIntData(d->hStmt, i);
+ break;
+ case QSql::LowPrecisionDouble:
+ d->fieldCache[i] = qGetDoubleData(d->hStmt, i);
+ break;
+ case QSql::HighPrecision:
+ d->fieldCache[i] = qGetStringData(d->hStmt, i, info.length(), false);
+ break;
}
+ break;
default:
d->fieldCache[i] = QVariant(qGetStringData(d->hStmt, i, info.length(), false));
break;
@@ -1628,10 +1639,6 @@ void QODBCResult::virtual_hook(int id, void *data)
Q_ASSERT(data);
*static_cast<bool*>(data) = nextResult();
break;
- case QSqlResult::SetNumericalPrecision:
- Q_ASSERT(data);
- d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
- break;
default:
QSqlResult::virtual_hook(id, data);
}
diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp
index ce0b8c5..169a371 100644
--- a/src/sql/drivers/psql/qsql_psql.cpp
+++ b/src/sql/drivers/psql/qsql_psql.cpp
@@ -136,13 +136,12 @@ void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type)
class QPSQLResultPrivate
{
public:
- QPSQLResultPrivate(QPSQLResult *qq): q(qq), driver(0), result(0), currentSize(-1), precisionPolicy(QSql::HighPrecision) {}
+ QPSQLResultPrivate(QPSQLResult *qq): q(qq), driver(0), result(0), currentSize(-1) {}
QPSQLResult *q;
const QPSQLDriverPrivate *driver;
PGresult *result;
int currentSize;
- QSql::NumericalPrecisionPolicy precisionPolicy;
bool preparedQueriesEnabled;
QString preparedStmtId;
@@ -320,15 +319,16 @@ QVariant QPSQLResult::data(int i)
return atoi(val);
case QVariant::Double:
if (ptype == QNUMERICOID) {
- if (d->precisionPolicy != QSql::HighPrecision) {
+ if (numericalPrecisionPolicy() != QSql::HighPrecision) {
QVariant retval;
bool convert;
- if (d->precisionPolicy == QSql::LowPrecisionInt64)
- retval = QString::fromAscii(val).toLongLong(&convert);
- else if (d->precisionPolicy == QSql::LowPrecisionInt32)
- retval = QString::fromAscii(val).toInt(&convert);
- else if (d->precisionPolicy == QSql::LowPrecisionDouble)
- retval = QString::fromAscii(val).toDouble(&convert);
+ double dbl=QString::fromAscii(val).toDouble(&convert);
+ if (numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
+ retval = (qlonglong)dbl;
+ else if (numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
+ retval = (int)dbl;
+ else if (numericalPrecisionPolicy() == QSql::LowPrecisionDouble)
+ retval = dbl;
if (!convert)
return QVariant();
return retval;
@@ -467,9 +467,6 @@ void QPSQLResult::virtual_hook(int id, void *data)
Q_ASSERT(data);
switch (id) {
- case QSqlResult::SetNumericalPrecision:
- d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
- break;
default:
QSqlResult::virtual_hook(id, data);
}
diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp
index 05d63ca..0f6fb25 100644
--- a/src/sql/drivers/sqlite/qsql_sqlite.cpp
+++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp
@@ -115,13 +115,12 @@ public:
uint skipRow: 1; // skip the next fetchNext()?
uint utf8: 1;
QSqlRecord rInf;
- QSql::NumericalPrecisionPolicy precisionPolicy;
};
static const uint initial_cache_size = 128;
QSQLiteResultPrivate::QSQLiteResultPrivate(QSQLiteResult* res) : q(res), access(0),
- stmt(0), skippedStatus(false), skipRow(false), utf8(false), precisionPolicy(QSql::HighPrecision)
+ stmt(0), skippedStatus(false), skipRow(false), utf8(false)
{
}
@@ -212,7 +211,7 @@ bool QSQLiteResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int i
values[i + idx] = sqlite3_column_int64(stmt, i);
break;
case SQLITE_FLOAT:
- switch(precisionPolicy) {
+ switch(q->numericalPrecisionPolicy()) {
case QSql::LowPrecisionInt32:
values[i + idx] = sqlite3_column_int(stmt, i);
break;
@@ -289,10 +288,6 @@ void QSQLiteResult::virtual_hook(int id, void *data)
if (d->stmt)
sqlite3_reset(d->stmt);
break;
- case QSqlResult::SetNumericalPrecision:
- Q_ASSERT(data);
- d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
- break;
default:
QSqlResult::virtual_hook(id, data);
}
@@ -481,11 +476,11 @@ bool QSQLiteDriver::hasFeature(DriverFeature f) const
case PositionalPlaceholders:
case SimpleLocking:
case FinishQuery:
+ case LowPrecisionNumbers:
return true;
case QuerySize:
case NamedPlaceholders:
case BatchOperations:
- case LowPrecisionNumbers:
case EventNotifications:
case MultipleResultSets:
return false;
diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp
index cb72ff0..bd7c367 100644
--- a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp
+++ b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp
@@ -114,13 +114,12 @@ public:
uint skipRow: 1; // skip the next fetchNext()?
uint utf8: 1;
QSqlRecord rInf;
- QSql::NumericalPrecisionPolicy precisionPolicy;
};
static const uint initial_cache_size = 128;
QSQLite2ResultPrivate::QSQLite2ResultPrivate(QSQLite2Result* res) : q(res), access(0), currentTail(0),
- currentMachine(0), skippedStatus(false), skipRow(false), utf8(false), precisionPolicy(QSql::HighPrecision)
+ currentMachine(0), skippedStatus(false), skipRow(false), utf8(false)
{
}
@@ -260,10 +259,6 @@ void QSQLite2Result::virtual_hook(int id, void *data)
case QSqlResult::DetachFromResultSet:
d->finalize();
break;
- case QSqlResult::SetNumericalPrecision:
- Q_ASSERT(data);
- d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
- break;
default:
QSqlResult::virtual_hook(id, data);
}
diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp
index a270c0e..990ad9a 100644
--- a/src/sql/kernel/qsqldatabase.cpp
+++ b/src/sql/kernel/qsqldatabase.cpp
@@ -129,11 +129,16 @@ Q_GLOBAL_STATIC(QConnectionDict, dbDict)
class QSqlDatabasePrivate
{
public:
- QSqlDatabasePrivate(QSqlDriver *dr = 0):
+ QSqlDatabasePrivate(QSqlDatabase *d, QSqlDriver *dr = 0):
+ q(d),
driver(dr),
port(-1)
{
ref = 1;
+ if(driver)
+ precisionPolicy = driver->numericalPrecisionPolicy();
+ else
+ precisionPolicy= QSql::LowPrecisionDouble;
}
QSqlDatabasePrivate(const QSqlDatabasePrivate &other);
~QSqlDatabasePrivate();
@@ -142,6 +147,7 @@ public:
void disable();
QAtomicInt ref;
+ QSqlDatabase *q;
QSqlDriver* driver;
QString dbname;
QString uname;
@@ -151,6 +157,7 @@ public:
int port;
QString connOptions;
QString connName;
+ QSql::NumericalPrecisionPolicy precisionPolicy;
static QSqlDatabasePrivate *shared_null();
static QSqlDatabase database(const QString& name, bool open);
@@ -164,6 +171,7 @@ public:
QSqlDatabasePrivate::QSqlDatabasePrivate(const QSqlDatabasePrivate &other)
{
ref = 1;
+ q = other.q;
dbname = other.dbname;
uname = other.uname;
pword = other.pword;
@@ -172,6 +180,7 @@ QSqlDatabasePrivate::QSqlDatabasePrivate(const QSqlDatabasePrivate &other)
port = other.port;
connOptions = other.connOptions;
driver = other.driver;
+ precisionPolicy = other.precisionPolicy;
}
QSqlDatabasePrivate::~QSqlDatabasePrivate()
@@ -216,7 +225,7 @@ DriverDict &QSqlDatabasePrivate::driverDict()
QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null()
{
static QSqlNullDriver dr;
- static QSqlDatabasePrivate n(&dr);
+ static QSqlDatabasePrivate n(NULL, &dr);
return &n;
}
@@ -281,6 +290,7 @@ QSqlDatabase QSqlDatabasePrivate::database(const QString& name, bool open)
*/
void QSqlDatabasePrivate::copy(const QSqlDatabasePrivate *other)
{
+ q = other->q;
dbname = other->dbname;
uname = other->uname;
pword = other->pword;
@@ -288,6 +298,7 @@ void QSqlDatabasePrivate::copy(const QSqlDatabasePrivate *other)
drvName = other->drvName;
port = other->port;
connOptions = other->connOptions;
+ precisionPolicy = other->precisionPolicy;
}
void QSqlDatabasePrivate::disable()
@@ -658,7 +669,7 @@ QStringList QSqlDatabase::connectionNames()
QSqlDatabase::QSqlDatabase(const QString &type)
{
- d = new QSqlDatabasePrivate();
+ d = new QSqlDatabasePrivate(this);
d->init(type);
}
@@ -670,7 +681,7 @@ QSqlDatabase::QSqlDatabase(const QString &type)
QSqlDatabase::QSqlDatabase(QSqlDriver *driver)
{
- d = new QSqlDatabasePrivate(driver);
+ d = new QSqlDatabasePrivate(this, driver);
}
/*!
@@ -1469,6 +1480,42 @@ QString QSqlDatabase::connectionName() const
return d->connName;
}
+/*!
+
+ Sets the default numerical precision policy that queries use when created
+ on this database connection.
+
+ Note: Drivers that don't support fetching numerical values with low
+ precision will ignore the precision policy. You can use
+ QSqlDriver::hasFeature() to find out whether a driver supports this
+ feature.
+
+ Note: Setting the default precision policy doesn't affect any currently
+ active queries.
+
+ \sa QSql::NumericalPrecisionPolicy, numericalPrecisionPolicy(), QSqlQuery::setNumericalPrecisionPolicy(), QSqlQuery::numericalPrecisionPolicy()
+*/
+void QSqlDatabase::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)
+{
+ if(driver())
+ driver()->setNumericalPrecisionPolicy(precisionPolicy);
+ d->precisionPolicy = precisionPolicy;
+}
+
+/*!
+ Returns the current default precision policy for the database connection.
+
+ \sa QSql::NumericalPrecisionPolicy, setNumericalPrecisionPolicy(), QSqlQuery::numericalPrecisionPolicy(), QSqlQuery::setNumericalPrecisionPolicy()
+*/
+QSql::NumericalPrecisionPolicy QSqlDatabase::numericalPrecisionPolicy() const
+{
+ if(driver())
+ return driver()->numericalPrecisionPolicy();
+ else
+ return d->precisionPolicy;
+}
+
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QSqlDatabase &d)
{
diff --git a/src/sql/kernel/qsqldatabase.h b/src/sql/kernel/qsqldatabase.h
index ca6f0b0..638a8a5 100644
--- a/src/sql/kernel/qsqldatabase.h
+++ b/src/sql/kernel/qsqldatabase.h
@@ -120,6 +120,8 @@ public:
int port() const;
QString connectOptions() const;
QString connectionName() const;
+ void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy);
+ QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const;
QSqlDriver* driver() const;
diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp
index 477d531..f7492c3 100644
--- a/src/sql/kernel/qsqldriver.cpp
+++ b/src/sql/kernel/qsqldriver.cpp
@@ -72,10 +72,11 @@ public:
uint isOpen : 1;
uint isOpenError : 1;
QSqlError error;
+ QSql::NumericalPrecisionPolicy precisionPolicy;
};
inline QSqlDriverPrivate::QSqlDriverPrivate()
- : QObjectPrivate(), isOpen(false), isOpenError(false)
+ : QObjectPrivate(), isOpen(false), isOpenError(false), precisionPolicy(QSql::LowPrecisionDouble)
{
}
@@ -912,4 +913,29 @@ QString QSqlDriver::stripDelimitersImplementation(const QString &identifier, Ide
return ret;
}
+/*!
+
+ Sets the default numerical precision policy that queries use when created
+ by this driver.
+
+ Note: Setting the default precision policy doesn't affect any currently
+ active queries.
+
+ \sa QSql::NumericalPrecisionPolicy, numericalPrecisionPolicy(), QSqlQuery::setNumericalPrecisionPolicy(), QSqlQuery::numericalPrecisionPolicy()
+*/
+void QSqlDriver::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)
+{
+ d_func()->precisionPolicy = precisionPolicy;
+}
+
+/*!
+ Returns the current default precision policy for the database connection.
+
+ \sa QSql::NumericalPrecisionPolicy, setNumericalPrecisionPolicy(), QSqlQuery::numericalPrecisionPolicy(), QSqlQuery::setNumericalPrecisionPolicy()
+*/
+QSql::NumericalPrecisionPolicy QSqlDriver::numericalPrecisionPolicy() const
+{
+ return d_func()->precisionPolicy;
+}
+
QT_END_NAMESPACE
diff --git a/src/sql/kernel/qsqldriver.h b/src/sql/kernel/qsqldriver.h
index 8ac1471..1b52437 100644
--- a/src/sql/kernel/qsqldriver.h
+++ b/src/sql/kernel/qsqldriver.h
@@ -130,6 +130,9 @@ public:
bool isIdentifierEscaped(const QString &identifier, IdentifierType type) const; // ### Qt 5: make virtual
QString stripDelimiters(const QString &identifier, IdentifierType type) const; // ### Qt 5: make virtual
+ void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy);
+ QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const;
+
Q_SIGNALS:
void notification(const QString &name);
diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp
index 2a07e28..2e531b4 100644
--- a/src/sql/kernel/qsqlquery.cpp
+++ b/src/sql/kernel/qsqlquery.cpp
@@ -61,7 +61,6 @@ public:
~QSqlQueryPrivate();
QAtomicInt ref;
QSqlResult* sqlResult;
- QSql::NumericalPrecisionPolicy precisionPolicy;
static QSqlQueryPrivate* shared_null();
};
@@ -81,7 +80,7 @@ QSqlQueryPrivate* QSqlQueryPrivate::shared_null()
\internal
*/
QSqlQueryPrivate::QSqlQueryPrivate(QSqlResult* result)
- : ref(1), sqlResult(result), precisionPolicy(QSql::HighPrecision)
+ : ref(1), sqlResult(result)
{
if (!sqlResult)
sqlResult = nullResult();
@@ -351,14 +350,14 @@ bool QSqlQuery::exec(const QString& query)
if (d->ref != 1) {
bool fo = isForwardOnly();
*this = QSqlQuery(driver()->createResult());
- d->sqlResult->setNumericalPrecisionPolicy(d->precisionPolicy);
+ d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy());
setForwardOnly(fo);
} else {
d->sqlResult->clear();
d->sqlResult->setActive(false);
d->sqlResult->setLastError(QSqlError());
d->sqlResult->setAt(QSql::BeforeFirstRow);
- d->sqlResult->setNumericalPrecisionPolicy(d->precisionPolicy);
+ d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy());
}
d->sqlResult->setQuery(query.trimmed());
if (!driver()->isOpen() || driver()->isOpenError()) {
@@ -891,12 +890,12 @@ bool QSqlQuery::prepare(const QString& query)
bool fo = isForwardOnly();
*this = QSqlQuery(driver()->createResult());
setForwardOnly(fo);
- d->sqlResult->setNumericalPrecisionPolicy(d->precisionPolicy);
+ d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy());
} else {
d->sqlResult->setActive(false);
d->sqlResult->setLastError(QSqlError());
d->sqlResult->setAt(QSql::BeforeFirstRow);
- d->sqlResult->setNumericalPrecisionPolicy(d->precisionPolicy);
+ d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy());
}
if (!driver()) {
qWarning("QSqlQuery::prepare: no driver");
@@ -1126,10 +1125,10 @@ QVariant QSqlQuery::lastInsertId() const
Instruct the database driver to return numerical values with a
precision specified by \a precisionPolicy.
- The Oracle driver, for example, retrieves numerical values as
- strings by default to prevent the loss of precision. If the high
- precision doesn't matter, use this method to increase execution
- speed by bypassing string conversions.
+ The Oracle driver, for example, can retrieve numerical values as
+ strings to prevent the loss of precision. If high precision doesn't
+ matter, use this method to increase execution speed by bypassing
+ string conversions.
Note: Drivers that don't support fetching numerical values with low
precision will ignore the precision policy. You can use
@@ -1144,7 +1143,7 @@ QVariant QSqlQuery::lastInsertId() const
*/
void QSqlQuery::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)
{
- d->precisionPolicy = precisionPolicy;
+ d->sqlResult->setNumericalPrecisionPolicy(precisionPolicy);
}
/*!
@@ -1154,7 +1153,7 @@ void QSqlQuery::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy preci
*/
QSql::NumericalPrecisionPolicy QSqlQuery::numericalPrecisionPolicy() const
{
- return d->precisionPolicy;
+ return d->sqlResult->numericalPrecisionPolicy();
}
/*!
diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp
index 180bfc7..a621b24 100644
--- a/src/sql/kernel/qsqlresult.cpp
+++ b/src/sql/kernel/qsqlresult.cpp
@@ -48,6 +48,7 @@
#include "qsqlresult.h"
#include "qvector.h"
#include "qsqldriver.h"
+#include <QDebug>
QT_BEGIN_NAMESPACE
@@ -64,7 +65,7 @@ class QSqlResultPrivate
public:
QSqlResultPrivate(QSqlResult* d)
: q(d), sqldriver(0), idx(QSql::BeforeFirstRow), active(false),
- isSel(false), forwardOnly(false), bindCount(0), binds(QSqlResult::PositionalBinding)
+ isSel(false), forwardOnly(false), precisionPolicy(QSql::LowPrecisionDouble), bindCount(0), binds(QSqlResult::PositionalBinding)
{}
void clearValues()
@@ -104,6 +105,7 @@ public:
bool isSel;
QSqlError error;
bool forwardOnly;
+ QSql::NumericalPrecisionPolicy precisionPolicy;
int bindCount;
QSqlResult::BindingSyntax binds;
@@ -249,6 +251,9 @@ QSqlResult::QSqlResult(const QSqlDriver *db)
{
d = new QSqlResultPrivate(this);
d->sqldriver = db;
+ if(db) {
+ setNumericalPrecisionPolicy(db->numericalPrecisionPolicy());
+ }
}
/*!
@@ -965,8 +970,14 @@ void QSqlResult::detachFromResultSet()
*/
void QSqlResult::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy)
{
- if (driver()->hasFeature(QSqlDriver::LowPrecisionNumbers))
- virtual_hook(SetNumericalPrecision, &policy);
+ d->precisionPolicy = policy;
+}
+
+/*! \internal
+ */
+QSql::NumericalPrecisionPolicy QSqlResult::numericalPrecisionPolicy() const
+{
+ return d->precisionPolicy;
}
/*! \internal
diff --git a/src/sql/kernel/qsqlresult.h b/src/sql/kernel/qsqlresult.h
index 0a3d8b9..30c933b 100644
--- a/src/sql/kernel/qsqlresult.h
+++ b/src/sql/kernel/qsqlresult.h
@@ -135,6 +135,7 @@ protected:
bool execBatch(bool arrayBind = false);
void detachFromResultSet();
void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy);
+ QSql::NumericalPrecisionPolicy numericalPrecisionPolicy() const;
bool nextResult();
private: