280{
281 uint16_t i, ci;
282 flatgeobuf_column *column;
284 uint32_t offset = 0;
285 uint8_t *
data = ctx->
ctx->properties;
286 uint32_t size = ctx->
ctx->properties_len;
287
288 POSTGIS_DEBUGF(3, "flatgeobuf: decode_properties from byte array with length %d at offset %d", size, offset);
289
290
291
292 if (size > 0 && size < (sizeof(uint16_t) + sizeof(uint8_t)))
293 elog(ERROR, "flatgeobuf: decode_properties: Unexpected properties data size %d", size);
294 while (offset + 1 < size) {
295 if (offset + sizeof(uint16_t) > size)
296 elog(ERROR, "flatgeobuf: decode_properties: Unexpected offset %d", offset);
297 memcpy(&i, data + offset, sizeof(uint16_t));
298 ci = i + 2;
299 offset += sizeof(uint16_t);
300 if (i >= ctx->
ctx->columns_size)
301 elog(ERROR, "flatgeobuf: decode_properties: Column index %hu out of range", i);
302 column = ctx->
ctx->columns[i];
304 isnull[ci] = false;
305 switch (type) {
306 case flatgeobuf_column_type_bool: {
308 if (offset + sizeof(uint8_t) > size)
309 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for bool value");
310 memcpy(&value, data + offset, sizeof(uint8_t));
311 values[ci] = BoolGetDatum(value);
312 offset += sizeof(uint8_t);
313 break;
314 }
315 case flatgeobuf_column_type_byte: {
317 if (offset + sizeof(int8_t) > size)
318 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for byte value");
319 memcpy(&value, data + offset, sizeof(int8_t));
320 values[ci] = Int8GetDatum(value);
321 offset += sizeof(int8_t);
322 break;
323 }
324 case flatgeobuf_column_type_ubyte: {
326 if (offset + sizeof(uint8_t) > size)
327 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for ubyte value");
328 memcpy(&value, data + offset, sizeof(uint8_t));
329 values[ci] = UInt8GetDatum(value);
330 offset += sizeof(uint8_t);
331 break;
332 }
333 case flatgeobuf_column_type_short: {
335 if (offset + sizeof(int16_t) > size)
336 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for short value");
337 memcpy(&value, data + offset, sizeof(int16_t));
338 values[ci] = Int16GetDatum(value);
339 offset += sizeof(int16_t);
340 break;
341 }
342 case flatgeobuf_column_type_ushort: {
344 if (offset + sizeof(uint16_t) > size)
345 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for ushort value");
346 memcpy(&value, data + offset, sizeof(uint16_t));
347 values[ci] = UInt16GetDatum(value);
348 offset += sizeof(uint16_t);
349 break;
350 }
351 case flatgeobuf_column_type_int: {
353 if (offset + sizeof(int32_t) > size)
354 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for int value");
355 memcpy(&value, data + offset, sizeof(int32_t));
356 values[ci] = Int32GetDatum(value);
357 offset += sizeof(int32_t);
358 break;
359 }
360 case flatgeobuf_column_type_uint: {
362 if (offset + sizeof(uint32_t) > size)
363 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for uint value");
364 memcpy(&value, data + offset, sizeof(uint32_t));
365 values[ci] = UInt32GetDatum(value);
366 offset += sizeof(uint32_t);
367 break;
368 }
369 case flatgeobuf_column_type_long: {
371 if (offset + sizeof(int64_t) > size)
372 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for long value");
373 memcpy(&value, data + offset, sizeof(int64_t));
374 values[ci] = Int64GetDatum(value);
375 offset += sizeof(int64_t);
376 break;
377 }
378 case flatgeobuf_column_type_ulong: {
380 if (offset + sizeof(uint64_t) > size)
381 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for ulong value");
382 memcpy(&value, data + offset, sizeof(uint64_t));
383 values[ci] = UInt64GetDatum(value);
384 offset += sizeof(uint64_t);
385 break;
386 }
387 case flatgeobuf_column_type_float: {
389 if (offset + sizeof(float) > size)
390 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for float value");
391 memcpy(&value, data + offset, sizeof(float));
392 values[ci] = Float4GetDatum(value);
393 offset += sizeof(float);
394 break;
395 }
396 case flatgeobuf_column_type_double: {
398 if (offset + sizeof(double) > size)
399 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for double value");
400 memcpy(&value, data + offset, sizeof(double));
401 values[ci] = Float8GetDatum(value);
402 offset += sizeof(double);
403 break;
404 }
405 case flatgeobuf_column_type_string: {
406 uint32_t len;
407 if (offset + sizeof(len) > size)
408 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for string value");
409 memcpy(&len, data + offset, sizeof(uint32_t));
410 offset += sizeof(len);
411 values[ci] = PointerGetDatum(cstring_to_text_with_len((const char *) data + offset, len));
412 offset += len;
413 break;
414 }
415 case flatgeobuf_column_type_datetime: {
416 uint32_t len;
417 char *buf;
418 char workbuf[MAXDATELEN + MAXDATEFIELDS];
419 char *field[MAXDATEFIELDS];
420 int ftype[MAXDATEFIELDS];
421 int dtype;
422 int nf;
423 struct pg_tm tt, *tm = &tt;
424 fsec_t fsec;
425 int tzp;
426 TimestampTz dttz;
427#if POSTGIS_PGSQL_VERSION >= 160
428 DateTimeErrorExtra extra;
429#endif
430 if (offset + sizeof(len) > size)
431 elog(ERROR, "flatgeobuf: decode_properties: Invalid size for string value");
432 memcpy(&len, data + offset, sizeof(uint32_t));
433 offset += sizeof(len);
434 buf = palloc0(len + 1);
435 memcpy(buf, (const char *) data + offset, len);
436 ParseDateTime((const char *) buf, workbuf, sizeof(workbuf), field, ftype, MAXDATEFIELDS, &nf);
437
438#if POSTGIS_PGSQL_VERSION >= 160
439 DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp, &extra);
440#else
441 DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp);
442#endif
443 tm2timestamp(tm, fsec, &tzp, &dttz);
444 values[ci] = TimestampTzGetDatum(dttz);
445 offset += len;
446 break;
447 }
448
449
450
451
452
453
454
455
456
457 default:
458 elog(ERROR, "flatgeobuf: decode_properties: Unknown type %d", type);
459 }
460 }
461
462}