grammar: Introduce basic View class stub

Parsing views or generating a CREATE VIEW statement isn't implemented
yet.

Also unify the process by which it's possible to retrieve information on
the fields of a database object.
This commit is contained in:
Martin Kleusberg
2017-01-23 17:06:41 +01:00
parent ebc3869627
commit d236f6df9f
5 changed files with 130 additions and 24 deletions

View File

@@ -195,15 +195,23 @@ void DbStructureModel::reloadData()
addNode(typeToParentItem.value("browsable"), *it);
// Add field nodes
sqlb::FieldVector pk = (*it).object.dynamicCast<sqlb::Table>()->primaryKey();
for(int i=0; i < (*it).object.dynamicCast<sqlb::Table>()->fields().size(); ++i)
QStringList pk_columns;
if(it->gettype() == sqlb::Object::Types::Table)
{
sqlb::FieldVector pk = it->object.dynamicCast<sqlb::Table>()->primaryKey();
foreach(sqlb::FieldPtr pk_col, pk)
pk_columns.push_back(pk_col->name());
}
sqlb::FieldInfoList fieldList = it->object->fieldInformation();
foreach(const sqlb::FieldInfo& field, fieldList)
{
QTreeWidgetItem *fldItem = new QTreeWidgetItem(item);
fldItem->setText(0, (*it).object.dynamicCast<sqlb::Table>()->fields().at(i)->name());
fldItem->setText(0, field.name);
fldItem->setText(1, "field");
fldItem->setText(2, (*it).object.dynamicCast<sqlb::Table>()->fields().at(i)->type());
fldItem->setText(3, (*it).object.dynamicCast<sqlb::Table>()->fields().at(i)->toString(" ", " "));
if(pk.contains((*it).object.dynamicCast<sqlb::Table>()->fields().at(i)))
fldItem->setText(2, field.type);
fldItem->setText(3, field.sql);
if(pk_columns.contains(field.name))
fldItem->setIcon(0, QIcon(":/icons/field_key"));
else
fldItem->setIcon(0, QIcon(":/icons/field"));

View File

@@ -367,11 +367,9 @@ void MainWindow::populateStructure()
{
QString objectname = it.value().getname();
for(int i=0; i < (*it).object.dynamicCast<sqlb::Table>()->fields().size(); ++i)
{
QString fieldname = (*it).object.dynamicCast<sqlb::Table>()->fields().at(i)->name();
tablesToColumnsMap[objectname].append(fieldname);
}
sqlb::FieldInfoList fi = it->object->fieldInformation();
foreach(const sqlb::FieldInfo& f, fi)
tablesToColumnsMap[objectname].append(f.name);
}
SqlTextEdit::sqlLexer->setTableNames(tablesToColumnsMap);
ui->editLogApplication->reloadKeywords();

View File

@@ -1253,27 +1253,28 @@ void DBBrowserDB::updateSchema( )
continue;
DBBrowserObject obj(val_name, val_sql, type, val_tblname);
if((type == sqlb::Object::Types::Table || type == sqlb::Object::Types::Index) && !val_sql.isEmpty())
if((type == sqlb::Object::Types::Table || type == sqlb::Object::Types::Index || type == sqlb::Object::Types::View) && !val_sql.isEmpty())
{
obj.object = sqlb::Object::parseSQL(type, val_sql);
if(val_temp == "1")
obj.object->setTemporary(true);
// For virtual tables query the column list using the SQLite pragma
if(type == sqlb::Object::Types::Table && obj.object.dynamicCast<sqlb::Table>()->isVirtual())
// For virtual tables and views query the column list using the SQLite pragma because for both we can't yet rely on our grammar parser
if((type == sqlb::Object::Types::Table && obj.object.dynamicCast<sqlb::Table>()->isVirtual()) || type == sqlb::Object::Types::View)
{
sqlb::TablePtr tab = obj.object.dynamicCast<sqlb::Table>();
auto columns = queryColumnInformation(val_name);
foreach(const auto& column, columns)
tab->addField(sqlb::FieldPtr(new sqlb::Field(column.first, column.second)));
if(type == sqlb::Object::Types::Table)
{
sqlb::TablePtr tab = obj.object.dynamicCast<sqlb::Table>();
foreach(const auto& column, columns)
tab->addField(sqlb::FieldPtr(new sqlb::Field(column.first, column.second)));
} else {
sqlb::ViewPtr view = obj.object.dynamicCast<sqlb::View>();
foreach(const auto& column, columns)
view->addField(sqlb::FieldPtr(new sqlb::Field(column.first, column.second)));
}
}
} else if(type == sqlb::Object::Types::View) {
// For views we currently can't rely on our grammar parser to get the column list. Use the pragma offered by SQLite instead
auto columns = queryColumnInformation(val_name);
sqlb::Table* view_dummy = new sqlb::Table("");
foreach(const auto& column, columns)
view_dummy->addField(sqlb::FieldPtr(new sqlb::Field(column.first, column.second)));
obj.object = sqlb::TablePtr(view_dummy);
}
objMap.insert(val_type, obj);
}

View File

@@ -76,6 +76,9 @@ ObjectPtr Object::parseSQL(Object::Types type, const QString& sSQL)
case Object::Types::Index:
result = Index::parseSQL(sSQL);
break;
case Object::Types::View:
result = View::parseSQL(sSQL);
break;
default:
return ObjectPtr(nullptr);
}
@@ -310,6 +313,14 @@ QStringList Table::fieldNames() const
return sl;
}
FieldInfoList Table::fieldInformation() const
{
FieldInfoList result;
foreach(FieldPtr f, m_fields)
result.append({f->name(), f->type(), f->toString(" ", " ")});
return result;
}
bool Table::hasAutoIncrement() const
{
foreach(FieldPtr f, m_fields) {
@@ -1132,4 +1143,52 @@ void CreateIndexWalker::parsecolumn(Index* index, antlr::RefAST c)
index->addColumn(IndexedColumnPtr(new IndexedColumn(name, isExpression, order)));
}
View::~View()
{
clear();
}
ObjectPtr View::parseSQL(const QString& /*sSQL*/)
{
// TODO
return ViewPtr(new View(""));
}
void View::clear()
{
m_fields.clear();
}
void View::addField(const FieldPtr& f)
{
m_fields.append(FieldPtr(f));
}
void View::setFields(const FieldVector& fields)
{
clear();
m_fields = fields;
}
QStringList View::fieldNames() const
{
QStringList sl;
foreach(FieldPtr f, m_fields)
sl << f->name();
return sl;
}
FieldInfoList View::fieldInformation() const
{
FieldInfoList result;
foreach(FieldPtr f, m_fields)
result.append({f->name(), f->type(), f->toString(" ", " ")});
return result;
}
} //namespace sqlb

View File

@@ -15,21 +15,32 @@ QString escapeIdentifier(QString id);
class Object;
class Table;
class Index;
class View;
class Field;
class Constraint;
class IndexedColumn;
struct FieldInfo;
typedef QSharedPointer<Object> ObjectPtr;
typedef QSharedPointer<Table> TablePtr;
typedef QSharedPointer<Index> IndexPtr;
typedef QSharedPointer<View> ViewPtr;
typedef QSharedPointer<Field> FieldPtr;
typedef QSharedPointer<Constraint> ConstraintPtr;
typedef QVector<FieldPtr> FieldVector;
typedef QSharedPointer<IndexedColumn> IndexedColumnPtr;
typedef QVector<IndexedColumnPtr> IndexedColumnVector;
typedef QMultiHash<FieldVector, ConstraintPtr> ConstraintMap;
typedef QList<FieldInfo> FieldInfoList;
QStringList fieldVectorToFieldNames(const sqlb::FieldVector& vector);
struct FieldInfo
{
QString name;
QString type;
QString sql;
};
class Object
{
public:
@@ -60,6 +71,8 @@ public:
void setFullyParsed(bool fully_parsed) { m_fullyParsed = fully_parsed; }
bool fullyParsed() const { return m_fullyParsed; }
virtual FieldInfoList fieldInformation() const { return FieldInfoList(); }
virtual void clear() {}
/**
@@ -250,6 +263,8 @@ public:
void clear();
virtual FieldInfoList fieldInformation() const;
void addConstraint(FieldVector fields, ConstraintPtr constraint);
void setConstraint(FieldVector fields, ConstraintPtr constraint);
void removeConstraints(FieldVector fields = FieldVector(), Constraint::ConstraintTypes type = Constraint::NoType); //! Only removes the first constraint, if any
@@ -365,6 +380,31 @@ private:
IndexedColumnVector m_columns;
};
class View : public Object
{
public:
explicit View(const QString& name): Object(name) {}
virtual ~View();
virtual Types type() const { return Object::View; }
QString sql() const { /* TODO */ return m_originalSql; }
static ObjectPtr parseSQL(const QString& sSQL);
void clear();
void addField(const FieldPtr& f);
void setFields(const FieldVector& fields);
const FieldPtr& field(int index) const { return m_fields[index]; }
QStringList fieldNames() const;
virtual FieldInfoList fieldInformation() const;
private:
FieldVector m_fields;
};
} //namespace sqlb
#endif // SQLITETYPES_H