1 /*
2 
3   Copyright (c) 2000-2021 Greg Sabino Mullane and others: see the Changes file
4   Portions Copyright (c) 1997-2000 Edmund Mergl
5   Portions Copyright (c) 1994-1997 Tim Bunce
6 
7   You may distribute under the terms of either the GNU General Public
8   License or the Artistic License, as specified in the Perl README file.
9 
10 */
11 
12 #define NEED_newSVpvn_flags
13 
14 #include "Pg.h"
15 
16 #ifdef _MSC_VER
17 #define strncasecmp(a,b,c) _strnicmp((a),(b),(c))
18 #endif
19 
20 MODULE = DBD::Pg    PACKAGE = DBD::Pg
21 
22 
23 I32
24 constant(name=Nullch)
25     char *name
26     PROTOTYPE:
27     ALIAS:
28     PG_ACLITEM                        = 1033
29     PG_ACLITEMARRAY                   = 1034
30     PG_ANY                            = 2276
31     PG_ANYARRAY                       = 2277
32     PG_ANYCOMPATIBLE                  = 5077
33     PG_ANYCOMPATIBLEARRAY             = 5078
34     PG_ANYCOMPATIBLEMULTIRANGE        = 4538
35     PG_ANYCOMPATIBLENONARRAY          = 5079
36     PG_ANYCOMPATIBLERANGE             = 5080
37     PG_ANYELEMENT                     = 2283
38     PG_ANYENUM                        = 3500
39     PG_ANYMULTIRANGE                  = 4537
40     PG_ANYNONARRAY                    = 2776
41     PG_ANYRANGE                       = 3831
42     PG_BIT                            = 1560
43     PG_BITARRAY                       = 1561
44     PG_BOOL                           = 16
45     PG_BOOLARRAY                      = 1000
46     PG_BOX                            = 603
47     PG_BOXARRAY                       = 1020
48     PG_BPCHAR                         = 1042
49     PG_BPCHARARRAY                    = 1014
50     PG_BYTEA                          = 17
51     PG_BYTEAARRAY                     = 1001
52     PG_CHAR                           = 18
53     PG_CHARARRAY                      = 1002
54     PG_CID                            = 29
55     PG_CIDARRAY                       = 1012
56     PG_CIDR                           = 650
57     PG_CIDRARRAY                      = 651
58     PG_CIRCLE                         = 718
59     PG_CIRCLEARRAY                    = 719
60     PG_CSTRING                        = 2275
61     PG_CSTRINGARRAY                   = 1263
62     PG_DATE                           = 1082
63     PG_DATEARRAY                      = 1182
64     PG_DATEMULTIRANGE                 = 4535
65     PG_DATEMULTIRANGEARRAY            = 6155
66     PG_DATERANGE                      = 3912
67     PG_DATERANGEARRAY                 = 3913
68     PG_EVENT_TRIGGER                  = 3838
69     PG_FDW_HANDLER                    = 3115
70     PG_FLOAT4                         = 700
71     PG_FLOAT4ARRAY                    = 1021
72     PG_FLOAT8                         = 701
73     PG_FLOAT8ARRAY                    = 1022
74     PG_GTSVECTOR                      = 3642
75     PG_GTSVECTORARRAY                 = 3644
76     PG_INDEX_AM_HANDLER               = 325
77     PG_INET                           = 869
78     PG_INETARRAY                      = 1041
79     PG_INT2                           = 21
80     PG_INT2ARRAY                      = 1005
81     PG_INT2VECTOR                     = 22
82     PG_INT2VECTORARRAY                = 1006
83     PG_INT4                           = 23
84     PG_INT4ARRAY                      = 1007
85     PG_INT4MULTIRANGE                 = 4451
86     PG_INT4MULTIRANGEARRAY            = 6150
87     PG_INT4RANGE                      = 3904
88     PG_INT4RANGEARRAY                 = 3905
89     PG_INT8                           = 20
90     PG_INT8ARRAY                      = 1016
91     PG_INT8MULTIRANGE                 = 4536
92     PG_INT8MULTIRANGEARRAY            = 6157
93     PG_INT8RANGE                      = 3926
94     PG_INT8RANGEARRAY                 = 3927
95     PG_INTERNAL                       = 2281
96     PG_INTERVAL                       = 1186
97     PG_INTERVALARRAY                  = 1187
98     PG_JSON                           = 114
99     PG_JSONARRAY                      = 199
100     PG_JSONB                          = 3802
101     PG_JSONBARRAY                     = 3807
102     PG_JSONPATH                       = 4072
103     PG_JSONPATHARRAY                  = 4073
104     PG_LANGUAGE_HANDLER               = 2280
105     PG_LINE                           = 628
106     PG_LINEARRAY                      = 629
107     PG_LSEG                           = 601
108     PG_LSEGARRAY                      = 1018
109     PG_MACADDR                        = 829
110     PG_MACADDR8                       = 774
111     PG_MACADDR8ARRAY                  = 775
112     PG_MACADDRARRAY                   = 1040
113     PG_MONEY                          = 790
114     PG_MONEYARRAY                     = 791
115     PG_NAME                           = 19
116     PG_NAMEARRAY                      = 1003
117     PG_NUMERIC                        = 1700
118     PG_NUMERICARRAY                   = 1231
119     PG_NUMMULTIRANGE                  = 4532
120     PG_NUMMULTIRANGEARRAY             = 6151
121     PG_NUMRANGE                       = 3906
122     PG_NUMRANGEARRAY                  = 3907
123     PG_OID                            = 26
124     PG_OIDARRAY                       = 1028
125     PG_OIDVECTOR                      = 30
126     PG_OIDVECTORARRAY                 = 1013
127     PG_PATH                           = 602
128     PG_PATHARRAY                      = 1019
129     PG_PG_ATTRIBUTE                   = 75
130     PG_PG_ATTRIBUTEARRAY              = 270
131     PG_PG_BRIN_BLOOM_SUMMARY          = 4600
132     PG_PG_BRIN_MINMAX_MULTI_SUMMARY   = 4601
133     PG_PG_CLASS                       = 83
134     PG_PG_CLASSARRAY                  = 273
135     PG_PG_DDL_COMMAND                 = 32
136     PG_PG_DEPENDENCIES                = 3402
137     PG_PG_LSN                         = 3220
138     PG_PG_LSNARRAY                    = 3221
139     PG_PG_MCV_LIST                    = 5017
140     PG_PG_NDISTINCT                   = 3361
141     PG_PG_NODE_TREE                   = 194
142     PG_PG_PROC                        = 81
143     PG_PG_PROCARRAY                   = 272
144     PG_PG_SNAPSHOT                    = 5038
145     PG_PG_SNAPSHOTARRAY               = 5039
146     PG_PG_TYPE                        = 71
147     PG_PG_TYPEARRAY                   = 210
148     PG_POINT                          = 600
149     PG_POINTARRAY                     = 1017
150     PG_POLYGON                        = 604
151     PG_POLYGONARRAY                   = 1027
152     PG_RECORD                         = 2249
153     PG_RECORDARRAY                    = 2287
154     PG_REFCURSOR                      = 1790
155     PG_REFCURSORARRAY                 = 2201
156     PG_REGCLASS                       = 2205
157     PG_REGCLASSARRAY                  = 2210
158     PG_REGCOLLATION                   = 4191
159     PG_REGCOLLATIONARRAY              = 4192
160     PG_REGCONFIG                      = 3734
161     PG_REGCONFIGARRAY                 = 3735
162     PG_REGDICTIONARY                  = 3769
163     PG_REGDICTIONARYARRAY             = 3770
164     PG_REGNAMESPACE                   = 4089
165     PG_REGNAMESPACEARRAY              = 4090
166     PG_REGOPER                        = 2203
167     PG_REGOPERARRAY                   = 2208
168     PG_REGOPERATOR                    = 2204
169     PG_REGOPERATORARRAY               = 2209
170     PG_REGPROC                        = 24
171     PG_REGPROCARRAY                   = 1008
172     PG_REGPROCEDURE                   = 2202
173     PG_REGPROCEDUREARRAY              = 2207
174     PG_REGROLE                        = 4096
175     PG_REGROLEARRAY                   = 4097
176     PG_REGTYPE                        = 2206
177     PG_REGTYPEARRAY                   = 2211
178     PG_TABLE_AM_HANDLER               = 269
179     PG_TEXT                           = 25
180     PG_TEXTARRAY                      = 1009
181     PG_TID                            = 27
182     PG_TIDARRAY                       = 1010
183     PG_TIME                           = 1083
184     PG_TIMEARRAY                      = 1183
185     PG_TIMESTAMP                      = 1114
186     PG_TIMESTAMPARRAY                 = 1115
187     PG_TIMESTAMPTZ                    = 1184
188     PG_TIMESTAMPTZARRAY               = 1185
189     PG_TIMETZ                         = 1266
190     PG_TIMETZARRAY                    = 1270
191     PG_TRIGGER                        = 2279
192     PG_TSMULTIRANGE                   = 4533
193     PG_TSMULTIRANGEARRAY              = 6152
194     PG_TSM_HANDLER                    = 3310
195     PG_TSQUERY                        = 3615
196     PG_TSQUERYARRAY                   = 3645
197     PG_TSRANGE                        = 3908
198     PG_TSRANGEARRAY                   = 3909
199     PG_TSTZMULTIRANGE                 = 4534
200     PG_TSTZMULTIRANGEARRAY            = 6153
201     PG_TSTZRANGE                      = 3910
202     PG_TSTZRANGEARRAY                 = 3911
203     PG_TSVECTOR                       = 3614
204     PG_TSVECTORARRAY                  = 3643
205     PG_TXID_SNAPSHOT                  = 2970
206     PG_TXID_SNAPSHOTARRAY             = 2949
207     PG_UNKNOWN                        = 705
208     PG_UUID                           = 2950
209     PG_UUIDARRAY                      = 2951
210     PG_VARBIT                         = 1562
211     PG_VARBITARRAY                    = 1563
212     PG_VARCHAR                        = 1043
213     PG_VARCHARARRAY                   = 1015
214     PG_VOID                           = 2278
215     PG_XID                            = 28
216     PG_XID8                           = 5069
217     PG_XID8ARRAY                      = 271
218     PG_XIDARRAY                       = 1011
219     PG_XML                            = 142
220     PG_XMLARRAY                       = 143
221 
222     PG_ASYNC                          = 1
223     PG_OLDQUERY_CANCEL                = 2
224     PG_OLDQUERY_WAIT                  = 4
225 
226     CODE:
227         if (0==ix) {
228             if (!name) {
229                 name = GvNAME(CvGV(cv));
230             }
231             croak("Unknown DBD::Pg constant '%s'", name);
232         }
233         else {
234             RETVAL = ix;
235         }
236     OUTPUT:
237         RETVAL
238 
239 INCLUDE: Pg.xsi
240 
241 
242 # ------------------------------------------------------------
243 # db functions
244 # ------------------------------------------------------------
245 MODULE=DBD::Pg    PACKAGE = DBD::Pg::db
246 
247 
248 SV*
249 quote(dbh, to_quote_sv, type_sv=Nullsv)
250     SV* dbh
251     SV* to_quote_sv
252     SV* type_sv
253 
254     CODE:
255     {
256         bool utf8;
257         D_imp_dbh(dbh);
258 
259         SvGETMAGIC(to_quote_sv);
260 
261         /* Reject references other than overloaded objects (presumed
262           stringifiable) and arrays (will make a PostgreSQL array). */
263         if (SvROK(to_quote_sv) && !SvAMAGIC(to_quote_sv)) {
264             if (SvTYPE(SvRV(to_quote_sv)) != SVt_PVAV)
265                 croak("Cannot quote a reference");
266             to_quote_sv = pg_stringify_array(to_quote_sv, ",", imp_dbh->pg_server_version, imp_dbh->client_encoding_utf8);
267         }
268 
269         /* Null is always returned as "NULL", so we can ignore any type given */
270         if (!SvOK(to_quote_sv)) {
271             RETVAL = newSVpvn("NULL", 4);
272         }
273         else {
274             sql_type_info_t *type_info;
275             char *quoted;
276             const char *to_quote;
277             STRLEN retlen=0;
278             STRLEN len=0;
279 
280             /* If no valid type is given, we default to unknown */
281             if (!type_sv || !SvOK(type_sv)) {
282                 type_info = pg_type_data(PG_UNKNOWN);
283             }
284             else {
285                 if SvMAGICAL(type_sv)
286                     (void)mg_get(type_sv);
287                 if (SvNIOK(type_sv)) {
288                     type_info = sql_type_data(SvIV(type_sv));
289                 }
290                 else {
291                     SV **svp;
292                     /* Currently the type argument must be a hashref, so throw an exception if not */
293                     if (!SvROK(type_sv) || SvTYPE(SvRV(type_sv)) != SVt_PVHV)
294                         croak("Second argument to quote must be a hashref");
295                     if ((svp = hv_fetch((HV*)SvRV(type_sv),"pg_type", 7, 0)) != NULL) {
296                         type_info = pg_type_data(SvIV(*svp));
297                     }
298                     else if ((svp = hv_fetch((HV*)SvRV(type_sv),"type", 4, 0)) != NULL) {
299                         type_info = sql_type_data(SvIV(*svp));
300                     }
301                     else {
302                         type_info = NULL;
303                     }
304                 }
305                 if (!type_info) {
306                     if (NULL == type_info)
307                         warn("No type given, defaulting to UNKNOWN");
308                     else
309                         warn("Unknown type %" IVdf ", defaulting to UNKNOWN", SvIV(type_sv));
310                     type_info = pg_type_data(PG_UNKNOWN);
311                 }
312             }
313 
314             /* At this point, type_info points to a valid struct, one way or another */
315             utf8 = imp_dbh->client_encoding_utf8
316                 && PG_BYTEA != type_info->type_id
317                 && SQL_BLOB != type_info->type_id
318                 && SQL_BINARY != type_info->type_id
319                 && SQL_VARBINARY != type_info->type_id
320                 && SQL_LONGVARBINARY != type_info->type_id;
321 
322             if (SvMAGICAL(to_quote_sv))
323                 (void)mg_get(to_quote_sv);
324 
325             /* avoid up- or down-grading the argument */
326             to_quote_sv = pg_rightgraded_sv(aTHX_ to_quote_sv, utf8);
327 
328             to_quote = SvPV(to_quote_sv, len);
329             /* Need good debugging here */
330             quoted = type_info->quote(aTHX_ to_quote, len, &retlen, imp_dbh->pg_server_version >= 80100 ? 1 : 0);
331             RETVAL = newSVpvn_utf8(quoted, retlen, utf8);
332             Safefree (quoted);
333         }
334     }
335     OUTPUT:
336         RETVAL
337 
338 
339 # ------------------------------------------------------------
340 # database level interface PG specific
341 # ------------------------------------------------------------
342 MODULE = DBD::Pg    PACKAGE = DBD::Pg::db
343 
344 
345 void state(dbh)
346     SV *dbh
347     CODE:
348     D_imp_dbh(dbh);
349     ST(0) = strEQ(imp_dbh->sqlstate,"00000")
350           ? &PL_sv_no
351           : sv_2mortal(newSVpv(imp_dbh->sqlstate, 5));
352 
353 
354 void do(dbh, statement_sv, attr=Nullsv, ...)
355     SV * dbh
356     SV * statement_sv
357     SV * attr
358     PROTOTYPE: $$;$@
359     CODE:
360     {
361         long retval;
362         int asyncflag = 0;
363         char *statement;
364         D_imp_dbh(dbh);
365 
366         /* Always reset the last stored sth */
367         imp_dbh->do_tmp_sth = NULL;
368 
369         statement_sv = pg_rightgraded_sv(aTHX_ statement_sv, imp_dbh->pg_utf8_flag);
370         statement = SvPV_nolen(statement_sv);
371 
372         if (statement[0] == '\0') { /* Corner case */
373             XST_mUNDEF(0);
374             return;
375         }
376 
377         if (attr && SvROK(attr) && SvTYPE(SvRV(attr)) == SVt_PVHV) {
378             SV **svp;
379             if ((svp = hv_fetch((HV*)SvRV(attr),"pg_async", 8, 0)) != NULL) {
380                asyncflag = (int)SvIV(*svp);
381             }
382         }
383         if (items < 4) { /* No bind arguments */
384             /* Quick run via PQexec */
385             retval = pg_quickexec(dbh, statement, asyncflag);
386         }
387         else { /* We've got bind arguments, so we do the whole prepare/execute route */
388             imp_sth_t *imp_sth;
389             SV * const sth = dbixst_bounce_method("prepare", 3);
390             if (!SvROK(sth))
391                 XSRETURN_UNDEF;
392             imp_sth = (imp_sth_t*)(DBIh_COM(sth));
393             if (!dbdxst_bind_params(sth, imp_sth, items-2, ax+2))
394                 XSRETURN_UNDEF;
395             imp_sth->async_flag = asyncflag;
396             imp_dbh->do_tmp_sth = imp_sth;
397             retval = dbd_st_execute(sth, imp_sth);
398         }
399 
400         if (retval == 0)
401             XST_mPV(0, "0E0");
402         else if (retval < -1)
403             XST_mUNDEF(0);
404         else
405             XST_mIV(0, retval);
406 }
407 
408 
409 void
410 _ping(dbh)
411     SV * dbh
412     CODE:
413         ST(0) = sv_2mortal(newSViv(dbd_db_ping(dbh)));
414 
415 
416 void
417 getfd(dbh)
418     SV * dbh
419     CODE:
420         int ret;
421         D_imp_dbh(dbh);
422         ret = pg_db_getfd(imp_dbh);
423         ST(0) = sv_2mortal( newSViv( ret ) );
424 
425 
426 void
427 pg_endcopy(dbh)
428     SV * dbh
429     CODE:
430         ST(0) = (pg_db_endcopy(dbh)!=0) ? &PL_sv_no : &PL_sv_yes;
431 
432 
433 void
434 pg_error_field(dbh, fieldname)
435     SV * dbh
436     char * fieldname;
437     CODE:
438         ST(0) = pg_db_error_field(dbh, fieldname);
439 
440 
441 void
442 pg_notifies(dbh)
443     SV * dbh
444     CODE:
445         D_imp_dbh(dbh);
446         ST(0) = pg_db_pg_notifies(dbh, imp_dbh);
447 
448 
449 void
450 pg_savepoint(dbh,name)
451     SV * dbh
452     char * name
453     CODE:
454         D_imp_dbh(dbh);
455         if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh))
456             warn("savepoint ineffective with AutoCommit enabled");
457         ST(0) = (pg_db_savepoint(dbh, imp_dbh, name)!=0) ? &PL_sv_yes : &PL_sv_no;
458 
459 
460 void
461 pg_rollback_to(dbh,name)
462     SV * dbh
463     char * name
464     CODE:
465         D_imp_dbh(dbh);
466         if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh))
467             warn("rollback_to ineffective with AutoCommit enabled");
468         ST(0) = (pg_db_rollback_to(dbh, imp_dbh, name)!=0) ? &PL_sv_yes : &PL_sv_no;
469 
470 
471 void
472 pg_release(dbh,name)
473     SV * dbh
474     char * name
475     CODE:
476         D_imp_dbh(dbh);
477         if (DBIc_has(imp_dbh,DBIcf_AutoCommit) && DBIc_WARN(imp_dbh))
478             warn("release ineffective with AutoCommit enabled");
479         ST(0) = (pg_db_release(dbh, imp_dbh, name)!=0) ? &PL_sv_yes : &PL_sv_no;
480 
481 void
482 pg_lo_creat(dbh, mode)
483     SV * dbh
484     int mode
485     CODE:
486         const unsigned int ret = pg_db_lo_creat(dbh, mode);
487         ST(0) = (ret > 0) ? sv_2mortal(newSVuv(ret)) : &PL_sv_undef;
488 
489 void
490 pg_lo_open(dbh, lobjId, mode)
491     SV * dbh
492     unsigned int lobjId
493     int mode
494     CODE:
495         const int ret = pg_db_lo_open(dbh, lobjId, mode);
496         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
497 
498 
499 void
500 pg_lo_write(dbh, fd, buf, len)
501     SV * dbh
502     int fd
503     char * buf
504     size_t len
505     CODE:
506         const int ret = pg_db_lo_write(dbh, fd, buf, len);
507         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
508 
509 
510 void
511 pg_lo_read(dbh, fd, buf, len)
512     SV * dbh
513     int fd
514     char * buf
515     size_t len
516     PREINIT:
517         SV * const bufsv = SvROK(ST(2)) ? SvRV(ST(2)) : ST(2);
518         int ret;
519     CODE:
520         sv_setpvn(bufsv,"",0); /* Make sure we can grow it safely */
521         buf = SvGROW(bufsv, len + 1);
522         ret = pg_db_lo_read(dbh, fd, buf, len);
523         if (ret > 0) {
524             SvCUR_set(bufsv, ret);
525             *SvEND(bufsv) = '\0';
526             sv_setpvn(ST(2), buf, (unsigned)ret);
527             SvSETMAGIC(ST(2));
528         }
529         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
530 
531 
532 void
533 pg_lo_lseek(dbh, fd, offset, whence)
534     SV * dbh
535     int fd
536     int offset
537     int whence
538     CODE:
539         const int ret = pg_db_lo_lseek(dbh, fd, offset, whence);
540         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
541 
542 void
543 pg_lo_lseek64(dbh, fd, offset, whence)
544     SV * dbh
545     int fd
546     unsigned int offset
547     int whence
548     CODE:
549         const unsigned int ret = pg_db_lo_lseek64(dbh, fd, offset, whence);
550         ST(0) = (ret >= 0) ? sv_2mortal(newSVuv(ret)) : &PL_sv_undef;
551 
552 void
553 pg_lo_tell(dbh, fd)
554     SV * dbh
555     int fd
556     CODE:
557         const int ret = pg_db_lo_tell(dbh, fd);
558         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
559 
560 void
561 pg_lo_tell64(dbh, fd)
562     SV * dbh
563     int fd
564     CODE:
565         const unsigned int ret = pg_db_lo_tell64(dbh, fd);
566         ST(0) = (ret >= 0) ? sv_2mortal(newSVuv(ret)) : &PL_sv_undef;
567 
568 void
569 pg_lo_truncate(dbh, fd, len)
570     SV * dbh
571     int fd
572     size_t len
573     CODE:
574         const int ret = pg_db_lo_truncate(dbh, fd, len);
575         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
576 
577 void
578 pg_lo_truncate64(dbh, fd, len)
579     SV * dbh
580     int fd
581     unsigned int len
582     CODE:
583         const int ret = pg_db_lo_truncate64(dbh, fd, len);
584         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
585 
586 void
587 pg_lo_close(dbh, fd)
588     SV * dbh
589     int fd
590     CODE:
591         ST(0) = (pg_db_lo_close(dbh, fd) >= 0) ? &PL_sv_yes : &PL_sv_no;
592 
593 
594 void
595 pg_lo_unlink(dbh, lobjId)
596     SV * dbh
597     unsigned int lobjId
598     CODE:
599         ST(0) = (pg_db_lo_unlink(dbh, lobjId) >= 1) ? &PL_sv_yes : &PL_sv_no;
600 
601 
602 void
603 pg_lo_import(dbh, filename)
604     SV * dbh
605     char * filename
606     CODE:
607         const unsigned int ret = pg_db_lo_import(dbh, filename);
608         ST(0) = (ret > 0) ? sv_2mortal(newSVuv(ret)) : &PL_sv_undef;
609 
610 
611 void
612 pg_lo_import_with_oid(dbh, filename, lobjId)
613     SV * dbh
614     char * filename
615     unsigned int lobjId
616     CODE:
617         const unsigned int ret = (lobjId==0) ? pg_db_lo_import(dbh, filename)
618             : pg_db_lo_import_with_oid(dbh, filename, lobjId);
619         ST(0) = (ret > 0) ? sv_2mortal(newSVuv(ret)) : &PL_sv_undef;
620 
621 
622 void
623 pg_lo_export(dbh, lobjId, filename)
624     SV * dbh
625     unsigned int lobjId
626     char * filename
627     CODE:
628         ST(0) = (pg_db_lo_export(dbh, lobjId, filename) >= 1) ? &PL_sv_yes : &PL_sv_no;
629 
630 
631 void
632 lo_creat(dbh, mode)
633     SV * dbh
634     int mode
635     CODE:
636         const unsigned int ret = pg_db_lo_creat(dbh, mode);
637         ST(0) = (ret > 0) ? sv_2mortal(newSVuv(ret)) : &PL_sv_undef;
638 
639 void
640 lo_open(dbh, lobjId, mode)
641     SV * dbh
642     unsigned int lobjId
643     int mode
644     CODE:
645         const int ret = pg_db_lo_open(dbh, lobjId, mode);
646         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
647 
648 
649 void
650 lo_write(dbh, fd, buf, len)
651     SV * dbh
652     int fd
653     char * buf
654     size_t len
655     CODE:
656         const int ret = pg_db_lo_write(dbh, fd, buf, len);
657         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
658 
659 
660 void
661 lo_read(dbh, fd, buf, len)
662     SV * dbh
663     int fd
664     char * buf
665     size_t len
666     PREINIT:
667         SV * const bufsv = SvROK(ST(2)) ? SvRV(ST(2)) : ST(2);
668         int ret;
669     CODE:
670         sv_setpvn(bufsv,"",0); /* Make sure we can grow it safely */
671         buf = SvGROW(bufsv, len + 1);
672         ret = pg_db_lo_read(dbh, fd, buf, len);
673         if (ret > 0) {
674             SvCUR_set(bufsv, ret);
675             *SvEND(bufsv) = '\0';
676             sv_setpvn(ST(2), buf, (unsigned)ret);
677             SvSETMAGIC(ST(2));
678         }
679         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
680 
681 
682 void
683 lo_lseek(dbh, fd, offset, whence)
684     SV * dbh
685     int fd
686     int offset
687     int whence
688     CODE:
689         const int ret = pg_db_lo_lseek(dbh, fd, offset, whence);
690         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
691 
692 
693 void
694 lo_tell(dbh, fd)
695     SV * dbh
696     int fd
697     CODE:
698         const int ret = pg_db_lo_tell(dbh, fd);
699         ST(0) = (ret >= 0) ? sv_2mortal(newSViv(ret)) : &PL_sv_undef;
700 
701 
702 void
703 lo_close(dbh, fd)
704     SV * dbh
705     int fd
706     CODE:
707         ST(0) = (pg_db_lo_close(dbh, fd) >= 0) ? &PL_sv_yes : &PL_sv_no;
708 
709 
710 void
711 lo_unlink(dbh, lobjId)
712     SV * dbh
713     unsigned int lobjId
714     CODE:
715         ST(0) = (pg_db_lo_unlink(dbh, lobjId) >= 1) ? &PL_sv_yes : &PL_sv_no;
716 
717 
718 void
719 lo_import(dbh, filename)
720     SV * dbh
721     char * filename
722     CODE:
723         const unsigned int ret = pg_db_lo_import(dbh, filename);
724         ST(0) = (ret > 0) ? sv_2mortal(newSVuv(ret)) : &PL_sv_undef;
725 
726 
727 void
728 lo_export(dbh, lobjId, filename)
729     SV * dbh
730     unsigned int lobjId
731     char * filename
732     CODE:
733         ST(0) = (pg_db_lo_export(dbh, lobjId, filename) >= 1) ? &PL_sv_yes : &PL_sv_no;
734 
735 
736 void
737 pg_putline(dbh, buf)
738     SV * dbh
739     SV * buf
740     CODE:
741         ST(0) = (pg_db_putline(dbh, buf)!=0) ? &PL_sv_no : &PL_sv_yes;
742 
743 
744 void
745 putline(dbh, buf)
746     SV * dbh
747     SV * buf
748     CODE:
749         ST(0) = (pg_db_putline(dbh, buf)!=0) ? &PL_sv_no : &PL_sv_yes;
750 
751 
752 void
753 pg_getline(dbh, buf, len)
754     PREINIT:
755         SV *bufsv = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
756     INPUT:
757         SV * dbh
758         unsigned int len
759         char * buf
760     CODE:
761         int ret;
762         bufsv = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
763         sv_setpvn(bufsv,"",0); /* Make sure we can grow it safely */
764         buf = SvGROW(bufsv, 3);
765         if (len > 3)
766             buf = SvGROW(bufsv, len);
767         ret = pg_db_getline(dbh, bufsv, (int)len);
768         sv_setpv((SV*)ST(1), buf);
769         SvSETMAGIC(ST(1));
770         ST(0) = (-1 != ret) ? &PL_sv_yes : &PL_sv_no;
771 
772 I32
773 pg_getcopydata(dbh, dataline)
774     INPUT:
775         SV * dbh
776     CODE:
777         RETVAL = pg_db_getcopydata(dbh, SvROK(ST(1)) ? SvRV(ST(1)) : ST(1), 0);
778     OUTPUT:
779         RETVAL
780 
781 I32
782 pg_getcopydata_async(dbh, dataline)
783     INPUT:
784         SV * dbh
785     CODE:
786         RETVAL = pg_db_getcopydata(dbh, SvROK(ST(1)) ? SvRV(ST(1)) : ST(1), 1);
787     OUTPUT:
788         RETVAL
789 
790 I32
791 pg_putcopydata(dbh, dataline)
792     INPUT:
793         SV * dbh
794         SV * dataline
795     CODE:
796         RETVAL = pg_db_putcopydata(dbh, dataline);
797     OUTPUT:
798         RETVAL
799 
800 I32
801 pg_putcopyend(dbh)
802     INPUT:
803         SV * dbh
804     CODE:
805         RETVAL = pg_db_putcopyend(dbh);
806     OUTPUT:
807         RETVAL
808 
809 void
810 getline(dbh, buf, len)
811     PREINIT:
812         SV *bufsv = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
813     INPUT:
814         SV * dbh
815         unsigned int len
816         char * buf
817     CODE:
818         int ret;
819         sv_setpvn(bufsv,"",0); /* Make sure we can grow it safely */
820         buf = SvGROW(bufsv, 3);
821         if (len > 3)
822             buf = SvGROW(bufsv, len);
823         ret = pg_db_getline(dbh, bufsv, (int)len);
824         sv_setpv((SV*)ST(1), buf);
825         SvSETMAGIC(ST(1));
826         ST(0) = (-1 != ret) ? &PL_sv_yes : &PL_sv_no;
827 
828 void
829 endcopy(dbh)
830     SV * dbh
831     CODE:
832         ST(0) = (-1 != pg_db_endcopy(dbh)) ? &PL_sv_yes : &PL_sv_no;
833 
834 void
835 pg_server_trace(dbh,fh)
836     SV * dbh
837     FILE * fh
838     CODE:
839         pg_db_pg_server_trace(dbh,fh);
840 
841 void
842 pg_server_untrace(dbh)
843     SV * dbh
844     CODE:
845         pg_db_pg_server_untrace(dbh);
846 
847 void
848 _pg_type_info (type_sv=Nullsv)
849     SV* type_sv
850     CODE:
851     {
852         int type_num = 0;
853 
854         if (type_sv && SvOK(type_sv)) {
855             sql_type_info_t *type_info;
856             if SvMAGICAL(type_sv)
857                 (void)mg_get(type_sv);
858             type_info = pg_type_data(SvIV(type_sv));
859             type_num = type_info ? type_info->type.sql : SQL_VARCHAR;
860         }
861         ST(0) = sv_2mortal( newSViv( type_num ) );
862     }
863 
864 void
865 pg_result(dbh)
866     SV * dbh
867     CODE:
868         int ret;
869         D_imp_dbh(dbh);
870         ret = pg_db_result(dbh, imp_dbh);
871         if (ret == 0)
872             XST_mPV(0, "0E0");
873         else if (ret < -1)
874             XST_mUNDEF(0);
875         else
876             XST_mIV(0, ret);
877 
878 void
879 pg_ready(dbh)
880     SV *dbh
881     CODE:
882         D_imp_dbh(dbh);
883         ST(0) = sv_2mortal(newSViv(pg_db_ready(dbh, imp_dbh)));
884 
885 void
886 pg_cancel(dbh)
887     SV *dbh
888     CODE:
889     D_imp_dbh(dbh);
890     ST(0) = pg_db_cancel(dbh, imp_dbh) ? &PL_sv_yes : &PL_sv_no;
891 
892 
893 # -- end of DBD::Pg::db
894 
895 
896 # ------------------------------------------------------------
897 # statement level interface PG specific
898 # ------------------------------------------------------------
899 MODULE = DBD::Pg    PACKAGE = DBD::Pg::st
900 
901 void state(sth)
902 SV *sth;
903     CODE:
904         D_imp_sth(sth);
905         D_imp_dbh_from_sth;
906         ST(0) = strEQ(imp_dbh->sqlstate,"00000")
907                   ? &PL_sv_no
908                   : sv_2mortal(newSVpv(imp_dbh->sqlstate, 5));
909 
910 void
911 pg_ready(sth)
912     SV *sth
913     CODE:
914         D_imp_sth(sth);
915         D_imp_dbh_from_sth;
916         ST(0) = sv_2mortal(newSViv(pg_db_ready(sth, imp_dbh)));
917 
918 void
919 pg_cancel(sth)
920     SV *sth
921     CODE:
922     D_imp_sth(sth);
923     ST(0) = pg_db_cancel_sth(sth, imp_sth) ? &PL_sv_yes : &PL_sv_no;
924 
925 void
926 cancel(sth)
927     SV *sth
928     CODE:
929     D_imp_sth(sth);
930     ST(0) = dbd_st_cancel(sth, imp_sth) ? &PL_sv_yes : &PL_sv_no;
931 
932 void
933 pg_result(sth)
934     SV * sth
935     CODE:
936         long ret;
937         D_imp_sth(sth);
938         D_imp_dbh_from_sth;
939         ret = pg_db_result(sth, imp_dbh);
940         if (ret == 0)
941             XST_mPV(0, "0E0");
942         else if (ret < -1)
943             XST_mUNDEF(0);
944         else
945             XST_mIV(0, ret);
946 
947 SV*
948 pg_canonical_ids(sth)
949     SV *sth
950     CODE:
951         D_imp_sth(sth);
952         RETVAL = dbd_st_canonical_ids(sth, imp_sth);
953     OUTPUT:
954         RETVAL
955 
956 SV*
957 pg_canonical_names(sth)
958     SV *sth
959     CODE:
960         D_imp_sth(sth);
961         RETVAL = dbd_st_canonical_names(sth, imp_sth);
962     OUTPUT:
963         RETVAL
964 
965 # end of Pg.xs
966