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 *
<refsynopsisdiv>
<funcsynopsis>
<funcprototype>
- <funcdef>bytea <function>ST_AsBinary</function></funcdef>
- <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
+ <funcdef>bytea <function>ST_AsBinary</function></funcdef>
+ <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
+ <paramdef choice="opt"><type>boolean </type> <parameter>outasin=FALSE</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsection>
<title>Description</title>
- <para>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.</para>
- <para>This is useful in binary cursors to pull data out of the
- database without converting it to a string representation.</para>
- </refsection>
+ <para>
+ Returns the Binary representation of the raster. If <varname>outasin</varname> is TRUE, out-db bands are treated as in-db.
+ </para>
+
+ <para>
+ This is useful in binary cursors to pull data out of the database without converting it to a string representation.
+ </para>
+
+ <note>
+ <para>
+ 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 <varname>outasin</varname> to TRUE.</para>
+ </note>
+
+ <para>Enhanced: 2.1.0 Addition of <varname>outasin</varname></para>
+ </refsection>
<refsection>
<title>Examples</title>
- <programlisting>SELECT ST_AsBinary(rast) As rastbin
-FROM dummy_rast WHERE rid=1;
+ <programlisting>
+SELECT ST_AsBinary(rast) As rastbin FROM dummy_rast WHERE rid=1;
rastbin
---------------------------------------------------------------------------------
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) {
}
/* 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) {
}
/* 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) {
}
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;
/* Add space for nodata value */
size += pixbytes;
- if (band->offline) {
+ if (!outasin && band->offline) {
/* Add space for band number */
size += 1;
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;
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);
/* 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;
assert(!((uint64_t) ptr % pixbytes));
#endif
- if (band->offline) {
+ if (!outasin && band->offline) {
/* Write band number */
*ptr = band->data.offline.bandNum;
ptr += 1;
/* 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;
}
}
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;
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");
* 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
* 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
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);
}
/* 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);
}
/**
- * 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)
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));
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);
-- 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;
-- 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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
--- /dev/null
+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';
--- /dev/null
+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"
--- /dev/null
+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);
--- /dev/null
+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"
-- 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');