pqt-specs(3)

NAME

   pqt-specs - A manual for libpqtypes data type specifier strings.

DESCRIPTION

   The  type  system  allows  addressing backend data types by their fully
   qualified schema name.  Similar to the backend type system,  libpqtypes
   has   an  input  and  output  function  for  each  type:  put  and  get
   respectively.   All  builtin  types  are   supported   by   libpqtypes.
   Additional  types,  such  as  composites and user-defined types, can be
   registered by an API-user on a per connection basis.

   Putting and getting types are  addressed  by  their  backend  names  as
   printf-style  format  specifiers.  For instance: %int4, %timestamptz or
   %text.  They can also be addressed using their fully  qualified  schema
   names:  %pg_catalog.int4,  %pg_catalog.timestamptz, %pg_catalog.text or
   %myschema.mytype to avoid ambiguity.

   Specifier Strings
   Specifier Mark
   A specifier mark indicates where a specifier begins. A mark is not part
   of the type name.

      %  Marks the beginning of a type name.  When getting results, this
         also indicates that a field will be referenced by number.

      #  Marks the beginning of a type name.  When getting results, this
         also indicates that a field will be referenced by name.

      @  Marks the beginning of a prepared specifier name, see
         PQspecPrepare().  When used, it must be the first and only
         specifier in the format string: "@prepared_spec", "@myfunc",
         etc...  NOTE: the @ must be the first character, no spaces.

   Type Specifier
   Type specifiers are comprised of an optional schema name and type name.
   Type specifiers have a set of rules:

      -) Format: [schema].type - optional schema name, a "." separator
         between schema and type and the type name.

      -) First character must be a-z or an underscore

      -) Double quotes are required for characters not in [a-zA-Z0-9_]
         NOTE: In libpqtypes, this includes "double precision"

      -) Schema "." separator, specifier marks or flags are not included
         in double quotes

      -) Non-quoted type names are casefolded, quoted names are not.

      -) Examples:
         "%int4"
         "%pg_catalog.int4"
         "%\"my oDd~ !tYpe naMe#\""
         "%myschema.\"my oDd~ !tYpe naMe#\""
         "%abc.int4 %pg_catalog.int4" <= fully qualified type names

      -) Last in First out: To find a type referenced in a specifier
         string, the search begins with the last type registered.
         User registered type handlers are searched first, followed
         by builtin types.

      -) pqt schema: There is a builtin schema named pqt.  By default,
         it contains two types: str and null.  Anything can be
         put into this schema, which has nothing to do with the server.
         This is good for aliases or type sub-classes that are
         client-specific.

   Specifier Flag
   Flags are used to alter the behavior of a  type  specifier.   They  are
   always  placed at the end of the specifier name.  If the name is double
   quoted, the flag is just after the closing quote.

      *  This is called the pointer flag.  It is only supported on a
         handful of builtin types during a PQputf(3), but user registered
         types can provide support for them.  Supported types are:
         VARCHAR, BPCHAR, TEXT, BYTEA, NAME and the pqt.str.

         Putting data: this flag tells libpqtypes to store a direct
         pointer to the data being put, rather than making a copy of
         it.

         Getting data: no built-in types make use of the pointer flag.
         User-defined type handlers can make the pointer flag behave
         anyway they see fit.  The get type handler is supplied a
         PGtypeArgs which contains an is_ptr member.

      [] This is called the array flag.  It indicates that an array is
         being referenced rather than a simple type.  This flag is always
         used with a PGarray.

NUMERICS

   With the exception of the "numeric"  type,  all  numeric  types  behave
   identically: int2, int4, int8, float4 and float8.

          PG type    C type
          PGint2     short
          PGint4     int
          PGint8     long long (platform dependent)
          PGfloat4   float
          PGfloat8   double

   Putting  numeric  values: If the value supplied is too large for the PG
   type, it will be silently truncated.
          PQputf(param, "%int2 %int4 %int8 %float4 %float8",
               SHRT_MAX, INT_MAX, LLONG_MAX, 1234.56, 123456.789);

   Getting numeric values: Like scanf, the correctly sized data type  must
   be  used.   For  instance:  you cannot use a 4-byte int for %int2 - you
   must use a short.
          // Read an int2 from field 0, int4 from field 1, int8 from
          // field 2, float4 from field 3 and a float8 from field 4
          PGint2 i2;
          PGint4 i4;
          PGint8 i8;
          PGfloat4 f4;
          PGfloat8 f8;
          PQgetf(result, tup_num, "%int2 %int4 %int8 %float4 %float8",
               0, &i2, 1, &i4, 2, &i8, 3, &f4, 4, &f8);

   The numeric data type is always exposed in text format.  There is no  C
   data structure. It is always sent in binary format.
          PQputf(param, "%numeric", "1728718718271827121233.121212121212");

   Even  if  binary  results  are  used  when  getting  a  numeric  value,
   libpqtypes will internally convert the numeric to text.  This  has  the
   advantage  of  allowing you to use binary results and still have access
   to numeric fields.  If you want to work with a numeric in binary  form,
   use PQgetvalue() on a binary result set.
          PGnumeric numstr;
          PQgetf(result, tup_num, "%numeric", field_num, &numstr);

   The  first  argument  is  the  field  number of the numeric. The second
   argument is a pointer to a PGnumeric  to  receive  the  numeric  string
   value (which will always be NUL terminated).

ARRAY

   Arrays  are  put  using  the PGarray structure.  Elements are put using
   PQputf(3) into a PGparam structure  contained  withn  a  PGarray.   The
   PGarray  contains  array  dimension members for specifing the number of
   dimension, the dimensions of each dimension and  the  lower  bounds  of
   each dimension.

   Arrays  are only handled using binary format.  This means that any type
   used as an array element must be put and gotten in binary format.  If a
   user-defined  type  does  not implement a send and recv function in the
   backend, it can not be used as an array element.

   For a discussion of composite arrays, `man pqt-composites(3).
          typedef struct
          {
               /* The number of array dimensions.  Specifing zero for this
                * value on puts has special meaning.  When zero, this value
                * is set to one, dims[0] is set to the number of items in
                * the param member and lbound[0] is set to one.
                */
               int ndims;

               /* An array of lower bounds for each dimension. */
               int lbound[MAXDIM];

               /* An array of dimensions for each dimension. */
               int dims[MAXDIM];

               /* When putting array elements, this PGparam is used.  Each
                * item put is one array element.  Because the PQputf(3)
                * interface allows putting more than one item at a time, you
                * can put multiple array elements.
                */
               PGparam *param;

               /* When getting an array, this is the PGresult object that
                * contains the array elements.  Each element is one tuple,
                * regardless of the array dimensions.  If the array has 100
                * elements across 3 dimensions, PQntuples(arr.res) will return
                * 100.  The only valid field, for non-composite arrays, is
                * field zero.
                */
               PGresult *res;
          } PGarray;

   When all elements have been put, the  PGarray  structure  must  be  put
   using the "[]" array specifer flag into a PGparam structure.  PQputf(3)
   is used to build the array elements and to put the resulting PGarray.

   Putting an array value:
          PGint4 i;
          PGarray arr;
          PGparam *param;

          /* One dimensional arrays do not require setting dimension info. For
           * convience, you can zero the structure or set ndims to zero.
           */
          arr.ndims = 0;

          /* create the param object that will contain the elements */
          arr.param = PQparamCreate(conn);

          /* Use PQputf(3) to put the array elements */
          for(i=0; i < 1000; i++)
            PQputf(arr.param, "%int4", i);

          /* The PGarray must be put into a PGparam struture.  So far, only
           * the array elements have been put.  param can continue to be
           * used to pack more parameters.  The array is now a single parameter
           * within param.
           */
          param = PQparamCreate(conn);
          PQputf(param, "%int[]", &arr);

          /* no longer needed */
          PQparamClear(arr.param);

   To get an array, PQgetf(3) is used  in  conjunction  with  the  PGarray
   structure.   The  result object contained with the PGarray is populated
   with the array elements.  The dimension info is assigned as well.  Each
   array  element  is  its own tuple that only contains a single field for
   non composite arrays.

   Getting an array value:
          int i;
          PGint4 val;
          int ntups;
          PGarray arr;
          PGresult *result = ...;

          PQgetf(result, 0, "%int[]", 0, &arr);

          /* not needed anymore*/
          PQclear(result);

          /* each tuple is an array element */
          ntups = PQntuples(arr.res);
          for(i=0; i < ntups; i++)
          {
            /* Always field 0 */
            PQgetf(arr.res, i, "%int4", 0, &val);
            printf("[%03d] %d\n", i, val);
          }

          PQclear(arr.res);

   The result object  is  not  organized  based  on  the  dimension  info.
   Indexes  are always zero-based.  If the dimension info is meaningful to
   your application, index translation must be done using the ndims,  dims
   and lbound members of the PGarray structure.

   You  cannot reference an array element by field name.  The only logical
   name for an array element would be the string version of its index  ...
   "0",  "1", etc..  The index value of a non-composite array is its tuple
   number, the field number is always zero.   This  means  "#int"  is  not
   legal  for  non-composite  arrays.   You  must use "%int" and reference
   field 0.

CHAR

   The "char" data type uses the PGchar.  The value is limited to 8-bits.

   Putting a "char" value:
          PGchar c = a;
          PQputf(param, "%char %char", 213, c);

   Getting a "char" value:
          PGchar c;
          PQgetf(result, tup_num, "%char", field_num, &c);

VARIABLE-LENGTH CHARACTER TYPES

   BPCHAR, VARCHAR, NAME and TEXT  are  handled  identically.   libpqtypes
   does  no  range checking on NAME, BPCHAR or VARCHAR, it lets the server
   perform these checks.   There  are  two  ways  to  put  strings:  allow
   libpqtypes to make an internal copy of the string (default behavior) or
   as a direct pointer: (both require that the C string is NUL-terminated)
          /* Put a string so libpqtypes makes a copy. In this case,
           * 4 copies would be made of the same string.
           */
          PGtext str = "foobar";
          PQputf(param, "%bpchar %varchar %name %text", str, str, str, str);

          /* Put a string so libpqtypes doesnt make a copy,
           * keeps a direct pointer.  More efficient than above,
           * especially if these are large strings.
           */
          PQputf(param, "%bpchar* %varchar* %name* %text*", str, str, str, str);

   WARNING: Be careful about variable scope when using the  "*"  specifier
   flag:
          /* when func returns, the str pointer becomes invalid!
           * The below should be using "%text" ... w/o the * flag.
           */
          int func(PGparam *param)
          {
               PGchar str[16];
               strcpy(str, "foobar");
               return PQputf(param, "%text*", str); // BAD IDEA!
          }

   To  PQgetf(3)  a  string,  you  supply  a  pointer to a PGtext.  Unlike
   putting string values,  getting  them  doesnt  make  use  of  the  "*"
   specifier flag (silently ignored).
          /* Get a string value */
          PGvarchar str;
          PQgetf(result, tup_num, "%varchar", field_num, &str);

          /* identical to */
          str = PQgetvalue(result, tup_num, field_num);

   The  reason  the  *  specifier  flag is silently ignored, rather than
   raising a syntax error, is it is common to define macros  for  specifer
   strings; that can be used for puts and gets:
          /* user_id, username, password */
          #define TYPESPEC_USERINFO "%int4 %text* %text*"

          PGint4 uid = 0;
          PGtext user = "foo", pass = "bar";
          PQputf(param, TYPESPEC_USERINFO, uid, user, pass);
          PQgetf(param, tup_num, TYPESPEC_USERINFO, 0, &uid, 1, &user, 2, &pass);

   The above allowance is more useful than a syntax error.

BYTEA

   There  are  two  ways to put a bytea: copy or direct pointer (just like
   variable-length character types).  In either case, you supply a pointer
   to a PGbytea.
          typedef struct
          {
            int len;    /* number of bytes */
            char *data; /* pointer to the bytea data */
          } PGbytea;

          /* Put a bytea letting libpqtypes make a copy; */
          PGbytea bytea = {4, {0, 1, 2, 3}};
          PQputf(param, "%bytea", &bytea);

          /* Put a bytea not letting libpqtypes make a copy, stores a
           * direct pointer to PGbytea.data.
           */
          PQputf(param, "%bytea*", &bytea);

   To  get  a  bytea,  you provide a pointer to a PGbytea.  Unlike putting
   bytea values, there is only one way to get them.
          /* Get a bytea value (exposed as binary, no
           * escaping/unescaping needed)
           */
          PGbytea bytea;
          PQgetf(result, tup_num, "%bytea", field_num, &bytea);

   NOTE: For text results, PQgetlength will not match the length  returned
   by  PQgetf(3).   The  values  PQgetf(3)  assigns  to  the user provided
   PGbytea* represent the unescaped bytea value.

DATE

   PGdate is used by DATE, TIMESTAMP and TIMESTAMPTZ data types. To put  a
   date,  you  must  set  the isbc, year, mon and mday members.  All other
   members are ignored.

          typedef struct
          {
               /* When non-zero, the date is in the BC ERA. */
               int isbc;

               /*
                * The BC or AD year, which is NOT adjusted by 1900 like
                * the POSIX struct tm.  Years are always positive values,
                * even BC years.  To distinguish between BC and AD years,
                * use the isbc flag: (year 0 not used)
                *   Ex. -1210 is represented as: isbc=1, year=1209
                */
               int year;

               /* The number of months since January, in the range 0 to 11. */
               int mon;

               /* The day of the month, in the range 1 to 31. */
               int mday;

               /* The Julian day in the Gregorian calendar. */
               int jday;

               /* The number of days since January 1, in the range 0 to 365. */
               int yday;

               /* The number of days since Sunday, in the range 0 to 6. */
               int wday;
          } PGdate;

   Putting a date value:
          // 1401-01-19 BC
          PGdate date;
          date.isbc = 1;
          date.year = 1401;
          date.mon  = 0;
          date.mday = 19;
          PQputf(param, "%date", &date);

   Getting a date value:
          PQgetf(result, tup_num, "%date", field_num, &date);

TIME

   PGtime is used by TIME, TIMETZ, TIMESTAMP and TIMESTAMPTZ  data  types.
   To  put  a time, you must set the hour, min, sec and usec members.  All
   other members are ignored.
          typedef struct
          {
               /* The number of hours past midnight, in the range 0 to 23. */
               int hour;

               /* The number of minutes after the hour, in the
                * range 0 to 59.
                */
               int min;

               /* The number of seconds after the minute, in the
                * range 0 to 59.
                */
               int sec;

               /* The number of microseconds after the second, in the
                * range of 0 to 999999.
                */
               int usec;

               /*
                * When non-zero, this is a TIME WITH TIME ZONE.  Otherwise,
                * it is a TIME WITHOUT TIME ZONE.
                */
               int withtz;

               /* A value of 1 indicates daylight savings time.  A value of 0
                * indicates standard time.  A value of -1 means unknown or
                * could not determine.
                */
               int isdst;

               /* Offset from UTC in seconds. This value is not always
                * available. It is set to 0 if it cannot be determined.
                */
               int gmtoff;

               /* Timezone abbreviation: such as EST, GMT, PDT, etc.
                * This value is not always available.  It is set to an empty
                * string if it cannot be determined.
                */
               char tzabbr[16];
          } PGtime;

   Putting a time value:
          // 10:41:06.002897
          PGdate time;
          time.hour   = 10;
          time.min    = 41;
          time.sec    = 6;
          time.usec   = 2897;
          PQputf(param, "%time", &time);

   Getting a time value:
          PQgetf(result, tup_num, "%time", field_num, &time);

TIMETZ

   The TIMETZ data type uses the PGtime structure, for  a  description  of
   this structure see the TIME section.  To put a timetz, you must set the
   hour, min, sec,  usec  and  gmtoff  members.   All  other  members  are
   ignored.

   Putting a timetz value:
          // 10:41:06.002897-05
          PGdate timetz;
          timetz.hour   = 10;
          timetz.min    = 41;
          timetz.sec    = 6;
          timetz.usec   = 2897;
          timetz.gmtoff = -18000;
          PQputf(param, "%timetz", &timetz);

   Getting a timetz value:
          PQgetf(result, tup_num, "%timetz", field_num, &timetz);

TIMESTAMP

   To  put a timestamp, the isbc, year, mon, mday, hour, min, sec and usec
   members must be set.  No other members are used.
          typedef struct
          {
               /* The number seconds before or after midnight UTC of
                * January 1, 1970, not counting leap seconds.
                */
               PGint8 epoch;

               /* The date part of the timestamp. */
               PGdate date;

               /* The time part of the timestamp. */
               PGtime time;
          } PGtimestamp;

   Putting a timestamp value:
          // 2000-01-19 10:41:06
          PGtimestamp ts;
          ts.date.isbc   = 0;
          ts.date.year   = 2000;
          ts.date.mon    = 0;
          ts.date.mday   = 19;
          ts.time.hour   = 10;
          ts.time.min    = 41;
          ts.time.sec    = 6;
          ts.time.usec   = 0;
          PQputf(param, "%timestamp", &ts);

   Getting a timestamp value:
          PQgetf(result, tup_num, "%timestamp", field_num, &ts);

   The timestamp type has no concept of timezone, so the value returned by
   PQgetf(3)  is exactly what the server sent; no timezone adjustments are
   attempted.  The gmtoff is always set to zero, tzabbr will be  an  empty
   string and withtz will be zero.

TIMESTAMPTZ

   To  put  a timestamptz, the isbc, year, mon, mday, hour, min, sec, usec
   and gmtoff members must be set.  No other members are used.

   Putting a timestamptz value:
          // 2000-01-19 10:41:06-05
          PGtimestamp ts;
          ts.date.isbc   = 0;
          ts.date.year   = 2000;
          ts.date.mon    = 0;
          ts.date.mday   = 19;
          ts.time.hour   = 10;
          ts.time.min    = 41;
          ts.time.sec    = 6;
          ts.time.usec   = 0;
          ts.time.gmtoff = -18000;
          PQputf(param, "%timestamptz", &ts);

   Getting a timestamptz value:
          PQgetf(result, tup_num, "%timestamptz", field_num, &ts);

   When using PQgetf(3) in binary mode, the timestamptz value is converted
   into the local machines timezone.  If the local machine's timezone can
   not be determined, the value will be in GMT (gmtoff is set to zero  and
   tzabbr is set to GMT).

   When using PQgetf(3) in text mode, the timestamptz value is returned as
   a datetime string in the servers timezone.  No adjustments are made to
   this value.  If the server is using a DateStyle that encodes the gmtoff
   "00:00:00-05", then gmtoff will be set to this value and tzabbr will be
   "GMT+/-hhmmss"  (00:00:00-05  => GMT-0500).  In this case, isdst is set
   to -1 ...  meaning  unknown.   If  the  servers  DateStyle  encodes  a
   timezone abbreviation, like PST, then tzabbr is set to this value.  The
   gmtoff and isdst members are properly set:

     DateStyle includes a timezone abbrev - "SQL, MDY"
     01/25/2007 00:00:00 EST => tzabbr=EST, gmtoff=-18000, isdst=0
     01/25/2007 01:00:00 EDT => tzabbr=EDT, gmtoff=-14400, isdst=1

INTERVAL

   To put an interval, all relevant members  of  a  PGinterval  should  be
   assigned and those not used should be set to zero.
          typedef struct
          {
               /* the number of years */
               int years;

               /* the number of months */
               int mons;

               /* the number of days */
               int days;

               /* the number of hours */
               int hours;

               /* the number of mins */
               int mins;

               /* the number of seconds */
               int secs;

               /* the number of microseconds */
               int usecs;
          } PGinterval;

   Putting an interval value:
          // "20 years 8 months 9 hours 10 mins 15 secs 123456 usecs"
          PGinterval interval;
          interval.years = 20;
          interval.mons  = 8;
          interval.days  = 0; // not used, set to 0
          interval.hours = 9;
          interval.mins  = 10;
          interval.secs  = 15;
          interval.usecs = 123456;
          PQputf(param, "%interval", &interval);

   Getting an interval value:
          PQgetf(result, tup_num, "%interval", field_num, &interval);

   NOTE:  When  using  text results with a non-ISO DateStyle, microseconds
   are truncated to a 2 digit value.  For example: "4 mins 2.11 secs"  but
   microseconds is really 111456.

POINT

   The PGpoint structure is used to put and get a point.
          typedef struct
          {
               double x; // point x value
               double y; // point y value
          } PGpoint;

   Putting a point value:
          PGpoint pt = {12.345, 6.789};
          PQputf(param, "%point", &pt);

   Getting a point value:
          PGpoint pt;
          PQgetf(result, tup_num, "%point", field_num, &pt);

LSEG

   The PGlseg structure is used to put and get a line segnment.
          typedef struct
          {
            PGpoint pts[2];
          } PGlseg;

   Putting a lseg value:
          PGlseg lseg = {{{12.345, 6.789}, {99.8, 88.9}}};
          PQputf(param, "%lseg", &lseg);

   Getting a lseg value:
          PGlseg lseg;
          PQgetf(result, tup_num, "%lseg", field_num, &lseg);

BOX

   The PGbox structure is used to put and get a box.
          typedef struct
          {
            PGpoint high;
            PGpoint low;
          } PGbox;

   Putting a box value:
          PGbox box = {{12.345, 6.789}, {22.234, 1.9998}};
          PQputf(param, "%box", &box);

   Getting a box value:
          PGbox box;
          PQgetf(result, tup_num, "%box", field_num, &box);

CIRCLE

   The PGcircle structure is used to put and get a circle.
          typedef struct
          {
            PGpoint center;
            double radius;
          } PGcircle;

   Putting a circle value:
          PGcircle circle = {{12.345, 6.789}, 2.34567};
          PQputf(param, "%circle", &circle);

   Getting a circle value:
          PGcircle circle;
          PQgetf(result, tup_num, "%circle", field_num, &circle);

PATH

   The  PGpath  structure  is  used  to put and get a path.  If the closed
   member is non-zero, the path is closed, otherwise it is open.
          typedef struct
          {
            int npts;
            int closed;
            PGpoint *pts;
          } PGpath;

   Putting a path value:
          // Put a closed path that contains 2 points
          PGpoint pts[] = {{12.345, 6.789}, {19.773, 7.882}};
          PGpath path = {2, 1, pts};
          PQputf(param, "%path", &path);

   Getting a path value:
          PGpath path;
          if(PQgetf(result, tup_num, "%path", field_num, &path))
          {
               // path.pts must be copied out if needed after clearing results
               copy_points(path.npts, path.pts, ...);

               PQclear(result);
               // path.pts is now invalid!
          }

POLYGON

   The PGpolygon structure is used to put and get a polygon.
          typedef struct
          {
            int npts;
            PGpoint *pts;
          } PGpolygon;

   Putting a polygon value:
          // Put a polygon that contains 2 points
          PGpoint pts[] = {{12.345, 6.789}, {19.773, 7.882}};
          PGpolygon polygon = {2, 1, pts};
          PQputf(param, "%polygon", &polygon);

   Getting a polygon value:
          PGpolygon polygon;
          if(PQgetf(result, tup_num, "%polygon", field_num, &polygon))
          {
               // polygon.pts must be copied out if needed after clearing results
               copy_points(polygon.npts, polygon.pts, ...);

               PQclear(result);
               // polygon.pts is now invalid
          }

INET & CIDR

   When putting an inet or cidr, all members must  be  set  excluding  the
   sa_len.
          typedef struct
          {
               /* The address mask, 32 for a single IP. */
               int mask;

               /* When non-zero, the PGinet structure represents a cidr
                * otherwise an inet.
                */
               int is_cidr;

               /* the length in bytes of the sa_buf member. */
               int sa_len;

               /* the socket address buffer, contains the data.  This can
                * be casted to a sockaddr, sockaddr_in, sockaddr_in6 or a
                * sockaddr_storage structure. This buffer is 128 bytes so
                * that it is large enough for a sockaddr_storage structure.
                */
               char sa_buf[128];
          } PGinet;

   Putting an inet or cidr:
          socklen_t len;
          PGinet inet;

          cli_fd = accept(srv_fd, (struct sockaddr *)inet.sa_buf, &len);
          if(cli_fd != -1)
          {
               inet.is_cidr = 0;
               inet.mask = 32;
               PQputf(param, "%inet", &inet);
          }

   Getting an inet or cidr:
          PGinet inet;
          unsigned short port;

          /* gets an inet from field 2 and an int2 from field 6 */
          if(PQgetf(result, tup_num, "%inet %int2", 2, &inet, 6, &port))
          {
               char ip[80];
               struct sockaddr *sa = (struct sockaddr *)inet.sa_buf;

               // converting a PGinet to an IPv4 or IPv6 address string
               getnameinfo(sa, inet.sa_len, ip, sizeof(ip),
                    NULL, 0, NI_NUMERICHOST);

               // The inet data type does not store a port.
               if(sa->sa_family == AF_INET)
                    ((struct sockaddr_in *)sa)->sin_port = htons(port);
               else
                    ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);

               printf("Connecting to %s:%d\n", ip, port);
               connect(sock_fd, sa, inet.sa_len);
          }

MACADDR

   The PGmacaddr structure is used to put and get a macaddr.
          typedef struct
          {
               int a;
               int b;
               int c;
               int d;
               int e;
               int f;
          } PGmacaddr;

   Putting a macaddr value:
          PGmacaddr macaddr = {0, 1, 2, 3, 4, 5};
          PQputf(param, "%macaddr", &macaddr);

   Getting a macaddr value:
          PGmacaddr macaddr;
          PQgetf(result, tup_num, "%macaddr", field_num, &macaddr);

MONEY

   The  money  type  is  put/get as a PGmoney (64-bit integer).  It can be
   converted to dollar and cents format by dividing by 100: double money =
   (double)money64  / 100.0;.  Pre 8.3 servers are limited to 32-bit money
   values.

   Putting a money value:
          PGmoney money = 600000000054LL; // 6 billion dollars and 54 cents
          PQputf(param, "%money", money);

   Getting a money value:
          PQgetf(result, tup_num, "%money", field_num, &money);

BOOL

   The bool type is put/get as a PGbool.  To put true or false, use  1  or
   0.

   Putting a bool value:
          PGbool b = 1; // put true
          PQputf(param, "%bool", b);

   Getting a bool value:
          PGbool b;
          PQgetf(result, tup_num, "%bool", field_num, &b);

UUID

   The  uuid  type is put/get as a sequence of 16 bytes.  To put a uuid as
   text, use "%str".  NOTE: this type is not available on pre 8.3 servers.

   Putting a uuid value:
          PGuuid uuid = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
          PQputf(param, "%uuid", uuid);

   Getting a uuid value:
          PGuuid uuid;
          PQgetf(result, tup_num, "%uuid", field_num, &uuid);

   WARNING: The data provided on a put call is expected to be at least  16
   bytes.

OID

   Putting an oid value:
          Oid oid = 2318;
          PQputf(param, "%oid", oid);

   Getting an oid value:
          Oid oid;
          PQgetf(result, tup_num, "%oid", field_num, &oid);

EXAMPLES

   None.

AUTHOR

   A  contribution  of  eSilo, LLC. for the PostgreSQL Database Management
   System.  Written by Andrew Chernow and Merlin Moncure.

REPORTING BUGS

   Report bugs to <[email protected]>.

COPYRIGHT

   Copyright (c) 2011 eSilo, LLC. All rights reserved.
   This is free software; see the source for copying conditions.  There is
   NO  warranty; not even for MERCHANTABILITY or  FITNESS FOR A PARTICULAR
   PURPOSE.

SEE ALSO

   PQgetf(3), PQputf(3).



Opportunity


Personal Opportunity - Free software gives you access to billions of dollars of software at no cost. Use this software for your business, personal use or to develop a profitable skill. Access to source code provides access to a level of capabilities/information that companies protect though copyrights. Open source is a core component of the Internet and it is available to you. Leverage the billions of dollars in resources and capabilities to build a career, establish a business or change the world. The potential is endless for those who understand the opportunity.

Business Opportunity - Goldman Sachs, IBM and countless large corporations are leveraging open source to reduce costs, develop products and increase their bottom lines. Learn what these companies know about open source and how open source can give you the advantage.


Free Software


Free Software provides computer programs and capabilities at no cost but more importantly, it provides the freedom to run, edit, contribute to, and share the software. The importance of free software is a matter of access, not price. Software at no cost is a benefit but ownership rights to the software and source code is far more significant.

Free Office Software - The Libre Office suite provides top desktop productivity tools for free. This includes, a word processor, spreadsheet, presentation engine, drawing and flowcharting, database and math applications. Libre Office is available for Linux or Windows.


Free Books


The Free Books Library is a collection of thousands of the most popular public domain books in an online readable format. The collection includes great classical literature and more recent works where the U.S. copyright has expired. These books are yours to read and use without restrictions.

Source Code - Want to change a program or know how it works? Open Source provides the source code for its programs so that anyone can use, modify or learn how to write those programs themselves. Visit the GNU source code repositories to download the source.


Education


Study at Harvard, Stanford or MIT - Open edX provides free online courses from Harvard, MIT, Columbia, UC Berkeley and other top Universities. Hundreds of courses for almost all major subjects and course levels. Open edx also offers some paid courses and selected certifications.

Linux Manual Pages - A man or manual page is a form of software documentation found on Linux/Unix operating systems. Topics covered include computer programs (including library and system calls), formal standards and conventions, and even abstract concepts.