📄 qsql_ibase.cpp
字号:
return buffer;}QVariant QIBaseResultPrivate::fetchArray(int pos, ISC_QUAD *arr){ QList<QVariant> list; ISC_ARRAY_DESC desc; if (!arr) return list; QByteArray relname(sqlda->sqlvar[pos].relname, sqlda->sqlvar[pos].relname_length); QByteArray sqlname(sqlda->sqlvar[pos].aliasname, sqlda->sqlvar[pos].aliasname_length); isc_array_lookup_bounds(status, &ibase, &trans, relname.data(), sqlname.data(), &desc); if (isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not find array"), QSqlError::StatementError)) return list; int arraySize = 1, subArraySize; short dimensions = desc.array_desc_dimensions; short *numElements = new short[dimensions]; for(int i = 0; i < dimensions; ++i) { subArraySize = (desc.array_desc_bounds[i].array_bound_upper - desc.array_desc_bounds[i].array_bound_lower + 1); numElements[i] = subArraySize; arraySize = subArraySize * arraySize; } ISC_LONG bufLen; QByteArray ba; /* varying arrayelements are stored with 2 trailing null bytes indicating the length of the string */ if (desc.array_desc_dtype == blr_varying || desc.array_desc_dtype == blr_varying2) { desc.array_desc_length += 2; bufLen = desc.array_desc_length * arraySize * sizeof(short); } else { bufLen = desc.array_desc_length * arraySize; } ba.resize(int(bufLen)); isc_array_get_slice(status, &ibase, &trans, arr, &desc, ba.data(), &bufLen); if (isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not get array data"), QSqlError::StatementError)) return list; readArrayBuffer(list, ba.data(), 0, numElements, &desc); delete[] numElements; return QVariant(list);}template<typename T>static char* fillList(char *buffer, const QList<QVariant> &list, T* = 0){ for (int i = 0; i < list.size(); ++i) { T val; val = qvariant_cast<T>(list.at(i)); memcpy(buffer, &val, sizeof(T)); buffer += sizeof(T); } return buffer;}template<>static char* fillList<float>(char *buffer, const QList<QVariant> &list, float*){ for (int i = 0; i < list.size(); ++i) { double val; float val2 = 0; val = qvariant_cast<double>(list.at(i)); val2 = (float)val; memcpy(buffer, &val2, sizeof(float)); buffer += sizeof(float); } return buffer;}static char* qFillBufferWithString(char *buffer, const QString& string, short buflen, bool varying, bool array){ QByteArray str = string.toUtf8(); // keep a copy of the string alive in this scope if (varying) { short tmpBuflen = buflen; if (str.length() < buflen) buflen = str.length(); if (array) { // interbase stores varying arrayelements different than normal varying elements memcpy(buffer, str.data(), buflen); memset(buffer + buflen, 0, tmpBuflen - buflen); } else { *(short*)buffer = buflen; // first two bytes is the length memcpy(buffer + sizeof(short), str.data(), buflen); } buffer += tmpBuflen; } else { str = str.leftJustified(buflen, ' ', true); memcpy(buffer, str.data(), buflen); buffer += buflen; } return buffer;}static char* createArrayBuffer(char *buffer, const QList<QVariant> &list, QVariant::Type type, short curDim, ISC_ARRAY_DESC *arrayDesc, QString& error){ int i; ISC_ARRAY_BOUND *bounds = arrayDesc->array_desc_bounds; short dim = arrayDesc->array_desc_dimensions - 1; int elements = (bounds[curDim].array_bound_upper - bounds[curDim].array_bound_lower + 1); if (list.size() != elements) { // size mismatch error = QLatin1String("Expected size: %1. Supplied size: %2"); error = QLatin1String("Array size mismatch. Fieldname: %1 ") + error.arg(elements).arg(list.size()); return 0; } if (curDim != dim) { for(i = 0; i < list.size(); ++i) { if (list.at(i).type() != QVariant::List) { // dimensions mismatch error = QLatin1String("Array dimensons mismatch. Fieldname: %1"); return 0; } buffer = createArrayBuffer(buffer, list.at(i).toList(), type, curDim + 1, arrayDesc, error); if (!buffer) return 0; } } else { switch(type) { case QVariant::Int: case QVariant::UInt: if (arrayDesc->array_desc_dtype == blr_short) buffer = fillList<short>(buffer, list); else buffer = fillList<int>(buffer, list); break; case QVariant::Double: if (arrayDesc->array_desc_dtype == blr_float) buffer = fillList<float>(buffer, list, static_cast<float *>(0)); else buffer = fillList<double>(buffer, list); break; case QVariant::LongLong: buffer = fillList<qint64>(buffer, list); break; case QVariant::ULongLong: buffer = fillList<quint64>(buffer, list); break; case QVariant::String: for (i = 0; i < list.size(); ++i) buffer = qFillBufferWithString(buffer, list.at(i).toString(), arrayDesc->array_desc_length, arrayDesc->array_desc_dtype == blr_varying, true); break; case QVariant::Date: for (i = 0; i < list.size(); ++i) { *((ISC_DATE*)buffer) = toDate(list.at(i).toDate()); buffer += sizeof(ISC_DATE); } break; case QVariant::Time: for (i = 0; i < list.size(); ++i) { *((ISC_TIME*)buffer) = toTime(list.at(i).toTime()); buffer += sizeof(ISC_TIME); } break; case QVariant::DateTime: for (i = 0; i < list.size(); ++i) { *((ISC_TIMESTAMP*)buffer) = toTimeStamp(list.at(i).toDateTime()); buffer += sizeof(ISC_TIMESTAMP); } break; default: break; } } return buffer;}bool QIBaseResultPrivate::writeArray(int column, const QList<QVariant> &list){ QString error; ISC_QUAD *arrayId = (ISC_QUAD*) inda->sqlvar[column].sqldata; ISC_ARRAY_DESC desc; QByteArray relname(inda->sqlvar[column].relname, inda->sqlvar[column].relname_length); QByteArray sqlname(inda->sqlvar[column].aliasname, inda->sqlvar[column].aliasname_length); isc_array_lookup_bounds(status, &ibase, &trans, relname.data(), sqlname.data(), &desc); if (isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not find array"), QSqlError::StatementError)) return false; short arraySize = 1; ISC_LONG bufLen; QList<QVariant> subList = list; short dimensions = desc.array_desc_dimensions; for(int i = 0; i < dimensions; ++i) { arraySize *= (desc.array_desc_bounds[i].array_bound_upper - desc.array_desc_bounds[i].array_bound_lower + 1); } /* varying arrayelements are stored with 2 trailing null bytes indicating the length of the string */ if (desc.array_desc_dtype == blr_varying || desc.array_desc_dtype == blr_varying2) desc.array_desc_length += 2; bufLen = desc.array_desc_length * arraySize; QByteArray ba; ba.resize(int(bufLen)); if (list.size() > arraySize) { error = QLatin1String("Array size missmatch: size of %1 is %2, size of provided list is %3"); error = error.arg(QLatin1String(sqlname)).arg(arraySize).arg(list.size()); q->setLastError(QSqlError(error, QLatin1String(""), QSqlError::StatementError)); return false; } if (!createArrayBuffer(ba.data(), list, qIBaseTypeName(desc.array_desc_dtype), 0, &desc, error)) { q->setLastError(QSqlError(error.arg(QLatin1String(sqlname)), QLatin1String(""), QSqlError::StatementError)); return false; } /* readjust the buffer size*/ if (desc.array_desc_dtype == blr_varying || desc.array_desc_dtype == blr_varying2) desc.array_desc_length -= 2; isc_array_put_slice(status, &ibase, &trans, arrayId, &desc, ba.data(), &bufLen); return true;}bool QIBaseResultPrivate::isSelect(){ char acBuffer[9]; char qType = isc_info_sql_stmt_type; isc_dsql_sql_info(status, &stmt, 1, &qType, sizeof(acBuffer), acBuffer); if (isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not get query info"), QSqlError::StatementError)) return false; int iLength = isc_vax_integer(&acBuffer[1], 2); queryType = isc_vax_integer(&acBuffer[3], iLength); return (queryType == isc_info_sql_stmt_select);}bool QIBaseResultPrivate::transaction(){ if (trans) return true; if (db->d->trans) { localTransaction = false; trans = db->d->trans; return true; } localTransaction = true; isc_start_transaction(status, &trans, 1, &ibase, 0, NULL); if (isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not start transaction"), QSqlError::TransactionError)) return false; return true;}// does nothing if the transaction is on the// driver levelbool QIBaseResultPrivate::commit(){ if (!trans) return false; // don't commit driver's transaction, the driver will do it for us if (!localTransaction) return true; isc_commit_transaction(status, &trans); trans = 0; return !isError(QT_TRANSLATE_NOOP("QIBaseResult", "Unable to commit transaction"), QSqlError::TransactionError);}//////////QIBaseResult::QIBaseResult(const QIBaseDriver* db): QSqlCachedResult(db){ d = new QIBaseResultPrivate(this, db);}QIBaseResult::~QIBaseResult(){ delete d;}bool QIBaseResult::prepare(const QString& query){ //qDebug("prepare: %s\n", qPrintable(query)); if (!driver() || !driver()->isOpen() || driver()->isOpenError()) return false; d->cleanup(); setActive(false); setAt(QSql::BeforeFirstRow); createDA(d->sqlda); createDA(d->inda); if (!d->transaction()) return false; isc_dsql_allocate_statement(d->status, &d->ibase, &d->stmt); if (d->isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not allocate statement"), QSqlError::StatementError)) return false; isc_dsql_prepare(d->status, &d->trans, &d->stmt, 0, const_cast<char*>(query.toUtf8().constData()), FBVERSION, d->sqlda); if (d->isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not prepare statement"), QSqlError::StatementError)) return false; isc_dsql_describe_bind(d->status, &d->stmt, FBVERSION, d->inda); if (d->isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not describe input statement"), QSqlError::StatementError)) return false; if (d->inda->sqld > d->inda->sqln) { enlargeDA(d->inda, d->inda->sqld); isc_dsql_describe_bind(d->status, &d->stmt, FBVERSION, d->inda); if (d->isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not describe input statement"), QSqlError::StatementError)) return false; } initDA(d->inda); if (d->sqlda->sqld > d->sqlda->sqln) { // need more field descriptors enlargeDA(d->sqlda, d->sqlda->sqld); isc_dsql_describe(d->status, &d->stmt, FBVERSION, d->sqlda); if (d->isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not describe statement"), QSqlError::StatementError)) return false; } initDA(d->sqlda); setSelect(d->isSelect()); if (!isSelect()) { free(d->sqlda); d->sqlda = 0; } return true;}bool QIBaseResult::exec(){ bool ok = true; if (!d->trans) d->transaction(); if (!driver() || !driver()->isOpen() || driver()->isOpenError()) return false; setActive(false); setAt(QSql::BeforeFirstRow); if (d->inda) { QVector<QVariant>& values = boundValues(); int i; if (values.count() > d->inda->sqld) { qWarning("QIBaseResult::exec: Parameter mismatch, expected %d, got %d parameters", d->inda->sqld, values.count()); return false; } int para = 0; for (i = 0; i < values.count(); ++i) { para = i; if (!d->inda->sqlvar[para].sqldata) // skip unknown datatypes continue; const QVariant val(values[i]); if (d->inda->sqlvar[para].sqltype & 1) { if (val.isNull()) { // set null indicator *(d->inda->sqlvar[para].sqlind) = -1; // and set the value to 0, otherwise it would count as empty string. // it seems to be working with just setting sqlind to -1 //*((char*)d->inda->sqlvar[para].sqldata) = 0; continue; } // a value of 0 means non-null. *(d->inda->sqlvar[para].sqlind) = 0; } switch(d->inda->sqlvar[para].sqltype & ~1) { case SQL_INT64: if (d->inda->sqlvar[para].sqlscale < 0) *((qint64*)d->inda->sqlvar[para].sqldata) = qint64(val.toDouble() * pow(10.0, d->inda->sqlvar[para].sqlscale * -1)); else *((qint64*)d->inda->sqlvar[para].sqldata) = val.toLongLong(); break; case SQL_LONG: *((long*)d->inda->sqlvar[para].sqldata) = (long)val.toLongLong(); break; case SQL_SHORT: *((short*)d->inda->sqlvar[para].sqldata) = (short)val.toInt(); break; case SQL_FLOAT: *((float*)d->inda->sqlvar[para].sqldata) = (float)val.toDouble(); break; case SQL_DOUBLE: *((double*)d->inda->sqlvar[para].sqldata) = val.toDouble(); break; case SQL_TIMESTAMP: *((ISC_TIMESTAMP*)d->inda->sqlvar[para].sqldata) = toTimeStamp(val.toDateTime()); break; case SQL_TYPE_TIME: *((ISC_TIME*)d->inda->sqlvar[para].sqldata) = toTime(val.toTime()); break; case SQL_TYPE_DATE: qDebug() << "bindig date"; *((ISC_DATE*)d->inda->sqlvar[para].sqldata) = toDate(val.toDate()); break; case SQL_VARYING: case SQL_TEXT: qFillBufferWithString(d->inda->sqlvar[para].sqldata, val.toString(), d->inda->sqlvar[para].sqllen, (d->inda->sqlvar[para].sqltype & ~1) == SQL_VARYING, false); break; case SQL_BLOB: ok &= d->writeBlob(para, val.toByteArray()); break; case SQL_ARRAY: ok &= d->writeArray(para, val.toList()); break; default: qWarning("QIBaseResult::exec: Unknown datatype %d", d->inda->sqlvar[para].sqltype & ~1); break; } } } if (ok) { if (colCount()) { isc_dsql_free_statement(d->status, &d->stmt, DSQL_close); if (d->isError(QT_TRANSLATE_NOOP("QIBaseResult", "Unable to close statement"))) return false; cleanup(); } isc_dsql_execute(d->status, &d->trans, &d->stmt, FBVERSION, d->inda); if (d->isError(QT_TRANSLATE_NOOP("QIBaseResult", "Unable to execute query"))) return false; if (d->sqlda) init(d->sqlda->sqld); if (d->queryType != isc_info_sql_stmt_select) d->commit(); setActive(true); return true; } return false;}bool QIBaseResult::reset (const QString& query){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -