Added page with the types (no details yet)
This commit is contained in:
parent
bdef76ed8a
commit
4c175d8c2c
16 changed files with 418 additions and 11 deletions
|
|
@ -22,7 +22,7 @@ QVariant BaseTableModel::data(const QModelIndex &index, int role) const
|
|||
return v;
|
||||
}
|
||||
|
||||
QVariant BaseTableModel::getDataMeaning(const QModelIndex &index) const
|
||||
QVariant BaseTableModel::getDataMeaning(const QModelIndex &) const
|
||||
{
|
||||
return static_cast<int>(DataMeaningNormal);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "widgets/CatalogNamespacePage.h"
|
||||
#include "widgets/CatalogSequencesPage.h"
|
||||
#include "widgets/CatalogTablesPage.h"
|
||||
#include "widgets/CatalogTypesPage.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTabWidget>
|
||||
|
|
@ -20,6 +21,7 @@ CatalogInspector::CatalogInspector(std::shared_ptr<OpenDatabase> open_database,
|
|||
m_tablesPage = new CatalogTablesPage(this);
|
||||
m_functionsPage = new CatalogFunctionsPage(this);
|
||||
m_sequencesPage = new CatalogSequencesPage(this);
|
||||
m_typesPage = new CatalogTypesPage(this);
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
setLayout(layout);
|
||||
|
|
@ -28,6 +30,7 @@ CatalogInspector::CatalogInspector(std::shared_ptr<OpenDatabase> open_database,
|
|||
m_tabWidget->addTab(m_tablesPage, "");
|
||||
m_tabWidget->addTab(m_functionsPage, "");
|
||||
m_tabWidget->addTab(m_sequencesPage, "");
|
||||
m_tabWidget->addTab(m_typesPage, "");
|
||||
|
||||
setCatalog(open_database->catalog());
|
||||
retranslateUi(false);
|
||||
|
|
@ -45,6 +48,8 @@ void CatalogInspector::retranslateUi(bool all)
|
|||
QApplication::translate("CatalogInspector", "Functions", nullptr));
|
||||
m_tabWidget->setTabText(m_tabWidget->indexOf(m_sequencesPage),
|
||||
QApplication::translate("CatalogInspector", "Sequences", nullptr));
|
||||
m_tabWidget->setTabText(m_tabWidget->indexOf(m_typesPage),
|
||||
QApplication::translate("CatalogInspector", "Types", nullptr));
|
||||
}
|
||||
|
||||
CatalogInspector::~CatalogInspector()
|
||||
|
|
@ -58,6 +63,7 @@ void CatalogInspector::setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
|
|||
m_tablesPage->setCatalog(cat);
|
||||
m_functionsPage->setCatalog(cat);
|
||||
m_sequencesPage->setCatalog(cat);
|
||||
m_typesPage->setCatalog(cat);
|
||||
}
|
||||
|
||||
void CatalogInspector::setNamespaceFilter(NamespaceFilter filter)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ class CatalogFunctionsPage;
|
|||
class CatalogSequencesPage;
|
||||
class CatalogTablesPage;
|
||||
class CatalogNamespacePage;
|
||||
class CatalogTypesPage;
|
||||
class OpenDatabase;
|
||||
class PgDatabaseCatalog;
|
||||
class QTabWidget;
|
||||
|
|
@ -29,6 +30,7 @@ private:
|
|||
CatalogTablesPage *m_tablesPage = nullptr;
|
||||
CatalogFunctionsPage *m_functionsPage = nullptr;
|
||||
CatalogSequencesPage *m_sequencesPage = nullptr;
|
||||
CatalogTypesPage *m_typesPage = nullptr;
|
||||
std::shared_ptr<PgDatabaseCatalog> m_catalog;
|
||||
|
||||
void retranslateUi(bool all = true);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ ColumnPage::ColumnPage(QWidget *parent)
|
|||
m_tableView->setItemDelegateForColumn(ColumnTableModel::TypeCol, new QStyledItemDelegate(this));
|
||||
m_tableView->setModel(m_sortFilterProxy);
|
||||
m_tableView->setSortingEnabled(true);
|
||||
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
// m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_sortFilterProxy->sort(ColumnTableModel::AttnumCol, Qt::AscendingOrder);
|
||||
|
||||
connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ void PropertyProxyModel::setActiveRow(const QModelIndex &row)
|
|||
QVector<int>() << Qt::DisplayRole);
|
||||
}
|
||||
|
||||
Qt::ItemFlags PropertyProxyModel::flags(const QModelIndex &index) const
|
||||
Qt::ItemFlags PropertyProxyModel::flags(const QModelIndex &) const
|
||||
{
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,7 +141,6 @@ QVariant RolesTableModel::getData(const QModelIndex &index) const
|
|||
v = authid.bypassRls;
|
||||
break;
|
||||
case ConnlimitCol:
|
||||
// todo lookup tablespace name
|
||||
v = authid.connLimit;
|
||||
break;
|
||||
case ValidUntilCol:
|
||||
|
|
|
|||
101
pglab/TypeModel.cpp
Normal file
101
pglab/TypeModel.cpp
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#include "TypeModel.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgNamespace.h"
|
||||
#include "catalog/PgTypeContainer.h"
|
||||
|
||||
TypeModel::TypeModel(QObject * parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant TypeModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (section) {
|
||||
case NameCol: return tr("Name");
|
||||
case SchemaCol: return tr("Schema");
|
||||
case OwnerCol: return tr("Owner");
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void TypeModel::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
|
||||
{
|
||||
if (cat != m_catalog) {
|
||||
m_catalog = cat;
|
||||
refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed,
|
||||
this, &TypeModel::refresh);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
//void TypeModel::setNamespaceFilter(NamespaceFilter filter)
|
||||
//{
|
||||
// m_namespaceFilter = filter;
|
||||
// refresh();
|
||||
//}
|
||||
|
||||
void TypeModel::refresh()
|
||||
{
|
||||
if (!m_catalog)
|
||||
return;
|
||||
|
||||
beginResetModel();
|
||||
|
||||
auto && typs = m_catalog->types();
|
||||
m_types.clear();
|
||||
for (auto&& s : *typs) {
|
||||
// bool add = false;
|
||||
// switch (m_namespaceFilter) {
|
||||
// case NamespaceFilter::User:
|
||||
// add = !s.ns().isSystemCatalog();
|
||||
// break;
|
||||
// case NamespaceFilter::PgCatalog:
|
||||
// add = s.ns().objectName() == "pg_catalog";
|
||||
// break;
|
||||
// case NamespaceFilter::InformationSchema:
|
||||
// add = s.ns().objectName() == "information_schema";
|
||||
// break;
|
||||
// }
|
||||
// if (add)
|
||||
m_types.push_back(s);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
PgType TypeModel::typ(int row) const
|
||||
{
|
||||
return m_types.at(static_cast<size_t>(row));
|
||||
}
|
||||
|
||||
int TypeModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return static_cast<int>(m_types.size());
|
||||
}
|
||||
|
||||
int TypeModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return colCount;
|
||||
}
|
||||
|
||||
QVariant TypeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (m_types.empty())
|
||||
return {};
|
||||
|
||||
int row = index.row();
|
||||
auto && seq = m_types.at(static_cast<size_t>(row));
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (index.column()) {
|
||||
case NameCol: return seq.objectName();
|
||||
case SchemaCol: return seq.nsName();
|
||||
case OwnerCol: return seq.ownerName();
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
40
pglab/TypeModel.h
Normal file
40
pglab/TypeModel.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef TYPEMODEL_H
|
||||
#define TYPEMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include "catalog/PgType.h"
|
||||
|
||||
class TypeModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum e_Columns : int {
|
||||
NameCol,
|
||||
SchemaCol,
|
||||
OwnerCol,
|
||||
|
||||
colCount
|
||||
};
|
||||
|
||||
TypeModel(QObject * parent = nullptr);
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
void setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||
//void setNamespaceFilter(NamespaceFilter filter);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
PgType typ(int row) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||
std::vector<PgType> m_types;
|
||||
//NamespaceFilter m_namespaceFilter = NamespaceFilter::User;
|
||||
QMetaObject::Connection refreshConnection;
|
||||
|
||||
void refresh();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -87,7 +87,8 @@ PropertyProxyModel.cpp \
|
|||
widgets/CatalogConstraintPage.cpp \
|
||||
widgets/CatalogTablesPage.cpp \
|
||||
widgets/CatalogFunctionsPage.cpp \
|
||||
widgets/CatalogSequencesPage.cpp
|
||||
widgets/CatalogSequencesPage.cpp \
|
||||
widgets/CatalogTypesPage.cpp
|
||||
|
||||
HEADERS += \
|
||||
ConnectionConfigurationWidget.h \
|
||||
|
|
@ -160,7 +161,8 @@ CustomDataRole.h \
|
|||
widgets/CatalogTablesPage.h \
|
||||
widgets/CatalogFunctionsPage.h \
|
||||
widgets/CatalogSequencesPage.h \
|
||||
NamespaceFilter.h
|
||||
NamespaceFilter.h \
|
||||
widgets/CatalogTypesPage.h
|
||||
|
||||
FORMS += \
|
||||
ConnectionManagerWindow.ui \
|
||||
|
|
|
|||
78
pglab/widgets/CatalogTypesPage.cpp
Normal file
78
pglab/widgets/CatalogTypesPage.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#include "CatalogTypesPage.h"
|
||||
#include "ResultTableModelUtil.h"
|
||||
#include "CustomFilterSortModel.h"
|
||||
#include "CustomDataRole.h"
|
||||
#include "PgLabItemDelegate.h"
|
||||
#include "catalog/PgType.h"
|
||||
#include "model/TypeSelectionItemModel.h"
|
||||
#include "SqlCodePreview.h"
|
||||
#include "PgLabTableView.h"
|
||||
#include <optional>
|
||||
|
||||
CatalogTypesPage::CatalogTypesPage(QWidget *parent)
|
||||
: QSplitter(Qt::Horizontal, parent)
|
||||
{
|
||||
m_typeTable = new PgLabTableView(this);
|
||||
m_definitionView = new SqlCodePreview(this);
|
||||
|
||||
// build widget tree
|
||||
// add top level widgets to splitter
|
||||
addWidget(m_typeTable);
|
||||
addWidget(m_definitionView);
|
||||
|
||||
m_model = new TypeModel(this);
|
||||
m_sortFilterProxy = new CustomFilterSortModel(this);
|
||||
m_sortFilterProxy->setSourceModel(m_model);
|
||||
m_typeTable->setModel(m_sortFilterProxy);
|
||||
m_typeTable->setSortingEnabled(true);
|
||||
m_typeTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_typeTable->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
connect(m_typeTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this,
|
||||
&CatalogTypesPage::typeTable_currentRowChanged);
|
||||
connect(m_model, &TypeModel::modelReset,
|
||||
[this] () { selectedTypeChanged({}); });
|
||||
|
||||
retranslateUi();
|
||||
|
||||
}
|
||||
|
||||
void CatalogTypesPage::retranslateUi()
|
||||
{
|
||||
}
|
||||
|
||||
void CatalogTypesPage::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
|
||||
{
|
||||
m_catalog = cat;
|
||||
m_model->setTypeList(cat->types());
|
||||
m_typeTable->resizeColumnsToContents();
|
||||
}
|
||||
|
||||
void CatalogTypesPage::typeTable_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
if (current.row() != previous.row()) {
|
||||
if (current.isValid()) {
|
||||
auto source_index = m_sortFilterProxy->mapToSource(current);
|
||||
auto proc = m_model->typ(source_index.row());
|
||||
selectedTypeChanged(proc);
|
||||
}
|
||||
else
|
||||
selectedTypeChanged({});
|
||||
}
|
||||
}
|
||||
|
||||
void CatalogTypesPage::selectedTypeChanged(const std::optional<PgType> &typ)
|
||||
{
|
||||
updateSqlTab(typ);
|
||||
}
|
||||
|
||||
void CatalogTypesPage::updateSqlTab(const std::optional<PgType> &typ)
|
||||
{
|
||||
if (!typ.has_value()) {
|
||||
m_definitionView->clear();
|
||||
return;
|
||||
}
|
||||
QString create_sql = typ->createSql();
|
||||
|
||||
m_definitionView->setPlainText(create_sql);
|
||||
}
|
||||
34
pglab/widgets/CatalogTypesPage.h
Normal file
34
pglab/widgets/CatalogTypesPage.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <QSplitter>
|
||||
|
||||
class PgLabTableView;
|
||||
class PgDatabaseCatalog;
|
||||
class TypeModel;
|
||||
class CustomFilterSortModel;
|
||||
class SqlCodePreview;
|
||||
class PgType;
|
||||
|
||||
|
||||
class CatalogTypesPage : public QSplitter
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CatalogTypesPage(QWidget *parent = nullptr);
|
||||
void setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||
public slots:
|
||||
|
||||
void typeTable_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
private:
|
||||
PgLabTableView *m_typeTable = nullptr;
|
||||
//QTabWidget *m_detailTabs = nullptr;
|
||||
SqlCodePreview *m_definitionView = nullptr;
|
||||
TypeModel *m_model = nullptr;
|
||||
CustomFilterSortModel *m_sortFilterProxy = nullptr;
|
||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||
|
||||
void retranslateUi();
|
||||
void selectedTypeChanged(const std::optional<PgType> &seq);
|
||||
void updateSqlTab(const std::optional<PgType> &seq);
|
||||
};
|
||||
|
||||
|
|
@ -12,6 +12,9 @@ void operator<<(TypCategory &s, const Pgsql::Value &v)
|
|||
case 'B':
|
||||
s = TypCategory::Boolean;
|
||||
break;
|
||||
case 'C':
|
||||
s = TypCategory::Composite;
|
||||
break;
|
||||
case 'D':
|
||||
s = TypCategory::DateTime;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "TypeSelectionItemModel.h"
|
||||
//#include "CustomDataRole.h"
|
||||
#include "catalog/PgTypeContainer.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -82,6 +83,9 @@ int TypeModel::columnCount(const QModelIndex &/*parent*/) const
|
|||
|
||||
QVariant TypeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
// if (role == CustomDataTypeRole)
|
||||
// return getType(index.column());
|
||||
|
||||
if (index.isValid()) {
|
||||
int row = index.row();
|
||||
int column = index.column();
|
||||
|
|
@ -91,15 +95,90 @@ QVariant TypeModel::data(const QModelIndex &index, int role) const
|
|||
switch (column) {
|
||||
case OidCol: return elem.oid();
|
||||
case NameCol: return elem.objectName();
|
||||
case NamespaceCol: return elem.nsName();
|
||||
case OwnerCol: return elem.ownerName();
|
||||
case CategoryCol: return TypCategoryString(elem.category);
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QString TypeModel::TypCategoryString(TypCategory tc)
|
||||
{
|
||||
switch (tc) {
|
||||
case TypCategory::Array:
|
||||
return tr("array");
|
||||
case TypCategory::Boolean:
|
||||
return tr("boolean");
|
||||
case TypCategory::Composite:
|
||||
return tr("composite");
|
||||
case TypCategory::DateTime:
|
||||
return tr("datetime");
|
||||
case TypCategory::Enum:
|
||||
return tr("enum");
|
||||
case TypCategory::Geometric:
|
||||
return tr("geometric");
|
||||
case TypCategory::NetworkAddress:
|
||||
return tr("networkaddress");
|
||||
case TypCategory::Numeric:
|
||||
return tr("numeric");
|
||||
case TypCategory::Pseudo:
|
||||
return tr("pseude");
|
||||
case TypCategory::Range:
|
||||
return tr("range");
|
||||
case TypCategory::String:
|
||||
return tr("string");
|
||||
case TypCategory::Timespan:
|
||||
return tr("timespan");
|
||||
case TypCategory::UserDefined:
|
||||
return tr("user");
|
||||
case TypCategory::BitString:
|
||||
return tr("bitstring");
|
||||
case TypCategory::Unknown:
|
||||
return tr("unknown");
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
Oid TypeModel::getType(int column) const
|
||||
{
|
||||
switch (column) {
|
||||
case OidCol:
|
||||
return Pgsql::oid_oid;
|
||||
case NameCol:
|
||||
case NamespaceCol:
|
||||
case OwnerCol:
|
||||
case CategoryCol:
|
||||
return Pgsql::varchar_oid;
|
||||
}
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
void TypeModel::setTypeList(std::shared_ptr<const PgTypeContainer> types)
|
||||
{
|
||||
beginResetModel();
|
||||
m_types = types;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
PgType TypeModel::typ(int row) const
|
||||
{
|
||||
return m_types->getByIdx(row);
|
||||
}
|
||||
|
||||
QVariant TypeModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (section) {
|
||||
case OidCol: return tr("Oid");
|
||||
case NameCol: return tr("Name");
|
||||
case NamespaceCol: return tr("Schema");
|
||||
case OwnerCol: return tr("Owner");
|
||||
case CategoryCol: return tr("Category");
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <QAbstractListModel>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "catalog/PgType.h"
|
||||
|
||||
class PgTypeContainer;
|
||||
|
||||
|
|
@ -28,19 +29,27 @@ public:
|
|||
enum e_Columns : int {
|
||||
OidCol,
|
||||
NameCol, //
|
||||
NamespaceCol,
|
||||
OwnerCol,
|
||||
CategoryCol,
|
||||
colCount
|
||||
};
|
||||
|
||||
explicit TypeModel(QObject *parent = 0);
|
||||
|
||||
void setTypeList(std::shared_ptr<const PgTypeContainer> types);
|
||||
PgType typ(int row) const;
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const PgTypeContainer> m_types;
|
||||
|
||||
static QString TypCategoryString(TypCategory tc);
|
||||
Oid getType(int column) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -211,6 +211,48 @@ QString ConvertToMultiLineRawCppString(const QString &in)
|
|||
return out;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class Token {
|
||||
public:
|
||||
enum Type {
|
||||
Code,
|
||||
StringLiteral,
|
||||
SingleLineComment,
|
||||
MultiLineComment
|
||||
};
|
||||
|
||||
const Type type;
|
||||
/// Depends on type
|
||||
/// Code: literal copy of the matched code
|
||||
/// StringLiteral: the contents of the string literal, escapes have been unescaped
|
||||
/// *Comment, the text in the comment
|
||||
const QString data;
|
||||
|
||||
Token(Type type, QString data)
|
||||
: type(type)
|
||||
, data(data)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Tokenizer to get SQL out of a piece of programming language code
|
||||
///
|
||||
/// It works by ignoring most input and only get's triggered by string literals
|
||||
/// and comments. It does return tokens for the code in between just so
|
||||
class ProgLangTokenizer {
|
||||
public:
|
||||
ProgLangTokenizer(const QString &in)
|
||||
: input(in)
|
||||
{}
|
||||
|
||||
private:
|
||||
const QString input;
|
||||
int position = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
QString ConvertLangToSqlString(const QString &in)
|
||||
{
|
||||
// Assume mostly C++ for now but allow some other things like
|
||||
|
|
@ -232,6 +274,7 @@ QString ConvertLangToSqlString(const QString &in)
|
|||
WHITESPACE,
|
||||
PREFIX,
|
||||
IN_STRING,
|
||||
SingleLineComment,
|
||||
END,
|
||||
ERROR
|
||||
} state = WHITESPACE;
|
||||
|
|
|
|||
|
|
@ -60,3 +60,14 @@ TEST(ConvertLangToSqlString, testSemiColon)
|
|||
auto output = ConvertLangToSqlString(in);
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ConvertLangToSqlString, testComment)
|
||||
{
|
||||
QString in(R"__( "SELECT * " // comment
|
||||
"FROM t"; )__");
|
||||
QString expected(R"__(SELECT *
|
||||
FROM t)__");
|
||||
|
||||
auto output = ConvertLangToSqlString(in);
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue