proposal: psql autocomplete for casting

Started by Pavel Stehulealmost 10 years ago5 messages
#1Pavel Stehule
pavel.stehule@gmail.com

Hi

We have not autocomplete for casting introduced by symbol "::". A
implementation should not be hard.

Regards

Pavel

#2Kyotaro HORIGUCHI
horiguchi.kyotaro@lab.ntt.co.jp
In reply to: Pavel Stehule (#1)
Re: proposal: psql autocomplete for casting

Hello, I considered on this,

At Thu, 3 Mar 2016 10:05:06 +0100, Pavel Stehule <pavel.stehule@gmail.com> wrote in <CAFj8pRDZ456OKbpV9jDJ_VCgTWprqxYu1kQp6z_Eu_WgNvs57Q@mail.gmail.com>

We have not autocomplete for casting introduced by symbol "::". A
implementation should not be hard.

Completion needs a sequence of break characters between two
succeeding words and the break characters cannot be a part of a
word. If cast operators are allowed to be preceded by white
space, the following diff gives maybe-desired behavior.

===
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1322,6 +1322,8 @@ psql_completion(const char *text, int start, int end)
                else
                        matches = complete_from_variables(text, ":", "", true);
        }
+       else if (text[0] == ':' && text[1] == ':')
+		COMPLETE_WITH_LIST3("::integer", "::text", "::date");

/* If no previous word, suggest one of the basic sql commands */
else if (previous_words_count == 0)
===

=# select 123 ::<tab>
::DATE ::INTEGER ::TEXT
=# select 123 ::T<tab>
=# select 123 ::TEXT

It might not be instinctive but would be doable by making such a
candidate list.

====
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 5f27120..179c9f0 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1322,6 +1322,8 @@ psql_completion(const char *text, int start, int end)
                else
                        matches = complete_from_variables(text, ":", "", true);
        }
+       else if (text[0] == ':' && text[1] == ':')
+               COMPLETE_WITH_QUERY("SELECT distinct('::' || typname) FROM pg_type where typname !~'^(pg)?_.*'");

/* If no previous word, suggest one of the basic sql commands */
else if (previous_words_count == 0)
====

=# select 2314 ::t<tab>
::t ::tinterval
::table_constraints ::transforms
::table_privileges ::trigger
::tables ::triggered_update_columns
::text ::triggers
::tid ::tsm_handler
::time ::tsquery
::timestamp ::tsrange
::time_stamp ::tstzrange
::timestamptz ::tsvector
::timetz ::txid_snapshot

Does this make sense?

regards,

--
Kyotaro Horiguchi
NTT Open Source Software Center

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Pavel Stehule
pavel.stehule@gmail.com
In reply to: Kyotaro HORIGUCHI (#2)
Re: proposal: psql autocomplete for casting

2016-03-03 12:06 GMT+01:00 Kyotaro HORIGUCHI <
horiguchi.kyotaro@lab.ntt.co.jp>:

Hello, I considered on this,

At Thu, 3 Mar 2016 10:05:06 +0100, Pavel Stehule <pavel.stehule@gmail.com>
wrote in <
CAFj8pRDZ456OKbpV9jDJ_VCgTWprqxYu1kQp6z_Eu_WgNvs57Q@mail.gmail.com>

We have not autocomplete for casting introduced by symbol "::". A
implementation should not be hard.

Completion needs a sequence of break characters between two
succeeding words and the break characters cannot be a part of a
word. If cast operators are allowed to be preceded by white
space, the following diff gives maybe-desired behavior.

===
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1322,6 +1322,8 @@ psql_completion(const char *text, int start, int end)
else
matches = complete_from_variables(text, ":", "",
true);
}
+       else if (text[0] == ':' && text[1] == ':')
+               COMPLETE_WITH_LIST3("::integer", "::text", "::date");

/* If no previous word, suggest one of the basic sql commands */
else if (previous_words_count == 0)
===

=# select 123 ::<tab>
::DATE ::INTEGER ::TEXT
=# select 123 ::T<tab>
=# select 123 ::TEXT

It might not be instinctive but would be doable by making such a
candidate list.

====
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 5f27120..179c9f0 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1322,6 +1322,8 @@ psql_completion(const char *text, int start, int end)
else
matches = complete_from_variables(text, ":", "",
true);
}
+       else if (text[0] == ':' && text[1] == ':')
+               COMPLETE_WITH_QUERY("SELECT distinct('::' || typname) FROM
pg_type where typname !~'^(pg)?_.*'");

/* If no previous word, suggest one of the basic sql commands */
else if (previous_words_count == 0)
====

=# select 2314 ::t<tab>
::t ::tinterval
::table_constraints ::transforms
::table_privileges ::trigger
::tables ::triggered_update_columns
::text ::triggers
::tid ::tsm_handler
::time ::tsquery
::timestamp ::tsrange
::time_stamp ::tstzrange
::timestamptz ::tsvector
::timetz ::txid_snapshot

Does this make sense?

the requirement of space before is not good :( - It should be any different
than operator chars. Not only space.

all other is perfect :)

Regards

Pavel

Show quoted text

regards,

--
Kyotaro Horiguchi
NTT Open Source Software Center

#4Kyotaro HORIGUCHI
horiguchi.kyotaro@lab.ntt.co.jp
In reply to: Pavel Stehule (#3)
1 attachment(s)
Re: proposal: psql autocomplete for casting

At Thu, 3 Mar 2016 12:15:13 +0100, Pavel Stehule <pavel.stehule@gmail.com> wrote in <CAFj8pRDB2PpESLxnwNDXmhvTS9VL0NMeAnUdv_hps9WzYwXLjw@mail.gmail.com>
pavel.stehule> 2016-03-03 12:06 GMT+01:00 Kyotaro HORIGUCHI <

the requirement of space before is not good :( - It should be any different
than operator chars. Not only space.

all other is perfect :)

Yeah, I fortunately agree with you:p

But the things are not so simple. readline can handle single
prefix characters but cannot not handle prefix strings.

The new diff adds ':' to WORD_BREAKS and adjusts related codes.
As far as I can see, colons are used only for variable prefix,
type casts and named parameter assignments in function
calls. This covers the first two and the last wouldn't be a
matter of tab-completion. This works as the following.

=# select now()::t<tab>
text trigger
tid tsm_handler
...
tinterval txid_snapshot
=# select now()::te<tab>
=# select now()::text

As an inevitable side effect, this makes completion for ": :"
with types (which results in an syntax error) but I believe it
won't be a matter.

I'm quite unpleasant that the additional conditional expressions
use bare previous_words but found no good solution.

else if (previous_words_count >= 2 &&
previous_words[1][strlen(previous_words[1])-1] == ':' &&
TailMatches1(":"))

It is good if we could limit the candidate types by knowing the
operand type but it seems a bit complicated.

Some familiar type names won't come as candidates. They are
"int", "float", "decimal", "dec", which are known only to gram.y
but it does't seem to matter, too.

Thoughts? Opinions?

regards,

--
Kyotaro Horiguchi
NTT Open Source Software Center

Attachments:

psql-complete-typecasts.patchtext/x-patch; charset=us-asciiDownload
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 5f27120..ab0e858 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -58,7 +58,7 @@ extern char *filename_completion_function();
 #endif
 
 /* word break characters */
-#define WORD_BREAKS		"\t\n@$><=;|&{() "
+#define WORD_BREAKS		"\t\n@$><=;:|&{() "
 
 /*
  * Since readline doesn't let us pass any state through to the tab completion
@@ -1312,15 +1312,23 @@ psql_completion(const char *text, int start, int end)
 	if (text[0] == '\\')
 		COMPLETE_WITH_LIST_CS(backslash_commands);
 
+	/* If current word is a typecast, handle that case */
+	else if (previous_words_count >= 2 &&
+			 previous_words[1][strlen(previous_words[1])-1] == ':' &&
+			 TailMatches1(":"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
+
 	/* If current word is a variable interpolation, handle that case */
-	else if (text[0] == ':' && text[1] != ':')
-	{
-		if (text[1] == '\'')
-			matches = complete_from_variables(text, ":'", "'", true);
-		else if (text[1] == '"')
-			matches = complete_from_variables(text, ":\"", "\"", true);
+	else if ((previous_words_count < 2 ||
+			  previous_words[1][strlen(previous_words[1])-1] != ':') &&
+			 TailMatches1(":"))
+	{
+		if (text[0] == '\'')
+			matches = complete_from_variables(text, "'", "'", true);
+		else if (text[0] == '"')
+			matches = complete_from_variables(text, "\"", "\"", true);
 		else
-			matches = complete_from_variables(text, ":", "", true);
+			matches = complete_from_variables(text, "", "", true);
 	}
 
 	/* If no previous word, suggest one of the basic sql commands */
#5Pavel Stehule
pavel.stehule@gmail.com
In reply to: Kyotaro HORIGUCHI (#4)
Re: proposal: psql autocomplete for casting

2016-03-04 5:29 GMT+01:00 Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp

:

At Thu, 3 Mar 2016 12:15:13 +0100, Pavel Stehule <pavel.stehule@gmail.com>
wrote in <
CAFj8pRDB2PpESLxnwNDXmhvTS9VL0NMeAnUdv_hps9WzYwXLjw@mail.gmail.com>
pavel.stehule> 2016-03-03 12:06 GMT+01:00 Kyotaro HORIGUCHI <

the requirement of space before is not good :( - It should be any

different

than operator chars. Not only space.

all other is perfect :)

Yeah, I fortunately agree with you:p

But the things are not so simple. readline can handle single
prefix characters but cannot not handle prefix strings.

The new diff adds ':' to WORD_BREAKS and adjusts related codes.
As far as I can see, colons are used only for variable prefix,
type casts and named parameter assignments in function
calls. This covers the first two and the last wouldn't be a
matter of tab-completion. This works as the following.

=# select now()::t<tab>
text trigger
tid tsm_handler
...
tinterval txid_snapshot
=# select now()::te<tab>
=# select now()::text

As an inevitable side effect, this makes completion for ": :"
with types (which results in an syntax error) but I believe it
won't be a matter.

I'm quite unpleasant that the additional conditional expressions
use bare previous_words but found no good solution.

else if (previous_words_count >= 2 &&
previous_words[1][strlen(previous_words[1])-1] == ':' &&
TailMatches1(":"))

It is good if we could limit the candidate types by knowing the
operand type but it seems a bit complicated.

Some familiar type names won't come as candidates. They are
"int", "float", "decimal", "dec", which are known only to gram.y
but it does't seem to matter, too.

Thoughts? Opinions?

It works. I found only one issue with multi word named types

I have not any complete option for select 1::timestamp with

maybe it is another limit of readline

Regards

Pavel

Show quoted text

regards,

--
Kyotaro Horiguchi
NTT Open Source Software Center