parser: Simplify code

This removes no longer needed code like the handling of not fully parsed
column constraints. It simplifies the code even further by handling
constraints in a more consistent manner which allows us to remove some
redundancies.
This commit is contained in:
Martin Kleusberg
2020-06-19 14:10:45 +02:00
parent d08dcba329
commit fb3a9a0638
7 changed files with 959 additions and 1253 deletions
File diff suppressed because it is too large Load Diff
+26 -134
View File
@@ -54,64 +54,10 @@
namespace sqlb { namespace parser { class ParserDriver; } }
typedef void* yyscan_t;
// Unfortunately we do not store column constraints in a systematic manner yet.
// Instead there is a variable for most column constraints directly inside the
// sqlb::Field class. This means that when parsing a column constraint we cannot
// just build a column constraint object with all the information and insert that
// into the Field object. Instead, the information needs to be passed upwards in
// some other way. This is what these declarations are for. We need to be able
// to pass information to the Field object as well as to the Table object too
// because some column constraints need to be transformed into Table constraints
// with our current layout.
class ColumnConstraintInfo
{
public:
ColumnConstraintInfo() : is_table_constraint(false), fully_parsed(false) {}
~ColumnConstraintInfo() {}
ColumnConstraintInfo& operator=(const ColumnConstraintInfo& other)
{
type = other.type;
is_table_constraint = other.is_table_constraint;
fully_parsed = other.fully_parsed;
constraint = other.constraint;
text = other.text;
generated_constraint = other.generated_constraint;
// 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>;
return *this;
}
ColumnConstraintInfo(const ColumnConstraintInfo& other)
{
*this = other;
}
enum ConstraintType
{
None,
AutoIncrement,
PrimaryKey,
NotNull,
Unique,
Check,
Default,
Collate,
ForeignKey,
Generated,
};
ConstraintType type;
bool is_table_constraint;
bool fully_parsed;
sqlb::ConstraintPtr constraint;
std::string text;
sqlb::GeneratedColumnConstraint generated_constraint;
};
using ColumnConstraintInfoVector = std::vector<ColumnConstraintInfo>;
// Colum definitions are a tuple of three elements: the Field object, a set of table constraints, and a bool to indicate whether parsing was complete
using ColumndefData = std::tuple<sqlb::Field, sqlb::ConstraintSet, bool>;
#line 115 "sqlite3_parser.hpp"
#line 61 "sqlite3_parser.hpp"
# include <cassert>
# include <cstdlib> // std::abort
@@ -246,7 +192,7 @@
#line 10 "sqlite3_parser.yy"
namespace sqlb { namespace parser {
#line 250 "sqlite3_parser.hpp"
#line 196 "sqlite3_parser.hpp"
@@ -460,45 +406,41 @@ namespace sqlb { namespace parser {
/// An auxiliary type to compute the largest semantic type.
union union_type
{
// columnconstraint
char dummy1[sizeof (ColumnConstraintInfo)];
// columnconstraint_list
char dummy2[sizeof (ColumnConstraintInfoVector)];
// columndef
char dummy3[sizeof (ColumndefData)];
char dummy1[sizeof (ColumndefData)];
// optional_if_not_exists
// optional_unique
// optional_temporary
// optional_withoutrowid
// optional_always_generated
char dummy4[sizeof (bool)];
char dummy2[sizeof (bool)];
// columnconstraint
// tableconstraint
char dummy5[sizeof (sqlb::ConstraintPtr)];
char dummy3[sizeof (sqlb::ConstraintPtr)];
// columnconstraint_list
// tableconstraint_list
// optional_tableconstraint_list
char dummy6[sizeof (sqlb::ConstraintSet)];
char dummy4[sizeof (sqlb::ConstraintSet)];
// createindex_stmt
char dummy7[sizeof (sqlb::IndexPtr)];
char dummy5[sizeof (sqlb::IndexPtr)];
// indexed_column
char dummy8[sizeof (sqlb::IndexedColumn)];
char dummy6[sizeof (sqlb::IndexedColumn)];
// indexed_column_list
char dummy9[sizeof (sqlb::IndexedColumnVector)];
char dummy7[sizeof (sqlb::IndexedColumnVector)];
// columnid_list
// optional_columnid_with_paren_list
char dummy10[sizeof (sqlb::StringVector)];
char dummy8[sizeof (sqlb::StringVector)];
// createvirtualtable_stmt
// createtable_stmt
char dummy11[sizeof (sqlb::TablePtr)];
char dummy9[sizeof (sqlb::TablePtr)];
// "ABORT"
// "ACTION"
@@ -623,10 +565,10 @@ namespace sqlb { namespace parser {
// fk_clause_part
// fk_clause_part_list
// optional_fk_clause
char dummy12[sizeof (std::string)];
char dummy10[sizeof (std::string)];
// columndef_list
char dummy13[sizeof (std::vector<ColumndefData>)];
char dummy11[sizeof (std::vector<ColumndefData>)];
};
/// The size of the largest semantic type.
@@ -1018,14 +960,6 @@ namespace sqlb { namespace parser {
{
switch (this->kind ())
{
case 158: // columnconstraint
value.move< ColumnConstraintInfo > (std::move (that.value));
break;
case 159: // columnconstraint_list
value.move< ColumnConstraintInfoVector > (std::move (that.value));
break;
case 160: // columndef
value.move< ColumndefData > (std::move (that.value));
break;
@@ -1038,10 +972,12 @@ namespace sqlb { namespace parser {
value.move< bool > (std::move (that.value));
break;
case 158: // columnconstraint
case 168: // tableconstraint
value.move< sqlb::ConstraintPtr > (std::move (that.value));
break;
case 159: // columnconstraint_list
case 169: // tableconstraint_list
case 170: // optional_tableconstraint_list
value.move< sqlb::ConstraintSet > (std::move (that.value));
@@ -1221,32 +1157,6 @@ namespace sqlb { namespace parser {
, location (l)
{}
#endif
#if 201103L <= YY_CPLUSPLUS
basic_symbol (typename Base::kind_type t, ColumnConstraintInfo&& v, location_type&& l)
: Base (t)
, value (std::move (v))
, location (std::move (l))
{}
#else
basic_symbol (typename Base::kind_type t, const ColumnConstraintInfo& v, const location_type& l)
: Base (t)
, value (v)
, location (l)
{}
#endif
#if 201103L <= YY_CPLUSPLUS
basic_symbol (typename Base::kind_type t, ColumnConstraintInfoVector&& v, location_type&& l)
: Base (t)
, value (std::move (v))
, location (std::move (l))
{}
#else
basic_symbol (typename Base::kind_type t, const ColumnConstraintInfoVector& v, const location_type& l)
: Base (t)
, value (v)
, location (l)
{}
#endif
#if 201103L <= YY_CPLUSPLUS
basic_symbol (typename Base::kind_type t, ColumndefData&& v, location_type&& l)
: Base (t)
@@ -1413,14 +1323,6 @@ namespace sqlb { namespace parser {
// Value type destructor.
switch (yykind)
{
case 158: // columnconstraint
value.template destroy< ColumnConstraintInfo > ();
break;
case 159: // columnconstraint_list
value.template destroy< ColumnConstraintInfoVector > ();
break;
case 160: // columndef
value.template destroy< ColumndefData > ();
break;
@@ -1433,10 +1335,12 @@ switch (yykind)
value.template destroy< bool > ();
break;
case 158: // columnconstraint
case 168: // tableconstraint
value.template destroy< sqlb::ConstraintPtr > ();
break;
case 159: // columnconstraint_list
case 169: // tableconstraint_list
case 170: // optional_tableconstraint_list
value.template destroy< sqlb::ConstraintSet > ();
@@ -3919,14 +3823,6 @@ switch (yykind)
{
switch (this->kind ())
{
case 158: // columnconstraint
value.copy< ColumnConstraintInfo > (YY_MOVE (that.value));
break;
case 159: // columnconstraint_list
value.copy< ColumnConstraintInfoVector > (YY_MOVE (that.value));
break;
case 160: // columndef
value.copy< ColumndefData > (YY_MOVE (that.value));
break;
@@ -3939,10 +3835,12 @@ switch (yykind)
value.copy< bool > (YY_MOVE (that.value));
break;
case 158: // columnconstraint
case 168: // tableconstraint
value.copy< sqlb::ConstraintPtr > (YY_MOVE (that.value));
break;
case 159: // columnconstraint_list
case 169: // tableconstraint_list
case 170: // optional_tableconstraint_list
value.copy< sqlb::ConstraintSet > (YY_MOVE (that.value));
@@ -4129,14 +4027,6 @@ switch (yykind)
super_type::move (s);
switch (this->kind ())
{
case 158: // columnconstraint
value.move< ColumnConstraintInfo > (YY_MOVE (s.value));
break;
case 159: // columnconstraint_list
value.move< ColumnConstraintInfoVector > (YY_MOVE (s.value));
break;
case 160: // columndef
value.move< ColumndefData > (YY_MOVE (s.value));
break;
@@ -4149,10 +4039,12 @@ switch (yykind)
value.move< bool > (YY_MOVE (s.value));
break;
case 158: // columnconstraint
case 168: // tableconstraint
value.move< sqlb::ConstraintPtr > (YY_MOVE (s.value));
break;
case 159: // columnconstraint_list
case 169: // tableconstraint_list
case 170: // optional_tableconstraint_list
value.move< sqlb::ConstraintSet > (YY_MOVE (s.value));
@@ -4373,7 +4265,7 @@ switch (yykind)
#line 10 "sqlite3_parser.yy"
} } // sqlb::parser
#line 4377 "sqlite3_parser.hpp"
#line 4269 "sqlite3_parser.hpp"
+92 -196
View File
@@ -17,62 +17,8 @@
namespace sqlb { namespace parser { class ParserDriver; } }
typedef void* yyscan_t;
// Unfortunately we do not store column constraints in a systematic manner yet.
// Instead there is a variable for most column constraints directly inside the
// sqlb::Field class. This means that when parsing a column constraint we cannot
// just build a column constraint object with all the information and insert that
// into the Field object. Instead, the information needs to be passed upwards in
// some other way. This is what these declarations are for. We need to be able
// to pass information to the Field object as well as to the Table object too
// because some column constraints need to be transformed into Table constraints
// with our current layout.
class ColumnConstraintInfo
{
public:
ColumnConstraintInfo() : is_table_constraint(false), fully_parsed(false) {}
~ColumnConstraintInfo() {}
ColumnConstraintInfo& operator=(const ColumnConstraintInfo& other)
{
type = other.type;
is_table_constraint = other.is_table_constraint;
fully_parsed = other.fully_parsed;
constraint = other.constraint;
text = other.text;
generated_constraint = other.generated_constraint;
return *this;
}
ColumnConstraintInfo(const ColumnConstraintInfo& other)
{
*this = other;
}
enum ConstraintType
{
None,
AutoIncrement,
PrimaryKey,
NotNull,
Unique,
Check,
Default,
Collate,
ForeignKey,
Generated,
};
ConstraintType type;
bool is_table_constraint;
bool fully_parsed;
sqlb::ConstraintPtr constraint;
std::string text;
sqlb::GeneratedColumnConstraint generated_constraint;
};
using ColumnConstraintInfoVector = std::vector<ColumnConstraintInfo>;
// Colum definitions are a tuple of three elements: the Field object, a set of table constraints, and a bool to indicate whether parsing was complete
using ColumndefData = std::tuple<sqlb::Field, sqlb::ConstraintSet, bool>;
// 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>;
}
// The parsing context
@@ -268,8 +214,8 @@
%type <std::string> optional_typename
%type <std::string> optional_storage_identifier
%type <bool> optional_always_generated
%type <ColumnConstraintInfoVector> columnconstraint_list
%type <ColumnConstraintInfo> columnconstraint
%type <sqlb::ConstraintSet> columnconstraint_list
%type <sqlb::ConstraintPtr> columnconstraint
%type <ColumndefData> columndef
%type <std::vector<ColumndefData>> columndef_list
%type <sqlb::StringVector> columnid_list
@@ -616,7 +562,7 @@ indexed_column_list:
createindex_stmt:
CREATE optional_unique INDEX optional_if_not_exists tableid_with_uninteresting_schema ON tableid "(" indexed_column_list ")" optional_where {
$$ = sqlb::IndexPtr(new sqlb::Index($5));
$$ = std::make_shared<sqlb::Index>($5);
$$->setTable($7);
$$->setUnique($2);
$$->setWhereExpr($11);
@@ -637,7 +583,7 @@ optional_exprlist_with_paren:
createvirtualtable_stmt:
CREATE VIRTUAL TABLE optional_if_not_exists tableid_with_uninteresting_schema USING id optional_exprlist_with_paren {
$$ = sqlb::TablePtr(new sqlb::Table($5));
$$ = std::make_shared<sqlb::Table>($5);
$$->setVirtualUsing($7);
$$->setFullyParsed(false);
}
@@ -685,192 +631,145 @@ optional_always_generated:
columnconstraint:
optional_constraintname PRIMARY KEY optional_sort_order optional_conflictclause {
$$.type = ColumnConstraintInfo::PrimaryKey;
$$.is_table_constraint = true;
sqlb::PrimaryKeyConstraint* pk = new sqlb::PrimaryKeyConstraint({sqlb::IndexedColumn("", false, $4)});
auto pk = std::make_shared<sqlb::PrimaryKeyConstraint>(sqlb::IndexedColumnVector{sqlb::IndexedColumn("", false, $4)});
pk->setName($1);
pk->setConflictAction($5);
$$.constraint = sqlb::ConstraintPtr(pk);
$$.fully_parsed = true;
$$ = pk;
}
| optional_constraintname PRIMARY KEY optional_sort_order optional_conflictclause AUTOINCREMENT {
$$.type = ColumnConstraintInfo::PrimaryKey;
$$.is_table_constraint = true;
sqlb::PrimaryKeyConstraint* pk = new sqlb::PrimaryKeyConstraint({sqlb::IndexedColumn("", false, $4)});
auto pk = std::make_shared<sqlb::PrimaryKeyConstraint>(sqlb::IndexedColumnVector{sqlb::IndexedColumn("", false, $4)});
pk->setName($1);
pk->setConflictAction($5);
pk->setAutoIncrement(true);
$$.constraint = sqlb::ConstraintPtr(pk);
$$.fully_parsed = true;
$$ = pk;
}
| optional_constraintname NOT NULL optional_conflictclause {
$$.type = ColumnConstraintInfo::NotNull;
$$.is_table_constraint = false;
sqlb::NotNullConstraint* nn = new sqlb::NotNullConstraint();
auto nn = std::make_shared<sqlb::NotNullConstraint>();
nn->setName($1);
nn->setConflictAction($4);
$$.constraint = sqlb::ConstraintPtr(nn);
$$.fully_parsed = true;
$$ = nn;
}
| optional_constraintname NULL {
$$.type = ColumnConstraintInfo::None;
$$.is_table_constraint = false;
$$.fully_parsed = true;
}
| optional_constraintname UNIQUE optional_conflictclause {
$$.type = ColumnConstraintInfo::Unique;
$$.is_table_constraint = false;
sqlb::UniqueConstraint* u = new sqlb::UniqueConstraint();
auto u = std::make_shared<sqlb::UniqueConstraint>();
u->setName($1);
u->setConflictAction($3);
$$.constraint = sqlb::ConstraintPtr(u);
$$.fully_parsed = true;
$$ = u;
}
| optional_constraintname CHECK "(" expr ")" {
$$.type = ColumnConstraintInfo::Check;
$$.is_table_constraint = false;
auto c = std::make_shared<sqlb::CheckConstraint>($4);
c->setName($1);
$$.constraint = c;
$$.fully_parsed = true;
$$ = std::make_shared<sqlb::CheckConstraint>($4);
$$->setName($1);
}
| optional_constraintname DEFAULT signednumber {
$$.type = ColumnConstraintInfo::Default;
$$.is_table_constraint = false;
auto d = std::make_shared<sqlb::DefaultConstraint>($3);
d->setName($1);
$$.constraint = d;
$$.fully_parsed = true;
$$ = std::make_shared<sqlb::DefaultConstraint>($3);
$$->setName($1);
}
| optional_constraintname DEFAULT literalvalue {
$$.type = ColumnConstraintInfo::Default;
$$.is_table_constraint = false;
auto d = std::make_shared<sqlb::DefaultConstraint>($3);
d->setName($1);
$$.constraint = d;
$$.fully_parsed = true;
$$ = std::make_shared<sqlb::DefaultConstraint>($3);
$$->setName($1);
}
| optional_constraintname DEFAULT id {
$$.type = ColumnConstraintInfo::Default;
$$.is_table_constraint = false;
auto d = std::make_shared<sqlb::DefaultConstraint>($3);
d->setName($1);
$$.constraint = d;
$$.fully_parsed = true;
$$ = std::make_shared<sqlb::DefaultConstraint>($3);
$$->setName($1);
}
| optional_constraintname DEFAULT allowed_keywords_as_identifier { // We must allow the same keywords as unquoted default values as in the columnid context.
// But we do not use columnid here in order to avoid reduce/reduce conflicts.
$$.type = ColumnConstraintInfo::Default;
$$.is_table_constraint = false;
auto d = std::make_shared<sqlb::DefaultConstraint>($3);
d->setName($1);
$$.constraint = d;
$$.fully_parsed = true;
$$ = std::make_shared<sqlb::DefaultConstraint>($3);
$$->setName($1);
}
| optional_constraintname DEFAULT IF { // Same as above.
$$.type = ColumnConstraintInfo::Default;
$$.is_table_constraint = false;
auto d = std::make_shared<sqlb::DefaultConstraint>($3);
d->setName($1);
$$.constraint = d;
$$.fully_parsed = true;
$$ = std::make_shared<sqlb::DefaultConstraint>($3);
$$->setName($1);
}
| optional_constraintname DEFAULT "(" expr ")" {
$$.type = ColumnConstraintInfo::Default;
$$.is_table_constraint = false;
auto d = std::make_shared<sqlb::DefaultConstraint>("(" + $4 + ")");
d->setName($1);
$$.constraint = d;
$$.fully_parsed = true;
$$ = std::make_shared<sqlb::DefaultConstraint>("(" + $4 + ")");
$$->setName($1);
}
| optional_constraintname COLLATE id {
$$.type = ColumnConstraintInfo::Collate;
$$.is_table_constraint = false;
auto c = std::make_shared<sqlb::CollateConstraint>($3);
c->setName($1);
$$.constraint = c;
$$.fully_parsed = true;
$$ = std::make_shared<sqlb::CollateConstraint>($3);
$$->setName($1);
}
| optional_constraintname REFERENCES tableid optional_columnid_with_paren_list optional_fk_clause { // TODO Solve shift/reduce conflict. It is not super important though as shifting seems to be right here.
$$.type = ColumnConstraintInfo::ForeignKey;
$$.is_table_constraint = true;
sqlb::ForeignKeyClause* fk = new sqlb::ForeignKeyClause();
auto fk = std::make_shared<sqlb::ForeignKeyClause>();
fk->setName($1);
fk->setTable($3);
fk->setColumns($4);
fk->setConstraint($5);
$$.constraint = sqlb::ConstraintPtr(fk);
$$.fully_parsed = true;
$$ = fk;
}
| optional_constraintname optional_always_generated AS "(" expr ")" optional_storage_identifier { // TODO Solve shift/reduce conflict.
$$.type = ColumnConstraintInfo::Generated;
$$.is_table_constraint = false;
$$.generated_constraint.setExpression($5);
$$.generated_constraint.setStorage($7);
$$.generated_constraint.setName($1);
$$.fully_parsed = true;
$$ = std::make_shared<sqlb::GeneratedColumnConstraint>($5, $7);
$$->setName($1);
}
;
columnconstraint_list:
columnconstraint { $$ = { $1 }; }
| columnconstraint_list columnconstraint { $$ = $1; $$.push_back($2); }
| columnconstraint_list columnconstraint { $$ = $1; $$.insert($2); }
;
columndef:
columnid optional_typename columnconstraint_list {
sqlb::Field f($1, $2);
bool fully_parsed = true;
sqlb::ConstraintSet table_constraints{};
for(auto c : $3)
for(const auto& c : $3)
{
if(c.fully_parsed == false)
fully_parsed = false;
if(c.type == ColumnConstraintInfo::None)
if(!c)
continue;
if(c.is_table_constraint)
switch(c->type())
{
if(c.constraint->columnList().empty())
c.constraint->setColumnList({$1});
case sqlb::Constraint::PrimaryKeyConstraintType:
case sqlb::Constraint::ForeignKeyConstraintType:
{
// Primary key and foreign key constraints are converted to table constraints
// because we cannot store them as column constraints at the moment.
if(c->columnList().empty())
c->setColumnList({$1});
else
c.constraint->replaceInColumnList("", $1);
table_constraints.insert(c.constraint);
} else {
if(c.type == ColumnConstraintInfo::NotNull) {
f.setNotNull(std::dynamic_pointer_cast<sqlb::NotNullConstraint>(c.constraint));
} else if(c.type == ColumnConstraintInfo::Unique) {
f.setUnique(std::dynamic_pointer_cast<sqlb::UniqueConstraint>(c.constraint));
} else if(c.type == ColumnConstraintInfo::Check) {
f.setCheck(std::dynamic_pointer_cast<sqlb::CheckConstraint>(c.constraint));
} else if(c.type == ColumnConstraintInfo::Default) {
f.setDefaultValue(std::dynamic_pointer_cast<sqlb::DefaultConstraint>(c.constraint));
} else if(c.type == ColumnConstraintInfo::Collate) {
f.setCollation(std::dynamic_pointer_cast<sqlb::CollateConstraint>(c.constraint));
} else if(c.type == ColumnConstraintInfo::Generated) {
f.setGenerated(c.generated_constraint);
c->replaceInColumnList("", $1);
table_constraints.insert(c);
break;
}
case sqlb::Constraint::NotNullConstraintType:
f.setNotNull(std::dynamic_pointer_cast<sqlb::NotNullConstraint>(c));
break;
case sqlb::Constraint::UniqueConstraintType:
f.setUnique(std::dynamic_pointer_cast<sqlb::UniqueConstraint>(c));
break;
case sqlb::Constraint::CheckConstraintType:
f.setCheck(std::dynamic_pointer_cast<sqlb::CheckConstraint>(c));
break;
case sqlb::Constraint::DefaultConstraintType:
f.setDefaultValue(std::dynamic_pointer_cast<sqlb::DefaultConstraint>(c));
break;
case sqlb::Constraint::CollateConstraintType:
f.setCollation(std::dynamic_pointer_cast<sqlb::CollateConstraint>(c));
break;
case sqlb::Constraint::GeneratedColumnConstraintType:
{
f.setGenerated(std::dynamic_pointer_cast<sqlb::GeneratedColumnConstraint>(c));
// This is a hack which removes any "GENERATED ALWAYS" from the end of the type name.
// As of now these are shifted to the type instead of reducing the type when seeing the GENERATED identifier.
// TODO Remove this once the grammar is conflict free
const std::string generated_always = "GENERATED ALWAYS";
if(f.type().size() >= generated_always.size() && f.type().compare(f.type().size() - generated_always.size(), generated_always.size(), generated_always) == 0)
{
std::string type = f.type().substr(0, f.type().size()-generated_always.size());
if(type.back() == ' ')
type.pop_back();
f.setType(type);
}
} else {
fully_parsed = false;
// This is a hack which removes any "GENERATED ALWAYS" from the end of the type name.
// As of now these are shifted to the type instead of reducing the type when seeing the GENERATED identifier.
// TODO Remove this once the grammar is conflict free
const std::string generated_always = "GENERATED ALWAYS";
if(f.type().size() >= generated_always.size() && f.type().compare(f.type().size() - generated_always.size(), generated_always.size(), generated_always) == 0)
{
std::string type = f.type().substr(0, f.type().size()-generated_always.size());
if(type.back() == ' ')
type.pop_back();
f.setType(type);
}
break;
}
}
}
$$ = std::make_tuple(f, table_constraints, fully_parsed);
$$ = std::make_tuple(f, table_constraints);
}
| columnid optional_typename { $$ = std::make_tuple(sqlb::Field($1, $2), sqlb::ConstraintSet{}, true); }
| columnid optional_typename { $$ = std::make_tuple(sqlb::Field($1, $2), sqlb::ConstraintSet{}); }
;
columndef_list:
@@ -936,30 +835,30 @@ optional_fk_clause:
tableconstraint:
optional_constraintname PRIMARY KEY "(" indexed_column_list ")" optional_conflictclause {
sqlb::PrimaryKeyConstraint* pk = new sqlb::PrimaryKeyConstraint($5);
auto pk = std::make_shared<sqlb::PrimaryKeyConstraint>($5);
pk->setName($1);
pk->setConflictAction($7);
$$ = sqlb::ConstraintPtr(pk);
$$ = pk;
}
| optional_constraintname PRIMARY KEY "(" indexed_column_list AUTOINCREMENT ")" optional_conflictclause {
sqlb::PrimaryKeyConstraint* pk = new sqlb::PrimaryKeyConstraint($5);
auto pk = std::make_shared<sqlb::PrimaryKeyConstraint>($5);
pk->setName($1);
pk->setConflictAction($8);
pk->setAutoIncrement(true);
$$ = sqlb::ConstraintPtr(pk);
$$ = pk;
}
| optional_constraintname UNIQUE "(" indexed_column_list ")" optional_conflictclause {
sqlb::UniqueConstraint* u = new sqlb::UniqueConstraint($4);
auto u = std::make_shared<sqlb::UniqueConstraint>($4);
u->setName($1);
u->setConflictAction($6);
$$ = sqlb::ConstraintPtr(u);
$$ = u;
}
| optional_constraintname CHECK "(" expr ")" {
$$ = sqlb::ConstraintPtr(new sqlb::CheckConstraint($4));
$$ = std::make_shared<sqlb::CheckConstraint>($4);
$$->setName($1);
}
| optional_constraintname FOREIGN KEY "(" columnid_list ")" REFERENCES tableid optional_columnid_with_paren_list optional_fk_clause {
$$ = sqlb::ConstraintPtr(new sqlb::ForeignKeyClause($8, $9, $10));
$$ = std::make_shared<sqlb::ForeignKeyClause>($8, $9, $10);
$$->setColumnList($5);
$$->setName($1);
}
@@ -978,11 +877,11 @@ optional_tableconstraint_list:
createtable_stmt:
CREATE optional_temporary TABLE optional_if_not_exists tableid_with_uninteresting_schema AS select_stmt {
$$ = sqlb::TablePtr(new sqlb::Table($5));
$$ = std::make_shared<sqlb::Table>($5);
$$->setFullyParsed(false);
}
| CREATE optional_temporary TABLE optional_if_not_exists tableid_with_uninteresting_schema "(" columndef_list optional_tableconstraint_list ")" optional_withoutrowid {
$$ = sqlb::TablePtr(new sqlb::Table($5));
$$ = std::make_shared<sqlb::Table>($5);
$$->setWithoutRowidTable($10);
$$->setConstraints($8);
$$->setFullyParsed(true);
@@ -991,11 +890,8 @@ createtable_stmt:
{
sqlb::Field f;
sqlb::ConstraintSet c;
bool fully_parsed;
std::tie(f, c, fully_parsed) = column;
std::tie(f, c) = column;
if(fully_parsed == false)
$$->setFullyParsed(false);
$$->fields.push_back(f);
for(const auto& i : c)
$$->addConstraint(i);
+2 -2
View File
@@ -306,8 +306,8 @@ std::string Field::toString(const std::string& indent, const std::string& sep) c
str += " " + m_unique->toSql();
if(m_collation)
str += " " + m_collation->toSql();
if(!m_generated.empty())
str += " " + m_generated.toSql();
if(m_generated)
str += " " + m_generated->toSql();
return str;
}
+4 -6
View File
@@ -344,8 +344,6 @@ public:
{
}
bool empty() const { return m_expression.empty(); }
void setExpression(const std::string& expr) { m_expression = expr; }
const std::string& expression() const { return m_expression; }
@@ -425,9 +423,9 @@ public:
bool unique() const { return m_unique ? true : false; }
std::string collation() const { return m_collation ? m_collation->collation() : std::string{}; }
const GeneratedColumnConstraint& generated() const { return m_generated; }
GeneratedColumnConstraint& generated() { return m_generated; }
void setGenerated(const GeneratedColumnConstraint& gen) { m_generated = gen; }
const std::shared_ptr<GeneratedColumnConstraint> generated() const { return m_generated; }
std::shared_ptr<GeneratedColumnConstraint> generated() { return m_generated; }
void setGenerated(std::shared_ptr<GeneratedColumnConstraint> gen) { m_generated = gen; }
private:
std::string m_name;
@@ -437,7 +435,7 @@ private:
std::shared_ptr<DefaultConstraint> m_defaultvalue;
std::shared_ptr<UniqueConstraint> m_unique;
std::shared_ptr<CollateConstraint> m_collation;
GeneratedColumnConstraint m_generated;
std::shared_ptr<GeneratedColumnConstraint> m_generated;
};
class Table : public Object
+1 -1
View File
@@ -1269,7 +1269,7 @@ std::string DBBrowserDB::emptyInsertStmt(const std::string& schemaName, const sq
for(const sqlb::Field& f : t.fields)
{
// Never insert into a generated column
if(!f.generated().empty())
if(f.generated())
continue;
sqlb::ConstraintPtr pk = t.constraint({f.name()}, sqlb::Constraint::PrimaryKeyConstraintType);
+1 -1
View File
@@ -981,7 +981,7 @@ bool SqliteTableModel::isEditable(const QModelIndex& index) const
if(index.isValid() && m_table_of_query)
{
const auto field = sqlb::findField(m_table_of_query, m_headers.at(static_cast<size_t>(index.column())));
if(field != m_table_of_query->fields.cend() && !field->generated().empty())
if(field != m_table_of_query->fields.cend() && field->generated())
return false;
}