Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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());
}
Ejemplo n.º 3
0
bool xBaseCursor::drv_close() {
  if (!d->internalCursor) {
    return false;
  }
  m_opened = false;
  KDbConnection* internalConn = d->internalCursor->connection();
  internalConn->deleteCursor( d->internalCursor );
  return true;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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());
}
Ejemplo n.º 6
0
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;
}