aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vrátil <[email protected]>2017-03-25 23:18:46 +0100
committerDaniel Vrátil <[email protected]>2017-04-01 12:34:04 +0200
commitd257ae7cc84c88e330fff2b9e1ade2721ec506fd (patch)
treefcc698436a1b74760e88ea74089a243d8f7e33d5
parent6b5b444a52eb9c994510e208d4414abcbc539a9a (diff)
Add support for "enum" type in schema XML
Allows each table to specify an enum type with values and set the enum type to a column. We don't actually use the enum feature of SQL, the values are still stored as TINYINT, but the enum is generated as part of the respective Entity subclass.
-rw-r--r--autotests/server/dbinitializer.cpp14
-rw-r--r--autotests/server/dbinitializer.h2
-rw-r--r--autotests/server/dbpopulator.xsl21
-rw-r--r--autotests/server/listhandlertest.cpp12
-rw-r--r--autotests/server/modifyhandlertest.cpp6
-rw-r--r--src/server/cachecleaner.cpp2
-rw-r--r--src/server/handler/create.cpp6
-rw-r--r--src/server/handler/list.cpp16
-rw-r--r--src/server/handler/modify.cpp12
-rw-r--r--src/server/handlerhelper.cpp6
-rw-r--r--src/server/intervalcheck.cpp2
-rw-r--r--src/server/storage/akonadidb.xml12
-rw-r--r--src/server/storage/akonadidb.xsd13
-rw-r--r--src/server/storage/dbinitializer.cpp34
-rw-r--r--src/server/storage/dbinitializer.h4
-rw-r--r--src/server/storage/dbinitializer_p.cpp34
-rw-r--r--src/server/storage/dbinitializer_p.h6
-rw-r--r--src/server/storage/entities-header.xsl10
-rw-r--r--src/server/storage/entities-source.xsl24
-rw-r--r--src/server/storage/entities.xsl17
-rw-r--r--src/server/storage/schema-source.xsl26
-rw-r--r--src/server/storage/schematypes.cpp1
-rw-r--r--src/server/storage/schematypes.h3
23 files changed, 176 insertions, 107 deletions
diff --git a/autotests/server/dbinitializer.cpp b/autotests/server/dbinitializer.cpp
index 6ec871f..334f2cc 100644
--- a/autotests/server/dbinitializer.cpp
+++ b/autotests/server/dbinitializer.cpp
@@ -101,15 +101,15 @@ QByteArray DbInitializer::toByteArray(bool enabled)
return "FALSE";
}
-QByteArray DbInitializer::toByteArray(Akonadi::Tristate tristate)
+QByteArray DbInitializer::toByteArray(Collection::Tristate tristate)
{
switch (tristate) {
- case Akonadi::Tristate::True:
+ case Collection::True:
return "TRUE";
- case Akonadi::Tristate::False:
+ case Collection::False:
return "FALSE";
- case Akonadi::Tristate::Undefined:
+ case Collection::Undefined:
default:
break;
}
@@ -167,9 +167,9 @@ Akonadi::Protocol::FetchCollectionsResponse DbInitializer::listResponse(const Co
}
resp.setReferenced(col.referenced());
resp.setEnabled(col.enabled());
- resp.setDisplayPref(col.displayPref());
- resp.setSyncPref(col.syncPref());
- resp.setIndexPref(col.indexPref());
+ resp.setDisplayPref(static_cast<Tristate>(col.displayPref()));
+ resp.setSyncPref(static_cast<Tristate>(col.syncPref()));
+ resp.setIndexPref(static_cast<Tristate>(col.indexPref()));
Akonadi::Protocol::Attributes attrs;
Q_FOREACH(const CollectionAttribute &attr, col.attributes()) {
diff --git a/autotests/server/dbinitializer.h b/autotests/server/dbinitializer.h
index ec25d24..9cc8eea 100644
--- a/autotests/server/dbinitializer.h
+++ b/autotests/server/dbinitializer.h
@@ -32,7 +32,7 @@ public:
Akonadi::Server::PimItem createItem(const char *name, const Akonadi::Server::Collection &parent);
Akonadi::Server::Part createPart(qint64 pimitemId, const QByteArray &partname, const QByteArray &data);
QByteArray toByteArray(bool enabled);
- QByteArray toByteArray(Akonadi::Tristate tristate);
+ QByteArray toByteArray(Akonadi::Server::Collection::Tristate tristate);
Akonadi::Protocol::FetchCollectionsResponse listResponse(const Akonadi::Server::Collection &col,
bool ancestors = false,
bool mimetypes = true,
diff --git a/autotests/server/dbpopulator.xsl b/autotests/server/dbpopulator.xsl
index 5940535..3ba71af 100644
--- a/autotests/server/dbpopulator.xsl
+++ b/autotests/server/dbpopulator.xsl
@@ -49,6 +49,13 @@
<xsl:text>set</xsl:text><xsl:call-template name="first-upper-case"><xsl:with-param name="name" select="@name"/></xsl:call-template>
</xsl:template>
+<xsl:template name="translate-enum-value">
+ <xsl:param name="value" />
+ <xsl:param name="enumType" />
+ <xsl:param name="table" />
+
+ <xsl:value-of select="$table"/>::<xsl:value-of select="substring($value, string-length($enumType) + 3)" />
+</xsl:template>
<xsl:template name="parse-entities-recursively">
<xsl:param name="attributes" />
@@ -162,13 +169,21 @@
</xsl:otherwise>
</xsl:choose>
</xsl:when>
- <xsl:when test="@type = 'Tristate'">
+ <xsl:when test="@type = 'enum'">
<xsl:choose>
<xsl:when test="$columnValue = 'NULL'">
- <xsl:text>Tristate::Undefined</xsl:text>
+ <xsl:call-template name="translate-enum-value">
+ <xsl:with-param name="value"><xsl:value-of select="$schema/table[@name = $tableName]/column[@name = $columnName]/@default"/></xsl:with-param>
+ <xsl:with-param name="enumType"><xsl:value-of select="$schema/table[@name = $tableName]/column[@name = $columnName]/@enumType"/></xsl:with-param>
+ <xsl:with-param name="table"><xsl:value-of select="$tableName"/></xsl:with-param>
+ </xsl:call-template>
</xsl:when>
<xsl:otherwise>
- <xsl:value-of select="$columnValue" />
+ <xsl:call-template name="translate-enum-value">
+ <xsl:with-param name="value"><xsl:value-of select="$columnValue"/></xsl:with-param>
+ <xsl:with-param name="enumType"><xsl:value-of select="$schema/table[@name = $tableName]/column[@name = $columnName]/@enumType"/></xsl:with-param>
+ <xsl:with-param name="table"><xsl:value-of select="$tableName"/></xsl:with-param>
+ </xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
diff --git a/autotests/server/listhandlertest.cpp b/autotests/server/listhandlertest.cpp
index 60c9e77..88c5dcf 100644
--- a/autotests/server/listhandlertest.cpp
+++ b/autotests/server/listhandlertest.cpp
@@ -262,15 +262,15 @@ private Q_SLOTS:
Collection col1 = initializer->createCollection("col1");
Collection col2 = initializer->createCollection("col2", col1);
col2.setEnabled(false);
- col2.setSyncPref(Tristate::True);
- col2.setDisplayPref(Tristate::True);
- col2.setIndexPref(Tristate::True);
+ col2.setSyncPref(Collection::True);
+ col2.setDisplayPref(Collection::True);
+ col2.setIndexPref(Collection::True);
col2.update();
Collection col3 = initializer->createCollection("col3", col2);
col3.setEnabled(true);
- col3.setSyncPref(Tristate::False);
- col3.setDisplayPref(Tristate::False);
- col3.setIndexPref(Tristate::False);
+ col3.setSyncPref(Collection::False);
+ col3.setDisplayPref(Collection::False);
+ col3.setIndexPref(Collection::False);
col3.update();
QTest::addColumn<TestScenario::List>("scenarios");
diff --git a/autotests/server/modifyhandlertest.cpp b/autotests/server/modifyhandlertest.cpp
index 2a59c45..168c381 100644
--- a/autotests/server/modifyhandlertest.cpp
+++ b/autotests/server/modifyhandlertest.cpp
@@ -167,11 +167,11 @@ private Q_SLOTS:
}
if (!notification.changedParts().intersect({ "ENABLED", "SYNC", "DISPLAY", "INDEX" }).isEmpty()) {
Collection col = Collection::retrieveById(notification.id());
- const bool sync = col.syncPref() == Tristate::Undefined ? col.enabled() : col.syncPref() == Tristate::True;
+ const bool sync = col.syncPref() == Collection::Undefined ? col.enabled() : col.syncPref() == Collection::True;
QCOMPARE(sync, newValue.toBool());
- const bool display = col.displayPref() == Tristate::Undefined ? col.enabled() : col.displayPref() == Tristate::True;
+ const bool display = col.displayPref() == Collection::Undefined ? col.enabled() : col.displayPref() == Collection::True;
QCOMPARE(display, newValue.toBool());
- const bool index = col.indexPref() == Tristate::Undefined ? col.enabled() : col.indexPref() == Tristate::True;
+ const bool index = col.indexPref() == Collection::Undefined ? col.enabled() : col.indexPref() == Collection::True;
QCOMPARE(index, newValue.toBool());
}
}
diff --git a/src/server/cachecleaner.cpp b/src/server/cachecleaner.cpp
index 5143fc1..cee0665 100644
--- a/src/server/cachecleaner.cpp
+++ b/src/server/cachecleaner.cpp
@@ -112,7 +112,7 @@ bool CacheCleaner::shouldScheduleCollection(const Collection &collection)
{
return collection.cachePolicyLocalParts() != QLatin1String("ALL")
&& collection.cachePolicyCacheTimeout() >= 0
- && (collection.enabled() || (collection.displayPref() == Tristate::True) || (collection.syncPref() == Tristate::True) || (collection.indexPref() == Tristate::True))
+ && (collection.enabled() || (collection.displayPref() == Collection::True) || (collection.syncPref() == Collection::True) || (collection.indexPref() == Collection::True))
&& collection.resourceId() > 0;
}
diff --git a/src/server/handler/create.cpp b/src/server/handler/create.cpp
index e65778f..2e87b6d 100644
--- a/src/server/handler/create.cpp
+++ b/src/server/handler/create.cpp
@@ -94,9 +94,9 @@ bool Create::parseStream()
collection.setRemoteRevision(cmd.remoteRevision());
collection.setIsVirtual(cmd.isVirtual() || forceVirtual);
collection.setEnabled(cmd.enabled());
- collection.setSyncPref(cmd.syncPref());
- collection.setDisplayPref(cmd.displayPref());
- collection.setIndexPref(cmd.indexPref());
+ collection.setSyncPref(static_cast<Collection::Tristate>(cmd.syncPref()));
+ collection.setDisplayPref(static_cast<Collection::Tristate>(cmd.displayPref()));
+ collection.setIndexPref(static_cast<Collection::Tristate>(cmd.indexPref()));
const Protocol::CachePolicy &cp = cmd.cachePolicy();
collection.setCachePolicyCacheTimeout(cp.cacheTimeout());
collection.setCachePolicyCheckInterval(cp.checkInterval());
diff --git a/src/server/handler/list.cpp b/src/server/handler/list.cpp
index cb5de0b..04bc147 100644
--- a/src/server/handler/list.cpp
+++ b/src/server/handler/list.cpp
@@ -143,9 +143,9 @@ void List::listCollection(const Collection &root, const QStack<Collection> &ance
static Query::Condition filterCondition(const QString &column)
{
Query::Condition orCondition(Query::Or);
- orCondition.addValueCondition(column, Query::Equals, (int)Tristate::True);
+ orCondition.addValueCondition(column, Query::Equals, (int)Collection::True);
Query::Condition andCondition(Query::And);
- andCondition.addValueCondition(column, Query::Equals, (int)Tristate::Undefined);
+ andCondition.addValueCondition(column, Query::Equals, (int)Collection::Undefined);
andCondition.addValueCondition(Collection::enabledFullColumnName(), Query::Equals, true);
orCondition.addCondition(andCondition);
orCondition.addValueCondition(Collection::referencedFullColumnName(), Query::Equals, true);
@@ -160,19 +160,19 @@ bool List::checkFilterCondition(const Collection &col) const
}
//Don't include the collection when only looking for collections to display/index/sync
if (mCollectionsToDisplay &&
- (((col.displayPref() == Tristate::Undefined) && !col.enabled()) ||
- (col.displayPref() == Tristate::False))) {
+ (((col.displayPref() == Collection::Undefined) && !col.enabled()) ||
+ (col.displayPref() == Collection::False))) {
return false;
}
if (mCollectionsToIndex &&
- (((col.indexPref() == Tristate::Undefined) && !col.enabled()) ||
- (col.indexPref() == Tristate::False))) {
+ (((col.indexPref() == Collection::Undefined) && !col.enabled()) ||
+ (col.indexPref() == Collection::False))) {
return false;
}
//Single collection sync will still work since that is using a base fetch
if (mCollectionsToSynchronize &&
- (((col.syncPref() == Tristate::Undefined) && !col.enabled()) ||
- (col.syncPref() == Tristate::False))) {
+ (((col.syncPref() == Collection::Undefined) && !col.enabled()) ||
+ (col.syncPref() == Collection::False))) {
return false;
}
return true;
diff --git a/src/server/handler/modify.cpp b/src/server/handler/modify.cpp
index 7bda812..843b8ed 100644
--- a/src/server/handler/modify.cpp
+++ b/src/server/handler/modify.cpp
@@ -210,16 +210,16 @@ bool Modify::parseStream()
collection.setEnabled(cmd.enabled());
changes.append(AKONADI_PARAM_ENABLED);
}
- if (cmd.syncPref() != collection.syncPref()) {
- collection.setSyncPref(cmd.syncPref());
+ if (cmd.syncPref() != static_cast<Tristate>(collection.syncPref())) {
+ collection.setSyncPref(static_cast<Collection::Tristate>(cmd.syncPref()));
changes.append(AKONADI_PARAM_SYNC);
}
- if (cmd.displayPref() != collection.displayPref()) {
- collection.setDisplayPref(cmd.displayPref());
+ if (cmd.displayPref() != static_cast<Tristate>(collection.displayPref())) {
+ collection.setDisplayPref(static_cast<Collection::Tristate>(cmd.displayPref()));
changes.append(AKONADI_PARAM_DISPLAY);
}
- if (cmd.indexPref() != collection.indexPref()) {
- collection.setIndexPref(cmd.indexPref());
+ if (cmd.indexPref() != static_cast<Tristate>(collection.indexPref())) {
+ collection.setIndexPref(static_cast<Collection::Tristate>(cmd.indexPref()));
changes.append(AKONADI_PARAM_INDEX);
}
}
diff --git a/src/server/handlerhelper.cpp b/src/server/handlerhelper.cpp
index ac33c2d..58c152a 100644
--- a/src/server/handlerhelper.cpp
+++ b/src/server/handlerhelper.cpp
@@ -154,9 +154,9 @@ Protocol::FetchCollectionsResponse HandlerHelper::fetchCollectionsResponse(const
response.setReferenced(isReferenced);
response.setEnabled(col.enabled());
- response.setDisplayPref(col.displayPref());
- response.setSyncPref(col.syncPref());
- response.setIndexPref(col.indexPref());
+ response.setDisplayPref(static_cast<Tristate>(col.displayPref()));
+ response.setSyncPref(static_cast<Tristate>(col.syncPref()));
+ response.setIndexPref(static_cast<Tristate>(col.indexPref()));
QMap<QByteArray, QByteArray> ra;
for (const CollectionAttribute &attr : attrs) {
diff --git a/src/server/intervalcheck.cpp b/src/server/intervalcheck.cpp
index 77fb152..c6c1e71 100644
--- a/src/server/intervalcheck.cpp
+++ b/src/server/intervalcheck.cpp
@@ -60,7 +60,7 @@ bool IntervalCheck::hasChanged(const Collection &collection, const Collection &c
bool IntervalCheck::shouldScheduleCollection(const Collection &collection)
{
return collection.cachePolicyCheckInterval() > 0
- && ((collection.syncPref() == Tristate::True) || ((collection.syncPref() == Tristate::Undefined) && collection.enabled()));
+ && ((collection.syncPref() == Collection::True) || ((collection.syncPref() == Collection::Undefined) && collection.enabled()));
}
void IntervalCheck::collectionExpired(const Collection &collection)
diff --git a/src/server/storage/akonadidb.xml b/src/server/storage/akonadidb.xml
index a3646ee..1593ee5 100644
--- a/src/server/storage/akonadidb.xml
+++ b/src/server/storage/akonadidb.xml
@@ -79,6 +79,12 @@
</table>
<table name="Collection">
+ <enum name="Tristate">
+ <value name="False"/>
+ <value name="True"/>
+ <value name="Undefined"/>
+ </enum>
+
<column name="id" type="qint64" allowNull="false" isAutoIncrement="true" isPrimaryKey="true"/>
<column name="remoteId" type="QString"/>
<column name="remoteRevision" type="QString"/>
@@ -86,9 +92,9 @@
<column name="parentId" type="qint64" refTable="Collection" refColumn="id" methodName="parent"/>
<column name="resourceId" type="qint64" refTable="Resource" refColumn="id" allowNull="false"/>
<column name="enabled" type="bool" default="true" allowNull="false"/>
- <column name="syncPref" type="Tristate" default="Tristate::Undefined"/>
- <column name="displayPref" type="Tristate" default="Tristate::Undefined"/>
- <column name="indexPref" type="Tristate" default="Tristate::Undefined"/>
+ <column name="syncPref" type="enum" enumType="Tristate" default="Tristate::Undefined"/>
+ <column name="displayPref" type="enum" enumType="Tristate" default="Tristate::Undefined"/>
+ <column name="indexPref" type="enum" enumType="Tristate" default="Tristate::Undefined"/>
<column name="referenced" type="bool" default="false" allowNull="false"/>
<column name="cachePolicyInherit" type="bool" default="true" allowNull="false"/>
<column name="cachePolicyCheckInterval" type="int" default="-1" allowNull="false"/>
diff --git a/src/server/storage/akonadidb.xsd b/src/server/storage/akonadidb.xsd
index 0563a46..893849c 100644
--- a/src/server/storage/akonadidb.xsd
+++ b/src/server/storage/akonadidb.xsd
@@ -40,6 +40,7 @@
<xsd:element name="index" type="indexType" minOccurs="0" maxOccurs="100"/>
<xsd:element name="reference" type="referenceType" minOccurs="0" maxOccurs="100"/>
<xsd:element name="data" type="dataType" minOccurs="0" maxOccurs="100"/>
+ <xsd:element name="enum" type="enumType" minOccurs="0" maxOccurs="100"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="properties" type="xsd:string"/>
@@ -75,6 +76,7 @@
<xsd:attribute name="onUpdate" type="xsd:string"/>
<xsd:attribute name="onDelete" type="xsd:string"/>
<xsd:attribute name="noUpdate" type="xsd:boolean" default="false"/>
+ <xsl:attribute name="enumType" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="indexType">
@@ -98,4 +100,15 @@
<xsd:attribute name="values" type="xsd:string" use="required"/>
</xsd:complexType>
+ <xsd:complexType name="enumType">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:sequence>
+ <xsd:element name="value" type="enumValueType" minOccurs="1" maxOccurs="100"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="enumValueType">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
</xsd:schema>
diff --git a/src/server/storage/dbinitializer.cpp b/src/server/storage/dbinitializer.cpp
index a0c7afe..e2a4a98 100644
--- a/src/server/storage/dbinitializer.cpp
+++ b/src/server/storage/dbinitializer.cpp
@@ -282,51 +282,43 @@ void DbInitializer::execPendingQueries(const QStringList &queries)
}
}
-QString DbInitializer::sqlType(const QString &type, int size) const
+QString DbInitializer::sqlType(const ColumnDescription &col, int size) const
{
Q_UNUSED(size);
- if (type == QLatin1String("int")) {
+ if (col.type == QLatin1String("int")) {
return QStringLiteral("INTEGER");
}
- if (type == QLatin1String("qint64")) {
+ if (col.type == QLatin1String("qint64")) {
return QStringLiteral("BIGINT");
}
- if (type == QLatin1String("QString")) {
+ if (col.type == QLatin1String("QString")) {
return QStringLiteral("TEXT");
}
- if (type == QLatin1String("QByteArray")) {
+ if (col.type == QLatin1String("QByteArray")) {
return QStringLiteral("LONGBLOB");
}
- if (type == QLatin1String("QDateTime")) {
+ if (col.type == QLatin1String("QDateTime")) {
return QStringLiteral("TIMESTAMP");
}
- if (type == QLatin1String("bool")) {
+ if (col.type == QLatin1String("bool")) {
return QStringLiteral("BOOL");
}
- if (type == QLatin1String("Tristate")) {
+ if (col.isEnum) {
return QStringLiteral("TINYINT");
}
- qCDebug(AKONADISERVER_LOG) << "Invalid type" << type;
+ qCDebug(AKONADISERVER_LOG) << "Invalid type" << col.type;
Q_ASSERT(false);
return QString();
}
-QString DbInitializer::sqlValue(const QString &type, const QString &value) const
+QString DbInitializer::sqlValue(const ColumnDescription &col, const QString &value) const
{
- if (type == QLatin1String("QDateTime") && value == QLatin1String("QDateTime::currentDateTime()")) {
+ if (col.type == QLatin1String("QDateTime") && value == QLatin1String("QDateTime::currentDateTime()")) {
return QStringLiteral("CURRENT_TIMESTAMP");
+ } else if (col.isEnum) {
+ return QString::number(col.enumValueMap[value]);
}
- if (type == QLatin1String("Tristate")) {
- if (value == QLatin1String("False")) {
- return QString::number((int)Akonadi::Tristate::False);
- }
- if (value == QLatin1String("True")) {
- return QString::number((int)Akonadi::Tristate::True);
- }
- return QString::number((int)Akonadi::Tristate::Undefined);
- }
-
return value;
}
diff --git a/src/server/storage/dbinitializer.h b/src/server/storage/dbinitializer.h
index 13031ad..a3bc803 100644
--- a/src/server/storage/dbinitializer.h
+++ b/src/server/storage/dbinitializer.h
@@ -116,9 +116,9 @@ protected:
* @param type Name of the C++ type.
* @param size Optional size hint for the column, if -1 use the default SQL type for @p type.
*/
- virtual QString sqlType(const QString &type, int size) const;
+ virtual QString sqlType(const ColumnDescription &col, int size) const;
/** Overwrite in backend-specific sub-classes to return the SQL value for a given C++ value. */
- virtual QString sqlValue(const QString &type, const QString &value) const;
+ virtual QString sqlValue(const ColumnDescription &col, const QString &value) const;
virtual QString buildColumnStatement(const ColumnDescription &columnDescription, const TableDescription &tableDescription) const = 0;
virtual QString buildAddColumnStatement(const TableDescription &tableDescription, const ColumnDescription &columnDescription) const;
diff --git a/src/server/storage/dbinitializer_p.cpp b/src/server/storage/dbinitializer_p.cpp
index e88b2dd..efac428 100644
--- a/src/server/storage/dbinitializer_p.cpp
+++ b/src/server/storage/dbinitializer_p.cpp
@@ -29,12 +29,12 @@ DbInitializerMySql::DbInitializerMySql(const QSqlDatabase &database)
{
}
-QString DbInitializerMySql::sqlType(const QString &type, int size) const
+QString DbInitializerMySql::sqlType(const ColumnDescription &col, int size) const
{
- if (type == QLatin1String("QString")) {
+ if (col.type == QLatin1String("QString")) {
return QLatin1Literal("VARBINARY(") + QString::number(size <= 0 ? 255 : size) + QLatin1Literal(")");
} else {
- return DbInitializer::sqlType(type, size);
+ return DbInitializer::sqlType(col, size);
}
}
@@ -67,7 +67,7 @@ QString DbInitializerMySql::buildColumnStatement(const ColumnDescription &column
{
QString column = columnDescription.name;
- column += QLatin1Char(' ') + sqlType(columnDescription.type, columnDescription.size);
+ column += QLatin1Char(' ') + sqlType(columnDescription, columnDescription.size);
if (!columnDescription.allowNull) {
column += QLatin1String(" NOT NULL");
@@ -86,7 +86,7 @@ QString DbInitializerMySql::buildColumnStatement(const ColumnDescription &column
}
if (!columnDescription.defaultValue.isEmpty()) {
- const QString defaultValue = sqlValue(columnDescription.type, columnDescription.defaultValue);
+ const QString defaultValue = sqlValue(columnDescription, columnDescription.defaultValue);
if (!defaultValue.isEmpty()) {
column += QStringLiteral(" DEFAULT %1").arg(defaultValue);
@@ -154,7 +154,7 @@ QString DbInitializerSqlite::buildColumnStatement(const ColumnDescription &colum
if (columnDescription.isAutoIncrement) {
column += QLatin1String("INTEGER");
} else {
- column += sqlType(columnDescription.type, columnDescription.size);
+ column += sqlType(columnDescription, columnDescription.size);
}
if (columnDescription.isPrimaryKey && tableDescription.primaryKeyColumnCount() == 1) {
@@ -172,7 +172,7 @@ QString DbInitializerSqlite::buildColumnStatement(const ColumnDescription &colum
}
if (!columnDescription.defaultValue.isEmpty()) {
- const QString defaultValue = sqlValue(columnDescription.type, columnDescription.defaultValue);
+ const QString defaultValue = sqlValue(columnDescription, columnDescription.defaultValue);
if (!defaultValue.isEmpty()) {
column += QStringLiteral(" DEFAULT %1").arg(defaultValue);
@@ -198,9 +198,9 @@ QString DbInitializerSqlite::buildInsertValuesStatement(const TableDescription &
QStringList(data.values()).join(QLatin1Char(',')));
}
-QString DbInitializerSqlite::sqlValue(const QString &type, const QString &value) const
+QString DbInitializerSqlite::sqlValue(const ColumnDescription &col, const QString &value) const
{
- if (type == QLatin1String("bool")) {
+ if (col.type == QLatin1String("bool")) {
if (value == QLatin1String("false")) {
return QStringLiteral("0");
} else if (value == QLatin1String("true")) {
@@ -209,7 +209,7 @@ QString DbInitializerSqlite::sqlValue(const QString &type, const QString &value)
return value;
}
- return Akonadi::Server::DbInitializer::sqlValue(type, value);
+ return Akonadi::Server::DbInitializer::sqlValue(col, value);
}
//END Sqlite
@@ -221,17 +221,17 @@ DbInitializerPostgreSql::DbInitializerPostgreSql(const QSqlDatabase &database)
{
}
-QString DbInitializerPostgreSql::sqlType(const QString &type, int size) const
+QString DbInitializerPostgreSql::sqlType(const ColumnDescription &col, int size) const
{
- if (type == QLatin1String("qint64")) {
+ if (col.type == QLatin1String("qint64")) {
return QStringLiteral("int8");
- } else if (type == QLatin1String("QByteArray")) {
+ } else if (col.type == QLatin1String("QByteArray")) {
return QStringLiteral("BYTEA");
- } else if (type == QLatin1String("Tristate")) {
+ } else if (col.isEnum) {
return QStringLiteral("SMALLINT");
}
- return DbInitializer::sqlType(type, size);
+ return DbInitializer::sqlType(col, size);
}
QString DbInitializerPostgreSql::buildCreateTableStatement(const TableDescription &tableDescription) const
@@ -257,7 +257,7 @@ QString DbInitializerPostgreSql::buildColumnStatement(const ColumnDescription &c
if (columnDescription.isAutoIncrement) {
column += QLatin1String("SERIAL");
} else {
- column += sqlType(columnDescription.type, columnDescription.size);
+ column += sqlType(columnDescription, columnDescription.size);
}
if (columnDescription.isPrimaryKey && tableDescription.primaryKeyColumnCount() == 1) {
@@ -271,7 +271,7 @@ QString DbInitializerPostgreSql::buildColumnStatement(const ColumnDescription &c
}
if (!columnDescription.defaultValue.isEmpty()) {
- const QString defaultValue = sqlValue(columnDescription.type, columnDescription.defaultValue);
+ const QString defaultValue = sqlValue(columnDescription, columnDescription.defaultValue);
if (!defaultValue.isEmpty()) {
column += QStringLiteral(" DEFAULT %1").arg(defaultValue);
diff --git a/src/server/storage/dbinitializer_p.h b/src/server/storage/dbinitializer_p.h
index 4fb1faf..83be649 100644
--- a/src/server/storage/dbinitializer_p.h
+++ b/src/server/storage/dbinitializer_p.h
@@ -33,7 +33,7 @@ class DbInitializerMySql : public DbInitializer
public:
explicit DbInitializerMySql(const QSqlDatabase &database);
protected:
- QString sqlType(const QString &type, int size) const Q_DECL_OVERRIDE;
+ QString sqlType(const ColumnDescription &col, int size) const Q_DECL_OVERRIDE;
QString buildCreateTableStatement(const TableDescription &tableDescription) const Q_DECL_OVERRIDE;
QString buildColumnStatement(const ColumnDescription &columnDescription, const TableDescription &tableDescription) const Q_DECL_OVERRIDE;
@@ -50,7 +50,7 @@ protected:
QString buildCreateTableStatement(const TableDescription &tableDescription) const Q_DECL_OVERRIDE;
QString buildColumnStatement(const ColumnDescription &columnDescription, const TableDescription &tableDescription) const Q_DECL_OVERRIDE;
QString buildInsertValuesStatement(const TableDescription &tableDescription, const DataDescription &dataDescription) const Q_DECL_OVERRIDE;
- QString sqlValue(const QString &type, const QString &value) const Q_DECL_OVERRIDE;
+ QString sqlValue(const ColumnDescription &col, const QString &value) const Q_DECL_OVERRIDE;
};
class DbInitializerPostgreSql : public DbInitializer
@@ -58,7 +58,7 @@ class DbInitializerPostgreSql : public DbInitializer
public:
explicit DbInitializerPostgreSql(const QSqlDatabase &database);
protected:
- QString sqlType(const QString &type, int size) const Q_DECL_OVERRIDE;
+ QString sqlType(const ColumnDescription &col, int size) const Q_DECL_OVERRIDE;
QString buildCreateTableStatement(const TableDescription &tableDescription) const Q_DECL_OVERRIDE;
QString buildColumnStatement(const ColumnDescription &columnDescription, const TableDescription &tableDescription) const Q_DECL_OVERRIDE;
diff --git a/src/server/storage/entities-header.xsl b/src/server/storage/entities-header.xsl
index e87e9ee..fc471aa 100644
--- a/src/server/storage/entities-header.xsl
+++ b/src/server/storage/entities-header.xsl
@@ -50,6 +50,14 @@ class <xsl:value-of select="$className"/> : private Entity
using Entity::addToRelation;
using Entity::removeFromRelation;
+ <xsl:for-each select="enum">
+ enum <xsl:value-of select="@name"/> {
+ <xsl:for-each select="value">
+ <xsl:value-of select="@name"/><xsl:if test="@value"> = <xsl:value-of select="@value"/></xsl:if>,
+ </xsl:for-each>
+ };
+ </xsl:for-each>
+
// constructor
<xsl:value-of select="$className"/>();
explicit <xsl:value-of select="$className"/>(
@@ -79,7 +87,7 @@ class <xsl:value-of select="$className"/> : private Entity
Returns the value of the <xsl:value-of select="@name"/> column of this record.
<xsl:value-of select="comment"/>
*/
- <xsl:value-of select="@type"/><xsl:text> </xsl:text><xsl:value-of select="@name"/>() const;
+ <xsl:call-template name="data-type"/><xsl:text> </xsl:text><xsl:value-of select="@name"/>() const;
/**
Sets the value of the <xsl:value-of select="@name"/> column of this record.
<xsl:value-of select="comment"/>
diff --git a/src/server/storage/entities-source.xsl b/src/server/storage/entities-source.xsl
index 50a22a4..3c74eed 100644
--- a/src/server/storage/entities-source.xsl
+++ b/src/server/storage/entities-source.xsl
@@ -55,8 +55,8 @@ class <xsl:value-of select="$className"/>::Private : public QSharedData
<xsl:for-each select="column[@type = 'bool']">
, <xsl:value-of select="@name"/>( <xsl:choose><xsl:when test="@default"><xsl:value-of select="@default"/></xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose> )
</xsl:for-each>
- <xsl:for-each select="column[@type = 'Tristate']">
- , <xsl:value-of select="@name"/>( <xsl:choose><xsl:when test="@default"><xsl:value-of select="@default"/></xsl:when><xsl:otherwise>Tristate::Undefined</xsl:otherwise></xsl:choose> )
+ <xsl:for-each select="column[@type = 'enum']">
+ , <xsl:value-of select="@name"/>( <xsl:choose><xsl:when test="@default"><xsl:value-of select="@default"/></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose> )
</xsl:for-each>
<xsl:for-each select="column[@name != 'id']">
, <xsl:value-of select="@name"/>_changed( false )
@@ -91,6 +91,9 @@ class <xsl:value-of select="$className"/>::Private : public QSharedData
<xsl:for-each select="column[@type = 'Tristate']">
Tristate <xsl:value-of select="@name"/>;
</xsl:for-each>
+ <xsl:for-each select="column[@type = 'enum']">
+ <xsl:value-of select="@enumType"/><xsl:text> </xsl:text><xsl:value-of select="@name"/>;
+ </xsl:for-each>
<xsl:for-each select="column[@name != 'id']">
bool <xsl:value-of select="@name"/>_changed : 1;
</xsl:for-each>
@@ -205,10 +208,7 @@ bool <xsl:value-of select="$className"/>::operator==( const <xsl:value-of select
// accessor methods
<xsl:for-each select="column[@name != 'id']">
-<xsl:choose>
- <xsl:when test="starts-with(@type, 'Tristate')">Akonadi::Tristate</xsl:when>
- <xsl:otherwise><xsl:value-of select="@type"/></xsl:otherwise>
-</xsl:choose><xsl:text> </xsl:text><xsl:value-of select="$className"/>::<xsl:value-of select="@name"/>() const
+<xsl:call-template name="data-type"/><xsl:text> </xsl:text><xsl:value-of select="$className"/>::<xsl:value-of select="@name"/>() const
{
<xsl:text>return d-&gt;</xsl:text><xsl:value-of select="@name"/>;
}
@@ -307,13 +307,13 @@ QVector&lt; <xsl:value-of select="$className"/> &gt; <xsl:value-of select="$clas
rv.append( <xsl:value-of select="$className"/>(
<xsl:for-each select="column">
(query.isNull(<xsl:value-of select="position() - 1"/>)) ?
- <xsl:value-of select="@type"/>() :
+ <xsl:call-template name="data-type"/>() :
<xsl:choose>
<xsl:when test="starts-with(@type,'QString')">
Utils::variantToString( query.value( <xsl:value-of select="position() - 1"/> ) )
</xsl:when>
- <xsl:when test="starts-with(@type, 'Tristate')">
- static_cast&lt;Tristate&gt;(query.value( <xsl:value-of select="position() - 1"/> ).value&lt;int&gt;())
+ <xsl:when test="starts-with(@type, 'enum')">
+ static_cast&lt;<xsl:value-of select="@enumType"/>&gt;(query.value( <xsl:value-of select="position() - 1"/> ).value&lt;int&gt;())
</xsl:when>
<xsl:otherwise>
query.value( <xsl:value-of select="position() - 1"/> ).value&lt;<xsl:value-of select="@type"/>&gt;()
@@ -561,7 +561,7 @@ QDebug &amp; operator&lt;&lt;( QDebug&amp; d, const <xsl:value-of select="$class
<xsl:for-each select="column">
&lt;&lt; "<xsl:value-of select="@name"/> = " &lt;&lt;
<xsl:choose>
- <xsl:when test="starts-with(@type, 'Tristate')">
+ <xsl:when test="starts-with(@type, 'enum')">
static_cast&lt;int&gt;(entity.<xsl:value-of select="@name"/>())
</xsl:when>
<xsl:otherwise>
@@ -595,7 +595,7 @@ bool <xsl:value-of select="$className"/>::insert( qint64* insertId )
<xsl:if test="$refColumn != 'id'">
if ( d-&gt;<xsl:value-of select="@name"/>_changed )
<xsl:choose>
- <xsl:when test="starts-with(@type, 'Tristate')">
+ <xsl:when test="starts-with(@type, 'enum')">
qb.setColumnValue( <xsl:value-of select="@name"/>Column(), static_cast&lt;int&gt;(this-&gt;<xsl:value-of select="@name"/>()) );
</xsl:when>
<xsl:otherwise>
@@ -644,7 +644,7 @@ bool <xsl:value-of select="$className"/>::update()
else
</xsl:if>
<xsl:choose>
- <xsl:when test="starts-with(@type, 'Tristate')">
+ <xsl:when test="starts-with(@type, 'enum')">
qb.setColumnValue( <xsl:value-of select="@name"/>Column(), static_cast&lt;int&gt;(this-&gt;<xsl:value-of select="@name"/>()) );
</xsl:when>
<xsl:otherwise>
diff --git a/src/server/storage/entities.xsl b/src/server/storage/entities.xsl
index 6fb1e92..d56e93c 100644
--- a/src/server/storage/entities.xsl
+++ b/src/server/storage/entities.xsl
@@ -148,9 +148,16 @@ QVector&lt;QString&gt; Akonadi::Server::allDatabaseTables()
<xsl:value-of select="concat(translate(substring($argument,1,1),'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), substring($argument,2))"/>
</xsl:template>
+<xsl:template name="data-type">
+ <xsl:choose>
+ <xsl:when test="@type = 'enum'"><xsl:value-of select="../@name"/>::<xsl:value-of select="@enumType"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="@type"/></xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
<!-- generates function argument code for the current column -->
<xsl:template name="argument">
- <xsl:if test="starts-with(@type,'Q')">const </xsl:if><xsl:value-of select="@type"/><xsl:text> </xsl:text>
+ <xsl:if test="starts-with(@type,'Q')">const </xsl:if><xsl:call-template name="data-type"/><xsl:text> </xsl:text>
<xsl:if test="starts-with(@type,'Q')">&amp;</xsl:if><xsl:value-of select="@name"/>
</xsl:template>
@@ -210,20 +217,20 @@ set<xsl:value-of select="$methodName"/>( <xsl:call-template name="argument"/> )
<!-- this indirection is required to prevent off-by-one access now that we skip the key column -->
int valueIndex = 0;
<xsl:for-each select="column">
- const <xsl:value-of select="@type"/> value<xsl:value-of select="position()"/> =
+ const <xsl:call-template name="data-type"/> value<xsl:value-of select="position()"/> =
<xsl:choose>
<xsl:when test="@name=$key">
<xsl:value-of select="$key"/>;
</xsl:when>
<xsl:otherwise>
(qb.query().isNull(valueIndex)) ?
- <xsl:value-of select="@type"/>() :
+ <xsl:call-template name="data-type"/>() :
<xsl:choose>
<xsl:when test="starts-with(@type,'QString')">
Utils::variantToString( qb.query().value( valueIndex ) )
</xsl:when>
- <xsl:when test="starts-with(@type, 'Tristate')">
- static_cast&lt;Tristate&gt;(qb.query().value( valueIndex ).value&lt;int&gt;())
+ <xsl:when test="starts-with(@type, 'enum')">
+ static_cast&lt;<xsl:value-of select="@enumType"/>&gt;(qb.query().value( valueIndex ).value&lt;int&gt;())
</xsl:when>
<xsl:when test="starts-with(@type, 'QDateTime')">
Utils::variantToDateTime(qb.query().value(valueIndex))
diff --git a/src/server/storage/schema-source.xsl b/src/server/storage/schema-source.xsl
index d0d294d..242e762 100644
--- a/src/server/storage/schema-source.xsl
+++ b/src/server/storage/schema-source.xsl
@@ -21,6 +21,13 @@
version="1.0">
<xsl:output method="text" encoding="utf-8"/>
+<xsl:template name="data-type">
+ <xsl:choose>
+ <xsl:when test="@type = 'enum'"><xsl:value-of select="@enumType"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="@type"/></xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
<xsl:template name="schema-source">
#include "<xsl:value-of select="$fileName"/>.h"
@@ -40,7 +47,7 @@ QVector&lt;TableDescription&gt; <xsl:value-of select="$className"/>::tables()
{
ColumnDescription c;
c.name = QStringLiteral("<xsl:value-of select="@name"/>");
- c.type = QStringLiteral("<xsl:value-of select="@type"/>");
+ c.type = QStringLiteral("<xsl:call-template name="data-type"/>");
<xsl:if test="@size">
c.size = <xsl:value-of select="@size"/>;
</xsl:if>
@@ -56,6 +63,9 @@ QVector&lt;TableDescription&gt; <xsl:value-of select="$className"/>::tables()
<xsl:if test="@isUnique">
c.isUnique = <xsl:value-of select="@isUnique"/>;
</xsl:if>
+ <xsl:if test="@type = 'enum'">
+ c.isEnum = true;
+ </xsl:if>
<xsl:if test="@refTable">
c.refTable = QStringLiteral("<xsl:value-of select="@refTable"/>");
</xsl:if>
@@ -75,6 +85,20 @@ QVector&lt;TableDescription&gt; <xsl:value-of select="$className"/>::tables()
c.noUpdate = <xsl:value-of select="@noUpdate"/>;
</xsl:if>
+ <xsl:if test="@type = 'enum'">
+ c.enumValueMap = {
+ <xsl:for-each select="../enum">
+ <xsl:for-each select="value">
+ { QStringLiteral("<xsl:value-of select="../@name"/>::<xsl:value-of select="@name"/>"),
+ <xsl:choose>
+ <xsl:when test="@value"><xsl:value-of select="@value"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="position() - 1"/></xsl:otherwise>
+ </xsl:choose> }<xsl:if test="position() != last()">,</xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ };
+ </xsl:if>
+
t.columns.push_back(c);
}
</xsl:for-each>
diff --git a/src/server/storage/schematypes.cpp b/src/server/storage/schematypes.cpp
index d03d39b..efeaf83 100644
--- a/src/server/storage/schematypes.cpp
+++ b/src/server/storage/schematypes.cpp
@@ -30,6 +30,7 @@ ColumnDescription::ColumnDescription()
, isAutoIncrement(false)
, isPrimaryKey(false)
, isUnique(false)
+ , isEnum(false)
, onUpdate(Cascade)
, onDelete(Cascade)
, noUpdate(false)
diff --git a/src/server/storage/schematypes.h b/src/server/storage/schematypes.h
index 02f5681..0e3fb54 100644
--- a/src/server/storage/schematypes.h
+++ b/src/server/storage/schematypes.h
@@ -52,12 +52,15 @@ public:
bool isAutoIncrement;
bool isPrimaryKey;
bool isUnique;
+ bool isEnum;
QString refTable;
QString refColumn;
QString defaultValue;
ReferentialAction onUpdate;
ReferentialAction onDelete;
bool noUpdate;
+
+ QMap<QString, int> enumValueMap;
};
/**