logo
Free, unlimited AI code reviews that run on commit
git-lrc git-lrc GitHub Install Now We'd appreciate a star git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt

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

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)´.
              typedefstruct{/*Thenumberofarraydimensions.Specifingzeroforthis*valueonputshasspecialmeaning.Whenzero,thisvalue*issettoone,dims[0]issettothenumberofitemsin*the´param´memberandlbound[0]issettoone.*/intndims;/*Anarrayoflowerboundsforeachdimension.*/intlbound[MAXDIM];/*Anarrayofdimensionsforeachdimension.*/intdims[MAXDIM];/*Whenputtingarrayelements,thisPGparamisused.Each*itemputisonearrayelement.BecausethePQputf(3)*interfaceallowsputtingmorethanoneitematatime,you*canputmultiplearrayelements.*/PGparam*param;/*Whengettinganarray,thisisthePGresultobjectthat*containsthearrayelements.Eachelementisonetuple,*regardlessofthearraydimensions.Ifthearrayhas100*elementsacross3dimensions,PQntuples(arr.res)willreturn*100.Theonlyvalidfield,fornon-compositearrays,is*fieldzero.*/PGresult*res;}PGarray;Whenallelementshavebeenput,thePGarraystructuremustbeputusingthe"[]"arrayspeciferflagintoaPGparamstructure.PQputf(3)isusedtobuildthearrayelementsandtoputtheresultingPGarray.Puttinganarrayvalue:PGint4i;PGarrayarr;PGparam*param;/*Onedimensionalarraysdonotrequiresettingdimensioninfo.For*convience,youcanzerothestructureorsetndimstozero.*/arr.ndims=0;/*createtheparamobjectthatwillcontaintheelements*/arr.param=PQparamCreate(conn);/*UsePQputf(3)toputthearrayelements*/for(i=0;i<1000;i++)PQputf(arr.param,"%int4",i);/*ThePGarraymustbeputintoaPGparamstruture.Sofar,only*thearrayelementshavebeenput.´param´cancontinuetobe*usedtopackmoreparameters.Thearrayisnowasingleparameter*within´param´.*/param=PQparamCreate(conn);PQputf(param,"%int[]",&arr);/*nolongerneeded*/PQparamClear(arr.param);Togetanarray,PQgetf(3)isusedinconjunctionwiththePGarraystructure.TheresultobjectcontainedwiththePGarrayispopulatedwiththearrayelements.Thedimensioninfoisassignedaswell.Eacharrayelementisitsowntuplethatonlycontainsasinglefieldfornoncompositearrays.Gettinganarrayvalue:inti;PGint4val;intntups;PGarrayarr;PGresult*result=...;PQgetf(result,0,"%int[]",0,&arr);/*notneededanymore*/PQclear(result);/*eachtupleisanarrayelement*/ntups=PQntuples(arr.res);for(i=0;i<ntups;i++){/*Alwaysfield0*/PQgetf(arr.res,i,"%int4",0,&val);printf("[%03d]%d\n",i,val);}PQclear(arr.res);Theresultobjectisnotorganizedbasedonthedimensioninfo.Indexesarealwayszero-based.Ifthedimensioninfoismeaningfultoyourapplication,indextranslationmustbedoneusingthendims,dimsandlboundmembersofthePGarraystructure.Youcannotreferenceanarrayelementbyfieldname.Theonlylogicalnameforanarrayelementwouldbethestringversionofitsindex..."0","1",etc..Theindexvalueofanon-compositearrayisitstuplenumber,thefieldnumberisalwayszero.Thismeans"#int"isnotlegalfornon-compositearrays.Youmustuse"%int"andreferencefield0.

Author

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

Bool

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

       Putting a bool value:
              PGboolb=1;//puttruePQputf(param,"%bool",b);

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

Box

       The PGbox structure is used to put and get a box.
              typedefstruct{PGpointhigh;PGpointlow;}PGbox;

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

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

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.
              typedefstruct{intlen;/*numberofbytes*/char*data;/*pointertothebyteadata*/}PGbytea;/*Putabytealettinglibpqtypesmakeacopy;*/PGbyteabytea={4,{0,1,2,3}};PQputf(param,"%bytea",&bytea);/*Putabyteanotlettinglibpqtypesmakeacopy,storesa*directpointertoPGbytea.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.
              /*Getabyteavalue(exposedasbinary,no*escaping/unescapingneeded)*/PGbyteabytea;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.

Char

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

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

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

Circle

       The PGcircle structure is used to put and get a circle.
              typedefstruct{PGpointcenter;doubleradius;}PGcircle;

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

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

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.

              typedefstruct{/*Whennon-zero,thedateisintheBCERA.*/intisbc;/**TheBCorADyear,whichisNOTadjustedby1900like*thePOSIXstructtm.Yearsarealwayspositivevalues,*evenBCyears.TodistinguishbetweenBCandADyears,*usetheisbcflag:(year0notused)*Ex.-1210isrepresentedas:isbc=1,year=1209*/intyear;/*ThenumberofmonthssinceJanuary,intherange0to11.*/intmon;/*Thedayofthemonth,intherange1to31.*/intmday;/*TheJuliandayintheGregoriancalendar.*/intjday;/*ThenumberofdayssinceJanuary1,intherange0to365.*/intyday;/*ThenumberofdayssinceSunday,intherange0to6.*/intwday;}PGdate;

       Putting a date value:
              //´1401-01-19BC´PGdatedate;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);

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.

   SpecifierStringsSpecifierMark
       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.

       TypeSpecifier
       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.

       SpecifierFlag
       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.

Examples

       None.

Inet & Cidr

       When putting an inet or cidr, all members must be set excluding the sa_len.
              typedefstruct{/*Theaddressmask,32forasingleIP.*/intmask;/*Whennon-zero,thePGinetstructurerepresentsacidr*otherwiseaninet.*/intis_cidr;/*thelengthinbytesofthesa_bufmember.*/intsa_len;/*thesocketaddressbuffer,containsthedata.Thiscan*becastedtoasockaddr,sockaddr_in,sockaddr_in6ora*sockaddr_storagestructure.Thisbufferis128bytesso*thatitislargeenoughforasockaddr_storagestructure.*/charsa_buf[128];}PGinet;

       Putting an inet or cidr:
              socklen_tlen;PGinetinet;cli_fd=accept(srv_fd,(structsockaddr*)inet.sa_buf,&len);if(cli_fd!=-1){inet.is_cidr=0;inet.mask=32;PQputf(param,"%inet",&inet);}

       Getting an inet or cidr:
              PGinetinet;unsignedshortport;/*getsaninetfromfield2andanint2fromfield6*/if(PQgetf(result,tup_num,"%inet%int2",2,&inet,6,&port)){charip[80];structsockaddr*sa=(structsockaddr*)inet.sa_buf;//convertingaPGinettoanIPv4orIPv6addressstringgetnameinfo(sa,inet.sa_len,ip,sizeof(ip),NULL,0,NI_NUMERICHOST);//Theinetdatatypedoesnotstoreaport.if(sa->sa_family==AF_INET)((structsockaddr_in*)sa)->sin_port=htons(port);else((structsockaddr_in6*)sa)->sin6_port=htons(port);printf("Connectingto%s:%d\n",ip,port);connect(sock_fd,sa,inet.sa_len);}

Interval

       To put an interval, all relevant members of a PGinterval should be assigned and those not used should  be
       set to zero.
              typedefstruct{/*thenumberofyears*/intyears;/*thenumberofmonths*/intmons;/*thenumberofdays*/intdays;/*thenumberofhours*/inthours;/*thenumberofmins*/intmins;/*thenumberofseconds*/intsecs;/*thenumberofmicroseconds*/intusecs;}PGinterval;

       Putting an interval value:
              //"20years8months9hours10mins15secs123456usecs"PGintervalinterval;interval.years=20;interval.mons=8;interval.days=0;//notused,setto0interval.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.

Lseg

       The PGlseg structure is used to put and get a line segnment.
              typedefstruct{PGpointpts[2];}PGlseg;

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

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

Macaddr

       The PGmacaddr structure is used to put and get a macaddr.
              typedefstruct{inta;intb;intc;intd;inte;intf;}PGmacaddr;

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

       Getting a macaddr value:
              PGmacaddrmacaddr;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:
              PGmoneymoney=600000000054LL;//6billiondollarsand54centsPQputf(param,"%money",money);

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

Name

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

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.
              //Readanint2fromfield0,int4fromfield1,int8from//field2,float4fromfield3andafloat8fromfield4PGint2i2;PGint4i4;PGint8i8;PGfloat4f4;PGfloat8f8;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.
              PGnumericnumstr;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).

Oid

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

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

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.
              typedefstruct{intnpts;intclosed;PGpoint*pts;}PGpath;

       Putting a path value:
              //Putaclosedpaththatcontains2pointsPGpointpts[]={{12.345,6.789},{19.773,7.882}};PGpathpath={2,1,pts};PQputf(param,"%path",&path);

       Getting a path value:
              PGpathpath;if(PQgetf(result,tup_num,"%path",field_num,&path)){//path.ptsmustbecopiedoutifneededafterclearingresultscopy_points(path.npts,path.pts,...);PQclear(result);//path.ptsisnowinvalid!}

Point

       The PGpoint structure is used to put and get a point.
              typedefstruct{doublex;//pointxvaluedoubley;//pointyvalue}PGpoint;

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

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

Polygon

       The PGpolygon structure is used to put and get a polygon.
              typedefstruct{intnpts;PGpoint*pts;}PGpolygon;

       Putting a polygon value:
              //Putapolygonthatcontains2pointsPGpointpts[]={{12.345,6.789},{19.773,7.882}};PGpolygonpolygon={2,1,pts};PQputf(param,"%polygon",&polygon);

       Getting a polygon value:
              PGpolygonpolygon;if(PQgetf(result,tup_num,"%polygon",field_num,&polygon)){//polygon.ptsmustbecopiedoutifneededafterclearingresultscopy_points(polygon.npts,polygon.pts,...);PQclear(result);//polygon.ptsisnowinvalid}

Reporting Bugs

       Report bugs to <libpqtypes@esilo.com>.

See Also

PQgetf(3), PQputf(3).

libpqtypes                                            2011                                          pqt-specs(3)

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.
              typedefstruct{/*Thenumberofhourspastmidnight,intherange0to23.*/inthour;/*Thenumberofminutesafterthehour,inthe*range0to59.*/intmin;/*Thenumberofsecondsaftertheminute,inthe*range0to59.*/intsec;/*Thenumberofmicrosecondsafterthesecond,inthe*rangeof0to999999.*/intusec;/**Whennon-zero,thisisaTIMEWITHTIMEZONE.Otherwise,*itisaTIMEWITHOUTTIMEZONE.*/intwithtz;/*Avalueof1indicatesdaylightsavingstime.Avalueof0*indicatesstandardtime.Avalueof-1meansunknownor*couldnotdetermine.*/intisdst;/*OffsetfromUTCinseconds.Thisvalueisnotalways*available.Itissetto0ifitcannotbedetermined.*/intgmtoff;/*Timezoneabbreviation:suchasEST,GMT,PDT,etc.*Thisvalueisnotalwaysavailable.Itissettoanempty*stringifitcannotbedetermined.*/chartzabbr[16];}PGtime;

       Putting a time value:
              //´10:41:06.002897´PGdatetime;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);

Timestamp

       To put a timestamp, the isbc, year, mon, mday, hour, min, sec and usec members must  be  set.   No  other
       members are used.
              typedefstruct{/*ThenumbersecondsbeforeoraftermidnightUTCof*January1,1970,notcountingleapseconds.*/PGint8epoch;/*Thedatepartofthetimestamp.*/PGdatedate;/*Thetimepartofthetimestamp.*/PGtimetime;}PGtimestamp;

       Putting a timestamp value:
              //´2000-01-1910:41:06´PGtimestampts;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-1910:41:06-05´PGtimestampts;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 machine´s
       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 server´s
       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  server´s
       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

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´PGdatetimetz;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);

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:
              PGuuiduuid={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};PQputf(param,"%uuid",uuid);

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

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

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)
              /*Putastringsolibpqtypesmakesacopy.Inthiscase,*4copieswouldbemadeofthesamestring.*/PGtextstr="foobar";PQputf(param,"%bpchar%varchar%name%text",str,str,str,str);/*Putastringsolibpqtypesdoesn´tmakeacopy,*keepsadirectpointer.Moreefficientthanabove,*especiallyifthesearelargestrings.*/PQputf(param,"%bpchar*%varchar*%name*%text*",str,str,str,str);

       WARNING: Be careful about variable scope when using the "*" specifier flag:
              /*when´func´returns,thestrpointerbecomesinvalid!*Thebelowshouldbeusing"%text"...w/othe*flag.*/intfunc(PGparam*param){PGcharstr[16];strcpy(str,"foobar");returnPQputf(param,"%text*",str);//BADIDEA!}

       To  PQgetf(3)  a  string,  you  supply a pointer to a PGtext.  Unlike putting string values, getting them
       doesn´t make use of the "*" specifier flag (silently ignored).
              /*Getastringvalue*/PGvarcharstr;PQgetf(result,tup_num,"%varchar",field_num,&str);/*identicalto*/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*/#defineTYPESPEC_USERINFO"%int4%text*%text*"PGint4uid=0;PGtextuser="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.

See Also