📄 qsql_ibase.cpp
字号:
if (!prepare(query)) return false; return exec();}bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx){ ISC_STATUS 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)); 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 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 (sizeof(int) == sizeof(long)) //dear compiler: please optimize me out. row[idx] = QVariant(int((*(long*)buf))); else row[idx] = QVariant(qint64((*(long*)buf))); break; case SQL_SHORT: 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: 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; } }// } return -1;#endif}int QIBaseResult::numRowsAffected(){ static char acCountInfo[] = {isc_info_sql_records}; char cCountType; switch (d->queryType) { case isc_info_sql_stmt_select: cCountType = isc_info_req_select_count; break; case isc_info_sql_stmt_update: cCountType = isc_info_req_update_count; break; case isc_info_sql_stmt_delete: cCountType = isc_info_req_delete_count; break; case isc_info_sql_stmt_insert: cCountType = isc_info_req_insert_count; break; } char acBuffer[33]; int iResult = -1; isc_dsql_sql_info(d->status, &d->stmt, sizeof(acCountInfo), acCountInfo, sizeof(acBuffer), acBuffer); if (d->isError(QT_TRANSLATE_NOOP("QIBaseResult", "Could not get statement info"), QSqlError::StatementError)) return -1; for (char *pcBuf = acBuffer + 3; *pcBuf != isc_info_end; /*nothing*/) { char cType = *pcBuf++; short sLength = isc_vax_integer (pcBuf, 2); pcBuf += 2; int iValue = isc_vax_integer (pcBuf, sLength); pcBuf += sLength; if (cType == cCountType) { iResult = iValue; break; } } return iResult;}QSqlRecord QIBaseResult::record() const{ QSqlRecord rec; if (!isActive() || !d->sqlda) return rec; XSQLVAR v; for (int i = 0; i < d->sqlda->sqld; ++i) { v = d->sqlda->sqlvar[i]; QSqlField f(QString::fromLatin1(v.aliasname, v.aliasname_length).simplified(), qIBaseTypeName2(d->sqlda->sqlvar[i].sqltype)); f.setLength(v.sqllen); f.setPrecision(v.sqlscale); f.setSqlType(v.sqltype); rec.append(f); } return rec;}QVariant QIBaseResult::handle() const{ return QVariant(qRegisterMetaType<isc_db_handle>("isc_stmt_handle"), d->stmt);}/*********************************/QIBaseDriver::QIBaseDriver(QObject * parent) : QSqlDriver(parent){ d = new QIBaseDriverPrivate(this);}QIBaseDriver::QIBaseDriver(void *connection, QObject *parent) : QSqlDriver(parent){ d = new QIBaseDriverPrivate(this); d->ibase = (isc_db_handle)connection; setOpen(true); setOpenError(false);}QIBaseDriver::~QIBaseDriver(){ delete d;}bool QIBaseDriver::hasFeature(DriverFeature f) const{ switch (f) { case QuerySize: case NamedPlaceholders: case LastInsertId: case BatchOperations: return false; case Transactions: case PreparedQueries: case PositionalPlaceholders: case Unicode: case BLOB: return true; } return false;}bool QIBaseDriver::open(const QString & db, const QString & user, const QString & password, const QString & host, int /*port*/, const QString & /* connOpts */){ if (isOpen()) close(); static const char enc[8] = "UTF_FSS"; QByteArray usr = user.toLocal8Bit(); QByteArray pass = password.toLocal8Bit(); usr.truncate(255); pass.truncate(255); QByteArray ba; ba.resize(usr.length() + pass.length() + sizeof(enc) + 6); int i = -1; ba[++i] = isc_dpb_version1; ba[++i] = isc_dpb_user_name; ba[++i] = usr.length(); memcpy(ba.data() + ++i, usr.data(), usr.length()); i += usr.length(); ba[i] = isc_dpb_password; ba[++i] = pass.length(); memcpy(ba.data() + ++i, pass.data(), pass.length()); i += pass.length(); ba[i] = isc_dpb_lc_ctype; ba[++i] = sizeof(enc) - 1; memcpy(ba.data() + ++i, enc, sizeof(enc) - 1); i += sizeof(enc) - 1; QString ldb; if (!host.isEmpty()) ldb += host + QLatin1Char(':'); ldb += db; isc_attach_database(d->status, 0, const_cast<char *>(ldb.toLatin1().constData()), &d->ibase, i, ba.data()); if (d->isError(QT_TRANSLATE_NOOP("QIBaseDriver", "Error opening database"), QSqlError::ConnectionError)) { setOpenError(true); return false; } setOpen(true); return true;}void QIBaseDriver::close(){ if (isOpen()) { isc_detach_database(d->status, &d->ibase); d->ibase = 0; setOpen(false); setOpenError(false); }}QSqlResult *QIBaseDriver::createResult() const{ return new QIBaseResult(this);}bool QIBaseDriver::beginTransaction(){ if (!isOpen() || isOpenError()) return false; if (d->trans) return false; isc_start_transaction(d->status, &d->trans, 1, &d->ibase, 0, NULL); return !d->isError(QT_TRANSLATE_NOOP("QIBaseDriver", "Could not start transaction"), QSqlError::TransactionError);}bool QIBaseDriver::commitTransaction(){ if (!isOpen() || isOpenError()) return false; if (!d->trans) return false; isc_commit_transaction(d->status, &d->trans); d->trans = 0; return !d->isError(QT_TRANSLATE_NOOP("QIBaseDriver", "Unable to commit transaction"), QSqlError::TransactionError);}bool QIBaseDriver::rollbackTransaction(){ if (!isOpen() || isOpenError()) return false; if (!d->trans) return false; isc_rollback_transaction(d->status, &d->trans); d->trans = 0; return !d->isError(QT_TRANSLATE_NOOP("QIBaseDriver", "Unable to rollback transaction"), QSqlError::TransactionError);}QStringList QIBaseDriver::tables(QSql::TableType type) const{ QStringList res; if (!isOpen()) return res; QString typeFilter; if (type == QSql::SystemTables) { typeFilter += QLatin1String("RDB$SYSTEM_FLAG != 0"); } else if (type == (QSql::SystemTables | QSql::Views)) { typeFilter += QLatin1String("RDB$SYSTEM_FLAG != 0 OR RDB$VIEW_BLR NOT NULL"); } else { if (!(type & QSql::SystemTables)) typeFilter += QLatin1String("RDB$SYSTEM_FLAG = 0 AND "); if (!(type & QSql::Views)) typeFilter += QLatin1String("RDB$VIEW_BLR IS NULL AND "); if (!(type & QSql::Tables)) typeFilter += QLatin1String("RDB$VIEW_BLR IS NOT NULL AND "); if (!typeFilter.isEmpty()) typeFilter.chop(5); } if (!typeFilter.isEmpty()) typeFilter.prepend(QLatin1String("where ")); QSqlQuery q(createResult()); q.setForwardOnly(true); if (!q.exec(QLatin1String("select rdb$relation_name from rdb$relations ") + typeFilter)) return res; while(q.next()) res << q.value(0).toString().simplified(); return res;}QSqlRecord QIBaseDriver::record(const QString& tablename) const{ QSqlRecord rec; if (!isOpen()) return rec; QSqlQuery q(createResult()); q.setForwardOnly(true); q.exec(QLatin1String("SELECT a.RDB$FIELD_NAME, b.RDB$FIELD_TYPE, b.RDB$FIELD_LENGTH, " "b.RDB$FIELD_SCALE, b.RDB$FIELD_PRECISION, a.RDB$NULL_FLAG " "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b " "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE " "AND a.RDB$RELATION_NAME = '") + tablename.toUpper() + QLatin1String("' " "ORDER BY a.RDB$FIELD_POSITION")); while (q.next()) { int type = q.value(1).toInt(); QSqlField f(q.value(0).toString().simplified(), qIBaseTypeName(type)); f.setLength(q.value(5).toInt()); f.setPrecision(q.value(2).toInt()); f.setRequired(q.value(4).toInt() > 0 ? true : false); f.setSqlType(type); rec.append(f); } return rec;}QSqlIndex QIBaseDriver::primaryIndex(const QString &table) const{ QSqlIndex index(table); if (!isOpen()) return index; QSqlQuery q(createResult()); q.setForwardOnly(true); q.exec(QLatin1String("SELECT a.RDB$INDEX_NAME, b.RDB$FIELD_NAME, d.RDB$FIELD_TYPE " "FROM RDB$RELATION_CONSTRAINTS a, RDB$INDEX_SEGMENTS b, RDB$RELATION_FIELDS c, RDB$FIELDS d " "WHERE a.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' " "AND a.RDB$RELATION_NAME = '") + table.toUpper() + QLatin1String(" 'AND a.RDB$INDEX_NAME = b.RDB$INDEX_NAME " "AND c.RDB$RELATION_NAME = a.RDB$RELATION_NAME " "AND c.RDB$FIELD_NAME = b.RDB$FIELD_NAME " "AND d.RDB$FIELD_NAME = c.RDB$FIELD_SOURCE " "ORDER BY b.RDB$FIELD_POSITION")); while (q.next()) { QSqlField field(q.value(1).toString().simplified(), qIBaseTypeName(q.value(2).toInt())); index.append(field); //TODO: asc? desc? index.setName(q.value(0).toString()); } return index;}QString QIBaseDriver::formatValue(const QSqlField &field, bool trimStrings) const{ switch (field.type()) { case QVariant::DateTime: { QDateTime datetime = field.value().toDateTime(); if (datetime.isValid()) return QLatin1Char('\'') + QString::number(datetime.date().year()) + QLatin1Char('-') + QString::number(datetime.date().month()) + QLatin1Char('-') + QString::number(datetime.date().day()) + QLatin1Char(' ') + QString::number(datetime.time().hour()) + QLatin1Char(':') + QString::number(datetime.time().minute()) + QLatin1Char(':') + QString::number(datetime.time().second()) + QLatin1Char('.') + QString::number(datetime.time().msec()).rightJustified(3, QLatin1Char('0'), true) + QLatin1Char('\''); else return QLatin1String("NULL"); } case QVariant::Time: { QTime time = field.value().toTime(); if (time.isValid()) return QLatin1Char('\'') + QString::number(time.hour()) + QLatin1Char(':') + QString::number(time.minute()) + QLatin1Char(':') + QString::number(time.second()) + QLatin1Char('.') + QString::number(time.msec()).rightJustified(3, QLatin1Char('0'), true) + QLatin1Char('\''); else return QLatin1String("NULL"); } case QVariant::Date: { QDate date = field.value().toDate(); if (date.isValid()) return QLatin1Char('\'') + QString::number(date.year()) + QLatin1Char('-') + QString::number(date.month()) + QLatin1Char('-') + QString::number(date.day()) + QLatin1Char('\''); else return QLatin1String("NULL"); } default: return QSqlDriver::formatValue(field, trimStrings); }}QVariant QIBaseDriver::handle() const{ return QVariant(qRegisterMetaType<isc_db_handle>("isc_db_handle"), d->ibase);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -