📄 qsql_ibase.cpp
字号:
{ 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*>(encodeString(d->tc, query).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: if (d->inda->sqlvar[para].sqlscale < 0) *((long*)d->inda->sqlvar[para].sqldata) = (long)(val.toDouble() * pow(10.0, d->inda->sqlvar[para].sqlscale * -1)); else *((long*)d->inda->sqlvar[para].sqldata) = (long)val.toLongLong(); break; case SQL_SHORT: if (d->inda->sqlvar[para].sqlscale < 0) *((short*)d->inda->sqlvar[para].sqldata) = (short)(val.toDouble() * pow(10.0, d->inda->sqlvar[para].sqlscale * -1)); else *((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: *((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, d->tc); 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(); } if (d->queryType == isc_info_sql_stmt_exec_procedure) isc_dsql_execute2(d->status, &d->trans, &d->stmt, FBVERSION, d->inda, d->sqlda); else 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; // Not all stored procedures necessarily return values. if (d->queryType == isc_info_sql_stmt_exec_procedure && d->sqlda->sqld == 0) delDA(d->sqlda); if (d->sqlda) init(d->sqlda->sqld); if (!isSelect()) d->commit(); setActive(true); return true; } return false;}bool QIBaseResult::reset (const QString& query){ if (!prepare(query)) return false; return exec();}bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx){ ISC_STATUS stat = 0; // Stored Procedures are special - they populate our d->sqlda when executing, // so we don't have to call isc_dsql_fetch if (d->queryType == isc_info_sql_stmt_exec_procedure) { // the first "fetch" shall succeed, all consecutive ones will fail since // we only have one row to fetch for stored procedures if (rowIdx != 0) stat = 100; } else { stat = isc_dsql_fetch(d->status, &d->stmt, FBVERSION, d->sqlda); } if (stat == 100) { // no more rows setAt(QSql::AfterLastRow); return false; } if (d->isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not fetch next item"), QSqlError::StatementError)) return false; if (rowIdx < 0) // not interested in actual values return true; for (int i = 0; i < d->sqlda->sqld; ++i) { int idx = rowIdx + i; char *buf = d->sqlda->sqlvar[i].sqldata; int size = d->sqlda->sqlvar[i].sqllen; Q_ASSERT(buf); if ((d->sqlda->sqlvar[i].sqltype & 1) && *d->sqlda->sqlvar[i].sqlind) { // null value QVariant v; v.convert(qIBaseTypeName2(d->sqlda->sqlvar[i].sqltype, d->sqlda->sqlvar[i].sqlscale < 0)); row[idx] = v; continue; } switch(d->sqlda->sqlvar[i].sqltype & ~1) { case SQL_VARYING: // pascal strings - a short with a length information followed by the data if (d->tc) row[idx] = d->tc->toUnicode(buf + sizeof(short), *(short*)buf); else row[idx] = QString::fromUtf8(buf + sizeof(short), *(short*)buf); break; case SQL_INT64: if (d->sqlda->sqlvar[i].sqlscale < 0) row[idx] = *(qint64*)buf * pow(10.0, d->sqlda->sqlvar[i].sqlscale); else row[idx] = QVariant(*(qint64*)buf); break; case SQL_LONG: if (d->sqlda->sqlvar[i].sqllen == 4) if (d->sqlda->sqlvar[i].sqlscale < 0) row[idx] = QVariant(*(qint32*)buf * pow(10.0, d->sqlda->sqlvar[i].sqlscale)); else row[idx] = QVariant(*(qint32*)buf); else row[idx] = QVariant(*(qint64*)buf); break; case SQL_SHORT: if (d->sqlda->sqlvar[i].sqlscale < 0) row[idx] = QVariant(long((*(short*)buf)) * pow(10.0, d->sqlda->sqlvar[i].sqlscale)); else row[idx] = QVariant(int((*(short*)buf))); break; case SQL_FLOAT: row[idx] = QVariant(double((*(float*)buf))); break; case SQL_DOUBLE: row[idx] = QVariant(*(double*)buf); break; case SQL_TIMESTAMP: row[idx] = fromTimeStamp(buf); break; case SQL_TYPE_TIME: row[idx] = fromTime(buf); break; case SQL_TYPE_DATE: row[idx] = fromDate(buf); break; case SQL_TEXT: if (d->tc) row[idx] = d->tc->toUnicode(buf, size); else row[idx] = QString::fromUtf8(buf, size); break; case SQL_BLOB: row[idx] = d->fetchBlob((ISC_QUAD*)buf); break; case SQL_ARRAY: row[idx] = d->fetchArray(i, (ISC_QUAD*)buf); break; default: // unknown type - don't even try to fetch row[idx] = QVariant(); break; } } return true;}int QIBaseResult::size(){ return -1;#if 0 /// ### FIXME static char sizeInfo[] = {isc_info_sql_records}; char buf[64]; //qDebug() << sizeInfo; if (!isActive() || !isSelect()) return -1; char ct; short len; int val = 0;// while(val == 0) { isc_dsql_sql_info(d->status, &d->stmt, sizeof(sizeInfo), sizeInfo, sizeof(buf), buf);// isc_database_info(d->status, &d->ibase, sizeof(sizeInfo), sizeInfo, sizeof(buf), buf); for(int i = 0; i < 66; ++i) qDebug() << QString::number(buf[i]); for (char* c = buf + 3; *c != isc_info_end; /*nothing*/) { ct = *(c++); len = isc_vax_integer(c, 2); c += 2; val = isc_vax_integer(c, len); c += len; qDebug() << "size" << val; if (ct == isc_info_req_select_count) return val; } //qDebug() << "size -1"; return -1; unsigned int i, result_size; if (buf[0] == isc_info_sql_records) { i = 3; result_size = isc_vax_integer(&buf[1],2); while (buf[i] != isc_info_end && i < result_size) { len = (short)isc_vax_integer(&buf[i+1],2); if (buf[i] == isc_info_req_select_count) return (isc_vax_integer(&buf[i+3],len)); i += len+3; } }// }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -