From: Bborie Park Date: Tue, 23 Apr 2013 23:46:27 +0000 (+0000) Subject: Added parameter to ST_AsBinary(raster) to permit out-db bands to be treated as in... X-Git-Tag: 2.1.0beta2~86 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bd4596f36653fcf8414132f3e5ad78566e7fd188;p=postgis Added parameter to ST_AsBinary(raster) to permit out-db bands to be treated as in-db. Ticket #2222 git-svn-id: http://svn.osgeo.org/postgis/trunk@11320 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index 953017829..3c5cc4a9d 100644 --- a/NEWS +++ b/NEWS @@ -135,6 +135,8 @@ PostGIS 2.1.0 with postgis in a custom schema - #2244, emit warning when changing raster's georeference if raster has out-db bands + - #2222, add parameter OutAsIn to flag whether ST_AsBinary should + return out-db bands as in-db bands * Fixes * diff --git a/doc/reference_raster.xml b/doc/reference_raster.xml index f689737b0..e04889484 100644 --- a/doc/reference_raster.xml +++ b/doc/reference_raster.xml @@ -7148,8 +7148,9 @@ SELECT rid, ST_ValueCount(rast,2,100) As count - bytea ST_AsBinary - raster rast + bytea ST_AsBinary + raster rast + boolean outasin=FALSE @@ -7157,18 +7158,27 @@ SELECT rid, ST_ValueCount(rast,2,100) As count Description - Returns the Binary representation of the raster. There are 2 variants of the function. The first - variant takes no endian encoding parameter and defaults to little endian. The second variant takes a second argument - denoting the encoding - using little-endian ('NDR') or big-endian ('XDR') encoding. - This is useful in binary cursors to pull data out of the - database without converting it to a string representation. - + + Returns the Binary representation of the raster. If outasin is TRUE, out-db bands are treated as in-db. + + + + This is useful in binary cursors to pull data out of the database without converting it to a string representation. + + + + + By default, WKB output contains the external file path for out-db bands. If the client does not have access to the raster file underlying an out-db band, set outasin to TRUE. + + + Enhanced: 2.1.0 Addition of outasin + Examples - SELECT ST_AsBinary(rast) As rastbin -FROM dummy_rast WHERE rid=1; + +SELECT ST_AsBinary(rast) As rastbin FROM dummy_rast WHERE rid=1; rastbin --------------------------------------------------------------------------------- diff --git a/raster/loader/raster2pgsql.c b/raster/loader/raster2pgsql.c index 8777fb9eb..8deae828d 100644 --- a/raster/loader/raster2pgsql.c +++ b/raster/loader/raster2pgsql.c @@ -1501,7 +1501,7 @@ build_overview(int idx, RTLOADERCFG *config, RASTERINFO *info, int ovx, STRINGBU rt_raster_set_srid(rast, info->srid); /* convert rt_raster to hexwkb */ - hex = rt_raster_to_hexwkb(rast, &hexlen); + hex = rt_raster_to_hexwkb(rast, FALSE, &hexlen); raster_destroy(rast); if (hex == NULL) { @@ -1818,7 +1818,7 @@ convert_raster(int idx, RTLOADERCFG *config, RASTERINFO *info, STRINGBUFFER *til } /* convert rt_raster to hexwkb */ - hex = rt_raster_to_hexwkb(rast, &hexlen); + hex = rt_raster_to_hexwkb(rast, FALSE, &hexlen); raster_destroy(rast); if (hex == NULL) { @@ -1936,7 +1936,7 @@ convert_raster(int idx, RTLOADERCFG *config, RASTERINFO *info, STRINGBUFFER *til } /* convert rt_raster to hexwkb */ - hex = rt_raster_to_hexwkb(rast, &hexlen); + hex = rt_raster_to_hexwkb(rast, FALSE, &hexlen); raster_destroy(rast); if (hex == NULL) { diff --git a/raster/rt_core/rt_api.c b/raster/rt_core/rt_api.c index 6e3a56f9f..b8f09496a 100644 --- a/raster/rt_core/rt_api.c +++ b/raster/rt_core/rt_api.c @@ -7722,7 +7722,7 @@ rt_raster_from_hexwkb(const char* hexwkb, uint32_t hexwkbsize) { } static uint32_t -rt_raster_wkb_size(rt_raster raster) { +rt_raster_wkb_size(rt_raster raster, int outasin) { uint32_t size = RT_WKB_HDR_SZ; uint16_t i = 0; @@ -7749,7 +7749,7 @@ rt_raster_wkb_size(rt_raster raster) { /* Add space for nodata value */ size += pixbytes; - if (band->offline) { + if (!outasin && band->offline) { /* Add space for band number */ size += 1; @@ -7765,8 +7765,17 @@ rt_raster_wkb_size(rt_raster raster) { return size; } +/** + * Return this raster in WKB form + * + * @param raster : the raster + * @param outasin : if TRUE, out-db bands are treated as in-db + * @param wkbsize : will be set to the size of returned wkb form + * + * @return WKB of raster or NULL on error + */ uint8_t * -rt_raster_to_wkb(rt_raster raster, uint32_t *wkbsize) { +rt_raster_to_wkb(rt_raster raster, int outasin, uint32_t *wkbsize) { #if POSTGIS_DEBUG_LEVEL > 0 const uint8_t *wkbend = NULL; @@ -7782,7 +7791,7 @@ rt_raster_to_wkb(rt_raster raster, uint32_t *wkbsize) { RASTER_DEBUG(2, "rt_raster_to_wkb: about to call rt_raster_wkb_size"); - *wkbsize = rt_raster_wkb_size(raster); + *wkbsize = rt_raster_wkb_size(raster, outasin); RASTER_DEBUGF(3, "rt_raster_to_wkb: found size: %d", *wkbsize); wkb = (uint8_t*) rtalloc(*wkbsize); @@ -7831,7 +7840,7 @@ rt_raster_to_wkb(rt_raster raster, uint32_t *wkbsize) { /* Add band type */ *ptr = band->pixtype; - if (band->offline) *ptr |= BANDTYPE_FLAG_OFFDB; + if (!outasin && band->offline) *ptr |= BANDTYPE_FLAG_OFFDB; if (band->hasnodata) *ptr |= BANDTYPE_FLAG_HASNODATA; if (band->isnodata) *ptr |= BANDTYPE_FLAG_ISNODATA; ptr += 1; @@ -7905,7 +7914,7 @@ rt_raster_to_wkb(rt_raster raster, uint32_t *wkbsize) { assert(!((uint64_t) ptr % pixbytes)); #endif - if (band->offline) { + if (!outasin && band->offline) { /* Write band number */ *ptr = band->data.offline.bandNum; ptr += 1; @@ -7918,7 +7927,9 @@ rt_raster_to_wkb(rt_raster raster, uint32_t *wkbsize) { /* Write data */ uint32_t datasize = raster->width * raster->height * pixbytes; RASTER_DEBUGF(4, "rt_raster_to_wkb: Copying %d bytes", datasize); - memcpy(ptr, band->data.mem, datasize); + + memcpy(ptr, rt_band_get_data(band), datasize); + ptr += datasize; } @@ -7939,7 +7950,7 @@ rt_raster_to_wkb(rt_raster raster, uint32_t *wkbsize) { } char * -rt_raster_to_hexwkb(rt_raster raster, uint32_t *hexwkbsize) { +rt_raster_to_hexwkb(rt_raster raster, int outasin, uint32_t *hexwkbsize) { uint8_t *wkb = NULL; char* hexwkb = NULL; uint32_t i = 0; @@ -7950,7 +7961,7 @@ rt_raster_to_hexwkb(rt_raster raster, uint32_t *hexwkbsize) { RASTER_DEBUG(2, "rt_raster_to_hexwkb: calling rt_raster_to_wkb"); - wkb = rt_raster_to_wkb(raster, &wkbsize); + wkb = rt_raster_to_wkb(raster, outasin, &wkbsize); RASTER_DEBUG(3, "rt_raster_to_hexwkb: rt_raster_to_wkb returned"); diff --git a/raster/rt_core/rt_api.h b/raster/rt_core/rt_api.h index b225b1c4c..59b729517 100644 --- a/raster/rt_core/rt_api.h +++ b/raster/rt_core/rt_api.h @@ -959,8 +959,7 @@ rt_raster rt_raster_new(uint32_t width, uint32_t height); * malformed WKB). * */ -rt_raster rt_raster_from_wkb(const uint8_t* wkb, - uint32_t wkbsize); +rt_raster rt_raster_from_wkb(const uint8_t* wkb, uint32_t wkbsize); /** * Construct an rt_raster from a text HEXWKB representation @@ -972,31 +971,30 @@ rt_raster rt_raster_from_wkb(const uint8_t* wkb, * malformed WKB). * */ -rt_raster rt_raster_from_hexwkb(const char* hexwkb, - uint32_t hexwkbsize); +rt_raster rt_raster_from_hexwkb(const char* hexwkb, uint32_t hexwkbsize); /** * Return this raster in WKB form * * @param raster : the raster + * @param outasin : if TRUE, out-db bands are treated as in-db * @param wkbsize : will be set to the size of returned wkb form * * @return WKB of raster or NULL on error */ -uint8_t *rt_raster_to_wkb(rt_raster raster, - uint32_t *wkbsize); +uint8_t *rt_raster_to_wkb(rt_raster raster, int outasin, uint32_t *wkbsize); /** * Return this raster in HEXWKB form (null-terminated hex) * * @param raster : the raster + * @param outasin : if TRUE, out-db bands are treated as in-db * @param hexwkbsize : will be set to the size of returned wkb form, * not including the null termination * * @return HEXWKB of raster or NULL on error */ -char *rt_raster_to_hexwkb(rt_raster raster, - uint32_t *hexwkbsize); +char *rt_raster_to_hexwkb(rt_raster raster, int outasin, uint32_t *hexwkbsize); /** * Release memory associated to a raster diff --git a/raster/rt_pg/rt_pg.c b/raster/rt_pg/rt_pg.c index 7bce5dd4c..ed353a66f 100644 --- a/raster/rt_pg/rt_pg.c +++ b/raster/rt_pg/rt_pg.c @@ -858,7 +858,7 @@ Datum RASTER_out(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } - hexwkb = rt_raster_to_hexwkb(raster, &hexwkbsize); + hexwkb = rt_raster_to_hexwkb(raster, FALSE, &hexwkbsize); if (!hexwkb) { elog(ERROR, "RASTER_out: Could not HEX-WKBize raster"); rt_raster_destroy(raster); @@ -898,7 +898,7 @@ Datum RASTER_to_bytea(PG_FUNCTION_ARGS) } /* Parse raster to wkb object */ - wkb = rt_raster_to_wkb(raster, &wkb_size); + wkb = rt_raster_to_wkb(raster, FALSE, &wkb_size); if (!wkb) { elog(ERROR, "RASTER_to_bytea: Could not allocate and generate WKB data"); rt_raster_destroy(raster); @@ -921,7 +921,7 @@ Datum RASTER_to_bytea(PG_FUNCTION_ARGS) } /** - * Return bytea object with raster requested using ST_AsBinary function. + * Return bytea object with raster in Well-Known-Binary form requested using ST_AsBinary function. */ PG_FUNCTION_INFO_V1(RASTER_to_binary); Datum RASTER_to_binary(PG_FUNCTION_ARGS) @@ -932,6 +932,7 @@ Datum RASTER_to_binary(PG_FUNCTION_ARGS) uint32_t wkb_size = 0; char *result = NULL; int result_size = 0; + int outasin = FALSE; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); @@ -944,8 +945,11 @@ Datum RASTER_to_binary(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } + if (!PG_ARGISNULL(1)) + outasin = PG_GETARG_BOOL(1); + /* Parse raster to wkb object */ - wkb = rt_raster_to_wkb(raster, &wkb_size); + wkb = rt_raster_to_wkb(raster, outasin, &wkb_size); if (!wkb) { elog(ERROR, "RASTER_to_binary: Could not allocate and generate WKB data"); rt_raster_destroy(raster); diff --git a/raster/rt_pg/rtpostgis.sql.in b/raster/rt_pg/rtpostgis.sql.in index 184f10133..691283df4 100644 --- a/raster/rt_pg/rtpostgis.sql.in +++ b/raster/rt_pg/rtpostgis.sql.in @@ -4814,7 +4814,7 @@ CREATE OR REPLACE FUNCTION st_minpossiblevalue(pixeltype text) -- Raster Outputs ----------------------------------------------------------------------- -CREATE OR REPLACE FUNCTION st_asbinary(raster) +CREATE OR REPLACE FUNCTION st_asbinary(raster, outasin boolean DEFAULT FALSE) RETURNS bytea AS 'MODULE_PATHNAME', 'RASTER_to_binary' LANGUAGE 'c' IMMUTABLE STRICT; diff --git a/raster/rt_pg/rtpostgis_drop.sql.in b/raster/rt_pg/rtpostgis_drop.sql.in index ac1bfaaac..f521772c6 100644 --- a/raster/rt_pg/rtpostgis_drop.sql.in +++ b/raster/rt_pg/rtpostgis_drop.sql.in @@ -483,3 +483,6 @@ DROP FUNCTION IF EXISTS st_tile(raster, integer, integer); -- function no longer exists DROP FUNCTION IF EXISTS _add_raster_constraint_regular_blocking(name, name, name); + +-- function signature changed +DROP FUNCTION IF EXISTS st_asbinary(raster); diff --git a/raster/test/cunit/cu_raster_wkb.c b/raster/test/cunit/cu_raster_wkb.c index 89e75a10e..00366774b 100644 --- a/raster/test/cunit/cu_raster_wkb.c +++ b/raster/test/cunit/cu_raster_wkb.c @@ -65,7 +65,7 @@ static void test_raster_wkb() { CU_ASSERT_EQUAL(rt_raster_get_width(raster), 7); CU_ASSERT_EQUAL(rt_raster_get_height(raster), 8); - out = rt_raster_to_hexwkb(raster, &len); + out = rt_raster_to_hexwkb(raster, FALSE, &len); /* printf(" in hexwkb len: %d\n", strlen(hexwkb)); printf("out hexwkb len: %d\n", len); @@ -123,7 +123,7 @@ static void test_raster_wkb() { CU_ASSERT_EQUAL(rt_raster_get_width(raster), 7); CU_ASSERT_EQUAL(rt_raster_get_height(raster), 8); - out = rt_raster_to_hexwkb(raster, &len); + out = rt_raster_to_hexwkb(raster, FALSE, &len); /* printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb)); printf("out hexwkb len: %u\n", len); @@ -187,7 +187,7 @@ static void test_raster_wkb() { CU_ASSERT_DOUBLE_EQUAL(val, 1, DBL_EPSILON); } - out = rt_raster_to_hexwkb(raster, &len); + out = rt_raster_to_hexwkb(raster, FALSE, &len); /* printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb)); printf("out hexwkb len: %u\n", len); @@ -276,7 +276,7 @@ static void test_raster_wkb() { CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON); } - out = rt_raster_to_hexwkb(raster, &len); + out = rt_raster_to_hexwkb(raster, FALSE, &len); /* printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb)); printf("out hexwkb len: %u\n", len); @@ -375,7 +375,7 @@ static void test_raster_wkb() { CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON); } - out = rt_raster_to_hexwkb(raster, &len); + out = rt_raster_to_hexwkb(raster, FALSE, &len); /* printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb)); printf("out hexwkb len: %u\n", len); @@ -461,7 +461,7 @@ static void test_raster_wkb() { CU_ASSERT_DOUBLE_EQUAL(val, 2, DBL_EPSILON); } - out = rt_raster_to_hexwkb(raster, &len); + out = rt_raster_to_hexwkb(raster, FALSE, &len); /* printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb)); printf("out hexwkb len: %u\n", len); @@ -525,7 +525,7 @@ static void test_raster_wkb() { CU_ASSERT_EQUAL(bandnum, 3); } - out = rt_raster_to_hexwkb(raster, &len); + out = rt_raster_to_hexwkb(raster, FALSE, &len); /* printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb)); printf("out hexwkb len: %u\n", len); @@ -598,7 +598,7 @@ static void test_raster_wkb() { CU_ASSERT_DOUBLE_EQUAL(val, 431, DBL_EPSILON); } - out = rt_raster_to_hexwkb(raster, &len); + out = rt_raster_to_hexwkb(raster, FALSE, &len); /* printf(" in hexwkb len: %d\n", strlen(hexwkb)); printf("out hexwkb len: %d\n", len); @@ -768,7 +768,7 @@ static void test_raster_wkb() { CU_ASSERT_DOUBLE_EQUAL(val, 161, DBL_EPSILON); } - out = rt_raster_to_hexwkb(raster, &len); + out = rt_raster_to_hexwkb(raster, FALSE, &len); /* printf(" in hexwkb len: %u\n", (uint32_t) strlen(hexwkb)); printf("out hexwkb len: %u\n", len); diff --git a/raster/test/regress/rt_bytea-post.pl b/raster/test/regress/rt_bytea-post.pl new file mode 100755 index 000000000..a48c932ff --- /dev/null +++ b/raster/test/regress/rt_bytea-post.pl @@ -0,0 +1,8 @@ +use File::Basename; +use Cwd 'abs_path'; + +my $REGDIR = abs_path(dirname($0)); +my $RASTERDIR = abs_path($REGDIR . "/../raster/test/regress"); + +unlink $RASTERDIR . '/' . $TEST . '-pre.sql'; +unlink $RASTERDIR . '/' . $TEST . '-post.sql'; diff --git a/raster/test/regress/rt_bytea-post.sh b/raster/test/regress/rt_bytea-post.sh new file mode 100755 index 000000000..e17075809 --- /dev/null +++ b/raster/test/regress/rt_bytea-post.sh @@ -0,0 +1,6 @@ +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +rm -f "$DIR/$TEST-pre.sql" +rm -f "$DIR/$TEST-post.sql" diff --git a/raster/test/regress/rt_bytea-pre.pl b/raster/test/regress/rt_bytea-pre.pl new file mode 100755 index 000000000..8a05dd3a0 --- /dev/null +++ b/raster/test/regress/rt_bytea-pre.pl @@ -0,0 +1,54 @@ +use File::Basename; +use Cwd 'abs_path'; + +my $REGDIR = abs_path(dirname($0)); +my $RASTERDIR = abs_path($REGDIR . "/../raster/test/regress"); +my $FILERASTER = $RASTERDIR . "/loader/testraster.tif"; + +my $sql = <<"END"; +DROP TABLE IF EXISTS raster_outdb_template; +CREATE TABLE raster_outdb_template AS +SELECT + 1 AS rid, + ST_AddBand( + ST_MakeEmptyRaster(90, 90, 0., 0., 1, -1, 0, 0, 0), + 1, '$FILERASTER'::text, NULL::int[] + ) AS rast +UNION ALL +SELECT + 2 AS rid, + ST_AddBand( + ST_MakeEmptyRaster(90, 90, 0., 0., 1, -1, 0, 0, 0), + '$FILERASTER'::text, NULL::int[] + ) AS rast +UNION ALL +SELECT + 3 AS rid, + ST_AddBand( + ST_AddBand( + ST_MakeEmptyRaster(90, 90, 0., 0., 1, -1, 0, 0, 0), + 1, '8BUI', 1, 0 + ), + '$FILERASTER'::text, ARRAY[2]::int[] + ) AS rast +UNION ALL +SELECT + 4 AS rid, + ST_AddBand( + ST_AddBand( + ST_MakeEmptyRaster(90, 90, 0., 0., 1, -1, 0, 0, 0), + 1, '8BUI', 1, 0 + ), + '$FILERASTER'::text, ARRAY[2]::int[], + 1, + 255 + ) AS rast +END + +open(PRESQL, '>', $RASTERDIR . '/' . $TEST . '-pre.sql'); +print PRESQL $sql; +close(PRESQL); + +open(POSTSQL, '>', $RASTERDIR . '/' . $TEST . '-post.sql'); +print POSTSQL "DROP TABLE IF EXISTS raster_outdb_template;\n"; +close(POSTSQL); diff --git a/raster/test/regress/rt_bytea-pre.sh b/raster/test/regress/rt_bytea-pre.sh new file mode 100755 index 000000000..68770fa6b --- /dev/null +++ b/raster/test/regress/rt_bytea-pre.sh @@ -0,0 +1,49 @@ +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +FILERASTER="$DIR/loader/testraster.tif" + +SQL=" \ +DROP TABLE IF EXISTS raster_outdb_template; \ +CREATE TABLE raster_outdb_template AS \ +SELECT \ + 1 AS rid, \ + ST_AddBand( \ + ST_MakeEmptyRaster(90, 90, 0., 0., 1, -1, 0, 0, 0), \ + 1, '$FILERASTER'::text, NULL::int[] \ + ) AS rast \ +UNION ALL \ +SELECT \ + 2 AS rid, \ + ST_AddBand( \ + ST_MakeEmptyRaster(90, 90, 0., 0., 1, -1, 0, 0, 0), \ + '$FILERASTER'::text, NULL::int[] \ + ) AS rast \ +UNION ALL \ +SELECT \ + 3 AS rid, \ + ST_AddBand( \ + ST_AddBand( \ + ST_MakeEmptyRaster(90, 90, 0., 0., 1, -1, 0, 0, 0), \ + 1, '8BUI', 1, 0 \ + ), \ + '$FILERASTER'::text, ARRAY[2]::int[] \ + ) AS rast \ +UNION ALL \ +SELECT \ + 4 AS rid, \ + ST_AddBand( \ + ST_AddBand( \ + ST_MakeEmptyRaster(90, 90, 0., 0., 1, -1, 0, 0, 0), \ + 1, '8BUI', 1, 0 \ + ), \ + '$FILERASTER'::text, ARRAY[2]::int[], \ + 1, \ + 255 \ + ) AS rast \ +" + +echo "$SQL" > "$DIR/$TEST-pre.sql" + +echo "DROP TABLE IF EXISTS raster_outdb_template;" > "$DIR/$TEST-post.sql" diff --git a/raster/test/regress/rt_bytea.sql b/raster/test/regress/rt_bytea.sql index 968c98037..f74c2f97c 100644 --- a/raster/test/regress/rt_bytea.sql +++ b/raster/test/regress/rt_bytea.sql @@ -167,3 +167,40 @@ WHERE -- Cleanup DROP TABLE rt_bytea_test; + +----------------------------------------------------------------------- +--- Test out-db as in-db +----------------------------------------------------------------------- +WITH foo AS ( + SELECT + rid, + ST_AsBinary(rast, FALSE) AS outout, + ST_AsBinary(rast, TRUE) AS outin + FROM raster_outdb_template +) +SELECT + rid +FROM foo +WHERE encode(outout, 'base64') = encode(outin, 'base64'); +WITH foo AS ( + SELECT + rid, + rast::bytea AS outbytea, + ST_AsBinary(rast, FALSE) AS outout + FROM raster_outdb_template +) +SELECT + rid +FROM foo +WHERE encode(outbytea, 'base64') != encode(outout, 'base64'); +WITH foo AS ( + SELECT + rid, + rast::bytea AS outbytea, + ST_AsBinary(rast, TRUE) AS outin + FROM raster_outdb_template +) +SELECT + rid +FROM foo +WHERE encode(outbytea, 'base64') = encode(outin, 'base64');