@@ -9,6 +9,41 @@ namespace sqlb { |
9 | 9 |
|
10 | 10 | QStringList Field::Datatypes = QStringList() << "INTEGER" << "TEXT" << "BLOB" << "REAL" << "NUMERIC"; |
11 | 11 |
|
| 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 | + |
12 | 47 | QString Field::toString(const QString& indent, const QString& sep) const |
13 | 48 | { |
14 | 49 | QString str = indent + '`' + m_name + '`' + sep + m_type; |
@@ -194,8 +229,8 @@ QString Table::sql() const |
194 | 229 | // foreign keys |
195 | 230 | foreach(FieldPtr f, m_fields) |
196 | 231 | { |
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()); |
199 | 234 | } |
200 | 235 |
|
201 | 236 | sql += "\n)"; |
@@ -372,6 +407,8 @@ Table CreateTableWalker::table() |
372 | 407 | break; |
373 | 408 | case sqlite3TokenTypes::FOREIGN: |
374 | 409 | { |
| 410 | + sqlb::ForeignKeyClause fk; |
| 411 | + |
375 | 412 | tc = tc->getNextSibling(); // FOREIGN |
376 | 413 | tc = tc->getNextSibling(); // KEY |
377 | 414 | tc = tc->getNextSibling(); // LPAREN |
@@ -386,7 +423,28 @@ Table CreateTableWalker::table() |
386 | 423 | tc = tc->getNextSibling(); // RPAREN |
387 | 424 | tc = tc->getNextSibling(); // REFERENCES |
388 | 425 |
|
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); |
390 | 448 | } |
391 | 449 | break; |
392 | 450 | default: |
@@ -423,7 +481,7 @@ void CreateTableWalker::parsecolumn(FieldPtr& f, antlr::RefAST c) |
423 | 481 | bool unique = false; |
424 | 482 | QString defaultvalue; |
425 | 483 | QString check; |
426 | | - QString foreignKey; |
| 484 | + sqlb::ForeignKeyClause foreignKey; |
427 | 485 |
|
428 | 486 | colname = columnname(c); |
429 | 487 | c = c->getNextSibling(); //type? |
@@ -491,7 +549,27 @@ void CreateTableWalker::parsecolumn(FieldPtr& f, antlr::RefAST c) |
491 | 549 | case sqlite3TokenTypes::REFERENCES: |
492 | 550 | { |
493 | 551 | 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)); |
495 | 573 | } |
496 | 574 | break; |
497 | 575 | default: |
|