PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
rtpostgis.c
Go to the documentation of this file.
1/*
2 *
3 * WKTRaster - Raster Types for PostGIS
4 * http://trac.osgeo.org/postgis/wiki/WKTRaster
5 *
6 * Copyright (C) 2011-2013 Regents of the University of California
7 * <bkpark@ucdavis.edu>
8 * Copyright (C) 2010-2011 Jorge Arevalo <jorge.arevalo@deimos-space.com>
9 * Copyright (C) 2010-2011 David Zwarg <dzwarg@azavea.com>
10 * Copyright (C) 2009-2011 Pierre Racine <pierre.racine@sbf.ulaval.ca>
11 * Copyright (C) 2009-2011 Mateusz Loskot <mateusz@loskot.net>
12 * Copyright (C) 2008-2009 Sandro Santilli <strk@kbt.io>
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software Foundation,
26 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 *
28 */
29
30/***************************************************************
31 * Some rules for returning NOTICE or ERROR...
32 *
33 * Send an ERROR like:
34 *
35 * elog(ERROR, "RASTER_out: Could not deserialize raster");
36 *
37 * only when:
38 *
39 * -something wrong happen with memory,
40 * -a function got an invalid argument ('3BUI' as pixel type) so that no row can
41 * be processed
42 *
43 * *** IMPORTANT: elog(ERROR, ...) does NOT return to calling function ***
44 *
45 * Send a NOTICE like:
46 *
47 * elog(NOTICE, "Invalid band index (must use 1-based). Returning NULL");
48 *
49 * when arguments (e.g. x, y, band) are NULL or out of range so that some or
50 * most rows can be processed anyway
51 *
52 * in this case,
53 * for SET functions or function normally returning a modified raster, return
54 * the original raster
55 * for GET functions, return NULL
56 * try to deduce a valid parameter value if it makes sense (e.g. out of range
57 * index for addBand)
58 *
59 * Do not put the name of the faulty function for NOTICEs, only with ERRORs.
60 *
61 ****************************************************************/
62
63/******************************************************************************
64 * Some notes on memory management...
65 *
66 * Every time a SQL function is called, PostgreSQL creates a new memory context.
67 * So, all the memory allocated with palloc/repalloc in that context is
68 * automatically free'd at the end of the function. If you want some data to
69 * live between function calls, you have 2 options:
70 *
71 * - Use fcinfo->flinfo->fn_mcxt context to store the data (by pointing the
72 * data you want to keep with fcinfo->flinfo->fn_extra)
73 * - Use SRF funcapi, and storing the data at multi_call_memory_ctx (by pointing
74 * the data you want to keep with funcctx->user_fctx. funcctx is created by
75 * funcctx = SPI_FIRSTCALL_INIT()). Recommended way in functions returning rows,
76 * like RASTER_dumpAsPolygons (see section 34.9.9 at
77 * http://www.postgresql.org/docs/8.4/static/xfunc-c.html).
78 *
79 * But raster code follows the same philosophy than the rest of PostGIS: keep
80 * memory as clean as possible. So, we free all allocated memory.
81 *
82 * TODO: In case of functions returning NULL, we should free the memory too.
83 *****************************************************************************/
84
85/******************************************************************************
86 * Notes for use of PG_DETOAST_DATUM(), PG_DETOAST_DATUM_SLICE()
87 * and PG_DETOAST_DATUM_COPY()
88 *
89 * When ONLY getting raster (not band) metadata, use PG_DETOAST_DATUM_SLICE()
90 * as it is generally quicker to get only the chunk of memory that contains
91 * the raster metadata.
92 *
93 * Example: PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0,
94 * sizeof(struct rt_raster_serialized_t))
95 *
96 * When ONLY setting raster or band(s) metadata OR reading band data, use
97 * PG_DETOAST_DATUM() as rt_raster_deserialize() allocates local memory
98 * for the raster and band(s) metadata.
99 *
100 * Example: PG_DETOAST_DATUM(PG_GETARG_DATUM(0))
101 *
102 * When SETTING band pixel values, use PG_DETOAST_DATUM_COPY(). This is
103 * because band data (not metadata) is just a pointer to the correct
104 * memory location in the detoasted datum. What is returned from
105 * PG_DETOAST_DATUM() may or may not be a copy of the input datum.
106 *
107 * From the comments in postgresql/src/include/fmgr.h...
108 *
109 * pg_detoast_datum() gives you either the input datum (if not toasted)
110 * or a detoasted copy allocated with palloc().
111 *
112 * From the mouth of Tom Lane...
113 * http://archives.postgresql.org/pgsql-hackers/2002-01/msg01289.php
114 *
115 * PG_DETOAST_DATUM_COPY guarantees to give you a copy, even if the
116 * original wasn't toasted. This allows you to scribble on the input,
117 * in case that happens to be a useful way of forming your result.
118 * Without a forced copy, a routine for a pass-by-ref datatype must
119 * NEVER, EVER scribble on its input ... because very possibly it'd
120 * be scribbling on a valid tuple in a disk buffer, or a valid entry
121 * in the syscache.
122 *
123 * The key detail above is that the raster datatype is a varlena, a
124 * passed by reference datatype.
125 *
126 * Example: PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0))
127 *
128 * If in doubt, use PG_DETOAST_DATUM_COPY() as that guarantees that the input
129 * datum is copied for use.
130 *****************************************************************************/
131
132/* PostgreSQL */
133#include "postgres.h" /* for palloc */
134#include "fmgr.h" /* for PG_MODULE_MAGIC */
135#include "libpq/pqsignal.h"
136#include "utils/guc.h"
137#include "utils/builtins.h"
138#include "utils/memutils.h"
139#include "utils/elog.h"
140
141/* PostGIS */
142#include "postgis_config.h"
143#include "liblwgeom.h"
144#include "lwgeom_pg.h"
145#include "stringlist.h"
146#include "optionlist.h"
147
148/* PostGIS Raster */
149#include "rtpostgis.h"
150#include "rtpg_internal.h"
151
152
153#ifndef __GNUC__
154# define __attribute__ (x)
155#endif
156
157/*
158 * This is required for builds against pgsql
159 */
161
162/* Module load callback */
163void _PG_init(void);
164
165/* Module unload callback */
166void _PG_fini(void);
167
168#define RT_MSG_MAXLEN 256
169
170/* ---------------------------------------------------------------- */
171/* Memory allocation / error reporting hooks */
172/* ---------------------------------------------------------------- */
173
174static void *
175rt_pg_alloc(size_t size)
176{
177 void * result;
178
179 POSTGIS_RT_DEBUGF(5, "rt_pgalloc(%ld) called", (long int) size);
180
181 result = palloc(size);
182
183 return result;
184}
185
186static void *
187rt_pg_realloc(void *mem, size_t size)
188{
189 void * result;
190
191 POSTGIS_RT_DEBUGF(5, "rt_pg_realloc(%ld) called", (long int) size);
192
193 if (mem)
194 result = repalloc(mem, size);
195
196 else
197 result = palloc(size);
198
199 return result;
200}
201
202static void
203rt_pg_free(void *ptr)
204{
205 POSTGIS_RT_DEBUG(5, "rt_pfree called");
206 pfree(ptr);
207}
208
209static void rt_pg_error(const char *fmt, va_list ap)
210 __attribute__(( format(printf,1,0) ));
211
212static void
213rt_pg_error(const char *fmt, va_list ap)
214{
215 char errmsg[RT_MSG_MAXLEN+1];
216
217 vsnprintf (errmsg, RT_MSG_MAXLEN, fmt, ap);
218
219 errmsg[RT_MSG_MAXLEN]='\0';
220 ereport(ERROR, (errmsg_internal("%s", errmsg)));
221}
222
223static void rt_pg_notice(const char *fmt, va_list ap)
224 __attribute__(( format(printf,1,0) ));
225
226static void
227rt_pg_notice(const char *fmt, va_list ap)
228{
229 char msg[RT_MSG_MAXLEN+1];
230
231 vsnprintf (msg, RT_MSG_MAXLEN, fmt, ap);
232
233 msg[RT_MSG_MAXLEN]='\0';
234 ereport(NOTICE, (errmsg_internal("%s", msg)));
235}
236
237static void rt_pg_debug(const char *fmt, va_list ap)
238 __attribute__(( format(printf,1,0) ));
239
240static void
241rt_pg_debug(const char *fmt, va_list ap)
242{
243 char msg[RT_MSG_MAXLEN+1];
244
245 vsnprintf (msg, RT_MSG_MAXLEN, fmt, ap);
246
247 msg[RT_MSG_MAXLEN]='\0';
248 ereport(DEBUG1, (errmsg_internal("%s", msg)));
249}
250
251static char *
252rt_pg_options(const char* varname)
253{
254 char optname[128];
255 char *optvalue;
256 snprintf(optname, 128, "postgis.%s", varname);
257 /* GetConfigOptionByName(name, found_name, missing_ok) */
258 optvalue = GetConfigOptionByName(optname, NULL, true);
259 if (optvalue && strlen(optvalue) == 0)
260 return NULL;
261 else
262 return optvalue;
263}
264
265/* ---------------------------------------------------------------- */
266/* GDAL allowed config options for VSI filesystems */
267/* ---------------------------------------------------------------- */
268
270
271
272#if POSTGIS_GDAL_VERSION < 20300
273
274/*
275* For older versions of GDAL we have extracted the list of options
276* that were available at the 2.2 release and use that
277* as our set of allowed VSI network file options.
278*/
279static void
281{
282 const char * gdaloption;
283 const char * const gdaloptions[] = {
284 "aws_access_key_id",
285 "aws_https",
286 "aws_max_keys",
287 "aws_s3_endpoint",
288 "aws_region",
289 "aws_request_payer",
290 "aws_secret_access_key",
291 "aws_session_token",
292 "aws_timestamp",
293 "aws_virtual_hosting",
294 "cpl_gs_timestamp",
295 "cpl_gs_endpoint",
296 "gs_secret_access_key",
297 "gs_access_key_id",
298 "goa2_client_id",
299 "goa2_client_secret",
300 "cpl_curl_enable_vsimem",
301 "cpl_curl_gzip",
302 "cpl_curl_verbose",
303 "gdal_http_auth",
304 "gdal_http_connecttimeout",
305 "gdal_http_cookie",
306 "gdal_http_header_file",
307 "gdal_http_low_speed_time",
308 "gdal_http_low_speed_limit",
309 "gdal_http_max_retry",
310 "gdal_http_netrc",
311 "gdal_http_proxy",
312 "gdal_http_proxyuserpwd",
313 "gdal_http_retry_delay",
314 "gdal_http_userpwd",
315 "gdal_http_timeout",
316 "gdal_http_unsafessl",
317 "gdal_http_useragent",
318 "gdal_disable_readdir_on_open",
319 "gdal_proxy_auth",
320 "curl_ca_bundle",
321 "ssl_cert_file",
322 "vsi_cache_size",
323 "cpl_vsil_curl_use_head",
324 "cpl_vsil_curl_use_s3_redirect",
325 "cpl_vsil_curl_max_ranges",
326 "cpl_vsil_curl_use_cache",
327 "cpl_vsil_curl_allowed_filename",
328 "cpl_vsil_curl_allowed_extensions",
329 "cpl_vsil_curl_slow_get_size",
330 "vsi_cache",
331 "vsis3_chunk_size",
332 NULL
333 };
334 const char * const * gdaloptionsptr = gdaloptions;
335
337 while((gdaloption = *gdaloptionsptr++))
338 {
340 }
342}
343
344#else /* POSTGIS_GDAL_VERSION < 20300 */
345
346/*
347* For newer versions of GDAL the VSIGetFileSystemOptions() call returns
348* all the allowed options for each VSI network file type, and we just have
349* to keep the list of VSI types statically in rt_pg_vsi_load_all_options().
350*/
351static void
352rt_pg_vsi_load_options(const char* vsiname, stringlist_t *s)
353{
354 CPLXMLNode *root, *optNode;
355 const char *xml = VSIGetFileSystemOptions(vsiname);
356 if (!xml) return;
357
358 root = CPLParseXMLString(xml);
359 if (!root) {
360 elog(ERROR, "%s: Unable to read options for VSI %s", __func__, vsiname);
361 return;
362 }
363 optNode = CPLSearchXMLNode(root, "Option");
364 if (!optNode) {
365 CPLDestroyXMLNode(root);
366 elog(ERROR, "%s: Unable to find <Option> in VSI XML %s", __func__, vsiname);
367 return;
368 }
369 while(optNode)
370 {
371 const char *option = CPLGetXMLValue(optNode, "name", NULL);
372 if (option) {
373 char *optionstr = pstrdup(option);
374 char *ptr = optionstr;
375 /* The options parser used in rt_util_gdal_open()
376 lowercases keys, so we'll lower case our list
377 of options before storing them in the stringlist. */
378 while (*ptr) {
379 *ptr = tolower(*ptr);
380 ptr++;
381 }
382 elog(DEBUG4, "GDAL %s option: %s", vsiname, optionstr);
384 }
385 optNode = optNode->psNext;
386 }
387 CPLDestroyXMLNode(root);
388}
389
390static void
392{
393 const char * vsiname;
394 const char * const vsilist[] = {
395 "/vsicurl/",
396 "/vsis3/",
397 "/vsigs/",
398 "/vsiaz/",
399 "/vsioss/",
400 "/vsihdfs/",
401 "/vsiwebhdfs/",
402 "/vsiswift/",
403 "/vsiadls/",
404 NULL
405 };
406 const char * const * vsilistptr = vsilist;
407
409 while((vsiname = *vsilistptr++))
410 {
411 rt_pg_vsi_load_options(vsiname, vsi_option_stringlist);
412 }
414}
415
416#endif /* POSTGIS_GDAL_VERSION < 20300 */
417
418
419static bool
420rt_pg_vsi_check_options(char **newval, void **extra, GucSource source)
421{
422 size_t olist_sz, i;
423 char *olist[OPTION_LIST_SIZE];
424 const char *found = NULL;
425 char *newoptions;
426
427 memset(olist, 0, sizeof(olist));
428 if (!newval || !*newval)
429 return false;
430 newoptions = pstrdup(*newval);
431
432 /* Cache the legal options if they aren't already loaded */
435
436 elog(DEBUG5, "%s: processing VSI options: %s", __func__, newoptions);
437 option_list_parse(newoptions, olist);
438 olist_sz = option_list_length(olist);
439 if (olist_sz % 2 != 0)
440 return false;
441
442 for (i = 0; i < olist_sz; i += 2)
443 {
444 found = stringlist_find(vsi_option_stringlist, olist[i]);
445 if (!found)
446 {
447 elog(WARNING, "'%s' is not a legal VSI network file option", olist[i]);
448 pfree(newoptions);
449 return false;
450 }
451 }
452 return true;
453}
454
455
456/* ---------------------------------------------------------------- */
457/* PostGIS raster GUCs */
458/* ---------------------------------------------------------------- */
459
460static char *gdal_datapath = NULL;
461static char *gdal_vsi_options = NULL;
462static char *gdal_enabled_drivers = NULL;
463static bool enable_outdb_rasters = false;
464static bool gdal_cpl_debug = false;
465
466/* ---------------------------------------------------------------- */
467/* Useful variables */
468/* ---------------------------------------------------------------- */
469
473
474/* postgis.gdal_datapath */
475static void
476rtpg_assignHookGDALDataPath(const char *newpath, void *extra) {
477 POSTGIS_RT_DEBUGF(4, "newpath = %s", newpath);
478 POSTGIS_RT_DEBUGF(4, "gdaldatapath = %s", gdal_datapath);
479
480 /* clear finder cache */
481 CPLFinderClean();
482
483 /* clear cached OSR */
484 OSRCleanup();
485
486 /* set GDAL_DATA */
487 CPLSetConfigOption("GDAL_DATA", newpath);
488 POSTGIS_RT_DEBUGF(4, "GDAL_DATA = %s", CPLGetConfigOption("GDAL_DATA", ""));
489}
490
491/* postgis.gdal_enabled_drivers */
492static void
493rtpg_assignHookGDALEnabledDrivers(const char *enabled_drivers, void *extra) {
494 int enable_all = 0;
495 int disable_all = 0;
496 int vsicurl = 0;
497
498 char **enabled_drivers_array = NULL;
499 uint32_t enabled_drivers_count = 0;
500 bool *enabled_drivers_found = NULL;
501 char *gdal_skip = NULL;
502
503 uint32_t i;
504 uint32_t j;
505
506 POSTGIS_RT_DEBUGF(4, "GDAL_SKIP = %s", CPLGetConfigOption("GDAL_SKIP", ""));
507 POSTGIS_RT_DEBUGF(4, "enabled_drivers = %s", enabled_drivers);
508
509 /* if NULL, nothing to do */
510 if (enabled_drivers == NULL)
511 return;
512
513 elog(DEBUG4, "Enabling GDAL drivers: %s", enabled_drivers);
514
515 /* destroy the driver manager */
516 /* this is the only way to ensure GDAL_SKIP is recognized */
517 GDALDestroyDriverManager();
518 CPLSetConfigOption("GDAL_SKIP", NULL);
519
520 /* force wrapper function to call GDALAllRegister() */
522
523 enabled_drivers_array = rtpg_strsplit(enabled_drivers, " ", &enabled_drivers_count);
524 enabled_drivers_found = palloc(sizeof(bool) * enabled_drivers_count);
525 memset(enabled_drivers_found, FALSE, sizeof(bool) * enabled_drivers_count);
526
527 /* scan for keywords DISABLE_ALL and ENABLE_ALL */
528 disable_all = 0;
529 enable_all = 0;
530 if (strstr(enabled_drivers, GDAL_DISABLE_ALL) != NULL) {
531 for (i = 0; i < enabled_drivers_count; i++) {
532 if (strstr(enabled_drivers_array[i], GDAL_DISABLE_ALL) != NULL) {
533 enabled_drivers_found[i] = TRUE;
534 disable_all = 1;
535 }
536 }
537 }
538 else if (strstr(enabled_drivers, GDAL_ENABLE_ALL) != NULL) {
539 for (i = 0; i < enabled_drivers_count; i++) {
540 if (strstr(enabled_drivers_array[i], GDAL_ENABLE_ALL) != NULL) {
541 enabled_drivers_found[i] = TRUE;
542 enable_all = 1;
543 }
544 }
545 }
546 else if (strstr(enabled_drivers, GDAL_VSICURL) != NULL) {
547 for (i = 0; i < enabled_drivers_count; i++) {
548 if (strstr(enabled_drivers_array[i], GDAL_VSICURL) != NULL) {
549 enabled_drivers_found[i] = TRUE;
550 vsicurl = 1;
551 }
552 }
553 }
554
555 if (!enable_all) {
556 int found = 0;
557 uint32_t drv_count = 0;
558 rt_gdaldriver drv_set = rt_raster_gdal_drivers(&drv_count, 0);
559
560 POSTGIS_RT_DEBUGF(4, "driver count = %d", drv_count);
561
562 /* all other drivers than those in new drivers are added to GDAL_SKIP */
563 for (i = 0; i < drv_count; i++) {
564 found = 0;
565
566 if (!disable_all) {
567 /* gdal driver found in enabled_drivers, continue to thorough search */
568 if (strstr(enabled_drivers, drv_set[i].short_name) != NULL) {
569 /* thorough search of enabled_drivers */
570 for (j = 0; j < enabled_drivers_count; j++) {
571 /* driver found */
572 if (strcmp(enabled_drivers_array[j], drv_set[i].short_name) == 0) {
573 enabled_drivers_found[j] = TRUE;
574 found = 1;
575 }
576 }
577 }
578 }
579
580 /* driver found, continue */
581 if (found)
582 continue;
583
584 /* driver not found, add to gdal_skip */
585 if (gdal_skip == NULL) {
586 gdal_skip = palloc(sizeof(char) * (strlen(drv_set[i].short_name) + 1));
587 gdal_skip[0] = '\0';
588 }
589 else {
590 gdal_skip = repalloc(
591 gdal_skip,
592 sizeof(char) * (
593 strlen(gdal_skip) + 1 + strlen(drv_set[i].short_name) + 1
594 )
595 );
596 strcat(gdal_skip, " ");
597 }
598 strcat(gdal_skip, drv_set[i].short_name);
599 }
600
601 for (i = 0; i < drv_count; i++) {
602 pfree(drv_set[i].short_name);
603 pfree(drv_set[i].long_name);
604 pfree(drv_set[i].create_options);
605 }
606 if (drv_count) pfree(drv_set);
607
608 }
609
610 for (i = 0; i < enabled_drivers_count; i++) {
611 if (enabled_drivers_found[i])
612 continue;
613
614 if (disable_all)
615 elog(WARNING, "%s set. Ignoring GDAL driver: %s", GDAL_DISABLE_ALL, enabled_drivers_array[i]);
616 else if (enable_all)
617 elog(WARNING, "%s set. Ignoring GDAL driver: %s", GDAL_ENABLE_ALL, enabled_drivers_array[i]);
618 else
619 elog(WARNING, "Unknown GDAL driver: %s", enabled_drivers_array[i]);
620 }
621
622 if (vsicurl)
623 elog(WARNING, "%s set.", GDAL_VSICURL);
624
625 /* destroy the driver manager */
626 /* this is the only way to ensure GDAL_SKIP is recognized */
627 GDALDestroyDriverManager();
628
629 /* set GDAL_SKIP */
630 POSTGIS_RT_DEBUGF(4, "gdal_skip = %s", gdal_skip);
631 CPLSetConfigOption("GDAL_SKIP", gdal_skip);
632 if (gdal_skip != NULL) pfree(gdal_skip);
633
634 /* force wrapper function to call GDALAllRegister() */
636
637 pfree(enabled_drivers_array);
638 pfree(enabled_drivers_found);
639 POSTGIS_RT_DEBUGF(4, "GDAL_SKIP = %s", CPLGetConfigOption("GDAL_SKIP", ""));
640}
641
642/* postgis.enable_outdb_rasters */
643static void
644rtpg_assignHookEnableOutDBRasters(bool enable, void *extra) {
645 /* do nothing for now */
646}
647
648
649/* Module load callback */
650void
651_PG_init(void) {
652
653 bool boot_postgis_enable_outdb_rasters = false;
654 MemoryContext old_context;
655
656 /*
657 * Change to context for memory allocation calls like palloc() in the
658 * extension initialization routine
659 */
660 old_context = MemoryContextSwitchTo(TopMemoryContext);
661
662 /*
663 use POSTGIS_GDAL_ENABLED_DRIVERS to set the bootValue
664 of GUC postgis.gdal_enabled_drivers
665 */
666 env_postgis_gdal_enabled_drivers = getenv("POSTGIS_GDAL_ENABLED_DRIVERS");
668 size_t sz = sizeof(char) * (strlen(GDAL_DISABLE_ALL) + 1);
671 }
672 else {
675 );
676 }
678 4,
679 "boot_postgis_gdal_enabled_drivers = %s",
681 );
682
683 /*
684 use POSTGIS_ENABLE_OUTDB_RASTERS to set the bootValue
685 of GUC postgis.enable_outdb_rasters
686 */
687 env_postgis_enable_outdb_rasters = getenv("POSTGIS_ENABLE_OUTDB_RASTERS");
690
691 /* out of memory */
692 if (env == NULL) {
693 elog(ERROR, "_PG_init: Cannot process environmental variable: POSTGIS_ENABLE_OUTDB_RASTERS");
694 return;
695 }
696
697 if (strcmp(env, "1") == 0)
698 boot_postgis_enable_outdb_rasters = true;
699
701 pfree(env);
702 }
704 4,
705 "boot_postgis_enable_outdb_rasters = %s",
706 boot_postgis_enable_outdb_rasters ? "TRUE" : "FALSE"
707 );
708
709 /* Install liblwgeom handlers */
710 pg_install_lwgeom_handlers();
711
712 /* Install rtcore handlers */
716
717 /* Define custom GUC variables. */
718 if ( postgis_guc_find_option("postgis.gdal_datapath") )
719 {
720 /* In this narrow case the previously installed GUC is tied to the callback in */
721 /* the previously loaded library. Probably this is happening during an */
722 /* upgrade, so the old library is where the callback ties to. */
723 elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.gdal_datapath");
724 }
725 else
726 {
727 DefineCustomStringVariable(
728 "postgis.gdal_datapath", /* name */
729 "Path to GDAL data files.", /* short_desc */
730 "Physical path to directory containing GDAL data files (sets the GDAL_DATA config option).", /* long_desc */
731 &gdal_datapath, /* valueAddr */
732 NULL, /* bootValue */
733 PGC_SUSET, /* GucContext context */
734 0, /* int flags */
735 NULL, /* GucStringCheckHook check_hook */
736 rtpg_assignHookGDALDataPath, /* GucStringAssignHook assign_hook */
737 NULL /* GucShowHook show_hook */
738 );
739 }
740
741 if ( postgis_guc_find_option("postgis.gdal_enabled_drivers") )
742 {
743 /* In this narrow case the previously installed GUC is tied to the callback in */
744 /* the previously loaded library. Probably this is happening during an */
745 /* upgrade, so the old library is where the callback ties to. */
746 elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.gdal_enabled_drivers");
747 }
748 else
749 {
750 DefineCustomStringVariable(
751 "postgis.gdal_enabled_drivers", /* name */
752 "Enabled GDAL drivers.", /* short_desc */
753 "List of enabled GDAL drivers by short name. To enable/disable all drivers, use 'ENABLE_ALL' or 'DISABLE_ALL' (sets the GDAL_SKIP config option).", /* long_desc */
754 &gdal_enabled_drivers, /* valueAddr */
755 boot_postgis_gdal_enabled_drivers, /* bootValue */
756 PGC_SUSET, /* GucContext context */
757 0, /* int flags */
758 NULL, /* GucStringCheckHook check_hook */
759 rtpg_assignHookGDALEnabledDrivers, /* GucStringAssignHook assign_hook */
760 NULL /* GucShowHook show_hook */
761 );
762 }
763
764 if ( postgis_guc_find_option("postgis.enable_outdb_rasters") )
765 {
766 /* In this narrow case the previously installed GUC is tied to the callback in */
767 /* the previously loaded library. Probably this is happening during an */
768 /* upgrade, so the old library is where the callback ties to. */
769 elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.enable_outdb_rasters");
770 }
771 else
772 {
773 DefineCustomBoolVariable(
774 "postgis.enable_outdb_rasters", /* name */
775 "Enable Out-DB raster bands", /* short_desc */
776 "If true, rasters can access data located outside the database", /* long_desc */
777 &enable_outdb_rasters, /* valueAddr */
778 boot_postgis_enable_outdb_rasters, /* bootValue */
779 PGC_SUSET, /* GucContext context */
780 0, /* int flags */
781 NULL, /* GucBoolCheckHook check_hook */
782 rtpg_assignHookEnableOutDBRasters, /* GucBoolAssignHook assign_hook */
783 NULL /* GucShowHook show_hook */
784 );
785 }
786
787 /* Prototype for CPL_Degbuf control function. */
788 if ( postgis_guc_find_option("postgis.gdal_cpl_debug") )
789 {
790 /* In this narrow case the previously installed GUC is tied to the callback in */
791 /* the previously loaded library. Probably this is happening during an */
792 /* upgrade, so the old library is where the callback ties to. */
793 elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.gdal_cpl_debug");
794 }
795 else
796 {
797 DefineCustomBoolVariable(
798 "postgis.gdal_cpl_debug", /* name */
799 "Enable GDAL debugging messages", /* short_desc */
800 "GDAL debug messages will be sent at the PgSQL debug log level", /* long_desc */
801 &gdal_cpl_debug, /* valueAddr */
802 false, /* bootValue */
803 PGC_SUSET, /* GucContext context */
804 0, /* int flags */
805 NULL, /* GucBoolCheckHook check_hook */
806 rtpg_gdal_set_cpl_debug, /* GucBoolAssignHook assign_hook */
807 NULL /* GucShowHook show_hook */
808 );
809 }
810
811 if ( postgis_guc_find_option("postgis.gdal_vsi_options") )
812 {
813 elog(WARNING, "'%s' is already set and cannot be changed until you reconnect", "postgis.gdal_vsi_options");
814 }
815 else
816 {
817 DefineCustomStringVariable(
818 "postgis.gdal_vsi_options", /* name */
819 "VSI config options", /* short_desc */
820 "Set the config options to be used when opening /vsi/ network files", /* long_desc */
821 &gdal_vsi_options, /* valueAddr */
822 "", /* bootValue */
823 PGC_USERSET, /* GucContext context */
824 0, /* int flags */
825 rt_pg_vsi_check_options, /* GucStringCheckHook check_hook */
826 NULL, /* GucStringAssignHook assign_hook */
827 NULL /* GucShowHook show_hook */
828 );
829 }
830
831 /* Revert back to old context */
832 MemoryContextSwitchTo(old_context);
833}
834
835/* Module unload callback */
836void
837_PG_fini(void) {
838
839 MemoryContext old_context = MemoryContextSwitchTo(TopMemoryContext);
840
841 elog(NOTICE, "Goodbye from PostGIS Raster %s", POSTGIS_VERSION);
842
843 /* Clean up */
847
851
852 /* Revert back to old context */
853 MemoryContextSwitchTo(old_context);
854}
855
856
857
char * s
Definition cu_in_wkt.c:23
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition cu_print.c:267
#define TRUE
Definition dbfopen.c:73
#define FALSE
Definition dbfopen.c:72
This library is the generic geometry handling section of PostGIS.
int rt_util_gdal_register_all(int force_register_all)
Definition rt_util.c:444
rt_gdaldriver rt_raster_gdal_drivers(uint32_t *drv_count, uint8_t cancc)
Returns a set of available GDAL drivers.
Definition rt_raster.c:1716
#define GDAL_ENABLE_ALL
Definition librtcore.h:2239
#define GDAL_DISABLE_ALL
Definition librtcore.h:2240
#define GDAL_VSICURL
Definition librtcore.h:2241
void rt_set_handlers_options(rt_allocator allocator, rt_reallocator reallocator, rt_deallocator deallocator, rt_message_handler error_handler, rt_message_handler info_handler, rt_message_handler warning_handler, rt_options options_handler)
Definition rt_context.c:169
size_t option_list_length(char **olist)
Returns the total number of keys and values in the list.
Definition optionlist.c:73
void option_list_parse(char *input, char **olist)
option_list is a null-terminated list of strings, where every odd string is a key and every even stri...
Definition optionlist.c:86
#define OPTION_LIST_SIZE
Definition optionlist.h:31
void rtpg_gdal_set_cpl_debug(bool value, void *extra)
Definition rtpg_gdal.c:1147
char ** rtpg_strsplit(const char *str, const char *delimiter, uint32_t *n)
char * rtpg_trim(const char *input)
static void * rt_pg_alloc(size_t size)
Definition rtpostgis.c:175
static char * env_postgis_enable_outdb_rasters
Definition rtpostgis.c:472
void _PG_init(void)
Definition rtpostgis.c:651
static char * gdal_vsi_options
Definition rtpostgis.c:461
PG_MODULE_MAGIC
Definition rtpostgis.c:160
static void rtpg_assignHookGDALDataPath(const char *newpath, void *extra)
Definition rtpostgis.c:476
static void rt_pg_error(const char *fmt, va_list ap) __attribute__((format(printf
Definition rtpostgis.c:213
void _PG_fini(void)
Definition rtpostgis.c:837
static bool enable_outdb_rasters
Definition rtpostgis.c:463
static void rt_pg_notice(const char *fmt, va_list ap) __attribute__((format(printf
Definition rtpostgis.c:227
static bool rt_pg_vsi_check_options(char **newval, void **extra, GucSource source)
Definition rtpostgis.c:420
static char * rt_pg_options(const char *varname)
Definition rtpostgis.c:252
static stringlist_t * vsi_option_stringlist
Definition rtpostgis.c:269
static void rt_pg_vsi_load_all_options(void)
Definition rtpostgis.c:280
static char * env_postgis_gdal_enabled_drivers
Definition rtpostgis.c:470
static char * boot_postgis_gdal_enabled_drivers
Definition rtpostgis.c:471
#define RT_MSG_MAXLEN
Definition rtpostgis.c:168
static void rtpg_assignHookGDALEnabledDrivers(const char *enabled_drivers, void *extra)
Definition rtpostgis.c:493
static void rt_pg_free(void *ptr)
Definition rtpostgis.c:203
static bool gdal_cpl_debug
Definition rtpostgis.c:464
static char * gdal_enabled_drivers
Definition rtpostgis.c:462
static void rtpg_assignHookEnableOutDBRasters(bool enable, void *extra)
Definition rtpostgis.c:644
#define __attribute__
Definition rtpostgis.c:154
static void rt_pg_debug(const char *fmt, va_list ap) __attribute__((format(printf
Definition rtpostgis.c:241
static char * gdal_datapath
Definition rtpostgis.c:460
static void * rt_pg_realloc(void *mem, size_t size)
Definition rtpostgis.c:187
#define POSTGIS_RT_DEBUG(level, msg)
Definition rtpostgis.h:65
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition rtpostgis.h:69
stringlist_t * stringlist_create(void)
Definition stringlist.c:71
void stringlist_add_string_nosort(stringlist_t *s, const char *string)
Definition stringlist.c:117
void stringlist_sort(stringlist_t *s)
Definition stringlist.c:123
const char * stringlist_find(stringlist_t *s, const char *key)
Definition stringlist.c:129