📄 qsql_ibase.cpp
字号:
} } } if (colCount()) { isc_dsql_free_statement(d->status, &d->stmt, DSQL_close); if (d->isError("Unable to close statement")) return FALSE; cleanup(); } if (d->sqlda) init(d->sqlda->sqld); isc_dsql_execute2(d->status, &d->trans, &d->stmt, 1, d->inda, 0); if (d->isError("Unable to execute query")) return FALSE; setActive(TRUE); return TRUE;}bool QIBaseResult::reset (const QString& query){// qDebug("reset: %s", query.ascii()); if (!driver() || !driver()->isOpen() || driver()->isOpenError()) return FALSE; d->cleanup(); setActive(FALSE); setAt(QSql::BeforeFirst); createDA(d->sqlda); if (!d->transaction()) return FALSE; isc_dsql_allocate_statement(d->status, &d->ibase, &d->stmt); if (d->isError("Could not allocate statement", QSqlError::Statement)) return FALSE; isc_dsql_prepare(d->status, &d->trans, &d->stmt, 0, query.utf8().data(), 3, d->sqlda); if (d->isError("Could not prepare statement", QSqlError::Statement)) return FALSE; if (d->sqlda->sqld > d->sqlda->sqln) { // need more field descriptors int n = d->sqlda->sqld; free(d->sqlda); d->sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(n)); d->sqlda->sqln = n; d->sqlda->version = SQLDA_VERSION1; isc_dsql_describe(d->status, &d->stmt, 1, d->sqlda); if (d->isError("Could not describe statement", QSqlError::Statement)) return FALSE; } initDA(d->sqlda); setSelect(d->isSelect()); if (isSelect()) { init(d->sqlda->sqld); } else { free(d->sqlda); d->sqlda = 0; } isc_dsql_execute(d->status, &d->trans, &d->stmt, 1, 0); if (d->isError("Unable to execute query")) return FALSE; // commit non-select queries (if they are local) if (!isSelect() && !d->commit()) return FALSE; setActive(TRUE); return TRUE;}bool QIBaseResult::gotoNext(QtSqlCachedResult::RowCache* row){ ISC_STATUS stat = isc_dsql_fetch(d->status, &d->stmt, 1, d->sqlda); if (stat == 100) { // no more rows setAt(QSql::AfterLast); return FALSE; } if (d->isError("Could not fetch next item", QSqlError::Statement)) return FALSE; if (!row) // not interested in actual values return TRUE; Q_ASSERT(row); Q_ASSERT((int)row->size() == d->sqlda->sqld); for (int i = 0; i < d->sqlda->sqld; ++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.cast(qIBaseTypeName2(d->sqlda->sqlvar[i].sqltype)); (*row)[i] = 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)[i] = QString::fromUtf8(buf + sizeof(short), *(short*)buf); break; case SQL_INT64: if (d->sqlda->sqlvar[i].sqlscale < 0) (*row)[i] = *(Q_LLONG*)buf * pow(10, d->sqlda->sqlvar[i].sqlscale); else (*row)[i] = QVariant(*(Q_LLONG*)buf); break; case SQL_LONG: if (sizeof(int) == sizeof(long)) //dear compiler: please optimize me out. (*row)[i] = QVariant((int)(*(long*)buf)); else (*row)[i] = QVariant((Q_LLONG)(*(long*)buf)); break; case SQL_SHORT: (*row)[i] = QVariant((int)(*(short*)buf)); break; case SQL_FLOAT: (*row)[i] = QVariant((double)(*(float*)buf)); break; case SQL_DOUBLE: (*row)[i] = QVariant(*(double*)buf); break; case SQL_TIMESTAMP: (*row)[i] = toQDateTime((ISC_TIMESTAMP*)buf); break; case SQL_TYPE_TIME: (*row)[i] = toQTime(*(ISC_TIME*)buf); break; case SQL_TYPE_DATE: (*row)[i] = toQDate(*(ISC_DATE*)buf); break; case SQL_TEXT: (*row)[i] = QString::fromUtf8(buf, size); break; case SQL_BLOB: (*row)[i] = d->fetchBlob((ISC_QUAD*)buf); break; default: // unknown type - don't even try to fetch (*row)[i] = QVariant(); break; } } return TRUE; }int QIBaseResult::size(){ static char sizeInfo[] = {isc_info_sql_records}; char buf[33]; if (!isActive() || !isSelect()) return -1; isc_dsql_sql_info(d->status, &d->stmt, sizeof(sizeInfo), sizeInfo, sizeof(buf), buf); for (char* c = buf + 3; *c != isc_info_end; /*nothing*/) { char ct = *c++; short len = isc_vax_integer(c, 2); c += 2; int val = isc_vax_integer(c, len); c += len; if (ct == isc_info_req_select_count) return val; } return -1;}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("Could not get statement info", QSqlError::Statement)) 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; }/*********************************/QIBaseDriver::QIBaseDriver(QObject * parent, const char * name) : QSqlDriver(parent, name ? name : QIBASE_DRIVER_NAME){ d = new QIBaseDriverPrivate(this);}QIBaseDriver::QIBaseDriver(void *connection, QObject *parent, const char *name) : QSqlDriver(parent, name ? name : QIBASE_DRIVER_NAME){ 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 Transactions:// case QuerySize: case PreparedQueries: case PositionalPlaceholders: case Unicode: case BLOB: return TRUE; default: 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"; QCString usr = user.local8Bit(); QCString pass = password.local8Bit(); usr.truncate(255); pass.truncate(255); QByteArray ba(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[++i], usr.data(), usr.length()); i += usr.length(); ba[i] = isc_dpb_password; ba[++i] = pass.length(); memcpy(&ba[++i], pass.data(), pass.length()); i += pass.length(); ba[i] = isc_dpb_lc_ctype; ba[++i] = sizeof(enc) - 1; memcpy(&ba[++i], enc, sizeof(enc) - 1); i += sizeof(enc) - 1; QString ldb; if (!host.isEmpty()) ldb += host + ":"; ldb += db; isc_attach_database(d->status, 0, (char*)ldb.latin1(), &d->ibase, i, ba.data()); if (d->isError("Error opening database", QSqlError::Connection)) { 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); }}QSqlQuery QIBaseDriver::createQuery() const{ return QSqlQuery(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("Could not start transaction", QSqlError::Transaction);}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("Unable to commit transaction", QSqlError::Transaction);}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("Unable to rollback transaction", QSqlError::Transaction);}QStringList QIBaseDriver::tables(const QString& typeName) const{ QStringList res; if (!isOpen()) return res; int type = typeName.isEmpty() ? (int)QSql::Tables | (int)QSql::Views : typeName.toInt(); QString typeFilter; if (type == (int)QSql::SystemTables) { typeFilter += "RDB$SYSTEM_FLAG != 0"; } else if (type == ((int)QSql::SystemTables | (int)QSql::Views)) { typeFilter += "RDB$SYSTEM_FLAG != 0 OR RDB$VIEW_BLR NOT NULL"; } else { if (!(type & (int)QSql::SystemTables)) typeFilter += "RDB$SYSTEM_FLAG = 0 AND "; if (!(type & (int)QSql::Views)) typeFilter += "RDB$VIEW_BLR IS NULL AND "; if (!(type & (int)QSql::Tables)) typeFilter += "RDB$VIEW_BLR IS NOT NULL AND "; if (!typeFilter.isEmpty()) typeFilter.truncate(typeFilter.length() - 5); } if (!typeFilter.isEmpty()) typeFilter.prepend("where "); QSqlQuery q = createQuery(); q.setForwardOnly(TRUE); if (!q.exec("select rdb$relation_name from rdb$relations " + typeFilter)) return res; while(q.next()) res << q.value(0).toString().stripWhiteSpace(); return res;}QSqlRecord QIBaseDriver::record(const QString& tablename) const{ QSqlRecord rec; if (!isOpen()) return rec; QSqlQuery q = createQuery(); q.setForwardOnly(TRUE); q.exec("SELECT a.RDB$FIELD_NAME, b.RDB$FIELD_TYPE " "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b " "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE " "AND a.RDB$RELATION_NAME = '" + tablename.upper()+ "' " "ORDER BY RDB$FIELD_POSITION"); while (q.next()) { QSqlField field(q.value(0).toString().stripWhiteSpace(), qIBaseTypeName(q.value(1).toInt())); rec.append(field); } return rec;}QSqlRecordInfo QIBaseDriver::recordInfo(const QString& tablename) const{ QSqlRecordInfo rec; if (!isOpen()) return rec; QSqlQuery q = createQuery(); q.setForwardOnly(TRUE); q.exec("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.upper() + "' " "ORDER BY a.RDB$FIELD_POSITION"); while (q.next()) { QVariant::Type type = qIBaseTypeName(q.value(1).toInt()); QSqlFieldInfo field(q.value(0).toString().stripWhiteSpace(), type, q.value(5).toInt(), q.value(2).toInt(), q.value(4).toInt(), QVariant()); rec.append(field); } return rec;}QSqlIndex QIBaseDriver::primaryIndex(const QString &table) const{ QSqlIndex index(table); if (!isOpen()) return index; QSqlQuery q = createQuery(); q.setForwardOnly(TRUE); q.exec("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.upper() + "' " "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().stripWhiteSpace(), qIBaseTypeName(q.value(2).toInt())); index.append(field); //TODO: asc? desc? index.setName(q.value(0).toString()); } return index;}QSqlRecord QIBaseDriver::record(const QSqlQuery& query) const{ QSqlRecord rec; if (query.isActive() && query.driver() == this) { QIBaseResult* result = (QIBaseResult*)query.result(); if (!result->d->sqlda) return rec; XSQLVAR v; for (int i = 0; i < result->d->sqlda->sqld; ++i) { v = result->d->sqlda->sqlvar[i]; QSqlField f(QString::fromLatin1(v.sqlname, v.sqlname_length).stripWhiteSpace(), qIBaseTypeName2(result->d->sqlda->sqlvar[i].sqltype)); rec.append(f); } } return rec;}QSqlRecordInfo QIBaseDriver::recordInfo(const QSqlQuery& query) const{ QSqlRecordInfo rec; if (query.isActive() && query.driver() == this) { QIBaseResult* result = (QIBaseResult*)query.result(); if (!result->d->sqlda) return rec; XSQLVAR v; for (int i = 0; i < result->d->sqlda->sqld; ++i) { v = result->d->sqlda->sqlvar[i]; QSqlFieldInfo f(QString::fromLatin1(v.sqlname, v.sqlname_length).stripWhiteSpace(), qIBaseTypeName2(result->d->sqlda->sqlvar[i].sqltype), -1, v.sqllen, QABS(v.sqlscale), QVariant(), v.sqltype); rec.append(f); } } return rec;}QString QIBaseDriver::formatValue(const QSqlField* field, bool trimStrings) const{ switch (field->type()) { case QVariant::DateTime: { QDateTime datetime = field->value().toDateTime(); if (datetime.isValid()) return "'" + QString::number(datetime.date().year()) + "-" + QString::number(datetime.date().month()) + "-" + QString::number(datetime.date().day()) + " " + QString::number(datetime.time().hour()) + ":" + QString::number(datetime.time().minute()) + ":" + QString::number(datetime.time().second()) + "." + QString::number(datetime.time().msec()).rightJustify(3, '0', TRUE) + "'"; else return "NULL"; } case QVariant::Time: { QTime time = field->value().toTime(); if (time.isValid()) return "'" + QString::number(time.hour()) + ":" + QString::number(time.minute()) + ":" + QString::number(time.second()) + "." + QString::number(time.msec()).rightJustify(3, '0', TRUE) + "'"; else return "NULL"; } case QVariant::Date: { QDate date = field->value().toDate(); if (date.isValid()) return "'" + QString::number(date.year()) + "-" + QString::number(date.month()) + "-" + QString::number(date.day()) + "'"; else return "NULL"; } default: return QSqlDriver::formatValue(field, trimStrings); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -