#include "postgres.h" #include #include #include "kokes.h" #include "access/gist.h" #include "access/skey.h" #include "lib/stringinfo.h" #include "utils/array.h" #include "utils/builtins.h" #include "libpq/pqformat.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(kokes_in); PG_FUNCTION_INFO_V1(kokes_out); PG_FUNCTION_INFO_V1(kokes_send); PG_FUNCTION_INFO_V1(kokes_recv); Datum kokes_in(PG_FUNCTION_ARGS); Datum kokes_out(PG_FUNCTION_ARGS); Datum kokes_send(PG_FUNCTION_ARGS); Datum kokes_recv(PG_FUNCTION_ARGS); extern int kokes_yyparse(); extern void kokes_scanner_init(const char *str); extern void kokes_scanner_finish(void); static void print_double_list(StringInfo str, double *data, unsigned long cntpnt); static void print_short_list(StringInfo str, short int *data, unsigned long cntpnt); static char *print_info(StringInfo str, char *buf); static char *print_infos(StringInfo str, char *buf); static char *print_atrs(StringInfo str, char *buf); KokesData *kokes; #define PORTABLE_SERIALIZATION Datum kokes_in(PG_FUNCTION_ARGS) { char *str; str = PG_GETARG_CSTRING(0); kokes_scanner_init(str); if (kokes_yyparse() != 0) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("bogus input"))); elog(NOTICE, "KOKES SIZE %d, pointer: %d, LEN: %d", VARSIZE( kokes), kokes, kokes->vl_len_); kokes_scanner_finish(); PG_RETURN_KokesData(kokes); } Datum kokes_out(PG_FUNCTION_ARGS) { Kokes kokes; StringInfoData buf; char *readbuf; initStringInfo(&buf); kokes = PG_GETARG_KokesData(0); elog(NOTICE, "1"); appendStringInfo(&buf, "((%u ", kokes->status); elog(NOTICE, "2"); appendStringInfo(&buf, "(%ld %ld %ld %ld) ", kokes->OOO[0], kokes->OOO[1], kokes->OOO[2], kokes->OOO[3]); appendStringInfo(&buf, "%lu %lu %d %d)", kokes->key, kokes->cntpnt, kokes->layer, kokes->alias); elog(NOTICE, ">>> %s", buf.data); print_double_list(&buf, KOKES_X_ARRAY(kokes), kokes->cntpnt); print_double_list(&buf, KOKES_Y_ARRAY(kokes), kokes->cntpnt); print_short_list(&buf, KOKES_SP_ARRAY(kokes), kokes->cntpnt); readbuf = print_infos(&buf, KOKES_INF_ARRAY(kokes)); print_atrs(&buf, readbuf); elog(NOTICE, "3"); appendStringInfoChar(&buf, ')'); PG_FREE_IF_COPY(kokes, 0); PG_RETURN_CSTRING(buf.data); } static void print_double_list(StringInfo str, double *data, unsigned long cntpnt) { int i; appendStringInfo(str, " ("); for (i = 0; i < cntpnt; i++) if (i > 0) appendStringInfo(str, " %g", data[i]); else appendStringInfo(str, "%g", data[i]); appendStringInfoChar(str, ')'); } static void print_short_list(StringInfo str, short int *data, unsigned long cntpnt) { int i; appendStringInfo(str, " ("); for (i = 0; i < cntpnt; i++) if (i > 0) appendStringInfo(str, " %d", data[i]); else appendStringInfo(str, "%d", data[i]); appendStringInfoChar(str, ')'); } static char * print_info(StringInfo str, char *buf) { GINFLEN ginflen = *((GINFLEN *) buf); int processed_chars = 0; buf += sizeof(GINFLEN); appendStringInfoChar(str, '('); /* pokud ma bod informace zobraz je */ if (*buf != '\0') { while (processed_chars < ginflen) { if (processed_chars != 0) appendStringInfoChar(str, ' '); appendStringInfo(str, "%c='", *buf++); processed_chars += 1; while (*buf != '\t' && *buf != '\0') { appendStringInfoChar(str, *buf++); processed_chars += 1; } appendStringInfoChar(str, '\''); if (*buf++ == '\0') break; processed_chars += 1; } } appendStringInfoChar(str, ')'); return buf; } static char * print_infos(StringInfo str, char *buf) { GATRLEN gatrlen = *((GATRLEN *) buf); char *endbuf; buf += sizeof(GATRLEN); endbuf = buf + gatrlen; appendStringInfo(str, " ("); while (buf < endbuf) { buf = print_info(str, buf); } appendStringInfoChar(str, ')'); return buf; } static char * print_atrs(StringInfo str, char *buf) { GATRLEN gatrlen = *((GATRLEN *) buf); int processed_chars = 0; buf += sizeof(GATRLEN); appendStringInfo(str, " ("); while (processed_chars++ < gatrlen) { char c = *buf++; switch (c) { case '\0': appendStringInfoChar(str, '\''); break; case '=': appendStringInfo(str, "='"); break; case '\n': appendStringInfo(str, "' "); break; default: appendStringInfoChar(str, c); } } appendStringInfoChar(str, ')'); return buf; } /* * Serializace je jednoducha - prenese se pole bytu. * Tato serializace je funkci pouze pri shode uladani poradi bajtu! * tj. je nezbytne aby server bezel na stejne platforme (z pohledu * poradi ukladni bajtu) jako klient - pokud by tato podminka neplatila * musel by se polozky struktury serializovat samostatne!! * coz by nebyl az takovy problem a patrne by to nebylo nijak zvlast * poznat na vykonu a bylo by to prenositelne, tj. do dalsi verze * pridat variantu */ #define FILLINT(kokes, buf, field) kokes->field = pq_getmsgint(buf, sizeof(kokes->field)) #define PUTINT(kokes, buf, field) pq_sendint(&buf, kokes->field, sizeof(kokes->field)) Datum kokes_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); Kokes kokes; #ifdef PORTABLE_SERIALIZATION unsigned long cntpnt; int i; size_t size; double *aux_dp; short int *aux_sp; #endif #ifndef PORTABLE_SERIALIZATION kokes = palloc(buf->len + VARHDRSZ); pq_copymsgbytes(buf, VARDATA(kokes), buf->len); SET_VARSIZE(kokes, buf->len + VARHDRSZ); #else cntpnt = pq_getmsgint(buf, sizeof(unsigned long)); size = offsetof(KokesData, data[0]) + (2 * sizeof(double)*cntpnt) + sizeof(short int)*cntpnt; kokes = (Kokes) palloc(size); kokes->cntpnt = cntpnt; FILLINT(kokes, buf, status); FILLINT(kokes, buf, key); FILLINT(kokes, buf, layer); FILLINT(kokes, buf, alias); FILLINT(kokes, buf, reserva); FILLINT(kokes, buf, OOO[0]); FILLINT(kokes, buf, OOO[1]); FILLINT(kokes, buf, OOO[2]); FILLINT(kokes, buf, OOO[3]); aux_dp = KOKES_X_ARRAY(kokes); for (i = 0; i < kokes->cntpnt; i++) *aux_dp++ = pq_getmsgfloat8(buf); aux_dp = KOKES_Y_ARRAY(kokes); for (i = 0; i < kokes->cntpnt; i++) *aux_dp++ = pq_getmsgfloat8(buf); aux_sp = KOKES_SP_ARRAY(kokes); for (i = 0; i < kokes->cntpnt; i++) *aux_sp++ = pq_getmsgint(buf, sizeof(short int)); #endif PG_RETURN_KokesData(kokes); } Datum kokes_send(PG_FUNCTION_ARGS) { Kokes kokes = PG_GETARG_KokesData(0); StringInfoData buf; #ifdef PORTABLE_SERIALIZATION int i; double *aux_dp; short int *aux_sp; #endif pq_begintypsend(&buf); #ifndef PORTABLE_SERIALIZATION pq_sendbytes(&buf, VARDATA(kokes), VARSIZE(kokes) - VARHDRSZ); #else PUTINT(kokes, buf, cntpnt); PUTINT(kokes, buf, status); PUTINT(kokes, buf, key); PUTINT(kokes, buf, layer); PUTINT(kokes, buf, alias); PUTINT(kokes, buf, reserva); PUTINT(kokes, buf, OOO[0]); PUTINT(kokes, buf, OOO[1]); PUTINT(kokes, buf, OOO[2]); PUTINT(kokes, buf, OOO[3]); aux_dp = KOKES_X_ARRAY(kokes); for (i = 0; i < kokes->cntpnt; i++) pq_sendfloat8(&buf, *aux_dp++); aux_dp = KOKES_Y_ARRAY(kokes); for (i = 0; i < kokes->cntpnt; i++) pq_sendfloat8(&buf, *aux_dp++); aux_sp = KOKES_SP_ARRAY(kokes); for (i = 0; i < kokes->cntpnt; i++) pq_sendint(&buf, *aux_sp++, sizeof(short int)); #endif PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }