mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 06:05:49 -06:00
Add autocomplite dlgFunction. Fix multibyte char support.
Добавлено использование автоподстановки в окно редактирования процедур и функции. Добавлена поддержка UTF-8. Добавлена поддержка unicode для идентификаторов. Добавлено сохранение выбранных опций в диалоге Выравнивания.
This commit is contained in:
parent
d034d02261
commit
400cbc2cc7
5 changed files with 130 additions and 10 deletions
|
|
@ -89,7 +89,7 @@ ctlSQLBox::ctlSQLBox(wxWindow *parent, wxWindowID id, const wxPoint &pos, const
|
||||||
m_dlgFindReplace = 0;
|
m_dlgFindReplace = 0;
|
||||||
m_dlgTransformText = 0;
|
m_dlgTransformText = 0;
|
||||||
m_database = NULL;
|
m_database = NULL;
|
||||||
|
|
||||||
m_autocompDisabled = false;
|
m_autocompDisabled = false;
|
||||||
process = 0;
|
process = 0;
|
||||||
processID = 0;
|
processID = 0;
|
||||||
|
|
@ -1344,10 +1344,11 @@ wxString ctlSQLBox::ExternalFormat(int typecmd)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wxArrayString choiceCmpOpts;
|
wxArrayString choiceCmpOpts;
|
||||||
wxArrayInt choiceSelectOpts;
|
|
||||||
choiceCmpOpts.Add(_("All line (use all EOL)"));
|
choiceCmpOpts.Add(_("All line (use all EOL)"));
|
||||||
choiceCmpOpts.Add(_("First line pattern (ignore all but the first EOL)"));
|
choiceCmpOpts.Add(_("First line pattern (ignore all but the first EOL)"));
|
||||||
choiceCmpOpts.Add(_("Try looking for patterns above"));
|
choiceCmpOpts.Add(_("Try looking for patterns above"));
|
||||||
|
choiceCmpOpts.Add(_("Compact view"));
|
||||||
choiceCmpOpts.Add(_("Remove multi spaces"));
|
choiceCmpOpts.Add(_("Remove multi spaces"));
|
||||||
wxMultiChoiceDialog dialog(this,
|
wxMultiChoiceDialog dialog(this,
|
||||||
_("A multi-choice convenience dialog"),
|
_("A multi-choice convenience dialog"),
|
||||||
|
|
@ -1362,7 +1363,8 @@ wxString ctlSQLBox::ExternalFormat(int typecmd)
|
||||||
if (choiceSelectOpts[n] == 0) cfg |= AlignWrap::ALL_LINES;
|
if (choiceSelectOpts[n] == 0) cfg |= AlignWrap::ALL_LINES;
|
||||||
if (choiceSelectOpts[n] == 1 ) cfg |= AlignWrap::FIRST_LINE ;
|
if (choiceSelectOpts[n] == 1 ) cfg |= AlignWrap::FIRST_LINE ;
|
||||||
if (choiceSelectOpts[n] == 2) cfg |= AlignWrap::FIND_UP_LONG_LINE;
|
if (choiceSelectOpts[n] == 2) cfg |= AlignWrap::FIND_UP_LONG_LINE;
|
||||||
if (choiceSelectOpts[n] == 3) cfg |= AlignWrap::ONLY_SINGLE_SPACE;
|
if (choiceSelectOpts[n] == 3) cfg |= AlignWrap::COMPACT_VIEW;
|
||||||
|
if (choiceSelectOpts[n] == 4) cfg |= AlignWrap::ONLY_SINGLE_SPACE;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (CHKCFGPARAM(cfg, AlignWrap::ALL_LINES) && CHKCFGPARAM(cfg, AlignWrap::FIRST_LINE)) cfg -= AlignWrap::FIRST_LINE;
|
if (CHKCFGPARAM(cfg, AlignWrap::ALL_LINES) && CHKCFGPARAM(cfg, AlignWrap::FIRST_LINE)) cfg -= AlignWrap::FIRST_LINE;
|
||||||
|
|
@ -1866,9 +1868,31 @@ void ctlSQLBox::OnAutoComplete(wxCommandEvent &rev)
|
||||||
if (m_autocompDisabled)
|
if (m_autocompDisabled)
|
||||||
return;
|
return;
|
||||||
int pos = GetCurrentPos();
|
int pos = GetCurrentPos();
|
||||||
wxString what = GetCurLine().Left(pos - PositionFromLine(GetCurrentLine()));;
|
//wxString what = GetCurLine().Left(pos - PositionFromLine(GetCurrentLine()));
|
||||||
|
wxString what = GetTextRange(PositionFromLine(GetCurrentLine()),pos);
|
||||||
int spaceidx = what.Find(' ', true);
|
int spaceidx = what.Find(' ', true);
|
||||||
|
int spacecharidx=spaceidx;
|
||||||
|
int poshome=PositionFromLine(GetCurrentLine());
|
||||||
|
int posspc=PositionRelative(poshome,spaceidx);
|
||||||
|
if (spaceidx != -1) {
|
||||||
|
|
||||||
|
while (poshome< posspc) {
|
||||||
|
int ch = GetCharAt(posspc);
|
||||||
|
int st = GetStyleAt(posspc) & 0x1F;
|
||||||
|
if (st == wxSTC_SQL_STRING || st == wxSTC_SQL_CHARACTER)
|
||||||
|
{
|
||||||
|
posspc--;
|
||||||
|
} else if (ch=='"' || ch=='.') {
|
||||||
|
posspc--;
|
||||||
|
} else if (ch==' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
wxString lastexp=GetTextRange(PositionFromLine(GetCurrentLine()),posspc);
|
||||||
|
spacecharidx=lastexp.Length();
|
||||||
|
spaceidx=posspc-poshome;
|
||||||
|
}
|
||||||
char *tab_ret;
|
char *tab_ret;
|
||||||
if (spaceidx == -1)
|
if (spaceidx == -1)
|
||||||
tab_ret = tab_complete(what.mb_str(wxConvUTF8), 0, what.Len() + 1, m_database);
|
tab_ret = tab_complete(what.mb_str(wxConvUTF8), 0, what.Len() + 1, m_database);
|
||||||
|
|
@ -2072,7 +2096,7 @@ void ctlSQLBox::OnAutoComplete(wxCommandEvent &rev)
|
||||||
if (found) {
|
if (found) {
|
||||||
wxString flt="";
|
wxString flt="";
|
||||||
if (!fld.IsEmpty()) flt = " and a.attname ~ " + qtConnString(fld);
|
if (!fld.IsEmpty()) flt = " and a.attname ~ " + qtConnString(fld);
|
||||||
wxString sql=wxT("select string_agg(a.attname,E'\t') from pg_attribute a where a.attrelid = (select oid from pg_class p where relname=") +qtConnString(table)
|
wxString sql=wxT("select string_agg(a.attname,E'\t') from pg_attribute a where a.attrelid in (select oid from pg_class p where relname=") +qtConnString(table)
|
||||||
+wxT(") and a.attisdropped IS FALSE and a.attnum>=0 ")+flt
|
+wxT(") and a.attisdropped IS FALSE and a.attnum>=0 ")+flt
|
||||||
+wxT(" order by 1");
|
+wxT(" order by 1");
|
||||||
//pgSet *res = m_database->ExecuteSet(sql);
|
//pgSet *res = m_database->ExecuteSet(sql);
|
||||||
|
|
@ -2134,7 +2158,8 @@ void ctlSQLBox::OnAutoComplete(wxCommandEvent &rev)
|
||||||
if (spaceidx == -1)
|
if (spaceidx == -1)
|
||||||
AutoCompShow(what.Len(), wxRet);
|
AutoCompShow(what.Len(), wxRet);
|
||||||
else
|
else
|
||||||
AutoCompShow(what.Len() - spaceidx - 1, wxRet);
|
//AutoCompShow(what.Len() - spacecharidx - 1, wxRet);
|
||||||
|
AutoCompShow(pos - posspc - 1, wxRet);
|
||||||
|
|
||||||
// Now switch back
|
// Now switch back
|
||||||
#ifdef __WXMAC__
|
#ifdef __WXMAC__
|
||||||
|
|
@ -2201,7 +2226,12 @@ char *pg_query_to_single_ordered_string(char *query, void *dbptr)
|
||||||
|
|
||||||
return strdup(ret.mb_str(wxConvUTF8));
|
return strdup(ret.mb_str(wxConvUTF8));
|
||||||
}
|
}
|
||||||
|
extern "C"
|
||||||
|
int get_id_encoding(void *dbptr)
|
||||||
|
{
|
||||||
|
pgConn *db = (pgConn *)dbptr;
|
||||||
|
return db->Get_client_encoding_id();
|
||||||
|
}
|
||||||
|
|
||||||
// Find some text in the document.
|
// Find some text in the document.
|
||||||
CharacterRange ctlSQLBox::RegexFindText(int minPos, int maxPos, const wxString &text)
|
CharacterRange ctlSQLBox::RegexFindText(int minPos, int maxPos, const wxString &text)
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,8 @@ dlgFunction::dlgFunction(pgaFactory *f, frmMain *frame, pgFunction *node, pgSche
|
||||||
txtSqlBox->SetMarginType(1, wxSTC_MARGIN_NUMBER);
|
txtSqlBox->SetMarginType(1, wxSTC_MARGIN_NUMBER);
|
||||||
txtSqlBox->SetMarginWidth(1, ConvertDialogToPixels(wxPoint(16, 0)).x);
|
txtSqlBox->SetMarginWidth(1, ConvertDialogToPixels(wxPoint(16, 0)).x);
|
||||||
}
|
}
|
||||||
|
if (function && function->GetDatabase())
|
||||||
|
txtSqlBox->SetDatabase(function->GetDatabase()->GetConnection());
|
||||||
btnAdd->Disable();
|
btnAdd->Disable();
|
||||||
btnRemove->Disable();
|
btnRemove->Disable();
|
||||||
btnChange->Disable();
|
btnChange->Disable();
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,7 @@ private:
|
||||||
dlgFindReplace *m_dlgFindReplace;
|
dlgFindReplace *m_dlgFindReplace;
|
||||||
dlgTransformText *m_dlgTransformText;
|
dlgTransformText *m_dlgTransformText;
|
||||||
pgConn *m_database;
|
pgConn *m_database;
|
||||||
|
wxArrayInt choiceSelectOpts;
|
||||||
bool m_autoIndent, m_autocompDisabled, m_hint_mode;
|
bool m_autoIndent, m_autocompDisabled, m_hint_mode;
|
||||||
struct InsensitiveCompare {
|
struct InsensitiveCompare {
|
||||||
bool operator() (const wxString& a, const wxString& b) const {
|
bool operator() (const wxString& a, const wxString& b) const {
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,11 @@ public:
|
||||||
{
|
{
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
int Get_client_encoding_id()
|
||||||
|
{
|
||||||
|
return PQclientEncoding(conn);
|
||||||
|
}
|
||||||
|
|
||||||
void Notice(const char *msg);
|
void Notice(const char *msg);
|
||||||
pgNotification *GetNotification();
|
pgNotification *GetNotification();
|
||||||
int GetTxStatus();
|
int GetTxStatus();
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
* Callbacks to the C++ world
|
* Callbacks to the C++ world
|
||||||
*/
|
*/
|
||||||
char *pg_query_to_single_ordered_string(char *query, void *dbptr);
|
char *pg_query_to_single_ordered_string(char *query, void *dbptr);
|
||||||
|
int get_id_encoding(void *dbptr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global vars for readline emulation
|
* Global vars for readline emulation
|
||||||
|
|
@ -170,6 +170,7 @@ static char *complete_from_schema_query(const char *text, const void* query, con
|
||||||
static char *complete_create_command(char *text);
|
static char *complete_create_command(char *text);
|
||||||
static char *complete_filename();
|
static char *complete_filename();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Include the main tab completion functionality from psql
|
* Include the main tab completion functionality from psql
|
||||||
*/
|
*/
|
||||||
|
|
@ -226,16 +227,97 @@ static char *complete_from_const(const char *text, const char *string)
|
||||||
{
|
{
|
||||||
return strdup(string);
|
return strdup(string);
|
||||||
}
|
}
|
||||||
|
static int lower_identifier(const char *ident, char *out,void *dbptr)
|
||||||
|
{
|
||||||
|
size_t buflen = strlen(ident) + 1;
|
||||||
|
|
||||||
|
char *sname;
|
||||||
|
char *oname;
|
||||||
|
char *optr;
|
||||||
|
char *tmp;
|
||||||
|
int inquotes=0;
|
||||||
|
int isneedlower=0;
|
||||||
|
int schemaquoted,objectquoted;
|
||||||
|
int encoding=6; // pg_enc.PG_UTF8
|
||||||
|
int enc_is_single_byte = 0;
|
||||||
|
int utf8len=0;
|
||||||
|
/* Initialize, making a certainly-large-enough output buffer */
|
||||||
|
schemaquoted = objectquoted = 0;
|
||||||
|
/* Scan */
|
||||||
|
inquotes = 0;
|
||||||
|
optr=out;
|
||||||
|
while (*ident)
|
||||||
|
{
|
||||||
|
unsigned char ch = (unsigned char) *ident++;
|
||||||
|
utf8len++;
|
||||||
|
if (ch == '"')
|
||||||
|
{
|
||||||
|
if (inquotes && *ident == '"')
|
||||||
|
{
|
||||||
|
/* two quote marks within a quoted identifier = emit quote */
|
||||||
|
*optr++ = '"';
|
||||||
|
ident++;
|
||||||
|
utf8len++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inquotes = !inquotes;
|
||||||
|
objectquoted = 1;
|
||||||
|
*optr++ = '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!enc_is_single_byte && ch>127)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Transfer multibyte characters without further processing. They
|
||||||
|
* wouldn't be affected by our downcasing rule anyway, and this
|
||||||
|
* avoids possibly doing the wrong thing in unsafe client
|
||||||
|
* encodings.
|
||||||
|
*/
|
||||||
|
int chlen = PQmblenBounded(ident - 1, encoding);
|
||||||
|
|
||||||
|
*optr++ = (char) ch;
|
||||||
|
while (--chlen > 0)
|
||||||
|
*optr++ = *ident++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!inquotes)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This downcasing transformation should match the backend's
|
||||||
|
* downcase_identifier() as best we can. We do not know the
|
||||||
|
* backend's locale, though, so it's necessarily approximate.
|
||||||
|
* We assume that psql is operating in the same locale and
|
||||||
|
* encoding as the backend.
|
||||||
|
*/
|
||||||
|
if (ch >= 'A' && ch <= 'Z')
|
||||||
|
ch += 'a' - 'A';
|
||||||
|
else if (enc_is_single_byte && ch>127 && isupper(ch))
|
||||||
|
ch = tolower(ch);
|
||||||
|
}
|
||||||
|
*optr++ = (char) ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*optr = '\0';
|
||||||
|
return utf8len;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
int string_length = strlen(text);
|
||||||
char* e_text;
|
char* e_text;
|
||||||
|
char* e_text_ident;
|
||||||
char* complete_query = NULL;
|
char* complete_query = NULL;
|
||||||
char* t;
|
char* t;
|
||||||
|
|
||||||
|
e_text_ident = malloc(string_length * 2 + 1);
|
||||||
|
PQescapeString(e_text_ident,text, strlen(text));
|
||||||
|
string_length=strlen(e_text_ident);
|
||||||
e_text = malloc(string_length * 2 + 1);
|
e_text = malloc(string_length * 2 + 1);
|
||||||
PQescapeString(e_text, text, string_length);
|
int utf8len=lower_identifier(e_text_ident,e_text,dbptr);
|
||||||
|
string_length=utf8len;
|
||||||
|
free(e_text_ident);
|
||||||
|
|
||||||
if (query != NULL)
|
if (query != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue