Skip to content

Commit 43dfe14

Browse files
authored
Replace '::' with '_' in namespaced classes; add identifier escaping in SQLite generator (#31)
1 parent 8c90a53 commit 43dfe14

File tree

8 files changed

+226
-26
lines changed

8 files changed

+226
-26
lines changed

src/orm/qormmetadatacache.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,10 @@ void QOrmMetadataCachePrivate::initialize(const QByteArray& className,
409409
}
410410

411411
// initialize the private part of the cached object
412+
QString defaultTableName = QString::fromUtf8(qMetaObject.className()).replace("::", "_");
413+
412414
data->m_className = QString::fromUtf8(qMetaObject.className());
413-
data->m_tableName =
414-
ormClassInfo.value(QOrm::Keyword::Table, QVariant::fromValue(data->m_className)).toString();
415+
data->m_tableName = ormClassInfo.value(QOrm::Keyword::Table, defaultTableName).toString();
415416
data->m_userMetadata = ormClassInfo;
416417

417418
for (int i = 0; i < qMetaObject.propertyCount(); ++i)

src/orm/qormsqlitestatementgenerator_p.cpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,15 @@ QString QOrmSqliteStatementGenerator::generateInsertStatement(const QOrmMetadata
144144
QString valueStr =
145145
insertParameter(boundParameters, propertyMapping.tableFieldName(), propertyValue);
146146

147-
fieldsList.push_back(propertyMapping.tableFieldName());
147+
fieldsList.push_back(escapeIdentifier(propertyMapping.tableFieldName()));
148148
valuesList.push_back(valueStr);
149149
}
150150

151151
QString fieldsStr = fieldsList.join(',');
152152
QString valuesStr = valuesList.join(',');
153153

154154
QString statement = QStringLiteral("INSERT INTO %1(%2) VALUES(%3)")
155-
.arg(relation.tableName(), fieldsStr, valuesStr);
155+
.arg(escapeIdentifier(relation.tableName()), fieldsStr, valuesStr);
156156

157157
return statement;
158158
}
@@ -260,7 +260,7 @@ QString QOrmSqliteStatementGenerator::generateFromClause(const QOrmRelation& rel
260260
switch (relation.type())
261261
{
262262
case QOrm::RelationType::Mapping:
263-
return QString{"FROM %1"}.arg(relation.mapping()->tableName());
263+
return QString{"FROM %1"}.arg(escapeIdentifier(relation.mapping()->tableName()));
264264

265265
case QOrm::RelationType::Query:
266266
Q_ASSERT(relation.query()->operation() == QOrm::Operation::Read);
@@ -510,12 +510,13 @@ QString QOrmSqliteStatementGenerator::generateCreateTableStatement(
510510
{
511511
Q_ASSERT(mapping.referencedEntity()->objectIdMapping() != nullptr);
512512

513-
columnDefs += {mapping.tableFieldName(),
513+
columnDefs += {escapeIdentifier(mapping.tableFieldName()),
514514
toSqliteType(mapping.referencedEntity()->objectIdMapping()->dataType())};
515515
}
516516
else
517517
{
518-
columnDefs += {mapping.tableFieldName(), toSqliteType(mapping.dataType())};
518+
columnDefs +=
519+
{escapeIdentifier(mapping.tableFieldName()), toSqliteType(mapping.dataType())};
519520

520521
if (mapping.isObjectId())
521522
columnDefs.push_back(QStringLiteral("PRIMARY KEY"));
@@ -530,7 +531,7 @@ QString QOrmSqliteStatementGenerator::generateCreateTableStatement(
530531
QString fieldsStr = fields.join(',');
531532

532533
Q_ASSERT(!overrideTableName.has_value() || !overrideTableName->isEmpty());
533-
QString effectiveTableName = overrideTableName.value_or(entity.tableName());
534+
QString effectiveTableName{overrideTableName.value_or(escapeIdentifier(entity.tableName()))};
534535

535536
return QStringLiteral("CREATE TABLE %1(%2)").arg(effectiveTableName, fieldsStr);
536537
}

tests/auto/qormmetadatacache/domain/withenum.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,18 @@ void WithEnum::setMyEnumClass(MyNamespace::MyEnumClass myEnumClass)
6060
m_myEnumClass = myEnumClass;
6161
emit myEnumClassChanged();
6262
}
63-
}
63+
}
64+
65+
MyNamespace::WithNamespace* WithEnum::myNamespacedClass() const
66+
{
67+
return m_myNamespacedClass;
68+
}
69+
70+
void WithEnum::setMyNamespacedClass(MyNamespace::WithNamespace* myNamespacedClass)
71+
{
72+
if (m_myNamespacedClass != myNamespacedClass)
73+
{
74+
m_myNamespacedClass = myNamespacedClass;
75+
emit myNamespacedClassChanged();
76+
}
77+
}

tests/auto/qormmetadatacache/domain/withenum.h

+29
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,28 @@ namespace MyNamespace
3737
MyEnumClassValue1,
3838
MyEnumClassValue2
3939
};
40+
41+
class WithNamespace : public QObject
42+
{
43+
Q_OBJECT
44+
45+
Q_PROPERTY(int id MEMBER m_id NOTIFY idChanged)
46+
Q_PROPERTY(QString value MEMBER m_value NOTIFY valueChanged)
47+
48+
public:
49+
Q_INVOKABLE WithNamespace(QObject* parent = nullptr)
50+
: QObject{parent}
51+
{
52+
}
53+
54+
signals:
55+
void idChanged();
56+
void valueChanged();
57+
58+
private:
59+
int m_id;
60+
QString m_value;
61+
};
4062
}
4163

4264
Q_DECLARE_METATYPE(MyNamespace::MyEnum);
@@ -49,6 +71,8 @@ class WithEnum : public QObject
4971
Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged)
5072
Q_PROPERTY(MyNamespace::MyEnum myEnum READ myEnum WRITE setMyEnum NOTIFY myEnumChanged)
5173
Q_PROPERTY(MyNamespace::MyEnumClass myEnumClass READ myEnumClass WRITE setMyEnumClass NOTIFY myEnumClassChanged)
74+
Q_PROPERTY(MyNamespace::WithNamespace* myNamespacedClass READ myNamespacedClass WRITE
75+
setMyNamespacedClass NOTIFY myNamespacedClassChanged)
5276

5377
public:
5478
Q_INVOKABLE WithEnum(QObject* parent = nullptr)
@@ -65,13 +89,18 @@ class WithEnum : public QObject
6589
[[nodiscard]] MyNamespace::MyEnumClass myEnumClass() const;
6690
void setMyEnumClass(MyNamespace::MyEnumClass myEnumClass);
6791

92+
[[nodiscard]] MyNamespace::WithNamespace* myNamespacedClass() const;
93+
void setMyNamespacedClass(MyNamespace::WithNamespace* myNamespacedClass);
94+
6895
signals:
6996
void idChanged();
7097
void myEnumChanged();
7198
void myEnumClassChanged();
99+
void myNamespacedClassChanged();
72100

73101
private:
74102
int m_id{0};
75103
MyNamespace::MyEnum m_myEnum{MyNamespace::MyEnumValue0};
76104
MyNamespace::MyEnumClass m_myEnumClass{MyNamespace::MyEnumClass::MyEnumClassValue0};
105+
MyNamespace::WithNamespace* m_myNamespacedClass{nullptr};
77106
};

tests/auto/qormmetadatacache/tst_metadatacachetest.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ private slots:
4444

4545
void testCustomizedEntity();
4646
void testColumnNameForColumnWithReference();
47+
void testNamespacedEntity();
4748

4849
void testEnumColumn();
50+
void testColumnWithNamespacedReference();
4951
};
5052

5153
MetadataCacheTest::MetadataCacheTest()
@@ -293,6 +295,17 @@ void MetadataCacheTest::testColumnNameForColumnWithReference()
293295
QCOMPARE(townPropertyMapping->isReference(), true);
294296
}
295297

298+
void MetadataCacheTest::testNamespacedEntity()
299+
{
300+
qRegisterOrmEntity<MyNamespace::WithNamespace>();
301+
302+
QOrmMetadataCache cache;
303+
QOrmMetadata meta = cache.get<MyNamespace::WithNamespace>();
304+
305+
QCOMPARE(meta.className(), "MyNamespace::WithNamespace");
306+
QCOMPARE(meta.tableName(), "MyNamespace_WithNamespace");
307+
}
308+
296309
void MetadataCacheTest::testEnumColumn()
297310
{
298311
qRegisterOrmEntity<WithEnum>();
@@ -325,6 +338,27 @@ void MetadataCacheTest::testEnumColumn()
325338
QCOMPARE(myEnumClassMapping->isTransient(), false);
326339
}
327340

341+
void MetadataCacheTest::testColumnWithNamespacedReference()
342+
{
343+
qRegisterOrmEntity<WithEnum>();
344+
345+
QOrmMetadataCache cache;
346+
QOrmMetadata meta = cache.get<WithEnum>();
347+
348+
auto myNamespacedClassMapping = meta.classPropertyMapping("myNamespacedClass");
349+
QVERIFY(myNamespacedClassMapping != nullptr);
350+
QCOMPARE(myNamespacedClassMapping->classPropertyName(), "myNamespacedClass");
351+
QCOMPARE(myNamespacedClassMapping->tableFieldName(), "mynamespacedclass_id");
352+
QCOMPARE(myNamespacedClassMapping->isObjectId(), false);
353+
QCOMPARE(myNamespacedClassMapping->isAutogenerated(), false);
354+
QCOMPARE(myNamespacedClassMapping->dataType(), QVariant::UserType);
355+
QCOMPARE(myNamespacedClassMapping->dataTypeName(), "MyNamespace::WithNamespace*");
356+
QCOMPARE(myNamespacedClassMapping->isReference(), true);
357+
QCOMPARE(myNamespacedClassMapping->referencedEntity(),
358+
&cache.get<MyNamespace::WithNamespace>());
359+
QCOMPARE(myNamespacedClassMapping->isTransient(), false);
360+
}
361+
328362
QTEST_APPLESS_MAIN(MetadataCacheTest)
329363

330364
#include "tst_metadatacachetest.moc"

tests/auto/qormsqlitestatementgenerator/domain/withenum.cpp

+23-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,28 @@
2020

2121
#include "withenum.h"
2222

23+
namespace MyNamespace
24+
{
25+
void WithNamespace::setId(int id)
26+
{
27+
if (m_id != id)
28+
{
29+
m_id = id;
30+
emit idChanged();
31+
}
32+
}
33+
34+
void WithNamespace::setValue(QString value)
35+
{
36+
if (m_value != value)
37+
{
38+
m_value = value;
39+
emit valueChanged();
40+
}
41+
}
42+
43+
} // namespace MyNamespace
44+
2345
int WithEnum::id() const
2446
{
2547
return m_id;
@@ -60,4 +82,4 @@ void WithEnum::setMyEnumClass(MyNamespace::MyEnumClass myEnumClass)
6082
m_myEnumClass = myEnumClass;
6183
emit myEnumClassChanged();
6284
}
63-
}
85+
}

tests/auto/qormsqlitestatementgenerator/domain/withenum.h

+28
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,34 @@ namespace MyNamespace
3737
MyEnumClassValue1,
3838
MyEnumClassValue2
3939
};
40+
41+
class WithNamespace : public QObject
42+
{
43+
Q_OBJECT
44+
45+
Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged)
46+
Q_PROPERTY(QString value READ value WRITE setValue NOTIFY valueChanged)
47+
48+
public:
49+
Q_INVOKABLE WithNamespace(QObject* parent = nullptr)
50+
: QObject{parent}
51+
{
52+
}
53+
54+
[[nodiscard]] int id() const { return m_id; }
55+
void setId(int id);
56+
57+
[[nodiscard]] QString value() { return m_value; }
58+
void setValue(QString value);
59+
60+
signals:
61+
void idChanged();
62+
void valueChanged();
63+
64+
private:
65+
int m_id;
66+
QString m_value;
67+
};
4068
}
4169

4270
Q_DECLARE_METATYPE(MyNamespace::MyEnum);

0 commit comments

Comments
 (0)