#include <ctype.h>
#include "crc32.h"
+#include "libpq/pqformat.h"
#include "ltree.h"
#include "utils/memutils.h"
-PG_FUNCTION_INFO_V1(ltree_in);
-PG_FUNCTION_INFO_V1(ltree_out);
-PG_FUNCTION_INFO_V1(lquery_in);
-PG_FUNCTION_INFO_V1(lquery_out);
-
typedef struct
{
- char *start;
+ const char *start;
int len; /* length in bytes */
int flag;
int wlen; /* length in characters */
#define LTPRS_WAITNAME 0
#define LTPRS_WAITDELIM 1
-Datum
-ltree_in(PG_FUNCTION_ARGS)
+/*
+ * expects a null terminated string
+ * returns an ltree
+ */
+static ltree *
+parse_ltree(const char *buf)
{
- char *buf = (char *) PG_GETARG_POINTER(0);
- char *ptr;
+ const char *ptr;
nodeitem *list,
*lptr;
int num = 0,
}
pfree(list);
- PG_RETURN_POINTER(result);
+ return result;
#undef UNCHAR
}
-Datum
-ltree_out(PG_FUNCTION_ARGS)
+/*
+ * expects an ltree
+ * returns a null terminated string
+ */
+static char *
+deparse_ltree(const ltree *in)
{
- ltree *in = PG_GETARG_LTREE_P(0);
char *buf,
*ptr;
int i;
}
*ptr = '\0';
- PG_FREE_IF_COPY(in, 0);
+ return buf;
+}
+
+/*
+ * Basic ltree I/O functions
+ */
+PG_FUNCTION_INFO_V1(ltree_in);
+Datum
+ltree_in(PG_FUNCTION_ARGS)
+{
+ char *buf = (char *) PG_GETARG_POINTER(0);
+
+ PG_RETURN_POINTER(parse_ltree(buf));
+}
+
+PG_FUNCTION_INFO_V1(ltree_out);
+Datum
+ltree_out(PG_FUNCTION_ARGS)
+{
+ ltree *in = PG_GETARG_LTREE_P(0);
+
+ PG_RETURN_POINTER(deparse_ltree(in));
+}
+
+/*
+ * ltree type send function
+ *
+ * The type is sent as text in binary mode, so this is almost the same
+ * as the output function, but it's prefixed with a version number so we
+ * can change the binary format sent in future if necessary. For now,
+ * only version 1 is supported.
+ */
+PG_FUNCTION_INFO_V1(ltree_send);
+Datum
+ltree_send(PG_FUNCTION_ARGS)
+{
+ ltree *in = PG_GETARG_LTREE_P(0);
+ StringInfoData buf;
+ int version = 1;
+ char *res = deparse_ltree(in);
+
+ pq_begintypsend(&buf);
+ pq_sendint8(&buf, version);
+ pq_sendtext(&buf, res, strlen(res));
+ pfree(res);
+
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+/*
+ * ltree type recv function
+ *
+ * The type is sent as text in binary mode, so this is almost the same
+ * as the input function, but it's prefixed with a version number so we
+ * can change the binary format sent in future if necessary. For now,
+ * only version 1 is supported.
+ */
+PG_FUNCTION_INFO_V1(ltree_recv);
+Datum
+ltree_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ int version = pq_getmsgint(buf, 1);
+ char *str;
+ int nbytes;
+ ltree *res;
- PG_RETURN_POINTER(buf);
+ if (version != 1)
+ elog(ERROR, "unsupported ltree version number %d", version);
+
+ str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+ res = parse_ltree(str);
+ pfree(str);
+
+ PG_RETURN_POINTER(res);
}
+
#define LQPRS_WAITLEVEL 0
#define LQPRS_WAITDELIM 1
#define LQPRS_WAITOPEN 2
#define ITEMSIZE MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*))
#define NEXTLEV(x) ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) )
-Datum
-lquery_in(PG_FUNCTION_ARGS)
+/*
+ * expects a null terminated string
+ * returns an lquery
+ */
+static lquery *
+parse_lquery(const char *buf)
{
- char *buf = (char *) PG_GETARG_POINTER(0);
- char *ptr;
+ const char *ptr;
int num = 0,
totallen = 0,
numOR = 0;
}
pfree(tmpql);
- PG_RETURN_POINTER(result);
+ return result;
#undef UNCHAR
}
-Datum
-lquery_out(PG_FUNCTION_ARGS)
+/*
+ * expects an lquery
+ * returns a null terminated string
+ */
+static char *
+deparse_lquery(const lquery *in)
{
- lquery *in = PG_GETARG_LQUERY_P(0);
char *buf,
*ptr;
int i,
}
*ptr = '\0';
- PG_FREE_IF_COPY(in, 0);
+ return buf;
+}
+
+/*
+ * Basic lquery I/O functions
+ */
+PG_FUNCTION_INFO_V1(lquery_in);
+Datum
+lquery_in(PG_FUNCTION_ARGS)
+{
+ char *buf = (char *) PG_GETARG_POINTER(0);
+
+ PG_RETURN_POINTER(parse_lquery(buf));
+}
+
+PG_FUNCTION_INFO_V1(lquery_out);
+Datum
+lquery_out(PG_FUNCTION_ARGS)
+{
+ lquery *in = PG_GETARG_LQUERY_P(0);
+
+ PG_RETURN_POINTER(deparse_lquery(in));
+}
+
+/*
+ * lquery type send function
+ *
+ * The type is sent as text in binary mode, so this is almost the same
+ * as the output function, but it's prefixed with a version number so we
+ * can change the binary format sent in future if necessary. For now,
+ * only version 1 is supported.
+ */
+PG_FUNCTION_INFO_V1(lquery_send);
+Datum
+lquery_send(PG_FUNCTION_ARGS)
+{
+ lquery *in = PG_GETARG_LQUERY_P(0);
+ StringInfoData buf;
+ int version = 1;
+ char *res = deparse_lquery(in);
+
+ pq_begintypsend(&buf);
+ pq_sendint8(&buf, version);
+ pq_sendtext(&buf, res, strlen(res));
+ pfree(res);
+
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+/*
+ * lquery type recv function
+ *
+ * The type is sent as text in binary mode, so this is almost the same
+ * as the input function, but it's prefixed with a version number so we
+ * can change the binary format sent in future if necessary. For now,
+ * only version 1 is supported.
+ */
+PG_FUNCTION_INFO_V1(lquery_recv);
+Datum
+lquery_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ int version = pq_getmsgint(buf, 1);
+ char *str;
+ int nbytes;
+ lquery *res;
+
+ if (version != 1)
+ elog(ERROR, "unsupported lquery version number %d", version);
+
+ str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+ res = parse_lquery(str);
+ pfree(str);
- PG_RETURN_POINTER(buf);
+ PG_RETURN_POINTER(res);
}
#include <ctype.h>
#include "crc32.h"
+#include "libpq/pqformat.h"
#include "ltree.h"
#include "miscadmin.h"
-PG_FUNCTION_INFO_V1(ltxtq_in);
-PG_FUNCTION_INFO_V1(ltxtq_out);
-
/* parser's states */
#define WAITOPERAND 1
/*
* in without morphology
*/
+PG_FUNCTION_INFO_V1(ltxtq_in);
Datum
ltxtq_in(PG_FUNCTION_ARGS)
{
PG_RETURN_POINTER(queryin((char *) PG_GETARG_POINTER(0)));
}
+/*
+ * ltxtquery type recv function
+ *
+ * The type is sent as text in binary mode, so this is almost the same
+ * as the input function, but it's prefixed with a version number so we
+ * can change the binary format sent in future if necessary. For now,
+ * only version 1 is supported.
+ */
+PG_FUNCTION_INFO_V1(ltxtq_recv);
+Datum
+ltxtq_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ int version = pq_getmsgint(buf, 1);
+ char *str;
+ int nbytes;
+ ltxtquery *res;
+
+ if (version != 1)
+ elog(ERROR, "unsupported ltxtquery version number %d", version);
+
+ str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+ res = queryin(str);
+ pfree(str);
+
+ PG_RETURN_POINTER(res);
+}
+
/*
* out function
*/
}
}
+PG_FUNCTION_INFO_V1(ltxtq_out);
Datum
ltxtq_out(PG_FUNCTION_ARGS)
{
nrm.op = GETOPERAND(query);
infix(&nrm, true);
- PG_FREE_IF_COPY(query, 0);
PG_RETURN_POINTER(nrm.buf);
}
+
+/*
+ * ltxtquery type send function
+ *
+ * The type is sent as text in binary mode, so this is almost the same
+ * as the output function, but it's prefixed with a version number so we
+ * can change the binary format sent in future if necessary. For now,
+ * only version 1 is supported.
+ */
+PG_FUNCTION_INFO_V1(ltxtq_send);
+Datum
+ltxtq_send(PG_FUNCTION_ARGS)
+{
+ ltxtquery *query = PG_GETARG_LTXTQUERY_P(0);
+ StringInfoData buf;
+ int version = 1;
+ INFIX nrm;
+
+ if (query->size == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("syntax error"),
+ errdetail("Empty query.")));
+
+ nrm.curpol = GETQUERY(query);
+ nrm.buflen = 32;
+ nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
+ *(nrm.cur) = '\0';
+ nrm.op = GETOPERAND(query);
+ infix(&nrm, true);
+
+ pq_begintypsend(&buf);
+ pq_sendint8(&buf, version);
+ pq_sendtext(&buf, nrm.buf, strlen(nrm.buf));
+ pfree(nrm.buf);
+
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}