File: gnatcoll-sql-postgres-gnade.ads

package info (click to toggle)
libgnatcoll-db 18-4
  • links: PTS
  • area: main
  • in suites: buster
  • size: 2,268 kB
  • sloc: ada: 23,786; python: 2,166; makefile: 486; sh: 34; ansic: 18
file content (632 lines) | stat: -rw-r--r-- 28,645 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
-------------------------------------------------------------------------------
--                                                                           --
--                      GNADE  : GNu Ada Database Environment                --
--                                                                           --
--  Copyright (C) 2000-2003, Juergen Pfeifer <juergen.pfeifer@gmx.net>       --
--  Copyright (C) 2004-2017, AdaCore                                         --
--                                                                           --
--  GNADE is free software;  you can redistribute it  and/or modify it under --
--  terms of the  GNU General Public License as published  by the Free Soft- --
--  ware  Foundation;  either version 2,  or (at your option) any later ver- --
--  sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
--  OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
--  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
--  for  more details.  You should have  received  a copy of the GNU General --
--  Public License  distributed with GNAT;  see file COPYING.  If not, write --
--  to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--  MA 02111-1307, USA.                                                      --
--                                                                           --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                           --
--  GNADE is implemented to work with GNAT, the GNU Ada compiler.            --
-------------------------------------------------------------------------------

--  This file is adapted from the GNADE package, with local changes, in
--  particular in the namespace.
--  This binding is not intended to provide a Layer that hides the details
--  of PostgreSQL, instead the opposite is intended. This binding exposes
--  the same functionality as the C interface libpq.
--
--  It contains the low-level binding to the postgreSQL library, and is not
--  recommended for end users (the higher-level API in GNATCOLL.SQL is easier
--  to use, more portable across DBMS and provides type-safety). However, this
--  package can be used to provide an easier transition of existing code to
--  the higher-level API.

with Ada.Finalization;
with Interfaces.C.Strings;
with GNATCOLL.SQL_Impl;
with GNATCOLL.Strings;
with System;

package GNATCOLL.SQL.Postgres.Gnade is
   PostgreSQL_Error : exception;

   NAMEDATALEN : constant := 32;
   --  The maximum length for system identifiers (e.g. table names etc.)

   type OID is new Interfaces.C.unsigned;
   --  PostreSQL assigns a unique Object ID (OID) to a row.

   InvalidOID : constant OID;
   --  This denotes an invalid OID.

   subtype TypeID is OID;
   --  Types are objects in the database and have IDs.
   InvalidTypeID : constant TypeID;

   type Field_Index is new Natural;
   --  Field indices in general start with 0 in PostgreSQL

   type Tuple_Index is new Natural;
   --  Tuple indices in general start with 0 in PostgreSQL

   type ConnStatus is (CONNECTION_OK,
                       CONNECTION_BAD,
                       CONNECTION_STARTED,
                       CONNECTION_MADE,
                       CONNECTION_AWAITING_RESPONSE,
                       CONNECTION_AUTH_OK,
                       CONNECTION_SETENV);
   pragma Convention (C, ConnStatus);

   subtype SynchConnStatus is
     ConnStatus range CONNECTION_OK .. CONNECTION_BAD;
   --  These values are possible for synchronous connections.

   type Backend_PID is new Interfaces.C.int;
   --  This type is used to identify the backend server process handling the
   --  database connection.

   type ExecStatus is (
     --  Direct mappings for C values

     PGRES_EMPTY_QUERY,
     PGRES_COMMAND_OK,
     PGRES_TUPLES_OK,
     PGRES_COPY_OUT,
     PGRES_COPY_IN,
     PGRES_BAD_RESPONSE,
     PGRES_NONFATAL_ERROR,
     PGRES_FATAL_ERROR,
     PGRES_COPY_BOTH,

     --  Additional value denoting a NULL PQresult

     PGRES_Null_Result);

   pragma Convention (C, ExecStatus);

   type Database (Parameters :  access String) is tagged limited private;
   --  You must pass the PostgreSQL connection string as discriminant
   --  when you instantiate a new Database object. The connection to
   --  the database will be made during the initialization of the object.
   --  The connection will be closed automatically when the Database objects
   --  goes out of scope (will be "finalized").

   procedure Reset (DB : Database'Class);
   pragma Inline (Reset);
   --  This function will close the connection to the backend and attempt
   --  to reestablish a new connection to the same postmaster, using all
   --  the same parameters previously used. This may be useful for error
   --  recovery if a working connection is lost.

   function Name (DB : Database'Class) return String;
   pragma Inline (Name);
   --  Returns the database name of the connection

   function User (DB : Database'Class) return String;
   pragma Inline (User);
   --  Returns the user name of the connection

   function Password (DB : Database'Class) return String;
   pragma Inline (Password);
   --  Returns the password of the connection

   function Host (DB : Database'Class) return String;
   pragma Inline (Host);
   --  Returns the server host name of the connection

   function Port (DB : Database'Class) return String;
   pragma Inline (Port);
   --  Returns the port of the connection

   function TTY (DB : Database'Class) return String;
   pragma Inline (TTY);
   --  Returns the debug tty of the connection

   function Options (DB : Database'Class) return String;
   pragma Inline (Options);
   --  Returns the backend options used in the connection

   function Error (DB : Database'Class) return String;
   pragma Inline (Error);
   --  Returns the error message most recently generated by an operation
   --  on the connection

   function Server_PID (DB : Database'Class) return Backend_PID;
   pragma Inline (Server_PID);
   --  Returns the process ID of the backend server handling this connection

   function Status (DB : Database'Class) return ConnStatus;
   pragma Inline (Status);
   --  Returns the status of the connection.
   --  Only two of the ConnStatus values are seen outside of an asynchronous
   --  connection procedure - CONNECTION_OK or CONNECTION_BAD. A good
   --  connection to the database has the status CONNECTION_OK. A failed
   --  connection attempt is signaled by status CONNECTION_BAD. Ordinarily,
   --  an OK status will remain so until PQfinish, but a communications
   --  failure might result in the status changing to CONNECTION_BAD
   --  prematurely. In that case the application could try to recover by
   --  calling the Reset procedure.

   --  -----------------------------------------------------------------------
   --  Management of Large Objects (BLOBs)
   --  Cf http://www.postgresql.org/docs/current/interactive/lo-interfaces.html
   --  (Added by Audran Le Baron <lebaron@act-europe.fr>)
   --  -----------------------------------------------------------------------

   type File_Mode is mod 16#100000000#;
   for File_Mode'Size use Integer'Size;
   INV_WRITE : constant File_Mode := 16#00020000#;
   INV_READ  : constant File_Mode := 16#00040000#;

   type File_Descriptor is new Integer;
   Invalid_FD : constant File_Descriptor := -1;

   Seek_Set : constant := 0;
   Seek_Cur : constant := 1;
   Seek_End : constant := 2;

   function BLOB_Create (DB   : Database'Class;
                         Mode : File_Mode)
                         return OID;
   pragma Inline (BLOB_Create);
   --  Create a Large Object. Read and write modes can be combined by OR'ing
   --  the correspondant flags. Return the OID of the newly created BLOB.
   --  Oid lo_creat (PGconn *conn, int mode)

   function BLOB_Import (DB           : Database'Class;
                         In_File_Name : String) return OID;
   pragma Inline (BLOB_Import);
   --  Import a Large Object into the database
   --  and return the corresponding OID.
   --  Oid lo_import(PGconn *conn, const char *filename)

   function BLOB_Export (DB            : Database'Class;
                         Object_Id     : OID;
                         Out_File_Name : String) return Boolean;
   pragma Inline (BLOB_Export);
   --  Export the given Large Object from the database to the specified file.
   --  Return False upon error, True otherwise.
   --  int lo_export(PGconn *conn, Oid lobjId, const char *filename)

   function BLOB_Open (DB        : Database'Class;
                       Object_Id : OID;
                       Mode      : File_Mode)
                       return File_Descriptor;
   pragma Inline (BLOB_Open);
   --  Open the given BLOB. Return the corresponding file descriptor.
   --  int lo_open  (PGconn *conn, Oid lobjId, int mode)

   function BLOB_Write (DB : Database'Class;
                        FD : File_Descriptor;
                        A  : System.Address;
                        N  : Integer)
                        return Integer;
   pragma Inline (BLOB_Write);
   --  Write N bytes from A to large object FD.
   --  Return the number of bytes actually written.
   --  int lo_write (PGconn *conn, int fd, const char *buf, size_t len)

   function BLOB_Read (DB : Database'Class;
                       FD : File_Descriptor;
                       A  : System.Address;
                       N  : Integer)
                       return Integer;
   pragma Inline (BLOB_Read);
   --  Read N bytes from large object FD to A.
   --  Return the number of bytes actually read.
   --  int lo_read  (PGconn *conn, int fd, char *buf, size_t len)

   function BLOB_Lseek (DB     : Database'Class;
                        FD     : File_Descriptor;
                        Offset : Integer;
                        Origin : Integer)
                        return Integer;
   pragma Inline (BLOB_Lseek);
   --  Move the current location pointer for the large object FD
   --  to the new location specified by offset.
   --  The valid values for Origin are:
   --     SEEK_SET (seek from object start),
   --     SEEK_CUR (seek from current position),
   --     SEEK_END (seek from object end).
   --  Return the new location pointer.
   --  int lo_lseek (PGconn *conn, int fd, int offset, int whence)

   function BLOB_Tell (DB : Database'Class;
                       FD : File_Descriptor)
                       return Integer;
   pragma Inline (BLOB_Tell);
   --  Return the current read or write location of large object FD.
   --  If there is an error, the return value is negative.
   --  int lo_tell  (PGconn *conn, int fd)

   function BLOB_Close (DB : Database'Class;
                        FD : File_Descriptor)
                        return Boolean;
   pragma Inline (BLOB_Close);
   --  Close the given large object (FD).
   --  Return True upon success, False otherwise.
   --  int lo_close (PGconn *conn, int fd)

   function BLOB_Unlink (DB        : Database'Class;
                         Object_Id : OID) return Boolean;
   pragma Inline (BLOB_Unlink);
   --  Remove the given Large Object from the database.
   --  Return True upon success, False otherwise.
   --  int lo_unlink(PGconn *conn, Oid lobjId)

   type Result is private;
   --  This is the abstraction of a query result set.
   --  You must call Clear to free the contents once you no longer need it

   procedure Clear (Res : in out Result);
   --  Free the memory used by Result

   procedure Execute
     (Res    : in out Result;
      DB     : Database'Class;
      Query  : String;
      Format : GNATCOLL.SQL_Impl.Formatter'Class;
      Params : SQL_Parameters := No_Parameters);
   --  Submit a query to Postgres and wait for the result

   procedure Prepare
     (Res       : out Result;
      DB        : Database'Class;
      Stmt_Name : String;
      Query     : String);
   --  Prepare the statement for execution

   procedure Exec_Prepared
     (Res       : out Result;
      DB        : Database'Class;
      Stmt_Name : String;
      Format    : GNATCOLL.SQL_Impl.Formatter'Class;
      Params    : SQL_Parameters := No_Parameters);
   --  Execute a prepared statement

   function Status (Res : Result) return ExecStatus;
   --  Returns the result status of the query
   --  If the result status is PGRES_TUPLES_OK, then the routines described
   --  below can be used to retrieve the tuples returned by the query.
   --  Note that a SELECT that happens to retrieve zero tuples still shows
   --  PGRES_TUPLES_OK. PGRES_COMMAND_OK is for commands that can never
   --  return tuples (INSERT, UPDATE, etc.). A response of PGRES_EMPTY_QUERY
   --  often exposes a bug in the client software.

   function Status (Status : ExecStatus) return String;
   --  Converts the enumerated type returned by PQresultStatus into a
   --  string constant describing the status code

   function Status (Res : Result) return String;
   pragma Inline (Status);
   --  Combination of the above two elementary functions. Get the string
   --  constant describing the status code directly from the Result

   function Error  (Res : Result) return String;
   pragma Inline (Error);
   --  Returns the error message associated with the query, or an empty
   --  string if there was no error.
   --
   --  Immediately following an Execute or GetResult call, Error (on the
   --  Database object) will return the same string as Error (on the Result).
   --  However, a Result will retain its error message until destroyed,
   --  whereas the Database's error message will change when subsequent
   --  operations are done. Use Error (on the Result) when you want to know
   --  the status associated with a particular Result; use Error (on the
   --  Database) when you want to know the status from the latest operation
   --  on the connection.

   function Tuple_Count (Res   : Result) return Tuple_Index;
   pragma Inline (Tuple_Count);
   --  Returns the number of tuples (instances) in the query result

   function Field_Count (Res   : Result) return Field_Index;
   pragma Inline (Field_Count);
   --  Returns the number of fields (attributes) in each tuple of the
   --  query result

   function Field_Name  (Res   : Result;
                         Index : Field_Index) return String;
   pragma Inline (Field_Name);
   --  Returns the field (attribute) name associated with the given field
   --  index.

   procedure Field_Lookup (Res   : Result;
                           Name  : String;
                           Index : out Field_Index;
                           Found : out Boolean);
   pragma Inline (Field_Lookup);
   --  Returns the field (attribute) index associated with the given
   --  field name. If the field was found, the 'Found' parameter is set
   --  to True and the 'Index' parameter will contain the fields index.
   --  Otherwise 'Found' is set to False.

   function Is_Binary (Res   : Result) return Boolean;
   pragma Inline (Is_Binary);
   --  Returns True if the Result contains binary tuple data, False if it
   --  contains ASCII data.

   function Field_Type  (Res   : Result;
                         Index : Field_Index) return TypeID;
   pragma Inline (Field_Type);
   --  Returns the field type associated with the given field index.
   --  The TypeID returned is an internal coding of the type.

   procedure Value (Res     : Result;
                    Tuple   : Tuple_Index;
                    Field   : Field_Index;
                    Pointer : out System.Address);
   --  For most queries, the value referenced by Pointer is a C-String
   --  representation of the attribute value. But if Is_Binary is True,
   --  the value referenced by Pointer is the binary representation of the type
   --  in the internal format of the backend server. It is then the
   --  programmer's responsibility to cast and convert the data to the
   --  correct Ada type. The Pointer returned points to storage that
   --  is part of the Result object. One should not modify it, and one
   --  must explicitly copy the value into other storage if it is to be
   --  used past the lifetime of the Result object itself.

   function C_Value
     (Res   : Result;
      Tuple : Tuple_Index := 0;
      Field : Field_Index := 0) return Interfaces.C.Strings.chars_ptr;
   --  Returns the C string

   function Value (Res   : Result;
                   Tuple : Tuple_Index := 0;
                   Field : Field_Index := 0) return String;
   --  Returns a single field (attribute) value of one tuple of a Result
   --  as a String. If this is a binary field please use the more general
   --  Value procedure above.

   function Boolean_Value (Res   : Result;
                           Tuple : Tuple_Index := 0;
                           Field : Field_Index := 0) return Boolean;
   pragma Inline (Boolean_Value);
   --  Same as above, but returns a boolean

   function Value (Res        : Result;
                   Tuple      : Tuple_Index := 0;
                   Field_Name : String) return String;
   --  Returns a single field (attribute) value of one tuple of a Result
   --  as a String. If this is a binary field please use the more general
   --  Value procedure above.
   pragma Inline (Value);

   function Boolean_Value (Res        : Result;
                           Tuple      : Tuple_Index := 0;
                           Field_Name : String) return Boolean;
   pragma Inline (Boolean_Value);
   --  Same as above but returns a boolean

   function Integer_Value (Res     : Result;
                           Tuple   : Tuple_Index := 0;
                           Field   : Field_Index := 0;
                           Default : Integer := Integer'First) return Integer;
   pragma Inline (Integer_Value);
   --  Same as above but returns an integer.
   --  If the field does not contain an integer, Default is returned if it
   --  was specified, or an exception is raised otherwise.

   function Array_Field (Value : String; Field : Positive) return String;
   --  Given a postgres array value "{1, 2, 3}", return the Index-th value.
   --  Constraint_Error is raised upon reaching the end of the array

   function Field_Size  (Res   : Result;
                         Field : Field_Index) return Integer;
   pragma Inline (Field_Size);
   --  Returns the size in bytes of the field associated with the given
   --  field index.
   --  Field_Size returns the space allocated for this field in a database
   --  tuple, in other words the size of the server's binary representation
   --  of the data type. -1 is returned if the field is variable size.

   function Field_Modification  (Res   : Result;
                                 Field : Field_Index) return Integer;
   pragma Inline (Field_Modification);
   --  Returns the type-specific modification data of the field associated
   --  with the given field index.

   function Field_Length (Res   : Result;
                          Tuple : Tuple_Index;
                          Field : Field_Index) return Natural;
   pragma Inline (Field_Length);
   --  Returns the length of a field (attribute) in bytes.
   --  This is the actual data length for the particular data value, that is
   --  the size of the object retrieved by the Value function. Note that for
   --  ASCII-represented values, this size has little to do with the binary
   --  size reported by Field_Size.

   function Is_Null (Res   : Result;
                     Tuple : Tuple_Index;
                     Field : Field_Index) return Boolean;
   pragma Inline (Is_Null);
   --  Tests a field for a NULL entry. This function returns True if the
   --  field contains a NULL, False if it contains a non-null value.
   --  (Note that the Value function will return an empty string for a NULL
   --  field.)

   function Command_Status (Res : Result) return String;
   pragma Inline (Command_Status);
   --  Returns the command status string from the SQL command that generated
   --  the Result.

   function Command_Tuples (Res : Result) return String;
   pragma Inline (Command_Tuples);
   --  Returns the number of rows affected by the SQL command.
   --  If the SQL command that generated the Result was INSERT, UPDATE or
   --  DELETE, this returns a string containing the number of rows affected.
   --  If the command was anything else, it returns the empty string

   function Command_Tuples (Res : Result) return Natural;
   pragma Inline (Command_Tuples);
   --  Returns the number of rows affected by the SQL command.
   --  If the SQL command that generated the Result was INSERT, UPDATE or
   --  DELETE, this returns the number of rows affected.
   --  If the command was anything else, it returns 0.

   function OID_Value (Res : Result) return OID;
   pragma Inline (OID_Value);
   --  Returns the object id of the tuple inserted, if the SQL command was
   --  an INSERT. Otherwise, returns InvalidOid.

   procedure Make_Empty_Result (Res    : out Result;
                                DB     : Database'Class;
                                Status : ExecStatus := PGRES_EMPTY_QUERY);
   --  Constructs an empty Result object with the given status
   --  This is libpq's internal routine to allocate and initialize an empty
   --  Result object. It is exported because some applications find it useful
   --  to generate result objects (particularly objects with error status)
   --  themselves. If the Database connection is valid and status indicates
   --  an error, the connection's current errorMessage is copied into the
   --  Result.
   pragma Inline (Make_Empty_Result);

   --  -----------------------------------------------------------------------
   --  Procedures and functions for Asynchronous query processing
   --  -----------------------------------------------------------------------

   function Is_Non_Blocking (DB : Database'Class) return Boolean;
   pragma Inline (Is_Non_Blocking);
   --  Returns the blocking status of the database connection.

   function Send_Query (DB    : Database'Class;
                        Query : String) return Boolean;
   pragma Inline (Send_Query);
   --  Submit a query to Postgres without waiting for the result(s). True is
   --  returned if the query was successfully dispatched, False if not (in
   --  which case, use function Error to get more information about the
   --  failure).
   --  After successfully calling Send_Query, call Get_Result one or more
   --  times to obtain the query results. Send_Query may not be called again
   --  (on the same connection) until Get_Result has returned with completion
   --  flag set to True, indicating that the query is done.

   procedure Get_Result (DB   : Database'Class;
                         Res  : out Result;
                         Done : out Boolean);
   --  Wait for the next result from a prior Send_Query, and return it.
   --  Done is set to True when the query is complete and there will be no
   --  more results, in this case Res will not be set. When Done is set to
   --  False, the Res contains a Result and processing is not finished.

   function Consume_Input (DB : Database'Class) return Boolean;
   pragma Inline (Consume_Input);
   --  If input is available from the backend, consume it.
   --  Consume_Input normally returns True indicating "no error", but returns
   --  False if there was some kind of trouble (in which case function Error
   --  should be used). Note that the result does not say whether any input
   --  data was actually collected. After calling Consume_Input, the
   --  application may check Is_Busy and/or Notifies to see if their state
   --  has changed.
   --
   --  Consume_Input may be called even if the application is not prepared to
   --  deal with a result or notification just yet. The routine will read
   --  available data and save it in a buffer, thereby causing a select(2)
   --  read-ready indication to go away. The application can thus use
   --  Consume_Input to clear the select condition immediately, and then
   --  examine the results at leisure.

   function Flush (DB : Database'Class) return Boolean;
   pragma Inline (Flush);
   --  Attempt to flush any data queued to the backend, returns True if
   --  successful (or if the send queue is empty) or False if it failed for
   --  some reason.
   --  Flush needs to be called on a non-blocking connection before calling
   --  select to determine if a responce has arrived. If True is returned it
   --  ensures that there is no data queued to the backend that has not
   --  actually been sent. Only applications that have used Set_Non_Blocking
   --  have a need for this.

   function Is_Busy (DB : Database'Class) return Boolean;
   pragma Inline (Is_Busy);
   --  Returns True if a query is busy, that is, Get_Result would block
   --  waiting for input. A False return indicates that Get_Result can be
   --  called with assurance of not blocking.
   --  Is_Busy will not itself attempt to read data from the backend;
   --  therefore Consume_Input must be invoked first, or the busy state will
   --  never end.

   function Socket (DB : Database'Class) return Interfaces.C.int;
   pragma Inline (Socket);
   --  Obtain the file descriptor number for the backend connection socket.
   --  A valid descriptor will be >= 0; a result of -1 indicates that no
   --  backend connection is currently open.

   function Request_Cancel (DB : Database'Class) return Boolean;
   pragma Inline (Request_Cancel);
   --  Request that Postgres abandon processing of the current query.
   --  The return value is True if the cancel request was successfully
   --  dispatched, False if not. (If not, function Error tells why not.)
   --  Successful dispatch is no guarantee that the request will have any
   --  effect, however. Regardless of the return value of Request_Cancel,
   --  the application must continue with the normal result-reading sequence
   --  using Get_Result. If the cancellation is effective, the current query
   --  will terminate early and return an error result. If the cancellation
   --  fails (say, because the backend was already done processing the query),
   --  then there will be no visible result at all.
   --  Note that if the current query is part of a transaction, cancellation
   --  will abort the whole transaction.
   --  Request_Cancel can safely be invoked from a signal handler. So, it is
   --  also possible to use it in conjunction with plain Execute, if the
   --  decision to cancel can be made in a signal handler. Note that
   --  Request_Cancel will have no effect if the connection is not currently
   --  open or the backend is not currently processing a query.

   procedure Notifies (DB      : Database'Class;
                       Message : out Notification;
                       Done    : out Boolean);
   --  Returns the next notification from a list of unhandled notification
   --  messages received from the backend. Done is set to False if there are
   --  no pending notifications. In this case Message is not be set. If Done
   --  is set to False, Message contains a valid Notification. Once a
   --  notification is returned from Notifies, it is considered handled and
   --  will be removed from the list of notifications.

   function Quote_Identifier (Identifier : String) return String;
   pragma Inline (Quote_Identifier);

private
   use Ada.Finalization;

   InvalidOID : constant OID := 0;
   InvalidTypeID : constant TypeID := TypeID (InvalidOID);

   type PGconnection is new System.Address;
   Null_Connection : constant PGconnection :=
     PGconnection (System.Null_Address);
   function Connect (Params : access String) return PGconnection;

   type Database (Parameters : access String) is new Limited_Controlled with
      record
         Connection : PGconnection := Connect (Parameters);
      end record;

   overriding procedure Finalize (Object : in out Database);

   type PGresult is new System.Address;
   Null_Result : constant PGresult := PGresult (System.Null_Address);

   type Result is record
      Res : PGresult := Null_Result;
   end record;

end GNATCOLL.SQL.Postgres.Gnade;