Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow defining a json file with preferred aliases #1382

Merged
merged 9 commits into from
Oct 6, 2023
Merged

Conversation

rob-b
Copy link
Contributor

@rob-b rob-b commented Nov 11, 2022

Description

At $WORK we have a lot of tables with names like foo_noun_verb or foo_noun_related-noun_verb and so while the default aliasing is very helpful for shortening unwieldy names we do end up with lots of aliases like LEFT JOIN fnv on fnv2.id = fnv.fnv2_id

This change will allow defining a json file of preferred aliases

> cat ~/.config/pgcli/aliases.json
{
    "foo_user": "user",
    "foo_user_group": "user_group"
}

so the alias suggestion for SELECT * FROM foo_user will be SELECT * FROM foo_user AS user instead of the default SELECT * FROM foo_user AS fu

Checklist

  • I've added this contribution to the changelog.rst.
  • I've added my name to the AUTHORS file (or it's already there).
  • I installed pre-commit hooks (pip install pre-commit && pre-commit install), and ran black on my code.
  • Please squash merge this pull request (uncheck if you'd like us to merge as multiple commits)

@rob-b rob-b force-pushed the main branch 2 times, most recently from fb73175 to 9a086ef Compare November 11, 2022 11:48
@rob-b rob-b marked this pull request as ready for review November 11, 2022 11:49
Comment on lines 108 to 111
alias_map_file = settings.get("alias_map_file")
if alias_map_file is not None:
with open(alias_map_file) as fo:
self.alias_map = json.load(fo)
Copy link
Contributor Author

@rob-b rob-b Nov 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to flag this part as I wasn't sure of what approaches here fit the project goals

  1. If the file doesn't exist what should I do? Allow the crash or just handle it silently and set the map to None?
  2. is loading the file in the constructor a good idea? I tend not to do IO in constructors normally but since theoretically the alias file could be quite large I thought slow startup was better than a slow first query. Maintainers might think the opposite

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. If someone specified a file in the config, and it doesn't exist, it should be an error. We can assume that the user wanted the file to be picked up, and so the user will be interested in fixing the path.
  2. How large is "quite large"? Did you do any benchmarks with your file? If you think it's worth the effort, you could run a background thread to load these aliases, like the completion refresher does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed a new version that wraps loading/decoding into a helper function and raises an informative error if the map_file cannot be read

My personal alias file is tiny - 5 aliases and the whole file is ~220 bytes - and so for myself at least loading is fast

In [1]: from pgcli.pgcompleter import load_alias_map_file

In [2]: from pgcli import config

In [3]: import timeit

In [4]: map_file = config.get_config()["main"]["alias_map_file"]

In [5]: t = timeit.Timer(lambda: load_alias_map_file(map_file))

In [6]: t.timeit(10_000)
Out[6]: 0.15082729199999534

I tried upping the alias file to 1000 aliases and it's still pretty fast

In [9]: t = timeit.Timer(lambda: load_alias_map_file(map_file))

In [10]: t.timeit(10_000)
Out[10]: 1.3473110840000118

How large is "quite large"?

For my own usage I can't see the file getting bigger than 200 lines (we have ~ 120 tables in prod) which is 8kb and quick to load

In [8]: t.timeit(10_000)
Out[8]: 0.3809067500000083

my caution was purely down to experience of users always doing something surprising and using features in unexpected ways.

I don't think that loading the aliases would need to be performed in a background thread

@codecov-commenter
Copy link

codecov-commenter commented Nov 11, 2022

Codecov Report

Base: 84.15% // Head: 80.14% // Decreases project coverage by -4.00% ⚠️

Coverage data is based on head (d30e5dc) compared to base (6884c29).
Patch coverage: 49.63% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1382      +/-   ##
==========================================
- Coverage   84.15%   80.14%   -4.01%     
==========================================
  Files          21       23       +2     
  Lines        2720     2166     -554     
==========================================
- Hits         2289     1736     -553     
+ Misses        431      430       -1     
Impacted Files Coverage Δ
pgcli/magic.py 0.00% <0.00%> (ø)
pgcli/packages/parseutils/tables.py 97.67% <ø> (ø)
pgcli/packages/sqlcompletion.py 97.67% <ø> (ø)
pgcli/pgstyle.py 64.00% <ø> (ø)
pgcli/pgtoolbar.py 31.57% <0.00%> (+0.15%) ⬆️
pgcli/pyev.py 15.38% <15.38%> (ø)
pgcli/explain_output_formatter.py 46.15% <46.15%> (ø)
pgcli/key_bindings.py 52.94% <66.66%> (-0.19%) ⬇️
pgcli/pgbuffer.py 67.85% <66.66%> (+1.19%) ⬆️
pgcli/pgexecute.py 83.22% <87.14%> (+2.86%) ⬆️
... and 11 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

pgcli/pgclirc Outdated
# "some_table_name": "desired_alias",
# "some_other_table_name": "another_alias"
# }
alias_map_file = ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
alias_map_file = ""
alias_map_file =

@@ -61,18 +62,38 @@ def Candidate(
normalize_ref = lambda ref: ref if ref[0] == '"' else '"' + ref.lower() + '"'


def generate_alias(tbl):
def generate_alias(tbl, alias_map=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we have no tests for this functions. I'd add one, especially now that the behavior is getting more complicated.

@rob-b
Copy link
Contributor Author

rob-b commented Nov 15, 2022

@j-bennet is there a way I can get codecov to re-run? It's reporting based on the first version of this PR and I'd be interested to see if the additional tests I've written have moved the number

@j-bennet
Copy link
Contributor

@rob-b I actually don't know how to bump codecov to recalculate, but I wouldn't worry about coverage report, it's not that important. Can you add your name to AUTHORS file? Otherwise I think the PR is good to merge.

@rob-b rob-b force-pushed the main branch 6 times, most recently from 73cd0ee to e50eeee Compare November 23, 2022 15:26
andyscho and others added 7 commits November 23, 2022 15:30
At $WORK we have a lot of tables with names like `foo_noun_verb` or
`foo_noun_related-noun_verb` and so while the default aliasing is very
helpful for shortening unwieldy names we do end up with lots of aliases
like `LEFT JOIN fnv on fnv2.id = fnv.fnv2_id`

This change will allow defining a json file of preferred aliases

```
> cat ~/.config/pgcli/aliases.json
{
    "foo_user": "user",
    "foo_user_group": "user_group"
}
```

so the alias suggestion for `SELECT * FROM foo_user` will be `SELECT * FROM foo_user AS user`
instead of the default `SELECT * FROM foo_user AS fu`
Raise a (hopefully) helpful exception when the alias_map_file cannot be
parsed or does not exist
Discussed this on the PR with a project maintainer
@j-bennet j-bennet merged commit 97a1fd6 into dbcli:main Oct 6, 2023
6 of 7 checks passed
@j-bennet
Copy link
Contributor

j-bennet commented Oct 6, 2023

@rob-b Sorry this took forever, it got lost from my radar. Thank you for the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants