diff -r ea836c4f7341 -r 1d2538a1ba8f src/server/plugins/postgresql/config.c --- a/src/server/plugins/postgresql/config.c Thu Aug 11 20:21:13 2022 +0200 +++ b/src/server/plugins/postgresql/config.c Thu Aug 11 20:51:39 2022 +0200 @@ -30,7 +30,52 @@ #include "../../util/util.h" -PgRepository* pg_init_repo(pool_handle_t *pool, WSConfigNode *config) { +static const char *sql_get_repository_root = "select resource_id from Resource where parent_id is NULL and nodename = $1 ;"; + + +// Uses a PGconn to lookup the resource id of the specified root node +// if the lookup succeeds, the resource id is written to rootid +// in case of an error, an error message will be logged +// returns: 0 success, 1 error +static int pg_lookup_root(ResourceData *res, scstr_t rootnode, int64_t *rootid) { + PGconn *connection = res->data; + + PGresult *result = PQexecParams( + connection, + sql_get_repository_root, + 1, // number of parameters + NULL, + &rootnode.ptr, // parameter value + NULL, + NULL, + 0); // 0: result in text format + + if(!result) { + log_ereport(LOG_FAILURE, "pg: root lookup failed: %s", PQerrorMessage(connection)); + return 1; + } + + int ret = 0; + + int nrows = PQntuples(result); + if(nrows == 1) { + char *resource_id_str = PQgetvalue(result, 0, 0); + if(resource_id_str) { + if(!util_strtoint(resource_id_str, rootid)) { + log_ereport(LOG_FAILURE, "pg: unexpected result for column resource_id", rootnode.ptr); + ret = 1; + } + } + } else { + log_ereport(LOG_FAILURE, "pg: cannot find root resource '%s'", rootnode.ptr); + ret = 1; + } + PQclear(result); + + return ret; +} + +PgRepository* pg_init_repo(ServerConfiguration *cfg, pool_handle_t *pool, WSConfigNode *config) { UcxAllocator a = util_pool_allocator(pool); ConfigNode *pg = serverconfig_get_node(config, CONFIG_NODE_OBJECT, SC("Postgresql")); @@ -41,6 +86,7 @@ scstr_t cfg_respool = serverconfig_directive_value(pg, SC("ResourcePool")); scstr_t cfg_rootid = serverconfig_directive_value(pg, SC("RootId")); + scstr_t cfg_rootnode = serverconfig_directive_value(pg, SC("RootNode")); scstr_t cfg_dav = serverconfig_directive_value(pg, SC("PGDavConfig")); // minimum requirement is a resource pool @@ -57,6 +103,29 @@ } } + // warn if RootId and RootNode are specified + if(cfg_rootid.length > 0 && cfg_rootnode.length > 0) { + log_ereport(LOG_WARN, "log_init_repo: RootId and RootNode specified, RootNode ignored"); + } else if(cfg_rootnode.length > 0) { + // check root node + + // resolve rootnode + // therefore we first need to get a connection from the resourcepool + ResourceData *res = resourcepool_cfg_lookup(cfg, cfg_respool.ptr, 0); + if(!res) { + log_ereport(LOG_MISCONFIG, "pg_init_repo: resource lookup failed"); + return NULL; + } + // do lookup, if successful, root_id will be set + int lookup_err = pg_lookup_root(res, cfg_rootnode, &root_id); + // we don't need the connection anymore + resourcepool_free(NULL, NULL, res); + if(lookup_err) { + // no logging required, pg_lookup_root will log the error + return NULL; + } + } + PgRepository *repo = pool_malloc(pool, sizeof(PgRepository)); ZERO(repo, sizeof(PgRepository));