Skip to content
Snippets Groups Projects
Commit 7fd221da authored by David Douard's avatar David Douard
Browse files

cli/db: show the actual error that occurred during sql script execution, if any

When executing a `swh db init` command, the executed sql files for the
package may fail, but the 'swh db' tool would eat the error reported by
sqlsh. Make these errors shown as output of the process if such an error
occurred.

e.g.:

  $ swh db init test:fail

  Error during database setup
  Command '['psql', '--quiet', '--no-psqlrc', '-v', 'ON_ERROR_STOP=1', '-d', 'postgresql://postgres@127.0.0.1:24370/tests', '-f', '/venv/swh-environment/swh-core/swh/core/db/tests/data/test/fail/sql/40-funcs.sql']' returned non-zero exit status 3.
  Process output:
  psql:/venv/swh-environment/swh-core/swh/core/db/tests/data/test/fail/sql/40-funcs.sql:6: ERROR:  function public.digest(text, unknown) does not exist
  LINE 5:     select encode(public.digest($1, 'sha1'), 'hex')
                          ^
  HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

  Aborted!
parent 0570b278
No related branches found
No related tags found
1 merge request!399cli/db: show the actual error that occurred during sql script execution, if any
Pipeline #11882 passed
......@@ -6,6 +6,7 @@
import logging
from os import environ
from subprocess import CalledProcessError
from typing import Any, Dict, List, Optional, Tuple
import warnings
......@@ -340,9 +341,17 @@ def initialize_one(package, module, backend_class, flavor, dbname, cfg):
logger.debug("db_init %s flavor=%s dbname=%s", module, flavor, dbname)
dbmodule = f"{package}:{cfg['cls']}"
initialized, dbversion, dbflavor = populate_database_for_package(
dbmodule, dbname, flavor
)
try:
initialized, dbversion, dbflavor = populate_database_for_package(
dbmodule, dbname, flavor
)
except CalledProcessError as exc:
click.secho("Error during database setup", fg="red", bold=True)
click.echo(str(exc))
click.echo("Process output:")
click.echo(exc.stderr)
raise click.Abort()
if dbversion is not None:
click.secho(
"ERROR: the database version has been populated by sql init scripts. "
......
......@@ -23,3 +23,6 @@ test:
will define 2 'swh.core.db' powered backends initialized from (resp.)
'./postgresql/sql' and './cli2/sql'.
The 'test:fail' backend is expected to fail when trying to initialize the
database (missing the pgcrypto extension, so the psql execution should fail).
-- origin table
create table if not exists origin (
id bigserial not null,
url text not null,
hash text not null
);
create or replace function hash_sha1(text)
returns text
language sql strict immutable
as $$
select encode(public.digest($1, 'sha1'), 'hex')
$$;
......@@ -3,8 +3,6 @@
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
from subprocess import CalledProcessError
import pytest
from pytest_postgresql import factories
import yaml
......@@ -117,8 +115,7 @@ def test_cli_swh_db_initialization_fail_without_creation_first(
result = cli_runner.invoke(swhdb, ["init", module_name, "--dbname", conninfo])
# Fails because we cannot connect to an inexisting db
assert result.exit_code == 1, f"Unexpected output: {result.output}"
assert isinstance(result.exception, CalledProcessError)
assert b'FATAL: database "inexisting-db" does not exist' in result.exception.stderr
assert 'FATAL: database "inexisting-db" does not exist' in result.output
def test_cli_swh_db_initialization_fail_without_extension(
......@@ -136,10 +133,8 @@ def test_cli_swh_db_initialization_fail_without_extension(
# Fails as the function `public.digest` is not installed, init-admin calls is needed
# first (the next tests show such behavior)
assert result.exit_code == 1, f"Unexpected output: {result.output}"
assert isinstance(result.exception, CalledProcessError)
assert (
b"ERROR: function public.digest(text, unknown) does not exist"
in result.exception.stderr
"ERROR: function public.digest(text, unknown) does not exist" in result.output
)
......@@ -263,6 +258,30 @@ def test_cli_swh_db_create_and_init_db_new_api(
assert len(origins) == 1
def test_cli_swh_db_init_report_sqlsh_error(
cli_runner,
postgresql,
mock_get_entry_points,
mocker,
tmp_path,
):
"""Create a db then initializing it should be ok for a "new style" datastore"""
module_name = "test:fail"
conninfo = craft_conninfo(postgresql)
# This initializes the schema and data
result = cli_runner.invoke(swhdb, ["init-admin", module_name, "--dbname", conninfo])
assert_result(result)
result = cli_runner.invoke(swhdb, ["init", module_name, "--dbname", conninfo])
assert result.exit_code == 1
assert (
"test/fail/sql/40-funcs.sql:6: "
"ERROR: function public.digest(text, unknown) does not exist"
) in result.output
@pytest.mark.init_version(version=2)
def test_cli_swh_db_upgrade_new_api(
request,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment