Store table constraints in a vector instead of a set

This should make sure we keep the constraints in the order the parser
reads them so the output of the SQL export becomes more stable.

See issue #2627.
This commit is contained in:
Martin Kleusberg
2021-03-16 15:17:16 +01:00
parent fb80d3bcd1
commit 4e1d1ff49f
6 changed files with 64 additions and 64 deletions

View File

@@ -1,8 +1,8 @@
// A Bison parser, made by GNU Bison 3.7.4.
// A Bison parser, made by GNU Bison 3.7.5.
// Locations for Bison parsers in C++
// Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc.
// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by

View File

@@ -1,8 +1,8 @@
// A Bison parser, made by GNU Bison 3.7.4.
// A Bison parser, made by GNU Bison 3.7.5.
// Skeleton implementation for Bison LALR(1) parsers in C++
// Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc.
// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -149,7 +149,7 @@
#else // !YYDEBUG
# define YYCDEBUG if (false) std::cerr
# define YY_SYMBOL_PRINT(Title, Symbol) YYUSE (Symbol)
# define YY_SYMBOL_PRINT(Title, Symbol) YY_USE (Symbol)
# define YY_REDUCE_PRINT(Rule) static_cast<void> (0)
# define YY_STACK_PRINT() static_cast<void> (0)
@@ -254,7 +254,7 @@ namespace sqlb { namespace parser {
case symbol_kind::S_columnconstraint_list: // columnconstraint_list
case symbol_kind::S_tableconstraint_list: // tableconstraint_list
case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list
value.YY_MOVE_OR_COPY< sqlb::ConstraintSet > (YY_MOVE (that.value));
value.YY_MOVE_OR_COPY< sqlb::ConstraintVector > (YY_MOVE (that.value));
break;
case symbol_kind::S_createindex_stmt: // createindex_stmt
@@ -444,7 +444,7 @@ namespace sqlb { namespace parser {
case symbol_kind::S_columnconstraint_list: // columnconstraint_list
case symbol_kind::S_tableconstraint_list: // tableconstraint_list
case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list
value.move< sqlb::ConstraintSet > (YY_MOVE (that.value));
value.move< sqlb::ConstraintVector > (YY_MOVE (that.value));
break;
case symbol_kind::S_createindex_stmt: // createindex_stmt
@@ -634,7 +634,7 @@ namespace sqlb { namespace parser {
case symbol_kind::S_columnconstraint_list: // columnconstraint_list
case symbol_kind::S_tableconstraint_list: // tableconstraint_list
case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list
value.copy< sqlb::ConstraintSet > (that.value);
value.copy< sqlb::ConstraintVector > (that.value);
break;
case symbol_kind::S_createindex_stmt: // createindex_stmt
@@ -823,7 +823,7 @@ namespace sqlb { namespace parser {
case symbol_kind::S_columnconstraint_list: // columnconstraint_list
case symbol_kind::S_tableconstraint_list: // tableconstraint_list
case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list
value.move< sqlb::ConstraintSet > (that.value);
value.move< sqlb::ConstraintVector > (that.value);
break;
case symbol_kind::S_createindex_stmt: // createindex_stmt
@@ -1003,7 +1003,7 @@ namespace sqlb { namespace parser {
parser::yy_print_ (std::ostream& yyo, const basic_symbol<Base>& yysym) const
{
std::ostream& yyoutput = yyo;
YYUSE (yyoutput);
YY_USE (yyoutput);
if (yysym.empty ())
yyo << "empty symbol";
else
@@ -1012,7 +1012,7 @@ namespace sqlb { namespace parser {
yyo << (yykind < YYNTOKENS ? "token" : "nterm")
<< ' ' << yysym.name () << " ("
<< yysym.location << ": ";
YYUSE (yykind);
YY_USE (yykind);
yyo << ')';
}
}
@@ -1257,7 +1257,7 @@ namespace sqlb { namespace parser {
case symbol_kind::S_columnconstraint_list: // columnconstraint_list
case symbol_kind::S_tableconstraint_list: // tableconstraint_list
case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list
yylhs.value.emplace< sqlb::ConstraintSet > ();
yylhs.value.emplace< sqlb::ConstraintVector > ();
break;
case symbol_kind::S_createindex_stmt: // createindex_stmt
@@ -2862,13 +2862,13 @@ namespace sqlb { namespace parser {
case 229: // columnconstraint_list: columnconstraint
#line 716 "sqlite3_parser.yy"
{ yylhs.value.as < sqlb::ConstraintSet > () = { yystack_[0].value.as < sqlb::ConstraintPtr > () }; }
{ yylhs.value.as < sqlb::ConstraintVector > () = { yystack_[0].value.as < sqlb::ConstraintPtr > () }; }
#line 2867 "sqlite3_parser.cpp"
break;
case 230: // columnconstraint_list: columnconstraint_list columnconstraint
#line 717 "sqlite3_parser.yy"
{ yylhs.value.as < sqlb::ConstraintSet > () = yystack_[1].value.as < sqlb::ConstraintSet > (); yylhs.value.as < sqlb::ConstraintSet > ().insert(yystack_[0].value.as < sqlb::ConstraintPtr > ()); }
{ yylhs.value.as < sqlb::ConstraintVector > () = yystack_[1].value.as < sqlb::ConstraintVector > (); yylhs.value.as < sqlb::ConstraintVector > ().push_back(yystack_[0].value.as < sqlb::ConstraintPtr > ()); }
#line 2873 "sqlite3_parser.cpp"
break;
@@ -2876,8 +2876,8 @@ namespace sqlb { namespace parser {
#line 721 "sqlite3_parser.yy"
{
sqlb::Field f(yystack_[2].value.as < std::string > (), yystack_[1].value.as < std::string > ());
sqlb::ConstraintSet table_constraints{};
for(const auto& c : yystack_[0].value.as < sqlb::ConstraintSet > ())
sqlb::ConstraintVector table_constraints{};
for(const auto& c : yystack_[0].value.as < sqlb::ConstraintVector > ())
{
if(!c)
continue;
@@ -2893,7 +2893,7 @@ namespace sqlb { namespace parser {
c->setColumnList({yystack_[2].value.as < std::string > ()});
else
c->replaceInColumnList("", yystack_[2].value.as < std::string > ());
table_constraints.insert(c);
table_constraints.push_back(c);
break;
}
case sqlb::Constraint::NotNullConstraintType:
@@ -2940,7 +2940,7 @@ namespace sqlb { namespace parser {
case 232: // columndef: columnid optional_typename
#line 782 "sqlite3_parser.yy"
{ yylhs.value.as < ColumndefData > () = std::make_tuple(sqlb::Field(yystack_[1].value.as < std::string > (), yystack_[0].value.as < std::string > ()), sqlb::ConstraintSet{}); }
{ yylhs.value.as < ColumndefData > () = std::make_tuple(sqlb::Field(yystack_[1].value.as < std::string > (), yystack_[0].value.as < std::string > ()), sqlb::ConstraintVector{}); }
#line 2945 "sqlite3_parser.cpp"
break;
@@ -3245,31 +3245,31 @@ namespace sqlb { namespace parser {
case 279: // tableconstraint_list: tableconstraint
#line 879 "sqlite3_parser.yy"
{ yylhs.value.as < sqlb::ConstraintSet > () = {yystack_[0].value.as < sqlb::ConstraintPtr > ()}; }
{ yylhs.value.as < sqlb::ConstraintVector > () = {yystack_[0].value.as < sqlb::ConstraintPtr > ()}; }
#line 3250 "sqlite3_parser.cpp"
break;
case 280: // tableconstraint_list: tableconstraint_list "," tableconstraint
#line 880 "sqlite3_parser.yy"
{ yylhs.value.as < sqlb::ConstraintSet > () = yystack_[2].value.as < sqlb::ConstraintSet > (); yylhs.value.as < sqlb::ConstraintSet > ().insert(yystack_[0].value.as < sqlb::ConstraintPtr > ()); }
{ yylhs.value.as < sqlb::ConstraintVector > () = yystack_[2].value.as < sqlb::ConstraintVector > (); yylhs.value.as < sqlb::ConstraintVector > ().push_back(yystack_[0].value.as < sqlb::ConstraintPtr > ()); }
#line 3256 "sqlite3_parser.cpp"
break;
case 281: // tableconstraint_list: tableconstraint_list tableconstraint
#line 881 "sqlite3_parser.yy"
{ yylhs.value.as < sqlb::ConstraintSet > () = yystack_[1].value.as < sqlb::ConstraintSet > (); yylhs.value.as < sqlb::ConstraintSet > ().insert(yystack_[0].value.as < sqlb::ConstraintPtr > ()); }
{ yylhs.value.as < sqlb::ConstraintVector > () = yystack_[1].value.as < sqlb::ConstraintVector > (); yylhs.value.as < sqlb::ConstraintVector > ().push_back(yystack_[0].value.as < sqlb::ConstraintPtr > ()); }
#line 3262 "sqlite3_parser.cpp"
break;
case 282: // optional_tableconstraint_list: %empty
#line 885 "sqlite3_parser.yy"
{ yylhs.value.as < sqlb::ConstraintSet > () = {}; }
{ yylhs.value.as < sqlb::ConstraintVector > () = {}; }
#line 3268 "sqlite3_parser.cpp"
break;
case 283: // optional_tableconstraint_list: "," tableconstraint_list
#line 886 "sqlite3_parser.yy"
{ yylhs.value.as < sqlb::ConstraintSet > () = yystack_[0].value.as < sqlb::ConstraintSet > (); }
{ yylhs.value.as < sqlb::ConstraintVector > () = yystack_[0].value.as < sqlb::ConstraintVector > (); }
#line 3274 "sqlite3_parser.cpp"
break;
@@ -3287,13 +3287,13 @@ namespace sqlb { namespace parser {
{
yylhs.value.as < sqlb::TablePtr > () = std::make_shared<sqlb::Table>(yystack_[5].value.as < std::string > ());
yylhs.value.as < sqlb::TablePtr > ()->setWithoutRowidTable(yystack_[0].value.as < bool > ());
yylhs.value.as < sqlb::TablePtr > ()->setConstraints(yystack_[2].value.as < sqlb::ConstraintSet > ());
yylhs.value.as < sqlb::TablePtr > ()->setConstraints(yystack_[2].value.as < sqlb::ConstraintVector > ());
yylhs.value.as < sqlb::TablePtr > ()->setFullyParsed(true);
for(const auto& column : yystack_[3].value.as < std::vector<ColumndefData> > ())
{
sqlb::Field f;
sqlb::ConstraintSet c;
sqlb::ConstraintVector c;
std::tie(f, c) = column;
yylhs.value.as < sqlb::TablePtr > ()->fields.push_back(f);
@@ -3782,7 +3782,7 @@ namespace sqlb { namespace parser {
const short
parser::yydefgoto_[] =
{
-1, 2, 3, 127, 128, 129, 70, 94, 208, 209,
0, 2, 3, 127, 128, 129, 70, 94, 208, 209,
103, 104, 130, 131, 132, 133, 134, 135, 136, 137,
160, 138, 139, 140, 98, 19, 202, 11, 286, 71,
142, 143, 4, 100, 5, 12, 230, 305, 105, 471,

View File

@@ -1,8 +1,8 @@
// A Bison parser, made by GNU Bison 3.7.4.
// A Bison parser, made by GNU Bison 3.7.5.
// Skeleton interface for Bison LALR(1) parsers in C++
// Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc.
// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -55,7 +55,7 @@
typedef void* yyscan_t;
// Colum definitions are a tuple of two elements: the Field object and a set of table constraints
using ColumndefData = std::tuple<sqlb::Field, sqlb::ConstraintSet>;
using ColumndefData = std::tuple<sqlb::Field, sqlb::ConstraintVector>;
#line 61 "sqlite3_parser.hpp"
@@ -128,9 +128,9 @@
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E))
# define YY_USE(E) ((void) (E))
#else
# define YYUSE(E) /* empty */
# define YY_USE(E) /* empty */
#endif
#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
@@ -423,7 +423,7 @@ namespace sqlb { namespace parser {
// columnconstraint_list
// tableconstraint_list
// optional_tableconstraint_list
char dummy4[sizeof (sqlb::ConstraintSet)];
char dummy4[sizeof (sqlb::ConstraintVector)];
// createindex_stmt
char dummy5[sizeof (sqlb::IndexPtr)];
@@ -980,7 +980,7 @@ namespace sqlb { namespace parser {
case symbol_kind::S_columnconstraint_list: // columnconstraint_list
case symbol_kind::S_tableconstraint_list: // tableconstraint_list
case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list
value.move< sqlb::ConstraintSet > (std::move (that.value));
value.move< sqlb::ConstraintVector > (std::move (that.value));
break;
case symbol_kind::S_createindex_stmt: // createindex_stmt
@@ -1201,13 +1201,13 @@ namespace sqlb { namespace parser {
#endif
#if 201103L <= YY_CPLUSPLUS
basic_symbol (typename Base::kind_type t, sqlb::ConstraintSet&& v, location_type&& l)
basic_symbol (typename Base::kind_type t, sqlb::ConstraintVector&& v, location_type&& l)
: Base (t)
, value (std::move (v))
, location (std::move (l))
{}
#else
basic_symbol (typename Base::kind_type t, const sqlb::ConstraintSet& v, const location_type& l)
basic_symbol (typename Base::kind_type t, const sqlb::ConstraintVector& v, const location_type& l)
: Base (t)
, value (v)
, location (l)
@@ -1319,7 +1319,7 @@ namespace sqlb { namespace parser {
}
/// Destroy contents, and record that is empty.
void clear ()
void clear () YY_NOEXCEPT
{
// User destructor.
symbol_kind_type yykind = this->kind ();
@@ -1354,7 +1354,7 @@ switch (yykind)
case symbol_kind::S_columnconstraint_list: // columnconstraint_list
case symbol_kind::S_tableconstraint_list: // tableconstraint_list
case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list
value.template destroy< sqlb::ConstraintSet > ();
value.template destroy< sqlb::ConstraintVector > ();
break;
case symbol_kind::S_createindex_stmt: // createindex_stmt
@@ -1565,7 +1565,7 @@ switch (yykind)
by_kind (kind_type t);
/// Record that this symbol is empty.
void clear ();
void clear () YY_NOEXCEPT;
/// Steal the symbol kind from \a that.
void move (by_kind& that);
@@ -3425,9 +3425,9 @@ switch (yykind)
{
public:
context (const parser& yyparser, const symbol_type& yyla);
const symbol_type& lookahead () const { return yyla_; }
symbol_kind_type token () const { return yyla_.kind (); }
const location_type& location () const { return yyla_.location; }
const symbol_type& lookahead () const YY_NOEXCEPT { return yyla_; }
symbol_kind_type token () const YY_NOEXCEPT { return yyla_.kind (); }
const location_type& location () const YY_NOEXCEPT { return yyla_.location; }
/// Put in YYARG at most YYARGN of the expected tokens, and return the
/// number of tokens stored in YYARG. If YYARG is null, return the
@@ -3850,7 +3850,7 @@ switch (yykind)
case symbol_kind::S_columnconstraint_list: // columnconstraint_list
case symbol_kind::S_tableconstraint_list: // tableconstraint_list
case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list
value.copy< sqlb::ConstraintSet > (YY_MOVE (that.value));
value.copy< sqlb::ConstraintVector > (YY_MOVE (that.value));
break;
case symbol_kind::S_createindex_stmt: // createindex_stmt
@@ -4054,7 +4054,7 @@ switch (yykind)
case symbol_kind::S_columnconstraint_list: // columnconstraint_list
case symbol_kind::S_tableconstraint_list: // tableconstraint_list
case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list
value.move< sqlb::ConstraintSet > (YY_MOVE (s.value));
value.move< sqlb::ConstraintVector > (YY_MOVE (s.value));
break;
case symbol_kind::S_createindex_stmt: // createindex_stmt
@@ -4243,7 +4243,7 @@ switch (yykind)
inline
void
parser::by_kind::clear ()
parser::by_kind::clear () YY_NOEXCEPT
{
kind_ = symbol_kind::S_YYEMPTY;
}

View File

@@ -18,7 +18,7 @@
typedef void* yyscan_t;
// Colum definitions are a tuple of two elements: the Field object and a set of table constraints
using ColumndefData = std::tuple<sqlb::Field, sqlb::ConstraintSet>;
using ColumndefData = std::tuple<sqlb::Field, sqlb::ConstraintVector>;
}
// The parsing context
@@ -222,7 +222,7 @@
%type <std::string> optional_typename
%type <std::string> optional_storage_identifier
%type <bool> optional_always_generated
%type <sqlb::ConstraintSet> columnconstraint_list
%type <sqlb::ConstraintVector> columnconstraint_list
%type <sqlb::ConstraintPtr> columnconstraint
%type <ColumndefData> columndef
%type <std::vector<ColumndefData>> columndef_list
@@ -232,8 +232,8 @@
%type <std::string> fk_clause_part_list
%type <std::string> optional_fk_clause
%type <sqlb::ConstraintPtr> tableconstraint
%type <sqlb::ConstraintSet> tableconstraint_list
%type <sqlb::ConstraintSet> optional_tableconstraint_list
%type <sqlb::ConstraintVector> tableconstraint_list
%type <sqlb::ConstraintVector> optional_tableconstraint_list
%type <sqlb::TablePtr> createtable_stmt
%%
@@ -714,13 +714,13 @@ columnconstraint:
columnconstraint_list:
columnconstraint { $$ = { $1 }; }
| columnconstraint_list columnconstraint { $$ = $1; $$.insert($2); }
| columnconstraint_list columnconstraint { $$ = $1; $$.push_back($2); }
;
columndef:
columnid optional_typename columnconstraint_list {
sqlb::Field f($1, $2);
sqlb::ConstraintSet table_constraints{};
sqlb::ConstraintVector table_constraints{};
for(const auto& c : $3)
{
if(!c)
@@ -737,7 +737,7 @@ columndef:
c->setColumnList({$1});
else
c->replaceInColumnList("", $1);
table_constraints.insert(c);
table_constraints.push_back(c);
break;
}
case sqlb::Constraint::NotNullConstraintType:
@@ -779,7 +779,7 @@ columndef:
$$ = std::make_tuple(f, table_constraints);
}
| columnid optional_typename { $$ = std::make_tuple(sqlb::Field($1, $2), sqlb::ConstraintSet{}); }
| columnid optional_typename { $$ = std::make_tuple(sqlb::Field($1, $2), sqlb::ConstraintVector{}); }
;
columndef_list:
@@ -877,8 +877,8 @@ tableconstraint:
tableconstraint_list:
tableconstraint { $$ = {$1}; }
| tableconstraint_list "," tableconstraint { $$ = $1; $$.insert($3); }
| tableconstraint_list tableconstraint { $$ = $1; $$.insert($2); }
| tableconstraint_list "," tableconstraint { $$ = $1; $$.push_back($3); }
| tableconstraint_list tableconstraint { $$ = $1; $$.push_back($2); }
;
optional_tableconstraint_list:
@@ -900,7 +900,7 @@ createtable_stmt:
for(const auto& column : $7)
{
sqlb::Field f;
sqlb::ConstraintSet c;
sqlb::ConstraintVector c;
std::tie(f, c) = column;
$$->fields.push_back(f);

View File

@@ -482,7 +482,7 @@ std::string Table::sql(const std::string& schema, bool ifNotExists) const
void Table::addConstraint(ConstraintPtr constraint)
{
m_constraints.insert(constraint);
m_constraints.push_back(constraint);
}
void Table::setConstraint(ConstraintPtr constraint)
@@ -537,19 +537,19 @@ std::vector<ConstraintPtr> Table::constraints(const StringVector& vStrFields, Co
return clist;
}
void Table::setConstraints(const ConstraintSet& constraints)
void Table::setConstraints(const ConstraintVector& constraints)
{
m_constraints = constraints;
}
void Table::replaceConstraint(ConstraintPtr from, ConstraintPtr to)
{
auto it = m_constraints.find(from);
auto it = std::find(m_constraints.begin(), m_constraints.end(), from);
if(it == m_constraints.end())
return;
m_constraints.erase(it); // Erase old constraint
m_constraints.insert(to); // Insert new constraint
m_constraints.erase(it); // Erase old constraint
m_constraints.push_back(to); // Insert new constraint
}
std::shared_ptr<PrimaryKeyConstraint> Table::primaryKey()

View File

@@ -69,7 +69,7 @@ using TriggerPtr = std::shared_ptr<Trigger>;
using ConstraintPtr = std::shared_ptr<Constraint>;
using FieldVector = std::vector<Field>;
using IndexedColumnVector = std::vector<IndexedColumn>;
using ConstraintSet = std::set<ConstraintPtr>;
using ConstraintVector = std::vector<ConstraintPtr>;
class Object
{
@@ -440,8 +440,8 @@ public:
void removeConstraints(const StringVector& vStrFields = StringVector(), Constraint::ConstraintTypes type = Constraint::NoType);
ConstraintPtr constraint(const StringVector& vStrFields = StringVector(), Constraint::ConstraintTypes type = Constraint::NoType) const; //! Only returns the first constraint, if any
std::vector<ConstraintPtr> constraints(const StringVector& vStrFields = StringVector(), Constraint::ConstraintTypes type = Constraint::NoType) const;
ConstraintSet allConstraints() const { return m_constraints; }
void setConstraints(const ConstraintSet& constraints);
ConstraintVector allConstraints() const { return m_constraints; }
void setConstraints(const ConstraintVector& constraints);
void replaceConstraint(ConstraintPtr from, ConstraintPtr to);
std::shared_ptr<PrimaryKeyConstraint> primaryKey();
void removeKeyFromAllConstraints(const std::string& key);
@@ -458,7 +458,7 @@ private:
private:
bool m_withoutRowid;
ConstraintSet m_constraints;
ConstraintVector m_constraints;
std::string m_virtual;
};