diff --git a/README.md b/README.md
index 9b830c1..4d56aca 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@ and provides helpers to run (and replay) migrations until it works.
* [Command ``upgrade`` (BETA)](#command-upgrade)
* [Command ``generate-module-analysis`` (BETA)](#command-generate-module-analysis)
* [Command ``estimate-workload`` (BETA)](#command-estimate-workload)
+ * [Command ``psql``](#command-psql)
@@ -365,3 +366,72 @@ the work to do for the migration.
renaming or merging of modules)
- check that the analysis and migration have been done for the official
modules present in odoo/odoo
+
+
+
+## Command: ``psql``
+
+**Prerequites:** init
+
+```
+odoo-openupgrade-wizard psql
+ --database DB_NAME
+ --command "SQL_REQUEST"
+```
+
+Execute an SQL Request on the target database.
+
+**Optional arguments**
+
+* If no ``database`` is provided, default ``postgres`` database will be used. exemple:
+
+```
+odoo-openupgrade-wizard psql --command "\l";
+```
+Result:
+```
+ List of databases
+ Name | Owner | Encoding | Collate | Ctype | Access privileges
+------------+-------+----------+------------+------------+-------------------
+ postgres | odoo | UTF8 | en_US.utf8 | en_US.utf8 |
+ template0 | odoo | UTF8 | en_US.utf8 | en_US.utf8 | =c/odoo +
+ | | | | | odoo=CTc/odoo
+ template1 | odoo | UTF8 | en_US.utf8 | en_US.utf8 | =c/odoo +
+ | | | | | odoo=CTc/odoo
+ test_psql | odoo | UTF8 | en_US.utf8 | en_US.utf8 |
+
+```
+
+* if you execute request that return long result, you can choose to select ``pager`` or ``-no-pager``
+ option to display the result via the click function ``echo_via_pager``.
+ (see : https://click.palletsprojects.com/en/8.1.x/utils/#pager-support)
+
+Note : Pager is enabled by default.
+
+
+* you can pass extra psql arguments inline.
+
+```
+odoo-openupgrade-wizard psql
+ --database=test_psql
+ --command "select id, name from res_partner where name ilike '%admin%';"
+ -H
+```
+Result:
+```
+
+
+ | id |
+ name |
+
+
+ | 3 |
+ Administrator |
+
+
+(1 row)
+
+
+```
+
+See all the options here https://www.postgresql.org/docs/current/app-psql.html
diff --git a/odoo_openupgrade_wizard/cli/cli.py b/odoo_openupgrade_wizard/cli/cli.py
index 9ada813..6677acb 100644
--- a/odoo_openupgrade_wizard/cli/cli.py
+++ b/odoo_openupgrade_wizard/cli/cli.py
@@ -24,6 +24,7 @@ from odoo_openupgrade_wizard.cli.cli_generate_module_analysis import (
from odoo_openupgrade_wizard.cli.cli_get_code import get_code
from odoo_openupgrade_wizard.cli.cli_init import init
from odoo_openupgrade_wizard.cli.cli_install_from_csv import install_from_csv
+from odoo_openupgrade_wizard.cli.cli_psql import psql
from odoo_openupgrade_wizard.cli.cli_pull_submodule import pull_submodule
from odoo_openupgrade_wizard.cli.cli_run import run
from odoo_openupgrade_wizard.cli.cli_upgrade import upgrade
@@ -113,6 +114,7 @@ main.add_command(generate_module_analysis)
main.add_command(get_code)
main.add_command(init)
main.add_command(install_from_csv)
+main.add_command(psql)
main.add_command(pull_submodule)
main.add_command(run)
main.add_command(upgrade)
diff --git a/odoo_openupgrade_wizard/cli/cli_psql.py b/odoo_openupgrade_wizard/cli/cli_psql.py
new file mode 100644
index 0000000..1b4b423
--- /dev/null
+++ b/odoo_openupgrade_wizard/cli/cli_psql.py
@@ -0,0 +1,21 @@
+import click
+
+from odoo_openupgrade_wizard.cli.cli_options import database_option
+from odoo_openupgrade_wizard.tools.tools_postgres import execute_psql_command
+
+
+@click.command(context_settings={"ignore_unknown_options": True})
+@database_option
+@click.option("-c", "--command", "request")
+@click.option("--pager/--no-pager", default=True)
+@click.argument("psql_args", nargs=-1, type=click.UNPROCESSED)
+@click.pass_context
+def psql(ctx, request, database, pager, psql_args):
+ """Run psql in the postgres container. Fill any parameters of psql
+ as PSQLARGS.
+ """
+ result = execute_psql_command(ctx, request, database, psql_args)
+ if pager:
+ click.echo_via_pager(result)
+ else:
+ click.echo(result)
diff --git a/odoo_openupgrade_wizard/tools/tools_postgres.py b/odoo_openupgrade_wizard/tools/tools_postgres.py
index 34da7d3..819a236 100644
--- a/odoo_openupgrade_wizard/tools/tools_postgres.py
+++ b/odoo_openupgrade_wizard/tools/tools_postgres.py
@@ -104,21 +104,9 @@ def execute_sql_file(ctx, database, sql_file):
def execute_sql_request(ctx, request, database="postgres"):
- container = get_postgres_container(ctx)
- command = (
- "psql"
- " --username=odoo"
- " --dbname={database}"
- " --tuples-only"
- ' --command "{request}"'
- ).format(database=database, request=request)
- logger.debug(
- "Executing the following command in postgres container"
- " on database %s \n %s" % (database, request)
- )
- docker_result = exec_container(container, command)
-
- lines = docker_result.output.decode("utf-8").split("\n")
+ psql_args = ("--tuples-only",)
+ output = execute_psql_command(ctx, request, database, psql_args)
+ lines = output.split("\n")
result = []
for line in lines:
if not line:
@@ -127,6 +115,26 @@ def execute_sql_request(ctx, request, database="postgres"):
return result
+def execute_psql_command(
+ ctx, request: str, database: str = None, psql_args: tuple = ()
+):
+ """Execute psql request in postgres container with psql_args on database"""
+ container = get_postgres_container(ctx)
+ command = (
+ "psql"
+ " --username=odoo"
+ f" --dbname={database or 'postgres'}"
+ f' --command "{request}"'
+ f" {' '.join(psql_args)}"
+ )
+ logger.debug(
+ "Executing the following command in postgres container\n"
+ "%s" % (command)
+ )
+ docker_result = exec_container(container, command)
+ return docker_result.output.decode("utf-8")
+
+
def ensure_database(ctx, database: str, state="present"):
"""
- Connect to postgres container.
diff --git a/tests/cli_30_psql_test.py b/tests/cli_30_psql_test.py
new file mode 100644
index 0000000..bc32b60
--- /dev/null
+++ b/tests/cli_30_psql_test.py
@@ -0,0 +1,73 @@
+from pytest import raises
+
+from odoo_openupgrade_wizard.tools.tools_postgres import (
+ ensure_database,
+ execute_psql_command,
+)
+
+from . import (
+ build_ctx_from_config_file,
+ cli_runner_invoke,
+ move_to_test_folder,
+)
+
+
+def test_cli_psql():
+ move_to_test_folder()
+ ctx = build_ctx_from_config_file()
+
+ db_name = "database_test_cli___psql"
+ ensure_database(ctx, db_name, state="absent")
+
+ # initialize database
+ cli_runner_invoke(
+ [
+ "--log-level=DEBUG",
+ "run",
+ "--step=1",
+ "--database=%s" % db_name,
+ "--init-modules=base",
+ "--stop-after-init",
+ ],
+ )
+
+ # Test requests from lib
+ request = (
+ "SELECT name"
+ " FROM ir_module_module"
+ " WHERE state ='installed'"
+ " AND name='base';"
+ )
+ output = execute_psql_command(
+ ctx,
+ request,
+ database=db_name,
+ psql_args=("--tuples-only",),
+ )
+ assert output.strip() == "base"
+
+ # test via cli ok
+ cli_runner_invoke(
+ [
+ "--log-level=DEBUG",
+ "psql",
+ "--database=%s" % db_name,
+ '--command "%s"' % request,
+ "--no-pager",
+ "--tuples-only",
+ ],
+ )
+
+ # test that cli fails with wrong parameters
+ with raises(Exception):
+ cli_runner_invoke(
+ [
+ "--log-level=DEBUG",
+ "psql",
+ "--database=%s" % db_name,
+ '--command "%s"' % request,
+ "--no-pager",
+ "--tuples-only",
+ "---unkwon-argument",
+ ],
+ )