Add in schema check for validity

to pointclound metadata table
This commit is contained in:
Paul Ramsey 2013-01-21 10:20:24 -08:00
parent e8a7788d00
commit 06a256616d
8 changed files with 95 additions and 19 deletions

View File

@ -24,6 +24,9 @@ clean:
@rm -f $(OBJS) $(LIBPC_A)
$(MAKE) -C cunit $@
install:
@echo "No install target in libpc"
check:
$(MAKE) -C cunit $@

View File

@ -20,8 +20,9 @@ static int
init_suite(void)
{
char *xmlstr = file_to_str(xmlfile);
schema = pc_schema_from_xml(xmlstr);
int rv = pc_schema_from_xml(xmlstr, &schema);
pcfree(xmlstr);
if ( rv == PC_FAILURE ) return 1;
return 0;
}

View File

@ -37,7 +37,7 @@ static void
test_schema_from_xml()
{
char *xmlstr = file_to_str(xmlfile);
schema = pc_schema_from_xml(xmlstr);
int rv = pc_schema_from_xml(xmlstr, &schema);
pcfree(xmlstr);
// char *schemastr = pc_schema_to_json(schema);

View File

@ -188,7 +188,7 @@ void pc_install_default_handlers(void);
/** Release the memory in a schema structure */
void pc_schema_free(PCSCHEMA *pcs);
/** Build a schema structure from the XML serialisation */
PCSCHEMA* pc_schema_from_xml(const char *xmlstr);
int pc_schema_from_xml(const char *xmlstr, PCSCHEMA **schema);
/** Print out JSON readable format of schema */
char* pc_schema_to_json(const PCSCHEMA *pcs);
/** Extract dimension information by position */

View File

@ -198,7 +198,8 @@ pc_schema_calculate_byteoffsets(const PCSCHEMA *pcs)
}
/** Population a PCSCHEMA struct from the XML representation */
PCSCHEMA* pc_schema_from_xml(const char *xml_str)
int
pc_schema_from_xml(const char *xml_str, PCSCHEMA **schema)
{
xmlDocPtr xml_doc = NULL;
xmlNodePtr xml_root = NULL;
@ -206,18 +207,27 @@ PCSCHEMA* pc_schema_from_xml(const char *xml_str)
xmlXPathContextPtr xpath_ctx;
xmlXPathObjectPtr xpath_obj;
xmlNodeSetPtr nodes;
PCSCHEMA *s = NULL;
PCSCHEMA *s;
const char *xml_ptr = xml_str;
size_t xml_size = strlen(xml_str);
/* Roll forward to start of XML string */
while( (*xml_ptr != '\0') && (*xml_ptr != '<') )
{
xml_ptr++;
}
size_t xml_size = strlen(xml_ptr);
static xmlChar *xpath_str = "/pc:PointCloudSchema/pc:dimension";
/* Parse XML doc */
*schema = NULL;
xmlInitParser();
xml_doc = xmlReadMemory(xml_str, xml_size, NULL, NULL, 0);
xml_doc = xmlReadMemory(xml_ptr, xml_size, NULL, NULL, 0);
if ( ! xml_doc )
{
xmlCleanupParser();
pcerror("unable to parse schema XML");
pcwarn("unable to parse schema XML");
return PC_FAILURE;
}
/* Capture the namespace */
@ -231,7 +241,8 @@ PCSCHEMA* pc_schema_from_xml(const char *xml_str)
{
xmlFreeDoc(xml_doc);
xmlCleanupParser();
pcerror("unable to create new XPath context to read schema XML");
pcwarn("unable to create new XPath context to read schema XML");
return PC_FAILURE;
}
/* Register the root namespace if there is one */
@ -245,7 +256,8 @@ PCSCHEMA* pc_schema_from_xml(const char *xml_str)
xmlXPathFreeContext(xpath_ctx);
xmlFreeDoc(xml_doc);
xmlCleanupParser();
pcerror("unable to evaluate xpath expression \"%s\" against schema XML", xpath_str);
pcwarn("unable to evaluate xpath expression \"%s\" against schema XML", xpath_str);
return PC_FAILURE;
}
/* Iterate on the dimensions we found */
@ -254,6 +266,7 @@ PCSCHEMA* pc_schema_from_xml(const char *xml_str)
int ndims = nodes->nodeNr;
int i;
s = pc_schema_new(ndims);
*schema = s;
for ( i = 0; i < ndims; i++ )
{
@ -312,7 +325,9 @@ PCSCHEMA* pc_schema_from_xml(const char *xml_str)
xmlXPathFreeContext(xpath_ctx);
xmlFreeDoc(xml_doc);
xmlCleanupParser();
pcerror("schema dimension at position \"%d\" is declared twice", d->position + 1, ndims);
pc_schema_free(s);
pcwarn("schema dimension at position \"%d\" is declared twice", d->position + 1, ndims);
return PC_FAILURE;
}
s->dims[d->position] = d;
d->size = pc_interpretation_size(d->interpretation);
@ -323,7 +338,13 @@ PCSCHEMA* pc_schema_from_xml(const char *xml_str)
}
else
{
xmlXPathFreeObject(xpath_obj);
xmlXPathFreeContext(xpath_ctx);
xmlFreeDoc(xml_doc);
xmlCleanupParser();
pc_schema_free(s);
pcwarn("schema dimension states position \"%d\", but number of XML dimensions is \"%d\"", d->position + 1, ndims);
return PC_FAILURE;
}
}
}
@ -338,7 +359,7 @@ PCSCHEMA* pc_schema_from_xml(const char *xml_str)
xmlFreeDoc(xml_doc);
xmlCleanupParser();
return s;
return PC_SUCCESS;
}
uint32_t

View File

@ -48,15 +48,15 @@ Datum PC_SchemaIsValid(PG_FUNCTION_ARGS)
bool valid;
text *xml = PG_GETARG_TEXT_P(0);
char *xmlstr = text_to_cstring(xml);
PCSCHEMA *schema = pc_schema_from_xml(xmlstr);
PCSCHEMA *schema;
int err = pc_schema_from_xml(xmlstr, &schema);
pfree(xmlstr);
if ( ! schema )
if ( ! err )
{
elog(NOTICE, "pc_schema_from_xml returned NULL");
PG_RETURN_BOOL(FALSE);
}
valid = pc_schema_is_valid(schema);
PG_RETURN_BOOL(valid);
}

View File

@ -136,11 +136,12 @@ pc_get_schema_by_id(uint32_t pcid)
SPI_finish();
/* Build the schema object */
schema = pc_schema_from_xml(xml);
err = pc_schema_from_xml(xml, &schema);
if ( ! schema )
if ( ! err )
{
elog(ERROR, "unable to parse XML representation of schema");
return NULL;
}
return schema;

View File

@ -17,4 +17,54 @@ CREATE TABLE pointcloud_formats (
);
-- Register pointcloud_formats table so the contents are included in pg_dump output
SELECT pg_catalog.pg_extension_config_dump('pointcloud_formats', '');
SELECT pg_catalog.pg_extension_config_dump('pointcloud_formats', '');
-- Sample data
INSERT INTO pointcloud_formats (pcid, srid, schema) VALUES (1, 4326, '<?xml version="1.0" encoding="UTF-8"?>
<pc:PointCloudSchema xmlns:pc="http://pointcloud.org/schemas/PC/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<pc:dimension>
<pc:position>1</pc:position>
<pc:size>4</pc:size>
<pc:description>X coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>X</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>0.01</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>2</pc:position>
<pc:size>4</pc:size>
<pc:description>Y coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>Y</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>0.01</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>3</pc:position>
<pc:size>4</pc:size>
<pc:description>Z coordinate as a long integer. You must use the scale and offset information of the header to determine the double value.</pc:description>
<pc:name>Z</pc:name>
<pc:interpretation>int32_t</pc:interpretation>
<pc:scale>0.01</pc:scale>
</pc:dimension>
<pc:dimension>
<pc:position>4</pc:position>
<pc:size>2</pc:size>
<pc:description>The intensity value is the integer representation of the pulse return magnitude. This value is optional and system specific. However, it should always be included if available.</pc:description>
<pc:name>Intensity</pc:name>
<pc:interpretation>uint16_t</pc:interpretation>
<pc:scale>1</pc:scale>
</pc:dimension>
<pc:metadata>
<Metadata name="compression"></Metadata>
<Metadata name="ght_xmin"></Metadata>
<Metadata name="ght_ymin"></Metadata>
<Metadata name="ght_xmax"></Metadata>
<Metadata name="ght_ymax"></Metadata>
<Metadata name="ght_keylength"></Metadata>
<Metadata name="ght_depth"></Metadata>
<Metadata name="spatialreference" type="id" authority="EPSG">4326</Metadata>
</pc:metadata>
</pc:PointCloudSchema>
');