// This isn't going to work right now as it uses d->mysqlrow QVariant MysqlCursor::value(int pos) { if (!d->mysqlrow || pos >= m_fieldCount || d->mysqlrow[pos] == 0) return QVariant(); KDbField *f = (m_visibleFieldsExpanded && pos < m_visibleFieldsExpanded->count()) ? m_visibleFieldsExpanded->at(pos)->field() : nullptr; //! @todo js: use MYSQL_FIELD::type here! bool ok; return KDb::cstringToVariant(d->mysqlrow[pos], f ? f->type() : KDbField::Text, &ok, d->lengths[pos]); }
void KexiDataSourcePage::slotFieldSelected() { KDbField::Type dataType = KDbField::InvalidType; #ifdef KEXI_AUTOFIELD_FORM_WIDGET_SUPPORT //! @todo this should also work for expressions KDbField *field = m_fieldListView->schema()->field( m_widgetDataSourceCombo->fieldOrExpression()); #else KDbField *field = m_tableOrQuerySchema->field( m_widgetDataSourceCombo->fieldOrExpression()); //temp #endif if (field) dataType = field->type(); emit dataSourceFieldOrExpressionChanged( m_widgetDataSourceCombo->fieldOrExpression(), m_widgetDataSourceCombo->fieldOrExpressionCaption(), dataType ); }
/* As with sqlite, the DB library returns all values (including numbers) as strings. So just put that string in a QVariant and let KDb deal with it. */ bool MysqlCursor::drv_storeCurrentRecord(KDbRecordData* data) const { // mysqlDebug() << "position is " << (long)m_at; if (d->numRows == 0) return false; if (!m_visibleFieldsExpanded) {//simple version: without types for (int i = 0; i < m_fieldCount; ++i) { (*data)[i] = QString::fromUtf8(d->mysqlrow[i], d->lengths[i]); } return true; } for (int i = 0; i < m_fieldCount; ++i) { KDbField *f = m_visibleFieldsExpanded->at(i)->field(); bool ok; (*data)[i] = KDb::cstringToVariant(d->mysqlrow[i], f ? f->type() : KDbField::Text, &ok, d->lengths[i]); if (!ok) { return false; } } return true; }
void KDbRelationship::createIndices(KDbQuerySchema *query, KDbField *field1, KDbField *field2) { if (!field1 || !field2 || !query) { kdbWarning() << "!masterField || !detailsField || !query"; return; } if (field1->isQueryAsterisk() || field2->isQueryAsterisk()) { kdbWarning() << "relationship's fields cannot be asterisks"; return; } if (field1->table() == field2->table()) { kdbWarning() << "fields cannot belong to the same table"; return; } if (!query->contains(field1->table()) || !query->contains(field2->table())) { kdbWarning() << "fields do not belong to this query"; return; } //! @todo: check more things: -types //! @todo: find existing global db relationships KDbField *masterField = 0, *detailsField = 0; bool p1 = field1->isPrimaryKey(), p2 = field2->isPrimaryKey(); if (p1 && p2) { //2 primary keys masterField = field1; m_masterIndex = masterField->table()->primaryKey(); detailsField = field2; m_detailsIndex = detailsField->table()->primaryKey(); } else if (!p1 && p2) { //foreign + primary: swap KDbField *tmp = field1; field1 = field2; field2 = tmp; p1 = !p1; p2 = !p2; } if (p1 && !p2) { //primary + foreign masterField = field1; m_masterIndex = masterField->table()->primaryKey(); detailsField = field2; //create foreign key //@todo: check if it already exists m_detailsIndex = new KDbIndexSchema; detailsField->table()->addIndex(m_detailsIndex); m_detailsIndexOwned = true; const bool ok = m_detailsIndex->addField(detailsField); Q_ASSERT(ok); m_detailsIndex->setForeignKey(true); } else if (!p1 && !p2) { masterField = field1; m_masterIndex = new KDbIndexSchema; masterField->table()->addIndex(m_masterIndex); m_masterIndexOwned = true; bool ok = m_masterIndex->addField(masterField); Q_ASSERT(ok); m_masterIndex->setForeignKey(true); detailsField = field2; m_detailsIndex = new KDbIndexSchema; detailsField->table()->addIndex(m_detailsIndex); m_detailsIndexOwned = true; ok = m_detailsIndex->addField(detailsField); Q_ASSERT(ok); m_detailsIndex->setForeignKey(true); } if (!m_masterIndex || !m_detailsIndex) return; //failed (void)setIndices(m_masterIndex, m_detailsIndex, false); }
bool KDbRelationship::setIndices(KDbIndexSchema* masterIndex, KDbIndexSchema* detailsIndex, bool ownedByMaster) { m_masterIndex = 0; m_detailsIndex = 0; m_pairs.clear(); if (!masterIndex || !detailsIndex || !masterIndex->table() || !detailsIndex->table() || masterIndex->table() == detailsIndex->table() || masterIndex->fieldCount() != detailsIndex->fieldCount()) { return false; } const KDbField::List* masterIndexFields = masterIndex->fields(); const KDbField::List* detailsIndexFields = detailsIndex->fields(); KDbField::ListIterator masterIt(masterIndexFields->constBegin()); KDbField::ListIterator detailsIt(detailsIndexFields->constBegin()); for (;masterIt != masterIndexFields->constEnd() && detailsIt != detailsIndexFields->constEnd(); ++masterIt, ++detailsIt) { KDbField *masterField = *masterIt; KDbField *detailsField = *detailsIt; const KDbField::Type masterType = masterField->type(); // cache: evaluating type of expressions can be expensive const KDbField::Type detailsType = detailsField->type(); if (masterType != detailsType && KDbField::isIntegerType(masterType) != KDbField::isIntegerType(detailsType) && KDbField::isTextType(masterType) != KDbField::isTextType(detailsType)) { kdbWarning() << "INDEX on" << masterIndex->table()->name() << ", INDEX on" << detailsIndex->table()->name() << ": !equal field types:" << KDbDriver::defaultSQLTypeName(masterType) << masterField->name() << "," << KDbDriver::defaultSQLTypeName(detailsType) << detailsField->name(); m_pairs.clear(); return false; } #if 0 //too STRICT! if ((masterField->isUnsigned() && !detailsField->isUnsigned()) || (!masterField->isUnsigned() && detailsField->isUnsigned())) { kdbWarning() << "KDbRelationship::setIndices(INDEX on '" << masterIndex->table()->name() << "',INDEX on " << detailsIndex->table()->name() << "): !equal signedness of field types: " << KDbDriver::defaultSQLTypeName(masterField->type()) << " " << masterField->name() << ", " << KDbDriver::defaultSQLTypeName(detailsField->type()) << " " << detailsField->name(); m_pairs.clear(); return; } #endif m_pairs.append(KDbField::Pair(masterField, detailsField)); } //ok: update information if (m_masterIndex) {//detach yourself m_masterIndex->detachRelationship(this); } if (m_detailsIndex) {//detach yourself m_detailsIndex->detachRelationship(this); } m_masterIndex = masterIndex; m_detailsIndex = detailsIndex; m_masterIndex->attachRelationship(this, ownedByMaster); m_detailsIndex->attachRelationship(this, ownedByMaster); return true; }
//================================================================================== //Return the value for a given column for the current record - Private const version QVariant PostgresqlCursor::pValue(int pos) const { // postgresqlWarning() << "PostgresqlCursor::value - ERROR: requested position is greater than the number of fields"; const qint64 row = at(); KDbField *f = (m_visibleFieldsExpanded && pos < qMin(m_visibleFieldsExpanded->count(), m_fieldCount)) ? m_visibleFieldsExpanded->at(pos)->field() : nullptr; // postgresqlDebug() << "pos:" << pos; const KDbField::Type type = m_realTypes[pos]; const KDbField::Type kdbType = f ? f->type() : KDbField::InvalidType; // cache: evaluating type of expressions can be expensive if (PQgetisnull(d->res, row, pos) || kdbType == KDbField::Null) { return QVariant(); } const char *data = PQgetvalue(d->res, row, pos); int len = PQgetlength(d->res, row, pos); switch (type) { // from most to least frequently used types: case KDbField::Text: case KDbField::LongText: { const int maxLength = m_realLengths[pos]; if (maxLength > 0) { len = qMin(len, maxLength); } return convertToKDbType(!KDbField::isTextType(kdbType), d->unicode ? QString::fromUtf8(data, len) : QString::fromLatin1(data, len), kdbType); } case KDbField::Integer: return convertToKDbType(!KDbField::isIntegerType(kdbType), atoi(data), // the fastest way kdbType); case KDbField::Boolean: return convertToKDbType(kdbType != KDbField::Boolean, bool(data[0] == 't'), kdbType); case KDbField::BigInteger: return convertToKDbType(kdbType != KDbField::BigInteger, (data[0] == '-') ? QByteArray::fromRawData(data, len).toLongLong() : QByteArray::fromRawData(data, len).toULongLong(), kdbType); case KDbField::Double: //! @todo support equivalent of QSql::NumericalPrecisionPolicy, especially for NUMERICOID return convertToKDbType(!KDbField::isFPNumericType(kdbType), QByteArray::fromRawData(data, len).toDouble(), kdbType); case KDbField::Date: return convertToKDbType(kdbType != KDbField::Date, (len == 0) ? QVariant(QDate()) : QVariant(QDate::fromString(QLatin1String(QByteArray::fromRawData(data, len)), Qt::ISODate)), kdbType); case KDbField::Time: return convertToKDbType(kdbType != KDbField::Time, timeFromData(data, len), kdbType); case KDbField::DateTime: return convertToKDbType(kdbType != KDbField::DateTime, dateTimeFromData(data, len), kdbType); case KDbField::BLOB: return convertToKDbType(kdbType != KDbField::BLOB, byteArrayFromData(data), kdbType); default: postgresqlWarning() << "PostgresqlCursor::pValue() data type?"; } return QVariant(); }