Add parsing support for UNIQUE table constraints

See issue #540.
This commit is contained in:
Martin Kleusberg
2016-08-18 20:33:39 +02:00
parent f1dbd2e8ac
commit 225d3437e0
2 changed files with 47 additions and 13 deletions

View File

@@ -127,6 +127,27 @@ void Table::setFields(const FieldVector &fields)
m_fields = fields;
}
void Table::setField(int index, FieldPtr f)
{
FieldPtr oldField = m_fields[index];
m_fields[index] = f;
// Update unique constraints. If an existing field is updated but was used in a unique constraint, the pointer in the
// unique constraint needs to be updated to the new field, too.
if(oldField)
{
for(int i=0;i<m_uniqueConstraints.size();++i)
{
FieldVector& constraint = m_uniqueConstraints[i];
for(int j=0;j<constraint.size();++j)
{
if(constraint[i] == oldField)
constraint[i] = f;
}
}
}
}
int Table::findField(const QString &sname)
{
for(int i = 0; i < m_fields.count(); ++i)
@@ -231,6 +252,15 @@ QString Table::sql() const
sql += pk + ")";
}
// unique constraints
foreach(FieldVector constraint, m_uniqueConstraints)
{
QStringList fieldnames;
foreach(FieldPtr field, constraint)
fieldnames.append(escapeIdentifier(field->name()));
sql += QString(",\n\tUNIQUE(%1)").arg(fieldnames.join(","));
}
// foreign keys
foreach(FieldPtr f, m_fields)
{
@@ -247,6 +277,11 @@ QString Table::sql() const
return sql + ";";
}
void Table::addUniqueConstraint(FieldVector fields)
{
m_uniqueConstraints.push_back(fields);
}
namespace
{
QString identifier(antlr::RefAST ident)
@@ -386,13 +421,12 @@ Table CreateTableWalker::table()
{
tc = tc->getNextSibling(); // skip UNIQUE
tc = tc->getNextSibling(); // skip LPAREN
QVector<int> uniquefieldsindex;
FieldVector fields;
do
{
QString col = columnname(tc);
int fieldindex = tab.findField(col);
if(fieldindex != -1)
uniquefieldsindex.append(fieldindex);
FieldPtr field = tab.field(tab.findField(col));
fields.push_back(field);
tc = tc->getNextSibling();
if(tc != antlr::nullAST
@@ -410,15 +444,10 @@ Table CreateTableWalker::table()
}
} while(tc != antlr::nullAST && tc->getType() != sqlite3TokenTypes::RPAREN);
if(uniquefieldsindex.size() == 1)
{
tab.fields().at(uniquefieldsindex[0])->setUnique(true);
}
if(fields.size() == 1)
fields[0]->setUnique(true);
else
{
// else save on table a unique with more than one field
m_bModifySupported = false;
}
tab.addUniqueConstraint(fields);
}
break;
case sqlite3TokenTypes::FOREIGN:

View File

@@ -106,6 +106,7 @@ private:
typedef QSharedPointer<Field> FieldPtr;
typedef QVector< FieldPtr > FieldVector;
class Table
{
public:
@@ -126,13 +127,16 @@ public:
void addField(const FieldPtr& f);
bool removeField(const QString& sFieldName);
void setFields(const FieldVector& fields);
void setField(int index, FieldPtr f) { m_fields[index] = f; }
void setField(int index, FieldPtr f);
const FieldPtr& field(int index) { return m_fields[index]; }
QStringList fieldNames() const;
void setRowidColumn(const QString& rowid) { m_rowidColumn = rowid; }
const QString& rowidColumn() const { return m_rowidColumn; }
bool isWithoutRowidTable() const { return m_rowidColumn != "_rowid_"; }
void clear();
void addUniqueConstraint(FieldVector fields);
/**
* @brief findField Finds a field and returns the index.
* @param sname
@@ -159,6 +163,7 @@ private:
QString m_name;
FieldVector m_fields;
QString m_rowidColumn;
QVector<FieldVector> m_uniqueConstraints;
};
/**