diff --git a/doc/src/sgml/auto-explain.sgml b/doc/src/sgml/auto-explain.sgml index c8215e0cc8..1a6dce0e42 100644 --- a/doc/src/sgml/auto-explain.sgml +++ b/doc/src/sgml/auto-explain.sgml @@ -1,4 +1,4 @@ - + auto_explain @@ -150,18 +150,19 @@ explain.log_min_duration = '3s' This might produce log output such as: - + Hash Join (cost=3.91..14.70 rows=81 width=0) Hash Cond: (pg_class.oid = pg_index.indrelid) - -> Seq Scan on pg_class (cost=0.00..8.27 rows=227 width=4) - -> Hash (cost=2.90..2.90 rows=81 width=4) - -> Seq Scan on pg_index (cost=0.00..2.90 rows=81 width=4) + -> Seq Scan on pg_class (cost=0.00..8.27 rows=227 width=4) + -> Hash (cost=2.90..2.90 rows=81 width=4) + -> Seq Scan on pg_index (cost=0.00..2.90 rows=81 width=4) Filter: indisunique STATEMENT: SELECT count(*) FROM pg_class, pg_index WHERE oid = indrelid AND indisunique; +]]> diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml index 0a99cf3303..fdb55c4aec 100644 --- a/doc/src/sgml/ecpg.sgml +++ b/doc/src/sgml/ecpg.sgml @@ -1,4 +1,4 @@ - + <application>ECPG</application> - Embedded <acronym>SQL</acronym> in C @@ -717,9 +717,9 @@ EXEC SQL EXECUTE mystmt USING 42, 'foobar'; If the statement you are executing returns values, then add an INTO clause: - + ?"; int v1, v2; VARCHAR v3; EXEC SQL END DECLARE SECTION; @@ -727,6 +727,7 @@ EXEC SQL END DECLARE SECTION; EXEC SQL PREPARE mystmt FROM :stmt; ... EXEC SQL EXECUTE mystmt INTO v1, v2, v3 USING 37; +]]> An EXECUTE command can have an INTO clause, a USING clause, @@ -752,7 +753,7 @@ EXEC SQL DEALLOCATE PREPARE name; functions to do basic calculations with those types within C, i.e. without the help of the PostgreSQL server. See the following example: - + @@ -3449,14 +3451,15 @@ int rsetnull(int t, char *ptr); Here is an example of a call to this function: - + @@ -3477,14 +3480,15 @@ int risnull(int t, char *ptr); Here is an example of how to use this function: - + @@ -4960,11 +4964,11 @@ EXEC SQL END DECLARE SECTION; EXEC SQL SELECT res INTO :result FROM mytable WHERE index = :index; is translated into: - +; +#include ; /* exec sql begin declare section */ @@ -4975,11 +4979,12 @@ EXEC SQL SELECT res INTO :result FROM mytable WHERE index = :index; /* exec sql end declare section */ ... ECPGdo(__LINE__, NULL, "SELECT res FROM mytable WHERE index = ? ", - ECPGt_int,&(index),1L,1L,sizeof(int), + ECPGt_int,&(index),1L,1L,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, - ECPGt_int,&(result),1L,1L,sizeof(int), + ECPGt_int,&(result),1L,1L,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); #line 147 "foo.pgc" +]]> (The indentation here is added for readability and not something the preprocessor does.) diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index a9d0d98d04..327eee1c2c 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1,4 +1,4 @@ - + <application>libpq</application> - C Library @@ -5415,8 +5415,9 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough) + /* The instanceData */ typedef struct @@ -5488,17 +5489,17 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) case PGEVT_REGISTER: { PGEventRegister *e = (PGEventRegister *)evtInfo; - mydata *data = get_mydata(e->conn); + mydata *data = get_mydata(e->conn); /* associate app specific data with connection */ - PQsetInstanceData(e->conn, myEventProc, data); + PQsetInstanceData(e->conn, myEventProc, data); break; } case PGEVT_CONNRESET: { PGEventConnReset *e = (PGEventConnReset *)evtInfo; - mydata *data = PQinstanceData(e->conn, myEventProc); + mydata *data = PQinstanceData(e->conn, myEventProc); if (data) memset(data, 0, sizeof(mydata)); @@ -5508,7 +5509,7 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) case PGEVT_CONNDESTROY: { PGEventConnDestroy *e = (PGEventConnDestroy *)evtInfo; - mydata *data = PQinstanceData(e->conn, myEventProc); + mydata *data = PQinstanceData(e->conn, myEventProc); /* free instance data because the conn is being destroyed */ if (data) @@ -5519,29 +5520,29 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) case PGEVT_RESULTCREATE: { PGEventResultCreate *e = (PGEventResultCreate *)evtInfo; - mydata *conn_data = PQinstanceData(e->conn, myEventProc); + mydata *conn_data = PQinstanceData(e->conn, myEventProc); mydata *res_data = dup_mydata(conn_data); /* associate app specific data with result (copy it from conn) */ - PQsetResultInstanceData(e->result, myEventProc, res_data); + PQsetResultInstanceData(e->result, myEventProc, res_data); break; } case PGEVT_RESULTCOPY: { PGEventResultCopy *e = (PGEventResultCopy *)evtInfo; - mydata *src_data = PQresultInstanceData(e->src, myEventProc); + mydata *src_data = PQresultInstanceData(e->src, myEventProc); mydata *dest_data = dup_mydata(src_data); /* associate app specific data with result (copy it from a result) */ - PQsetResultInstanceData(e->dest, myEventProc, dest_data); + PQsetResultInstanceData(e->dest, myEventProc, dest_data); break; } case PGEVT_RESULTDESTROY: { PGEventResultDestroy *e = (PGEventResultDestroy *)evtInfo; - mydata *data = PQresultInstanceData(e->result, myEventProc); + mydata *data = PQresultInstanceData(e->result, myEventProc); /* free instance data because the result is being destroyed */ if (data) @@ -5556,6 +5557,7 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) return TRUE; /* event processing succeeded */ } +]]> @@ -6407,13 +6409,14 @@ testlibpq.o(.text+0xa4): undefined reference to `PQerrorMessage' <application>libpq</application> Example Program 1 + +#include #include "libpq-fe.h" static void @@ -6438,7 +6441,7 @@ main(int argc, char **argv) * conninfo string; otherwise default to setting dbname=postgres and using * environment variables or defaults for all other connection parameters. */ - if (argc > 1) + if (argc > 1) conninfo = argv[1]; else conninfo = "dbname = postgres"; @@ -6498,14 +6501,14 @@ main(int argc, char **argv) /* first, print out the attribute names */ nFields = PQnfields(res); - for (i = 0; i < nFields; i++) + for (i = 0; i < nFields; i++) printf("%-15s", PQfname(res, i)); printf("\n\n"); /* next, print out the rows */ - for (i = 0; i < PQntuples(res); i++) + for (i = 0; i < PQntuples(res); i++) { - for (j = 0; j < nFields; j++) + for (j = 0; j < nFields; j++) printf("%-15s", PQgetvalue(res, i, j)); printf("\n"); } @@ -6525,6 +6528,7 @@ main(int argc, char **argv) return 0; } +]]> @@ -6532,6 +6536,7 @@ main(int argc, char **argv) <application>libpq</application> Example Program 2 + +#include +#include +#include +#include #include "libpq-fe.h" static void @@ -6583,7 +6588,7 @@ main(int argc, char **argv) * conninfo string; otherwise default to setting dbname=postgres and using * environment variables or defaults for all other connection parameters. */ - if (argc > 1) + if (argc > 1) conninfo = argv[1]; else conninfo = "dbname = postgres"; @@ -6618,7 +6623,7 @@ main(int argc, char **argv) /* Quit after four notifies are received. */ nnotifies = 0; - while (nnotifies < 4) + while (nnotifies < 4) { /* * Sleep until something happens on the connection. We use select(2) @@ -6630,13 +6635,13 @@ main(int argc, char **argv) sock = PQsocket(conn); - if (sock < 0) + if (sock < 0) break; /* shouldn't happen */ - FD_ZERO(&input_mask); - FD_SET(sock, &input_mask); + FD_ZERO(&input_mask); + FD_SET(sock, &input_mask); - if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0) + if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0) { fprintf(stderr, "select() failed: %s\n", strerror(errno)); exit_nicely(conn); @@ -6648,7 +6653,7 @@ main(int argc, char **argv) { fprintf(stderr, "ASYNC NOTIFY of '%s' received from backend pid %d\n", - notify->relname, notify->be_pid); + notify->relname, notify->be_pid); PQfreemem(notify); nnotifies++; } @@ -6661,6 +6666,7 @@ main(int argc, char **argv) return 0; } +]]> @@ -6668,6 +6674,7 @@ main(int argc, char **argv) <application>libpq</application> Example Program 3</> <programlisting> +<![CDATA[ /* * testlibpq3.c * Test out-of-line parameters and binary I/O. @@ -6692,15 +6699,15 @@ main(int argc, char **argv) * t = (8 bytes) 'ho there' * b = (5 bytes) \004\003\002\001\000 */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> #include "libpq-fe.h" /* for ntohl/htonl */ -#include <netinet/in.h> -#include <arpa/inet.h> +#include <netinet/in.h> +#include <arpa/inet.h> static void @@ -6729,7 +6736,7 @@ show_binary_results(PGresult *res) t_fnum = PQfnumber(res, "t"); b_fnum = PQfnumber(res, "b"); - for (i = 0; i < PQntuples(res); i++) + for (i = 0; i < PQntuples(res); i++) { char *iptr; char *tptr; @@ -6764,7 +6771,7 @@ show_binary_results(PGresult *res) printf(" t = (%d bytes) '%s'\n", PQgetlength(res, i, t_fnum), tptr); printf(" b = (%d bytes) ", blen); - for (j = 0; j < blen; j++) + for (j = 0; j < blen; j++) printf("\\%03o", bptr[j]); printf("\n\n"); } @@ -6786,7 +6793,7 @@ main(int argc, char **argv) * conninfo string; otherwise default to setting dbname=postgres and using * environment variables or defaults for all other connection parameters. */ - if (argc > 1) + if (argc > 1) conninfo = argv[1]; else conninfo = "dbname = postgres"; @@ -6850,7 +6857,7 @@ main(int argc, char **argv) binaryIntVal = htonl((uint32_t) 2); /* Set up parameter arrays for PQexecParams */ - paramValues[0] = (char *) &binaryIntVal; + paramValues[0] = (char *) &binaryIntVal; paramLengths[0] = sizeof(binaryIntVal); paramFormats[0] = 1; /* binary */ @@ -6879,6 +6886,7 @@ main(int argc, char **argv) return 0; } +]]> </programlisting> </example> diff --git a/doc/src/sgml/lobj.sgml b/doc/src/sgml/lobj.sgml index 65ac435e36..750b9c5c4e 100644 --- a/doc/src/sgml/lobj.sgml +++ b/doc/src/sgml/lobj.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/lobj.sgml,v 1.48 2008/03/22 01:55:14 ishii Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/lobj.sgml,v 1.49 2008/12/07 23:46:39 alvherre Exp $ --> <chapter id="largeObjects"> <title id="largeObjects-title">Large Objects @@ -457,7 +457,7 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image Large Objects with <application>libpq</application> Example Program - + +#include "libpq-fe.h" +#include "libpq/libpq-fs.h" #define BUFSIZE 1024 /* * importFile - * import file "in_filename" into database as large object "lobjOid" + * import file "in_filename" into database as large object "lobjOid" * */ Oid @@ -492,9 +492,9 @@ importFile(PGconn *conn, char *filename) * open the file to be read in */ fd = open(filename, O_RDONLY, 0666); - if (fd < 0) + if (fd < 0) { /* error */ - fprintf(stderr, "cannot open unix file %s\n", filename); + fprintf(stderr, "cannot open unix file %s\n", filename); } /* @@ -502,18 +502,18 @@ importFile(PGconn *conn, char *filename) */ lobjId = lo_creat(conn, INV_READ | INV_WRITE); if (lobjId == 0) - fprintf(stderr, "cannot create large object\n"); + fprintf(stderr, "cannot create large object\n"); lobj_fd = lo_open(conn, lobjId, INV_WRITE); /* * read in from the Unix file and write to the inversion file */ - while ((nbytes = read(fd, buf, BUFSIZE)) > 0) + while ((nbytes = read(fd, buf, BUFSIZE)) > 0) { tmp = lo_write(conn, lobj_fd, buf, nbytes); - if (tmp < nbytes) - fprintf(stderr, "error while reading large object\n"); + if (tmp < nbytes) + fprintf(stderr, "error while reading large object\n"); } (void) close(fd); @@ -531,9 +531,9 @@ pickout(PGconn *conn, Oid lobjId, int start, int len) int nread; lobj_fd = lo_open(conn, lobjId, INV_READ); - if (lobj_fd < 0) + if (lobj_fd < 0) { - fprintf(stderr, "cannot open large object %d\n", + fprintf(stderr, "cannot open large object %d\n", lobjId); } @@ -541,15 +541,15 @@ pickout(PGconn *conn, Oid lobjId, int start, int len) buf = malloc(len + 1); nread = 0; - while (len - nread > 0) + while (len - nread > 0) { nbytes = lo_read(conn, lobj_fd, buf, len - nread); buf[nbytes] = ' '; - fprintf(stderr, ">>> %s", buf); + fprintf(stderr, ">>> %s", buf); nread += nbytes; } free(buf); - fprintf(stderr, "\n"); + fprintf(stderr, "\n"); lo_close(conn, lobj_fd); } @@ -563,33 +563,33 @@ overwrite(PGconn *conn, Oid lobjId, int start, int len) int i; lobj_fd = lo_open(conn, lobjId, INV_WRITE); - if (lobj_fd < 0) + if (lobj_fd < 0) { - fprintf(stderr, "cannot open large object %d\n", + fprintf(stderr, "cannot open large object %d\n", lobjId); } lo_lseek(conn, lobj_fd, start, SEEK_SET); buf = malloc(len + 1); - for (i = 0; i < len; i++) + for (i = 0; i < len; i++) buf[i] = 'X'; buf[i] = ' '; nwritten = 0; - while (len - nwritten > 0) + while (len - nwritten > 0) { nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten); nwritten += nbytes; } free(buf); - fprintf(stderr, "\n"); + fprintf(stderr, "\n"); lo_close(conn, lobj_fd); } /* * exportFile - * export large object "lobjOid" to file "out_filename" + * export large object "lobjOid" to file "out_filename" * */ void @@ -605,9 +605,9 @@ exportFile(PGconn *conn, Oid lobjId, char *filename) * open the large object */ lobj_fd = lo_open(conn, lobjId, INV_READ); - if (lobj_fd < 0) + if (lobj_fd < 0) { - fprintf(stderr, "cannot open large object %d\n", + fprintf(stderr, "cannot open large object %d\n", lobjId); } @@ -615,21 +615,21 @@ exportFile(PGconn *conn, Oid lobjId, char *filename) * open the file to be written to */ fd = open(filename, O_CREAT | O_WRONLY, 0666); - if (fd < 0) + if (fd < 0) { /* error */ - fprintf(stderr, "cannot open unix file %s\n", + fprintf(stderr, "cannot open unix file %s\n", filename); } /* * read in from the inversion file and write to the Unix file */ - while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0) + while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0) { tmp = write(fd, buf, nbytes); - if (tmp < nbytes) + if (tmp < nbytes) { - fprintf(stderr, "error while writing %s\n", + fprintf(stderr, "error while writing %s\n", filename); } } @@ -659,7 +659,7 @@ main(int argc, char **argv) if (argc != 4) { - fprintf(stderr, "Usage: %s database_name in_filename out_filename\n", + fprintf(stderr, "Usage: %s database_name in_filename out_filename\n", argv[0]); exit(1); } @@ -676,36 +676,37 @@ main(int argc, char **argv) /* check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) { - fprintf(stderr, "Connection to database '%s' failed.\n", database); - fprintf(stderr, "%s", PQerrorMessage(conn)); + fprintf(stderr, "Connection to database '%s' failed.\n", database); + fprintf(stderr, "%s", PQerrorMessage(conn)); exit_nicely(conn); } - res = PQexec(conn, "begin"); + res = PQexec(conn, "begin"); PQclear(res); - printf("importing file %s\n", in_filename); + printf("importing file %s\n", in_filename); /* lobjOid = importFile(conn, in_filename); */ lobjOid = lo_import(conn, in_filename); /* - printf("as large object %d.\n", lobjOid); + printf("as large object %d.\n", lobjOid); - printf("picking out bytes 1000-2000 of the large object\n"); + printf("picking out bytes 1000-2000 of the large object\n"); pickout(conn, lobjOid, 1000, 1000); - printf("overwriting bytes 1000-2000 of the large object with X's\n"); + printf("overwriting bytes 1000-2000 of the large object with X's\n"); overwrite(conn, lobjOid, 1000, 1000); */ - printf("exporting large object to file %s\n", out_filename); + printf("exporting large object to file %s\n", out_filename); /* exportFile(conn, lobjOid, out_filename); */ lo_export(conn, lobjOid, out_filename); - res = PQexec(conn, "end"); + res = PQexec(conn, "end"); PQclear(res); PQfinish(conn); exit(0); } +]]> diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml index a13925b066..9e7fab64a2 100644 --- a/doc/src/sgml/trigger.sgml +++ b/doc/src/sgml/trigger.sgml @@ -1,4 +1,4 @@ - + Triggers @@ -559,7 +559,7 @@ CREATE TABLE ttest ( This is the source code of the trigger function: - +context; TupleDesc tupdesc; HeapTuple rettuple; char *when; @@ -584,38 +584,38 @@ trigf(PG_FUNCTION_ARGS) elog(ERROR, "trigf: not called by trigger manager"); /* tuple to return to executor */ - if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) - rettuple = trigdata->tg_newtuple; + if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) + rettuple = trigdata->tg_newtuple; else - rettuple = trigdata->tg_trigtuple; + rettuple = trigdata->tg_trigtuple; /* check for null values */ - if (!TRIGGER_FIRED_BY_DELETE(trigdata->tg_event) - && TRIGGER_FIRED_BEFORE(trigdata->tg_event)) + if (!TRIGGER_FIRED_BY_DELETE(trigdata->tg_event) + && TRIGGER_FIRED_BEFORE(trigdata->tg_event)) checknull = true; - if (TRIGGER_FIRED_BEFORE(trigdata->tg_event)) + if (TRIGGER_FIRED_BEFORE(trigdata->tg_event)) when = "before"; else when = "after "; - tupdesc = trigdata->tg_relation->rd_att; + tupdesc = trigdata->tg_relation->rd_att; /* connect to SPI manager */ - if ((ret = SPI_connect()) < 0) + if ((ret = SPI_connect()) < 0) elog(INFO, "trigf (fired %s): SPI_connect returned %d", when, ret); /* get number of rows in table */ ret = SPI_exec("SELECT count(*) FROM ttest", 0); - if (ret < 0) + if (ret < 0) elog(NOTICE, "trigf (fired %s): SPI_exec returned %d", when, ret); /* count(*) returns int8, so be careful to convert */ - i = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[0], - SPI_tuptable->tupdesc, + i = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[0], + SPI_tuptable->tupdesc, 1, - &isnull)); + &isnull)); elog (INFO, "trigf (fired %s): there are %d rows in ttest", when, i); @@ -623,13 +623,14 @@ trigf(PG_FUNCTION_ARGS) if (checknull) { - SPI_getbinval(rettuple, tupdesc, 1, &isnull); + SPI_getbinval(rettuple, tupdesc, 1, &isnull); if (isnull) rettuple = NULL; } return PointerGetDatum(rettuple); } +]]> diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 44c83e8dbc..863a17ff52 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,4 +1,4 @@ - + User-Defined Functions @@ -1621,15 +1621,16 @@ typedef struct { For example, if we wanted to store 40 bytes in a text structure, we might use a code fragment like this: - +length = VARHDRSZ + 40; +memcpy(destination->data, buffer, 40); ... +]]> VARHDRSZ is the same as sizeof(int4), but @@ -1842,9 +1843,9 @@ memcpy(destination->data, buffer, 40); Here are some examples: - + /* by value */ @@ -1871,8 +1872,8 @@ makepoint(Point *pointx, Point *pointy) { Point *new_point = (Point *) palloc(sizeof(Point)); - new_point->x = pointx->x; - new_point->y = pointy->y; + new_point->x = pointx->x; + new_point->y = pointy->y; return new_point; } @@ -1908,6 +1909,7 @@ concat_text(text *arg1, text *arg2) VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ); return new_text; } +]]> @@ -2014,9 +2016,9 @@ PG_FUNCTION_INFO_V1(funcname); Here we show the same functions as above, coded in version-1 style: - + #include "fmgr.h" /* by value */ @@ -2054,8 +2056,8 @@ makepoint(PG_FUNCTION_ARGS) Point *pointy = PG_GETARG_POINT_P(1); Point *new_point = (Point *) palloc(sizeof(Point)); - new_point->x = pointx->x; - new_point->y = pointy->y; + new_point->x = pointx->x; + new_point->y = pointy->y; PG_RETURN_POINT_P(new_point); } @@ -2098,6 +2100,7 @@ concat_text(PG_FUNCTION_ARGS) VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ); PG_RETURN_TEXT_P(new_text); } +]]> @@ -2552,7 +2555,7 @@ SELECT name, c_overpaid(emp, 1500) AS overpaid Using call conventions version 0, we can define c_overpaid as: - + limit; } +]]> In version-1 coding, the above would look like this: - + limit); } +]]> @@ -2974,7 +2979,7 @@ my_set_returning_function(PG_FUNCTION_ARGS) A complete example of a simple SRF returning a composite type looks like: - +multi_call_memory_ctx); /* total number of tuples to be returned */ - funcctx->max_calls = PG_GETARG_UINT32(0); + funcctx->max_calls = PG_GETARG_UINT32(0); /* Build a tuple descriptor for our result type */ - if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " @@ -3012,7 +3017,7 @@ retcomposite(PG_FUNCTION_ARGS) * C strings */ attinmeta = TupleDescGetAttInMetadata(tupdesc); - funcctx->attinmeta = attinmeta; + funcctx->attinmeta = attinmeta; MemoryContextSwitchTo(oldcontext); } @@ -3020,11 +3025,11 @@ retcomposite(PG_FUNCTION_ARGS) /* stuff done on every call of the function */ funcctx = SRF_PERCALL_SETUP(); - call_cntr = funcctx->call_cntr; - max_calls = funcctx->max_calls; - attinmeta = funcctx->attinmeta; + call_cntr = funcctx->call_cntr; + max_calls = funcctx->max_calls; + attinmeta = funcctx->attinmeta; - if (call_cntr < max_calls) /* do when there is more left to send */ + if (call_cntr < max_calls) /* do when there is more left to send */ { char **values; HeapTuple tuple; @@ -3063,6 +3068,7 @@ retcomposite(PG_FUNCTION_ARGS) SRF_RETURN_DONE(funcctx); } } +]]> One way to declare this function in SQL is: diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml index 84b2c9050a..485b6c06a1 100644 --- a/doc/src/sgml/xindex.sgml +++ b/doc/src/sgml/xindex.sgml @@ -1,4 +1,4 @@ - + Interfacing Extensions To Indexes @@ -499,8 +499,8 @@ reduces the odds of getting inconsistent results for corner cases. Following this approach, we first write: - -#define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y) +x*(c)->x + (c)->y*(c)->y) static int complex_abs_cmp_internal(Complex *a, Complex *b) @@ -508,17 +508,18 @@ complex_abs_cmp_internal(Complex *a, Complex *b) double amag = Mag(a), bmag = Mag(b); - if (amag < bmag) + if (amag < bmag) return -1; - if (amag > bmag) + if (amag > bmag) return 1; return 0; } +]]> Now the less-than function looks like: - + The other four functions differ only in how they compare the internal @@ -617,15 +619,16 @@ CREATE FUNCTION complex_abs_cmp(complex, complex) Now that we have the required operators and support routine, we can finally create the operator class: - += , + OPERATOR 5 > , FUNCTION 1 complex_abs_cmp(complex, complex); +]]> @@ -708,87 +711,88 @@ CREATE OPERATOR CLASS complex_abs_ops on one of these types can be searched using a comparison value of another type. The family could be duplicated by these definitions: - += , + OPERATOR 5 > , FUNCTION 1 btint8cmp(int8, int8) ; CREATE OPERATOR CLASS int4_ops DEFAULT FOR TYPE int4 USING btree FAMILY integer_ops AS -- standard int4 comparisons - OPERATOR 1 < , - OPERATOR 2 <= , + OPERATOR 1 < , + OPERATOR 2 <= , OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , + OPERATOR 4 >= , + OPERATOR 5 > , FUNCTION 1 btint4cmp(int4, int4) ; CREATE OPERATOR CLASS int2_ops DEFAULT FOR TYPE int2 USING btree FAMILY integer_ops AS -- standard int2 comparisons - OPERATOR 1 < , - OPERATOR 2 <= , + OPERATOR 1 < , + OPERATOR 2 <= , OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , + OPERATOR 4 >= , + OPERATOR 5 > , FUNCTION 1 btint2cmp(int2, int2) ; ALTER OPERATOR FAMILY integer_ops USING btree ADD -- cross-type comparisons int8 vs int2 - OPERATOR 1 < (int8, int2) , - OPERATOR 2 <= (int8, int2) , + OPERATOR 1 < (int8, int2) , + OPERATOR 2 <= (int8, int2) , OPERATOR 3 = (int8, int2) , - OPERATOR 4 >= (int8, int2) , - OPERATOR 5 > (int8, int2) , + OPERATOR 4 >= (int8, int2) , + OPERATOR 5 > (int8, int2) , FUNCTION 1 btint82cmp(int8, int2) , -- cross-type comparisons int8 vs int4 - OPERATOR 1 < (int8, int4) , - OPERATOR 2 <= (int8, int4) , + OPERATOR 1 < (int8, int4) , + OPERATOR 2 <= (int8, int4) , OPERATOR 3 = (int8, int4) , - OPERATOR 4 >= (int8, int4) , - OPERATOR 5 > (int8, int4) , + OPERATOR 4 >= (int8, int4) , + OPERATOR 5 > (int8, int4) , FUNCTION 1 btint84cmp(int8, int4) , -- cross-type comparisons int4 vs int2 - OPERATOR 1 < (int4, int2) , - OPERATOR 2 <= (int4, int2) , + OPERATOR 1 < (int4, int2) , + OPERATOR 2 <= (int4, int2) , OPERATOR 3 = (int4, int2) , - OPERATOR 4 >= (int4, int2) , - OPERATOR 5 > (int4, int2) , + OPERATOR 4 >= (int4, int2) , + OPERATOR 5 > (int4, int2) , FUNCTION 1 btint42cmp(int4, int2) , -- cross-type comparisons int4 vs int8 - OPERATOR 1 < (int4, int8) , - OPERATOR 2 <= (int4, int8) , + OPERATOR 1 < (int4, int8) , + OPERATOR 2 <= (int4, int8) , OPERATOR 3 = (int4, int8) , - OPERATOR 4 >= (int4, int8) , - OPERATOR 5 > (int4, int8) , + OPERATOR 4 >= (int4, int8) , + OPERATOR 5 > (int4, int8) , FUNCTION 1 btint48cmp(int4, int8) , -- cross-type comparisons int2 vs int8 - OPERATOR 1 < (int2, int8) , - OPERATOR 2 <= (int2, int8) , + OPERATOR 1 < (int2, int8) , + OPERATOR 2 <= (int2, int8) , OPERATOR 3 = (int2, int8) , - OPERATOR 4 >= (int2, int8) , - OPERATOR 5 > (int2, int8) , + OPERATOR 4 >= (int2, int8) , + OPERATOR 5 > (int2, int8) , FUNCTION 1 btint28cmp(int2, int8) , -- cross-type comparisons int2 vs int4 - OPERATOR 1 < (int2, int4) , - OPERATOR 2 <= (int2, int4) , + OPERATOR 1 < (int2, int4) , + OPERATOR 2 <= (int2, int4) , OPERATOR 3 = (int2, int4) , - OPERATOR 4 >= (int2, int4) , - OPERATOR 5 > (int2, int4) , + OPERATOR 4 >= (int2, int4) , + OPERATOR 5 > (int2, int4) , FUNCTION 1 btint24cmp(int2, int4) ; +]]> Notice that this definition overloads the operator strategy and diff --git a/doc/src/sgml/xtypes.sgml b/doc/src/sgml/xtypes.sgml index c80126a119..14eb83a8e1 100644 --- a/doc/src/sgml/xtypes.sgml +++ b/doc/src/sgml/xtypes.sgml @@ -1,4 +1,4 @@ - + User-Defined Types @@ -75,7 +75,7 @@ typedef struct Complex { write a complete and robust parser for that representation as your input function. For instance: - +x = x; + result->y = y; PG_RETURN_POINTER(result); } +]]> The output function can simply be: - +x, complex->y); PG_RETURN_CSTRING(result); } +]]> @@ -134,7 +136,7 @@ complex_out(PG_FUNCTION_ARGS) complex, we will piggy-back on the binary I/O converters for type float8: - +x = pq_getmsgfloat8(buf); + result->y = pq_getmsgfloat8(buf); PG_RETURN_POINTER(result); } @@ -157,11 +159,12 @@ complex_send(PG_FUNCTION_ARGS) Complex *complex = (Complex *) PG_GETARG_POINTER(0); StringInfoData buf; - pq_begintypsend(&buf); - pq_sendfloat8(&buf, complex->x); - pq_sendfloat8(&buf, complex->y); - PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); + pq_begintypsend(&buf); + pq_sendfloat8(&buf, complex->x); + pq_sendfloat8(&buf, complex->y); + PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); } +]]>