int main(int argc, char** argv) { KAboutData aboutData("kexicrash", 0, kxi18n("kexicrash"), "0.1"); KCmdLineArgs::init(argc, argv, &aboutData); KApplication app; KDbDriverManager manager; KDbDriver* driver = manager.driver("sqlite3"); KDbConnectionData cd; QString fname("d.kexi"); cd.setFileName(fname); KDbConnection *connection = driver->createConnection(cd); connection->connect(); connection->useDatabase(fname); KDbCursor *cursor = connection->executeQuery("select * from abc", KDbCursor::Buffered); //cursor->moveFirst(); if (cursor) { cursor->moveNext(); cursor->moveNext(); cursor->moveNext(); cursor->movePrev(); cursor->moveNext(); // <---- Crashes here } return 0; }
tristate Part::remove(KexiPart::Item *item) { Q_ASSERT(item); KDbConnection *conn = KexiMainWindowIface::global()->project()->dbConnection(); if (!conn) return false; return conn->removeObject(item->identifier()); }
bool xBaseCursor::drv_close() { if (!d->internalCursor) { return false; } m_opened = false; KDbConnection* internalConn = d->internalCursor->connection(); internalConn->deleteCursor( d->internalCursor ); return true; }
tristate KexiQueryView::executeQuery(KDbQuerySchema *query) { if (!query) return false; KexiUtils::WaitCursor wait; KDbCursor *oldCursor = d->cursor; qDebug() << query->parameters(); bool ok; KDbConnection * conn = KexiMainWindowIface::global()->project()->dbConnection(); { KexiUtils::WaitCursorRemover remover; d->currentParams = KexiQueryParameters::getParameters(this, *conn->driver(), query, &ok); } if (!ok) {//input cancelled return cancelled; } d->cursor = conn->executeQuery(query, d->currentParams); if (!d->cursor) { window()->setStatus( conn, xi18n("Query executing failed.")); //! @todo also provide server result and sql statement return false; } setData(d->cursor); //! @todo remove close() when dynamic cursors arrive if (!d->cursor->close()) { return false; } if (oldCursor) oldCursor->connection()->deleteCursor(oldCursor); //! @todo maybe allow writing and inserting for single-table relations? tableView()->setReadOnly(true); //! @todo maybe allow writing and inserting for single-table relations? //set data model itself read-only too tableView()->data()->setReadOnly(true); tableView()->setInsertingEnabled(false); return true; }
void KexiDBSubForm::setFormName(const QString &name) { if (m_formName == name) return; m_formName = name; //assign, even if the name points to nowhere if (name.isEmpty()) { delete m_widget; m_widget = 0; //updateScrollBars(); return; } QWidget *pw = parentWidget(); KexiFormView *view = 0; QSet<QString> names; while (pw) { if (KexiUtils::objectIsA(pw, "KexiDBSubForm")) { if (names.contains(pw->objectName())) { //! @todo error message return; // Be sure to don't run into a endless-loop cause of recursive subforms. } names.insert(pw->objectName()); } else if (! view && KexiUtils::objectIsA(pw, "KexiFormView")) { view = static_cast<KexiFormView*>(pw); // we need a KexiFormView* } pw = pw->parentWidget(); } if (!view || !view->window() || !KexiMainWindowIface::global()->project()->dbConnection()) return; KDbConnection *conn = KexiMainWindowIface::global()->project()->dbConnection(); // we check if there is a form with this name int id; if (true != KDb::idForObjectName(*conn, &id, name, KexiPart::FormObjectType)) { return; } if ((id == 0) || (id == view->window()->id())) // == our form return; // because of recursion when loading // we create the container widget delete m_widget; m_widget = new QWidget(viewport()); m_widget->setObjectName("KexiDBSubForm_widget"); m_widget->show(); //addChild(m_widget); m_form = new KFormDesigner::Form(m_parentForm); m_form->setObjectName(QString("KFormDesigner::Form_") + objectName()); m_form->createToplevel(m_widget); // and load the sub form QString data; tristate res = conn->loadDataBlock(id, &data, QString()); if (res == true) res = KFormDesigner::FormIO::loadFormFromString(m_form, m_widget, &data); if (res != true) { delete m_widget; m_widget = 0; //updateScrollBars(); m_formName.clear(); return; } m_form->setMode(KFormDesigner::Form::DataMode); // Install event filters on the whole newly created form KFormDesigner::ObjectTreeItem *tree = m_parentForm->objectTree()->lookup(QObject::objectName()); //KFormDesigner::installRecursiveEventFilter(this, tree->eventEater()); }
bool KexiCSVExport::exportData(KDbTableOrQuerySchema *tableOrQuery, const Options& options, int recordCount, QTextStream *predefinedTextStream) { KDbConnection* conn = tableOrQuery->connection(); if (!conn) return false; KDbQuerySchema* query = tableOrQuery->query(); QList<QVariant> queryParams; if (!query) { query = tableOrQuery->table()->query(); } else { queryParams = KexiMainWindowIface::global()->currentParametersForQuery(query->id()); } if (recordCount == -1) recordCount = KDb::recordCount(tableOrQuery, queryParams); if (recordCount == -1) return false; //! @todo move this to non-GUI location so it can be also used via command line //! @todo add a "finish" page with a progressbar. //! @todo look at recordCount whether the data is really large; //! if so: avoid copying to clipboard (or ask user) because of system memory //! @todo OPTIMIZATION: use fieldsExpanded(true /*UNIQUE*/) //! @todo OPTIMIZATION? (avoid multiple data retrieving) look for already fetched data within KexiProject.. KDbQueryColumnInfo::Vector fields(query->fieldsExpanded(KDbQuerySchema::WithInternalFields)); QString buffer; QScopedPointer<QSaveFile> kSaveFile; QTextStream *stream = 0; QScopedPointer<QTextStream> kSaveFileTextStream; const bool copyToClipboard = options.mode == Clipboard; if (copyToClipboard) { //! @todo (during exporting): enlarge bufSize by factor of 2 when it became too small int bufSize = qMin((recordCount < 0 ? 10 : recordCount) * fields.count() * 20, 128000); buffer.reserve(bufSize); if (buffer.capacity() < bufSize) { qWarning() << "Cannot allocate memory for " << bufSize << " characters"; return false; } } else { if (predefinedTextStream) { stream = predefinedTextStream; } else { if (options.fileName.isEmpty()) {//sanity qWarning() << "Fname is empty"; return false; } kSaveFile.reset(new QSaveFile(options.fileName)); qDebug() << "QSaveFile Filename:" << kSaveFile->fileName(); if (kSaveFile->open(QIODevice::WriteOnly)) { kSaveFileTextStream.reset(new QTextStream(kSaveFile.data())); stream = kSaveFileTextStream.data(); qDebug() << "have a stream"; } if (QFileDevice::NoError != kSaveFile->error() || !stream) {//sanity qWarning() << "Status != 0 or stream == 0"; //! @todo show error return false; } } } //! @todo escape strings #define _ERR \ if (kSaveFile) { kSaveFile->cancelWriting(); } \ return false #define APPEND(what) \ if (copyToClipboard) buffer.append(what); else (*stream) << (what) // use native line ending for copying, RFC 4180 one for saving to file #define APPEND_EOLN \ if (copyToClipboard) { APPEND('\n'); } else { APPEND("\r\n"); } qDebug() << 0 << "Columns: " << query->fieldsExpanded().count(); // 0. Cache information const int fieldsCount = query->fieldsExpanded().count(); //real fields count without internals const QByteArray delimiter(options.delimiter.left(1).toLatin1()); const bool hasTextQuote = !options.textQuote.isEmpty(); const QString textQuote(options.textQuote.left(1)); const QByteArray escapedTextQuote((textQuote + textQuote).toLatin1()); //ok? //cache for faster checks QScopedArrayPointer<bool> isText(new bool[fieldsCount]); QScopedArrayPointer<bool> isDateTime(new bool[fieldsCount]); QScopedArrayPointer<bool> isTime(new bool[fieldsCount]); QScopedArrayPointer<bool> isBLOB(new bool[fieldsCount]); QScopedArrayPointer<int> visibleFieldIndex(new int[fieldsCount]); // bool isInteger[fieldsCount]; //cache for faster checks // bool isFloatingPoint[fieldsCount]; //cache for faster checks for (int i = 0; i < fieldsCount; i++) { KDbQueryColumnInfo* ci; const int indexForVisibleLookupValue = fields[i]->indexForVisibleLookupValue(); if (-1 != indexForVisibleLookupValue) { ci = query->expandedOrInternalField(indexForVisibleLookupValue); visibleFieldIndex[i] = indexForVisibleLookupValue; } else { ci = fields[i]; visibleFieldIndex[i] = i; } const KDbField::Type t = ci->field->type(); // cache: evaluating type of expressions can be expensive isText[i] = KDbField::isTextType(t); isDateTime[i] = t == KDbField::DateTime; isTime[i] = t == KDbField::Time; isBLOB[i] = t == KDbField::BLOB; // isInteger[i] = KDbField::isIntegerType(t) // || t == KDbField::Boolean; // isFloatingPoint[i] = KDbField::isFPNumericType(t); } // 1. Output column names if (options.addColumnNames) { for (int i = 0; i < fieldsCount; i++) { //qDebug() << "Adding column names"; if (i > 0) { APPEND(delimiter); } if (hasTextQuote) { APPEND(textQuote + fields[i]->captionOrAliasOrName().replace(textQuote, escapedTextQuote) + textQuote); } else { APPEND(fields[i]->captionOrAliasOrName()); } } APPEND_EOLN } KexiGUIMessageHandler handler; KDbCursor *cursor = conn->executeQuery(query, queryParams); if (!cursor) { handler.showErrorMessage(conn->result()); _ERR; } for (cursor->moveFirst(); !cursor->eof() && !cursor->result().isError(); cursor->moveNext()) { //qDebug() << "Adding records"; const int realFieldCount = qMin(cursor->fieldCount(), fieldsCount); for (int i = 0; i < realFieldCount; i++) { const int real_i = visibleFieldIndex[i]; if (i > 0) { APPEND(delimiter); } if (cursor->value(real_i).isNull()) { continue; } if (isText[real_i]) { if (hasTextQuote) APPEND(textQuote + QString(cursor->value(real_i).toString()).replace(textQuote, escapedTextQuote) + textQuote); else APPEND(cursor->value(real_i).toString()); } else if (isDateTime[real_i]) { //avoid "T" in ISO DateTime APPEND(cursor->value(real_i).toDateTime().date().toString(Qt::ISODate) + " " + cursor->value(real_i).toDateTime().time().toString(Qt::ISODate)); } else if (isTime[real_i]) { //time is temporarily stored as null date + time... APPEND(cursor->value(real_i).toTime().toString(Qt::ISODate)); } else if (isBLOB[real_i]) { //BLOB is escaped in a special way if (hasTextQuote) //! @todo add options to suppport other types from KDbBLOBEscapingType enum... APPEND(textQuote + KDb::escapeBLOB(cursor->value(real_i).toByteArray(), KDb::BLOBEscapeHex) + textQuote); else APPEND(KDb::escapeBLOB(cursor->value(real_i).toByteArray(), KDb::BLOBEscapeHex)); } else {//other types APPEND(cursor->value(real_i).toString()); } } APPEND_EOLN } if (copyToClipboard) buffer.squeeze(); if (!conn->deleteCursor(cursor)) { handler.showErrorMessage(conn->result()); _ERR; } if (copyToClipboard) QApplication::clipboard()->setText(buffer, QClipboard::Clipboard); qDebug() << "Done"; if (kSaveFile) { stream->flush(); if (!kSaveFile->commit()) { qWarning() << "Error commiting the file" << kSaveFile->fileName(); } } return true; }