mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-05-24 22:48:23 -05:00
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:
+833
-913
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user