Repository: dbcli/litecli

Issue:
Autocompleting tables and columns that are all caps should not add backticks
Autocompleting tables and columns that are all caps adds backticks around the names. For example, completing a table named `BAR` adds backticks around this and completes to "\`BAR\`". (I can't format it correctly on GitHub. See the screen shots below).

Here's an example schema:

```
test.sqlite> .schema
+-----------------------------------------------------+
| sql                                                 |
+-----------------------------------------------------+
| CREATE TABLE BAR (PK integer primary key, BAR text) |
| CREATE TABLE foo (pk integer primary key, foo text) |
+-----------------------------------------------------+
```

The `foo` table completion works as expected:

<img width="697" alt="foo completion" src="https://github.com/user-attachments/assets/776dab9f-18f0-4bf5-8044-3773da779339">

However, the `BAR` table completion adds unnecessary backticks:

<img width="697" alt="BAR completion" src="https://github.com/user-attachments/assets/11395241-e3ba-402d-b9ec-d9d495274044">

For schemas that use all caps for all tables and columns, this adds a lot of unnecessary noise when typing queries. I don't think this should be adding quotes at all. At the least, it would be great to have an option to disable this behavior.

This is on:

```
LiteCli: 1.12.3 (SQLite: 3.46.1)
```

Discussion:
@kracekumar: I can reproduce this in the latest version and in Mac OSX.

```sql
:memory> create table BAR(PK integer primary key, BAR text);
Query OK
Time: 0.002s
:memory> select * from `BAR`;
0 rows in set
Time: 0.000s
:memory> insert into `BAR` values(1, "öne");
Query OK, 1 row affected
Time: 0.001s
:memory> insert into `BAR` values(2, "two");
Query OK, 1 row affected
Time: 0.001s
:memory> select * from `BAR`;
+----+-----+
| PK | BAR |
+----+-----+
| 1  | öne |
| 2  | two |
+----+-----+
2 rows in set
Time: 0.004s
:memory>
Goodbye!
```
Even though it causes unease while viewing the autocomplete, the query works with back tick. 

Let me dig more to see why this is needed.

Solution patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3685c5d..c75374f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@
 ### Bug Fixes
 
 * Fix a bug where the `\llm` command on alternate invocations weren't detected correctly. (#211)
+* Do not escape upper table or column name. [(#185)](https://github.com/dbcli/litecli/issues/185)
 
 ### Internal
 
diff --git a/litecli/sqlcompleter.py b/litecli/sqlcompleter.py
index a8a5a1e..1309f9b 100644
--- a/litecli/sqlcompleter.py
+++ b/litecli/sqlcompleter.py
@@ -258,7 +258,7 @@ def __init__(self, supported_formats=(), keyword_casing="auto"):
         self.reserved_words = set()
         for x in self.keywords:
             self.reserved_words.update(x.split())
-        self.name_pattern = compile(r"^[_a-z][_a-z0-9\$]*$")
+        self.name_pattern = compile(r"^[_a-zA-Z][_a-zA-Z0-9\$]*$")
 
         self.special_commands = []
         self.table_formats = supported_formats


Test patch:
diff --git a/tests/test_smart_completion_public_schema_only.py b/tests/test_smart_completion_public_schema_only.py
index 6134ff3..45909a8 100644
--- a/tests/test_smart_completion_public_schema_only.py
+++ b/tests/test_smart_completion_public_schema_only.py
@@ -40,6 +40,18 @@ def complete_event():
     return Mock()
 
 
+def test_escape_name(completer):
+
+    for name, expected_name in [# Upper case name shouldn't be escaped
+        ("BAR", "BAR"),
+        # This name is escaped and should start with back tick
+        ("2025todos", "`2025todos`"),
+        # normal case
+        ("people", "people"),
+        # table name with _underscore should not be escaped
+        ("django_users", "django_users")]:
+        assert completer.escape_name(name) == expected_name
+
 def test_empty_string_completion(completer, complete_event):
     text = ""
     position = 0
@@ -302,7 +314,7 @@ def test_auto_escaped_col_names(completer, complete_event):
     result = list(completer.get_completions(Document(text=text, cursor_position=position), complete_event))
     assert result == [
         Completion(text="*", start_position=0),
-        Completion(text="`ABC`", start_position=0),
+        Completion(text="ABC", start_position=0),
         Completion(text="`insert`", start_position=0),
         Completion(text="id", start_position=0),
     ] + list(map(Completion, completer.functions)) + [Completion(text="select", start_position=0)] + list(
@@ -317,7 +329,7 @@ def test_un_escaped_table_names(completer, complete_event):
     assert result == list(
         [
             Completion(text="*", start_position=0),
-            Completion(text="`ABC`", start_position=0),
+            Completion(text="ABC", start_position=0),
             Completion(text="`insert`", start_position=0),
             Completion(text="id", start_position=0),
         ]