Changeset 561 for trunk/src/sql/drivers


Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/sql/drivers/db2/qsql_db2.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5050#include <qvarlengtharray.h>
    5151#include <qvector.h>
    52 
    53 #ifndef UNICODE
    54 #define UNICODE
    55 #endif
     52#include <QDebug>
    5653
    5754#if defined(Q_CC_BOR)
     
    6360#endif
    6461
     62#define UNICODE
     63
    6564#include <sqlcli1.h>
    6665
     
    8483{
    8584public:
    86     QDB2ResultPrivate(const QDB2DriverPrivate* d): dp(d), hStmt(0), precisionPolicy(QSql::HighPrecision)
     85    QDB2ResultPrivate(const QDB2DriverPrivate* d): dp(d), hStmt(0)
    8786    {}
    8887    ~QDB2ResultPrivate()
    8988    {
    90         for (int i = 0; i < valueCache.count(); ++i)
     89        emptyValueCache();
     90    }
     91    void clearValueCache()
     92    {
     93        for (int i = 0; i < valueCache.count(); ++i) {
    9194            delete valueCache[i];
     95            valueCache[i] = NULL;
     96        }
     97    }
     98    void emptyValueCache()
     99    {
     100        clearValueCache();
     101        valueCache.clear();
    92102    }
    93103
     
    96106    QSqlRecord recInf;
    97107    QVector<QVariant*> valueCache;
    98     QSql::NumericalPrecisionPolicy precisionPolicy;
    99108};
    100109
    101110static QString qFromTChar(SQLTCHAR* str)
    102111{
    103 #ifdef UNICODE
    104112    return QString::fromUtf16(str);
    105 #else
    106     return QString::fromLocal8Bit((const char*) str);
    107 #endif
    108113}
    109114
     
    112117static SQLTCHAR* qToTChar(const QString& str)
    113118{
    114 #ifdef UNICODE
    115119    return (SQLTCHAR*)str.utf16();
    116 #else
    117     return (unsigned char*) str.ascii();
    118 #endif
    119120}
    120121
     
    337338    while (true) {
    338339        r = SQLGetData(hStmt,
    339                         column+1,
    340 #ifdef UNICODE
     340                        column + 1,
    341341                        SQL_C_WCHAR,
    342 #else
    343                         SQL_C_CHAR,
    344 #endif
    345342                        (SQLPOINTER)buf,
    346343                        colSize * sizeof(SQLTCHAR),
     
    545542
    546543    d->recInf.clear();
    547     d->valueCache.clear();
     544    d->emptyValueCache();
    548545
    549546    if (!qMakeStatement(d, isForwardOnly()))
     
    569566    }
    570567    d->valueCache.resize(count);
     568    d->valueCache.fill(NULL);
    571569    setActive(true);
    572570    return true;
     
    580578
    581579    d->recInf.clear();
    582     d->valueCache.clear();
     580    d->emptyValueCache();
    583581
    584582    if (!qMakeStatement(d, isForwardOnly()))
     
    608606
    609607    d->recInf.clear();
    610     d->valueCache.clear();
     608    d->emptyValueCache();
    611609
    612610    if (!qMakeStatement(d, isForwardOnly(), false))
     
    729727                break; }
    730728            case QVariant::String:
    731 #ifdef UNICODE
    732729            {
    733730                QString str(values.at(i).toString());
     
    763760                break;
    764761            }
    765 #endif
    766             // fall through
    767762            default: {
    768763                QByteArray ba = values.at(i).toString().toAscii();
     
    812807    setActive(true);
    813808    d->valueCache.resize(count);
     809    d->valueCache.fill(NULL);
    814810
    815811    //get out parameters
     
    837833                break;
    838834            case QVariant::String:
    839 #ifdef UNICODE
    840835                if (bindValueType(i) & QSql::Out)
    841836                    values[i] = QString::fromUtf16((ushort*)tmpStorage.takeFirst().constData());
    842837                break;
    843 #endif
    844                 // fall through
    845838            default: {
    846839                values[i] = QString::fromAscii(tmpStorage.takeFirst().constData());
     
    859852    if (i == at())
    860853        return true;
    861     d->valueCache.fill(0);
     854    d->clearValueCache();
    862855    int actualIdx = i + 1;
    863856    if (actualIdx <= 0) {
     
    876869                            actualIdx);
    877870    }
    878     if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
     871    if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r != SQL_NO_DATA) {
    879872        setLastError(qMakeError(QCoreApplication::translate("QDB2Result",
    880873                                "Unable to fetch record %1").arg(i), QSqlError::StatementError, d));
    881874        return false;
    882875    }
     876    else if (r == SQL_NO_DATA)
     877        return false;
    883878    setAt(i);
    884879    return true;
     
    888883{
    889884    SQLRETURN r;
    890     d->valueCache.fill(0);
     885    d->clearValueCache();
    891886    r = SQLFetchScroll(d->hStmt,
    892887                       SQL_FETCH_NEXT,
     
    908903    if (isForwardOnly())
    909904        return fetchNext();
    910     d->valueCache.fill(0);
     905    d->clearValueCache();
    911906    SQLRETURN r;
    912907    r = SQLFetchScroll(d->hStmt,
     
    914909                       0);
    915910    if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
    916         setLastError(qMakeError(QCoreApplication::translate("QDB2Result", "Unable to fetch first"),
    917                                 QSqlError::StatementError, d));
     911        if(r!= SQL_NO_DATA)
     912            setLastError(qMakeError(QCoreApplication::translate("QDB2Result", "Unable to fetch first"),
     913                                    QSqlError::StatementError, d));
    918914        return false;
    919915    }
     
    924920bool QDB2Result::fetchLast()
    925921{
    926     d->valueCache.fill(0);
     922    d->clearValueCache();
    927923
    928924    int i = at();
     
    10301026        case QVariant::Double:
    10311027            {
    1032             QString value=qGetStringData(d->hStmt, field, info.length() + 1, isNull);
    1033             bool ok=false;
    1034             switch(d->precisionPolicy) {
     1028            switch(numericalPrecisionPolicy()) {
    10351029                case QSql::LowPrecisionInt32:
    1036                     v = new QVariant(value.toInt(&ok));
     1030                    v = new QVariant(qGetIntData(d->hStmt, field, isNull));
    10371031                    break;
    10381032                case QSql::LowPrecisionInt64:
    1039                     v = new QVariant(value.toLongLong(&ok));
     1033                    v = new QVariant(qGetBigIntData(d->hStmt, field, isNull));
    10401034                    break;
    10411035                case QSql::LowPrecisionDouble:
    1042                     v = new QVariant(value.toDouble(&ok));
     1036                    v = new QVariant(qGetDoubleData(d->hStmt, field, isNull));
    10431037                    break;
    10441038                case QSql::HighPrecision:
     
    10461040                    // length + 1 for the comma
    10471041                    v = new QVariant(qGetStringData(d->hStmt, field, info.length() + 1, isNull));
    1048                     ok = true;
    10491042                    break;
    10501043            }
    1051             if(!ok)
    1052                 v = new QVariant();
    10531044            break;
    10541045            }
     
    11021093    setAt(QSql::BeforeFirstRow);
    11031094    d->recInf.clear();
    1104     d->valueCache.clear();
     1095    d->emptyValueCache();
    11051096    setSelect(false);
    11061097
     
    11211112
    11221113    d->valueCache.resize(fieldCount);
     1114    d->valueCache.fill(NULL);
    11231115    setActive(true);
    11241116
     
    11331125        *static_cast<bool*>(data) = nextResult();
    11341126        break;
    1135     case QSqlResult::SetNumericalPrecision:
    1136         Q_ASSERT(data);
    1137         d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
     1127    case QSqlResult::DetachFromResultSet:
     1128        if (d->hStmt)
     1129            SQLCloseCursor(d->hStmt);
    11381130        break;
    11391131    default:
     
    11681160}
    11691161
    1170 bool QDB2Driver::open(const QString& db, const QString& user, const QString& password, const QString&, int,
     1162bool QDB2Driver::open(const QString& db, const QString& user, const QString& password, const QString& host, int port,
    11711163                       const QString& connOpts)
    11721164{
     
    11911183        return false;
    11921184    }
     1185
     1186    QString protocol;
    11931187    // Set connection attributes
    11941188    const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts));
     
    12211215            v = val.toUInt();
    12221216            r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) v, 0);
    1223         } else {
     1217        } else if (opt.compare(QLatin1String("PROTOCOL"), Qt::CaseInsensitive) == 0) {
     1218                        protocol = tmp;
     1219        }
     1220        else {
    12241221            qWarning("QDB2Driver::open: Unknown connection attribute '%s'",
    12251222                      tmp.toLocal8Bit().constData());
     
    12301227    }
    12311228
     1229    if (protocol.isEmpty())
     1230        protocol = QLatin1String("PROTOCOL=TCPIP");
     1231
     1232    if (port < 0 )
     1233        port = 50000;
     1234
    12321235    QString connQStr;
    1233     connQStr = QLatin1String("DSN=") + db + QLatin1String(";UID=") + user + QLatin1String(";PWD=")
    1234                + password;
     1236    connQStr =  protocol + QLatin1String(";DATABASE=") + db + QLatin1String(";HOSTNAME=") + host
     1237        + QLatin1String(";PORT=") + QString::number(port) + QLatin1String(";UID=") + user
     1238        + QLatin1String(";PWD=") + password;
     1239
     1240
    12351241    SQLTCHAR connOut[SQL_MAX_OPTION_STRING_LENGTH];
    12361242    SQLSMALLINT cb;
     
    12511257    }
    12521258
    1253     d->user = user.toUpper();
     1259    d->user = user;
    12541260    setOpen(true);
    12551261    setOpenError(false);
     
    12961302    SQLHANDLE hStmt;
    12971303    QString catalog, schema, table;
    1298     qSplitTableQualifier(tableName.toUpper(), &catalog, &schema, &table);
     1304    qSplitTableQualifier(tableName, &catalog, &schema, &table);
    12991305    if (schema.isEmpty())
    13001306        schema = d->user;
     1307
     1308    if (isIdentifierEscaped(catalog, QSqlDriver::TableName))
     1309        catalog = stripDelimiters(catalog, QSqlDriver::TableName);
     1310    else
     1311        catalog = catalog.toUpper();
     1312
     1313    if (isIdentifierEscaped(schema, QSqlDriver::TableName))
     1314        schema = stripDelimiters(schema, QSqlDriver::TableName);
     1315    else
     1316        schema = schema.toUpper();
     1317
     1318    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     1319        table = stripDelimiters(table, QSqlDriver::TableName);
     1320    else
     1321        table = table.toUpper();
    13011322
    13021323    SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT,
     
    13131334                        SQL_IS_UINTEGER);
    13141335
     1336
     1337    //Aside: szSchemaName and szTableName parameters of SQLColumns
     1338    //are case sensitive search patterns, so no escaping is used.
    13151339    r =  SQLColumns(hStmt,
    13161340                     NULL,
     
    13931417        QString fieldVal = qGetStringData(hStmt, 2, -1, isNull);
    13941418        QString userVal = qGetStringData(hStmt, 1, -1, isNull);
    1395         if (userVal != d->user)
     1419        QString user = d->user;
     1420        if ( isIdentifierEscaped(user, QSqlDriver::TableName))
     1421            user = stripDelimiters(user, QSqlDriver::TableName);
     1422        else
     1423            user = user.toUpper();
     1424
     1425        if (userVal != user)
    13961426            fieldVal = userVal + QLatin1Char('.') + fieldVal;
    13971427        tl.append(fieldVal);
     
    14241454    }
    14251455    QString catalog, schema, table;
    1426     qSplitTableQualifier(tablename.toUpper(), &catalog, &schema, &table);
     1456    qSplitTableQualifier(tablename, &catalog, &schema, &table);
     1457
     1458    if (isIdentifierEscaped(catalog, QSqlDriver::TableName))
     1459        catalog = stripDelimiters(catalog, QSqlDriver::TableName);
     1460    else
     1461        catalog = catalog.toUpper();
     1462
     1463    if (isIdentifierEscaped(schema, QSqlDriver::TableName))
     1464        schema = stripDelimiters(schema, QSqlDriver::TableName);
     1465    else
     1466        schema = schema.toUpper();
     1467
     1468    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     1469        table = stripDelimiters(table, QSqlDriver::TableName);
     1470    else
     1471        table = table.toUpper();
     1472
    14271473    r = SQLSetStmtAttr(hStmt,
    14281474                        SQL_ATTR_CURSOR_TYPE,
     
    14681514        case LastInsertId:
    14691515        case SimpleLocking:
    1470         case LowPrecisionNumbers:
    14711516        case EventNotifications:
    14721517            return false;
     
    14761521        case PreparedQueries:
    14771522        case PositionalPlaceholders:
     1523        case LowPrecisionNumbers:
     1524        case FinishQuery:
    14781525            return true;
    14791526        case Unicode:
    1480         // this is the query that shows the codepage for the types:
    1481         // select typename, codepage from syscat.datatypes
    1482 #ifdef UNICODE
    14831527            return true;
    1484 #else
    1485             return false;
    1486 #endif
    14871528    }
    14881529    return false;
     
    15981639{
    15991640    QString res = identifier;
    1600     if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
     1641    if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
    16011642        res.replace(QLatin1Char('"'), QLatin1String("\"\""));
    16021643        res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
  • trunk/src/sql/drivers/db2/qsql_db2.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/sql/drivers/ibase/qsql_ibase.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5656#include <math.h>
    5757#include <qdebug.h>
     58#include <QVarLengthArray>
    5859
    5960QT_BEGIN_NAMESPACE
     
    6768enum { QIBaseChunkSize = SHRT_MAX / 2 };
    6869
    69 static bool getIBaseError(QString& msg, ISC_STATUS* status, ISC_LONG &sqlcode,
    70                           QTextCodec *tc)
     70#if defined(FB_API_VER) && FB_API_VER >= 20
     71static bool getIBaseError(QString& msg, const ISC_STATUS* status, ISC_LONG &sqlcode, QTextCodec *tc)
     72#else
     73static bool getIBaseError(QString& msg, ISC_STATUS* status, ISC_LONG &sqlcode, QTextCodec *tc)
     74#endif
    7175{
    7276    if (status[0] != 1 || status[1] <= 0)
     
    7680    sqlcode = isc_sqlcode(status);
    7781    char buf[512];
     82#if defined(FB_API_VER) && FB_API_VER >= 20
     83    while(fb_interpret(buf, 512, &status)) {
     84#else
    7885    while(isc_interprete(buf, &status)) {
     86#endif
    7987        if(!msg.isEmpty())
    8088            msg += QLatin1String(" - ");
     
    9098{
    9199    sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(1));
     100    if (sqlda == (XSQLDA*)0) return;
    92101    sqlda->sqln = 1;
    93102    sqlda->sqld = 0;
     
    99108static void enlargeDA(XSQLDA *&sqlda, int n)
    100109{
    101     free(sqlda);
     110    if (sqlda != (XSQLDA*)0)
     111        free(sqlda);
    102112    sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(n));
     113    if (sqlda == (XSQLDA*)0) return;
    103114    sqlda->sqln = n;
    104115    sqlda->version = SQLDA_CURRENT_VERSION;
     
    119130        case SQL_TEXT:
    120131        case SQL_BLOB:
    121             sqlda->sqlvar[i].sqldata = (char*)malloc(sqlda->sqlvar[i].sqllen);
     132            sqlda->sqlvar[i].sqldata = new char[sqlda->sqlvar[i].sqllen];
    122133            break;
    123134        case SQL_ARRAY:
    124             sqlda->sqlvar[i].sqldata = (char*)malloc(sizeof(ISC_QUAD));
     135            sqlda->sqlvar[i].sqldata = new char[sizeof(ISC_QUAD)];
    125136            memset(sqlda->sqlvar[i].sqldata, 0, sizeof(ISC_QUAD));
    126137            break;
    127138        case SQL_VARYING:
    128             sqlda->sqlvar[i].sqldata = (char*)malloc(sqlda->sqlvar[i].sqllen + sizeof(short));
     139            sqlda->sqlvar[i].sqldata = new char[sqlda->sqlvar[i].sqllen + sizeof(short)];
    129140            break;
    130141        default:
     
    134145        }
    135146        if (sqlda->sqlvar[i].sqltype & 1) {
    136             sqlda->sqlvar[i].sqlind = (short*)malloc(sizeof(short));
     147            sqlda->sqlvar[i].sqlind = new short[1];
    137148            *(sqlda->sqlvar[i].sqlind) = 0;
    138149        } else {
     
    147158        return;
    148159    for (int i = 0; i < sqlda->sqld; ++i) {
    149         free(sqlda->sqlvar[i].sqlind);
    150         free(sqlda->sqlvar[i].sqldata);
     160        delete [] sqlda->sqlvar[i].sqlind;
     161        delete [] sqlda->sqlvar[i].sqldata;
    151162    }
    152163    free(sqlda);
     
    293304    ISC_LONG bufferLength;
    294305    ISC_LONG eventId;
    295    
     306
    296307    enum QIBaseSubscriptionState { Starting, Subscribed, Finished };
    297308    QIBaseSubscriptionState subscriptionState;
     
    444455    ba.resize(read);
    445456
    446     bool isErr = (status[1] == isc_segstr_eof ? false : 
    447                     isError(QT_TRANSLATE_NOOP("QIBaseResult", 
     457    bool isErr = (status[1] == isc_segstr_eof ? false :
     458                    isError(QT_TRANSLATE_NOOP("QIBaseResult",
    448459                                                "Unable to read BLOB"),
    449460                                                QSqlError::StatementError));
     
    512523                    else
    513524                        valList.append(QString::fromUtf8(buffer, o));
    514                    
     525
    515526                    buffer += strLen;
    516527                }
     
    577588    int arraySize = 1, subArraySize;
    578589    short dimensions = desc.array_desc_dimensions;
    579     short *numElements = new short[dimensions];
     590    QVarLengthArray<short> numElements(dimensions);
    580591
    581592    for(int i = 0; i < dimensions; ++i) {
     
    606617        return list;
    607618
    608     readArrayBuffer(list, ba.data(), 0, numElements, &desc, tc);
    609 
    610     delete[] numElements;
     619    readArrayBuffer(list, ba.data(), 0, numElements.data(), &desc, tc);
    611620
    612621    return QVariant(list);
     
    639648}
    640649
    641 static char* qFillBufferWithString(char *buffer, const QString& string, 
    642                                    short buflen, bool varying, bool array, 
     650static char* qFillBufferWithString(char *buffer, const QString& string,
     651                                   short buflen, bool varying, bool array,
    643652                                   QTextCodec *tc)
    644653{
     
    872881bool QIBaseResult::prepare(const QString& query)
    873882{
    874     //qDebug("prepare: %s\n", qPrintable(query));
     883//     qDebug("prepare: %s", qPrintable(query));
    875884    if (!driver() || !driver()->isOpen() || driver()->isOpenError())
    876885        return false;
     
    880889
    881890    createDA(d->sqlda);
     891    if (d->sqlda == (XSQLDA*)0) {
     892        qWarning()<<"QIOBaseResult: createDA(): failed to allocate memory";
     893        return false;
     894    }
     895
    882896    createDA(d->inda);
     897    if (d->inda == (XSQLDA*)0){
     898        qWarning()<<"QIOBaseResult: createDA():  failed to allocate memory";
     899        return false;
     900    }
    883901
    884902    if (!d->transaction())
     
    901919    if (d->inda->sqld > d->inda->sqln) {
    902920        enlargeDA(d->inda, d->inda->sqld);
     921        if (d->inda == (XSQLDA*)0) {
     922            qWarning()<<"QIOBaseResult: enlargeDA(): failed to allocate memory";
     923            return false;
     924        }
    903925
    904926        isc_dsql_describe_bind(d->status, &d->stmt, FBVERSION, d->inda);
     
    911933        // need more field descriptors
    912934        enlargeDA(d->sqlda, d->sqlda->sqld);
     935        if (d->sqlda == (XSQLDA*)0) {
     936            qWarning()<<"QIOBaseResult: enlargeDA(): failed to allocate memory";
     937            return false;
     938        }
    913939
    914940        isc_dsql_describe(d->status, &d->stmt, FBVERSION, d->sqlda);
     
    9781004            case SQL_LONG:
    9791005                if (d->inda->sqlvar[para].sqlscale < 0)
    980                     *((long*)d->inda->sqlvar[para].sqldata) = 
     1006                    *((long*)d->inda->sqlvar[para].sqldata) =
    9811007                        (long)floor(0.5 + val.toDouble() * pow(10.0, d->inda->sqlvar[para].sqlscale * -1));
    9821008                else
     
    9851011            case SQL_SHORT:
    9861012                if (d->inda->sqlvar[para].sqlscale < 0)
    987                     *((short*)d->inda->sqlvar[para].sqldata) = 
     1013                    *((short*)d->inda->sqlvar[para].sqldata) =
    9881014                        (short)floor(0.5 + val.toDouble() * pow(10.0, d->inda->sqlvar[para].sqlscale * -1));
    9891015                else
     
    10261052
    10271053    if (ok) {
    1028         if (colCount()) {
     1054        if (colCount() && d->queryType != isc_info_sql_stmt_exec_procedure) {
    10291055            isc_dsql_free_statement(d->status, &d->stmt, DSQL_close);
    10301056            if (d->isError(QT_TRANSLATE_NOOP("QIBaseResult", "Unable to close statement")))
     
    10401066
    10411067        // Not all stored procedures necessarily return values.
    1042         if (d->queryType == isc_info_sql_stmt_exec_procedure && d->sqlda->sqld == 0)
     1068        if (d->queryType == isc_info_sql_stmt_exec_procedure && d->sqlda && d->sqlda->sqld == 0)
    10431069            delDA(d->sqlda);
    10441070
     
    10981124            QVariant v;
    10991125            v.convert(qIBaseTypeName2(d->sqlda->sqlvar[i].sqltype, d->sqlda->sqlvar[i].sqlscale < 0));
     1126            if(v.type() == QVariant::Double) {
     1127                switch(numericalPrecisionPolicy()) {
     1128                case QSql::LowPrecisionInt32:
     1129                    v.convert(QVariant::Int);
     1130                    break;
     1131                case QSql::LowPrecisionInt64:
     1132                    v.convert(QVariant::LongLong);
     1133                    break;
     1134                case QSql::HighPrecision:
     1135                    v.convert(QVariant::String);
     1136                    break;
     1137                }
     1138            }
    11001139            row[idx] = v;
    11011140            continue;
     
    11621201            row[idx] = QVariant();
    11631202            break;
     1203        }
     1204        if (d->sqlda->sqlvar[i].sqlscale < 0) {
     1205            QVariant v = row[idx];
     1206            switch(numericalPrecisionPolicy()) {
     1207            case QSql::LowPrecisionInt32:
     1208                if(v.convert(QVariant::Int))
     1209                    row[idx]=v;
     1210                break;
     1211            case QSql::LowPrecisionInt64:
     1212                if(v.convert(QVariant::LongLong))
     1213                    row[idx]=v;
     1214                break;
     1215            case QSql::LowPrecisionDouble:
     1216                if(v.convert(QVariant::Double))
     1217                    row[idx]=v;
     1218                break;
     1219            case QSql::HighPrecision:
     1220                if(v.convert(QVariant::String))
     1221                    row[idx]=v;
     1222                break;
     1223            }
    11641224        }
    11651225    }
     
    12371297        cCountType = isc_info_req_insert_count;
    12381298        break;
     1299    default:
     1300        qWarning() << "numRowsAffected: Unknown statement type (" << d->queryType << ")";
     1301        return -1;
    12391302    }
    12401303
     
    12711334        QSqlField f(QString::fromLatin1(v.aliasname, v.aliasname_length).simplified(),
    12721335                    qIBaseTypeName2(v.sqltype, v.sqlscale < 0));
    1273         QSqlQuery q(new QIBaseResult(d->db));
    1274         q.setForwardOnly(true);
    1275         q.exec(QLatin1String("select b.RDB$FIELD_PRECISION, b.RDB$FIELD_SCALE, b.RDB$FIELD_LENGTH, a.RDB$NULL_FLAG "
    1276                 "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b "
    1277                 "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE "
    1278                 "AND a.RDB$RELATION_NAME = '") + QString::fromAscii(v.relname, v.relname_length).toUpper() + QLatin1String("' "
    1279                 "AND a.RDB$FIELD_NAME = '") + QString::fromAscii(v.sqlname, v.sqlname_length).toUpper() + QLatin1String("' "));
    1280         if(q.first()) {
    1281             if(v.sqlscale < 0) {
    1282                 f.setLength(q.value(0).toInt());
    1283                 f.setPrecision(qAbs(q.value(1).toInt()));
    1284             } else {
    1285                 f.setLength(q.value(2).toInt());
    1286                 f.setPrecision(0);
     1336        f.setLength(v.sqllen);
     1337        f.setPrecision(qAbs(v.sqlscale));
     1338        f.setRequiredStatus((v.sqltype & 1) == 0 ? QSqlField::Required : QSqlField::Optional);
     1339        if(v.sqlscale < 0) {
     1340            QSqlQuery q(new QIBaseResult(d->db));
     1341            q.setForwardOnly(true);
     1342            q.exec(QLatin1String("select b.RDB$FIELD_PRECISION, b.RDB$FIELD_SCALE, b.RDB$FIELD_LENGTH, a.RDB$NULL_FLAG "
     1343                    "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b "
     1344                    "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE "
     1345                    "AND a.RDB$RELATION_NAME = '") + QString::fromAscii(v.relname, v.relname_length).toUpper() + QLatin1String("' "
     1346                    "AND a.RDB$FIELD_NAME = '") + QString::fromAscii(v.sqlname, v.sqlname_length).toUpper() + QLatin1String("' "));
     1347            if(q.first()) {
     1348                if(v.sqlscale < 0) {
     1349                    f.setLength(q.value(0).toInt());
     1350                    f.setPrecision(qAbs(q.value(1).toInt()));
     1351                } else {
     1352                    f.setLength(q.value(2).toInt());
     1353                    f.setPrecision(0);
     1354                }
     1355                f.setRequiredStatus(q.value(3).toBool() ? QSqlField::Required : QSqlField::Optional);
    12871356            }
    1288             f.setRequiredStatus(q.value(3).toBool() ? QSqlField::Required : QSqlField::Optional);
    1289         }
    1290         else {
    1291             f.setLength(0);
    1292             f.setPrecision(0);
    1293             f.setRequiredStatus(QSqlField::Unknown);
    12941357        }
    12951358        f.setSqlType(v.sqltype);
     
    13341397    case BatchOperations:
    13351398    case SimpleLocking:
    1336     case LowPrecisionNumbers:
    13371399    case FinishQuery:
    13381400    case MultipleResultSets:
     
    13441406    case BLOB:
    13451407    case EventNotifications:
     1408    case LowPrecisionNumbers:
    13461409        return true;
    13471410    }
     
    15531616    QSqlQuery q(createResult());
    15541617    q.setForwardOnly(true);
    1555 
     1618    QString table = tablename;
     1619    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     1620        table = stripDelimiters(table, QSqlDriver::TableName);
     1621    else
     1622        table = table.toUpper();
    15561623    q.exec(QLatin1String("SELECT a.RDB$FIELD_NAME, b.RDB$FIELD_TYPE, b.RDB$FIELD_LENGTH, "
    15571624           "b.RDB$FIELD_SCALE, b.RDB$FIELD_PRECISION, a.RDB$NULL_FLAG "
    15581625           "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b "
    15591626           "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE "
    1560            "AND a.RDB$RELATION_NAME = '") + tablename.toUpper() + QLatin1String("' "
     1627           "AND a.RDB$RELATION_NAME = '") + table + QLatin1String("' "
    15611628           "ORDER BY a.RDB$FIELD_POSITION"));
    15621629
     
    15861653        return index;
    15871654
     1655    QString tablename = table;
     1656    if (isIdentifierEscaped(tablename, QSqlDriver::TableName))
     1657        tablename = stripDelimiters(tablename, QSqlDriver::TableName);
     1658    else
     1659        tablename = tablename.toUpper();
     1660
    15881661    QSqlQuery q(createResult());
    15891662    q.setForwardOnly(true);
     
    15911664           "FROM RDB$RELATION_CONSTRAINTS a, RDB$INDEX_SEGMENTS b, RDB$RELATION_FIELDS c, RDB$FIELDS d "
    15921665           "WHERE a.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' "
    1593            "AND a.RDB$RELATION_NAME = '") + table.toUpper() +
     1666           "AND a.RDB$RELATION_NAME = '") + tablename +
    15941667           QLatin1String(" 'AND a.RDB$INDEX_NAME = b.RDB$INDEX_NAME "
    15951668           "AND c.RDB$RELATION_NAME = a.RDB$RELATION_NAME "
     
    16681741    QIBaseDriver *driver = qBufferDriverMap()->value(result);
    16691742    qMutex()->unlock();
    1670    
     1743
    16711744    // We use an asynchronous call (i.e., queued connection) because the event callback
    16721745    // is executed in a different thread than the one in which the driver lives.
     
    17171790
    17181791    if (status[0] == 1 && status[1]) {
    1719         setLastError(QSqlError(QString(QLatin1String("Could not subscribe to event notifications for %1.")).arg(name)));
     1792        setLastError(QSqlError(QString::fromLatin1("Could not subscribe to event notifications for %1.").arg(name)));
    17201793        d->eventBuffers.remove(name);
    17211794        qFreeEventBuffer(eBuffer);
     
    17451818
    17461819    if (status[0] == 1 && status[1]) {
    1747         setLastError(QSqlError(QString(QLatin1String("Could not unsubscribe from event notifications for %1.")).arg(name)));
     1820        setLastError(QSqlError(QString::fromLatin1("Could not unsubscribe from event notifications for %1.").arg(name)));
    17481821        return false;
    17491822    }
     
    18031876{
    18041877    QString res = identifier;
    1805     if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
     1878    if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
    18061879        res.replace(QLatin1Char('"'), QLatin1String("\"\""));
    18071880        res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
  • trunk/src/sql/drivers/ibase/qsql_ibase.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/sql/drivers/mysql/qsql_mysql.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    8686        tc(0),
    8787#endif
    88         preparedQuerys(false), preparedQuerysEnabled(false) {}
     88        preparedQuerysEnabled(false) {}
    8989    MYSQL *mysql;
    9090    QTextCodec *tc;
    9191
    92     bool preparedQuerys;
    9392    bool preparedQuerysEnabled;
    9493};
     
    164163}
    165164
    166 class QMYSQLResultPrivate
    167 {
     165class QMYSQLResultPrivate : public QObject
     166{
     167    Q_OBJECT
    168168public:
    169     QMYSQLResultPrivate(QMYSQLDriverPrivate* dp) : d(dp), result(0),
     169    QMYSQLResultPrivate(const QMYSQLDriver* dp, const QMYSQLResult* d) : driver(dp), result(0), q(d),
    170170        rowsAffected(0), hasBlobs(false)
    171171#if MYSQL_VERSION_ID >= 40108
    172172        , stmt(0), meta(0), inBinds(0), outBinds(0)
    173173#endif
    174         , precisionPolicy(QSql::HighPrecision)
    175         {}
    176 
    177     QMYSQLDriverPrivate* d;
     174        , preparedQuery(false)
     175        {
     176            connect(dp, SIGNAL(destroyed()), this, SLOT(driverDestroyed()));
     177        }
     178
     179    const QMYSQLDriver* driver;
    178180    MYSQL_RES *result;
    179181    MYSQL_ROW row;
     182    const QMYSQLResult* q;
    180183
    181184    int rowsAffected;
     
    207210    MYSQL_BIND *outBinds;
    208211#endif
    209     QSql::NumericalPrecisionPolicy precisionPolicy;
     212
     213    bool preparedQuery;
     214
     215private Q_SLOTS:
     216    void driverDestroyed() { driver = NULL; }
    210217};
    211218
     
    225232                            const QMYSQLDriverPrivate* p)
    226233{
    227     const char *cerr = mysql_error(p->mysql);
     234    const char *cerr = p->mysql ? mysql_error(p->mysql) : 0;
    228235    return QSqlError(QLatin1String("QMYSQL: ") + err,
    229236                     p->tc ? toUnicode(p->tc, cerr) : QString::fromLatin1(cerr),
     
    250257    case FIELD_TYPE_FLOAT :
    251258    case FIELD_TYPE_DOUBLE :
     259    case FIELD_TYPE_DECIMAL :
     260#if defined(FIELD_TYPE_NEWDECIMAL)
     261    case FIELD_TYPE_NEWDECIMAL:
     262#endif
    252263        type = QVariant::Double;
    253264        break;
     
    273284    case FIELD_TYPE_ENUM :
    274285    case FIELD_TYPE_SET :
    275     case FIELD_TYPE_DECIMAL :
    276286        type = QVariant::String;
    277287        break;
     
    350360        QMyField &f = fields[i];
    351361        f.myField = fieldInfo;
     362
    352363        f.type = qDecodeMYSQLType(fieldInfo->type, fieldInfo->flags);
    353364        if (qIsBlob(fieldInfo->type)) {
     
    380391: QSqlResult(db)
    381392{
    382     d = new QMYSQLResultPrivate(db->d);
     393    d = new QMYSQLResultPrivate(db, this);
    383394}
    384395
     
    392403{
    393404#if MYSQL_VERSION_ID >= 40108
    394     if(d->d->preparedQuerys)
     405    if(d->preparedQuery)
    395406        return d->meta ? qVariantFromValue(d->meta) : qVariantFromValue(d->stmt);
    396407    else
     
    407418// if this isn't done subsequent queries will fail with "Commands out of sync"
    408419#if MYSQL_VERSION_ID >= 40100
    409     while (d->d->mysql && mysql_next_result(d->d->mysql) == 0) {
    410         MYSQL_RES *res = mysql_store_result(d->d->mysql);
     420    while (d->driver && d->driver->d->mysql && mysql_next_result(d->driver->d->mysql) == 0) {
     421        MYSQL_RES *res = mysql_store_result(d->driver->d->mysql);
    411422        if (res)
    412423            mysql_free_result(res);
     
    447458    setAt(-1);
    448459    setActive(false);
    449 
    450     d->d->preparedQuerys = d->d->preparedQuerysEnabled;
    451460}
    452461
    453462bool QMYSQLResult::fetch(int i)
    454463{
     464    if(!d->driver)
     465        return false;
    455466    if (isForwardOnly()) { // fake a forward seek
    456467        if (at() < i) {
     
    464475    if (at() == i)
    465476        return true;
    466     if (d->d->preparedQuerys) {
     477    if (d->preparedQuery) {
    467478#if MYSQL_VERSION_ID >= 40108
    468479        mysql_stmt_data_seek(d->stmt, i);
     
    495506bool QMYSQLResult::fetchNext()
    496507{
    497     if (d->d->preparedQuerys) {
     508    if(!d->driver)
     509        return false;
     510    if (d->preparedQuery) {
    498511#if MYSQL_VERSION_ID >= 40108
    499         if (mysql_stmt_fetch(d->stmt))
     512        int nRC = mysql_stmt_fetch(d->stmt);
     513        if (nRC) {
     514#ifdef MYSQL_DATA_TRUNCATED
     515            if (nRC == 1 || nRC == MYSQL_DATA_TRUNCATED)
     516#else
     517            if (nRC == 1)
     518#endif // MYSQL_DATA_TRUNCATED
     519                setLastError(qMakeStmtError(QCoreApplication::translate("QMYSQLResult",
     520                                    "Unable to fetch data"), QSqlError::StatementError, d->stmt));
    500521            return false;
     522        }
    501523#else
    502524        return false;
    503525#endif
    504526    } else {
    505     d->row = mysql_fetch_row(d->result);
    506     if (!d->row)
    507         return false;
     527        d->row = mysql_fetch_row(d->result);
     528        if (!d->row)
     529            return false;
    508530    }
    509531    setAt(at() + 1);
     
    513535bool QMYSQLResult::fetchLast()
    514536{
     537    if(!d->driver)
     538        return false;
    515539    if (isForwardOnly()) { // fake this since MySQL can't seek on forward only queries
    516540        bool success = fetchNext(); // did we move at all?
     
    520544
    521545    my_ulonglong numRows;
    522     if (d->d->preparedQuerys) {
     546    if (d->preparedQuery) {
    523547#if MYSQL_VERSION_ID >= 40108
    524548        numRows = mysql_stmt_num_rows(d->stmt);
     
    554578    }
    555579
     580    if (!d->driver)
     581        return QVariant();
     582
    556583    int fieldLength = 0;
    557584    const QMYSQLResultPrivate::QMyField &f = d->fields.at(field);
    558585    QString val;
    559     if (d->d->preparedQuerys) {
     586    if (d->preparedQuery) {
    560587        if (f.nullIndicator)
    561588            return QVariant(f.type);
    562589
    563590        if (f.type != QVariant::ByteArray)
    564             val = toUnicode(d->d->tc, f.outField, f.bufLength);
     591            val = toUnicode(d->driver->d->tc, f.outField, f.bufLength);
    565592    } else {
    566593        if (d->row[field] == NULL) {
     
    570597        fieldLength = mysql_fetch_lengths(d->result)[field];
    571598        if (f.type != QVariant::ByteArray)
    572             val = toUnicode(d->d->tc, d->row[field], fieldLength);
     599            val = toUnicode(d->driver->d->tc, d->row[field], fieldLength);
    573600    }
    574601
     
    585612        QVariant v;
    586613        bool ok=false;
    587         switch(d->precisionPolicy) {
     614        double dbl = val.toDouble(&ok);
     615        switch(numericalPrecisionPolicy()) {
    588616            case QSql::LowPrecisionInt32:
    589                 v=val.toInt(&ok);
     617                v=QVariant(dbl).toInt();
    590618                break;
    591619            case QSql::LowPrecisionInt64:
    592                 v = val.toLongLong(&ok);
     620                v = QVariant(dbl).toLongLong();
    593621                break;
    594622            case QSql::LowPrecisionDouble:
    595                 v = val.toDouble(&ok);
     623                v = QVariant(dbl);
    596624                break;
    597625            case QSql::HighPrecision:
     
    606634            return QVariant();
    607635    }
     636        return QVariant(val.toDouble());
    608637    case QVariant::Date:
    609638        return qDateFromString(val);
     
    615644
    616645        QByteArray ba;
    617         if (d->d->preparedQuerys) {
     646        if (d->preparedQuery) {
    618647            ba = QByteArray(f.outField, f.bufLength);
    619648        } else {
     
    632661bool QMYSQLResult::isNull(int field)
    633662{
    634    if (d->d->preparedQuerys)
     663   if (d->preparedQuery)
    635664       return d->fields.at(field).nullIndicator;
    636665   else
     
    640669bool QMYSQLResult::reset (const QString& query)
    641670{
    642     if (!driver() || !driver()->isOpen() || driver()->isOpenError())
    643         return false;
    644 
    645     if(d->d->preparedQuerysEnabled && prepare(query)) {
    646         d->d->preparedQuerys = true;
    647         return exec();
    648     }
    649     d->d->preparedQuerys = false;
    650 
    651     const QByteArray encQuery(fromUnicode(d->d->tc, query));
    652     if (mysql_real_query(d->d->mysql, encQuery.data(), encQuery.length())) {
     671    if (!driver() || !driver()->isOpen() || driver()->isOpenError() || !d->driver)
     672        return false;
     673
     674    d->preparedQuery = false;
     675
     676    cleanup();
     677
     678    const QByteArray encQuery(fromUnicode(d->driver->d->tc, query));
     679    if (mysql_real_query(d->driver->d->mysql, encQuery.data(), encQuery.length())) {
    653680        setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to execute query"),
    654                      QSqlError::StatementError, d->d));
    655         return false;
    656     }
    657     d->result = mysql_store_result(d->d->mysql);
    658     if (!d->result && mysql_field_count(d->d->mysql) > 0) {
     681                     QSqlError::StatementError, d->driver->d));
     682        return false;
     683    }
     684    d->result = mysql_store_result(d->driver->d->mysql);
     685    if (!d->result && mysql_field_count(d->driver->d->mysql) > 0) {
    659686        setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to store result"),
    660                     QSqlError::StatementError, d->d));
    661         return false;
    662     }
    663     int numFields = mysql_field_count(d->d->mysql);
     687                    QSqlError::StatementError, d->driver->d));
     688        return false;
     689    }
     690    int numFields = mysql_field_count(d->driver->d->mysql);
    664691    setSelect(numFields != 0);
    665692    d->fields.resize(numFields);
    666     d->rowsAffected = mysql_affected_rows(d->d->mysql);
     693    d->rowsAffected = mysql_affected_rows(d->driver->d->mysql);
     694
    667695    if (isSelect()) {
    668696        for(int i = 0; i < numFields; i++) {
     
    678706int QMYSQLResult::size()
    679707{
    680     if (isSelect())
    681         if (d->d->preparedQuerys)
     708    if (d->driver && isSelect())
     709        if (d->preparedQuery)
    682710#if MYSQL_VERSION_ID >= 40108
    683711            return mysql_stmt_num_rows(d->stmt);
     
    698726QVariant QMYSQLResult::lastInsertId() const
    699727{
    700     if (!isActive())
     728    if (!isActive() || !d->driver)
    701729        return QVariant();
    702730
    703     if (d->d->preparedQuerys) {
     731    if (d->preparedQuery) {
    704732#if MYSQL_VERSION_ID >= 40108
    705733        quint64 id = mysql_stmt_insert_id(d->stmt);
     
    708736#endif
    709737    } else {
    710         quint64 id = mysql_insert_id(d->d->mysql);
     738        quint64 id = mysql_insert_id(d->driver->d->mysql);
    711739        if (id)
    712740            return QVariant(id);
     
    719747    QSqlRecord info;
    720748    MYSQL_RES *res;
    721     if (!isActive() || !isSelect())
     749    if (!isActive() || !isSelect() || !d->driver)
    722750        return info;
    723751
    724752#if MYSQL_VERSION_ID >= 40108
    725     res = d->d->preparedQuerys ? d->meta : d->result;
     753    res = d->preparedQuery ? d->meta : d->result;
    726754#else
    727755    res = d->result;
    728756#endif
    729757
    730     if (!mysql_errno(d->d->mysql)) {
     758    if (!mysql_errno(d->driver->d->mysql)) {
    731759        mysql_field_seek(res, 0);
    732760        MYSQL_FIELD* field = mysql_fetch_field(res);
    733761        while(field) {
    734             info.append(qToField(field, d->d->tc));
     762            info.append(qToField(field, d->driver->d->tc));
    735763            field = mysql_fetch_field(res);
    736764        }
     
    742770bool QMYSQLResult::nextResult()
    743771{
     772    if(!d->driver)
     773        return false;
    744774#if MYSQL_VERSION_ID >= 40100
    745775    setAt(-1);
     
    755785    d->fields.clear();
    756786
    757     int status = mysql_next_result(d->d->mysql);
     787    int status = mysql_next_result(d->driver->d->mysql);
    758788    if (status > 0) {
    759789        setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to execute next query"),
    760                      QSqlError::StatementError, d->d));
     790                     QSqlError::StatementError, d->driver->d));
    761791        return false;
    762792    } else if (status == -1) {
     
    764794    }
    765795
    766     d->result = mysql_store_result(d->d->mysql);
    767     int numFields = mysql_field_count(d->d->mysql);
     796    d->result = mysql_store_result(d->driver->d->mysql);
     797    int numFields = mysql_field_count(d->driver->d->mysql);
    768798    if (!d->result && numFields > 0) {
    769799        setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to store next result"),
    770                      QSqlError::StatementError, d->d));
     800                     QSqlError::StatementError, d->driver->d));
    771801        return false;
    772802    }
     
    774804    setSelect(numFields > 0);
    775805    d->fields.resize(numFields);
    776     d->rowsAffected = mysql_affected_rows(d->d->mysql);
     806    d->rowsAffected = mysql_affected_rows(d->driver->d->mysql);
    777807
    778808    if (isSelect()) {
     
    797827        *static_cast<bool*>(data) = nextResult();
    798828        break;
    799     case QSqlResult::SetNumericalPrecision:
    800         Q_ASSERT(data);
    801         d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
    802         break;
    803829    default:
    804830        QSqlResult::virtual_hook(id, data);
     
    834860bool QMYSQLResult::prepare(const QString& query)
    835861{
     862    if(!d->driver)
     863        return false;
    836864#if MYSQL_VERSION_ID >= 40108
    837865    cleanup();
    838     if (!d->d->preparedQuerys)
     866    if (!d->driver->d->preparedQuerysEnabled)
    839867        return QSqlResult::prepare(query);
    840868
     
    845873
    846874    if (!d->stmt)
    847         d->stmt = mysql_stmt_init(d->d->mysql);
     875        d->stmt = mysql_stmt_init(d->driver->d->mysql);
    848876    if (!d->stmt) {
    849877        setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to prepare statement"),
    850                      QSqlError::StatementError, d->d));
    851         return false;
    852     }
    853 
    854     const QByteArray encQuery(fromUnicode(d->d->tc, query));
     878                     QSqlError::StatementError, d->driver->d));
     879        return false;
     880    }
     881
     882    const QByteArray encQuery(fromUnicode(d->driver->d->tc, query));
    855883    r = mysql_stmt_prepare(d->stmt, encQuery.constData(), encQuery.length());
    856884    if (r != 0) {
     
    866894
    867895    setSelect(d->bindInValues());
     896    d->preparedQuery = true;
    868897    return true;
    869898#else
     
    874903bool QMYSQLResult::exec()
    875904{
    876     if (!d->d->preparedQuerys)
     905    if (!d->driver)
     906        return false;
     907    if (!d->preparedQuery)
    877908        return QSqlResult::exec();
    878909    if (!d->stmt)
     
    907938            currBind->is_null = &nullVector[i];
    908939            currBind->length = 0;
     940            currBind->is_unsigned = 0;
    909941
    910942            switch (val.type()) {
     
    953985                    currBind->buffer = data;
    954986                    currBind->buffer_length = sizeof(double);
    955                     currBind->is_unsigned = 0;
    956987                    break;
    957988                case QVariant::LongLong:
     
    964995                case QVariant::String:
    965996                default: {
    966                     QByteArray ba = fromUnicode(d->d->tc, val.toString());
     997                    QByteArray ba = fromUnicode(d->driver->d->tc, val.toString());
    967998                    stringVector.append(ba);
    968999                    currBind->buffer_type = MYSQL_TYPE_STRING;
    9691000                    currBind->buffer = const_cast<char *>(ba.constData());
    9701001                    currBind->buffer_length = ba.length();
    971                     currBind->is_unsigned = 0;
    9721002                    break; }
    9731003            }
     
    11291159    case BatchOperations:
    11301160    case SimpleLocking:
    1131     case LowPrecisionNumbers:
    11321161    case EventNotifications:
    11331162    case FinishQuery:
     
    11371166    case LastInsertId:
    11381167    case Unicode:
     1168    case LowPrecisionNumbers:
    11391169        return true;
    11401170    case PreparedQueries:
     
    11931223    const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts));
    11941224    QString unixSocket;
     1225#if MYSQL_VERSION_ID >= 50000
     1226    my_bool reconnect=false;
     1227#endif
    11951228
    11961229    // extract the real options from the string
     
    12031236            if (opt == QLatin1String("UNIX_SOCKET"))
    12041237                unixSocket = val;
     1238#if MYSQL_VERSION_ID >= 50000
     1239            else if (opt == QLatin1String("MYSQL_OPT_RECONNECT")) {
     1240                if (val == QLatin1String("TRUE") || val == QLatin1String("1") || val.isEmpty())
     1241                    reconnect = true;
     1242            }
     1243#endif
    12051244            else if (val == QLatin1String("TRUE") || val == QLatin1String("1"))
    12061245                setOptionFlag(optionFlags, tmp.left(idx).simplified());
     
    12351274            return false;
    12361275        }
     1276#if MYSQL_VERSION_ID >= 50000
     1277        if(reconnect)
     1278            mysql_options(d->mysql, MYSQL_OPT_RECONNECT, &reconnect);
     1279#endif
    12371280    } else {
    12381281        setLastError(qMakeError(tr("Unable to connect"),
     
    12591302#endif
    12601303
     1304#ifndef QT_NO_THREAD
     1305    mysql_thread_init();
     1306#endif
     1307
     1308
    12611309    setOpen(true);
    12621310    setOpenError(false);
     
    12671315{
    12681316    if (isOpen()) {
     1317#ifndef QT_NO_THREAD
     1318        mysql_thread_end();
     1319#endif
    12691320        mysql_close(d->mysql);
    12701321        d->mysql = NULL;
     
    12821333{
    12831334    QStringList tl;
    1284     if (!isOpen())
    1285         return tl;
    1286     if (!(type & QSql::Tables))
    1287         return tl;
    1288 
    1289     MYSQL_RES* tableRes = mysql_list_tables(d->mysql, NULL);
    1290     MYSQL_ROW row;
    1291     int i = 0;
    1292     while (tableRes) {
    1293         mysql_data_seek(tableRes, i);
    1294         row = mysql_fetch_row(tableRes);
    1295         if (!row)
    1296             break;
    1297         tl.append(toUnicode(d->tc, row[0]));
    1298         i++;
    1299     }
    1300     mysql_free_result(tableRes);
     1335#if MYSQL_VERSION_ID >= 40100
     1336    if( mysql_get_server_version(d->mysql) < 50000)
     1337    {
     1338#endif
     1339        if (!isOpen())
     1340            return tl;
     1341        if (!(type & QSql::Tables))
     1342            return tl;
     1343
     1344        MYSQL_RES* tableRes = mysql_list_tables(d->mysql, NULL);
     1345        MYSQL_ROW row;
     1346        int i = 0;
     1347        while (tableRes) {
     1348            mysql_data_seek(tableRes, i);
     1349            row = mysql_fetch_row(tableRes);
     1350            if (!row)
     1351                break;
     1352            tl.append(toUnicode(d->tc, row[0]));
     1353            i++;
     1354        }
     1355        mysql_free_result(tableRes);
     1356#if MYSQL_VERSION_ID >= 40100
     1357    } else {
     1358        QSqlQuery q(createResult());
     1359        if(type & QSql::Tables) {
     1360            q.exec(QLatin1String("select table_name from information_schema.tables where table_type = 'BASE TABLE'"));
     1361            while(q.next())
     1362                tl.append(q.value(0).toString());
     1363        }
     1364        if(type & QSql::Views) {
     1365            q.exec(QLatin1String("select table_name from information_schema.tables where table_type = 'VIEW'"));
     1366            while(q.next())
     1367                tl.append(q.value(0).toString());
     1368        }
     1369    }
     1370#endif
    13011371    return tl;
    13021372}
     
    13051375{
    13061376    QSqlIndex idx;
    1307     bool prepQ;
    13081377    if (!isOpen())
    13091378        return idx;
    1310 
    1311     prepQ = d->preparedQuerys;
    1312     d->preparedQuerys = false;
    13131379
    13141380    QSqlQuery i(createResult());
    13151381    QString stmt(QLatin1String("show index from %1;"));
    13161382    QSqlRecord fil = record(tablename);
    1317     i.exec(stmt.arg(escapeIdentifier(tablename, QSqlDriver::TableName)));
     1383    i.exec(stmt.arg(tablename));
    13181384    while (i.isActive() && i.next()) {
    13191385        if (i.value(2).toString() == QLatin1String("PRIMARY")) {
     
    13241390    }
    13251391
    1326     d->preparedQuerys = prepQ;
    13271392    return idx;
    13281393}
     
    13301395QSqlRecord QMYSQLDriver::record(const QString& tablename) const
    13311396{
     1397    QString table=tablename;
     1398    if(isIdentifierEscaped(table, QSqlDriver::TableName))
     1399        table = stripDelimiters(table, QSqlDriver::TableName);
     1400
    13321401    QSqlRecord info;
    13331402    if (!isOpen())
    13341403        return info;
    1335     MYSQL_RES* r = mysql_list_fields(d->mysql, tablename.toLocal8Bit().constData(), 0);
     1404    MYSQL_RES* r = mysql_list_fields(d->mysql, table.toLocal8Bit().constData(), 0);
    13361405    if (!r) {
    13371406        return info;
    13381407    }
    13391408    MYSQL_FIELD* field;
     1409
    13401410    while ((field = mysql_fetch_field(r)))
    13411411        info.append(qToField(field, d->tc));
     
    14371507{
    14381508    QString res = identifier;
    1439     if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('`')) && identifier.right(1) != QString(QLatin1Char('`')) ) {
     1509    if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('`')) && !identifier.endsWith(QLatin1Char('`')) ) {
    14401510        res.prepend(QLatin1Char('`')).append(QLatin1Char('`'));
    14411511        res.replace(QLatin1Char('.'), QLatin1String("`.`"));
     
    14441514}
    14451515
     1516bool QMYSQLDriver::isIdentifierEscapedImplementation(const QString &identifier, IdentifierType type) const
     1517{
     1518    Q_UNUSED(type);
     1519    return identifier.size() > 2
     1520        && identifier.startsWith(QLatin1Char('`')) //left delimited
     1521        && identifier.endsWith(QLatin1Char('`')); //right delimited
     1522}
     1523
    14461524QT_END_NAMESPACE
     1525
     1526#include "qsql_mysql.moc"
  • trunk/src/sql/drivers/mysql/qsql_mysql.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7070{
    7171    friend class QMYSQLDriver;
     72    friend class QMYSQLResultPrivate;
    7273public:
    7374    explicit QMYSQLResult(const QMYSQLDriver* db);
     
    124125    QString escapeIdentifier(const QString &identifier, IdentifierType type) const;
    125126
     127protected Q_SLOTS:
     128    bool isIdentifierEscapedImplementation(const QString &identifier, IdentifierType type) const;
     129
    126130protected:
    127131    bool beginTransaction();
  • trunk/src/sql/drivers/oci/qsql_oci.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    149149    int serverVersion;
    150150    int prefetchRows, prefetchMem;
    151     QSql::NumericalPrecisionPolicy precisionPolicy;
    152151
    153152    void setCharset(OCIBind* hbnd);
     
    406405    ub4 prefetchRows;
    407406    ub2 prefetchMem;
    408     QSql::NumericalPrecisionPolicy precisionPolicy;
    409407    QString user;
    410408
     
    414412QOCIDriverPrivate::QOCIDriverPrivate()
    415413    : env(0), svc(0), srvhp(0), authp(0), err(0), transaction(false), serverVersion(-1),
    416       prefetchRows(-1), prefetchMem(QOCI_PREFETCH_MEM), precisionPolicy(QSql::HighPrecision)
     414      prefetchRows(-1), prefetchMem(QOCI_PREFETCH_MEM)
    417415{
    418416}
     
    520518    else if (ocitype == QLatin1String("LONG") || ocitype == QLatin1String("NCLOB")
    521519             || ocitype == QLatin1String("CLOB"))
    522         type = QVariant::ByteArray;
     520        type = QVariant::String;
    523521    else if (ocitype == QLatin1String("RAW") || ocitype == QLatin1String("LONG RAW")
    524522             || ocitype == QLatin1String("ROWID") || ocitype == QLatin1String("BLOB")
     
    546544    case SQLT_RDD:
    547545    case SQLT_LNG:
     546    case SQLT_CLOB:
    548547#ifdef SQLT_INTERVAL_YM
    549548    case SQLT_INTERVAL_YM:
     
    587586    case SQLT_REF:
    588587    case SQLT_RID:
    589     case SQLT_CLOB:
    590588        type = QVariant::ByteArray;
    591589        break;
     
    612610    f.setRequired(ofi.oraIsNull == 0);
    613611
    614     if (ofi.type == QVariant::String)
     612    if (ofi.type == QVariant::String && ofi.oraType != SQLT_NUM && ofi.oraType != SQLT_VNU)
    615613        f.setLength(ofi.oraFieldLength);
    616614    else
     
    621619    return f;
    622620}
    623 
    624 static OraFieldInfo qMakeOraField(const QOCIResultPrivate* p, OCIParam* param)
    625 {
    626     OraFieldInfo ofi;
    627     ub2 colType(0);
    628     text *colName = 0;
    629     ub4 colNameLen(0);
    630     sb1 colScale(0);
    631     ub2 colLength(0);
    632     ub2 colFieldLength(0);
    633     sb2 colPrecision(0);
    634     ub1 colIsNull(0);
    635     int r(0);
    636     QVariant::Type type(QVariant::Invalid);
    637 
    638     r = OCIAttrGet(param,
    639                    OCI_DTYPE_PARAM,
    640                    &colType,
    641                    0,
    642                    OCI_ATTR_DATA_TYPE,
    643                    p->err);
    644     if (r != 0)
    645         qOraWarning("qMakeOraField:", p->err);
    646 
    647     r = OCIAttrGet(param,
    648                    OCI_DTYPE_PARAM,
    649                    &colName,
    650                    &colNameLen,
    651                    OCI_ATTR_NAME,
    652                    p->err);
    653     if (r != 0)
    654         qOraWarning("qMakeOraField:", p->err);
    655 
    656     r = OCIAttrGet(param,
    657                    OCI_DTYPE_PARAM,
    658                    &colLength,
    659                    0,
    660                    OCI_ATTR_DATA_SIZE, /* in bytes */
    661                    p->err);
    662     if (r != 0)
    663         qOraWarning("qMakeOraField:", p->err);
    664 
    665 #ifdef OCI_ATTR_CHAR_SIZE
    666     r = OCIAttrGet(param,
    667                    OCI_DTYPE_PARAM,
    668                    &colFieldLength,
    669                    0,
    670                    OCI_ATTR_CHAR_SIZE,
    671                    p->err);
    672     if (r != 0)
    673         qOraWarning("qMakeOraField:", p->err);
    674 #else
    675     // for Oracle8.
    676     colFieldLength = colLength;
    677 #endif
    678 
    679     r = OCIAttrGet(param,
    680                    OCI_DTYPE_PARAM,
    681                    &colPrecision,
    682                    0,
    683                    OCI_ATTR_PRECISION,
    684                    p->err);
    685     if (r != 0)
    686         qOraWarning("qMakeOraField:", p->err);
    687 
    688     r = OCIAttrGet(param,
    689                    OCI_DTYPE_PARAM,
    690                    &colScale,
    691                    0,
    692                    OCI_ATTR_SCALE,
    693                    p->err);
    694     if (r != 0)
    695         qOraWarning("qMakeOraField:", p->err);
    696     r = OCIAttrGet(param,
    697                    OCI_DTYPE_PARAM,
    698                    &colType,
    699                    0,
    700                    OCI_ATTR_DATA_TYPE,
    701                    p->err);
    702     if (r != 0)
    703         qOraWarning("qMakeOraField:", p->err);
    704     r = OCIAttrGet(param,
    705                    OCI_DTYPE_PARAM,
    706                    &colIsNull,
    707                    0,
    708                    OCI_ATTR_IS_NULL,
    709                    p->err);
    710     if (r != 0)
    711         qOraWarning("qMakeOraField:", p->err);
    712 
    713     type = qDecodeOCIType(colType, p->precisionPolicy);
    714 
    715     if (type == QVariant::Int) {
    716         if (colLength == 22 && colPrecision == 0 && colScale == 0)
    717             type = QVariant::String;
    718         if (colScale > 0)
    719             type = QVariant::String;
    720     }
    721 
    722     // bind as double if the precision policy asks for it
    723     if (((colType == SQLT_FLT) || (colType == SQLT_NUM))
    724             && (p->precisionPolicy == QSql::LowPrecisionDouble)) {
    725         type = QVariant::Double;
    726     }
    727 
    728     // bind as int32 or int64 if the precision policy asks for it
    729     if ((colType == SQLT_NUM) || (colType == SQLT_VNU) || (colType == SQLT_UIN)
    730             || (colType == SQLT_INT)) {
    731         if (p->precisionPolicy == QSql::LowPrecisionInt64)
    732             type = QVariant::LongLong;
    733         else if (p->precisionPolicy == QSql::LowPrecisionInt32)
    734             type = QVariant::Int;
    735     }
    736 
    737     if (colType == SQLT_BLOB)
    738         colLength = 0;
    739 
    740     // colNameLen is length in bytes
    741     ofi.name = QString(reinterpret_cast<const QChar*>(colName), colNameLen / 2);
    742     ofi.type = type;
    743     ofi.oraType = colType;
    744     ofi.oraFieldLength = colFieldLength;
    745     ofi.oraLength = colLength;
    746     ofi.oraScale = colScale;
    747     ofi.oraPrecision = colPrecision;
    748     ofi.oraIsNull = colIsNull;
    749 
    750     return ofi;
    751 }
    752 
    753621
    754622/*!
     
    807675    char* create(int position, int size);
    808676    OCILobLocator ** createLobLocator(int position, OCIEnv* env);
     677    OraFieldInfo qMakeOraField(const QOCIResultPrivate* p, OCIParam* param) const;
    809678
    810679    class OraFieldInf
     
    11381007}
    11391008
     1009OraFieldInfo QOCICols::qMakeOraField(const QOCIResultPrivate* p, OCIParam* param) const
     1010{
     1011    OraFieldInfo ofi;
     1012    ub2 colType(0);
     1013    text *colName = 0;
     1014    ub4 colNameLen(0);
     1015    sb1 colScale(0);
     1016    ub2 colLength(0);
     1017    ub2 colFieldLength(0);
     1018    sb2 colPrecision(0);
     1019    ub1 colIsNull(0);
     1020    int r(0);
     1021    QVariant::Type type(QVariant::Invalid);
     1022
     1023    r = OCIAttrGet(param,
     1024                   OCI_DTYPE_PARAM,
     1025                   &colType,
     1026                   0,
     1027                   OCI_ATTR_DATA_TYPE,
     1028                   p->err);
     1029    if (r != 0)
     1030        qOraWarning("qMakeOraField:", p->err);
     1031
     1032    r = OCIAttrGet(param,
     1033                   OCI_DTYPE_PARAM,
     1034                   &colName,
     1035                   &colNameLen,
     1036                   OCI_ATTR_NAME,
     1037                   p->err);
     1038    if (r != 0)
     1039        qOraWarning("qMakeOraField:", p->err);
     1040
     1041    r = OCIAttrGet(param,
     1042                   OCI_DTYPE_PARAM,
     1043                   &colLength,
     1044                   0,
     1045                   OCI_ATTR_DATA_SIZE, /* in bytes */
     1046                   p->err);
     1047    if (r != 0)
     1048        qOraWarning("qMakeOraField:", p->err);
     1049
     1050#ifdef OCI_ATTR_CHAR_SIZE
     1051    r = OCIAttrGet(param,
     1052                   OCI_DTYPE_PARAM,
     1053                   &colFieldLength,
     1054                   0,
     1055                   OCI_ATTR_CHAR_SIZE,
     1056                   p->err);
     1057    if (r != 0)
     1058        qOraWarning("qMakeOraField:", p->err);
     1059#else
     1060    // for Oracle8.
     1061    colFieldLength = colLength;
     1062#endif
     1063
     1064    r = OCIAttrGet(param,
     1065                   OCI_DTYPE_PARAM,
     1066                   &colPrecision,
     1067                   0,
     1068                   OCI_ATTR_PRECISION,
     1069                   p->err);
     1070    if (r != 0)
     1071        qOraWarning("qMakeOraField:", p->err);
     1072
     1073    r = OCIAttrGet(param,
     1074                   OCI_DTYPE_PARAM,
     1075                   &colScale,
     1076                   0,
     1077                   OCI_ATTR_SCALE,
     1078                   p->err);
     1079    if (r != 0)
     1080        qOraWarning("qMakeOraField:", p->err);
     1081    r = OCIAttrGet(param,
     1082                   OCI_DTYPE_PARAM,
     1083                   &colType,
     1084                   0,
     1085                   OCI_ATTR_DATA_TYPE,
     1086                   p->err);
     1087    if (r != 0)
     1088        qOraWarning("qMakeOraField:", p->err);
     1089    r = OCIAttrGet(param,
     1090                   OCI_DTYPE_PARAM,
     1091                   &colIsNull,
     1092                   0,
     1093                   OCI_ATTR_IS_NULL,
     1094                   p->err);
     1095    if (r != 0)
     1096        qOraWarning("qMakeOraField:", p->err);
     1097
     1098    type = qDecodeOCIType(colType, p->q->numericalPrecisionPolicy());
     1099
     1100    if (type == QVariant::Int) {
     1101        if (colLength == 22 && colPrecision == 0 && colScale == 0)
     1102            type = QVariant::String;
     1103        if (colScale > 0)
     1104            type = QVariant::String;
     1105    }
     1106
     1107    // bind as double if the precision policy asks for it
     1108    if (((colType == SQLT_FLT) || (colType == SQLT_NUM))
     1109            && (p->q->numericalPrecisionPolicy() == QSql::LowPrecisionDouble)) {
     1110        type = QVariant::Double;
     1111    }
     1112
     1113    // bind as int32 or int64 if the precision policy asks for it
     1114    if ((colType == SQLT_NUM) || (colType == SQLT_VNU) || (colType == SQLT_UIN)
     1115            || (colType == SQLT_INT)) {
     1116        if (p->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
     1117            type = QVariant::LongLong;
     1118        else if (p->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
     1119            type = QVariant::Int;
     1120    }
     1121
     1122    if (colType == SQLT_BLOB)
     1123        colLength = 0;
     1124
     1125    // colNameLen is length in bytes
     1126    ofi.name = QString(reinterpret_cast<const QChar*>(colName), colNameLen / 2);
     1127    ofi.type = type;
     1128    ofi.oraType = colType;
     1129    ofi.oraFieldLength = colFieldLength;
     1130    ofi.oraLength = colLength;
     1131    ofi.oraScale = colScale;
     1132    ofi.oraPrecision = colPrecision;
     1133    ofi.oraIsNull = colIsNull;
     1134
     1135    return ofi;
     1136}
     1137
    11401138struct QOCIBatchColumn
    11411139{
     
    12601258                col.bindAs = SQLT_STR;
    12611259                for (uint j = 0; j < col.recordCount; ++j) {
    1262                     uint len = boundValues.at(i).toList().at(j).toString().length() + 1;
     1260                    uint len;
     1261                    if(d->isOutValue(i))
     1262                        len = boundValues.at(i).toList().at(j).toString().capacity() + 1;
     1263                    else
     1264                        len = boundValues.at(i).toList().at(j).toString().length() + 1;
    12631265                    if (len > col.maxLen)
    12641266                        col.maxLen = len;
     
    12711273                col.bindAs = SQLT_LBI;
    12721274                for (uint j = 0; j < col.recordCount; ++j) {
    1273                     col.lengths[j] = boundValues.at(i).toList().at(j).toByteArray().size();
     1275                    if(d->isOutValue(i))
     1276                        col.lengths[j] = boundValues.at(i).toList().at(j).toByteArray().capacity();
     1277                    else
     1278                        col.lengths[j] = boundValues.at(i).toList().at(j).toByteArray().size();
    12741279                    if (col.lengths[j] > col.maxLen)
    12751280                        col.maxLen = col.lengths[j];
     
    15811586        case QVariant::Int:
    15821587        case QVariant::LongLong:
    1583             if (d->precisionPolicy != QSql::HighPrecision) {
    1584                 if ((d->precisionPolicy == QSql::LowPrecisionDouble)
     1588            if (d->q->numericalPrecisionPolicy() != QSql::HighPrecision) {
     1589                if ((d->q->numericalPrecisionPolicy() == QSql::LowPrecisionDouble)
    15851590                        && (fld.typ == QVariant::Double)) {
    15861591                    v[index + i] = *reinterpret_cast<double *>(fld.data);
    15871592                    break;
    1588                 } else if ((d->precisionPolicy == QSql::LowPrecisionInt64)
     1593                } else if ((d->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
    15891594                        && (fld.typ == QVariant::LongLong)) {
    15901595                    qint64 qll = 0;
    1591                     OCINumberToInt(d->err, reinterpret_cast<OCINumber *>(fld.data), sizeof(qint64),
     1596                    int r = OCINumberToInt(d->err, reinterpret_cast<OCINumber *>(fld.data), sizeof(qint64),
    15921597                                   OCI_NUMBER_SIGNED, &qll);
    1593                     v[index + i] = qll;
     1598                    if(r == OCI_SUCCESS)
     1599                        v[index + i] = qll;
     1600                    else
     1601                        v[index + i] = QVariant();
    15941602                    break;
    1595                 } else if ((d->precisionPolicy == QSql::LowPrecisionInt32)
     1603                } else if ((d->q->numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
    15961604                        && (fld.typ == QVariant::Int)) {
    15971605                    v[index + i] = *reinterpret_cast<int *>(fld.data);
     
    16191627    : cols(0), q(result), env(driver->env), err(0), svc(const_cast<OCISvcCtx*&>(driver->svc)),
    16201628      sql(0), transaction(driver->transaction), serverVersion(driver->serverVersion),
    1621       prefetchRows(driver->prefetchRows), prefetchMem(driver->prefetchMem),
    1622       precisionPolicy(driver->precisionPolicy)
     1629      prefetchRows(driver->prefetchRows), prefetchMem(driver->prefetchMem)
    16231630{
    16241631    int r = OCIHandleAlloc(env,
     
    17901797{
    17911798    int r = 0;
    1792     ub2 stmtType;
     1799    ub2 stmtType=0;
    17931800    ub4 iters;
    17941801    ub4 mode;
     
    18031810                    OCI_ATTR_STMT_TYPE,
    18041811                    d->err);
     1812
     1813    if (r != OCI_SUCCESS && r != OCI_SUCCESS_WITH_INFO) {
     1814        qOraWarning("QOCIResult::exec: Unable to get statement type:", d->err);
     1815        setLastError(qMakeError(QCoreApplication::translate("QOCIResult",
     1816                     "Unable to get statement type"), QSqlError::StatementError, d->err));
     1817#ifdef QOCI_DEBUG
     1818        qDebug() << "lastQuery()" << lastQuery();
     1819#endif
     1820        return false;
     1821    }
    18051822
    18061823    if (stmtType == OCI_STMT_SELECT) {
     
    18921909        QOCICols::execBatch(d, boundValues(), *reinterpret_cast<bool *>(data));
    18931910        break;
    1894     case QSqlResult::SetNumericalPrecision:
    1895         d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
    1896         break;
    18971911    default:
    1898         QSqlResult::virtual_hook(id, data);
     1912        QSqlCachedResult::virtual_hook(id, data);
    18991913    }
    19001914}
     
    20312045    if (!hostname.isEmpty())
    20322046        connectionString =
    2033             QString(QLatin1String("(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=%1)(Port=%2))"
    2034                 "(CONNECT_DATA=(SID=%3)))")).arg(hostname).arg((port > -1 ? port : 1521)).arg(db);
     2047        QString::fromLatin1("(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=%1)(Port=%2))"
     2048                "(CONNECT_DATA=(SID=%3)))").arg(hostname).arg((port > -1 ? port : 1521)).arg(db);
    20352049
    20362050    r = OCIHandleAlloc(d->env, reinterpret_cast<void **>(&d->srvhp), OCI_HTYPE_SERVER, 0, 0);
     
    20992113    setOpen(true);
    21002114    setOpenError(false);
    2101     d->user = user.toUpper();
     2115    d->user = user;
    21022116
    21032117    return true;
     
    21872201{
    21882202    QStringList tl;
     2203    QStringList sysUsers = QStringList() << QLatin1String("MDSYS")
     2204                                    << QLatin1String("LBACSYS")
     2205                                    << QLatin1String("SYS")
     2206                                    << QLatin1String("SYSTEM")
     2207                                    << QLatin1String("WKSYS")
     2208                                    << QLatin1String("CTXSYS")
     2209                                    << QLatin1String("WMSYS");
     2210
     2211    QString user = d->user;
     2212    if ( isIdentifierEscaped(user, QSqlDriver::TableName))
     2213        user = stripDelimiters(user, QSqlDriver::TableName);
     2214    else
     2215        user = user.toUpper();
     2216
     2217    if(sysUsers.contains(user))
     2218        sysUsers.removeAll(user);;
     2219
    21892220    if (!isOpen())
    21902221        return tl;
     
    21932224    t.setForwardOnly(true);
    21942225    if (type & QSql::Tables) {
    2195         t.exec(QLatin1String("select owner, table_name from all_tables "
    2196                 "where owner != 'MDSYS' "
    2197                 "and owner != 'LBACSYS' "
    2198                 "and owner != 'SYS' "
    2199                 "and owner != 'SYSTEM' "
    2200                 "and owner != 'WKSYS'"
    2201                 "and owner != 'CTXSYS'"
    2202                 "and owner != 'WMSYS'"));
     2226        QString query = QLatin1String("select owner, table_name from all_tables where ");
     2227        QStringList whereList;
     2228        foreach(const QString &sysUserName, sysUsers)
     2229            whereList << QLatin1String("owner != '") + sysUserName + QLatin1String("' ");
     2230        t.exec(query + whereList.join(QLatin1String(" and ")));
     2231
     2232        while (t.next()) {
     2233            if (t.value(0).toString().toUpper() != user.toUpper())
     2234                tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());
     2235            else
     2236                tl.append(t.value(1).toString());
     2237        }
     2238
     2239        // list all table synonyms as well
     2240        query = QLatin1String("select owner, synonym_name from all_synonyms where ");
     2241        t.exec(query + whereList.join(QLatin1String(" and ")));
     2242        while (t.next()) {
     2243            if (t.value(0).toString() != d->user)
     2244                tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());
     2245            else
     2246                tl.append(t.value(1).toString());
     2247        }
     2248    }
     2249    if (type & QSql::Views) {
     2250        QString query = QLatin1String("select owner, view_name from all_views where ");
     2251        QStringList whereList;
     2252        foreach(const QString &sysUserName, sysUsers)
     2253            whereList << QLatin1String("owner != '") + sysUserName + QLatin1String("' ");
     2254        t.exec(query + whereList.join(QLatin1String(" and ")));
     2255        while (t.next()) {
     2256            if (t.value(0).toString().toUpper() != d->user.toUpper())
     2257                tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());
     2258            else
     2259                tl.append(t.value(1).toString());
     2260        }
     2261    }
     2262    if (type & QSql::SystemTables) {
     2263        t.exec(QLatin1String("select table_name from dictionary"));
     2264        while (t.next()) {
     2265            tl.append(t.value(0).toString());
     2266        }
     2267        QString query = QLatin1String("select owner, table_name from all_tables where ");
     2268        QStringList whereList;
     2269        foreach(const QString &sysUserName, sysUsers)
     2270            whereList << QLatin1String("owner = '") + sysUserName + QLatin1String("' ");
     2271        t.exec(query + whereList.join(QLatin1String(" or ")));
     2272
     2273        while (t.next()) {
     2274            if (t.value(0).toString().toUpper() != user.toUpper())
     2275                tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());
     2276            else
     2277                tl.append(t.value(1).toString());
     2278        }
     2279
     2280        // list all table synonyms as well
     2281        query = QLatin1String("select owner, synonym_name from all_synonyms where ");
     2282        t.exec(query + whereList.join(QLatin1String(" or ")));
    22032283        while (t.next()) {
    22042284            if (t.value(0).toString() != d->user)
     
    22082288        }
    22092289    }
    2210     if (type & QSql::Views) {
    2211         t.exec(QLatin1String("select owner, view_name from all_views "
    2212                 "where owner != 'MDSYS' "
    2213                 "and owner != 'LBACSYS' "
    2214                 "and owner != 'SYS' "
    2215                 "and owner != 'SYSTEM' "
    2216                 "and owner != 'WKSYS'"
    2217                 "and owner != 'CTXSYS'"
    2218                 "and owner != 'WMSYS'"));
    2219         while (t.next()) {
    2220             if (t.value(0).toString() != d->user)
    2221                 tl.append(t.value(0).toString() + QLatin1String(".") + t.value(1).toString());
    2222             else
    2223                 tl.append(t.value(1).toString());
    2224         }
    2225     }
    2226     if (type & QSql::SystemTables) {
    2227         t.exec(QLatin1String("select table_name from dictionary"));
    2228         while (t.next()) {
    2229             tl.append(t.value(0).toString());
    2230         }
    2231     }
    22322290    return tl;
    22332291}
     
    22382296    int i = tname.indexOf(QLatin1Char('.')); // prefixed with owner?
    22392297    if (i != -1) {
    2240         *tbl = tname.right(tname.length() - i - 1).toUpper();
    2241         *owner = tname.left(i).toUpper();
     2298        *tbl = tname.right(tname.length() - i - 1);
     2299        *owner = tname.left(i);
    22422300    } else {
    2243         *tbl = tname.toUpper();
     2301        *tbl = tname;
    22442302    }
    22452303}
     
    22562314    QString stmt(QLatin1String("select column_name, data_type, data_length, "
    22572315                  "data_precision, data_scale, nullable, data_default%1"
    2258                   "from all_tab_columns "
    2259                   "where upper(table_name)=%2"));
     2316                  "from all_tab_columns a "
     2317                  "where a.table_name=%2"));
    22602318    if (d->serverVersion >= 9)
    22612319        stmt = stmt.arg(QLatin1String(", char_length "));
     
    22652323    QString table, owner, tmpStmt;
    22662324    qSplitTableAndOwner(tablename, &table, &owner);
     2325
     2326    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     2327        table = stripDelimiters(table, QSqlDriver::TableName);
     2328    else
     2329        table = table.toUpper();
     2330
    22672331    tmpStmt = stmt.arg(QLatin1Char('\'') + table + QLatin1Char('\''));
    22682332    if (owner.isEmpty()) {
    22692333        owner = d->user;
    22702334    }
    2271     tmpStmt += QLatin1String(" and upper(owner)='") + owner + QLatin1String("'");
     2335
     2336    if (isIdentifierEscaped(owner, QSqlDriver::TableName))
     2337        owner = stripDelimiters(owner, QSqlDriver::TableName);
     2338    else
     2339        owner = owner.toUpper();
     2340
     2341    tmpStmt += QLatin1String(" and a.owner='") + owner + QLatin1Char('\'');
    22722342    t.setForwardOnly(true);
    22732343    t.exec(tmpStmt);
    22742344    if (!t.next()) { // try and see if the tablename is a synonym
    2275         stmt= stmt.arg(QLatin1String("(select tname from sys.synonyms where sname='")
    2276                         + table + QLatin1String("' and creator=owner)"));
     2345        stmt = stmt + QLatin1String(" join all_synonyms b "
     2346                              "on a.owner=b.table_owner and a.table_name=b.table_name "
     2347                              "where b.owner='") + owner +
     2348                      QLatin1String("' and b.synonym_name='") + table +
     2349                      QLatin1Char('\'');
    22772350        t.setForwardOnly(true);
    22782351        t.exec(stmt);
     
    22862359    if (buildRecordInfo) {
    22872360        do {
    2288             QVariant::Type ty = qDecodeOCIType(t.value(1).toString(),t.numericalPrecisionPolicy());
     2361            QVariant::Type ty = qDecodeOCIType(t.value(1).toString(), t.numericalPrecisionPolicy());
    22892362            QSqlField f(t.value(0).toString(), ty);
    22902363            f.setRequired(t.value(5).toString() == QLatin1String("N"));
     
    23182391    QString table, owner, tmpStmt;
    23192392    qSplitTableAndOwner(tablename, &table, &owner);
    2320     tmpStmt = stmt + QLatin1String(" and upper(a.table_name)='") + table + QLatin1String("'");
     2393
     2394    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     2395        table = stripDelimiters(table, QSqlDriver::TableName);
     2396    else
     2397        table = table.toUpper();
     2398
     2399    tmpStmt = stmt + QLatin1String(" and a.table_name='") + table + QLatin1Char('\'');
    23212400    if (owner.isEmpty()) {
    23222401        owner = d->user;
    23232402    }
    2324     tmpStmt += QLatin1String(" and upper(a.owner)='") + owner + QLatin1String("'");
     2403
     2404    if (isIdentifierEscaped(owner, QSqlDriver::TableName))
     2405        owner = stripDelimiters(owner, QSqlDriver::TableName);
     2406    else
     2407        owner = owner.toUpper();
     2408
     2409    tmpStmt += QLatin1String(" and a.owner='") + owner + QLatin1Char('\'');
    23252410    t.setForwardOnly(true);
    23262411    t.exec(tmpStmt);
     
    23462431                     t.value(2).toString() + QLatin1String("' and column_name='") +
    23472432                     t.value(0).toString() + QLatin1String("' and owner='") +
    2348                      owner +QLatin1String("'"));
     2433                     owner + QLatin1Char('\''));
    23492434            if (!tt.next()) {
    23502435                return QSqlIndex();
     
    24162501}
    24172502
    2418 QString QOCIDriver::escapeIdentifier(const QString &identifier, IdentifierType /* type */) const
     2503QString QOCIDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const
    24192504{
    24202505    QString res = identifier;
    2421     res.replace(QLatin1Char('"'), QLatin1String("\"\""));
    2422     if (identifier.indexOf(QLatin1Char(' ')) != -1)
     2506    if(!identifier.isEmpty() && !isIdentifierEscaped(identifier, type)) {
     2507        res.replace(QLatin1Char('"'), QLatin1String("\"\""));
    24232508        res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
    2424 //     res.replace(QLatin1Char('.'), QLatin1String("\".\""));
     2509        res.replace(QLatin1Char('.'), QLatin1String("\".\""));
     2510    }
    24252511    return res;
    24262512}
  • trunk/src/sql/drivers/oci/qsql_oci.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/sql/drivers/odbc/qsql_odbc.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5656#include <qvector.h>
    5757#include <QDebug>
     58#include <QSqlQuery>
    5859
    5960QT_BEGIN_NAMESPACE
     
    7071
    7172// newer platform SDKs use SQLLEN instead of SQLINTEGER
    72 #if defined(SQLLEN) || defined(Q_OS_WIN64)
     73#if defined(WIN32) && (_MSC_VER < 1300)
     74# define QSQLLEN SQLINTEGER
     75# define QSQLULEN SQLUINTEGER
     76#else
    7377# define QSQLLEN SQLLEN
    74 #else
    75 # define QSQLLEN SQLINTEGER
    76 #endif
    77 
    78 #if defined(SQLULEN) || defined(Q_OS_WIN64)
    7978# define QSQLULEN SQLULEN
    80 #else
    81 # define QSQLULEN SQLUINTEGER
    82 #endif
     79#endif
     80
    8381
    8482static const int COLNAMESIZE = 256;
     
    8987{
    9088public:
     89    enum DefaultCase{Lower, Mixed, Upper, Sensitive};
    9190    QODBCDriverPrivate()
    9291    : hEnv(0), hDbc(0), useSchema(false), disconnectCount(0), isMySqlServer(false),
    93            isMSSqlServer(false), hasSQLFetchScroll(true), hasMultiResultSets(false)
     92           isMSSqlServer(false), hasSQLFetchScroll(true), hasMultiResultSets(false),
     93           isQuoteInitialized(false), quote(QLatin1Char('"'))
    9494    {
    95         sql_char_type = sql_varchar_type = sql_longvarchar_type = QVariant::ByteArray;
    9695        unicode = false;
    9796    }
     
    102101    uint unicode :1;
    103102    uint useSchema :1;
    104     QVariant::Type sql_char_type;
    105     QVariant::Type sql_varchar_type;
    106     QVariant::Type sql_longvarchar_type;
    107103    int disconnectCount;
    108104    bool isMySqlServer;
     
    120116    void splitTableQualifier(const QString &qualifier, QString &catalog,
    121117                             QString &schema, QString &table);
     118    DefaultCase defaultCase() const;
     119    QString adjustCase(const QString&) const;
     120    QChar quoteChar();
     121private:
     122    bool isQuoteInitialized;
     123    QChar quote;
    122124};
    123125
     
    125127{
    126128public:
    127     QODBCPrivate()
    128     : hEnv(0), hDbc(0), hStmt(0), useSchema(false), hasSQLFetchScroll(true), precisionPolicy(QSql::HighPrecision)
     129    QODBCPrivate(QODBCDriverPrivate *dpp)
     130    : hStmt(0), useSchema(false), hasSQLFetchScroll(true), driverPrivate(dpp), userForwardOnly(false)
    129131    {
    130         sql_char_type = sql_varchar_type = sql_longvarchar_type = QVariant::ByteArray;
    131132        unicode = false;
    132133    }
     
    135136    { fieldCache.fill(QVariant()); fieldCacheIdx = 0; }
    136137
    137     SQLHANDLE hEnv;
    138     SQLHANDLE hDbc;
     138    SQLHANDLE dpEnv() const { return driverPrivate ? driverPrivate->hEnv : 0;}
     139    SQLHANDLE dpDbc() const { return driverPrivate ? driverPrivate->hDbc : 0;}
    139140    SQLHANDLE hStmt;
    140141
    141142    uint unicode :1;
    142143    uint useSchema :1;
    143     QVariant::Type sql_char_type;
    144     QVariant::Type sql_varchar_type;
    145     QVariant::Type sql_longvarchar_type;
    146144
    147145    QSqlRecord rInf;
     
    150148    int disconnectCount;
    151149    bool hasSQLFetchScroll;
    152     QSql::NumericalPrecisionPolicy precisionPolicy;
     150    QODBCDriverPrivate *driverPrivate;
     151    bool userForwardOnly;
    153152
    154153    bool isStmtHandleValid(const QSqlDriver *driver);
     
    174173    SQLRETURN r = SQL_NO_DATA;
    175174    SQLTCHAR state_[SQL_SQLSTATE_SIZE+1];
    176     SQLTCHAR description_[SQL_MAX_MESSAGE_LENGTH];
     175    QVarLengthArray<SQLTCHAR> description_(SQL_MAX_MESSAGE_LENGTH);
    177176    QString result;
    178177    int i = 1;
    179178
    180179    description_[0] = 0;
     180    r = SQLGetDiagRec(handleType,
     181                      handle,
     182                      i,
     183                      state_,
     184                      &nativeCode_,
     185                      0,
     186                      NULL,
     187                      &msgLen);
     188    if(r == SQL_NO_DATA)
     189        return QString();
     190    description_.resize(msgLen+1);
    181191    do {
    182192        r = SQLGetDiagRec(handleType,
    183193                            handle,
    184194                            i,
    185                             (SQLTCHAR*)state_,
     195                            state_,
    186196                            &nativeCode_,
    187                             (SQLTCHAR*)description_,
    188                             SQL_MAX_MESSAGE_LENGTH, /* in bytes, not in characters */
     197                            description_.data(),
     198                            description_.size(),
    189199                            &msgLen);
    190200        if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
     
    193203            QString tmpstore;
    194204#ifdef UNICODE
    195             tmpstore = QString((const QChar*)description_, msgLen);
     205            tmpstore = QString((const QChar*)description_.data(), msgLen);
    196206#else
    197             tmpstore = QString::fromLocal8Bit((const char*)description_, msgLen);
     207            tmpstore = QString::fromLocal8Bit((const char*)description_.data(), msgLen);
    198208#endif
    199209            if(result != tmpstore) {
     
    212222static QString qODBCWarn(const QODBCPrivate* odbc, int *nativeCode = 0)
    213223{
    214     return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1String(" ")
    215              + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc) + QLatin1String(" ")
     224    return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->dpEnv()) + QLatin1Char(' ')
     225             + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->dpDbc()) + QLatin1Char(' ')
    216226             + qWarnODBCHandle(SQL_HANDLE_STMT, odbc->hStmt, nativeCode));
    217227}
     
    219229static QString qODBCWarn(const QODBCDriverPrivate* odbc, int *nativeCode = 0)
    220230{
    221     return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1String(" ")
     231    return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1Char(' ')
    222232             + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc, nativeCode));
    223233}
     
    251261static QVariant::Type qDecodeODBCType(SQLSMALLINT sqltype, const T* p, bool isSigned = true)
    252262{
     263    Q_UNUSED(p);
    253264    QVariant::Type type = QVariant::Invalid;
    254265    switch (sqltype) {
     
    263274    case SQL_INTEGER:
    264275    case SQL_BIT:
     276        type = isSigned ? QVariant::Int : QVariant::UInt;
     277        break;
    265278    case SQL_TINYINT:
    266         type = isSigned ? QVariant::Int : QVariant::UInt;
     279        type = QVariant::UInt;
    267280        break;
    268281    case SQL_BIGINT:
     
    294307#endif
    295308    case SQL_CHAR:
    296         type = p->sql_char_type;
    297         break;
    298309    case SQL_VARCHAR:
    299310    case SQL_GUID:
    300         type = p->sql_varchar_type;
    301         break;
    302311    case SQL_LONGVARCHAR:
    303         type = p->sql_longvarchar_type;
     312        type = QVariant::String;
    304313        break;
    305314    default:
     
    327336        }
    328337    }
    329     char* buf = new char[colSize];
     338    QVarLengthArray<char> buf(colSize);
    330339    while (true) {
    331340        r = SQLGetData(hStmt,
    332341                        column+1,
    333342                        unicode ? SQL_C_WCHAR : SQL_C_CHAR,
    334                         (SQLPOINTER)buf,
     343                        (SQLPOINTER)buf.data(),
    335344                        colSize,
    336345                        &lengthIndicator);
     
    347356            int rSize = (r == SQL_SUCCESS_WITH_INFO) ? (unicode ? colSize-2 : colSize-1) : lengthIndicator;
    348357            if (unicode) {
    349                 fieldVal += QString((QChar*) buf, rSize / 2);
     358                fieldVal += QString((const QChar*) buf.constData(), rSize / 2);
    350359            } else {
    351                 fieldVal += QString::fromAscii(buf, rSize);
     360                fieldVal += QString::fromAscii(buf.constData(), rSize);
    352361            }
    353             if (fieldVal.size() + lengthIndicator >= colSize) {
     362            memset(buf.data(), 0, colSize);
     363            if (lengthIndicator < colSize) {
    354364                // workaround for Drivermanagers that don't return SQL_NO_DATA
    355365                break;
     
    363373        }
    364374    }
    365     delete[] buf;
    366375    return fieldVal;
    367376}
     
    443452}
    444453
     454static QVariant qGetDoubleData(SQLHANDLE hStmt, int column)
     455{
     456    SQLDOUBLE dblbuf;
     457    QSQLLEN lengthIndicator = 0;
     458    SQLRETURN r = SQLGetData(hStmt,
     459                              column+1,
     460                              SQL_C_DOUBLE,
     461                              (SQLPOINTER) &dblbuf,
     462                              0,
     463                              &lengthIndicator);
     464    if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
     465        return QVariant(QVariant::Invalid);
     466    }
     467    if(lengthIndicator == SQL_NULL_DATA)
     468        return QVariant(QVariant::Double);
     469
     470    return (double) dblbuf;
     471}
     472
     473
    445474static QVariant qGetBigIntData(SQLHANDLE hStmt, int column, bool isSigned = true)
    446475{
     
    552581    if (connOpts.contains(QLatin1String("SQL_ATTR_ODBC_VERSION=SQL_OV_ODBC3"), Qt::CaseInsensitive))
    553582        return SQL_OV_ODBC3;
    554 #endif 
     583#endif
    555584    return SQL_OV_ODBC2;
    556585}
     586
     587QChar QODBCDriverPrivate::quoteChar()
     588{
     589    if (!isQuoteInitialized) {
     590        char driverResponse[4];
     591        SQLSMALLINT length;
     592        int r = SQLGetInfo(hDbc,
     593                SQL_IDENTIFIER_QUOTE_CHAR,
     594                &driverResponse,
     595                sizeof(driverResponse),
     596                &length);
     597        if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
     598            quote = QLatin1Char(driverResponse[0]);
     599        } else {
     600            quote = QLatin1Char('"');
     601        }
     602        isQuoteInitialized = true;
     603    }
     604    return quote;
     605}
     606
    557607
    558608bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
     
    706756}
    707757
     758QODBCDriverPrivate::DefaultCase QODBCDriverPrivate::defaultCase() const
     759{
     760    DefaultCase ret;
     761    SQLUSMALLINT casing;
     762    int r = SQLGetInfo(hDbc,
     763            SQL_IDENTIFIER_CASE,
     764            &casing,
     765            sizeof(casing),
     766            NULL);
     767    if ( r != SQL_SUCCESS)
     768        ret = Mixed;//arbitrary case if driver cannot be queried
     769    else {
     770        switch (casing) {
     771            case (SQL_IC_UPPER):
     772                ret = Upper;
     773                break;
     774            case (SQL_IC_LOWER):
     775                ret = Lower;
     776                break;
     777            case (SQL_IC_SENSITIVE):
     778                ret = Sensitive;
     779                break;
     780            case (SQL_IC_MIXED):
     781            default:
     782                ret = Mixed;
     783                break;
     784        }
     785    }
     786    return ret;
     787}
     788
     789/*
     790   Adjust the casing of an identifier to match what the
     791   database engine would have done to it.
     792*/
     793QString QODBCDriverPrivate::adjustCase(const QString &identifier) const
     794{
     795    QString ret = identifier;
     796    switch(defaultCase()) {
     797        case (Lower):
     798            ret = identifier.toLower();
     799            break;
     800        case (Upper):
     801            ret = identifier.toUpper();
     802            break;
     803        case(Mixed):
     804        case(Sensitive):
     805        default:
     806            ret = identifier;
     807    }
     808    return ret;
     809}
     810
    708811////////////////////////////////////////////////////////////////////////////
    709812
     
    711814: QSqlResult(db)
    712815{
    713     d = new QODBCPrivate();
    714     d->hEnv = p->hEnv;
    715     d->hDbc = p->hDbc;
     816    d = new QODBCPrivate(p);
    716817    d->unicode = p->unicode;
    717818    d->useSchema = p->useSchema;
    718     d->sql_char_type = p->sql_char_type;
    719     d->sql_varchar_type = p->sql_varchar_type;
    720     d->sql_longvarchar_type = p->sql_longvarchar_type;
    721819    d->disconnectCount = p->disconnectCount;
    722820    d->hasSQLFetchScroll = p->hasSQLFetchScroll;
     
    754852    }
    755853    r  = SQLAllocHandle(SQL_HANDLE_STMT,
    756                          d->hDbc,
     854                         d->dpDbc(),
    757855                         &d->hStmt);
    758856    if (r != SQL_SUCCESS) {
     
    763861    d->updateStmtHandleState(driver());
    764862
    765     if (isForwardOnly()) {
     863    if (d->userForwardOnly) {
    766864        r = SQLSetStmtAttr(d->hStmt,
    767865                            SQL_ATTR_CURSOR_TYPE,
     
    796894        return false;
    797895    }
     896
     897    SQLINTEGER isScrollable, bufferLength;
     898    r = SQLGetStmtAttr(d->hStmt, SQL_ATTR_CURSOR_SCROLLABLE, &isScrollable, SQL_IS_INTEGER, &bufferLength);
     899    if(r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO)
     900        QSqlResult::setForwardOnly(isScrollable==SQL_NONSCROLLABLE);
    798901
    799902    SQLSMALLINT count;
     
    883986                       SQL_FETCH_FIRST,
    884987                       0);
    885     if (r != SQL_SUCCESS) { 
     988    if (r != SQL_SUCCESS) {
    886989        if (r != SQL_NO_DATA)
    887990            setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
     
    9021005                       SQL_FETCH_PRIOR,
    9031006                       0);
    904     if (r != SQL_SUCCESS) { 
     1007    if (r != SQL_SUCCESS) {
    9051008        if (r != SQL_NO_DATA)
    9061009            setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
     
    9331036                       SQL_FETCH_LAST,
    9341037                       0);
    935     if (r != SQL_SUCCESS) { 
     1038    if (r != SQL_SUCCESS) {
    9361039        if (r != SQL_NO_DATA)
    9371040            setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
     
    10241127            break;
    10251128        case QVariant::String:
    1026             d->fieldCache[i] = qGetStringData(d->hStmt, i, info.length(), true);
     1129            d->fieldCache[i] = qGetStringData(d->hStmt, i, info.length(), d->unicode);
    10271130            break;
    10281131        case QVariant::Double:
    1029             {
    1030                 QString value=qGetStringData(d->hStmt, i, info.length(), false);
    1031                 bool ok=false;
    1032                 switch(d->precisionPolicy) {
    1033                     case QSql::LowPrecisionInt32:
    1034                         d->fieldCache[i] = value.toInt(&ok);
    1035                         break;
    1036                     case QSql::LowPrecisionInt64:
    1037                         d->fieldCache[i] = value.toLongLong(&ok);
    1038                         break;
    1039                     case QSql::LowPrecisionDouble:
    1040                         d->fieldCache[i] = value.toDouble(&ok);
    1041                         break;
    1042                     case QSql::HighPrecision:
    1043                     default:
    1044                         d->fieldCache[i] = value;
    1045                         ok=true;
    1046                         break;
    1047                 }
    1048                 if(ok==false)
    1049                     d->fieldCache[i] = QVariant();
    1050                 break;
     1132            switch(numericalPrecisionPolicy()) {
     1133                case QSql::LowPrecisionInt32:
     1134                    d->fieldCache[i] = qGetIntData(d->hStmt, i);
     1135                    break;
     1136                case QSql::LowPrecisionInt64:
     1137                    d->fieldCache[i] = qGetBigIntData(d->hStmt, i);
     1138                    break;
     1139                case QSql::LowPrecisionDouble:
     1140                    d->fieldCache[i] = qGetDoubleData(d->hStmt, i);
     1141                    break;
     1142                case QSql::HighPrecision:
     1143                    d->fieldCache[i] = qGetStringData(d->hStmt, i, info.length(), false);
     1144                    break;
    10511145            }
     1146            break;
    10521147        default:
    10531148            d->fieldCache[i] = QVariant(qGetStringData(d->hStmt, i, info.length(), false));
     
    11031198    }
    11041199    r  = SQLAllocHandle(SQL_HANDLE_STMT,
    1105                          d->hDbc,
     1200                         d->dpDbc(),
    11061201                         &d->hStmt);
    11071202    if (r != SQL_SUCCESS) {
     
    11121207    d->updateStmtHandleState(driver());
    11131208
    1114     if (isForwardOnly()) {
     1209    if (d->userForwardOnly) {
    11151210        r = SQLSetStmtAttr(d->hStmt,
    11161211                            SQL_ATTR_CURSOR_TYPE,
     
    13721467#endif
    13731468                {
    1374                     QByteArray str = val.toString().toUtf8();
     1469                    QByteArray str = val.toString().toAscii();
    13751470                    if (*ind != SQL_NULL_DATA)
    13761471                        *ind = str.length();
    13771472                    int strSize = str.length();
    1378                    
     1473
    13791474                    r = SQLBindParameter(d->hStmt,
    13801475                                          i + 1,
     
    14231518    }
    14241519
     1520    SQLINTEGER isScrollable, bufferLength;
     1521    r = SQLGetStmtAttr(d->hStmt, SQL_ATTR_CURSOR_SCROLLABLE, &isScrollable, SQL_IS_INTEGER, &bufferLength);
     1522    if(r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO)
     1523        QSqlResult::setForwardOnly(isScrollable==SQL_NONSCROLLABLE);
     1524
    14251525    SQLSMALLINT count;
    14261526    SQLNumResultCols(d->hStmt, &count);
     
    14571557                               QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000)));
    14581558                break; }
     1559            case QVariant::Bool:
    14591560            case QVariant::Int:
    14601561            case QVariant::UInt:
     
    15461647        *static_cast<bool*>(data) = nextResult();
    15471648        break;
    1548     case QSqlResult::SetNumericalPrecision:
    1549         Q_ASSERT(data);
    1550         d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
    1551         break;
    15521649    default:
    15531650        QSqlResult::virtual_hook(id, data);
    15541651    }
     1652}
     1653
     1654void QODBCResult::setForwardOnly(bool forward)
     1655{
     1656    d->userForwardOnly = forward;
     1657    QSqlResult::setForwardOnly(forward);
    15551658}
    15561659
     
    16701773    if (db.contains(QLatin1String(".dsn"), Qt::CaseInsensitive))
    16711774        connQStr = QLatin1String("FILEDSN=") + db;
    1672     else if (db.contains(QLatin1String("DRIVER="), Qt::CaseInsensitive) 
     1775    else if (db.contains(QLatin1String("DRIVER="), Qt::CaseInsensitive)
    16731776            || db.contains(QLatin1String("SERVER="), Qt::CaseInsensitive))
    16741777        connQStr = db;
     
    16801783    if (!password.isEmpty())
    16811784        connQStr += QLatin1String(";PWD=") + password;
    1682    
     1785
    16831786    SQLSMALLINT cb;
    16841787    SQLTCHAR connOut[1024];
     
    17031806    if (!d->checkDriver()) {
    17041807        setLastError(qMakeError(tr("Unable to connect - Driver doesn't support all "
    1705                      "needed functionality"), QSqlError::ConnectionError, d));
     1808                     "functionality required"), QSqlError::ConnectionError, d));
    17061809        setOpenError(true);
    17071810        return false;
     
    17151818    setOpen(true);
    17161819    setOpenError(false);
     1820    if(d->isMSSqlServer) {
     1821        QSqlQuery i(createResult());
     1822        i.exec(QLatin1String("SET QUOTED_IDENTIFIER ON"));
     1823    }
    17171824    return true;
    17181825}
     
    17631870    return;
    17641871#endif
    1765 #if defined(Q_WS_WIN)
    1766     QT_WA(
    1767     {},
    1768     {
    1769         unicode = false;
    1770         return;
    1771     })
    1772 #endif
     1872
    17731873    SQLRETURN   r;
    17741874    SQLUINTEGER fFunc;
     
    17811881                    NULL);
    17821882    if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WCHAR)) {
    1783         sql_char_type = QVariant::String;
    17841883        unicode = true;
    17851884    }
     
    17911890                    NULL);
    17921891    if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WVARCHAR)) {
    1793         sql_varchar_type = QVariant::String;
    17941892        unicode = true;
    17951893    }
     
    18011899                    NULL);
    18021900    if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WLONGVARCHAR)) {
    1803         sql_longvarchar_type = QVariant::String;
    18041901        unicode = true;
    18051902    }
     
    20852182    QString catalog, schema, table;
    20862183    d->splitTableQualifier(tablename, catalog, schema, table);
     2184
     2185    if (isIdentifierEscaped(catalog, QSqlDriver::TableName))
     2186        catalog = stripDelimiters(catalog, QSqlDriver::TableName);
     2187    else
     2188        catalog = d->adjustCase(catalog);
     2189
     2190    if (isIdentifierEscaped(schema, QSqlDriver::TableName))
     2191        schema = stripDelimiters(schema, QSqlDriver::TableName);
     2192    else
     2193        schema = d->adjustCase(schema);
     2194
     2195    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     2196        table = stripDelimiters(table, QSqlDriver::TableName);
     2197    else
     2198        table = d->adjustCase(table);
     2199
    20872200    r = SQLSetStmtAttr(hStmt,
    20882201                        SQL_ATTR_CURSOR_TYPE,
     
    21872300    QString catalog, schema, table;
    21882301    d->splitTableQualifier(tablename, catalog, schema, table);
     2302
     2303    if (isIdentifierEscaped(catalog, QSqlDriver::TableName))
     2304        catalog = stripDelimiters(catalog, QSqlDriver::TableName);
     2305    else
     2306        catalog = d->adjustCase(catalog);
     2307
     2308    if (isIdentifierEscaped(schema, QSqlDriver::TableName))
     2309        schema = stripDelimiters(schema, QSqlDriver::TableName);
     2310    else
     2311        schema = d->adjustCase(schema);
     2312
     2313    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     2314        table = stripDelimiters(table, QSqlDriver::TableName);
     2315    else
     2316        table = d->adjustCase(table);
     2317
    21892318    SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT,
    21902319                                  d->hDbc,
     
    22942423QString QODBCDriver::escapeIdentifier(const QString &identifier, IdentifierType) const
    22952424{
     2425    QChar quote = d->quoteChar();
    22962426    QString res = identifier;
    2297     if (d->isMySqlServer) {
    2298         if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('`')) && identifier.right(1) != QString(QLatin1Char('`')) ) {
    2299             res.prepend(QLatin1Char('`')).append(QLatin1Char('`'));
    2300             res.replace(QLatin1Char('.'), QLatin1String("`.`"));
    2301         }
    2302     } else {
    2303         if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
    2304             res.replace(QLatin1Char('"'), QLatin1String("\"\""));
    2305             res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
    2306             res.replace(QLatin1Char('.'), QLatin1String("\".\""));
    2307         }
     2427    if(!identifier.isEmpty() && !identifier.startsWith(quote) && !identifier.endsWith(quote) ) {
     2428        res.replace(quote, QString(quote)+QString(quote));
     2429        res.prepend(quote).append(quote);
     2430        res.replace(QLatin1Char('.'), QString(quote)+QLatin1Char('.')+QString(quote));
    23082431    }
    23092432    return res;
    23102433}
    23112434
     2435bool QODBCDriver::isIdentifierEscapedImplementation(const QString &identifier, IdentifierType) const
     2436{
     2437    QChar quote = d->quoteChar();
     2438    return identifier.size() > 2
     2439        && identifier.startsWith(quote) //left delimited
     2440        && identifier.endsWith(quote); //right delimited
     2441}
     2442
    23122443QT_END_NAMESPACE
  • trunk/src/sql/drivers/odbc/qsql_odbc.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    101101
    102102    QVariant handle() const;
     103    virtual void setForwardOnly(bool forward);
    103104
    104105protected:
     
    146147    QString escapeIdentifier(const QString &identifier, IdentifierType type) const;
    147148
     149protected Q_SLOTS:
     150    bool isIdentifierEscapedImplementation(const QString &identifier, IdentifierType type) const;
     151
    148152protected:
    149153    bool beginTransaction();
    150154    bool commitTransaction();
    151155    bool rollbackTransaction();
     156
    152157private:
    153158    void init();
  • trunk/src/sql/drivers/psql/qsql_psql.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5555#include <qmutex.h>
    5656
     57
    5758#include <libpq-fe.h>
    5859#include <pg_config.h>
     
    6061#include <stdlib.h>
    6162#include <math.h>
     63// below code taken from an example at http://www.gnu.org/software/hello/manual/autoconf/Function-Portability.html
     64#ifndef isnan
     65    # define isnan(x) \
     66        (sizeof (x) == sizeof (long double) ? isnan_ld (x) \
     67        : sizeof (x) == sizeof (double) ? isnan_d (x) \
     68        : isnan_f (x))
     69    static inline int isnan_f  (float       x) { return x != x; }
     70    static inline int isnan_d  (double      x) { return x != x; }
     71    static inline int isnan_ld (long double x) { return x != x; }
     72#endif
     73
     74#ifndef isinf
     75    # define isinf(x) \
     76        (sizeof (x) == sizeof (long double) ? isinf_ld (x) \
     77        : sizeof (x) == sizeof (double) ? isinf_d (x) \
     78        : isinf_f (x))
     79    static inline int isinf_f  (float       x) { return isnan (x - x); }
     80    static inline int isinf_d  (double      x) { return isnan (x - x); }
     81    static inline int isinf_ld (long double x) { return isnan (x - x); }
     82#endif
     83
    6284
    6385// workaround for postgres defining their OIDs in a private header file
     
    137159{
    138160public:
    139     QPSQLResultPrivate(QPSQLResult *qq): q(qq), driver(0), result(0), currentSize(-1), precisionPolicy(QSql::HighPrecision) {}
     161    QPSQLResultPrivate(QPSQLResult *qq): q(qq), driver(0), result(0), currentSize(-1), preparedQueriesEnabled(false) {}
    140162
    141163    QPSQLResult *q;
     
    143165    PGresult *result;
    144166    int currentSize;
    145     QSql::NumericalPrecisionPolicy precisionPolicy;
    146167    bool preparedQueriesEnabled;
    147168    QString preparedStmtId;
     
    321342    case QVariant::Double:
    322343        if (ptype == QNUMERICOID) {
    323             if (d->precisionPolicy != QSql::HighPrecision) {
     344            if (numericalPrecisionPolicy() != QSql::HighPrecision) {
    324345                QVariant retval;
    325346                bool convert;
    326                 if (d->precisionPolicy == QSql::LowPrecisionInt64)
    327                     retval = QString::fromAscii(val).toLongLong(&convert);
    328                 else if (d->precisionPolicy == QSql::LowPrecisionInt32)
    329                     retval = QString::fromAscii(val).toInt(&convert);
    330                 else if (d->precisionPolicy == QSql::LowPrecisionDouble)
    331                     retval = QString::fromAscii(val).toDouble(&convert);
     347                double dbl=QString::fromAscii(val).toDouble(&convert);
     348                if (numericalPrecisionPolicy() == QSql::LowPrecisionInt64)
     349                    retval = (qlonglong)dbl;
     350                else if (numericalPrecisionPolicy() == QSql::LowPrecisionInt32)
     351                    retval = (int)dbl;
     352                else if (numericalPrecisionPolicy() == QSql::LowPrecisionDouble)
     353                    retval = dbl;
    332354                if (!convert)
    333355                    return QVariant();
     
    336358            return QString::fromAscii(val);
    337359        }
    338         return strtod(val, 0);
     360        return QString::fromAscii(val).toDouble();
    339361    case QVariant::Date:
    340362        if (val[0] == '\0') {
     
    468490
    469491    switch (id) {
    470     case QSqlResult::SetNumericalPrecision:
    471         d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
    472         break;
    473492    default:
    474493        QSqlResult::virtual_hook(id, data);
     
    535554    if (!d->preparedQueriesEnabled)
    536555        return QSqlResult::prepare(query);
    537    
     556
    538557    cleanup();
    539558
     
    542561
    543562    const QString stmtId = qMakePreparedStmtId();
    544     const QString stmt = QString(QLatin1String("PREPARE %1 AS ")).arg(stmtId).append(qReplacePlaceholderMarkers(query));
     563    const QString stmt = QString::fromLatin1("PREPARE %1 AS ").arg(stmtId).append(qReplacePlaceholderMarkers(query));
    545564
    546565    PGresult *result = PQexec(d->driver->connection,
     
    571590    const QString params = qCreateParamString(boundValues(), d->q->driver());
    572591    if (params.isEmpty())
    573         stmt = QString(QLatin1String("EXECUTE %1")).arg(d->preparedStmtId);
     592        stmt = QString::fromLatin1("EXECUTE %1").arg(d->preparedStmtId);
    574593    else
    575         stmt = QString(QLatin1String("EXECUTE %1 (%2)")).arg(d->preparedStmtId).arg(params);
     594        stmt = QString::fromLatin1("EXECUTE %1 (%2)").arg(d->preparedStmtId).arg(params);
    576595
    577596    d->result = PQexec(d->driver->connection,
     
    605624    QPSQLDriver::Protocol serverVersion = QPSQLDriver::Version6;
    606625    PGresult* result = PQexec(connection, "select version()");
    607     int status =  PQresultStatus(result);
     626    int status = PQresultStatus(result);
    608627    if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK) {
    609628        QString val = QString::fromAscii(PQgetvalue(result, 0, 0));
    610         PQclear(result);
    611629        QRegExp rx(QLatin1String("(\\d+)\\.(\\d+)"));
    612630        rx.setMinimal(true); // enforce non-greedy RegExp
     
    649667        }
    650668    }
     669    PQclear(result);
    651670
    652671    if (serverVersion < QPSQLDriver::Version71)
     
    825844    }
    826845    PGresult* res = PQexec(d->connection, "COMMIT");
    827     if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
     846
     847    bool transaction_failed = false;
     848
     849    // XXX
     850    // This hack is used to tell if the transaction has succeeded for the protocol versions of
     851    // PostgreSQL below. For 7.x and other protocol versions we are left in the dark.
     852    // This hack can dissapear once there is an API to query this sort of information.
     853    if (d->pro == QPSQLDriver::Version8 ||
     854        d->pro == QPSQLDriver::Version81 ||
     855        d->pro == QPSQLDriver::Version82) {
     856        transaction_failed = qstrcmp(PQcmdStatus(res), "ROLLBACK") == 0;
     857    }
     858
     859    if (!res || PQresultStatus(res) != PGRES_COMMAND_OK || transaction_failed) {
    828860        PQclear(res);
    829861        setLastError(qMakeError(tr("Could not commit transaction"),
     
    895927    qSplitTableName(tbl, schema);
    896928
     929    if (isIdentifierEscaped(tbl, QSqlDriver::TableName))
     930        tbl = stripDelimiters(tbl, QSqlDriver::TableName);
     931    else
     932        tbl = tbl.toLower();
     933
     934    if (isIdentifierEscaped(schema, QSqlDriver::TableName))
     935        schema = stripDelimiters(schema, QSqlDriver::TableName);
     936    else
     937        schema = schema.toLower();
     938
    897939    switch(d->pro) {
    898940    case QPSQLDriver::Version6:
    899941        stmt = QLatin1String("select pg_att1.attname, int(pg_att1.atttypid), pg_cl.relname "
    900942                "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
    901                 "where lower(pg_cl.relname) = '%1_pkey' "
     943                "where pg_cl.relname = '%1_pkey' "
    902944                "and pg_cl.oid = pg_ind.indexrelid "
    903945                "and pg_att2.attrelid = pg_ind.indexrelid "
     
    910952        stmt = QLatin1String("select pg_att1.attname, pg_att1.atttypid::int, pg_cl.relname "
    911953                "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
    912                 "where lower(pg_cl.relname) = '%1_pkey' "
     954                "where pg_cl.relname = '%1_pkey' "
    913955                "and pg_cl.oid = pg_ind.indexrelid "
    914956                "and pg_att2.attrelid = pg_ind.indexrelid "
     
    927969                "WHERE %1 pg_class.oid IN "
    928970                "(SELECT indexrelid FROM pg_index WHERE indisprimary = true AND indrelid IN "
    929                 " (SELECT oid FROM pg_class WHERE lower(relname) = '%2')) "
     971                " (SELECT oid FROM pg_class WHERE relname = '%2')) "
    930972                "AND pg_attribute.attrelid = pg_class.oid "
    931973                "AND pg_attribute.attisdropped = false "
     
    935977        else
    936978            stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
    937                    "pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema.toLower()));
    938         break;
    939     }
    940 
    941     i.exec(stmt.arg(tbl.toLower()));
     979                   "pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema));
     980        break;
     981    }
     982
     983    i.exec(stmt.arg(tbl));
    942984    while (i.isActive() && i.next()) {
    943985        QSqlField f(i.value(0).toString(), qDecodePSQLType(i.value(1).toInt()));
     
    957999    QString schema;
    9581000    qSplitTableName(tbl, schema);
     1001
     1002    if (isIdentifierEscaped(tbl, QSqlDriver::TableName))
     1003        tbl = stripDelimiters(tbl, QSqlDriver::TableName);
     1004    else
     1005        tbl = tbl.toLower();
     1006
     1007    if (isIdentifierEscaped(schema, QSqlDriver::TableName))
     1008        schema = stripDelimiters(schema, QSqlDriver::TableName);
     1009    else
     1010        schema = schema.toLower();
    9591011
    9601012    QString stmt;
     
    9651017                "int(pg_attribute.attrelid), pg_attribute.attnum "
    9661018                "from pg_class, pg_attribute "
    967                 "where lower(pg_class.relname) = '%1' "
     1019                "where pg_class.relname = '%1' "
    9681020                "and pg_attribute.attnum > 0 "
    9691021                "and pg_attribute.attrelid = pg_class.oid ");
     
    9741026                "pg_attribute.attrelid::int, pg_attribute.attnum "
    9751027                "from pg_class, pg_attribute "
    976                 "where lower(pg_class.relname) = '%1' "
     1028                "where pg_class.relname = '%1' "
    9771029                "and pg_attribute.attnum > 0 "
    9781030                "and pg_attribute.attrelid = pg_class.oid ");
     
    9851037                "left join pg_attrdef on (pg_attrdef.adrelid = "
    9861038                "pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
    987                 "where lower(pg_class.relname) = '%1' "
     1039                "where pg_class.relname = '%1' "
    9881040                "and pg_attribute.attnum > 0 "
    9891041                "and pg_attribute.attrelid = pg_class.oid "
     
    10021054                "pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
    10031055                "where %1 "
    1004                 "and lower(pg_class.relname) = '%2' "
     1056                "and pg_class.relname = '%2' "
    10051057                "and pg_attribute.attnum > 0 "
    10061058                "and pg_attribute.attrelid = pg_class.oid "
     
    10111063        else
    10121064            stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from "
    1013                    "pg_namespace where pg_namespace.nspname = '%1')").arg(schema.toLower()));
     1065                   "pg_namespace where pg_namespace.nspname = '%1')").arg(schema));
    10141066        break;
    10151067    }
    10161068
    10171069    QSqlQuery query(createResult());
    1018     query.exec(stmt.arg(tbl.toLower()));
     1070    query.exec(stmt.arg(tbl));
    10191071    if (d->pro >= QPSQLDriver::Version71) {
    10201072        while (query.next()) {
     
    10831135                // msecs need to be right aligned otherwise psql
    10841136                // interpretes them wrong
    1085                 r = QLatin1String("'") + QString::number(dt.year()) + QLatin1String("-")
    1086                           + QString::number(dt.month()) + QLatin1String("-")
    1087                           + QString::number(dt.day()) + QLatin1String(" ")
    1088                           + tm.toString() + QLatin1String(".")
     1137                r = QLatin1Char('\'') + QString::number(dt.year()) + QLatin1Char('-')
     1138                          + QString::number(dt.month()) + QLatin1Char('-')
     1139                          + QString::number(dt.day()) + QLatin1Char(' ')
     1140                          + tm.toString() + QLatin1Char('.')
    10891141                          + QString::number(tm.msec()).rightJustified(3, QLatin1Char('0'))
    1090                           + QLatin1String("'");
     1142                          + QLatin1Char('\'');
    10911143            } else {
    10921144                r = QLatin1String("NULL");
     
    10991151#ifndef QT_NO_DATESTRING
    11001152            if (field.value().toTime().isValid()) {
    1101                 r = field.value().toTime().toString(Qt::ISODate);
     1153                r = QLatin1Char('\'') + field.value().toTime().toString(QLatin1String("hh:mm:ss.zzz")) + QLatin1Char('\'');
    11021154            } else
    11031155#endif
     
    11051157                r = QLatin1String("NULL");
    11061158            }
     1159            break;
    11071160        case QVariant::String:
    11081161        {
     
    11321185            break;
    11331186        }
     1187        case QVariant::Double: {
     1188            double val = field.value().toDouble();
     1189            if (isnan(val))
     1190                r = QLatin1String("'NaN'");
     1191            else {
     1192                int res = isinf(val);
     1193                if (res == 1)
     1194                    r = QLatin1String("'Infinity'");
     1195                else if (res == -1)
     1196                    r = QLatin1String("'-Infinity'");
     1197                else
     1198                    r = QSqlDriver::formatValue(field, trimStrings);
     1199            }
     1200            break;
     1201        }
    11341202        default:
    11351203            r = QSqlDriver::formatValue(field, trimStrings);
     
    11431211{
    11441212    QString res = identifier;
    1145     if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
     1213    if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
    11461214        res.replace(QLatin1Char('"'), QLatin1String("\"\""));
    11471215        res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
     
    11731241        return false;
    11741242    }
    1175    
     1243
    11761244    int socket = PQsocket(d->connection);
    11771245    if (socket) {
    1178         QString query = QString(QLatin1String("LISTEN %1")).arg(escapeIdentifier(name, QSqlDriver::TableName));
    1179         if (PQresultStatus(PQexec(d->connection, 
    1180                                   d->isUtf8 ? query.toUtf8().constData() 
     1246        QString query = QLatin1String("LISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
     1247        if (PQresultStatus(PQexec(d->connection,
     1248                                  d->isUtf8 ? query.toUtf8().constData()
    11811249                                            : query.toLocal8Bit().constData())
    11821250                          ) != PGRES_COMMAND_OK) {
     
    12081276    }
    12091277
    1210     QString query = QString(QLatin1String("UNLISTEN %1")).arg(escapeIdentifier(name, QSqlDriver::TableName));
    1211     if (PQresultStatus(PQexec(d->connection, 
    1212                               d->isUtf8 ? query.toUtf8().constData() 
     1278    QString query = QLatin1String("UNLISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
     1279    if (PQresultStatus(PQexec(d->connection,
     1280                              d->isUtf8 ? query.toUtf8().constData()
    12131281                                        : query.toLocal8Bit().constData())
    12141282                      ) != PGRES_COMMAND_OK) {
     
    12361304{
    12371305    PQconsumeInput(d->connection);
    1238     PGnotify *notify = PQnotifies(d->connection);
    1239     if (notify) {
     1306
     1307    PGnotify *notify = 0;
     1308    while((notify = PQnotifies(d->connection)) != 0) {
    12401309        QString name(QLatin1String(notify->relname));
    1241 
    12421310        if (d->seid.contains(name))
    12431311            emit notification(name);
    12441312        else
    1245             qWarning("QPSQLDriver: received notification for '%s' which isn't subscribed to.", 
    1246                 qPrintable(name));
     1313            qWarning("QPSQLDriver: received notification for '%s' which isn't subscribed to.",
     1314                    qPrintable(name));
    12471315
    12481316        qPQfreemem(notify);
  • trunk/src/sql/drivers/psql/qsql_psql.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/sql/drivers/sqlite/qsql_sqlite.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6464
    6565QT_BEGIN_NAMESPACE
     66
     67static QString _q_escapeIdentifier(const QString &identifier)
     68{
     69    QString res = identifier;
     70    if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
     71        res.replace(QLatin1Char('"'), QLatin1String("\"\""));
     72        res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
     73        res.replace(QLatin1Char('.'), QLatin1String("\".\""));
     74    }
     75    return res;
     76}
    6677
    6778static QVariant::Type qGetColumnType(const QString &tpName)
     
    112123    sqlite3_stmt *stmt;
    113124
    114     uint skippedStatus: 1; // the status of the fetchNext() that's skipped
    115     uint skipRow: 1; // skip the next fetchNext()?
    116     uint utf8: 1;
     125    bool skippedStatus; // the status of the fetchNext() that's skipped
     126    bool skipRow; // skip the next fetchNext()?
    117127    QSqlRecord rInf;
    118     QSql::NumericalPrecisionPolicy precisionPolicy;
     128    QVector<QVariant> firstRow;
    119129};
    120130
    121 static const uint initial_cache_size = 128;
    122 
    123131QSQLiteResultPrivate::QSQLiteResultPrivate(QSQLiteResult* res) : q(res), access(0),
    124     stmt(0), skippedStatus(false), skipRow(false), utf8(false), precisionPolicy(QSql::HighPrecision)
     132    stmt(0), skippedStatus(false), skipRow(false)
    125133{
    126134}
     
    182190        Q_ASSERT(!initialFetch);
    183191        skipRow = false;
     192        for(int i=0;i<firstRow.count();i++)
     193            values[i]=firstRow[i];
    184194        return skippedStatus;
    185195    }
    186196    skipRow = initialFetch;
     197
     198    if(initialFetch) {
     199        firstRow.clear();
     200        firstRow.resize(sqlite3_column_count(stmt));
     201    }
    187202
    188203    if (!stmt) {
     
    213228                break;
    214229            case SQLITE_FLOAT:
    215                 switch(precisionPolicy) {
     230                switch(q->numericalPrecisionPolicy()) {
    216231                    case QSql::LowPrecisionInt32:
    217232                        values[i + idx] = sqlite3_column_int(stmt, i);
     
    221236                        break;
    222237                    case QSql::LowPrecisionDouble:
    223                         values[i + idx] = sqlite3_column_double(stmt, i);
    224                         break;
    225238                    case QSql::HighPrecision:
    226239                    default:
    227                         values[i + idx] = QString::fromUtf16(static_cast<const ushort *>(
    228                                             sqlite3_column_text16(stmt, i)),
    229                                             sqlite3_column_bytes16(stmt, i) / sizeof(ushort));
     240                        values[i + idx] = sqlite3_column_double(stmt, i);
    230241                        break;
    231242                };
     
    290301            sqlite3_reset(d->stmt);
    291302        break;
    292     case QSqlResult::SetNumericalPrecision:
    293         Q_ASSERT(data);
    294         d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
    295         break;
    296303    default:
    297         QSqlResult::virtual_hook(id, data);
     304        QSqlCachedResult::virtual_hook(id, data);
    298305    }
    299306}
     
    400407        return false;
    401408    }
    402     d->skippedStatus = d->fetchNext(cache(), 0, true);
     409    d->skippedStatus = d->fetchNext(d->firstRow, 0, true);
    403410    if (lastError().isValid()) {
    404411        setSelect(false);
     
    482489    case SimpleLocking:
    483490    case FinishQuery:
     491    case LowPrecisionNumbers:
    484492        return true;
    485493    case QuerySize:
    486494    case NamedPlaceholders:
    487495    case BatchOperations:
    488     case LowPrecisionNumbers:
    489496    case EventNotifications:
    490497    case MultipleResultSets:
     
    499506
    500507    opts.remove(QLatin1Char(' '));
    501     if (opts.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) {
    502         bool ok;
    503         int nt = opts.mid(21).toInt(&ok);
    504         if (ok)
    505             return nt;
     508    foreach(QString option, opts.split(QLatin1Char(';'))) {
     509        if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) {
     510            bool ok;
     511            int nt = option.mid(21).toInt(&ok);
     512            if (ok)
     513                return nt;
     514        }
    506515    }
    507516    return DefaultTimeout;
     517}
     518
     519static int qGetSqliteOpenMode(QString opts)
     520{
     521    opts.remove(QLatin1Char(' '));
     522    foreach(QString option, opts.split(QLatin1Char(';'))) {
     523        if (option == QLatin1String("QSQLITE_OPEN_READONLY"))
     524                return SQLITE_OPEN_READONLY;
     525    }
     526    return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
    508527}
    509528
     
    520539        return false;
    521540
    522     if (sqlite3_open16(db.constData(), &d->access) == SQLITE_OK) {
     541    if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, qGetSqliteOpenMode(conOpts), NULL) == SQLITE_OK) {
    523542        sqlite3_busy_timeout(d->access, qGetSqliteTimeout(conOpts));
    524543        setOpen(true);
     
    632651    QString schema;
    633652    QString table(tableName);
    634     int indexOfSeparator = tableName.indexOf(QLatin1String("."));
     653    int indexOfSeparator = tableName.indexOf(QLatin1Char('.'));
    635654    if (indexOfSeparator > -1) {
    636         schema = tableName.left(indexOfSeparator).append(QLatin1String("."));
     655        schema = tableName.left(indexOfSeparator).append(QLatin1Char('.'));
    637656        table = tableName.mid(indexOfSeparator + 1);
    638657    }
    639     q.exec(QLatin1String("PRAGMA ") + schema + QLatin1String("table_info ('") + table + QLatin1String("')"));
     658    q.exec(QLatin1String("PRAGMA ") + schema + QLatin1String("table_info (") + _q_escapeIdentifier(table) + QLatin1String(")"));
    640659
    641660    QSqlIndex ind;
     
    662681        return QSqlIndex();
    663682
     683    QString table = tblname;
     684    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     685        table = stripDelimiters(table, QSqlDriver::TableName);
     686
    664687    QSqlQuery q(createResult());
    665688    q.setForwardOnly(true);
    666     return qGetTableInfo(q, tblname, true);
     689    return qGetTableInfo(q, table, true);
    667690}
    668691
     
    672695        return QSqlRecord();
    673696
     697    QString table = tbl;
     698    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     699        table = stripDelimiters(table, QSqlDriver::TableName);
     700
    674701    QSqlQuery q(createResult());
    675702    q.setForwardOnly(true);
    676     return qGetTableInfo(q, tbl);
     703    return qGetTableInfo(q, table);
    677704}
    678705
     
    682709}
    683710
    684 QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType /*type*/) const
    685 {
    686     QString res = identifier;
    687     if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
    688         res.replace(QLatin1Char('"'), QLatin1String("\"\""));
    689         res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
    690         res.replace(QLatin1Char('.'), QLatin1String("\".\""));
    691     }
    692     return res;
     711QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const
     712{
     713    Q_UNUSED(type);
     714    return _q_escapeIdentifier(identifier);
    693715}
    694716
  • trunk/src/sql/drivers/sqlite/qsql_sqlite.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/sql/drivers/sqlite2/qsql_sqlite2.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    111111    sqlite_vm *currentMachine;
    112112
    113     uint skippedStatus: 1; // the status of the fetchNext() that's skipped
    114     uint skipRow: 1; // skip the next fetchNext()?
    115     uint utf8: 1;
     113    bool skippedStatus; // the status of the fetchNext() that's skipped
     114    bool skipRow; // skip the next fetchNext()?
     115    bool utf8;
    116116    QSqlRecord rInf;
    117     QSql::NumericalPrecisionPolicy precisionPolicy;
     117    QVector<QVariant> firstRow;
    118118};
    119119
     
    121121
    122122QSQLite2ResultPrivate::QSQLite2ResultPrivate(QSQLite2Result* res) : q(res), access(0), currentTail(0),
    123     currentMachine(0), skippedStatus(false), skipRow(false), utf8(false), precisionPolicy(QSql::HighPrecision)
     123    currentMachine(0), skippedStatus(false), skipRow(false), utf8(false)
    124124{
    125125}
     
    168168        const char* lastDot = strrchr(cnames[i], '.');
    169169        const char* fieldName = lastDot ? lastDot + 1 : cnames[i];
    170         rInf.append(QSqlField(QString::fromAscii(fieldName),
     170       
     171        //remove quotations around the field name if any
     172        QString fieldStr = QString::fromAscii(fieldName);
     173        QLatin1Char quote('\"');
     174        if ( fieldStr.length() > 2 && fieldStr.startsWith(quote) && fieldStr.endsWith(quote)) {
     175            fieldStr = fieldStr.mid(1);
     176            fieldStr.chop(1);
     177        }
     178        rInf.append(QSqlField(fieldStr,
    171179                              nameToType(QString::fromAscii(cnames[i+numCols]))));
    172180    }
     
    186194        Q_ASSERT(!initialFetch);
    187195        skipRow = false;
     196        for(int i=0;i<firstRow.count(); i++)
     197            values[i] = firstRow[i];
    188198        return skippedStatus;
    189199    }
     
    203213    }
    204214
     215    if(initialFetch) {
     216        firstRow.clear();
     217        firstRow.resize(colNum);
     218    }
     219   
    205220    switch(res) {
    206221    case SQLITE_ROW:
     
    253268        d->finalize();
    254269        break;
    255     case QSqlResult::SetNumericalPrecision:
    256         Q_ASSERT(data);
    257         d->precisionPolicy = *reinterpret_cast<QSql::NumericalPrecisionPolicy *>(data);
    258         break;
    259270    default:
    260         QSqlResult::virtual_hook(id, data);
     271        QSqlCachedResult::virtual_hook(id, data);
    261272    }
    262273}
     
    297308    // we have to fetch one row to find out about
    298309    // the structure of the result set
    299     d->skippedStatus = d->fetchNext(cache(), 0, true);
     310    d->skippedStatus = d->fetchNext(d->firstRow, 0, true);
    300311    if (lastError().isValid()) {
    301312        setSelect(false);
     
    386397    d->access = sqlite_open(QFile::encodeName(db), 0, &err);
    387398    if (err) {
    388         setLastError(QSqlError(tr("Error to open database"), QString::fromAscii(err),
     399        setLastError(QSqlError(tr("Error opening database"), QString::fromAscii(err),
    389400                     QSqlError::ConnectionError));
    390401        sqlite_freemem(err);
     
    461472        return true;
    462473
    463     setLastError(QSqlError(tr("Unable to rollback Transaction"),
     474    setLastError(QSqlError(tr("Unable to rollback transaction"),
    464475                           QString::fromAscii(err), QSqlError::TransactionError, res));
    465476    sqlite_freemem(err);
     
    504515    QSqlQuery q(createResult());
    505516    q.setForwardOnly(true);
     517    QString table = tblname;
     518    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     519        table = stripDelimiters(table, QSqlDriver::TableName);
    506520    // finrst find a UNIQUE INDEX
    507     q.exec(QLatin1String("PRAGMA index_list('") + tblname + QLatin1String("');"));
     521    q.exec(QLatin1String("PRAGMA index_list('") + table + QLatin1String("');"));
    508522    QString indexname;
    509523    while(q.next()) {
     
    518532    q.exec(QLatin1String("PRAGMA index_info('") + indexname + QLatin1String("');"));
    519533
    520     QSqlIndex index(tblname, indexname);
     534    QSqlIndex index(table, indexname);
    521535    while(q.next()) {
    522536        QString name = q.value(2).toString();
     
    533547    if (!isOpen())
    534548        return QSqlRecord();
     549    QString table = tbl;
     550    if (isIdentifierEscaped(tbl, QSqlDriver::TableName))
     551        table = stripDelimiters(table, QSqlDriver::TableName);
    535552
    536553    QSqlQuery q(createResult());
     
    548565{
    549566    QString res = identifier;
    550     if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
     567    if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
    551568        res.replace(QLatin1Char('"'), QLatin1String("\"\""));
    552569        res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
  • trunk/src/sql/drivers/sqlite2/qsql_sqlite2.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/sql/drivers/tds/qsql_tds.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    165165extern "C" {
    166166static int CS_PUBLIC qTdsMsgHandler (DBPROCESS* dbproc,
    167                             DBINT /*msgno*/,
     167                            DBINT msgno,
    168168                            int msgstate,
    169169                            int severity,
    170170                            char* msgtext,
    171                             char* /*srvname*/,
     171                            char* srvname,
    172172                            char* /*procname*/,
    173                             int /*line*/)
     173                            int line)
    174174{
    175175    QTDSResultPrivate* p = errs()->value(dbproc);
     
    182182
    183183    if (severity > 0) {
    184         QString errMsg = QString(QLatin1String("%1 (%2)")).arg(QString::fromAscii(msgtext)).arg(
    185                                     msgstate);
     184        QString errMsg = QString::fromLatin1("%1 (Msg %2, Level %3, State %4, Server %5, Line %6)")
     185                         .arg(QString::fromAscii(msgtext))
     186                         .arg(msgno)
     187                         .arg(severity)
     188                         .arg(msgstate)
     189                         .arg(QString::fromAscii(srvname))
     190                         .arg(line);
    186191        p->addErrorMsg(errMsg);
     192        if (severity > 10) {
     193            // Severe messages are really errors in the sense of lastError
     194            errMsg = p->getErrorMsgs();
     195            p->lastError = qMakeError(errMsg, QSqlError::UnknownError, msgno);
     196            p->clearErrorMsgs();
     197        }
    187198    }
    188199
     
    212223
    213224
    214     QString errMsg = QString(QLatin1String("%1 %2\n")).arg(QString::fromAscii(dberrstr)).arg(
    215                                 QString::fromAscii(oserrstr));
     225    QString errMsg = QString::fromLatin1("%1 %2\n").arg(QLatin1String(dberrstr)).arg(
     226                                QLatin1String(oserrstr));
    216227    errMsg += p->getErrorMsgs();
    217228    p->lastError = qMakeError(errMsg, QSqlError::UnknownError, dberr);
     
    294305    // insert d in error handler dict
    295306    errs()->insert(d->dbproc, d);
     307    dbcmd(d->dbproc, "set quoted_identifier on");
     308    dbsqlexec(d->dbproc);
    296309}
    297310
     
    368381                    values[idx] = QVariant(QVariant::String);
    369382                else
    370                     values[idx] = QString::fromLocal8Bit((const char*)d->buffer.at(i * 2));
     383                    values[idx] = QString::fromLocal8Bit((const char*)d->buffer.at(i * 2)).trimmed();
    371384                break;
    372385            case QVariant::ByteArray: {
     
    699712    QSqlQuery t(createResult());
    700713    t.setForwardOnly(true);
     714
     715    QString table = tablename;
     716    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     717        table = stripDelimiters(table, QSqlDriver::TableName);
     718
    701719    QString stmt (QLatin1String("select name, type, length, prec from syscolumns "
    702720                   "where id = (select id from sysobjects where name = '%1')"));
    703     t.exec(stmt.arg(tablename));
     721    t.exec(stmt.arg(table));
    704722    while (t.next()) {
    705723        QSqlField f(t.value(0).toString().simplified(), qDecodeTDSType(t.value(1).toInt()));
     
    748766    else if (field.type() == QVariant::DateTime) {
    749767        if (field.value().toDateTime().isValid()){
    750             r = field.value().toDateTime().toString(QLatin1String("'yyyyMMdd hh:mm:ss'"));
     768            r = field.value().toDateTime().toString(QLatin1String("yyyyMMdd hh:mm:ss"));
     769            r.prepend(QLatin1String("'"));
     770            r.append(QLatin1String("'"));
    751771        } else
    752772            r = QLatin1String("NULL");
     
    771791    QSqlRecord rec = record(tablename);
    772792
    773     QSqlIndex idx(tablename);
    774     if ((!isOpen()) || (tablename.isEmpty()))
     793    QString table = tablename;
     794    if (isIdentifierEscaped(table, QSqlDriver::TableName))
     795        table = stripDelimiters(table, QSqlDriver::TableName);
     796
     797    QSqlIndex idx(table);
     798    if ((!isOpen()) || (table.isEmpty()))
    775799        return QSqlIndex();
    776800
    777801    QSqlQuery t(createResult());
    778802    t.setForwardOnly(true);
    779     t.exec(QString::fromLatin1("sp_helpindex '%1'").arg(tablename));
     803    t.exec(QString::fromLatin1("sp_helpindex '%1'").arg(table));
    780804    if (t.next()) {
    781805        QStringList fNames = t.value(2).toString().simplified().split(QLatin1Char(','));
     
    795819}
    796820
     821QString QTDSDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const
     822{
     823    QString res = identifier;
     824    if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
     825        res.replace(QLatin1Char('"'), QLatin1String("\"\""));
     826        res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
     827        res.replace(QLatin1Char('.'), QLatin1String("\".\""));
     828    }
     829    return res;
     830}
     831
    797832QT_END_NAMESPACE
  • trunk/src/sql/drivers/tds/qsql_tds.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtSql module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    117117    QVariant handle() const;
    118118
     119    QString escapeIdentifier(const QString &identifier, IdentifierType type) const;
     120
    119121protected:
    120122    bool beginTransaction();
Note: See TracChangeset for help on using the changeset viewer.