Repository: opendatacube/datacube-core

Issue:
Error running `datacube system init --no-init-users`
### Expected behaviour

`datacube system init --no-init-users` should initialise a new ODC database schema without creating any PostgreSQL roles. It should be able to run as a non superuser postgresql role.


### Actual behaviour

<summary>

Error when running  `datacube system init --no-init-users`

<details>

```console
$ datacube system init --no-init-users 
Initialising database...
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
    self.dialect.do_execute(
  File "/usr/local/lib/python3.10/dist-packages/sqlalchemy/engine/default.py", line 736, in do_execute
    cursor.execute(statement, parameters)
psycopg2.errors.InvalidSchemaName: schema "agdc" does not exist


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/bin/datacube", line 8, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/datacube/ui/click.py", line 200, in new_func
    return f(parsed_config, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/datacube/ui/click.py", line 232, in with_index
    return f(index, *args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/datacube/scripts/system.py", line 52, in database_init
    was_created = index.init_db(with_default_types=default_types,
  File "/usr/local/lib/python3.10/dist-packages/datacube/index/postgres/index.py", line 86, in init_db
    is_new = self._db.init(with_permissions=with_permissions)
  File "/usr/local/lib/python3.10/dist-packages/datacube/drivers/postgres/_connections.py", line 205, in init
    _core.update_schema(self._engine)
  File "/usr/local/lib/python3.10/dist-packages/datacube/drivers/postgres/_core.py", line 199, in update_schema
    install_timestamp_trigger(connection)
  File "/usr/local/lib/python3.10/dist-packages/datacube/drivers/postgres/_core.py", line 49, in install_timestamp_trigger
    connection.execute(text(UPDATE_TIMESTAMP_SQL))
  File "/usr/local/lib/python3.10/dist-packages/sqlalchemy/engine/base.py", line 1385, in execute
    return meth(self, multiparams, params, _EMPTY_EXECUTION_OPTS)
  File "/usr/local/lib/python3.10/dist-packages/sqlalchemy/sql/elements.py", line 334, in _execute_on_connection
    return connection._execute_clauseelement(
  File "/usr/local/lib/python3.10/dist-packages/sqlalchemy/engine/base.py", line 1577, in _execute_clauseelement
    ret = self._execute_context(
  File "/usr/local/lib/python3.10/dist-packages/sqlalchemy/engine/base.py", line 1953, in _execute_context
    self._handle_dbapi_exception(
  File "/usr/local/lib/python3.10/dist-packages/sqlalchemy/engine/base.py", line 2134, in _handle_dbapi_exception
    util.raise_(
  File "/usr/local/lib/python3.10/dist-packages/sqlalchemy/util/compat.py", line 211, in raise_
    raise exception
  File "/usr/local/lib/python3.10/dist-packages/sqlalchemy/engine/base.py", line 1910, in _execute_context
    self.dialect.do_execute(
  File "/usr/local/lib/python3.10/dist-packages/sqlalchemy/engine/default.py", line 736, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.InvalidSchemaName) schema "agdc" does not exist

[SQL: 
create or replace function agdc.set_row_update_time()
returns trigger as $$
begin
  new.updated = now();
  return new;
end;
$$ language plpgsql;
]
(Background on this error at: https://sqlalche.me/e/14/f405)
```

</summary>
</details>


### Environment information

* Which ``datacube --version`` are you using? 
**1.8.16**

* What datacube deployment/enviornment are you running against? 
**Inside a new docker image based on `ghcr.io/osgeo/gdal:ubuntu-small-3.7.2`, which is based on Ubuntu LTS 22.04**





Discussion:
It seems that #1476 moved the logic to create the schema if it doesn't exist, such that it now only executes if user roles and grants are included, and only in the postgres driver. So this command should execute correctly with postgis.
@SpacemanPaul any reason for this change or was it made in error?

Resolving patch:
diff --git a/datacube/drivers/postgres/_core.py b/datacube/drivers/postgres/_core.py
--- a/datacube/drivers/postgres/_core.py
+++ b/datacube/drivers/postgres/_core.py
@@ -96,29 +96,30 @@ def ensure_db(engine, with_permissions=True):
         c.execute(text("""
         grant all on database {db} to agdc_admin;
         """.format(db=quoted_db_name)))
-        if not has_schema(engine):
-            is_new = True
-            try:
-                sqla_txn = c.begin()
-                if with_permissions:
-                    # Switch to 'agdc_admin', so that all items are owned by them.
-                    c.execute(text('set role agdc_admin'))
-                _LOG.info('Creating schema.')
-                c.execute(CreateSchema(SCHEMA_NAME, if_not_exists=True))
-                _LOG.info('Creating tables.')
-                c.execute(text(TYPES_INIT_SQL))
-                METADATA.create_all(c)
-                _LOG.info("Creating triggers.")
-                install_timestamp_trigger(c)
-                _LOG.info("Creating added column.")
-                install_added_column(c)
-                sqla_txn.commit()
-            except:  # noqa: E722
-                sqla_txn.rollback()
-                raise
-            finally:
-                if with_permissions:
-                    c.execute(text('set role {}'.format(quoted_user)))
+
+    if not has_schema(engine):
+        is_new = True
+        try:
+            sqla_txn = c.begin()
+            if with_permissions:
+                # Switch to 'agdc_admin', so that all items are owned by them.
+                c.execute(text('set role agdc_admin'))
+            _LOG.info('Creating schema.')
+            c.execute(CreateSchema(SCHEMA_NAME, if_not_exists=True))
+            _LOG.info('Creating tables.')
+            c.execute(text(TYPES_INIT_SQL))
+            METADATA.create_all(c)
+            _LOG.info("Creating triggers.")
+            install_timestamp_trigger(c)
+            _LOG.info("Creating added column.")
+            install_added_column(c)
+            sqla_txn.commit()
+        except:  # noqa: E722
+            sqla_txn.rollback()
+            raise
+        finally:
+            if with_permissions:
+                c.execute(text('set role {}'.format(quoted_user)))
 
     if with_permissions:
         _LOG.info('Adding role grants.')


Test patch: