我如何在 GNAT CE 2019 中查询 PostgreSQL

How do I query PostgreSQL within GNAT CE 2019

我正在尝试使用 GNAT CE 2019 查询 PostgreSQL 数据库。我的数据库中有两个表,car 和 person:

mydb1-# \dt
         List of relations
 Schema |  Name  | Type  |  Owner   
--------+--------+-------+----------
 public | car    | table | postgres
 public | person | table | postgres
(2 rows)

我想执行一个简单的 Select 语句,当我在终端中使用 psql 执行此操作时,返回的是:

mydb1=# SELECT * FROM Person;

              person_uid              | first_name | last_name  | gender |            email             | date_of_birth | country_of_birth |               car_uid                
--------------------------------------+------------+------------+--------+------------------------------+---------------+------------------+--------------------------------------
 75f5e55d-12b2-463e-93ff-1c921e44c3e1 | Audrie     | Vasyukov   | Female | avasyukovd6@domainmarket.com | 1988-11-24    | Guatemala        | 
 9e3f7f90-6e9a-4f2d-ae4e-c852d819ed33 | Nefen      | Philippard | Male   | nphilippardd7@economist.com  | 2006-11-08    | Russia           | 
 ffad6113-2321-47c3-8e1d-b8bbe1f7ffa1 | Leonore    | Garthland  | Female | lgarthlandd8@furl.net        | 1991-03-23    | Canada           | 
 268c1977-a5cc-4794-9cdd-e0e4af7890b9 | Yank       | Turfitt    | Male   | yturfittd9@exblog.jp         | 1990-02-07    | China            | 
 3c815fa3-74b9-493a-9466-f32010806b16 | Benn       | Pawley     | Male   | bpawleyda@indiegogo.com      | 2006-10-28    | Russia           | 
 690fc9e9-309e-4d70-8dab-167653b99763 | Tod        | Easen      | Male   | teasend4@php.net             | 1990-08-24    | China            | 5fa7490e-ba42-4a96-b806-097bbb16e30e

但是,我想在 GNAT CE 2019 中执行此操作。这是我的 main.adb 文件当前的样子:

with GNATCOLL.SQL.Postgres;  use GNATCOLL.SQL.Postgres;
with GNATCOLL.SQL.Exec;      use GNATCOLL.SQL.Exec;
with GNATCOLL.VFS;           use GNATCOLL.VFS;
with GNATCOLL.SQL.Inspect;   use GNATCOLL.SQL.Inspect;
with GNATCOLL.SQL;           use GNATCOLL.SQL;



procedure Main is


   -- Datebase Description
   --
   DB_Descr : GNATCOLL.SQL.Exec.Database_Description;

   -- Database Connection
   --
   DB : GNATCOLL.SQL.Exec.Database_Connection;


   -- Used to Query the data
   --
   Q : SQL_Query;


begin


   -- Database Description
   --
   DB_Descr := GNATCOLL.SQL.Postgres.Setup ("mydb1", "parallels", "localhost", "MyPassword", 5432);

   -- Database Connection
   --
   DB := DB_Descr.Build_Connection;



   -- Query the data
   --

   Q := SQL_Select
      (Fields => Person.first_name,
       From   => Person);




  Free (DB);  --  for all connections you have opened
  Free (DB_Descr);

   end Main;

尝试连接到数据库时,进程成功终止。

我不确定应该用于 Select 语句的语法。如果有人能够告诉我如何在 GNAT CE 2019 中执行简单的 SELECT * FROM Person; 语句,将不胜感激。

谢谢, 劳埃德

添加于 2020 年 5 月 13 日

parallels@localhost gnatcoll_db2ada]$ ls
dborm.py                  gnatcoll-db2ada-main-generate.adb
dbschema.txt              gnatcoll_postgres2ada.adb
gnatcoll_all2ada.adb      gnatcoll_postgres2ada.gpr
gnatcoll_all2ada.gpr      gnatcoll_sqlite2ada.adb
gnatcoll_db2ada.adb       gnatcoll_sqlite2ada.gpr
gnatcoll-db2ada.ads       Makefile
gnatcoll_db2ada.gpr       makefile.setup
[parallels@localhost gnatcoll_db2ada]$ gnatcoll_postgres2ada -dbmodel dschema.txt/home/parallels/Desktop/dschema.txt
bash: gnatcoll_postgres2ada: command not found...
[parallels@localhost gnatcoll_db2ada]$ 

添加于 2020 年 5 月 15 日

prbuild -d -P/home/parallels/Documents/Ada Projects/TEST/default.gpr -XGNATCOLL_OS=unix -XBUILD=PROD -XGNATCOLL_HASPQPREPARE=yes -XGPR_BUILD=static -XLIBRARY_TYPE=static -XXMLADA_BUILD=static -XGNATCOLL_CORE_BUILD=static -XGNATCOLL_BUILD=static /home/parallels/Documents/Ada Projects/TEST/src/main.adb
Compile
   [Ada]          main.adb
Bind
   [gprbind]      main.bexch
   [Ada]          main.ali
Link
   [link]         main.adb
/home/parallels/opt/GNAT/2019/bin/../libexec/gcc/x86_64-pc-linux-gnu/8.3.1/ld: cannot find -lpq
collect2: error: ld returned 1 exit status
gprbuild: link of main.adb failed
gprbuild: failed command was: /home/parallels/opt/GNAT/2019/bin/gcc main.o b__main.o /home/parallels/Documents/Ada Projects/TEST/obj/database_names.o /home/parallels/Documents/Ada Projects/TEST/obj/database.o /home/parallels/gnatcoll-db/postgres/lib/static/libgnatcoll_postgres.a /home/parallels/gnatcoll-db/sql/lib/static/libgnatcoll_sql.a /home/parallels/opt/GNAT/2019/lib/gnatcoll.static/libgnatcoll.a /home/parallels/opt/GNAT/2019/lib/gpr/static/gpr/libgpr.a /home/parallels/opt/GNAT/2019/lib/xmla
da/xmlada_schema.static/libxmlada_schema.a /home/parallels/opt/GNAT/2019/lib/xmlada/xmlada_dom.static/libxmlada_dom.a /home/parallels/opt/GNAT/2019/lib/xmlada/xmlada_sax.static/libxmlada_sax.a /home/parallels/opt/GNAT/2019/lib/xmlada/xmlada_input.static/libxmlada_input_sources.a /home/parallels/opt/GNAT/2019/lib/xmlada/xmlada_unicode.static/libxmlada_unicode.a -lpq -L/home/parallels/Documents/Ada Projects/TEST/obj/ -L/home/parallels/Documents/Ada Projects/TEST/obj/ -L/home/parallels/gnatcoll-db/p
ostgres/lib/static/ -L/home/parallels/opt/GNAT/2019/lib/gnatcoll.static/ -L/home/parallels/opt/GNAT/2019/lib/xmlada/xmlada_dom.static/ -L/home/parallels/opt/GNAT/2019/lib/xmlada/xmlada_sax.static/ -L/home/parallels/opt/GNAT/2019/lib/xmlada/xmlada_unicode.static/ -L/home/parallels/opt/GNAT/2019/lib/xmlada/xmlada_input.static/ -L/home/parallels/opt/GNAT/2019/lib/xmlada/xmlada_schema.static/ -L/home/parallels/opt/GNAT/2019/lib/gpr/static/gpr/ -L/home/parallels/gnatcoll-db/sql/lib/static/ -L/home/par
allels/opt/GNAT/2019/lib/gcc/x86_64-pc-linux-gnu/8.3.1/adalib/ -static-libgcc /home/parallels/opt/GNAT/2019/lib/gcc/x86_64-pc-linux-gnu/8.3.1/adalib/libgnarl.a /home/parallels/opt/GNAT/2019/lib/gcc/x86_64-pc-linux-gnu/8.3.1/adalib/libgnat.a -lrt -lpthread -ldl -Wl,-rpath-link,/home/parallels/opt/GNAT/2019/lib/gcc/x86_64-pc-linux-gnu/8.3.1//adalib -Wl,-z,origin,-rpath,$ORIGIN/:$ORIGIN/../../../..//gnatcoll-db/postgres/lib/static:$ORIGIN/../../../..//opt/GNAT/2019/lib/gnatcoll.static:$ORIGIN/../../
../..//opt/GNAT/2019/lib/xmlada/xmlada_dom.static:$ORIGIN/../../../..//opt/GNAT/2019/lib/xmlada/xmlada_sax.static:$ORIGIN/../../../..//opt/GNAT/2019/lib/xmlada/xmlada_unicode.static:$ORIGIN/../../../..//opt/GNAT/2019/lib/xmlada/xmlada_input.static:$ORIGIN/../../../..//opt/GNAT/2019/lib/xmlada/xmlada_schema.static:$ORIGIN/../../../..//opt/GNAT/2019/lib/gpr/static/gpr:$ORIGIN/../../../..//gnatcoll-db/sql/lib/static:$ORIGIN/../../../..//opt/GNAT/2019/lib/gcc/x86_64-pc-linux-gnu/8.3.1/adalib -o main
[2020-05-15 14:56:50] process exited with status 4, 100% (30/30), elapsed time: 02.34s

添加于 2020 年 5 月 17 日

[SQL.ERROR] FATAL:  Ident authentication failed for user "postgres"
_SQL.ERROR_ FATAL:  Ident authentication failed for user "postgres"
_SQL.ERROR_  params="dbname='mydb1' user='postgres' host='localhost' sslmode=allow" ()
[SQL.ERROR] Failed to execute SELECT persons.person_uid, persons.first_name, persons.last_name, persons.gender, persons.email, persons.date_of_birth, persons.country_of_birth FROM persons  error=No connection to database
FAILED
[2020-05-17 19:30:04] process terminated successfully, elapsed time: 00.19s

添加于 2020 年 5 月 29 日

home/parallels/Documents/Ada Projects/Connect to a DB/obj/main
[SQL.ERROR] select failed: SELECT persons.person_uid, persons.first_name, persons.last_name, persons.gender, persons.email, persons.date_of_birth, persons.country_of_birth FROM persons PGRES_FATAL_ERROR ERROR:  relation "persons" does not exist
_SQL.ERROR_ LINE 1: ...persons.date_of_birth, persons.country_of_birth FROM persons
_SQL.ERROR_                                                                 ^
FAILED
[2020-05-29 22:40:11] process terminated successfully, elapsed time: 00.19s
postgres=# select * from persons;
              person_uid              | first_name | last_name  | gender |            email             | date_of_birth | country_of_birth 
--------------------------------------+------------+------------+--------+------------------------------+---------------+------------------
 afbf64be-e7d5-45a1-b8fb-1a9fd66e2765 | Audrie     | Vasyukov   | Female | avasyukovd6@domainmarket.com | 1988-11-24    | Guatemala
 ffda7264-1e54-428b-ae68-9ddb7b97702a | Nefen      | Philippard | Male   | nphilippardd7@economist.com  | 2006-11-08    | Russia
 169d5fb9-8d40-451e-8b02-cd1c3639fbed | Leonore    | Garthland  | Female | lgarthlandd8@furl.net        | 1991-03-23    | Canada
 e34f4f21-524c-4134-81d6-7fd1fd9a7537 | Yank       | Turfitt    | Male   | yturfittd9@exblog.jp         | 1990-02-07    | China
 57336d0e-34f2-4166-a100-7b468e96a521 | Benn       | Pawley     | Male   | bpawleyda@indiegogo.com      | 2006-10-28    | Russia
 b54a8411-3674-4432-b896-aaf35a10919b | Tod        | Easen      | Male   | teasend4@php.net             | 1990-08-24    | China
(6 rows)

user manual states that you must first generate Ada data types that represent the entities (tables, fields, etc.) of the database with which you interact in order to use functions like SQL_Select. This can be done using the gnatcoll_db2ada utility (see here);通过对数据库的某种反思或提供手写模式(用户手册中的示例)。以下是我自己创建示例的步骤。

安装依赖项:

$ sudo apt-get install postgresql libpq-dev

创建数据库用户(此处:deedee):

$ sudo -u postgres bash
postgres@debian: $ createuser --pwprompt deedee

克隆 gnatcoll-db:

$ git clone https://github.com/AdaCore/gnatcoll-db.git

构建并安装 gnatcoll-sql:

gnatcoll-db/sql $ make setup
gnatcoll-db/sql $ make
gnatcoll-db/sql $ sudo bash -c "PATH=$PATH:/opt/GNAT/2019/bin make install"

构建并安装 gnatcoll-postgress:

gnatcoll-db/postgress $ make setup
gnatcoll-db/postgress $ make
gnatcoll-db/postgress $ sudo bash -c "PATH=$PATH:/opt/GNAT/2019/bin make install"

构建并安装 gnatcoll_db2ada:

gnatcoll-db/gnatcoll_db2ada $ make setup DB_BACKEND=postgres
gnatcoll-db/gnatcoll_db2ada $ make
gnatcoll-db/gnatcoll_db2ada $ sudo bash -c "PATH=$PATH:/opt/GNAT/2019/bin make install"

该实用程序将安装在所有其他 GNAT 程序旁边:

$ which gnatcoll_postgres2ada
/opt/GNAT/2019/bin/gnatcoll_postgres2ada

为了使用该实用程序,我首先使用您提供的数据创建了一个小型数据库。我使用以下命令重新创建了 table persons

$ sudo -u postgres bash
postgres@debian: $ createdb mydb1
postgres@debian: $ psql mydb1 < persons.sql

persons.sql

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TYPE gender AS ENUM ('Male', 'Female');

CREATE TABLE persons (
    person_uid        uuid DEFAULT uuid_generate_v4 () PRIMARY KEY,
    first_name        VARCHAR (20) NOT NULL,
    last_name         VARCHAR (20) NOT NULL,
    gender            gender       NOT NULL,
    email             VARCHAR (50) NOT NULL,
    date_of_birth     DATE         NOT NULL,
    country_of_birth  VARCHAR (20) NOT NULL
);

INSERT INTO persons (
    first_name, 
    last_name, 
    gender, 
    email, 
    date_of_birth, 
    country_of_birth
)
VALUES
   ('Audrie' , 'Vasyukov'  , 'Female', 'avasyukovd6@domainmarket.com', '1988-11-24', 'Guatemala'),
   ('Nefen'  , 'Philippard', 'Male'  , 'nphilippardd7@economist.com' , '2006-11-08', 'Russia'   ),
   ('Leonore', 'Garthland' , 'Female', 'lgarthlandd8@furl.net'       , '1991-03-23', 'Canada'   ),
   ('Yank'   , 'Turfitt'   , 'Male'  , 'yturfittd9@exblog.jp'        , '1990-02-07', 'China'    ),
   ('Benn'   , 'Pawley'    , 'Male'  , 'bpawleyda@indiegogo.com'     , '2006-10-28', 'Russia'   ),
   ('Tod'    , 'Easen'     , 'Male'  , 'teasend4@php.net'            , '1990-08-24', 'China'    );

GRANT SELECT ON persons TO deedee;

然后我创建了一个数据库模式(参见用户手册)并生成了 Ada 代码:

$ gnatcoll_postgres2ada -dbmodel dschema.txt
$ ls
database.adb  database.ads  database_names.ads  dschema.txt

dschema.txt

| TABLE             | persons |          || The contents of person |
| person_uid        | TEXT    | PK       || Auto-generated id      |
| first_name        | TEXT    | NOT NULL || First name             |
| last_name         | TEXT    | NOT NULL || Last name              |
| gender            | TEXT    | NOT NULL || Gender                 |
| email             | TEXT    | NOT NULL || E-mail address         |
| date_of_birth     | DATE    | NOT NULL || Date of birth          |
| country_of_birth  | TEXT    | NOT NULL || Country of birth       |

我终于添加了一个跟踪配置文件(基于 GNATcoll 用户手册中的示例),调整了您的示例代码并使其与我自己的代码一起使用 table:

.gnatdebug(将跟踪信息写入标准错误;由 >&2 表示)

>&2
SQL.yes
SQL.SELECT=yes
SQL.LITE=yes

default.gpr

with "gnatcoll_postgres.gpr";

project Default is
   for Source_Dirs use ("src");
   for Object_Dir use "obj";
   for Main use ("main.adb");
end Default;

main.adb

with Ada.Text_IO;            use Ada.Text_IO;
with GNATCOLL.Traces;        use GNATCOLL.Traces;
with GNATCOLL.SQL.Postgres;  use GNATCOLL.SQL.Postgres;
with GNATCOLL.SQL.Exec;      use GNATCOLL.SQL.Exec;
with GNATCOLL.VFS;           use GNATCOLL.VFS;
with GNATCOLL.SQL.Inspect;   use GNATCOLL.SQL.Inspect;
with GNATCOLL.SQL;           use GNATCOLL.SQL;
with Database;

procedure Main is

   -- Datebase Description
   DB_Descr : GNATCOLL.SQL.Exec.Database_Description;

   -- Database Connection
   DB : GNATCOLL.SQL.Exec.Database_Connection;

   -- Used to Query the data
   Q : SQL_Query;

begin

   --  Enable tracing, so we can see if something goes wrong.
   GNATCOLL.Traces.Parse_Config_File (".gnatdebug");

   -- Database description.
   DB_Descr := GNATCOLL.SQL.Postgres.Setup
     (Database => "mydb1",
      User     => "deedee",
      Host     => "localhost",
      Password => "xxxx");

   -- Database connection.
   DB := DB_Descr.Build_Connection;

   -- Define the query.
   Q := SQL_Select
     (Fields =>
        Database.Persons.Person_Uid        &  --  0
        Database.Persons.First_Name        &  --  1
        Database.Persons.Last_Name         &  --  2
        Database.Persons.Gender            &  --  3
        Database.Persons.Email             &  --  4
        Database.Persons.Date_Of_Birth     &  --  5
        Database.Persons.Country_Of_Birth,    --  6
      From => Database.Persons);

   declare
      R : Forward_Cursor;
   begin

      --  Perform the actual query, show results if OK.
      R.Fetch (DB, Q);
      if Success (DB) then
         while Has_Row (R) loop

            Put_Line ("UUID . . : " & Value (R, 0));
            Put_Line ("Name . . : " & Value (R, 1) & " " & Value (R, 2));
            Put_Line ("Gender . : " & Value (R, 3));
            Put_Line ("E-Mail . : " & Value (R, 4));
            Put_Line ("Birth. . : " & Value (R, 5) & ", " & Value (R, 6));
            New_Line;

            Next (R);
         end loop;

      else
         Put_Line ("FAILED");
      end if;
   end;

   Free (DB);  --  for all connections you have opened
   Free (DB_Descr);

   GNATCOLL.Traces.Finalize;

end Main;

构建&输出

$ gprbuild -P default.gpr
[...]
$ ./obj/main
[SQL.SELECT] SELECT persons.person_uid, persons.first_name, persons.last_name, persons.gender, persons.email, persons.date_of_birth, persons.country_of_birth FROM persons (6 tuples) PGRES_TUPLES_OK
UUID . . : 564b6d18-5f99-4d6b-8098-d5ce79910107
Name . . : Audrie Vasyukov
Gender . : Female
E-Mail . : avasyukovd6@domainmarket.com
Birth. . : 1988-11-24, Guatemala

UUID . . : a4c2743a-40ad-409e-9af7-f21e7b91da05
Name . . : Nefen Philippard
Gender . : Male
E-Mail . : nphilippardd7@economist.com
Birth. . : 2006-11-08, Russia

UUID . . : 04aa6123-b317-4be3-a1af-8a01d43ee60f
Name . . : Leonore Garthland
Gender . : Female
E-Mail . : lgarthlandd8@furl.net
Birth. . : 1991-03-23, Canada

UUID . . : e43ec5ef-3cd2-4d3c-8f3e-106b7c2f2ccf
Name . . : Yank Turfitt
Gender . : Male
E-Mail . : yturfittd9@exblog.jp
Birth. . : 1990-02-07, China

UUID . . : 3e1d6431-62d5-4d4b-8333-a92a66575f9f
Name . . : Benn Pawley
Gender . : Male
E-Mail . : bpawleyda@indiegogo.com
Birth. . : 2006-10-28, Russia

UUID . . : ae60db02-298a-43d3-81a2-59fcf610c045
Name . . : Tod Easen
Gender . : Male
E-Mail . : teasend4@php.net
Birth. . : 1990-08-24, China

附录

我使用了默认的(非自定义的)基于主机的身份验证 (hba) 文件。

pg_hba.conf

# Database administrative login by Unix domain socket
local   all             postgres                                peer

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            md5
host    replication     all             ::1/128                 md5