PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
raster2pgsql.c
Go to the documentation of this file.
1/*
2 *
3 * PostGIS raster loader
4 * http://trac.osgeo.org/postgis/wiki/WKTRaster
5 *
6 * Copyright 2001-2003 Refractions Research Inc.
7 * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
8 * Copyright 2009 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
9 * Copyright (C) 2011 Regents of the University of California
10 * <bkpark@ucdavis.edu>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 */
27
28#include "raster2pgsql.h"
29#include "gdal_vrt.h"
30#include "ogr_srs_api.h"
31#include <assert.h>
32
33#define xstr(s) str(s)
34#define str(s) #s
35
36static void
37loader_rt_error_handler(const char *fmt, va_list ap) __attribute__ ((format (printf, 1, 0)));
38
39static void
40loader_rt_error_handler(const char *fmt, va_list ap) {
41 static const char *label = "ERROR: ";
42 char newfmt[1024] = {0};
43 snprintf(newfmt, 1024, "%s%s\n", label, fmt);
44 newfmt[1023] = '\0';
45 vfprintf(stderr, newfmt, ap);
46 va_end(ap);
47}
48
49static void
50loader_rt_warning_handler(const char *fmt, va_list ap) __attribute__ ((format (printf, 1, 0)));
51
52static void
53loader_rt_warning_handler(const char *fmt, va_list ap) {
54 static const char *label = "WARNING: ";
55 char newfmt[1024] = {0};
56 snprintf(newfmt, 1024, "%s%s\n", label, fmt);
57 newfmt[1023] = '\0';
58 vfprintf(stderr, newfmt, ap);
59 va_end(ap);
60}
61
62static void
63loader_rt_info_handler(const char *fmt, va_list ap) __attribute__ ((format (printf, 1, 0)));
64
65static void
66loader_rt_info_handler(const char *fmt, va_list ap) {
67 static const char *label = "INFO: ";
68 char newfmt[1024] = {0};
69 snprintf(newfmt, 1024, "%s%s\n", label, fmt);
70 newfmt[1023] = '\0';
71 vfprintf(stderr, newfmt, ap);
72 va_end(ap);
73}
74
75static void
86
87static void
89 uint16_t i;
90 uint16_t nbands = rt_raster_get_num_bands(raster);
91 for (i = 0; i < nbands; i++) {
92 rt_band band = rt_raster_get_band(raster, i);
93 if (band == NULL) continue;
94
95 if (!rt_band_is_offline(band) && !rt_band_get_ownsdata_flag(band)) {
96 void* mem = rt_band_get_data(band);
97 if (mem) rtdealloc(mem);
98 }
99 rt_band_destroy(band);
100 }
101 rt_raster_destroy(raster);
102}
103
104static int
105array_range(int min, int max, int step, int **range, uint32_t *len) {
106 int i = 0;
107 int j = 0;
108
109 step = abs(step);
110 *len = (uint32_t) ((abs(max - min) + 1 + (step / 2)) / step);
111 *range = rtalloc(sizeof(int) * *len);
112
113 if (min < max) {
114 for (i = min, j = 0; i <= max; i += step, j++)
115 (*range)[j] = i;
116 }
117 else if (max < min) {
118 if (step > 0) step *= -1;
119 for (i = min, j = 0; i >= max; i += step, j++)
120 (*range)[j] = i;
121 }
122 else if (min == max) {
123 (*range)[0] = min;
124 }
125 else {
126 *len = 0;
127 *range = NULL;
128 return 0;
129 }
130
131 return 1;
132}
133
134/* string replacement function taken from
135 * http://ubuntuforums.org/showthread.php?s=aa6f015109fd7e4c7e30d2fd8b717497&t=141670&page=3
136 */
137/* ---------------------------------------------------------------------------
138 Name : replace - Search & replace a substring by another one.
139 Creation : Thierry Husson, Sept 2010
140 Parameters :
141 str : Big string where we search
142 oldstr : Substring we are looking for
143 newstr : Substring we want to replace with
144 count : Optional pointer to int (input / output value). NULL to ignore.
145 Input: Maximum replacements to be done. NULL or < 1 to do all.
146 Output: Number of replacements done or -1 if not enough memory.
147 Returns : Pointer to the new string or NULL if error.
148 Notes :
149 - Case sensitive - Otherwise, replace functions "strstr" by "strcasestr"
150 - Always allocates memory for the result.
151--------------------------------------------------------------------------- */
152static char*
154 const char *str,
155 const char *oldstr, const char *newstr,
156 int *count
157) {
158 const char *tmp = str;
159 char *result;
160 int found = 0;
161 int length, reslen;
162 int oldlen = strlen(oldstr);
163 int newlen = strlen(newstr);
164 int limit = (count != NULL && *count > 0) ? *count : -1;
165
166 tmp = str;
167 while ((tmp = strstr(tmp, oldstr)) != NULL && found != limit)
168 found++, tmp += oldlen;
169
170 length = (int)strlen(str) + found * (newlen - oldlen);
171 if ((result = (char *) rtalloc(length + 1)) == NULL) {
172 rterror(_("strreplace: Not enough memory"));
173 found = -1;
174 }
175 else {
176 tmp = str;
177 limit = found; /* Countdown */
178 reslen = 0; /* length of current result */
179
180 /* Replace each old string found with new string */
181 while ((limit-- > 0) && (tmp = strstr(tmp, oldstr)) != NULL) {
182 length = (tmp - str); /* Number of chars to keep intouched */
183 strncpy(result + reslen, str, length); /* Original part keeped */
184 strcpy(result + (reslen += length), newstr); /* Insert new string */
185
186 reslen += newlen;
187 tmp += oldlen;
188 str = tmp;
189 }
190 strcpy(result + reslen, str); /* Copies last part and ending null char */
191 }
192
193 if (count != NULL) *count = found;
194 return result;
195}
196
197static char *
199 int j;
200
201 for (j = strlen(str) - 1; j >= 0; j--)
202 str[j] = tolower(str[j]);
203
204 return str;
205}
206
207/* split a string based on a delimiter */
208static char**
209strsplit(const char *str, const char *delimiter, uint32_t *n) {
210 char *tmp = NULL;
211 char **rtn = NULL;
212 char *token = NULL;
213
214 *n = 0;
215 if (!str)
216 return NULL;
217
218 /* copy str to tmp as strtok will mangle the string */
219 tmp = rtalloc(sizeof(char) * (strlen(str) + 1));
220 if (NULL == tmp) {
221 rterror(_("strsplit: Not enough memory"));
222 return NULL;
223 }
224 strcpy(tmp, str);
225
226 if (!strlen(tmp) || !delimiter || !strlen(delimiter)) {
227 *n = 1;
228 rtn = (char **) rtalloc(*n * sizeof(char *));
229 if (NULL == rtn) {
230 rterror(_("strsplit: Not enough memory"));
231 return NULL;
232 }
233 rtn[0] = (char *) rtalloc(sizeof(char) * (strlen(tmp) + 1));
234 if (NULL == rtn[0]) {
235 rterror(_("strsplit: Not enough memory"));
236 return NULL;
237 }
238 strcpy(rtn[0], tmp);
239 rtdealloc(tmp);
240 return rtn;
241 }
242
243 token = strtok(tmp, delimiter);
244 while (token != NULL) {
245 if (*n < 1) {
246 rtn = (char **) rtalloc(sizeof(char *));
247 }
248 else {
249 rtn = (char **) rtrealloc(rtn, (*n + 1) * sizeof(char *));
250 }
251 if (NULL == rtn) {
252 rterror(_("strsplit: Not enough memory"));
253 return NULL;
254 }
255
256 rtn[*n] = NULL;
257 rtn[*n] = (char *) rtalloc(sizeof(char) * (strlen(token) + 1));
258 if (NULL == rtn[*n]) {
259 rterror(_("strsplit: Not enough memory"));
260 return NULL;
261 }
262
263 strcpy(rtn[*n], token);
264 *n = *n + 1;
265
266 token = strtok(NULL, delimiter);
267 }
268
269 rtdealloc(tmp);
270 return rtn;
271}
272
273static char*
274trim(const char *input) {
275 char *rtn;
276 char *ptr;
277 uint32_t offset = 0;
278 size_t len = 0;
279
280 if (!input)
281 return NULL;
282 else if (!*input)
283 return (char *) input;
284
285 /* trim left */
286 while (isspace(*input))
287 input++;
288
289 /* trim right */
290 ptr = ((char *) input) + strlen(input);
291 while (isspace(*--ptr))
292 offset++;
293
294 len = strlen(input) - offset + 1;
295 rtn = rtalloc(sizeof(char) * len);
296 if (NULL == rtn) {
297 rterror(_("trim: Not enough memory"));
298 return NULL;
299 }
300 strncpy(rtn, input, len);
301
302 return rtn;
303}
304
305static char*
306chartrim(const char *input, char *remove) {
307 char *rtn = NULL;
308 char *ptr = NULL;
309 uint32_t offset = 0;
310 size_t len = 0;
311
312 if (!input)
313 return NULL;
314 else if (!*input)
315 return (char *) input;
316
317 /* trim left */
318 while (strchr(remove, *input) != NULL)
319 input++;
320
321 /* trim right */
322 ptr = ((char *) input) + strlen(input);
323 while (strchr(remove, *--ptr) != NULL)
324 offset++;
325
326 len = strlen(input) - offset + 1;
327 rtn = rtalloc(sizeof(char) * len);
328 if (NULL == rtn) {
329 rterror(_("chartrim: Not enough memory"));
330 return NULL;
331 }
332 strncpy(rtn, input, len);
333 rtn[strlen(input) - offset] = '\0';
334
335 return rtn;
336}
337
338static void
340 printf(_("RELEASE: %s GDAL_VERSION=%d (%s)\n"), POSTGIS_LIB_VERSION, POSTGIS_GDAL_VERSION, xstr(POSTGIS_REVISION));
341 printf(_(
342 "USAGE: raster2pgsql [<options>] <raster>[ <raster>[ ...]] [[<schema>.]<table>]\n"
343 " Multiple rasters can also be specified using wildcards (*,?).\n"
344 "\n"
345 "OPTIONS:\n"
346 ));
347 /*
348 printf(_(
349 " -s [<from>:]<srid> Set the SRID field. Defaults to %d.\n"
350 " Optionally reprojects from given SRID (cannot be used with -Y).\n"
351 " Raster's metadata will be checked to determine an appropriate SRID.\n"
352 " If a srid of %d is provided (either as from or as target).\n"
353 ), SRID_UNKNOWN, SRID_UNKNOWN);
354 */
355 printf(_(
356 " -s <srid> Set the SRID field. Defaults to %d. If SRID not\n"
357 " provided or is %d, raster's metadata will be checked to\n"
358 " determine an appropriate SRID.\n"
360 printf(_(
361 " -b <band> Index (1-based) of band to extract from raster. For more\n"
362 " than one band index, separate with comma (,). Ranges can be\n"
363 " defined by separating with dash (-). If unspecified, all bands\n"
364 " of raster will be extracted.\n"
365 ));
366 printf(_(
367 " -t <tile size> Cut raster into tiles to be inserted one per\n"
368 " table row. <tile size> is expressed as WIDTHxHEIGHT.\n"
369 " <tile size> can also be \"auto\" to allow the loader to compute\n"
370 " an appropriate tile size using the first raster and applied to\n"
371 " all rasters.\n"
372 ));
373 printf(_(
374 " -P Pad right-most and bottom-most tiles to guarantee that all tiles\n"
375 " have the same width and height.\n"
376 ));
377 printf(_(
378 " -R Register the raster as an out-of-db (filesystem) raster. Provided\n"
379 " raster should have absolute path to the file\n"
380 ));
381 printf(_(
382 " (-d|a|c|p) These are mutually exclusive options:\n"
383 " -d Drops the table, then recreates it and populates\n"
384 " it with current raster data.\n"
385 " -a Appends raster into current table, must be\n"
386 " exactly the same table schema.\n"
387 " -c Creates a new table and populates it, this is the\n"
388 " default if you do not specify any options.\n"
389 " -p Prepare mode, only creates the table.\n"
390 ));
391 printf(_(
392 " -f <column> Specify the name of the raster column\n"
393 ));
394 printf(_(
395 " -F Add a column with the filename of the raster.\n"
396 ));
397 printf(_(
398 " -n <column> Specify the name of the filename column. Implies -F.\n"
399 ));
400 printf(_(
401 " -l <overview factor> Create overview of the raster. For more than\n"
402 " one factor, separate with comma(,). Overview table name follows\n"
403 " the pattern o_<overview factor>_<table>. Created overview is\n"
404 " stored in the database and is not affected by -R.\n"
405 ));
406 printf(_(
407 " -q Wrap PostgreSQL identifiers in quotes.\n"
408 ));
409 printf(_(
410 " -I Create a GIST spatial index on the raster column. The ANALYZE\n"
411 " command will automatically be issued for the created index.\n"
412 ));
413 printf(_(
414 " -M Run VACUUM ANALYZE on the table of the raster column. Most\n"
415 " useful when appending raster to existing table with -a.\n"
416 ));
417 printf(_(
418 " -C Set the standard set of constraints on the raster\n"
419 " column after the rasters are loaded. Some constraints may fail\n"
420 " if one or more rasters violate the constraint.\n"
421 " -x Disable setting the max extent constraint. Only applied if\n"
422 " -C flag is also used.\n"
423 " -r Set the constraints (spatially unique and coverage tile) for\n"
424 " regular blocking. Only applied if -C flag is also used.\n"
425 ));
426 printf(_(
427 " -T <tablespace> Specify the tablespace for the new table.\n"
428 " Note that indices (including the primary key) will still use\n"
429 " the default tablespace unless the -X flag is also used.\n"
430 ));
431 printf(_(
432 " -X <tablespace> Specify the tablespace for the table's new index.\n"
433 " This applies to the primary key and the spatial index if\n"
434 " the -I flag is used.\n"
435 ));
436 printf(_(
437 " -N <nodata> NODATA value to use on bands without a NODATA value.\n"
438 ));
439 printf(_(
440 " -k Keep empty tiles by skipping NODATA value checks for each raster band. \n"
441 ));
442 printf(_(
443 " -E <endian> Control endianness of generated binary output of\n"
444 " raster. Use 0 for XDR and 1 for NDR (default). Only NDR\n"
445 " is supported at this time.\n"
446 ));
447 printf(_(
448 " -V <version> Specify version of output WKB format. Default\n"
449 " is 0. Only 0 is supported at this time.\n"
450 ));
451 printf(_(
452 " -e Execute each statement individually, do not use a transaction.\n"
453 ));
454 printf(_(
455 " -Y <max_rows_per_copy> Use COPY statements instead of INSERT statements. \n"
456 " Optionally specify <max_rows_per_copy>; default 50 when not specified. \n"
457 ));
458
459 printf(_(
460 " -G Print the supported GDAL raster formats.\n"
461 ));
462 printf(_(
463 " -? Display this help screen.\n"
464 ));
465}
466
467static void
468calc_tile_size(uint32_t dimX, uint32_t dimY, int *tileX, int *tileY)
469{
470 uint32_t min_tile_size = 30;
471 uint32_t max_tile_size = 300;
472
473 for (uint8_t current_dimension = 0; current_dimension <= 1; current_dimension++)
474 {
475 uint32_t img_size = (current_dimension == 0) ? dimX : dimY;
476 uint32_t best_gap = max_tile_size;
477 uint32_t best_size = img_size;
478
479 if (img_size > max_tile_size)
480 {
481 for (uint32_t tile_size = max_tile_size; tile_size >= min_tile_size; tile_size--)
482 {
483 uint32_t gap = img_size % tile_size;
484 if (gap < best_gap)
485 {
486 best_gap = gap;
487 best_size = tile_size;
488 }
489 }
490 }
491
492 if (current_dimension == 0)
493 *tileX = best_size;
494 else
495 *tileY = best_size;
496 }
497}
498
499static void
501 info->srid = SRID_UNKNOWN;
502 info->srs = NULL;
503 memset(info->dim, 0, sizeof(uint32_t) * 2);
504 info->nband_count = 0;
505 info->nband = NULL;
506 info->gdalbandtype = NULL;
507 info->bandtype = NULL;
508 info->hasnodata = NULL;
509 info->nodataval = NULL;
510 memset(info->gt, 0, sizeof(double) * 6);
511 memset(info->tile_size, 0, sizeof(int) * 2);
512}
513
514static void
516 if (info->srs != NULL)
517 rtdealloc(info->srs);
518 if (info->nband_count > 0 && info->nband != NULL)
519 rtdealloc(info->nband);
520 if (info->gdalbandtype != NULL)
521 rtdealloc(info->gdalbandtype);
522 if (info->bandtype != NULL)
523 rtdealloc(info->bandtype);
524 if (info->hasnodata != NULL)
525 rtdealloc(info->hasnodata);
526 if (info->nodataval != NULL)
527 rtdealloc(info->nodataval);
528}
529
530static int
532 if (src->srs != NULL) {
533 dst->srs = rtalloc(sizeof(char) * (strlen(src->srs) + 1));
534 if (dst->srs == NULL) {
535 rterror(_("copy_rastinfo: Not enough memory"));
536 return 0;
537 }
538 strcpy(dst->srs, src->srs);
539 }
540 memcpy(dst->dim, src->dim, sizeof(uint32_t) * 2);
541 dst->nband_count = src->nband_count;
542 if (src->nband_count && src->nband != NULL) {
543 dst->nband = rtalloc(sizeof(int) * src->nband_count);
544 if (dst->nband == NULL) {
545 rterror(_("copy_rastinfo: Not enough memory"));
546 return 0;
547 }
548 memcpy(dst->nband, src->nband, sizeof(int) * src->nband_count);
549 }
550 if (src->gdalbandtype != NULL) {
551 dst->gdalbandtype = rtalloc(sizeof(GDALDataType) * src->nband_count);
552 if (dst->gdalbandtype == NULL) {
553 rterror(_("copy_rastinfo: Not enough memory"));
554 return 0;
555 }
556 memcpy(dst->gdalbandtype, src->gdalbandtype, sizeof(GDALDataType) * src->nband_count);
557 }
558 if (src->bandtype != NULL) {
559 dst->bandtype = rtalloc(sizeof(rt_pixtype) * src->nband_count);
560 if (dst->bandtype == NULL) {
561 rterror(_("copy_rastinfo: Not enough memory"));
562 return 0;
563 }
564 memcpy(dst->bandtype, src->bandtype, sizeof(rt_pixtype) * src->nband_count);
565 }
566 if (src->hasnodata != NULL) {
567 dst->hasnodata = rtalloc(sizeof(int) * src->nband_count);
568 if (dst->hasnodata == NULL) {
569 rterror(_("copy_rastinfo: Not enough memory"));
570 return 0;
571 }
572 memcpy(dst->hasnodata, src->hasnodata, sizeof(int) * src->nband_count);
573 }
574 if (src->nodataval != NULL) {
575 dst->nodataval = rtalloc(sizeof(double) * src->nband_count);
576 if (dst->nodataval == NULL) {
577 rterror(_("copy_rastinfo: Not enough memory"));
578 return 0;
579 }
580 memcpy(dst->nodataval, src->nodataval, sizeof(double) * src->nband_count);
581 }
582 memcpy(dst->gt, src->gt, sizeof(double) * 6);
583 memcpy(dst->tile_size, src->tile_size, sizeof(int) * 2);
584
585 return 1;
586}
587
588static void
590 static uint8_t msg[6] = {0};
591 uint32_t i = 0;
592
593 /* # of bands */
594 if (
595 !msg[0] &&
596 x->nband_count != ref->nband_count
597 ) {
598 rtwarn(_("Different number of bands found in the set of rasters being converted to PostGIS raster"));
599 msg[0]++;
600 }
601
602 /* pixel types */
603 if (!msg[1]) {
604 for (i = 0; i < ref->nband_count; i++) {
605 if (x->bandtype[i] != ref->bandtype[i]) {
606 rtwarn(_("Different pixel types found for band %d in the set of rasters being converted to PostGIS raster"), ref->nband[i]);
607 msg[1]++;
608 }
609 }
610 }
611
612 /* hasnodata */
613 if (!msg[2]) {
614 for (i = 0; i < ref->nband_count; i++) {
615 if (x->hasnodata[i] != ref->hasnodata[i]) {
616 rtwarn(_("Different hasnodata flags found for band %d in the set of rasters being converted to PostGIS raster"), ref->nband[i]);
617 msg[2]++;
618 }
619 }
620 }
621
622 /* nodataval */
623 if (!msg[3]) {
624 for (i = 0; i < ref->nband_count; i++) {
625 if (!x->hasnodata[i] && !ref->hasnodata[i]) continue;
626 if (x->hasnodata[i] != ref->hasnodata[i]) {
627 rtwarn(_("Different NODATA values found for band %d in the set of rasters being converted to PostGIS raster"), ref->nband[i]);
628 msg[3]++;
629 }
630 }
631 }
632
633 /* alignment */
634 if (!msg[4]) {
635 rt_raster rx = NULL;
636 rt_raster rref = NULL;
637 int err;
638 int aligned;
639
640 if (
641 (rx = rt_raster_new(1, 1)) == NULL ||
642 (rref = rt_raster_new(1, 1)) == NULL
643 ) {
644 rterror(_("diff_rastinfo: Could not allocate memory for raster alignment test"));
645 if (rx != NULL) rt_raster_destroy(rx);
646 if (rref != NULL) rt_raster_destroy(rref);
647 return;
648 }
649
652
653 err = rt_raster_same_alignment(rx, rref, &aligned, NULL);
655 rt_raster_destroy(rref);
656 if (err != ES_NONE) {
657 rterror(_("diff_rastinfo: Could not run raster alignment test"));
658 return;
659 }
660
661 if (!aligned) {
662 rtwarn(_("Raster with different alignment found in the set of rasters being converted to PostGIS raster"));
663 msg[4]++;
664 }
665 }
666
667 /* tile size */
668 if (!msg[5]) {
669 for (i = 0; i < 2; i++) {
670 if (x->tile_size[i] != ref->tile_size[i]) {
671 rtwarn(_("Different tile sizes found in the set of rasters being converted to PostGIS raster"));
672 msg[5]++;
673 break;
674 }
675 }
676 }
677}
678
679static void
681 config->rt_file_count = 0;
682 config->rt_file = NULL;
683 config->rt_filename = NULL;
684 config->schema = NULL;
685 config->table = NULL;
686 config->raster_column = NULL;
687 config->file_column = 0;
688 config->file_column_name = NULL;
689 config->overview_count = 0;
690 config->overview = NULL;
691 config->overview_table = NULL;
692 config->quoteident = 0;
693 config->srid = config->out_srid = SRID_UNKNOWN;
694 config->nband = NULL;
695 config->nband_count = 0;
696 memset(config->tile_size, 0, sizeof(int) * 2);
697 config->pad_tile = 0;
698 config->outdb = 0;
699 config->opt = 'c';
700 config->idx = 0;
701 config->maintenance = 0;
702 config->constraints = 0;
703 config->max_extent = 1;
704 config->regular_blocking = 0;
705 config->tablespace = NULL;
706 config->idx_tablespace = NULL;
707 config->hasnodata = 0;
708 config->nodataval = 0;
709 config->skip_nodataval_check = 0;
710 config->endian = 1;
711 config->version = 0;
712 config->transaction = 1;
713 config->copy_statements = 0;
714 config->max_tiles_per_copy = 50;
715}
716
717static void
719 int i = 0;
720 if (config->rt_file_count) {
721 for (i = config->rt_file_count - 1; i >= 0; i--) {
722 rtdealloc(config->rt_file[i]);
723 if (config->rt_filename)
724 rtdealloc(config->rt_filename[i]);
725 }
726 rtdealloc(config->rt_file);
727 if (config->rt_filename)
728 rtdealloc(config->rt_filename);
729 }
730 if (config->schema != NULL)
731 rtdealloc(config->schema);
732 if (config->table != NULL)
733 rtdealloc(config->table);
734 if (config->raster_column != NULL)
735 rtdealloc(config->raster_column);
736 if (config->file_column_name != NULL)
738 if (config->overview_count > 0) {
739 if (config->overview != NULL)
740 rtdealloc(config->overview);
741 if (config->overview_table != NULL) {
742 for (i = config->overview_count - 1; i >= 0; i--)
743 rtdealloc(config->overview_table[i]);
744 rtdealloc(config->overview_table);
745 }
746 }
747 if (config->nband_count > 0 && config->nband != NULL)
748 rtdealloc(config->nband);
749 if (config->tablespace != NULL)
750 rtdealloc(config->tablespace);
751 if (config->idx_tablespace != NULL)
752 rtdealloc(config->idx_tablespace);
753
754 rtdealloc(config);
755}
756
757static void
759 buffer->line = NULL;
760 buffer->length = 0;
761}
762
763static void
765 if (buffer->length) {
766 uint32_t i = 0;
767 for (i = 0; i < buffer->length; i++) {
768 if (buffer->line[i] != NULL)
769 rtdealloc(buffer->line[i]);
770 }
771 rtdealloc(buffer->line);
772 }
773 buffer->line = NULL;
774 buffer->length = 0;
775
776 if (freebuffer)
778}
779
780static void
782 uint32_t i = 0;
783
784 for (i = 0; i < buffer->length; i++) {
785 printf("%s\n", buffer->line[i]);
786 }
787}
788
789static void
794
795/* Takes ownership of the passed string */
796static int
798 buffer->length++;
799
800 buffer->line = rtrealloc(buffer->line, sizeof(char *) * buffer->length);
801 if (buffer->line == NULL) {
802 rterror(_("append_stringbuffer: Could not allocate memory for appending string to buffer"));
803 return 0;
804 }
805
806 buffer->line[buffer->length - 1] = (char *) str;
807
808 return 1;
809}
810
811static int
813 if (buffer->length > 9)
815
817}
818
819static int
820copy_from(const char *schema, const char *table, const char *column,
821 const char *filename, const char *file_column_name,
823{
824 char *sql = NULL;
825 uint32_t len = 0;
826
827 assert(table != NULL);
828 assert(column != NULL);
829
830 len = strlen("COPY () FROM stdin;") + 1;
831 if (schema != NULL)
832 len += strlen(schema);
833 len += strlen(table);
834 len += strlen(column);
835 if (filename != NULL)
836 len += strlen(",") + strlen(file_column_name);
837
838 sql = rtalloc(sizeof(char) * len);
839 if (sql == NULL) {
840 rterror(_("copy_from: Could not allocate memory for COPY statement"));
841 return 0;
842 }
843 sprintf(sql, "COPY %s%s (%s%s%s) FROM stdin;",
844 (schema != NULL ? schema : ""),
845 table,
846 column,
847 (filename != NULL ? "," : ""),
848 (filename != NULL ? file_column_name : "")
849 );
850
852 sql = NULL;
853
854 return 1;
855}
856
857static int
859{
860 /* end of data */
861 append_sql_to_buffer(buffer, strdup("\\."));
862
863 return 1;
864}
865
866static int
868 const char *schema, const char *table, const char *column,
869 const char *filename, const char *file_column_name,
870 int copy_statements, int out_srid,
872) {
873 char *fn = NULL;
874 uint32_t len = 0;
875 char *sql = NULL;
876 uint32_t x = 0;
877
878 assert(table != NULL);
879 assert(column != NULL);
880
881 /* COPY statements */
882 if (copy_statements) {
883
884 if (!copy_from(
885 schema, table, column,
886 (file_column_name ? filename : NULL), file_column_name,
887 buffer
888 )) {
889 rterror(_("insert_records: Could not add COPY statement to string buffer"));
890 return 0;
891 }
892
893
894 /* escape tabs in filename */
895 if (filename != NULL)
896 fn = strreplace(filename, "\t", "\\t", NULL);
897
898 /* rows */
899 for (x = 0; x < tileset->length; x++) {
900 len = strlen(tileset->line[x]) + 1;
901
902 if (filename != NULL)
903 len += strlen(fn) + 1;
904
905 sql = rtalloc(sizeof(char) * len);
906 if (sql == NULL) {
907 rterror(_("insert_records: Could not allocate memory for COPY statement"));
908 return 0;
909 }
910 sprintf(sql, "%s%s%s",
911 tileset->line[x],
912 (filename != NULL ? "\t" : ""),
913 (filename != NULL ? fn : "")
914 );
915
917 sql = NULL;
918 }
919
920 if (!copy_from_end(buffer)) {
921 rterror(_("process_rasters: Could not add COPY end statement to string buffer"));
922 return 0;
923 }
924
925 }
926 /* INSERT statements */
927 else {
928 len = strlen("INSERT INTO () VALUES (ST_Transform(''::raster,xxxxxxxxx));") + 1;
929 if (schema != NULL)
930 len += strlen(schema);
931 len += strlen(table);
932 len += strlen(column);
933 if (filename != NULL)
934 len += strlen(",") + strlen(file_column_name);
935
936 /* escape single-quotes in filename */
937 if (filename != NULL)
938 fn = strreplace(filename, "'", "''", NULL);
939
940 for (x = 0; x < tileset->length; x++) {
941 char *ptr;
942 int sqllen = len;
943
944 sqllen += strlen(tileset->line[x]);
945 if (filename != NULL)
946 sqllen += strlen(",''") + strlen(fn);
947
948 sql = rtalloc(sizeof(char) * sqllen);
949 if (sql == NULL) {
950 rterror(_("insert_records: Could not allocate memory for INSERT statement"));
951 return 0;
952 }
953 ptr = sql;
954 ptr += sprintf(sql, "INSERT INTO %s%s (%s%s%s) VALUES (",
955 (schema != NULL ? schema : ""),
956 table,
957 column,
958 (filename != NULL ? "," : ""),
959 (filename != NULL ? file_column_name : "")
960 );
961 if (out_srid != SRID_UNKNOWN) {
962 ptr += sprintf(ptr, "ST_Transform(");
963 }
964 ptr += sprintf(ptr, "'%s'::raster",
965 tileset->line[x]
966 );
967 if (out_srid != SRID_UNKNOWN) {
968 ptr += sprintf(ptr, ", %d)", out_srid);
969 }
970 if (filename != NULL) {
971 ptr += sprintf(ptr, ",'%s'", fn);
972 }
973 ptr += sprintf(ptr, ");");
974
976 sql = NULL;
977 }
978 }
979
980 if (fn != NULL) rtdealloc(fn);
981 return 1;
982}
983
984static int
985drop_table(const char *schema, const char *table, STRINGBUFFER *buffer) {
986 char *sql = NULL;
987 uint32_t len = 0;
988
989 len = strlen("DROP TABLE IF EXISTS ;") + 1;
990 if (schema != NULL)
991 len += strlen(schema);
992 len += strlen(table);
993
994 sql = rtalloc(sizeof(char) * len);
995 if (sql == NULL) {
996 rterror(_("drop_table: Could not allocate memory for DROP TABLE statement"));
997 return 0;
998 }
999 sprintf(sql, "DROP TABLE IF EXISTS %s%s;",
1000 (schema != NULL ? schema : ""),
1001 table
1002 );
1003
1005
1006 return 1;
1007}
1008
1009static int
1011 const char *schema, const char *table, const char *column,
1012 const int file_column, const char *file_column_name,
1013 const char *tablespace, const char *idx_tablespace,
1015) {
1016 char *sql = NULL;
1017 uint32_t len = 0;
1018
1019 assert(table != NULL);
1020 assert(column != NULL);
1021
1022 len = strlen("CREATE TABLE (\"rid\" serial PRIMARY KEY, raster);") + 1;
1023 if (schema != NULL)
1024 len += strlen(schema);
1025 len += strlen(table);
1026 len += strlen(column);
1027 if (file_column)
1028 len += strlen(", text") + strlen(file_column_name);
1029 if (tablespace != NULL)
1030 len += strlen(" TABLESPACE ") + strlen(tablespace);
1031 if (idx_tablespace != NULL)
1032 len += strlen(" USING INDEX TABLESPACE ") + strlen(idx_tablespace);
1033
1034 sql = rtalloc(sizeof(char) * len);
1035 if (sql == NULL) {
1036 rterror(_("create_table: Could not allocate memory for CREATE TABLE statement"));
1037 return 0;
1038 }
1039 sprintf(sql, "CREATE TABLE %s%s (\"rid\" serial PRIMARY KEY%s%s,%s raster%s%s%s)%s%s;",
1040 (schema != NULL ? schema : ""),
1041 table,
1042 (idx_tablespace != NULL ? " USING INDEX TABLESPACE " : ""),
1043 (idx_tablespace != NULL ? idx_tablespace : ""),
1044 column,
1045 (file_column ? "," : ""),
1046 (file_column ? file_column_name : ""),
1047 (file_column ? " text" : ""),
1048 (tablespace != NULL ? " TABLESPACE " : ""),
1049 (tablespace != NULL ? tablespace : "")
1050 );
1051
1053
1054 return 1;
1055}
1056
1057static int
1059 const char *schema, const char *table, const char *column,
1060 const char *tablespace,
1062) {
1063 char *sql = NULL;
1064 uint32_t len = 0;
1065 char *_table = NULL;
1066 char *_column = NULL;
1067
1068 assert(table != NULL);
1069 assert(column != NULL);
1070
1071 _table = chartrim(table, "\"");
1072 _column = chartrim(column, "\"");
1073
1074 /* create index */
1075 len = strlen("CREATE INDEX \"__gist\" ON USING gist (st_convexhull());") + 1;
1076 if (schema != NULL)
1077 len += strlen(schema);
1078 len += strlen(_table);
1079 len += strlen(_column);
1080 len += strlen(table);
1081 len += strlen(column);
1082 if (tablespace != NULL)
1083 len += strlen(" TABLESPACE ") + strlen(tablespace);
1084
1085 sql = rtalloc(sizeof(char) * len);
1086 if (sql == NULL) {
1087 rterror(_("create_index: Could not allocate memory for CREATE INDEX statement"));
1088 rtdealloc(_table);
1089 rtdealloc(_column);
1090 return 0;
1091 }
1092 sprintf(sql, "CREATE INDEX ON %s%s USING gist (st_convexhull(%s))%s%s;",
1093 (schema != NULL ? schema : ""),
1094 table,
1095 column,
1096 (tablespace != NULL ? " TABLESPACE " : ""),
1097 (tablespace != NULL ? tablespace : "")
1098 );
1099 rtdealloc(_table);
1100 rtdealloc(_column);
1101
1103
1104 return 1;
1105}
1106
1107static int
1109 const char *schema, const char *table,
1111) {
1112 char *sql = NULL;
1113 uint32_t len = 0;
1114
1115 assert(table != NULL);
1116
1117 len = strlen("ANALYZE ;") + 1;
1118 if (schema != NULL)
1119 len += strlen(schema);
1120 len += strlen(table);
1121
1122 sql = rtalloc(sizeof(char) * len);
1123 if (sql == NULL) {
1124 rterror(_("analyze_table: Could not allocate memory for ANALYZE TABLE statement"));
1125 return 0;
1126 }
1127 sprintf(sql, "ANALYZE %s%s;",
1128 (schema != NULL ? schema : ""),
1129 table
1130 );
1131
1133
1134 return 1;
1135}
1136
1137static int
1139 const char *schema, const char *table,
1141) {
1142 char *sql = NULL;
1143 uint32_t len = 0;
1144
1145 assert(table != NULL);
1146
1147 len = strlen("VACUUM ANALYZE ;") + 1;
1148 if (schema != NULL)
1149 len += strlen(schema);
1150 len += strlen(table);
1151
1152 sql = rtalloc(sizeof(char) * len);
1153 if (sql == NULL) {
1154 rterror(_("vacuum_table: Could not allocate memory for VACUUM statement"));
1155 return 0;
1156 }
1157 sprintf(sql, "VACUUM ANALYZE %s%s;",
1158 (schema != NULL ? schema : ""),
1159 table
1160 );
1161
1163
1164 return 1;
1165}
1166
1167static int
1169 const char *schema, const char *table, const char *column,
1170 int regular_blocking, int max_extent,
1172) {
1173 char *sql = NULL;
1174 uint32_t len = 0;
1175
1176 char *_tmp = NULL;
1177 char *_schema = NULL;
1178 char *_table = NULL;
1179 char *_column = NULL;
1180
1181 assert(table != NULL);
1182 assert(column != NULL);
1183
1184 /* schema */
1185 if (schema != NULL) {
1186 _tmp = chartrim(schema, ".");
1187 _schema = chartrim(_tmp, "\"");
1188 rtdealloc(_tmp);
1189 _tmp = strreplace(_schema, "'", "''", NULL);
1190 rtdealloc(_schema);
1191 _schema = _tmp;
1192 }
1193
1194 /* table */
1195 _tmp = chartrim(table, "\"");
1196 _table = strreplace(_tmp, "'", "''", NULL);
1197 rtdealloc(_tmp);
1198
1199 /* column */
1200 _tmp = chartrim(column, "\"");
1201 _column = strreplace(_tmp, "'", "''", NULL);
1202 rtdealloc(_tmp);
1203
1204 len = strlen("SELECT AddRasterConstraints('','','',TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,FALSE,TRUE,TRUE,TRUE,TRUE,FALSE);") + 1;
1205 if (_schema != NULL)
1206 len += strlen(_schema);
1207 len += strlen(_table);
1208 len += strlen(_column);
1209
1210 sql = rtalloc(sizeof(char) * len);
1211 if (sql == NULL) {
1212 rterror(_("add_raster_constraints: Could not allocate memory for AddRasterConstraints statement"));
1213 return 0;
1214 }
1215 sprintf(sql, "SELECT AddRasterConstraints('%s','%s','%s',TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,%s,TRUE,TRUE,TRUE,TRUE,%s);",
1216 (_schema != NULL ? _schema : ""),
1217 _table,
1218 _column,
1219 (regular_blocking ? "TRUE" : "FALSE"),
1220 (max_extent ? "TRUE" : "FALSE")
1221 );
1222
1223 if (_schema != NULL)
1224 rtdealloc(_schema);
1225 rtdealloc(_table);
1226 rtdealloc(_column);
1227
1229
1230 return 1;
1231}
1232
1233static int
1235 const char *ovschema, const char *ovtable, const char *ovcolumn,
1236 const char *schema, const char *table, const char *column,
1237 const int factor,
1239) {
1240 char *sql = NULL;
1241 uint32_t len = 0;
1242
1243 char *_tmp = NULL;
1244
1245 char *_ovschema = NULL;
1246 char *_ovtable = NULL;
1247 char *_ovcolumn = NULL;
1248
1249 char *_schema = NULL;
1250 char *_table = NULL;
1251 char *_column = NULL;
1252
1253 assert(ovtable != NULL);
1254 assert(ovcolumn != NULL);
1255 assert(table != NULL);
1256 assert(column != NULL);
1257 assert(factor >= MINOVFACTOR && factor <= MAXOVFACTOR);
1258
1259 /* overview schema */
1260 if (ovschema != NULL) {
1261 _tmp = chartrim(ovschema, ".");
1262 _ovschema = chartrim(_tmp, "\"");
1263 rtdealloc(_tmp);
1264 _tmp = strreplace(_ovschema, "'", "''", NULL);
1265 rtdealloc(_ovschema);
1266 _ovschema = _tmp;
1267 }
1268
1269 /* overview table */
1270 _tmp = chartrim(ovtable, "\"");
1271 _ovtable = strreplace(_tmp, "'", "''", NULL);
1272 rtdealloc(_tmp);
1273
1274 /* overview column*/
1275 _tmp = chartrim(ovcolumn, "\"");
1276 _ovcolumn = strreplace(_tmp, "'", "''", NULL);
1277 rtdealloc(_tmp);
1278
1279 /* schema */
1280 if (schema != NULL) {
1281 _tmp = chartrim(schema, ".");
1282 _schema = chartrim(_tmp, "\"");
1283 rtdealloc(_tmp);
1284 _tmp = strreplace(_schema, "'", "''", NULL);
1285 rtdealloc(_schema);
1286 _schema = _tmp;
1287 }
1288
1289 /* table */
1290 _tmp = chartrim(table, "\"");
1291 _table = strreplace(_tmp, "'", "''", NULL);
1292 rtdealloc(_tmp);
1293
1294 /* column */
1295 _tmp = chartrim(column, "\"");
1296 _column = strreplace(_tmp, "'", "''", NULL);
1297 rtdealloc(_tmp);
1298
1299 len = strlen("SELECT AddOverviewConstraints('','','','','','',);") + 5;
1300 if (_ovschema != NULL)
1301 len += strlen(_ovschema);
1302 len += strlen(_ovtable);
1303 len += strlen(_ovcolumn);
1304 if (_schema != NULL)
1305 len += strlen(_schema);
1306 len += strlen(_table);
1307 len += strlen(_column);
1308
1309 sql = rtalloc(sizeof(char) * len);
1310 if (sql == NULL) {
1311 rterror(_("add_overview_constraints: Could not allocate memory for AddOverviewConstraints statement"));
1312 return 0;
1313 }
1314 sprintf(sql, "SELECT AddOverviewConstraints('%s','%s','%s','%s','%s','%s',%d);",
1315 (_ovschema != NULL ? _ovschema : ""),
1316 _ovtable,
1317 _ovcolumn,
1318 (_schema != NULL ? _schema : ""),
1319 _table,
1320 _column,
1321 factor
1322 );
1323
1324 if (_ovschema != NULL)
1325 rtdealloc(_ovschema);
1326 rtdealloc(_ovtable);
1327 rtdealloc(_ovcolumn);
1328
1329 if (_schema != NULL)
1330 rtdealloc(_schema);
1331 rtdealloc(_table);
1332 rtdealloc(_column);
1333
1335
1336 return 1;
1337}
1338
1339static int
1340build_overview(int idx, RTLOADERCFG *config, RASTERINFO *info, uint32_t ovx, STRINGBUFFER *tileset, STRINGBUFFER *buffer) {
1341 GDALDatasetH hdsSrc;
1342 VRTDatasetH hdsOv;
1343 VRTSourcedRasterBandH hbandOv;
1344 double gtOv[6] = {0.};
1345 int dimOv[2] = {0};
1346
1347 uint32_t j = 0;
1348 int factor;
1349 const char *ovtable = NULL;
1350
1351 VRTDatasetH hdsDst;
1352 VRTSourcedRasterBandH hbandDst;
1353 int tile_size[2] = {0};
1354 int _tile_size[2] = {0};
1355 int ntiles[2] = {1, 1};
1356 int xtile = 0;
1357 int ytile = 0;
1358 double gt[6] = {0.};
1359
1360 rt_raster rast = NULL;
1361 char *hex;
1362 uint32_t hexlen = 0;
1363
1364 hdsSrc = GDALOpenShared(config->rt_file[idx], GA_ReadOnly);
1365 if (hdsSrc == NULL) {
1366 rterror(_("build_overview: Could not open raster: %s"), config->rt_file[idx]);
1367 return 0;
1368 }
1369
1370 /* working copy of geotransform matrix */
1371 memcpy(gtOv, info->gt, sizeof(double) * 6);
1372
1373 if (ovx >= config->overview_count) {
1374 rterror(_("build_overview: Invalid overview index: %d"), ovx);
1375 return 0;
1376 }
1377 factor = config->overview[ovx];
1378 ovtable = (const char *) config->overview_table[ovx];
1379
1380 /* factor must be within valid range */
1381 if (factor < MINOVFACTOR || factor > MAXOVFACTOR) {
1382 rterror(_("build_overview: Overview factor %d is not between %d and %d"), factor, MINOVFACTOR, MAXOVFACTOR);
1383 return 0;
1384 }
1385
1386 dimOv[0] = (int) (info->dim[0] + (factor / 2)) / factor;
1387 dimOv[1] = (int) (info->dim[1] + (factor / 2)) / factor;
1388
1389 /* create VRT dataset */
1390 hdsOv = VRTCreate(dimOv[0], dimOv[1]);
1391 /*
1392 GDALSetDescription(hdsOv, "/tmp/ov.vrt");
1393 */
1394 GDALSetProjection(hdsOv, info->srs);
1395
1396 /* adjust scale */
1397 gtOv[1] *= factor;
1398 gtOv[5] *= factor;
1399
1400 GDALSetGeoTransform(hdsOv, gtOv);
1401
1402 /* add bands as simple sources */
1403 for (j = 0; j < info->nband_count; j++) {
1404 GDALAddBand(hdsOv, info->gdalbandtype[j], NULL);
1405 hbandOv = (VRTSourcedRasterBandH) GDALGetRasterBand(hdsOv, j + 1);
1406
1407 if (info->hasnodata[j])
1408 GDALSetRasterNoDataValue(hbandOv, info->nodataval[j]);
1409
1410 VRTAddSimpleSource(
1411 hbandOv, GDALGetRasterBand(hdsSrc, info->nband[j]),
1412 0, 0,
1413 info->dim[0], info->dim[1],
1414 0, 0,
1415 dimOv[0], dimOv[1],
1416 "near", VRT_NODATA_UNSET
1417 );
1418 }
1419
1420 /* make sure VRT reflects all changes */
1421 VRTFlushCache(hdsOv);
1422
1423 /* decide on tile size */
1424 if (!config->tile_size[0])
1425 tile_size[0] = dimOv[0];
1426 else
1427 tile_size[0] = config->tile_size[0];
1428 if (!config->tile_size[1])
1429 tile_size[1] = dimOv[1];
1430 else
1431 tile_size[1] = config->tile_size[1];
1432
1433 /* number of tiles */
1434 if (
1435 tile_size[0] != dimOv[0] &&
1436 tile_size[1] != dimOv[1]
1437 ) {
1438 ntiles[0] = (dimOv[0] + tile_size[0] - 1) / tile_size[0];
1439 ntiles[1] = (dimOv[1] + tile_size[1] - 1) / tile_size[1];
1440 }
1441
1442 /* working copy of geotransform matrix */
1443 memcpy(gt, gtOv, sizeof(double) * 6);
1444
1445 /* tile overview */
1446 /* each tile is a VRT with constraints set for just the data required for the tile */
1447 for (ytile = 0; ytile < ntiles[1]; ytile++) {
1448
1449 /* edge y tile */
1450 if (!config->pad_tile && ntiles[1] > 1 && (ytile + 1) == ntiles[1])
1451 _tile_size[1] = dimOv[1] - (ytile * tile_size[1]);
1452 else
1453 _tile_size[1] = tile_size[1];
1454
1455 for (xtile = 0; xtile < ntiles[0]; xtile++) {
1456 /*
1457 char fn[100];
1458 sprintf(fn, "/tmp/ovtile%d.vrt", (ytile * ntiles[0]) + xtile);
1459 */
1460
1461 /* edge x tile */
1462 if (!config->pad_tile && ntiles[0] > 1 && (xtile + 1) == ntiles[0])
1463 _tile_size[0] = dimOv[0] - (xtile * tile_size[0]);
1464 else
1465 _tile_size[0] = tile_size[0];
1466
1467 /* compute tile's upper-left corner */
1468 GDALApplyGeoTransform(
1469 gtOv,
1470 xtile * tile_size[0], ytile * tile_size[1],
1471 &(gt[0]), &(gt[3])
1472 );
1473
1474 /* create VRT dataset */
1475 hdsDst = VRTCreate(_tile_size[0], _tile_size[1]);
1476 /*
1477 GDALSetDescription(hdsDst, fn);
1478 */
1479 GDALSetProjection(hdsDst, info->srs);
1480 GDALSetGeoTransform(hdsDst, gt);
1481
1482 /* add bands as simple sources */
1483 for (j = 0; j < info->nband_count; j++) {
1484 GDALAddBand(hdsDst, info->gdalbandtype[j], NULL);
1485 hbandDst = (VRTSourcedRasterBandH) GDALGetRasterBand(hdsDst, j + 1);
1486
1487 if (info->hasnodata[j])
1488 GDALSetRasterNoDataValue(hbandDst, info->nodataval[j]);
1489
1490 VRTAddSimpleSource(
1491 hbandDst, GDALGetRasterBand(hdsOv, j + 1),
1492 xtile * tile_size[0], ytile * tile_size[1],
1493 _tile_size[0], _tile_size[1],
1494 0, 0,
1495 _tile_size[0], _tile_size[1],
1496 "near", VRT_NODATA_UNSET
1497 );
1498 }
1499
1500 /* make sure VRT reflects all changes */
1501 VRTFlushCache(hdsDst);
1502
1503 /* convert VRT dataset to rt_raster */
1504 rast = rt_raster_from_gdal_dataset(hdsDst);
1505 if (rast == NULL) {
1506 rterror(_("build_overview: Could not convert VRT dataset to PostGIS raster"));
1507 GDALClose(hdsDst);
1508 return 0;
1509 }
1510
1511 /* set srid if provided */
1512 rt_raster_set_srid(rast, info->srid);
1513
1514 /* convert rt_raster to hexwkb */
1515 hex = rt_raster_to_hexwkb(rast, FALSE, &hexlen);
1516 raster_destroy(rast);
1517
1518 if (hex == NULL) {
1519 rterror(_("build_overview: Could not convert PostGIS raster to hex WKB"));
1520 GDALClose(hdsDst);
1521 return 0;
1522 }
1523
1524 /* add hexwkb to tileset */
1525 append_stringbuffer(tileset, hex);
1526
1527 GDALClose(hdsDst);
1528
1529 /* flush if tileset gets too big */
1530 if (tileset->length >= config->max_tiles_per_copy) {
1531 if (!insert_records(
1532 config->schema, ovtable, config->raster_column,
1533 (config->file_column ? config->rt_filename[idx] : NULL), config->file_column_name,
1534 config->copy_statements, config->out_srid,
1535 tileset, buffer
1536 )) {
1537 rterror(_("build_overview: Could not convert raster tiles into INSERT or COPY statements"));
1538 GDALClose(hdsSrc);
1539 return 0;
1540 }
1541
1542 rtdealloc_stringbuffer(tileset, 0);
1543 }
1544 }
1545 }
1546
1547 GDALClose(hdsOv);
1548 GDALClose(hdsSrc);
1549 return 1;
1550}
1551
1552static int
1554 GDALDatasetH hdsSrc;
1555 GDALRasterBandH hbandSrc;
1556 int nband = 0;
1557 uint32_t i = 0;
1558 int ntiles[2] = {1, 1};
1559 int _tile_size[2] = {0, 0};
1560 int xtile = 0;
1561 int ytile = 0;
1562 int naturalx = 1;
1563 int naturaly = 1;
1564 double gt[6] = {0.};
1565 const char* pszProjectionRef = NULL;
1566 int tilesize = 0;
1567
1568 rt_raster rast = NULL;
1569 uint32_t numbands = 0;
1570 rt_band band = NULL;
1571 char *hex;
1572 uint32_t hexlen = 0;
1573
1574 info->srid = config->srid;
1575
1576 hdsSrc = GDALOpenShared(config->rt_file[idx], GA_ReadOnly);
1577 if (hdsSrc == NULL) {
1578 rterror(_("convert_raster: Could not open raster: %s"), config->rt_file[idx]);
1579 return 0;
1580 }
1581
1582 nband = GDALGetRasterCount(hdsSrc);
1583 if (!nband) {
1584 rterror(_("convert_raster: No bands found in raster: %s"), config->rt_file[idx]);
1585 GDALClose(hdsSrc);
1586 return 0;
1587 }
1588
1589 /* check that bands specified are available */
1590 for (i = 0; i < config->nband_count; i++) {
1591 if (config->nband[i] > nband) {
1592 rterror(_("convert_raster: Band %d not found in raster: %s"), config->nband[i], config->rt_file[idx]);
1593 GDALClose(hdsSrc);
1594 return 0;
1595 }
1596 }
1597
1598 /* record srs */
1599 pszProjectionRef = GDALGetProjectionRef(hdsSrc);
1600 if (pszProjectionRef != NULL && pszProjectionRef[0] != '\0') {
1601 info->srs = rtalloc(sizeof(char) * (strlen(pszProjectionRef) + 1));
1602 if (info->srs == NULL) {
1603 rterror(_("convert_raster: Could not allocate memory for storing SRS"));
1604 GDALClose(hdsSrc);
1605 return 0;
1606 }
1607 strcpy(info->srs, pszProjectionRef);
1608
1609 if (info->srid == SRID_UNKNOWN) {
1610 OGRSpatialReferenceH hSRS = OSRNewSpatialReference(NULL);
1611 if (OSRSetFromUserInput(hSRS, pszProjectionRef) == OGRERR_NONE) {
1612 const char* pszAuthorityName = OSRGetAuthorityName(hSRS, NULL);
1613 const char* pszAuthorityCode = OSRGetAuthorityCode(hSRS, NULL);
1614 if (
1615 pszAuthorityName != NULL &&
1616 strcmp(pszAuthorityName, "EPSG") == 0 &&
1617 pszAuthorityCode != NULL
1618 ) {
1619 info->srid = atoi(pszAuthorityCode);
1620 }
1621 }
1622 OSRDestroySpatialReference(hSRS);
1623 }
1624 }
1625
1626 if ( info->srid == SRID_UNKNOWN && config->out_srid != SRID_UNKNOWN ) {
1627 rterror(_("convert_raster: could not determine source srid, cannot transform to target srid %d"), config->out_srid);
1628 GDALClose(hdsSrc);
1629 return 0;
1630 }
1631
1632 /* record geotransform matrix */
1633 if (GDALGetGeoTransform(hdsSrc, info->gt) != CE_None) {
1634 rtinfo(_("Using default geotransform matrix (0, 1, 0, 0, 0, -1) for raster: %s"), config->rt_file[idx]);
1635 info->gt[0] = 0;
1636 info->gt[1] = 1;
1637 info->gt[2] = 0;
1638 info->gt[3] = 0;
1639 info->gt[4] = 0;
1640 info->gt[5] = -1;
1641 }
1642 memcpy(gt, info->gt, sizeof(double) * 6);
1643
1644 /* record # of bands */
1645 /* user-specified bands */
1646 if (config->nband_count > 0) {
1647 info->nband_count = config->nband_count;
1648 info->nband = rtalloc(sizeof(int) * info->nband_count);
1649 if (info->nband == NULL) {
1650 rterror(_("convert_raster: Could not allocate memory for storing band indices"));
1651 GDALClose(hdsSrc);
1652 return 0;
1653 }
1654 memcpy(info->nband, config->nband, sizeof(int) * info->nband_count);
1655 }
1656 /* all bands */
1657 else {
1658 info->nband_count = nband;
1659 info->nband = rtalloc(sizeof(int) * info->nband_count);
1660 if (info->nband == NULL) {
1661 rterror(_("convert_raster: Could not allocate memory for storing band indices"));
1662 GDALClose(hdsSrc);
1663 return 0;
1664 }
1665 for (i = 0; i < info->nband_count; i++)
1666 info->nband[i] = i + 1;
1667 }
1668
1669 /* initialize parameters dependent on nband */
1670 info->gdalbandtype = rtalloc(sizeof(GDALDataType) * info->nband_count);
1671 if (info->gdalbandtype == NULL) {
1672 rterror(_("convert_raster: Could not allocate memory for storing GDAL data type"));
1673 GDALClose(hdsSrc);
1674 return 0;
1675 }
1676 info->bandtype = rtalloc(sizeof(rt_pixtype) * info->nband_count);
1677 if (info->bandtype == NULL) {
1678 rterror(_("convert_raster: Could not allocate memory for storing pixel type"));
1679 GDALClose(hdsSrc);
1680 return 0;
1681 }
1682 info->hasnodata = rtalloc(sizeof(int) * info->nband_count);
1683 if (info->hasnodata == NULL) {
1684 rterror(_("convert_raster: Could not allocate memory for storing hasnodata flag"));
1685 GDALClose(hdsSrc);
1686 return 0;
1687 }
1688 info->nodataval = rtalloc(sizeof(double) * info->nband_count);
1689 if (info->nodataval == NULL) {
1690 rterror(_("convert_raster: Could not allocate memory for storing nodata value"));
1691 GDALClose(hdsSrc);
1692 return 0;
1693 }
1694 memset(info->gdalbandtype, GDT_Unknown, sizeof(GDALDataType) * info->nband_count);
1695 memset(info->bandtype, PT_END, sizeof(rt_pixtype) * info->nband_count);
1696 memset(info->hasnodata, 0, sizeof(int) * info->nband_count);
1697 memset(info->nodataval, 0, sizeof(double) * info->nband_count);
1698
1699 /* dimensions of raster */
1700 info->dim[0] = GDALGetRasterXSize(hdsSrc);
1701 info->dim[1] = GDALGetRasterYSize(hdsSrc);
1702
1703 tilesize = 0;
1704
1705 /* go through bands for attributes */
1706 for (i = 0; i < info->nband_count; i++) {
1707 hbandSrc = GDALGetRasterBand(hdsSrc, info->nband[i]);
1708
1709 /* datatype */
1710 info->gdalbandtype[i] = GDALGetRasterDataType(hbandSrc);
1711
1712 /* complex data type? */
1713 if (GDALDataTypeIsComplex(info->gdalbandtype[i])) {
1714 rterror(_("convert_raster: The pixel type of band %d is a complex data type. PostGIS raster does not support complex data types"), i + 1);
1715 GDALClose(hdsSrc);
1716 return 0;
1717 }
1718 GDALGetBlockSize(hbandSrc, &naturalx, &naturaly);
1719
1720 /* convert data type to that of postgis raster */
1722
1723 /* hasnodata and nodataval */
1724 info->nodataval[i] = GDALGetRasterNoDataValue(hbandSrc, &(info->hasnodata[i]));
1725 if (!info->hasnodata[i]) {
1726 /* does NOT have nodata value, but user-specified */
1727 if (config->hasnodata) {
1728 info->hasnodata[i] = 1;
1729 info->nodataval[i] = config->nodataval;
1730 }
1731 else
1732 info->nodataval[i] = 0;
1733 }
1734
1735 /* update estimated byte size of 1 pixel */
1736 tilesize += rt_pixtype_size(info->bandtype[i]);
1737 }
1738
1739 /* tile size is "auto" */
1740 if (config->tile_size[0] == -1 && config->tile_size[1] == -1)
1741 {
1742 calc_tile_size((naturalx > 1) ? (uint32_t)naturalx : info->dim[0],
1743 (naturaly > 1) ? (uint32_t)naturaly : info->dim[1],
1744 &(config->tile_size[0]),
1745 &(config->tile_size[1]));
1746
1747 rtinfo(_("Using computed tile size: %dx%d"), config->tile_size[0], config->tile_size[1]);
1748 }
1749
1750 /* decide on tile size */
1751 if (!config->tile_size[0])
1752 info->tile_size[0] = info->dim[0];
1753 else
1754 info->tile_size[0] = config->tile_size[0];
1755 if (!config->tile_size[1])
1756 info->tile_size[1] = info->dim[1];
1757 else
1758 info->tile_size[1] = config->tile_size[1];
1759
1760 /* number of tiles */
1761 if ((uint32_t)info->tile_size[0] != info->dim[0])
1762 ntiles[0] = (info->dim[0] + info->tile_size[0] - 1) / info->tile_size[0];
1763 if ((uint32_t)info->tile_size[1] != info->dim[1])
1764 ntiles[1] = (info->dim[1] + info->tile_size[1] - 1) / info->tile_size[1];
1765
1766 /* estimate size of 1 tile */
1767 tilesize *= info->tile_size[0] * info->tile_size[1];
1768
1769 /* roughly estimate size of one tile and all bands */
1770 tilesize *= 1.1;
1771 if (tilesize > MAXTILESIZE)
1772 rtwarn(_("The size of each output tile may exceed 1 GB. Use -t to specify a reasonable tile size"));
1773
1774 /* out-db raster */
1775 if (config->outdb) {
1776 GDALClose(hdsSrc);
1777
1778 /* each tile is a raster */
1779 for (ytile = 0; ytile < ntiles[1]; ytile++) {
1780 /* edge y tile */
1781 if (!config->pad_tile && ntiles[1] > 1 && (ytile + 1) == ntiles[1])
1782 _tile_size[1] = info->dim[1] - (ytile * info->tile_size[1]);
1783 else
1784 _tile_size[1] = info->tile_size[1];
1785
1786 for (xtile = 0; xtile < ntiles[0]; xtile++) {
1787 int tile_is_nodata = !config->skip_nodataval_check;
1788
1789 /* edge x tile */
1790 if (!config->pad_tile && ntiles[0] > 1 && (xtile + 1) == ntiles[0])
1791 _tile_size[0] = info->dim[0] - (xtile * info->tile_size[0]);
1792 else
1793 _tile_size[0] = info->tile_size[0];
1794
1795 /* compute tile's upper-left corner */
1796 GDALApplyGeoTransform(
1797 info->gt,
1798 xtile * info->tile_size[0], ytile * info->tile_size[1],
1799 &(gt[0]), &(gt[3])
1800 );
1801
1802 /* create raster object */
1803 rast = rt_raster_new(_tile_size[0], _tile_size[1]);
1804 if (rast == NULL) {
1805 rterror(_("convert_raster: Could not create raster"));
1806 return 0;
1807 }
1808
1809 /* set raster attributes */
1810 rt_raster_set_srid(rast, info->srid);
1812
1813 /* add bands */
1814 for (i = 0; i < info->nband_count; i++) {
1815 band = rt_band_new_offline(
1816 _tile_size[0], _tile_size[1],
1817 info->bandtype[i],
1818 info->hasnodata[i], info->nodataval[i],
1819 info->nband[i] - 1,
1820 config->rt_file[idx]
1821 );
1822 if (band == NULL) {
1823 rterror(_("convert_raster: Could not create offline band"));
1824 raster_destroy(rast);
1825 return 0;
1826 }
1827
1828 /* add band to raster */
1829 if (rt_raster_add_band(rast, band, rt_raster_get_num_bands(rast)) == -1) {
1830 rterror(_("convert_raster: Could not add offlineband to raster"));
1831 rt_band_destroy(band);
1832 raster_destroy(rast);
1833 return 0;
1834 }
1835
1836 /* inspect each band of raster where band is NODATA */
1837 if (!config->skip_nodataval_check)
1838 tile_is_nodata = tile_is_nodata && rt_band_check_is_nodata(band);
1839 }
1840
1841 /* convert rt_raster to hexwkb */
1842 if (!tile_is_nodata)
1843 hex = rt_raster_to_hexwkb(rast, FALSE, &hexlen);
1844 raster_destroy(rast);
1845
1846 if (!hex && !tile_is_nodata)
1847 {
1848 rterror(_("convert_raster: Could not convert PostGIS raster to hex WKB"));
1849 return 0;
1850 }
1851
1852 /* add hexwkb to tileset */
1853 if (!tile_is_nodata)
1854 append_stringbuffer(tileset, hex);
1855
1856 /* flush if tileset gets too big */
1857 if (tileset->length >= config->max_tiles_per_copy ) {
1858 if (!insert_records(
1859 config->schema, config->table, config->raster_column,
1860 (config->file_column ? config->rt_filename[idx] : NULL), config->file_column_name,
1861 config->copy_statements, config->out_srid,
1862 tileset, buffer
1863 )) {
1864 rterror(_("convert_raster: Could not convert raster tiles into INSERT or COPY statements"));
1865 return 0;
1866 }
1867
1868 rtdealloc_stringbuffer(tileset, 0);
1869 }
1870 }
1871 }
1872 }
1873 /* in-db raster */
1874 else {
1875 VRTDatasetH hdsDst;
1876 VRTSourcedRasterBandH hbandDst;
1877
1878 /* each tile is a VRT with constraints set for just the data required for the tile */
1879 for (ytile = 0; ytile < ntiles[1]; ytile++) {
1880
1881 /* edge y tile */
1882 if (!config->pad_tile && ntiles[1] > 1 && (ytile + 1) == ntiles[1])
1883 _tile_size[1] = info->dim[1] - (ytile * info->tile_size[1]);
1884 else
1885 _tile_size[1] = info->tile_size[1];
1886
1887 for (xtile = 0; xtile < ntiles[0]; xtile++) {
1888 int tile_is_nodata = !config->skip_nodataval_check;
1889 /*
1890 char fn[100];
1891 sprintf(fn, "/tmp/tile%d.vrt", (ytile * ntiles[0]) + xtile);
1892 */
1893
1894 /* edge x tile */
1895 if (!config->pad_tile && ntiles[0] > 1 && (xtile + 1) == ntiles[0])
1896 _tile_size[0] = info->dim[0] - (xtile * info->tile_size[0]);
1897 else
1898 _tile_size[0] = info->tile_size[0];
1899
1900 /* compute tile's upper-left corner */
1901 GDALApplyGeoTransform(
1902 info->gt,
1903 xtile * info->tile_size[0], ytile * info->tile_size[1],
1904 &(gt[0]), &(gt[3])
1905 );
1906 /*
1907 rtinfo(_("tile (%d, %d) gt = (%f, %f, %f, %f, %f, %f)"),
1908 xtile, ytile,
1909 gt[0], gt[1], gt[2], gt[3], gt[4], gt[5]
1910 );
1911 */
1912
1913 /* create VRT dataset */
1914 hdsDst = VRTCreate(_tile_size[0], _tile_size[1]);
1915 /*
1916 GDALSetDescription(hdsDst, fn);
1917 */
1918 GDALSetProjection(hdsDst, info->srs);
1919 GDALSetGeoTransform(hdsDst, gt);
1920
1921 /* add bands as simple sources */
1922 for (i = 0; i < info->nband_count; i++) {
1923 GDALAddBand(hdsDst, info->gdalbandtype[i], NULL);
1924 hbandDst = (VRTSourcedRasterBandH) GDALGetRasterBand(hdsDst, i + 1);
1925
1926 if (info->hasnodata[i])
1927 GDALSetRasterNoDataValue(hbandDst, info->nodataval[i]);
1928
1929 VRTAddSimpleSource(
1930 hbandDst, GDALGetRasterBand(hdsSrc, info->nband[i]),
1931 xtile * info->tile_size[0], ytile * info->tile_size[1],
1932 _tile_size[0], _tile_size[1],
1933 0, 0,
1934 _tile_size[0], _tile_size[1],
1935 "near", VRT_NODATA_UNSET
1936 );
1937 }
1938
1939 /* make sure VRT reflects all changes */
1940 VRTFlushCache(hdsDst);
1941
1942 /* convert VRT dataset to rt_raster */
1943 rast = rt_raster_from_gdal_dataset(hdsDst);
1944 if (rast == NULL) {
1945 rterror(_("convert_raster: Could not convert VRT dataset to PostGIS raster"));
1946 GDALClose(hdsDst);
1947 return 0;
1948 }
1949
1950 /* set srid if provided */
1951 rt_raster_set_srid(rast, info->srid);
1952
1953 /* inspect each band of raster where band is NODATA */
1954 numbands = rt_raster_get_num_bands(rast);
1955 for (i = 0; i < numbands; i++) {
1956 band = rt_raster_get_band(rast, i);
1957 if (band != NULL && !config->skip_nodataval_check)
1958 tile_is_nodata = tile_is_nodata && rt_band_check_is_nodata(band);
1959 }
1960
1961 /* convert rt_raster to hexwkb */
1962 if (!tile_is_nodata)
1963 hex = rt_raster_to_hexwkb(rast, FALSE, &hexlen);
1964 raster_destroy(rast);
1965
1966 if (!hex && !tile_is_nodata)
1967 {
1968 rterror(_("convert_raster: Could not convert PostGIS raster to hex WKB"));
1969 GDALClose(hdsDst);
1970 return 0;
1971 }
1972
1973 /* add hexwkb to tileset */
1974 if (!tile_is_nodata)
1975 append_stringbuffer(tileset, hex);
1976
1977 GDALClose(hdsDst);
1978
1979 /* flush if tileset gets too big */
1980 if (tileset->length >= config->max_tiles_per_copy ) {
1981 if (!insert_records(
1982 config->schema, config->table, config->raster_column,
1983 (config->file_column ? config->rt_filename[idx] : NULL), config->file_column_name,
1984 config->copy_statements, config->out_srid,
1985 tileset, buffer
1986 )) {
1987 rterror(_("convert_raster: Could not convert raster tiles into INSERT or COPY statements"));
1988 GDALClose(hdsSrc);
1989 return 0;
1990 }
1991
1992 rtdealloc_stringbuffer(tileset, 0);
1993 }
1994 }
1995 }
1996
1997 GDALClose(hdsSrc);
1998 }
1999
2000 return 1;
2001}
2002
2003static int
2005 uint32_t i = 0;
2006
2007 assert(config != NULL);
2008 assert(config->table != NULL);
2009 assert(config->raster_column != NULL);
2010
2011 if (config->transaction) {
2012 if (!append_sql_to_buffer(buffer, strdup("BEGIN;"))) {
2013 rterror(_("process_rasters: Could not add BEGIN statement to string buffer"));
2014 return 0;
2015 }
2016 }
2017
2018 /* drop table */
2019 if (config->opt == 'd') {
2020 if (!drop_table(config->schema, config->table, buffer)) {
2021 rterror(_("process_rasters: Could not add DROP TABLE statement to string buffer"));
2022 return 0;
2023 }
2024
2025 if (config->overview_count) {
2026 for (i = 0; i < config->overview_count; i++) {
2027 if (!drop_table(config->schema, config->overview_table[i], buffer)) {
2028 rterror(_("process_rasters: Could not add an overview's DROP TABLE statement to string buffer"));
2029 return 0;
2030 }
2031 }
2032 }
2033 }
2034
2035 /* create table */
2036 if (config->opt != 'a') {
2037 if (!create_table(
2038 config->schema, config->table, config->raster_column,
2039 config->file_column, config->file_column_name,
2040 config->tablespace, config->idx_tablespace,
2041 buffer
2042 )) {
2043 rterror(_("process_rasters: Could not add CREATE TABLE statement to string buffer"));
2044 return 0;
2045 }
2046
2047 if (config->overview_count) {
2048 for (i = 0; i < config->overview_count; i++) {
2049 if (!create_table(
2050 config->schema, config->overview_table[i], config->raster_column,
2051 config->file_column, config->file_column_name,
2052 config->tablespace, config->idx_tablespace,
2053 buffer
2054 )) {
2055 rterror(_("process_rasters: Could not add an overview's CREATE TABLE statement to string buffer"));
2056 return 0;
2057 }
2058 }
2059 }
2060 }
2061
2062 /* no need to run if opt is 'p' */
2063 if (config->opt != 'p') {
2064 RASTERINFO refinfo;
2065 init_rastinfo(&refinfo);
2066
2067 /* process each raster */
2068 for (i = 0; i < config->rt_file_count; i++) {
2069 RASTERINFO rastinfo;
2070 STRINGBUFFER tileset;
2071
2072 fprintf(stderr, _("Processing %d/%d: %s\n"), i + 1, config->rt_file_count, config->rt_file[i]);
2073
2074 init_rastinfo(&rastinfo);
2075 init_stringbuffer(&tileset);
2076
2077 /* convert raster */
2078 if (!convert_raster(i, config, &rastinfo, &tileset, buffer)) {
2079 rterror(_("process_rasters: Could not process raster: %s"), config->rt_file[i]);
2080 rtdealloc_rastinfo(&rastinfo);
2081 rtdealloc_stringbuffer(&tileset, 0);
2082 return 0;
2083 }
2084
2085 /* process raster tiles into COPY or INSERT statements */
2086 if (tileset.length && !insert_records(
2087 config->schema, config->table, config->raster_column,
2088 (config->file_column ? config->rt_filename[i] : NULL),
2089 config->file_column_name,
2090 config->copy_statements, config->out_srid,
2091 &tileset, buffer
2092 )) {
2093 rterror(_("process_rasters: Could not convert raster tiles into INSERT or COPY statements"));
2094 rtdealloc_rastinfo(&rastinfo);
2095 rtdealloc_stringbuffer(&tileset, 0);
2096 return 0;
2097 }
2098
2099 rtdealloc_stringbuffer(&tileset, 0);
2100
2101 /* flush buffer after every raster */
2103
2104 /* overviews */
2105 if (config->overview_count) {
2106 uint32_t j = 0;
2107
2108 for (j = 0; j < config->overview_count; j++) {
2109
2110 if (!build_overview(i, config, &rastinfo, j, &tileset, buffer)) {
2111 rterror(_("process_rasters: Could not create overview of factor %d for raster %s"), config->overview[j], config->rt_file[i]);
2112 rtdealloc_rastinfo(&rastinfo);
2113 rtdealloc_stringbuffer(&tileset, 0);
2114 return 0;
2115 }
2116
2117 if (tileset.length && !insert_records(
2118 config->schema, config->overview_table[j], config->raster_column,
2119 (config->file_column ? config->rt_filename[i] : NULL), config->file_column_name,
2120 config->copy_statements, config->out_srid,
2121 &tileset, buffer
2122 )) {
2123 rterror(_("process_rasters: Could not convert overview tiles into INSERT or COPY statements"));
2124 rtdealloc_rastinfo(&rastinfo);
2125 rtdealloc_stringbuffer(&tileset, 0);
2126 return 0;
2127 }
2128
2129 rtdealloc_stringbuffer(&tileset, 0);
2130
2131 /* flush buffer after every raster */
2133 }
2134 }
2135
2136 if (config->rt_file_count > 1) {
2137 if (i < 1)
2138 copy_rastinfo(&refinfo, &rastinfo);
2139 else {
2140 diff_rastinfo(&rastinfo, &refinfo);
2141 }
2142 }
2143
2144 rtdealloc_rastinfo(&rastinfo);
2145 }
2146
2147 rtdealloc_rastinfo(&refinfo);
2148 }
2149
2150 /* index */
2151 if (config->idx) {
2152 /* create index */
2153 if (!create_index(
2154 config->schema, config->table, config->raster_column,
2155 config->idx_tablespace,
2156 buffer
2157 )) {
2158 rterror(_("process_rasters: Could not add CREATE INDEX statement to string buffer"));
2159 return 0;
2160 }
2161
2162 /* analyze */
2163 if (config->opt != 'p') {
2164 if (!analyze_table(
2165 config->schema, config->table,
2166 buffer
2167 )) {
2168 rterror(_("process_rasters: Could not add ANALYZE statement to string buffer"));
2169 return 0;
2170 }
2171 }
2172
2173 if (config->overview_count) {
2174 for (i = 0; i < config->overview_count; i++) {
2175 /* create index */
2176 if (!create_index(
2177 config->schema, config->overview_table[i], config->raster_column,
2178 config->idx_tablespace,
2179 buffer
2180 )) {
2181 rterror(_("process_rasters: Could not add an overview's CREATE INDEX statement to string buffer"));
2182 return 0;
2183 }
2184
2185 /* analyze */
2186 if (config->opt != 'p') {
2187 if (!analyze_table(
2188 config->schema, config->overview_table[i],
2189 buffer
2190 )) {
2191 rterror(_("process_rasters: Could not add an overview's ANALYZE statement to string buffer"));
2192 return 0;
2193 }
2194 }
2195 }
2196 }
2197 }
2198
2199 /* add constraints */
2200 if (config->constraints) {
2202 config->schema, config->table, config->raster_column,
2203 config->regular_blocking, config->max_extent,
2204 buffer
2205 )) {
2206 rterror(_("process:rasters: Could not add AddRasterConstraints statement to string buffer"));
2207 return 0;
2208 }
2209
2210 if (config->overview_count) {
2211 for (i = 0; i < config->overview_count; i++) {
2213 config->schema, config->overview_table[i], config->raster_column,
2214 config->regular_blocking, config->max_extent,
2215 buffer
2216 )) {
2217 rterror(_("process_rasters: Could not add an overview's AddRasterConstraints statement to string buffer"));
2218 return 0;
2219 }
2220 }
2221 }
2222 }
2223
2224 /* overview constraint is automatically added */
2225 if (config->overview_count) {
2226 for (i = 0; i < config->overview_count; i++) {
2228 config->schema, config->overview_table[i], config->raster_column,
2229 config->schema, config->table, config->raster_column,
2230 config->overview[i],
2231 buffer
2232 )) {
2233 rterror(_("process_rasters: Could not add an overview's AddOverviewConstraints statement to string buffer"));
2234 return 0;
2235 }
2236 }
2237 }
2238
2239 if (config->transaction) {
2240 if (!append_sql_to_buffer(buffer, strdup("END;"))) {
2241 rterror(_("process_rasters: Could not add END statement to string buffer"));
2242 return 0;
2243 }
2244 }
2245
2246 /* maintenance */
2247 if (config->opt != 'p' && config->maintenance) {
2248 if (!vacuum_table(
2249 config->schema, config->table,
2250 buffer
2251 )) {
2252 rterror(_("process_rasters: Could not add VACUUM statement to string buffer"));
2253 return 0;
2254 }
2255
2256 if (config->overview_count) {
2257 for (i = 0; i < config->overview_count; i++) {
2258 if (!vacuum_table(
2259 config->schema, config->overview_table[i],
2260 buffer
2261 )) {
2262 rterror(_("process_rasters: Could not add an overview's VACUUM statement to string buffer"));
2263 return 0;
2264 }
2265 }
2266 }
2267
2268 }
2269
2270 return 1;
2271}
2272
2273int
2274main(int argc, char **argv) {
2275 RTLOADERCFG *config = NULL;
2276 STRINGBUFFER *buffer = NULL;
2277 uint32_t i = 0;
2278 uint32_t j = 0;
2279 char **elements = NULL;
2280 uint32_t n = 0;
2281 GDALDriverH drv = NULL;
2282 char *tmp = NULL;
2283 int argit = 0;
2284
2286
2287#ifdef USE_NLS
2288 setlocale (LC_ALL, "");
2289 bindtextdomain (PACKAGE, LOCALEDIR);
2290 textdomain (PACKAGE);
2291#endif
2292
2293 /* no args, show usage */
2294 if (argc == 1) {
2295 usage();
2296 exit(0);
2297 }
2298
2299 /* initialize config */
2300 config = rtalloc(sizeof(RTLOADERCFG));
2301 if (config == NULL) {
2302 rterror(_("Could not allocate memory for loader configuration"));
2303 exit(1);
2304 }
2305 init_config(config);
2306
2307 /****************************************************************************
2308 * parse arguments
2309 ****************************************************************************/
2310
2311 for (argit = 1; argit < argc; argit++) {
2312 char *optarg, *ptr;
2313 /* srid */
2314
2315 if (CSEQUAL(argv[argit], "-s") && argit < argc - 1) {
2316 optarg = argv[++argit];
2317 ptr = strchr(optarg, ':');
2318 if (ptr) {
2319 *ptr++ = '\0';
2320 sscanf(optarg, "%d", &config->srid);
2321 sscanf(ptr, "%d", &config->out_srid);
2322 } else {
2323 config->srid = atoi(optarg);
2324 }
2325 }
2326 /* band index */
2327 else if (CSEQUAL(argv[argit], "-b") && argit < argc - 1) {
2328 elements = strsplit(argv[++argit], ",", &n);
2329 if (n < 1) {
2330 rterror(_("Could not process -b"));
2331 rtdealloc_config(config);
2332 exit(1);
2333 }
2334
2335 config->nband_count = 0;
2336 for (j = 0; j < n; j++) {
2337 char *t = trim(elements[j]);
2338 char **minmax = NULL;
2339 int *range = NULL;
2340 uint32_t p = 0;
2341 uint32_t l = 0;
2342 int m = 0;
2343 uint32_t o = 0;
2344
2345 /* is t a range? */
2346 minmax = strsplit(t, "-", &o);
2347 if (o == 2) {
2348 if (!array_range(atoi(minmax[0]), atoi(minmax[1]), 1, &range, &p)) {
2349 rterror(_("Could not allocate memory for storing band indices"));
2350 for (l = 0; l < o; l++)
2351 rtdealloc(minmax[l]);
2352 rtdealloc(minmax);
2353 for (j = 0; j < n; j++)
2354 rtdealloc(elements[j]);
2355 rtdealloc(elements);
2356 rtdealloc(t);
2357 rtdealloc_config(config);
2358 exit(1);
2359 }
2360 }
2361 else {
2362 p = 1;
2363 range = rtalloc(sizeof(int));
2364 if (range == NULL) {
2365 rterror(_("Could not allocate memory for storing band indices"));
2366 for (l = 0; l < o; l++)
2367 rtdealloc(minmax[l]);
2368 rtdealloc(minmax);
2369 for (j = 0; j < n; j++)
2370 rtdealloc(elements[j]);
2371 rtdealloc(elements);
2372 rtdealloc(t);
2373 rtdealloc_config(config);
2374 exit(1);
2375 }
2376 *range = atoi(t);
2377 }
2378
2379 m = config->nband_count;
2380 config->nband_count += p;
2381 config->nband = rtrealloc(config->nband, sizeof(int) * config->nband_count);
2382 if (config->nband == NULL) {
2383 rterror(_("Could not allocate memory for storing band indices"));
2384 rtdealloc(range);
2385 for (l = 0; l < o; l++)
2386 rtdealloc(minmax[l]);
2387 rtdealloc(minmax);
2388 for (j = 0; j < n; j++)
2389 rtdealloc(elements[j]);
2390 rtdealloc(elements);
2391 rtdealloc(t);
2392 rtdealloc_config(config);
2393 exit(1);
2394 }
2395
2396 for (l = 0; l < p; l++, m++)
2397 config->nband[m] = range[l];
2398
2399 rtdealloc(range);
2400
2401 for (l = 0; l < o; l++)
2402 rtdealloc(minmax[l]);
2403 rtdealloc(minmax);
2404
2405 rtdealloc(t);
2406 rtdealloc(elements[j]);
2407 }
2408 rtdealloc(elements);
2409 elements = NULL;
2410 n = 0;
2411
2412 for (j = 0; j < config->nband_count; j++) {
2413 if (config->nband[j] < 1) {
2414 rterror(_("Band index %d must be greater than 0"), config->nband[j]);
2415 rtdealloc_config(config);
2416 exit(1);
2417 }
2418 }
2419 }
2420 /* tile size */
2421 else if (CSEQUAL(argv[argit], "-t") && argit < argc - 1) {
2422 if (CSEQUAL(argv[++argit], "auto")) {
2423 config->tile_size[0] = -1;
2424 config->tile_size[1] = -1;
2425 }
2426 else {
2427 elements = strsplit(argv[argit], "x", &n);
2428 if (n != 2) {
2429 rterror(_("Could not process -t"));
2430 rtdealloc_config(config);
2431 exit(1);
2432 }
2433
2434 for (j = 0; j < n; j++) {
2435 char *t = trim(elements[j]);
2436 config->tile_size[j] = atoi(t);
2437 rtdealloc(t);
2438 rtdealloc(elements[j]);
2439 }
2440 rtdealloc(elements);
2441 elements = NULL;
2442 n = 0;
2443
2444 for (j = 0; j < 2; j++) {
2445 if (config->tile_size[j] < 1) {
2446 rterror(_("Tile size must be greater than 0x0"));
2447 rtdealloc_config(config);
2448 exit(1);
2449 }
2450 }
2451 }
2452 }
2453 /* pad tiles */
2454 else if (CSEQUAL(argv[argit], "-P")) {
2455 config->pad_tile = 1;
2456 }
2457 /* out-of-db raster */
2458 else if (CSEQUAL(argv[argit], "-R")) {
2459 config->outdb = 1;
2460 }
2461 /* drop table and recreate */
2462 else if (CSEQUAL(argv[argit], "-d")) {
2463 config->opt = 'd';
2464 }
2465 /* append to table */
2466 else if (CSEQUAL(argv[argit], "-a")) {
2467 config->opt = 'a';
2468 }
2469 /* create new table */
2470 else if (CSEQUAL(argv[argit], "-c")) {
2471 config->opt = 'c';
2472 }
2473 /* prepare only */
2474 else if (CSEQUAL(argv[argit], "-p")) {
2475 config->opt = 'p';
2476 }
2477 /* raster column name */
2478 else if (CSEQUAL(argv[argit], "-f") && argit < argc - 1) {
2479 const size_t len = (strlen(argv[++argit]) + 1);
2480 config->raster_column = rtalloc(sizeof(char) * len);
2481 if (config->raster_column == NULL) {
2482 rterror(_("Could not allocate memory for storing raster column name"));
2483 rtdealloc_config(config);
2484 exit(1);
2485 }
2486 strncpy(config->raster_column, argv[argit], len);
2487 }
2488 /* filename column */
2489 else if (CSEQUAL(argv[argit], "-F")) {
2490 config->file_column = 1;
2491 }
2492 /* filename column name */
2493 else if (CSEQUAL(argv[argit], "-n") && argit < argc - 1) {
2494 const size_t len = (strlen(argv[++argit]) + 1);
2495 config->file_column_name = rtalloc(sizeof(char) * len);
2496 if (config->file_column_name == NULL) {
2497 rterror(_("Could not allocate memory for storing filename column name"));
2498 rtdealloc_config(config);
2499 exit(1);
2500 }
2501 strncpy(config->file_column_name, argv[argit], len);
2502 config->file_column = 1;
2503 }
2504 /* overview factors */
2505 else if (CSEQUAL(argv[argit], "-l") && argit < argc - 1) {
2506 elements = strsplit(argv[++argit], ",", &n);
2507 if (n < 1) {
2508 rterror(_("Could not process -l"));
2509 rtdealloc_config(config);
2510 exit(1);
2511 }
2512
2513 config->overview_count = n;
2514 config->overview = rtalloc(sizeof(int) * n);
2515 if (config->overview == NULL) {
2516 rterror(_("Could not allocate memory for storing overview factors"));
2517 rtdealloc_config(config);
2518 exit(1);
2519 }
2520 for (j = 0; j < n; j++) {
2521 char *t = trim(elements[j]);
2522 config->overview[j] = atoi(t);
2523 rtdealloc(t);
2524 rtdealloc(elements[j]);
2525 }
2526 rtdealloc(elements);
2527 elements = NULL;
2528 n = 0;
2529
2530 for (j = 0; j < (uint32_t)config->overview_count; j++) {
2531 if (config->overview[j] < MINOVFACTOR || config->overview[j] > MAXOVFACTOR) {
2532 rterror(_("Overview factor %d is not between %d and %d"), config->overview[j], MINOVFACTOR, MAXOVFACTOR);
2533 rtdealloc_config(config);
2534 exit(1);
2535 }
2536 }
2537 }
2538 /* quote identifiers */
2539 else if (CSEQUAL(argv[argit], "-q")) {
2540 config->quoteident = 1;
2541 }
2542 /* create index */
2543 else if (CSEQUAL(argv[argit], "-I")) {
2544 config->idx = 1;
2545 }
2546 /* maintenance */
2547 else if (CSEQUAL(argv[argit], "-M")) {
2548 config->maintenance = 1;
2549 }
2550 /* set constraints */
2551 else if (CSEQUAL(argv[argit], "-C")) {
2552 config->constraints = 1;
2553 }
2554 /* disable extent constraint */
2555 else if (CSEQUAL(argv[argit], "-x")) {
2556 config->max_extent = 0;
2557 }
2558 /* enable regular_blocking */
2559 else if (CSEQUAL(argv[argit], "-r")) {
2560 config->regular_blocking = 1;
2561 }
2562 /* tablespace of new table */
2563 else if (CSEQUAL(argv[argit], "-T") && argit < argc - 1) {
2564 const size_t len = (strlen(argv[++argit]) + 1);
2565 config->tablespace = rtalloc(len);
2566 if (config->tablespace == NULL) {
2567 rterror(_("Could not allocate memory for storing tablespace of new table"));
2568 rtdealloc_config(config);
2569 exit(1);
2570 }
2571 strncpy(config->tablespace, argv[argit], len);
2572 }
2573 /* tablespace of new index */
2574 else if (CSEQUAL(argv[argit], "-X") && argit < argc - 1) {
2575 const size_t len = (strlen(argv[++argit]) + 1);
2576 config->idx_tablespace = rtalloc(len);
2577 if (config->idx_tablespace == NULL) {
2578 rterror(_("Could not allocate memory for storing tablespace of new indices"));
2579 rtdealloc_config(config);
2580 exit(1);
2581 }
2582 strncpy(config->idx_tablespace, argv[argit], len);
2583 }
2584 /* nodata value */
2585 else if (CSEQUAL(argv[argit], "-N") && argit < argc - 1) {
2586 config->hasnodata = 1;
2587 config->nodataval = atof(argv[++argit]);
2588 }
2589 /* skip NODATA value check for bands */
2590 else if (CSEQUAL(argv[argit], "-k")) {
2591 config->skip_nodataval_check = 1;
2592 }
2593 /* endianness */
2594 else if (CSEQUAL(argv[argit], "-E") && argit < argc - 1) {
2595 config->endian = atoi(argv[++argit]);
2596 config->endian = 1;
2597 }
2598 /* version */
2599 else if (CSEQUAL(argv[argit], "-V") && argit < argc - 1) {
2600 config->version = atoi(argv[++argit]);
2601 config->version = 0;
2602 }
2603 /* transaction */
2604 else if (CSEQUAL(argv[argit], "-e")) {
2605 config->transaction = 0;
2606 }
2607 /* COPY statements */
2608 else if (CSEQUAL(argv[argit], "-Y")) {
2609 config->copy_statements = 1;
2610 /* max tiles per copy */
2611 if ( argit < argc - 1) {
2612 optarg = argv[argit + 1];
2613 if (atoi(optarg) > 0 ) {
2614 config->max_tiles_per_copy = atoi(optarg);
2615 ++argit;
2616 }
2617 }
2618 }
2619
2620
2621 /* GDAL formats */
2622 else if (CSEQUAL(argv[argit], "-G")) {
2623 uint32_t drv_count = 0;
2624 rt_gdaldriver drv_set = rt_raster_gdal_drivers(&drv_count, 0);
2625 if (drv_set == NULL || !drv_count) {
2626 rterror(_("Could not get list of available GDAL raster formats"));
2627 }
2628 else {
2629 printf(_("Supported GDAL raster formats:\n"));
2630 for (j = 0; j < drv_count; j++) {
2631 printf(_(" %s\n"), drv_set[j].long_name);
2632
2633 rtdealloc(drv_set[j].short_name);
2634 rtdealloc(drv_set[j].long_name);
2635 rtdealloc(drv_set[j].create_options);
2636 }
2637 rtdealloc(drv_set);
2638 }
2639
2640 rtdealloc_config(config);
2641 exit(0);
2642 }
2643 /* help */
2644 else if (CSEQUAL(argv[argit], "-?")) {
2645 usage();
2646 rtdealloc_config(config);
2647 exit(0);
2648 }
2649 else {
2650 size_t len;
2651 config->rt_file_count++;
2652 config->rt_file = (char **) rtrealloc(config->rt_file, sizeof(char *) * config->rt_file_count);
2653 if (config->rt_file == NULL) {
2654 rterror(_("Could not allocate memory for storing raster files"));
2655 rtdealloc_config(config);
2656 exit(1);
2657 }
2658
2659 len = strlen(argv[argit]) + 1;
2660 config->rt_file[config->rt_file_count - 1] = rtalloc(sizeof(char) * len);
2661 if (config->rt_file[config->rt_file_count - 1] == NULL) {
2662 rterror(_("Could not allocate memory for storing raster filename"));
2663 rtdealloc_config(config);
2664 exit(1);
2665 }
2666 strncpy(config->rt_file[config->rt_file_count - 1], argv[argit], len);
2667 }
2668 }
2669
2670 if (config->srid != config->out_srid && config->out_srid != SRID_UNKNOWN) {
2671 if (config->copy_statements) {
2672 rterror(_("Invalid argument combination - cannot use -Y with -s FROM_SRID:TO_SRID"));
2673 exit(1);
2674 }
2675 }
2676
2677 /* register GDAL drivers */
2678 GDALAllRegister();
2679
2680 /* no files provided */
2681 if (!config->rt_file_count) {
2682 rterror(_("No raster provided"));
2683 rtdealloc_config(config);
2684 exit(1);
2685 }
2686 /*
2687 at least two files, see if last is table
2688 last isn't recognized by GDAL
2689 */
2690 else if (config->rt_file_count > 1) {
2691 drv = GDALIdentifyDriver(config->rt_file[config->rt_file_count - 1], NULL);
2692
2693 if (drv == NULL) {
2694 char *ptr;
2695 ptr = strchr(config->rt_file[config->rt_file_count - 1], '.');
2696
2697 /* schema.table */
2698 if (ptr) {
2699 config->schema = rtalloc(sizeof(char) * (ptr - config->rt_file[config->rt_file_count - 1] + 1));
2700 if (config->schema == NULL) {
2701 rterror(_("Could not allocate memory for storing schema name"));
2702 rtdealloc_config(config);
2703 exit(1);
2704 }
2705 snprintf(config->schema, ptr - config->rt_file[config->rt_file_count - 1] + 1, "%s", config->rt_file[config->rt_file_count - 1]);
2706 config->schema[ptr - config->rt_file[config->rt_file_count - 1]] = '\0';
2707
2708 config->table = rtalloc(sizeof(char) * (strlen(config->rt_file[config->rt_file_count - 1]) - strlen(config->schema) + 1));
2709 if (config->table == NULL) {
2710 rterror(_("Could not allocate memory for storing table name"));
2711 rtdealloc_config(config);
2712 exit(1);
2713 }
2714 snprintf(config->table, strlen(config->rt_file[config->rt_file_count - 1]) - strlen(config->schema), "%s", ptr + 1);
2715 config->table[strlen(config->rt_file[config->rt_file_count - 1]) - strlen(config->schema)] = '\0';
2716 }
2717 /* table */
2718 else {
2719 const size_t len = strlen(config->rt_file[config->rt_file_count - 1]) + 1;
2720 config->table = rtalloc(sizeof(char) * len);
2721 if (config->table == NULL) {
2722 rterror(_("Could not allocate memory for storing table name"));
2723 rtdealloc_config(config);
2724 exit(1);
2725 }
2726 strncpy(config->table, config->rt_file[config->rt_file_count - 1], len);
2727 }
2728
2729 rtdealloc(config->rt_file[--(config->rt_file_count)]);
2730 config->rt_file = (char **) rtrealloc(config->rt_file, sizeof(char *) * config->rt_file_count);
2731 if (config->rt_file == NULL) {
2732 rterror(_("Could not reallocate the memory holding raster names"));
2733 rtdealloc_config(config);
2734 exit(1);
2735 }
2736 }
2737 }
2738
2739 /****************************************************************************
2740 * validate raster files
2741 ****************************************************************************/
2742
2743 /* check that GDAL recognizes all files */
2744 for (i = 0; i < config->rt_file_count; i++) {
2745 drv = GDALIdentifyDriver(config->rt_file[i], NULL);
2746
2747 if (drv == NULL) {
2748 rterror(_("Unable to read raster file: %s"), config->rt_file[i]);
2749 rtdealloc_config(config);
2750 exit(1);
2751 }
2752 }
2753
2754 /* process each file for just the filename */
2755 config->rt_filename = (char **) rtalloc(sizeof(char *) * config->rt_file_count);
2756 if (config->rt_filename == NULL) {
2757 rterror(_("Could not allocate memory for cleaned raster filenames"));
2758 rtdealloc_config(config);
2759 exit(1);
2760 }
2761 for (i = 0; i < config->rt_file_count; i++) {
2762 char *file;
2763 char *ptr;
2764
2765 file = rtalloc(sizeof(char) * (strlen(config->rt_file[i]) + 1));
2766 if (file == NULL) {
2767 rterror(_("Could not allocate memory for cleaned raster filename"));
2768 rtdealloc_config(config);
2769 exit(1);
2770 }
2771 strcpy(file, config->rt_file[i]);
2772
2773 for (ptr = file + strlen(file); ptr > file; ptr--) {
2774 if (*ptr == '/' || *ptr == '\\') {
2775 ptr++;
2776 break;
2777 }
2778 }
2779
2780 config->rt_filename[i] = rtalloc(sizeof(char) * (strlen(ptr) + 1));
2781 if (config->rt_filename[i] == NULL) {
2782 rterror(_("Could not allocate memory for cleaned raster filename"));
2783 rtdealloc_config(config);
2784 exit(1);
2785 }
2786 strcpy(config->rt_filename[i], ptr);
2787 rtdealloc(file);
2788 }
2789
2790 /****************************************************************************
2791 * defaults for table and column names
2792 ****************************************************************************/
2793
2794 /* first file as proxy table name */
2795 if (config->table == NULL) {
2796 char *file;
2797 char *ptr;
2798
2799 file = rtalloc(sizeof(char) * (strlen(config->rt_filename[0]) + 1));
2800 if (file == NULL) {
2801 rterror(_("Could not allocate memory for proxy table name"));
2802 rtdealloc_config(config);
2803 exit(1);
2804 }
2805 strcpy(file, config->rt_filename[0]);
2806
2807 for (ptr = file + strlen(file); ptr > file; ptr--) {
2808 if (*ptr == '.') {
2809 *ptr = '\0';
2810 break;
2811 }
2812 }
2813
2814 config->table = rtalloc(sizeof(char) * (strlen(file) + 1));
2815 if (config->table == NULL) {
2816 rterror(_("Could not allocate memory for proxy table name"));
2817 rtdealloc_config(config);
2818 exit(1);
2819 }
2820 strcpy(config->table, file);
2821 rtdealloc(file);
2822 }
2823
2824 /* raster_column not specified, default to "rast" */
2825 if (config->raster_column == NULL) {
2826 config->raster_column = rtalloc(sizeof(char) * (strlen("rast") + 1));
2827 if (config->raster_column == NULL) {
2828 rterror(_("Could not allocate memory for default raster column name"));
2829 rtdealloc_config(config);
2830 exit(1);
2831 }
2832 strcpy(config->raster_column, "rast");
2833 }
2834
2835 /* file_column_name not specified, default to "filename" */
2836 if (config->file_column_name == NULL) {
2837 config->file_column_name = rtalloc(sizeof(char) * (strlen("filename") + 1));
2838 if (config->file_column_name == NULL) {
2839 rterror(_("Could not allocate memory for default filename column name"));
2840 rtdealloc_config(config);
2841 exit(1);
2842 }
2843 strcpy(config->file_column_name, "filename");
2844 }
2845
2846 /****************************************************************************
2847 * literal PostgreSQL identifiers disabled
2848 ****************************************************************************/
2849
2850 /* no quotes, lower case everything */
2851 if (!config->quoteident) {
2852 if (config->schema != NULL)
2853 config->schema = strtolower(config->schema);
2854 if (config->table != NULL)
2855 config->table = strtolower(config->table);
2856 if (config->raster_column != NULL)
2857 config->raster_column = strtolower(config->raster_column);
2858 if (config->file_column_name != NULL)
2859 config->file_column_name = strtolower(config->file_column_name);
2860 if (config->tablespace != NULL)
2861 config->tablespace = strtolower(config->tablespace);
2862 if (config->idx_tablespace != NULL)
2863 config->idx_tablespace = strtolower(config->idx_tablespace);
2864 }
2865
2866 /****************************************************************************
2867 * overview table names
2868 ****************************************************************************/
2869
2870 if (config->overview_count) {
2871 char factor[4];
2872 config->overview_table = rtalloc(sizeof(char *) * config->overview_count);
2873 if (config->overview_table == NULL) {
2874 rterror(_("Could not allocate memory for overview table names"));
2875 rtdealloc_config(config);
2876 exit(1);
2877 }
2878
2879 for (i = 0; i < config->overview_count; i++) {
2880 sprintf(factor, "%d", config->overview[i]);
2881
2882 config->overview_table[i] = rtalloc(sizeof(char) * (strlen("o__") + strlen(factor) + strlen(config->table) + 1));
2883 if (config->overview_table[i] == NULL) {
2884 rterror(_("Could not allocate memory for overview table name"));
2885 rtdealloc_config(config);
2886 exit(1);
2887 }
2888 sprintf(config->overview_table[i], "o_%d_%s", config->overview[i], config->table);
2889 }
2890 }
2891
2892 /****************************************************************************
2893 * check that identifiers won't get truncated
2894 ****************************************************************************/
2895
2896 if (config->schema != NULL && strlen(config->schema) > MAXNAMELEN) {
2897 rtwarn(_("The schema name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2898 config->schema,
2900 );
2901 }
2902 if (config->table != NULL && strlen(config->table) > MAXNAMELEN) {
2903 rtwarn(_("The table name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2904 config->table,
2906 );
2907 }
2908 if (config->raster_column != NULL && strlen(config->raster_column) > MAXNAMELEN) {
2909 rtwarn(_("The column name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2910 config->raster_column,
2912 );
2913 }
2914 if (config->file_column_name != NULL && strlen(config->file_column_name) > MAXNAMELEN) {
2915 rtwarn(_("The column name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2916 config->file_column_name,
2918 );
2919 }
2920 if (config->tablespace != NULL && strlen(config->tablespace) > MAXNAMELEN) {
2921 rtwarn(_("The tablespace name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2922 config->tablespace,
2924 );
2925 }
2926 if (config->idx_tablespace != NULL && strlen(config->idx_tablespace) > MAXNAMELEN) {
2927 rtwarn(_("The index tablespace name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2928 config->idx_tablespace,
2930 );
2931 }
2932 if (config->overview_count) {
2933 for (i = 0; i < config->overview_count; i++) {
2934 if (strlen(config->overview_table[i]) > MAXNAMELEN) {
2935 rtwarn(_("The overview table name \"%s\" may exceed the maximum string length permitted for PostgreSQL identifiers (%d)"),
2936 config->overview_table[i],
2938 );
2939 }
2940 }
2941 }
2942
2943 /****************************************************************************
2944 * double quote identifiers
2945 ****************************************************************************/
2946
2947 if (config->schema != NULL) {
2948 tmp = rtalloc(sizeof(char) * (strlen(config->schema) + 4));
2949 if (tmp == NULL) {
2950 rterror(_("Could not allocate memory for quoting schema name"));
2951 rtdealloc_config(config);
2952 exit(1);
2953 }
2954
2955 sprintf(tmp, "\"%s\".", config->schema);
2956 rtdealloc(config->schema);
2957 config->schema = tmp;
2958 }
2959 if (config->table != NULL) {
2960 tmp = rtalloc(sizeof(char) * (strlen(config->table) + 3));
2961 if (tmp == NULL) {
2962 rterror(_("Could not allocate memory for quoting table name"));
2963 rtdealloc_config(config);
2964 exit(1);
2965 }
2966
2967 sprintf(tmp, "\"%s\"", config->table);
2968 rtdealloc(config->table);
2969 config->table = tmp;
2970 }
2971 if (config->raster_column != NULL) {
2972 tmp = rtalloc(sizeof(char) * (strlen(config->raster_column) + 3));
2973 if (tmp == NULL) {
2974 rterror(_("Could not allocate memory for quoting raster column name"));
2975 rtdealloc_config(config);
2976 exit(1);
2977 }
2978
2979 sprintf(tmp, "\"%s\"", config->raster_column);
2980 rtdealloc(config->raster_column);
2981 config->raster_column = tmp;
2982 }
2983 if (config->file_column_name != NULL) {
2984 tmp = rtalloc(sizeof(char) * (strlen(config->file_column_name) + 3));
2985 if (tmp == NULL) {
2986 rterror(_("Could not allocate memory for quoting raster column name"));
2987 rtdealloc_config(config);
2988 exit(1);
2989 }
2990
2991 sprintf(tmp, "\"%s\"", config->file_column_name);
2992 rtdealloc(config->file_column_name);
2993 config->file_column_name = tmp;
2994 }
2995 if (config->tablespace != NULL) {
2996 tmp = rtalloc(sizeof(char) * (strlen(config->tablespace) + 3));
2997 if (tmp == NULL) {
2998 rterror(_("Could not allocate memory for quoting tablespace name"));
2999 rtdealloc_config(config);
3000 exit(1);
3001 }
3002
3003 sprintf(tmp, "\"%s\"", config->tablespace);
3004 rtdealloc(config->tablespace);
3005 config->tablespace = tmp;
3006 }
3007 if (config->idx_tablespace != NULL) {
3008 tmp = rtalloc(sizeof(char) * (strlen(config->idx_tablespace) + 3));
3009 if (tmp == NULL) {
3010 rterror(_("Could not allocate memory for quoting index tablespace name"));
3011 rtdealloc_config(config);
3012 exit(1);
3013 }
3014
3015 sprintf(tmp, "\"%s\"", config->idx_tablespace);
3016 rtdealloc(config->idx_tablespace);
3017 config->idx_tablespace = tmp;
3018 }
3019 if (config->overview_count) {
3020 for (i = 0; i < config->overview_count; i++) {
3021 tmp = rtalloc(sizeof(char) * (strlen(config->overview_table[i]) + 3));
3022 if (tmp == NULL) {
3023 rterror(_("Could not allocate memory for quoting overview table name"));
3024 rtdealloc_config(config);
3025 exit(1);
3026 }
3027
3028 sprintf(tmp, "\"%s\"", config->overview_table[i]);
3029 rtdealloc(config->overview_table[i]);
3030 config->overview_table[i] = tmp;
3031 }
3032 }
3033
3034 /****************************************************************************
3035 * processing of rasters
3036 ****************************************************************************/
3037
3038 /* initialize string buffer */
3039 buffer = rtalloc(sizeof(STRINGBUFFER));
3040 if (buffer == NULL) {
3041 rterror(_("Could not allocate memory for output string buffer"));
3042 rtdealloc_config(config);
3043 exit(1);
3044 }
3046
3047 /* pass off to processing function */
3048 if (!process_rasters(config, buffer)) {
3049 rterror(_("Unable to process rasters"));
3051 rtdealloc_config(config);
3052 exit(1);
3053 }
3054
3056
3058 rtdealloc_config(config);
3059
3060 return 0;
3061}
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition cu_print.c:267
#define FALSE
Definition dbfopen.c:72
#define __attribute__(x)
Definition liblwgeom.h:228
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:215
void rterror(const char *fmt,...) __attribute__((format(printf
Wrappers used for reporting errors and info.
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition rt_context.c:191
rt_pixtype rt_util_gdal_datatype_to_pixtype(GDALDataType gdt)
Convert GDALDataType to rt_pixtype.
Definition rt_util.c:255
void * default_rt_allocator(size_t size)
The default memory/logging handlers installed by lwgeom_install_default_allocators()
Definition rt_context.c:47
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster's geotransform using 6-element array.
Definition rt_raster.c:609
void void rtinfo(const char *fmt,...) __attribute__((format(printf
void void void rtwarn(const char *fmt,...) __attribute__((format(printf
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
int rt_raster_add_band(rt_raster raster, rt_band band, int index)
Add band data to a raster.
Definition rt_raster.c:409
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
Definition rt_band.c:559
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition rt_raster.c:86
rt_pixtype
Definition librtcore.h:188
@ PT_END
Definition librtcore.h:201
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
Definition rt_raster.c:52
rt_raster rt_raster_from_gdal_dataset(GDALDatasetH ds)
Return a raster from a GDAL dataset.
Definition rt_raster.c:2175
void default_rt_deallocator(void *mem)
Definition rt_context.c:61
void * default_rt_reallocator(void *mem, size_t size)
Definition rt_context.c:54
int rt_band_check_is_nodata(rt_band band)
Returns TRUE if the band is only nodata values.
Definition rt_band.c:2089
char * rt_raster_to_hexwkb(rt_raster raster, int outasin, uint32_t *hexwkbsize)
Return this raster in HEXWKB form (null-terminated hex)
Definition rt_wkb.c:693
@ ES_NONE
Definition librtcore.h:182
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition rt_band.c:499
void * rtrealloc(void *mem, size_t size)
Definition rt_context.c:199
uint16_t rt_raster_get_num_bands(rt_raster raster)
Definition rt_raster.c:376
rt_band rt_band_new_offline(uint16_t width, uint16_t height, rt_pixtype pixtype, uint32_t hasnodata, double nodataval, uint8_t bandNum, const char *path)
Create an out-db rt_band.
Definition rt_band.c:283
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
Definition rt_raster.c:367
void rtdealloc(void *mem)
Definition rt_context.c:206
int rt_band_get_ownsdata_flag(rt_band band)
Return 0 (FALSE) or non-zero (TRUE) indicating if rt_band is responsible for managing the memory for ...
Definition rt_band.c:818
int rt_band_is_offline(rt_band band)
Return non-zero if the given band data is on the filesystem.
Definition rt_band.c:488
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
void rt_set_handlers(rt_allocator allocator, rt_reallocator reallocator, rt_deallocator deallocator, rt_message_handler error_handler, rt_message_handler info_handler, rt_message_handler warning_handler)
This function is called when the PostgreSQL backend is taking care of the memory and we want to use p...
Definition rt_context.c:159
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
Definition rt_pixel.c:40
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition rt_raster.c:385
int main(void)
Datum buffer(PG_FUNCTION_ARGS)
static int add_overview_constraints(const char *ovschema, const char *ovtable, const char *ovcolumn, const char *schema, const char *table, const char *column, const int factor, STRINGBUFFER *buffer)
static int append_sql_to_buffer(STRINGBUFFER *buffer, const char *str)
static int build_overview(int idx, RTLOADERCFG *config, RASTERINFO *info, uint32_t ovx, STRINGBUFFER *tileset, STRINGBUFFER *buffer)
static void diff_rastinfo(RASTERINFO *x, RASTERINFO *ref)
static void dump_stringbuffer(STRINGBUFFER *buffer)
static void loader_rt_warning_handler(const char *fmt, va_list ap) __attribute__((format(printf
static void calc_tile_size(uint32_t dimX, uint32_t dimY, int *tileX, int *tileY)
static int convert_raster(int idx, RTLOADERCFG *config, RASTERINFO *info, STRINGBUFFER *tileset, STRINGBUFFER *buffer)
static int append_stringbuffer(STRINGBUFFER *buffer, const char *str)
static int copy_from_end(STRINGBUFFER *buffer)
static void rtdealloc_stringbuffer(STRINGBUFFER *buffer, int freebuffer)
static int insert_records(const char *schema, const char *table, const char *column, const char *filename, const char *file_column_name, int copy_statements, int out_srid, STRINGBUFFER *tileset, STRINGBUFFER *buffer)
static void usage()
static int array_range(int min, int max, int step, int **range, uint32_t *len)
static void flush_stringbuffer(STRINGBUFFER *buffer)
static void init_config(RTLOADERCFG *config)
static void rtdealloc_rastinfo(RASTERINFO *info)
static char * strreplace(const char *str, const char *oldstr, const char *newstr, int *count)
static char * strtolower(char *str)
static void loader_rt_info_handler(const char *fmt, va_list ap) __attribute__((format(printf
static void rt_init_allocators(void)
static void raster_destroy(rt_raster raster)
static char * chartrim(const char *input, char *remove)
static void init_rastinfo(RASTERINFO *info)
static int vacuum_table(const char *schema, const char *table, STRINGBUFFER *buffer)
static char ** strsplit(const char *str, const char *delimiter, uint32_t *n)
static int create_index(const char *schema, const char *table, const char *column, const char *tablespace, STRINGBUFFER *buffer)
static int add_raster_constraints(const char *schema, const char *table, const char *column, int regular_blocking, int max_extent, STRINGBUFFER *buffer)
static int drop_table(const char *schema, const char *table, STRINGBUFFER *buffer)
static int copy_rastinfo(RASTERINFO *dst, RASTERINFO *src)
#define str(s)
static void loader_rt_error_handler(const char *fmt, va_list ap) __attribute__((format(printf
static void rtdealloc_config(RTLOADERCFG *config)
static void init_stringbuffer(STRINGBUFFER *buffer)
#define xstr(s)
static int process_rasters(RTLOADERCFG *config, STRINGBUFFER *buffer)
static int copy_from(const char *schema, const char *table, const char *column, const char *filename, const char *file_column_name, STRINGBUFFER *buffer)
static char * trim(const char *input)
static int analyze_table(const char *schema, const char *table, STRINGBUFFER *buffer)
static int create_table(const char *schema, const char *table, const char *column, const int file_column, const char *file_column_name, const char *tablespace, const char *idx_tablespace, STRINGBUFFER *buffer)
#define MAXNAMELEN
#define CSEQUAL(a, b)
#define MAXOVFACTOR
#define MINOVFACTOR
#define MAXTILESIZE
#define POSTGIS_GDAL_VERSION
#define _(String)
Definition shpcommon.h:24
#define POSTGIS_LIB_VERSION
Definition sqldefines.h:13
uint32_t max_tiles_per_copy
max tiles per copy
double * nodataval
rt_pixtype * bandtype
double gt[6]
uint32_t nband_count
GDALDataType * gdalbandtype
uint32_t dim[2]