Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,17 @@ Possible customizations:
* `IDENTITY [true|false]`: mark the property as the identity
* `AUTOGENERATED [true|false]`: mark the property as autogenerated by the database backend
* `TRANSIENT [true|false]`: mark the property as transient
* `NOT_NULL [true|false]`: mark the property as not null
* `FOREIGN_KEY [true|false]`: mark the relation as having a foreign key in the generated schema
* `UNIQUE [<common_name>]`: mark the property as unique (properties with same `common_name` will create a compound unique index)

Restrictions and requirements:

* There can be only one `IDENTITY`
* `IDENTITY` is required for `AUTOGENERATED`
* `TRANSIENT` cannot be combined with `IDENTITY`
* Renaming columns and tables to names containing QtOrm keywords (`IDENTITY`, `COLUMN`, `TRANSIENT`, etc.) is not supported.
* Renaming columns and tables to names containing QtOrm keywords (`IDENTITY`, `COLUMN`, `TRANSIENT`, etc.) or the `!` and `,` characters is not supported.
* Schema `Append` mode will not set `NOT_NULL` on `UNIQUE` on the new column(s)

#### Relationships

Expand Down
5 changes: 4 additions & 1 deletion src/orm/qormglobal.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,10 @@ namespace QOrm
Autogenerated,
Identity,
Transient,
Schema
Schema,
NotNull,
ForeignKey,
Unique
};
inline auto qHash(Keyword value)
{
Expand Down
79 changes: 78 additions & 1 deletion src/orm/qormmetadatacache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ namespace
{QOrm::Keyword::Column, QLatin1String("COLUMN")},
{QOrm::Keyword::Identity, QLatin1String("IDENTITY")},
{QOrm::Keyword::Transient, QLatin1String("TRANSIENT")},
{QOrm::Keyword::Autogenerated, QLatin1String("AUTOGENERATED")}};
{QOrm::Keyword::Autogenerated, QLatin1String("AUTOGENERATED")},
{QOrm::Keyword::NotNull, QLatin1String("NOT_NULL")},
{QOrm::Keyword::ForeignKey, QLatin1String("FOREIGN_KEY")},
{QOrm::Keyword::Unique, QLatin1String("UNIQUE")}};

template<typename Iterable>
KeywordPosition findNextKeyword(const QString& data,
Expand Down Expand Up @@ -301,6 +304,47 @@ namespace
ormPropertyInfo.insert(QOrm::Keyword::Autogenerated,
isAutogenerated.value_or(true));
}
else if (keywordPosition.keyword->id == QOrm::Keyword::NotNull)
{
auto extractResult = extractBoolean(data, pos, PropertyKeywords);

if (!extractResult.has_value())
{
qFatal("QtOrm: syntax error in %s in Q_ORM_PROPERTY(%s ...) after NOT_NULL",
qMetaObject.className(),
qPrintable(propertyName));
}

std::optional<bool> isNotNull = extractResult->value;
keywordPosition = extractResult->nextKeyword;

ormPropertyInfo.insert(QOrm::Keyword::NotNull, isNotNull.value_or(true));
}
else if (keywordPosition.keyword->id == QOrm::Keyword::ForeignKey)
{
auto extractResult = extractBoolean(data, pos, PropertyKeywords);

if (!extractResult.has_value())
{
qFatal("QtOrm: syntax error in %s in Q_ORM_PROPERTY(%s ...) after FOREIGN_KEY",
qMetaObject.className(),
qPrintable(propertyName));
}

std::optional<bool> hasForeignKey = extractResult->value;
keywordPosition = extractResult->nextKeyword;

ormPropertyInfo.insert(QOrm::Keyword::ForeignKey, hasForeignKey.value_or(true));
}
else if (keywordPosition.keyword->id == QOrm::Keyword::Unique)
{
auto extractResult = extractString(data, pos, PropertyKeywords);

QString uniqueGroup = extractResult.value;
keywordPosition = extractResult.nextKeyword;

ormPropertyInfo.insert(QOrm::Keyword::Unique, uniqueGroup);
}
}

return ormPropertyInfo;
Expand All @@ -320,6 +364,11 @@ class QOrmMetadataCachePrivate
const QOrmMetadata* referencedEntity = nullptr;
bool isTransient = false;
bool isEnumeration{false};
bool isNotNull = false;
bool hasForeignKey = false;
bool isUnique = false;
QString uniqueGroup;

QMetaType::Type dataType{QMetaType::UnknownType};
};

Expand Down Expand Up @@ -464,6 +513,10 @@ void QOrmMetadataCachePrivate::initialize(const QByteArray& className,
descriptor.dataType,
descriptor.referencedEntity,
descriptor.isTransient,
descriptor.isNotNull,
descriptor.hasForeignKey,
descriptor.isUnique,
descriptor.uniqueGroup,
userPropertyMetadata);
auto idx = static_cast<int>(data->m_propertyMappings.size() - 1);

Expand Down Expand Up @@ -496,6 +549,10 @@ QOrmMetadataCachePrivate::MappingDescriptor QOrmMetadataCachePrivate::mappingDes
bool isObjectId = qstricmp(property.name(), "id") == 0;
bool isAutogenerated = isObjectId;
bool isTransient = !property.isStored();
bool isNotNull = false;
bool hasForeignKey = false;
bool isUnique = false;
QString uniqueGroup;

// Check if defaults are overridden by the user property metadata
if (userPropertyMetadata.contains(QOrm::Keyword::Column))
Expand All @@ -519,11 +576,31 @@ QOrmMetadataCachePrivate::MappingDescriptor QOrmMetadataCachePrivate::mappingDes
isTransient = userPropertyMetadata.value(QOrm::Keyword::Transient).toBool();
}

if (userPropertyMetadata.contains(QOrm::Keyword::NotNull))
{
isNotNull = userPropertyMetadata.value(QOrm::Keyword::NotNull).toBool();
}

if (userPropertyMetadata.contains(QOrm::Keyword::ForeignKey))
{
hasForeignKey = userPropertyMetadata.value(QOrm::Keyword::ForeignKey).toBool();
}

if (userPropertyMetadata.contains(QOrm::Keyword::Unique))
{
isUnique = true;
uniqueGroup = userPropertyMetadata.value(QOrm::Keyword::Unique).toString();
}

descriptor.classPropertyName = QString::fromUtf8(property.name());
descriptor.tableFieldName = tableFieldName;
descriptor.isObjectId = isObjectId;
descriptor.isAutogenerated = isAutogenerated;
descriptor.isTransient = isTransient;
descriptor.isNotNull = isNotNull;
descriptor.hasForeignKey = hasForeignKey;
descriptor.isUnique = isUnique;
descriptor.uniqueGroup = uniqueGroup;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
descriptor.dataType = property.type() == QVariant::UserType
? static_cast<QMetaType::Type>(property.userType())
Expand Down
54 changes: 54 additions & 0 deletions src/orm/qormpropertymapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ QDebug operator<<(QDebug dbg, const QOrmPropertyMapping& propertyMapping)
if (propertyMapping.isTransient())
dbg << ", transient";

if (propertyMapping.isNotNull())
dbg << ", not null";

if (propertyMapping.hasForeignKey())
dbg << ", fk";

if (propertyMapping.isUnique()) {
dbg << ", unique";

if (!propertyMapping.uniqueGroup().isEmpty()) {
dbg << "(" << propertyMapping.uniqueGroup() << ")";
}
}

dbg << ")";

return dbg;
Expand All @@ -58,6 +72,10 @@ class QOrmPropertyMappingPrivate : public QSharedData
QMetaType::Type dataType,
const QOrmMetadata* referencedEntity,
bool isTransient,
bool isNotNull,
bool hasForeignKey,
bool isUnique,
QString uniqueGroup,
QOrmUserMetadata userMetadata)
: m_enclosingEntity{enclosingEntity}
, m_qMetaProperty{std::move(qMetaProperty)}
Expand All @@ -68,6 +86,10 @@ class QOrmPropertyMappingPrivate : public QSharedData
, m_dataType{dataType}
, m_referencedEntity{referencedEntity}
, m_isTransient{isTransient}
, m_isNotNull{isNotNull}
, m_hasForeignKey{hasForeignKey}
, m_isUnique{isUnique}
, m_uniqueGroup{uniqueGroup}
, m_userMetadata{std::move(userMetadata)}
{
}
Expand All @@ -81,6 +103,10 @@ class QOrmPropertyMappingPrivate : public QSharedData
QMetaType::Type m_dataType{QMetaType::UnknownType};
const QOrmMetadata* m_referencedEntity{nullptr};
bool m_isTransient{false};
bool m_isNotNull{false};
bool m_hasForeignKey{false};
bool m_isUnique{false};
QString m_uniqueGroup;
QOrmUserMetadata m_userMetadata;
};

Expand All @@ -93,6 +119,10 @@ QOrmPropertyMapping::QOrmPropertyMapping(const QOrmMetadata& enclosingEntity,
QMetaType::Type dataType,
const QOrmMetadata* referencedEntity,
bool isTransient,
bool isNotNull,
bool hasForeignKey,
bool isUnique,
QString uniqueGroup,
QOrmUserMetadata userMetadata)
: d{new QOrmPropertyMappingPrivate{enclosingEntity,
std::move(qMetaProperty),
Expand All @@ -103,6 +133,10 @@ QOrmPropertyMapping::QOrmPropertyMapping(const QOrmMetadata& enclosingEntity,
dataType,
referencedEntity,
isTransient,
isNotNull,
hasForeignKey,
isUnique,
uniqueGroup,
std::move(userMetadata)}}
{
}
Expand Down Expand Up @@ -172,6 +206,26 @@ bool QOrmPropertyMapping::isTransient() const
return d->m_isTransient;
}

bool QOrmPropertyMapping::isNotNull() const
{
return d->m_isNotNull;
}

bool QOrmPropertyMapping::hasForeignKey() const
{
return d->m_hasForeignKey;
}

bool QOrmPropertyMapping::isUnique() const
{
return d->m_isUnique;
}

QString QOrmPropertyMapping::uniqueGroup() const
{
return d->m_uniqueGroup;
}

const QOrmUserMetadata& QOrmPropertyMapping::userMetadata() const
{
return d->m_userMetadata;
Expand Down
8 changes: 8 additions & 0 deletions src/orm/qormpropertymapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class Q_ORM_EXPORT QOrmPropertyMapping
QMetaType::Type dataType,
const QOrmMetadata* referencedEntity,
bool isTransient,
bool isNotNull,
bool hasForeignKey,
bool isUnique,
QString uniqueGroup,
QOrmUserMetadata userMetadata);
QOrmPropertyMapping(const QOrmPropertyMapping&);
QOrmPropertyMapping(QOrmPropertyMapping&&);
Expand All @@ -64,6 +68,10 @@ class Q_ORM_EXPORT QOrmPropertyMapping
[[nodiscard]] bool isReference() const;
[[nodiscard]] const QOrmMetadata* referencedEntity() const;
[[nodiscard]] bool isTransient() const;
[[nodiscard]] bool isNotNull() const;
[[nodiscard]] bool hasForeignKey() const;
[[nodiscard]] bool isUnique() const;
[[nodiscard]] QString uniqueGroup() const;
[[nodiscard]] const QOrmUserMetadata& userMetadata() const;

private:
Expand Down
1 change: 1 addition & 0 deletions src/orm/qormsessionconfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static QOrmSqliteConfiguration _build_json_sqlite_configuration(const QJsonObjec
sqlConfiguration.setDatabaseName(object["databaseName"].toString());
sqlConfiguration.setVerbose(object["verbose"].toBool(false));
sqlConfiguration.setConnectOptions(object["connectOptions"].toString());
sqlConfiguration.setForeignKeysEnabled(object["foreignKeysEnabled"].toBool(false));

QString schemaModeStr = object["schemaMode"].toString("validate").toLower();

Expand Down
10 changes: 10 additions & 0 deletions src/orm/qormsqliteconfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,14 @@ void QOrmSqliteConfiguration::setSchemaMode(SchemaMode schemaMode)
m_schemaMode = schemaMode;
}

bool QOrmSqliteConfiguration::foreignKeysEnabled() const
{
return m_foreignKeysEnabled;
}

void QOrmSqliteConfiguration::setForeignKeysEnabled(bool foreignKeysEnabled)
{
m_foreignKeysEnabled = foreignKeysEnabled;
}

QT_END_NAMESPACE
4 changes: 4 additions & 0 deletions src/orm/qormsqliteconfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,15 @@ class Q_ORM_EXPORT QOrmSqliteConfiguration
SchemaMode schemaMode() const;
void setSchemaMode(SchemaMode schemaMode);

[[nodiscard]] bool foreignKeysEnabled() const;
void setForeignKeysEnabled(bool foreignKeysEnabled);

private:
QString m_connectOptions;
QString m_databaseName;
bool m_verbose{false};
SchemaMode m_schemaMode;
bool m_foreignKeysEnabled{false};
};

QT_END_NAMESPACE
Expand Down
Loading
Loading