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