#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "geopackage.h"
static int fail(const char *what, gpkg_error_t *error) {
fprintf(stderr, "%s: code=%d message=%s\n", what, (int)error->code,
error->message ? error->message : "(none)");
gpkg_error_clear(error);
return 1;
}
static long long drain(struct ArrowArrayStream *stream) {
long long rows = 0;
for (;;) {
struct ArrowArray array;
memset(&array, 0, sizeof(array));
if (stream->get_next(stream, &array) != 0) {
const char *detail = stream->get_last_error(stream);
fprintf(stderr, "get_next: %s\n", detail ? detail : "(none)");
stream->release(stream);
return -1;
}
if (array.release == NULL) {
break;
}
rows += array.length;
array.release(&array);
}
stream->release(stream);
return rows;
}
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "usage: query <file.gpkg> <layer>\n");
return 2;
}
gpkg_error_t error = {GPKG_STATUS_OK, NULL};
gpkg_t *gpkg = gpkg_open_read_only(argv[1], &error);
if (!gpkg) {
return fail("gpkg_open_read_only", &error);
}
const char *columns[] = {"name"};
gpkg_layer_t *layer =
gpkg_layer_open_with_columns(gpkg, argv[2], columns, 1, &error);
if (!layer) {
return fail("gpkg_layer_open_with_columns", &error);
}
int32_t srs_id = 0;
if (gpkg_layer_srs_id(layer, &srs_id, &error) != GPKG_STATUS_OK) {
return fail("gpkg_layer_srs_id", &error);
}
char *organization = NULL;
int32_t code = 0;
char *definition = NULL;
if (gpkg_srs(gpkg, srs_id, NULL, &organization, &code, &definition, NULL,
NULL, &error) != GPKG_STATUS_OK) {
return fail("gpkg_srs", &error);
}
printf("crs: %s:%d, definition %zu bytes\n", organization, (int)code,
strlen(definition));
gpkg_string_free(organization);
gpkg_string_free(definition);
double bbox[4] = {-180.0, -90.0, 180.0, 90.0};
struct ArrowArrayStream stream;
memset(&stream, 0, sizeof(stream));
if (gpkg_layer_read_arrow_filtered(layer, bbox, NULL, NULL, 0, &stream,
&error) != GPKG_STATUS_OK) {
return fail("gpkg_layer_read_arrow_filtered (bbox)", &error);
}
long long in_view = drain(&stream);
if (in_view < 0) {
return 1;
}
printf("in view: %lld rows\n", in_view);
gpkg_value_t wanted = {GPKG_VALUE_KIND_TEXT, {.text = "alpha"}};
memset(&stream, 0, sizeof(stream));
if (gpkg_layer_read_arrow_filtered(layer, bbox, "name = ?1", &wanted, 1,
&stream, &error) != GPKG_STATUS_OK) {
return fail("gpkg_layer_read_arrow_filtered (subset)", &error);
}
long long matching = drain(&stream);
if (matching < 0) {
return 1;
}
printf("matching subset: %lld rows\n", matching);
gpkg_value_t fid = {GPKG_VALUE_KIND_INTEGER, {.integer = 1}};
memset(&stream, 0, sizeof(stream));
if (gpkg_layer_read_arrow_filtered(layer, NULL, "fid = ?1", &fid, 1,
&stream, &error) != GPKG_STATUS_OK) {
return fail("gpkg_layer_read_arrow_filtered (fid)", &error);
}
long long selected = drain(&stream);
if (selected < 0) {
return 1;
}
printf("selected by fid: %lld rows\n", selected);
gpkg_layer_free(layer);
if (gpkg_close(gpkg, &error) != GPKG_STATUS_OK) {
return fail("gpkg_close", &error);
}
printf("ok\n");
return 0;
}