Added new features autocomplite.

1. Добавлена подстановка соединений таблиц(и представлений) по их FK.
   Подстановка работает в двух вариантах:
   1.1 После ключевого слова ON:самая правая таблица соединяется с любой левой.
   1.2 После ключевого слова WHERE AND OR все таблицы соединяются со всеми.
2. Дополнение условия соединения после символа = .
   Представления можно соединить только если поле представления является полем таблицы.
3. Стандартное автодополнение теперь выдаёт список таблиц и представление после JOIN.
This commit is contained in:
lsv 2025-02-10 11:01:46 +05:00
parent b7b911c93b
commit 21ee30844a
10 changed files with 1873 additions and 916 deletions

View file

@ -131,6 +131,7 @@ namespace FSQL {
wxString columnList;
int startIndex = -1;
int endIndex = -1;
int level = 0;
};
struct bits {
unsigned int from : 1;
@ -154,6 +155,11 @@ namespace FSQL {
wxString BuildAutoComplite(int startIndex, int level);
wxString GetListTable(int cursorPos);
wxString GetColsList(wxString what, wxString& listfieldOut, wxString& nameTableOut);
/// <summary>
/// Возращает количество таблиц слева от курсора и заполняет их имена и псевдонимы.
///
/// </summary>
int GetTableListBeforePosition(int positem, wxArrayString& listtable, wxArrayString& listalias);
//
int ParseSql(int flags);
wxString printParseArray();
@ -161,13 +167,14 @@ namespace FSQL {
int GetIndexItemNextSqlPosition(int sqlPosition);
int GetNextPositionSqlParse();
bool GetItem(int index, FSQL::view_item& item);
int next_item_no_space(int& index, int direction = 1);
private:
wxString get_list_columns(int startindex, union FSQL::Byte zone);
wxPoint align_level(int start_i, int level, int Xpos, int Ypos, int flag);
int check_bracket(int index);
int get_prev_value(int indx, wxString keyword);
int next_item_no_space(int& index, int direction = 1);
wxSize max_width_size(int index); // index bracet
wxSize best_sizeAndDraw(wxDC& dc, wxPoint& pos, FSQL::view_item& vi, int mode);
int maxYheightLine = 0;

View file

@ -0,0 +1,192 @@
#pragma once
class Table;
class Cols
{
public:
wxString name;
int num;
// Для v - ссылка view/table текущего уровня (самый нижний уровень).
// Для r - сыылка на FK таблицу
Table *linkTable=NULL;
int linknumcol;
wxString linkOid;
bool pk = false;
//(самый нижний уровень).
Table* relTable = NULL;
int relcol = 0;
bool operator< (const Cols& e) const
{
return (name < e.name);
}
bool operator==(const Cols& otherPoint) const
{
if (this->name == otherPoint.name ) return true;
else return false;
}
struct HashFunction
{
size_t operator()(const Cols& point) const
{
size_t xHash = std::hash<wxString>()(point.name);
//size_t yHash = std::hash<wxString>()(point.y) << 1;
return xHash;
}
};
};
class Table
{
public:
Table(const wxString &tablename);
Table() {};
const wxString& GetName(){ return name; };
const wxString& GetSchema() { return schema; };
const wxString& GetAlias() { return alias; };
void SetAlias(const wxString str) { alias=str; };
const wxString& GetOID() { return oid; };
const int GetColsCount() { return cols.size(); };
Cols& operator[](unsigned index) { return cols[index]; }
void SetCol(int index,Cols & valcol){ cols[index]=valcol; }
char GetType() { return type; };
void Set(wxString kind,wxString sch,wxString toid, wxString tname);
void AddColumn(wxString ncol, wxString colname, wxString oidTable, wxString ncolTable);
bool operator< (const Table& e) const
{
return (schema < e.schema)||(schema == e.schema && name < e.name);
}
bool operator==(const Table& otherPoint) const
{
if (this->name == otherPoint.name && this->schema== otherPoint.schema) return true;
else return false;
}
struct HashFunction
{
size_t operator()(const Table& point) const
{
size_t xHash = std::hash<wxString>()(point.name);
size_t yHash = std::hash<wxString>()(point.schema) << 1;
return xHash ^ yHash;
}
};
private:
void make_name(const wxString& tablename);
wxString name;
wxString schema;
wxString alias;
char type=0; // pg_class.relkind
wxString oid;
//std::unordered_set<Cols,Cols::HashFunction> cols;
std::vector<Cols> cols;
};
/// <summary>
/// Связка двух таблиц по колонкам
/// </summary>
class LinkTableFK
{
public:
Table *parent;
Table *child;
std::vector<int> colsp;
std::vector<int> colsc;
};
typedef struct tab_col_struct {
Table* t; int column;
bool operator< (const tab_col_struct& e) const
{
return (t < e.t) || (t == e.t && column < e.column);
}
bool operator==(const tab_col_struct& otherPoint) const
{
if (t == otherPoint.t && column == otherPoint.column) return true;
else return false;
}
} tab_col_struct;
typedef struct tab_tab_struct {
Table* t;
Table* t2;
bool operator< (const tab_tab_struct& e) const
{
return (t < e.t) || (t == e.t && t2 < e.t2);
}
} tab_tab_struct;
typedef struct fk_full_struct {
tab_col_struct left;
tab_col_struct right;
bool operator< (const fk_full_struct& e) const
{
return (left < e.left) || (left == e.left && right < e.right);
}
} fk_full_struct;
class TableColsMap
{
public:
enum Flag {
ALL_LEFT_TO_RIGHT = 1,
SEQUENCE_LIST_TABLE = 2,
USE_TRANSIT_FK = 4,
NOT_ADD_FIRST_SPACE=8
};
#define CHKFLAG(va,par) (((va) & (par))==(par))
#ifdef DEBUG
static void TEST() {
Table v1("\"schema\".table");
Table v2("\"schema\".\"table\"");
Table v3("schema.table");
Table v4("schema.\"table\"");
Table v5("\"table\"");
Table v6("table");
Table e1("sc.table.t");
Table e2("\"\".table");
Table e3("\".\".table");
}
#endif // DEBUG
TableColsMap() { regaction.Compile(
R"((?x)
\{TARGETENTRY.*?
(\{ ([^{}]++|(?1))* \})
\s+:resno\s(\d+)\s
:resname\s(\S+)\s.*?
:resorigtbl\s(\d+)\s.*?
:resorigcol\s(\d+)(\s:)
)",wxRE_EXTENDED);
};
void checkDBconn(pgConn *dbconn);
/// <summary>
/// Добавить таблицы для поиска ссылок.
/// </summary>
/// <param name="dbconn">Соединие к БД</param>
/// <param name="tables">список таблиц</param>
/// <param name="alias">список синонимов</param>
/// <returns>true если успешно добавлены</returns>
wxString AddTableList(pgConn* dbconn, const wxArrayString& tables, const wxArrayString& alias, const TableColsMap::Flag flag, const wxString& leftexp);
void MapViewColToRelCol(const TableColsMap::Flag flag);
Table* GetRelTableForViewCol(const wxString oid, int ncolview, int& outrelcol);
Table* GetTablebyOID(const wxString oid);
Table* GetTableByName(const wxString& sch, const wxString& tname);
void BuildMapTableColumnsToSQLexp(Table* reltab, const wxString& alias, std::map<tab_col_struct, wxString>& map);
wxString MapTableToTable(std::map<tab_col_struct, wxString>& maplefttables, std::map<tab_col_struct, wxString>& maprighttable, const TableColsMap::Flag flag, const wxString& leftexp);
~TableColsMap();
private:
void getDatabaseViews();
void getDatabaseTables(const TableColsMap::Flag flag);
tab_col_struct search_link(tab_col_struct start, tab_col_struct chknode, std::set<fk_full_struct>& traz, int level);
void Clear();
pgConn* db = NULL;
//std::map<Table *, std::vector<LinkTableFK>> tablechild_fk;
std::multimap<tab_col_struct, tab_col_struct> all_fk_index; // {parent_t, n_col}={ftable, fcol}
//std::map<Table *, wxString> alias;
wxRegEx regaction;
std::map<wxString, Table*> oids;
wxString whereexp;
};