Autocomplite, server status, publications

Добавлен контроль прав доступа на select для таблиц и представления
при ипользовании автодополнения.
Добавлен контроль доступа при пролучении информации о подписках.
Добалена совместимость с более ранними версиями при получении информации
о публикациях.
При получении логов в окне "Статус сервера" добавлена проверка наличия прав на используемые функции при получении файлы логов.
Мелкие правки при работе с автодополнениями в окне запросов.
This commit is contained in:
levinsv 2025-08-18 15:53:25 +05:00
parent f43f341ffd
commit a77fcfcd5a
6 changed files with 207 additions and 111 deletions

View file

@ -66,6 +66,20 @@ static const SchemaQuery Query_for_list_of_aggregates = {
/* qualresult */
NULL
};
static const SchemaQuery Query_for_list_of_publication = {
/* catname */
"pg_catalog.pg_publication p",
/* selcondition */
"pg_catalog.has_database_privilege(current_database(),'CREATE')",
/* viscondition */
NULL,
/* namespace */
"-",
/* result */
"pg_catalog.quote_ident(p.pubname)",
/* qualresult */
NULL
};
static const SchemaQuery Query_for_list_of_datatypes = {
/* catname */
@ -148,7 +162,49 @@ static const SchemaQuery Query_for_list_of_tables = {
/* catname */
"pg_catalog.pg_class c",
/* selcondition */
"c.relkind IN ('r')",
"c.relkind IN ('r') and pg_catalog.has_table_privilege(c.oid, 'select')",
/* viscondition */
"pg_catalog.pg_table_is_visible(c.oid)",
/* namespace */
"c.relnamespace",
/* result */
"pg_catalog.quote_ident(c.relname)",
/* qualresult */
NULL
};
static const SchemaQuery Query_for_list_of_tables_insert = {
/* catname */
"pg_catalog.pg_class c",
/* selcondition */
"c.relkind IN ('r','v') and pg_catalog.has_table_privilege(c.oid, 'insert')",
/* viscondition */
"pg_catalog.pg_table_is_visible(c.oid)",
/* namespace */
"c.relnamespace",
/* result */
"pg_catalog.quote_ident(c.relname)",
/* qualresult */
NULL
};
static const SchemaQuery Query_for_list_of_tables_update = {
/* catname */
"pg_catalog.pg_class c",
/* selcondition */
"c.relkind IN ('r','v') and pg_catalog.has_table_privilege(c.oid, 'update')",
/* viscondition */
"pg_catalog.pg_table_is_visible(c.oid)",
/* namespace */
"c.relnamespace",
/* result */
"pg_catalog.quote_ident(c.relname)",
/* qualresult */
NULL
};
static const SchemaQuery Query_for_list_of_tables_delete = {
/* catname */
"pg_catalog.pg_class c",
/* selcondition */
"c.relkind IN ('r','v') and pg_catalog.has_table_privilege(c.oid, 'delete')",
/* viscondition */
"pg_catalog.pg_table_is_visible(c.oid)",
/* namespace */
@ -178,7 +234,7 @@ static const SchemaQuery Query_for_list_of_tsv = {
/* catname */
"pg_catalog.pg_class c",
/* selcondition */
"c.relkind IN ('r', 'S', 'v','m','f','p')",
"c.relkind IN ('r', 'S', 'v','m','f','p') and pg_catalog.has_table_privilege(c.oid, 'select')",
/* viscondition */
"pg_catalog.pg_table_is_visible(c.oid)",
/* namespace */
@ -193,7 +249,7 @@ static const SchemaQuery Query_for_list_of_views = {
/* catname */
"pg_catalog.pg_class c",
/* selcondition */
"c.relkind IN ('v')",
"c.relkind IN ('v') and pg_catalog.has_table_privilege(c.oid, 'select')",
/* viscondition */
"pg_catalog.pg_table_is_visible(c.oid)",
/* namespace */
@ -249,7 +305,7 @@ static const SchemaQuery Query_for_list_of_views = {
#define Query_for_list_of_schemas \
"SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
" WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
" WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s' and pg_catalog.has_schema_privilege(oid,'usage')"
#define Query_for_list_of_set_vars \
"SELECT name FROM "\
@ -329,7 +385,8 @@ typedef struct
static const pgsql_thing_t words_after_create[] = {
{"AGGREGATE", NULL, &Query_for_list_of_aggregates},
{"PUBLICATION", NULL, NULL},
{"PUBLICATION", NULL, &Query_for_list_of_publication},
{"SUBSCRIPTION", NULL, NULL},
{"CAST", NULL, NULL}, /* Casts have complex structures for names, so
* skip it */
@ -428,6 +485,8 @@ static char * psql_completion(char *text, int start, int end, void *dbptr)
/* If no previous word, suggest one of the basic sql commands */
else if (!prev_wd)
COMPLETE_WITH_LIST(sql_commands);
else if (prev_wd[strlen(prev_wd)-1] == ',')
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* CREATE or DROP but not ALTER (TABLE|DOMAIN|GROUP) sth DROP */
/* complete with something you can create or drop */
@ -448,9 +507,9 @@ static char * psql_completion(char *text, int start, int end, void *dbptr)
pg_strcasecmp(prev3_wd, "TABLE") != 0)
{
static const char *const list_ALTER[] =
{"AGGREGATE", "CONVERSION", "DATABASE", "DOMAIN", "FUNCTION",
"GROUP", "INDEX", "LANGUAGE", "OPERATOR", "ROLE", "SCHEMA", "SEQUENCE", "TABLE",
"TABLESPACE", "TRIGGER", "TYPE", "USER", NULL};
{"AGGREGATE","CONVERSION","DATABASE","DOMAIN","FUNCTION","GROUP","INDEX","LANGUAGE"
,"OPERATOR","PUBLICATION","ROLE","SCHEMA","SEQUENCE","SUBSCRIPTION","TABLE"
,"TABLESPACE","TRIGGER","TYPE","USER", NULL};
COMPLETE_WITH_LIST(list_ALTER);
}
@ -1058,7 +1117,7 @@ static char * psql_completion(char *text, int start, int end, void *dbptr)
/* Complete DELETE FROM with a list of tables */
else if (pg_strcasecmp(prev2_wd, "DELETE") == 0 &&
pg_strcasecmp(prev_wd, "FROM") == 0)
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_delete, NULL);
/* Complete DELETE FROM <table> */
else if (pg_strcasecmp(prev3_wd, "DELETE") == 0 &&
pg_strcasecmp(prev2_wd, "FROM") == 0)
@ -1273,7 +1332,7 @@ static char * psql_completion(char *text, int start, int end, void *dbptr)
/* Complete INSERT INTO with table names */
else if (pg_strcasecmp(prev2_wd, "INSERT") == 0 &&
pg_strcasecmp(prev_wd, "INTO") == 0)
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_insert, NULL);
/* Complete "INSERT INTO <table> (" with attribute names */
else if (rl_line_buffer[start - 1] == '(' &&
pg_strcasecmp(prev3_wd, "INSERT") == 0 &&
@ -1553,7 +1612,7 @@ static char * psql_completion(char *text, int start, int end, void *dbptr)
/* UPDATE */
/* If prev. word is UPDATE suggest a list of tables */
else if (pg_strcasecmp(prev_wd, "UPDATE") == 0)
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_update, NULL);
/* Complete UPDATE <table> with "SET" */
else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0)
COMPLETE_WITH_CONST("SET");

View file

@ -227,26 +227,26 @@ static char *complete_from_const(const char *text, const char *string)
return strdup(string);
}
static char *_complete_from_query(const char *text, const char *query, const SchemaQuery *squery, const char *addon, void *dbptr)
static char* _complete_from_query(const char* text, const char* query, const SchemaQuery* squery, const char* addon, void* dbptr)
{
int string_length = strlen(text);
char *e_text;
char *complete_query = NULL;
char *t;
char* e_text;
char* complete_query = NULL;
char* t;
e_text = malloc(string_length*2+1);
e_text = malloc(string_length * 2 + 1);
PQescapeString(e_text, text, string_length);
if (query != NULL)
{
/* Normal query */
int bufsize = 1024;
char *e_addon;
char* e_addon;
/* Normal query needs escaped string */
if (addon)
{
e_addon = malloc(strlen(addon)*2+1);
e_addon = malloc(strlen(addon) * 2 + 1);
PQescapeString(e_addon, addon, strlen(addon));
}
else
@ -259,7 +259,7 @@ static char *_complete_from_query(const char *text, const char *query, const Sch
#ifdef WIN32
r = _snprintf(complete_query, bufsize, query, string_length, e_text, e_addon);
#else
r = snprintf(complete_query, bufsize, query, string_length, e_text, e_addon);
r = snprintf(complete_query, bufsize, query, string_length, e_text, e_addon);
#endif
if (r < 0 || r >= bufsize)
bufsize *= 2;
@ -271,29 +271,29 @@ static char *_complete_from_query(const char *text, const char *query, const Sch
else
{
/* Schema query */
char *selcondition = NULL;
char *viscondition = NULL;
char *suppress_str = NULL;
const char *qualresult;
char* selcondition = NULL;
char* viscondition = NULL;
char* suppress_str = NULL;
const char* qualresult;
int bufsize = 2048;
if (squery->selcondition)
{
selcondition = malloc(strlen(squery->selcondition)+10);
sprintf(selcondition,"%s AND ",squery->selcondition);
selcondition = malloc(strlen(squery->selcondition) + 10);
sprintf(selcondition, "%s AND ", squery->selcondition);
}
else
selcondition = strdup("");
if (squery->viscondition)
{
viscondition = malloc(strlen(squery->viscondition)+10);
sprintf(viscondition, " AND %s",squery->viscondition);
viscondition = malloc(strlen(squery->viscondition) + 10);
sprintf(viscondition, " AND %s", squery->viscondition);
}
else
viscondition = strdup("");
if (strcmp(squery->catname,"pg_catalog.pg_class c") == 0 &&
if (strcmp(squery->catname, "pg_catalog.pg_class c") == 0 &&
strncmp(text, "pg_", 3) != 0)
suppress_str = " AND c.relnamespace <> (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')";
else
@ -308,15 +308,15 @@ static char *_complete_from_query(const char *text, const char *query, const Sch
int r;
complete_query = realloc(complete_query, bufsize);
#ifdef WIN32
r = _snprintf(complete_query, bufsize,
r = _snprintf(complete_query, bufsize,
#else
r = snprintf(complete_query, bufsize,
r = snprintf(complete_query, bufsize,
#endif
"SELECT %s FROM %s WHERE %s substring(%s,1,%d)='%s' %s %s "
"\nUNION\n"
"SELECT pg_catalog.quote_ident(n.nspname) || '.' FROM pg_catalog.pg_namespace n WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s' AND (SELECT pg_catalog.count(*) FROM pg_catalog.pg_namespace WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d)= substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1))>1"
"SELECT pg_catalog.quote_ident(n.nspname) || '.' FROM pg_catalog.pg_namespace n WHERE pg_catalog.has_schema_privilege(n.oid,'usage') and substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s' AND (SELECT pg_catalog.count(*) FROM pg_catalog.pg_namespace WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d)= substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1))>1"
"\nUNION\n"
"SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s FROM %s, pg_catalog.pg_namespace n WHERE %s = n.oid AND %s substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s' AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) = substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1) AND (SELECT pg_catalog.count(*) FROM pg_catalog.pg_namespace WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) = substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1"
"SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s FROM %s, pg_catalog.pg_namespace n WHERE pg_catalog.has_schema_privilege(n.oid,'usage') and %s = n.oid AND %s substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s' AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) = substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1) AND (SELECT pg_catalog.count(*) FROM pg_catalog.pg_namespace WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) = substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1"
"\n%s",
squery->result,
squery->catname,
@ -341,15 +341,21 @@ static char *_complete_from_query(const char *text, const char *query, const Sch
e_text,
string_length,
e_text,
addon?addon:"");
addon ? addon : "");
if (r < 0 || r >= bufsize)
bufsize *= 2;
else
break;
{
// namespace=='-'
if (squery->namespace[0] == '-') {
char* newlinePtr = strchr(complete_query, '\n');
if (newlinePtr != NULL) *newlinePtr = '\0';
}
}
break;
}
free(viscondition);
free(selcondition);