From 4df71c305f886f6aa180631005be16ddaed07345 Mon Sep 17 00:00:00 2001 From: Trygve Aspenes Date: Fri, 29 Sep 2023 13:42:02 +0200 Subject: [PATCH] Cached(ie default) time dimension used instead of requested time dimension for getfeatureinfo (#311) --- include/mapcache.h | 6 ++++ lib/connection_pool.c | 1 + lib/dimension_pg.c | 69 ++++++++++++++++++++++++++++++++++++++++++- lib/service_wms.c | 8 ++++- 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/include/mapcache.h b/include/mapcache.h index 83f5891a..82b27626 100644 --- a/include/mapcache.h +++ b/include/mapcache.h @@ -1749,6 +1749,12 @@ struct mapcache_dimension { apr_array_header_t* (*get_all_ogc_formatted_entries)(mapcache_context *ctx, mapcache_dimension *dimension, mapcache_tileset *tileset, mapcache_extent *extent, mapcache_grid *grid); + /** + * \brief return all value to override default value + */ + apr_array_header_t* (*get_default_value)(mapcache_context *ctx, mapcache_dimension *dimension, + mapcache_tileset *tileset, mapcache_extent *extent, mapcache_grid *grid); + /** * \brief parse the value given in the configuration */ diff --git a/lib/connection_pool.c b/lib/connection_pool.c index 5ef196cd..56d20df4 100644 --- a/lib/connection_pool.c +++ b/lib/connection_pool.c @@ -140,6 +140,7 @@ mapcache_pooled_connection* mapcache_connection_pool_get_connection(mapcache_con pc->private->next = pcc->head; pc->private->pcc = pcc; + pcc->max_list_size = ctx->config->cp_hmax; if(count == pcc->max_list_size) { /* max number of connections atained, we must destroy the last one that was used */ mapcache_pooled_connection *opc; diff --git a/lib/dimension_pg.c b/lib/dimension_pg.c index 5d4d14e2..00a7dbc2 100644 --- a/lib/dimension_pg.c +++ b/lib/dimension_pg.c @@ -40,8 +40,10 @@ struct mapcache_dimension_postgresql { char *dbconnection; char *get_values_for_entry_query; char *get_all_values_query; + char *get_default_value_query; apr_hash_t *get_values_indexes; apr_hash_t *get_all_indexes; + apr_hash_t *get_default_value_indexes; }; struct postgresql_dimension_conn { @@ -74,9 +76,10 @@ static int qparam(mapcache_context *ctx, char *qstring, const char *param, int i static void parse_queries(mapcache_context *ctx, mapcache_dimension_postgresql *dim) { const char *keys[9] = {":tileset",":dim",":gridsrs",":minx",":maxx",":miny",":maxy",":start_timestamp",":end_timestamp"}; int i; - int gaidx=1,gvidx=1; + int gaidx=1,gvidx=1,gdidx=1; dim->get_all_indexes = apr_hash_make(ctx->pool); dim->get_values_indexes = apr_hash_make(ctx->pool); + dim->get_default_value_indexes = apr_hash_make(ctx->pool); for(i=0;i<9;i++) { if(qparam(ctx,dim->get_all_values_query,keys[i],gaidx)) { apr_hash_set(dim->get_all_indexes,keys[i],APR_HASH_KEY_STRING,INT2VOIDP(gaidx)); @@ -86,6 +89,12 @@ static void parse_queries(mapcache_context *ctx, mapcache_dimension_postgresql * apr_hash_set(dim->get_values_indexes,keys[i],APR_HASH_KEY_STRING,INT2VOIDP(gvidx)); gvidx++; } + if (dim->get_default_value_query){ + if(qparam(ctx,dim->get_default_value_query,keys[i],gdidx)) { + apr_hash_set(dim->get_default_value_indexes,keys[i],APR_HASH_KEY_STRING,INT2VOIDP(gdidx)); + gdidx++; + } + } } } @@ -220,6 +229,14 @@ void mapcache_postgresql_dimension_connection_constructor(mapcache_context *ctx, *conn_ = NULL; return; } + if (dim->get_default_value_query){ + prepare_query(ctx,conn->pgconn, "get_default_value", dim->get_default_value_query, dim->get_default_value_indexes); + if(GC_HAS_ERROR(ctx)) { + PQfinish(conn->pgconn); + *conn_ = NULL; + return; + } + } } void mapcache_postgresql_dimension_connection_destructor(void *conn_) @@ -330,6 +347,47 @@ static apr_array_header_t* _mapcache_dimension_postgresql_get_all_entries(mapcac } +static apr_array_header_t* _mapcache_dimension_postgresql_get_default_entries(mapcache_context *ctx, mapcache_dimension *dim, + mapcache_tileset *tileset, mapcache_extent *extent, mapcache_grid *grid) { + mapcache_dimension_postgresql *sdim = (mapcache_dimension_postgresql*)dim; + PGresult *res; + apr_array_header_t *time_ids = NULL; + mapcache_pooled_connection *pc; + struct postgresql_dimension_conn *conn; + int nParams, *paramLengths,*paramFormats,i; + char **paramValues; + + if (sdim->get_default_value_query == NULL){ + return NULL; + } + pc = _postgresql_dimension_get_conn(ctx,tileset,sdim); + if (GC_HAS_ERROR(ctx)) { + return NULL; + } + conn = pc->connection; + _mapcache_dimension_postgresql_bind_parameters(ctx,sdim->get_all_indexes,NULL,tileset,extent,grid,0,0,&nParams,¶mValues,¶mLengths,¶mFormats); + if(GC_HAS_ERROR(ctx)) { + _postgresql_dimension_release_conn(ctx, pc); + return NULL; + } + res = PQexecPrepared(conn->pgconn,"get_default_value",nParams,(const char *const*)paramValues,paramLengths,paramFormats,0); + if (PQresultStatus(res) != PGRES_TUPLES_OK) { + //ctx->set_error(ctx, 500, "postgresql query: %s", PQerrorMessage(conn->pgconn)); + PQclear(res); + _postgresql_dimension_release_conn(ctx, pc); + return NULL; + } + + time_ids = apr_array_make(ctx->pool,0,sizeof(char*)); + for(i=0;ipool, PQgetvalue(res,i,0)); + } + PQclear(res); + _postgresql_dimension_release_conn(ctx, pc); + return time_ids; + +} + static void _mapcache_dimension_postgresql_parse_xml(mapcache_context *ctx, mapcache_dimension *dim, ezxml_t node) { @@ -359,6 +417,14 @@ static void _mapcache_dimension_postgresql_parse_xml(mapcache_context *ctx, mapc ctx->set_error(ctx,400,"postgresql dimension \"%s\" has no node", dim->name); return; } + child = ezxml_child(node,"default_query"); + if(child) { + dimension->get_default_value_query = apr_pstrdup(ctx->pool, child->txt); + } else { + dimension->get_default_value_query = NULL; + // ctx->set_error(ctx,400,"postgresql dimension \"%s\" has no node", dim->name); + // return; + } parse_queries(ctx,dimension); //printf("q1: %s\n",dimension->get_all_values_query); //printf("q2: %s\n",dimension->get_values_for_entry_query); @@ -377,6 +443,7 @@ mapcache_dimension* mapcache_dimension_postgresql_create(mapcache_context *ctx, dimension->dimension.configuration_parse_xml = _mapcache_dimension_postgresql_parse_xml; dimension->dimension.get_all_entries = _mapcache_dimension_postgresql_get_all_entries; dimension->dimension.get_all_ogc_formatted_entries = _mapcache_dimension_postgresql_get_all_entries; + dimension->dimension.get_default_value = _mapcache_dimension_postgresql_get_default_entries; return (mapcache_dimension*)dimension; #else ctx->set_error(ctx,400,"postgresql dimension support requires POSTGRESQL support to be built in"); diff --git a/lib/service_wms.c b/lib/service_wms.c index 9ed4a3e1..ffeb1982 100644 --- a/lib/service_wms.c +++ b/lib/service_wms.c @@ -314,6 +314,7 @@ void _create_capabilities_wms(mapcache_context *ctx, mapcache_request_get_capabi if(tileset->dimensions) { for(i=0; idimensions->nelts; i++) { apr_array_header_t *values; + apr_array_header_t *default_value; int value_idx; char *dimval = NULL; mapcache_dimension *dimension = APR_ARRAY_IDX(tileset->dimensions,i,mapcache_dimension*); @@ -337,6 +338,11 @@ void _create_capabilities_wms(mapcache_context *ctx, mapcache_request_get_capabi if(dimval) { ezxml_set_txt(dimxml,dimval); } + default_value = dimension->get_default_value(ctx,dimension,tileset,NULL,NULL); + if (default_value){ + dimension->default_value = APR_ARRAY_IDX(default_value,0,char *); + ezxml_set_attr(dimxml,"default",dimension->default_value); + } } } @@ -886,7 +892,7 @@ void _mapcache_service_wms_parse_request(mapcache_context *ctx, mapcache_service mapcache_dimension *dimension = APR_ARRAY_IDX(tileset->dimensions,i,mapcache_dimension*); const char *value; if((value = (char*)apr_table_get(params,dimension->name)) != NULL) { - mapcache_map_set_cached_dimension(ctx,&fi->map,dimension->name,value); + mapcache_map_set_requested_dimension(ctx,&fi->map,dimension->name,value); GC_CHECK_ERROR(ctx); } }