diff options
-rw-r--r-- | pgcli/packages/parseutils.py | 33 | ||||
-rw-r--r-- | tests/test_smart_completion_multiple_schemata.py | 31 | ||||
-rw-r--r-- | tests/test_smart_completion_public_schema_only.py | 31 |
3 files changed, 86 insertions, 9 deletions
diff --git a/pgcli/packages/parseutils.py b/pgcli/packages/parseutils.py index fd78eec3..d099c02f 100644 --- a/pgcli/packages/parseutils.py +++ b/pgcli/packages/parseutils.py @@ -125,6 +125,28 @@ def extract_from_part(parsed, stop_at_punctuation=True): def extract_table_identifiers(token_stream, allow_functions=True): """yields tuples of TableReference namedtuples""" + # We need to do some massaging of the names because postgres is case- + # insensitive and '"Foo"' is not the same table as 'Foo' (while 'foo' is) + def getnames(item): + name = item.get_real_name() + schema_name = item.get_parent_name() + alias = item.get_alias() + if not name: + schema_name = None + name = item.get_name() + alias = alias or name + schemaisquoted = schema_name and item.value[0] == '"' + if schema_name and not schemaisquoted: + schema_name = schema_name.lower() + quotecount = item.value.count('"') + nameisquoted = quotecount > 2 or (quotecount and not schemaisquoted) + if name and not nameisquoted and name != name.lower(): + if not alias: + alias = name + name = name.lower() + return schema_name, name, alias + + for item in token_stream: if isinstance(item, IdentifierList): for identifier in item.get_identifiers(): @@ -141,17 +163,10 @@ def extract_table_identifiers(token_stream, allow_functions=True): yield TableReference(schema_name, real_name, identifier.get_alias(), is_function) elif isinstance(item, Identifier): - real_name = item.get_real_name() - schema_name = item.get_parent_name() + schema_name, real_name, alias = getnames(item) is_function = allow_functions and _identifier_is_function(item) - if real_name: - yield TableReference(schema_name, real_name, item.get_alias(), - is_function) - else: - name = item.get_name() - yield TableReference(None, name, item.get_alias() or name, - is_function) + yield TableReference(schema_name, real_name, alias, is_function) elif isinstance(item, Function): yield TableReference(None, item.get_real_name(), item.get_alias(), allow_functions) diff --git a/tests/test_smart_completion_multiple_schemata.py b/tests/test_smart_completion_multiple_schemata.py index fbe79ac0..a7eb7834 100644 --- a/tests/test_smart_completion_multiple_schemata.py +++ b/tests/test_smart_completion_multiple_schemata.py @@ -13,6 +13,7 @@ metadata = { }, 'custom': { 'users': ['id', 'phone_number'], + 'Users': ['userid', 'username'], 'products': ['id', 'product_name', 'price'], 'shipments': ['id', 'address', 'user_id'] }}, @@ -185,6 +186,7 @@ def test_suggested_table_names_with_schema_dot(completer, complete_event, assert set(result) == set([ Completion(text='func3', start_position=start_pos, display_meta='function'), Completion(text='users', start_position=start_pos, display_meta='table'), + Completion(text='"Users"', start_position=start_pos, display_meta='table'), Completion(text='products', start_position=start_pos, display_meta='table'), Completion(text='shipments', start_position=start_pos, display_meta='table'), Completion(text='set_returning_func', start_position=start_pos, display_meta='function'), @@ -309,6 +311,7 @@ def test_schema_qualified_type_name(text, completer, complete_event): Completion(text='typ3', display_meta='datatype'), Completion(text='typ4', display_meta='datatype'), Completion(text='users', display_meta='table'), + Completion(text='"Users"', display_meta='table'), Completion(text='products', display_meta='table'), Completion(text='shipments', display_meta='table'), ]) @@ -390,3 +393,31 @@ def test_wildcard_column_expansion_with_two_tables_and_parent(completer, complet display='*', display_meta='columns')] assert expected == completions + +@pytest.mark.parametrize('text', [ + 'SELECT U. FROM custom.Users U', + 'SELECT U. FROM custom.USERS U', + 'SELECT U. FROM custom.users U', + 'SELECT U. FROM "custom".Users U', + 'SELECT U. FROM "custom".USERS U', + 'SELECT U. FROM "custom".users U' +]) +def test_suggest_columns_from_unquoted_table(completer, complete_event, text): + pos = len('SELECT U.') + result = completer.get_completions(Document(text=text, cursor_position=pos), + complete_event) + assert set(result) == set([ + Completion(text='id', start_position=0, display_meta='column'), + Completion(text='phone_number', start_position=0, display_meta='column')]) + +@pytest.mark.parametrize('text', [ + 'SELECT U. FROM custom."Users" U', + 'SELECT U. FROM "custom"."Users" U' +]) +def test_suggest_columns_from_quoted_table(completer, complete_event, text): + pos = len('SELECT U.') + result = completer.get_completions(Document(text=text, cursor_position=pos), + complete_event) + assert set(result) == set([ + Completion(text='userid', start_position=0, display_meta='column'), + Completion(text='username', start_position=0, display_meta='column')]) diff --git a/tests/test_smart_completion_public_schema_only.py b/tests/test_smart_completion_public_schema_only.py index cbd0d96b..4dd1127c 100644 --- a/tests/test_smart_completion_public_schema_only.py +++ b/tests/test_smart_completion_public_schema_only.py @@ -7,6 +7,7 @@ from pgcli.packages.function_metadata import FunctionMetadata metadata = { 'tables': { 'users': ['id', 'email', 'first_name', 'last_name'], + 'Users': ['userid', 'username'], 'orders': ['id', 'ordered_date', 'status', 'email'], 'select': ['id', 'insert', 'ABC']}, 'views': { @@ -92,6 +93,7 @@ def test_schema_or_visible_table_completion(completer, complete_event): assert set(result) == set([ Completion(text='public', start_position=0, display_meta='schema'), Completion(text='users', start_position=0, display_meta='table'), + Completion(text='"Users"', start_position=0, display_meta='table'), Completion(text='"select"', start_position=0, display_meta='table'), Completion(text='orders', start_position=0, display_meta='table'), Completion(text='user_emails', start_position=0, display_meta='view'), @@ -374,6 +376,7 @@ def test_table_names_after_from(completer, complete_event): assert set(result) == set([ Completion(text='public', start_position=0, display_meta='schema'), Completion(text='users', start_position=0, display_meta='table'), + Completion(text='"Users"', start_position=0, display_meta='table'), Completion(text='orders', start_position=0, display_meta='table'), Completion(text='"select"', start_position=0, display_meta='table'), Completion(text='user_emails', start_position=0, display_meta='view'), @@ -389,6 +392,7 @@ def test_table_names_after_from_are_lexical_ordered_by_text(completer, complete_ Document(text=text, cursor_position=position), complete_event) assert [c.text for c in result] == [ + '"Users"', 'custom_func1', 'custom_func2', 'orders', @@ -443,6 +447,7 @@ def test_suggest_datatype(text, completer, complete_event): Completion(text='custom_type2', start_position=0, display_meta='datatype'), Completion(text='public', start_position=0, display_meta='schema'), Completion(text='users', start_position=0, display_meta='table'), + Completion(text='"Users"', start_position=0, display_meta='table'), Completion(text='orders', start_position=0, display_meta='table'), Completion(text='"select"', start_position=0, display_meta='table')] + list(map(lambda f: Completion(f, display_meta='datatype'), completer.datatypes))) @@ -612,3 +617,29 @@ def test_wildcard_column_expansion_with_two_tables_and_parent(completer, complet display='*', display_meta='columns')] assert expected == completions + + +@pytest.mark.parametrize('text', [ + 'SELECT U. FROM Users U', + 'SELECT U. FROM USERS U', + 'SELECT U. FROM users U' +]) +def test_suggest_columns_from_unquoted_table(completer, complete_event, text): + pos = len('SELECT U.') + result = completer.get_completions(Document(text=text, cursor_position=pos), + complete_event) + assert set(result) == set([ + Completion(text='id', start_position=0, display_meta='column'), + Completion(text='email', start_position=0, display_meta='column'), + Completion(text='first_name', start_position=0, display_meta='column'), + Completion(text='last_name', start_position=0, display_meta='column')]) + + +def test_suggest_columns_from_quoted_table(completer, complete_event): + text = 'SELECT U. FROM "Users" U' + pos = len('SELECT U.') + result = completer.get_completions(Document(text=text, cursor_position=pos), + complete_event) + assert set(result) == set([ + Completion(text='userid', start_position=0, display_meta='column'), + Completion(text='username', start_position=0, display_meta='column')]) |