30 #include "../postgis_config.h"
31 #include "lwgeom_pg.h"
33 #include "lwgeom_cache.h"
35 #include <executor/spi.h>
36 #include <utils/builtins.h>
40 switch (column_type) {
41 case flatgeobuf_column_type_bool:
43 case flatgeobuf_column_type_byte:
44 case flatgeobuf_column_type_ubyte:
46 case flatgeobuf_column_type_short:
48 case flatgeobuf_column_type_int:
50 case flatgeobuf_column_type_uint:
51 case flatgeobuf_column_type_long:
52 case flatgeobuf_column_type_ulong:
54 case flatgeobuf_column_type_float:
56 case flatgeobuf_column_type_double:
57 return "double precision";
58 case flatgeobuf_column_type_datetime:
60 case flatgeobuf_column_type_string:
62 case flatgeobuf_column_type_binary:
64 case flatgeobuf_column_type_json:
67 elog(ERROR,
"unknown column_type %d", column_type);
83 size_t column_defs_total_len;
84 char *column_defs_str;
91 schema_input = PG_GETARG_TEXT_P(0);
92 schema = text_to_cstring(schema_input);
94 table_input = PG_GETARG_TEXT_P(1);
95 table = text_to_cstring(table_input);
97 data = PG_GETARG_BYTEA_PP(2);
99 ctx = palloc0(
sizeof(*
ctx));
100 ctx->ctx = palloc0(
sizeof(flatgeobuf_ctx));
101 ctx->ctx->size = VARSIZE_ANY_EXHDR(
data);
102 POSTGIS_DEBUGF(3,
"bytea data size is %ld",
ctx->ctx->size);
104 memcpy(
ctx->ctx->buf, VARDATA_ANY(
data),
ctx->ctx->size);
105 ctx->ctx->offset = 0;
108 flatgeobuf_decode_header(
ctx->ctx);
110 column_defs = palloc(
sizeof(
char *) *
ctx->ctx->columns_size);
111 column_defs_total_len = 0;
112 POSTGIS_DEBUGF(2,
"found %d columns",
ctx->ctx->columns_size);
113 for (i = 0; i <
ctx->ctx->columns_size; i++) {
114 flatgeobuf_column *column =
ctx->ctx->columns[i];
115 const char *name = column->name;
116 uint8_t column_type = column->type;
118 size_t len = strlen(name) + 1 + strlen(pgtype) + 1;
119 column_defs[i] = palloc0(
sizeof(
char) * len);
120 strcat(column_defs[i], name);
121 strcat(column_defs[i],
" ");
122 strcat(column_defs[i], pgtype);
123 column_defs_total_len += len;
125 column_defs_str = palloc0(
sizeof(
char) * column_defs_total_len + (
ctx->ctx->columns_size * 2) + 2 + 1);
126 if (
ctx->ctx->columns_size > 0)
127 strcat(column_defs_str,
", ");
128 for (i = 0; i <
ctx->ctx->columns_size; i++) {
129 strcat(column_defs_str, column_defs[i]);
130 if (i < ctx->
ctx->columns_size - 1)
131 strcat(column_defs_str,
", ");
134 POSTGIS_DEBUGF(2,
"column_defs_str %s", column_defs_str);
136 format =
"create table %s.%s (id int, geom geometry%s)";
137 sql = palloc0(strlen(format) + strlen(schema) + strlen(table) + strlen(column_defs_str) + 1);
139 sprintf(
sql, format, schema, table, column_defs_str);
141 POSTGIS_DEBUGF(3,
"sql: %s",
sql);
143 if (SPI_connect() != SPI_OK_CONNECT)
144 elog(ERROR,
"Failed to connect SPI");
146 if (SPI_execute(
sql,
false, 0) != SPI_OK_UTILITY)
147 elog(ERROR,
"Failed to create table");
149 if (SPI_finish() != SPI_OK_FINISH)
150 elog(ERROR,
"Failed to finish SPI");
152 POSTGIS_DEBUG(3,
"finished");
161 FuncCallContext *funcctx;
165 MemoryContext oldcontext;
169 if (SRF_IS_FIRSTCALL()) {
170 funcctx = SRF_FIRSTCALL_INIT();
171 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
173 funcctx->max_calls = 0;
175 if (get_call_result_type(fcinfo, NULL, &
tupdesc) != TYPEFUNC_COMPOSITE)
177 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
178 errmsg(
"function returning record called in context "
179 "that cannot accept type record")));
181 data = PG_GETARG_BYTEA_PP(1);
183 ctx = palloc0(
sizeof(*
ctx));
185 ctx->ctx = palloc0(
sizeof(flatgeobuf_ctx));
186 ctx->ctx->size = VARSIZE_ANY_EXHDR(
data);
187 POSTGIS_DEBUGF(3,
"VARSIZE_ANY_EXHDR %ld",
ctx->ctx->size);
188 ctx->ctx->buf = palloc(
ctx->ctx->size);
189 memcpy(
ctx->ctx->buf, VARDATA_ANY(
data),
ctx->ctx->size);
190 ctx->ctx->offset = 0;
194 funcctx->user_fctx =
ctx;
196 if (
ctx->ctx->size == 0) {
197 POSTGIS_DEBUG(2,
"no data");
198 MemoryContextSwitchTo(oldcontext);
199 SRF_RETURN_DONE(funcctx);
203 flatgeobuf_decode_header(
ctx->ctx);
205 POSTGIS_DEBUGF(2,
"header decoded now at offset %ld",
ctx->ctx->offset);
207 if (
ctx->ctx->size ==
ctx->ctx->offset) {
208 POSTGIS_DEBUGF(2,
"no feature data offset %ld",
ctx->ctx->offset);
209 MemoryContextSwitchTo(oldcontext);
210 SRF_RETURN_DONE(funcctx);
214 MemoryContextSwitchTo(oldcontext);
217 funcctx = SRF_PERCALL_SETUP();
218 ctx = funcctx->user_fctx;
222 POSTGIS_DEBUG(2,
"Calling SRF_RETURN_NEXT");
223 SRF_RETURN_NEXT(funcctx,
ctx->result);
225 POSTGIS_DEBUG(2,
"Calling SRF_RETURN_DONE");
226 SRF_RETURN_DONE(funcctx);
void flatgeobuf_check_magicbytes(struct flatgeobuf_decode_ctx *ctx)
void flatgeobuf_decode_row(struct flatgeobuf_decode_ctx *ctx)
void * lwalloc(size_t size)
This library is the generic geometry handling section of PostGIS.
Datum pgis_fromflatgeobuf(PG_FUNCTION_ARGS)
static char * get_pgtype(uint8_t column_type)
PG_FUNCTION_INFO_V1(pgis_tablefromflatgeobuf)
Datum pgis_tablefromflatgeobuf(PG_FUNCTION_ARGS)