GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Parse foreign key clauses instead of just treating them as a big string · feiva/sqlitebrowser@0e18e36

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • src
    • EditTableDialog.cpp
    • sqlitetypes.cpp
    • sqlitetypes.h
    • tests
      • testsqlobjects.cpp
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/EditTableDialog.cpp‎

Copy file name to clipboardExpand all lines: src/EditTableDialog.cpp
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ void EditTableDialog::populateFields()
115115
tbitem->setText(kDefault, f->defaultValue());
116116

117117
tbitem->setText(kCheck, f->check());
118-
tbitem->setText(kForeignKey, f->foreignKey());
118+
tbitem->setText(kForeignKey, f->foreignKey().toString());
119119
ui->treeWidget->addTopLevelItem(tbitem);
120120
}
121121

@@ -374,7 +374,9 @@ void EditTableDialog::itemChanged(QTreeWidgetItem *item, int column)
374374
callRenameColumn = true;
375375
break;
376376
case kForeignKey:
377-
field->setForeignKey(item->text(column));
377+
sqlb::ForeignKeyClause fk;
378+
fk.setFromString(item->text(column));
379+
field->setForeignKey(fk);
378380
if(!m_bNewTable)
379381
callRenameColumn = true;
380382
break;
Collapse file

‎src/sqlitetypes.cpp‎

Copy file name to clipboardExpand all lines: src/sqlitetypes.cpp
+83-5Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,41 @@ namespace sqlb {
99

1010
QStringList Field::Datatypes = QStringList() << "INTEGER" << "TEXT" << "BLOB" << "REAL" << "NUMERIC";
1111

12+
bool ForeignKeyClause::isSet() const
13+
{
14+
return m_override.size() || m_table.size();
15+
}
16+
17+
QString ForeignKeyClause::toString() const
18+
{
19+
if(!isSet())
20+
return QString();
21+
22+
if(m_override.size())
23+
return m_override;
24+
25+
QString result = "`" + m_table + "`";
26+
27+
if(m_columns.size())
28+
{
29+
result += "(";
30+
foreach(const QString& column, m_columns)
31+
result += "`" + column + "`,";
32+
result.chop(1); // Remove last comma
33+
result += ")";
34+
}
35+
36+
if(m_constraint.size())
37+
result += " " + m_constraint;
38+
39+
return result;
40+
}
41+
42+
void ForeignKeyClause::setFromString(const QString& fk)
43+
{
44+
m_override = fk;
45+
}
46+
1247
QString Field::toString(const QString& indent, const QString& sep) const
1348
{
1449
QString str = indent + '`' + m_name + '`' + sep + m_type;
@@ -194,8 +229,8 @@ QString Table::sql() const
194229
// foreign keys
195230
foreach(FieldPtr f, m_fields)
196231
{
197-
if(!f->foreignKey().isEmpty())
198-
sql += QString(",\n\tFOREIGN KEY(`%1`) REFERENCES %2").arg(f->name()).arg(f->foreignKey());
232+
if(f->foreignKey().isSet())
233+
sql += QString(",\n\tFOREIGN KEY(`%1`) REFERENCES %2").arg(f->name()).arg(f->foreignKey().toString());
199234
}
200235

201236
sql += "\n)";
@@ -372,6 +407,8 @@ Table CreateTableWalker::table()
372407
break;
373408
case sqlite3TokenTypes::FOREIGN:
374409
{
410+
sqlb::ForeignKeyClause fk;
411+
375412
tc = tc->getNextSibling(); // FOREIGN
376413
tc = tc->getNextSibling(); // KEY
377414
tc = tc->getNextSibling(); // LPAREN
@@ -386,7 +423,28 @@ Table CreateTableWalker::table()
386423
tc = tc->getNextSibling(); // RPAREN
387424
tc = tc->getNextSibling(); // REFERENCES
388425

389-
tab.fields().at(tab.findField(column_name))->setForeignKey(concatTextAST(tc, true));
426+
fk.setTable(identifier(tc));
427+
tc = tc->getNextSibling(); // identifier
428+
429+
if(tc != antlr::nullAST && tc->getType() == sqlite3TokenTypes::LPAREN)
430+
{
431+
tc = tc->getNextSibling(); // LPAREN
432+
433+
QStringList fk_cols;
434+
while(tc != antlr::nullAST && tc->getType() != sqlite3TokenTypes::RPAREN)
435+
{
436+
if(tc->getType() != sqlite3TokenTypes::COMMA)
437+
fk_cols.push_back(identifier(tc));
438+
tc = tc->getNextSibling();
439+
}
440+
fk.setColumns(fk_cols);
441+
442+
tc = tc->getNextSibling(); // RPAREN
443+
}
444+
445+
fk.setConstraint(concatTextAST(tc, true));
446+
447+
tab.fields().at(tab.findField(column_name))->setForeignKey(fk);
390448
}
391449
break;
392450
default:
@@ -423,7 +481,7 @@ void CreateTableWalker::parsecolumn(FieldPtr& f, antlr::RefAST c)
423481
bool unique = false;
424482
QString defaultvalue;
425483
QString check;
426-
QString foreignKey;
484+
sqlb::ForeignKeyClause foreignKey;
427485

428486
colname = columnname(c);
429487
c = c->getNextSibling(); //type?
@@ -491,7 +549,27 @@ void CreateTableWalker::parsecolumn(FieldPtr& f, antlr::RefAST c)
491549
case sqlite3TokenTypes::REFERENCES:
492550
{
493551
con = con->getNextSibling(); // REFERENCES
494-
foreignKey = concatTextAST(con, true);
552+
553+
foreignKey.setTable(identifier(con));
554+
con = con->getNextSibling(); // identifier
555+
556+
if(con != antlr::nullAST && con->getType() == sqlite3TokenTypes::LPAREN)
557+
{
558+
con = con->getNextSibling(); // LPAREN
559+
560+
QStringList fk_cols;
561+
while(con != antlr::nullAST && con->getType() != sqlite3TokenTypes::RPAREN)
562+
{
563+
if(con->getType() != sqlite3TokenTypes::COMMA)
564+
fk_cols.push_back(identifier(con));
565+
con = con->getNextSibling();
566+
}
567+
foreignKey.setColumns(fk_cols);
568+
569+
con = con->getNextSibling(); // RPAREN
570+
}
571+
572+
foreignKey.setConstraint(concatTextAST(con, true));
495573
}
496574
break;
497575
default:
Collapse file

‎src/sqlitetypes.h‎

Copy file name to clipboardExpand all lines: src/sqlitetypes.h
+35-3Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,38 @@
1212

1313
namespace sqlb {
1414

15+
class ForeignKeyClause
16+
{
17+
public:
18+
ForeignKeyClause(const QString& table = QString(), const QStringList& columns = QStringList(), const QString& constraint = QString())
19+
: m_table(table),
20+
m_columns(columns),
21+
m_constraint(constraint),
22+
m_override(QString())
23+
{
24+
}
25+
26+
bool isSet() const;
27+
QString toString() const;
28+
void setFromString(const QString& fk);
29+
30+
void setTable(const QString& table) { m_override = QString(); m_table = table; }
31+
const QString& table() const { return m_table; }
32+
33+
void setColumns(const QStringList& columns) { m_columns = columns; }
34+
const QStringList& columns() const { return m_columns; }
35+
36+
void setConstraint(const QString& constraint) { m_constraint = constraint; }
37+
const QString& constraint() const { return m_constraint; }
38+
39+
private:
40+
QString m_table;
41+
QStringList m_columns;
42+
QString m_constraint;
43+
44+
QString m_override;
45+
};
46+
1547
class Field
1648
{
1749
public:
@@ -42,7 +74,7 @@ class Field
4274
void setAutoIncrement(bool autoinc) { m_autoincrement = autoinc; }
4375
void setPrimaryKey(bool pk) { m_primaryKey = pk; }
4476
void setUnique(bool u) { m_unique = u; }
45-
void setForeignKey(const QString& key) { m_foreignKey = key; }
77+
void setForeignKey(const ForeignKeyClause& key) { m_foreignKey = key; }
4678

4779
bool isText() const;
4880
bool isInteger() const;
@@ -55,7 +87,7 @@ class Field
5587
bool autoIncrement() const { return m_autoincrement; }
5688
bool primaryKey() const { return m_primaryKey; }
5789
bool unique() const { return m_unique; }
58-
const QString& foreignKey() const { return m_foreignKey; }
90+
const ForeignKeyClause& foreignKey() const { return m_foreignKey; }
5991

6092
static QStringList Datatypes;
6193
private:
@@ -64,7 +96,7 @@ class Field
6496
bool m_notnull;
6597
QString m_check;
6698
QString m_defaultvalue;
67-
QString m_foreignKey; // Even though this information is a table constraint easier for accessing and processing to store it here
99+
ForeignKeyClause m_foreignKey; // Even though this information is a table constraint it's easier for accessing and processing to store it here
68100
bool m_autoincrement; //! this is stored here for simplification
69101
bool m_primaryKey;
70102
bool m_unique;
Collapse file

‎src/tests/testsqlobjects.cpp‎

Copy file name to clipboardExpand all lines: src/tests/testsqlobjects.cpp
+5-5Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,12 @@ void TestTable::foreignKeys()
8282
{
8383
Table tt("testtable");
8484
FieldPtr f = FieldPtr(new Field("a", "integer"));
85-
f->setForeignKey("b(c)");
85+
f->setForeignKey(sqlb::ForeignKeyClause("b", QStringList("c")));
8686
tt.addField(f);
8787

8888
QCOMPARE(tt.sql(), QString("CREATE TABLE `testtable` (\n"
8989
"\t`a`\tinteger,\n"
90-
"\tFOREIGN KEY(`a`) REFERENCES b(c)\n"
90+
"\tFOREIGN KEY(`a`) REFERENCES `b`(`c`)\n"
9191
");"));
9292
}
9393

@@ -241,17 +241,17 @@ void TestTable::parseSQLEscapedQuotes()
241241

242242
void TestTable::parseSQLForeignKeys()
243243
{
244-
QString sql = "CREATE TABLE foreign_key_test(a int, b int, foreign key (a) references x, foreign key (b) references w(z) on delete set null);";
244+
QString sql = "CREATE TABLE foreign_key_test(a int, b int, foreign key (a) references x, foreign key (b) references w(y,z) on delete set null);";
245245

246246
Table tab = Table::parseSQL(sql).first;
247247

248248
QCOMPARE(tab.name(), QString("foreign_key_test"));
249249
QCOMPARE(tab.fields().at(0)->name(), QString("a"));
250250
QCOMPARE(tab.fields().at(0)->type(), QString("int"));
251-
QCOMPARE(tab.fields().at(0)->foreignKey(), QString("x"));
251+
QCOMPARE(tab.fields().at(0)->foreignKey().table(), QString("x"));
252252
QCOMPARE(tab.fields().at(1)->name(), QString("b"));
253253
QCOMPARE(tab.fields().at(1)->type(), QString("int"));
254-
QCOMPARE(tab.fields().at(1)->foreignKey(), QString("w ( z ) on delete set null"));
254+
QCOMPARE(tab.fields().at(1)->foreignKey().toString(), QString("`w`(`y`,`z`) on delete set null"));
255255
}
256256

257257
void TestTable::parseSQLCheckConstraint()

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.