Skip to content

Commit

Permalink
Add support for conflict clauses to the grammar parser
Browse files Browse the repository at this point in the history
Add support for parsing and generating CREATE statements with an ON
CONFLICT clause for their primary key.
  • Loading branch information
MKleusberg committed Jan 5, 2018
1 parent 29fa332 commit 743e798
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/sqlitetypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class CreateTableWalker

private:
void parsecolumn(Table* table, antlr::RefAST c);
QString parseConflictClause(antlr::RefAST c);

private:
antlr::RefAST m_root;
Expand Down Expand Up @@ -219,6 +220,9 @@ QString PrimaryKeyConstraint::toSql(const FieldVector& applyOn) const
result += QString("CONSTRAINT %1 ").arg(escapeIdentifier(m_name));
result += QString("PRIMARY KEY(%1)").arg(fieldVectorToFieldNames(applyOn).join(","));

if(!m_conflictAction.isEmpty())
result += " ON CONFLICT " + m_conflictAction;

return result;
}

Expand Down Expand Up @@ -794,6 +798,10 @@ TablePtr CreateTableWalker::table()
}
} while(tc != antlr::nullAST && tc->getType() != sqlite3TokenTypes::RPAREN);

// We're either done now or there is a conflict clause
tc = tc->getNextSibling(); // skip RPAREN
pk->setConflictAction(parseConflictClause(tc));

tab->addConstraint(fields, ConstraintPtr(pk));
}
break;
Expand Down Expand Up @@ -1026,6 +1034,9 @@ void CreateTableWalker::parsecolumn(Table* table, antlr::RefAST c)
table->setFullyParsed(false);
con = con->getNextSibling(); //skip
}

primaryKey->setConflictAction(parseConflictClause(con));

if(con != antlr::nullAST && con->getType() == sqlite3TokenTypes::AUTOINCREMENT)
autoincrement = true;
}
Expand Down Expand Up @@ -1145,6 +1156,21 @@ void CreateTableWalker::parsecolumn(Table* table, antlr::RefAST c)
}
}

QString CreateTableWalker::parseConflictClause(antlr::RefAST c)
{
QString conflictAction;

if(c != antlr::nullAST && c->getType() == sqlite3TokenTypes::ON && c->getNextSibling()->getType() == sqlite3TokenTypes::CONFLICT)
{
c = c->getNextSibling(); // skip ON
c = c->getNextSibling(); // skip CONFLICT
conflictAction = identifier(c);
c = c->getNextSibling(); // skip action
}

return conflictAction;
}



QString IndexedColumn::toString(const QString& indent, const QString& sep) const
Expand Down
6 changes: 6 additions & 0 deletions src/sqlitetypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,15 @@ class PrimaryKeyConstraint : public Constraint
public:
PrimaryKeyConstraint() {}

void setConflictAction(const QString& conflict) { m_conflictAction = conflict; }
const QString& conflictAction() const { return m_conflictAction; }

virtual QString toSql(const FieldVector& applyOn) const;

virtual ConstraintTypes type() const { return PrimaryKeyConstraintType; }

private:
QString m_conflictAction;
};

class CheckConstraint : public Constraint
Expand Down

0 comments on commit 743e798

Please sign in to comment.