free pascal訪問postgresql數據庫

根據fp自帶例子修改sql

一、testpg1.ppbash

Program testpg;

{ Demo program to test pascal connection with postgres database }
{ Translated from the testlibpq example program of PostGreSQL   }

Uses postgres,strings;


Procedure exit_nicely(Conn : PPGconn);

begin
  PQfinish(conn);
  halt(1);
end;


Var
  pghost,pgport,pgoptions,pgtty,dbname : Pchar;
  nFields,i,j : longint;
  conn : PPGConn;
  res : PPGresult;

begin
  pghost := 'localhost';        { host name of the backend server }
  pgport := '5432';        { port of the backend server }
  pgoptions := NiL;     { special options to start up the backend server }
  pgtty := NiL;         { debugging tty for the backend server }
  dbName := 'template1';

  { make a connection to the database }
  conn := PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);

  { check to see that the backend connection was successfully made }
  if (PQstatus(conn) = CONNECTION_BAD) then
    begin
    Writeln (stderr, 'Connection to database ',dbname,' failed.');
    Writeln (stderr, PQerrorMessage(conn));
    exit_nicely(conn);
    end;


  { start a transaction block }
  res := PQexec(conn, 'BEGIN');
  if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
    begin
    Writeln (stderr, 'BEGIN command failed');
    PQclear(res);
    exit_nicely(conn);
    end;

  {
   * should PQclear PGresult whenever it is no longer needed to avoid
   * memory leaks
   }
  PQclear(res);

  {
   * fetch instances from the pg_database, the system catalog of
   * databases
   }
  res := PQexec(conn, 'DECLARE myportal CURSOR FOR select * from pg_database');
  if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
    begin
    Writeln (stderr, 'DECLARE CURSOR command failed');
    PQclear(res);
    exit_nicely(conn);
    end;
  PQclear(res);

  res := PQexec(conn, 'FETCH ALL in myportal');
  if (PQresultStatus(res) <> PGRES_TUPLES_OK) then
    begin
    Writeln (stderr, 'FETCH ALL command didn''t return tuples properly');
    PQclear(res);
    exit_nicely(conn);
    end;

  { first, print out the attribute names }
  nFields := PQnfields(res);
  for i := 0 to nFields-1 do
    Write (PQfname(res, i),space (15-strlen(PQfname(res, i))) );
  writeln;
  writeln;

  { next, print out the instances }
  for i := 0 to PQntuples(res)-1 do
    begin
    for j := 0 to nFields-1 do
      write(PQgetvalue(res, i, j),space (15-strlen(PQgetvalue(res, i,j))));
    writeln;
    end;

  PQclear(res);

  { close the portal }
  res := PQexec(conn, 'CLOSE myportal');
  PQclear(res);

  { end the transaction }
  res := PQexec(conn, 'END');
  PQclear(res);

  { close the connection to the database and cleanup }
  PQfinish(conn);
end.

編譯運行:dom

$ fpc testpg1.pp 
Free Pascal Compiler version 3.0.4 [2017/10/03] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling testpg1.pp
Linking testpg1
/usr/bin/ld: 警告: link.res 含有輸出節;您忘記了 -T?
105 lines compiled, 0.1 sec
~/prg/mypas/psqlExample$ ./testpg1 
datname        datdba         encoding       datcollate     datctype       datistemplate  datallowconn   datconnlimit   datlastsysoid  datfrozenxid   datminmxid     dattablespace  datacl         

template1      10             6              zh_CN.UTF-8    zh_CN.UTF-8    t              t              -1             12410          656            1              1663           {=c/postgres,postgres=CTc/postgres}                                                                                                                                                                                                                                            
template0      10             6              zh_CN.UTF-8    zh_CN.UTF-8    t              f              -1             12410          656            1              1663           {=c/postgres,postgres=CTc/postgres}                                                                                                                                                                                                                                            
postgres       10             6              zh_CN.UTF-8    zh_CN.UTF-8    f              t              -1             12410          656            1              1663                          
mymotif        16393          6              zh_CN.UTF-8    zh_CN.UTF-8    f              t              -1             12410          656            1              16394                         
mydb           16393          6              zh_CN.UTF-8    zh_CN.UTF-8    f              t              -1             12410          656            1              16396                         
testdb         16393          6              zh_CN.UTF-8    zh_CN.UTF-8    f              t              -1             12410          656            1              16394                         
drupal8.2.1    16393          6              zh_CN.UTF-8    zh_CN.UTF-8    f              t              -1             12410          656            1              16473

2、testpg2.ppsocket

Program testpg;

{ Demo program to test pascal connection with postgres database }
{ Translated from the testlibpq example program of PostGreSQL   }

Uses postgres,strings;


Procedure exit_nicely(Conn : PPGconn);

begin
  PQfinish(conn);
  halt(1);
end;


Var
  pghost,pgport,pgoptions,pgtty,dbname : Pchar;
  nFields,i : longint;
  conn : PPGConn;
  res : PPGresult;
  dummy : string;

begin
  pghost := 'localhost';        { host name of the backend server }
  pgport := '5432';        { port of the backend server }
  pgoptions := NiL;     { special options to start up the backend server }
  pgtty := NiL;         { debugging tty for the backend server }
  if paramcount=1 then
    begin
    dummy:=paramstr(1)+#0;
    dbname:=@dummy[1];
    end
  else
    dbName := 'testdb';

  { make a connection to the database }
  conn := PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);

  { check to see that the backend connection was successfully made }
  if (PQstatus(conn) = CONNECTION_BAD) then
    begin
    Writeln (stderr, 'Connection to database ',dbname,' failed.');
    Writeln (stderr, PQerrorMessage(conn));
    exit_nicely(conn);
    end;

  res := PQexec(conn, 'select * from userdeatail');
  if (PQresultStatus(res) <> PGRES_TUPLES_OK) then
    begin
    Writeln (stderr, 'select command failed.');
    PQclear(res);
    exit_nicely(conn);
    end;


  { first, print out the attribute names }
  nFields := PQnfields(res);
  Write ('|',PQfname(res, 0),space (4-strlen(PQfname(res, 0))) );
  Write ('|',PQfname(res, 1),space (20-strlen(PQfname(res, 1))) );
  Write ('|',PQfname(res, 2),space (40-strlen(PQfname(res, 2))) );
  writeln ('|');
  writeln ('+----+--------------------+----------------------------------------+');

  { next, print out the instances }
  for i := 0 to PQntuples(res)-1 do
    begin
    write('|',PQgetvalue(res, i, 0),space (4-strlen(PQgetvalue(res, i,0))));
    write('|',PQgetvalue(res, i, 1),space (20-strlen(PQgetvalue(res, i,1))));
    write('|',PQgetvalue(res, i, 2),space (40-strlen(PQgetvalue(res, i,2))));
    writeln ('|');
    end;

  PQclear(res);

  { close the connection to the database and cleanup }
  PQfinish(conn);
end.

testdb庫中表:tcp

CREATE TABLE userdeatail
(
  uid integer,
  intro character varying(30),
  profile character varying(30)
);

編譯運行:ide

$ fpc testpg2.pp 
Free Pascal Compiler version 3.0.4 [2017/10/03] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling testpg2.pp
testpg2.pp(19,3) Note: Local variable "nFields" is assigned but never used
Linking testpg2
/usr/bin/ld: 警告: link.res 含有輸出節;您忘記了 -T?
78 lines compiled, 0.1 sec
1 note(s) issued
$ ./testpg2 
|uid |intro               |profile                                 |
+----+--------------------+----------------------------------------+
|11  |wxw                 |pppp                                    |

3、一些出錯的處理:
(1)編譯鏈接時找不到-lpq庫:
$ fpc testpg1.pp
/usr/bin/ld: 找不到 -lpq
testpg1.pp(107,1) Error: Error while linking
testpg1.pp(107,1) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
改成:
 $ fpc testpg1.pp -Fl/opt/PostgreSQL/10/lib(/opt/PostgreSQL/10爲PostgreSQL實際安裝的路徑)
或在Makefile中處理:
追加環境變量:export PGLIBDIR=/opt/PostgreSQL/10/lib
在Makefile中增長下面內容:
ifdef PGLIBDIR
override FPCOPT+=$(addprefix -Fl,$(PGLIBDIR))
endifpost

(2)、出現Unix domain socket鏈接錯誤:
$ ./testpg1 
Connection to database template1 failed.
could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
有兩種處理方法:
一、指定pg Unix domain socket的位置
在.bashrc中設置環境變量$PGHOST:export PGHOST=/tmp
二、改用tcp/ip鏈接方式:
 即pghost := NiL; 改成  pghost := 'localhost'; {或pghost := '127.0.0.1'}fetch

(3)、出現用戶名密碼錯誤
$ ./testpg1
Connection to database template1 failed.
fe_sendauth: no password supplied
處理方法:PQsetdb,改成PQsetdbLogin
即:conn=PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
改成:conn=PQsetdbLogin(pghost,pgport,pgoptions,pgtty,dbname,user,pwd)ui

修改後代碼testpg1.ppspa

Program testpg;

{ Demo program to test pascal connection with postgres database }
{ Translated from the testlibpq example program of PostGreSQL   }

Uses postgres,strings;


Procedure exit_nicely(Conn : PPGconn);

begin
  PQfinish(conn);
  halt(1);
end;


Var
  pghost,pgport,pgoptions,pgtty,dbname,myuser,passwd : Pchar;
  nFields,i,j : longint;
  conn : PPGConn;
  res : PPGresult;

begin
  pghost := 'localhost';        { host name of the backend server }
  pgport := NiL;        { port of the backend server }
  pgoptions := NiL;     { special options to start up the backend server }
  pgtty := NiL;         { debugging tty for the backend server }
  dbName := 'template1';
  myuser:='postgres';
  passwd:='wxwpxh';
  { make a connection to the database }
  {conn := PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);}
  conn := PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName,myuser,passwd);

  { check to see that the backend connection was successfully made }
  if (PQstatus(conn) = CONNECTION_BAD) then
    begin
    Writeln (stderr, 'Connection to database ',dbname,' failed.');
    Writeln (stderr, PQerrorMessage(conn));
    exit_nicely(conn);
    end;


  { start a transaction block }
  res := PQexec(conn, 'BEGIN');
  if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
    begin
    Writeln (stderr, 'BEGIN command failed');
    PQclear(res);
    exit_nicely(conn);
    end;

  {
   * should PQclear PGresult whenever it is no longer needed to avoid
   * memory leaks
   }
  PQclear(res);

  {
   * fetch instances from the pg_database, the system catalog of
   * databases
   }
  res := PQexec(conn, 'DECLARE myportal CURSOR FOR select * from pg_database');
  if (PQresultStatus(res) <> PGRES_COMMAND_OK) then
    begin
    Writeln (stderr, 'DECLARE CURSOR command failed');
    PQclear(res);
    exit_nicely(conn);
    end;
  PQclear(res);

  res := PQexec(conn, 'FETCH ALL in myportal');
  if (PQresultStatus(res) <> PGRES_TUPLES_OK) then
    begin
    Writeln (stderr, 'FETCH ALL command didn''t return tuples properly');
    PQclear(res);
    exit_nicely(conn);
    end;

  { first, print out the attribute names }
  nFields := PQnfields(res);
  for i := 0 to nFields-1 do
    Write (PQfname(res, i),space (15-strlen(PQfname(res, i))) );
  writeln;
  writeln;

  { next, print out the instances }
  for i := 0 to PQntuples(res)-1 do
    begin
    for j := 0 to nFields-1 do
      write(PQgetvalue(res, i, j),space (15-strlen(PQgetvalue(res, i,j))));
    writeln;
    end;

  PQclear(res);

  { close the portal }
  res := PQexec(conn, 'CLOSE myportal');
  PQclear(res);

  { end the transaction }
  res := PQexec(conn, 'END');
  PQclear(res);

  { close the connection to the database and cleanup }
  PQfinish(conn);
end.

修改後testpg2.pp代碼:

Program testpg;

{ Demo program to test pascal connection with postgres database }
{ Translated from the testlibpq example program of PostGreSQL   }

Uses postgres,strings;


Procedure exit_nicely(Conn : PPGconn);

begin
  PQfinish(conn);
  halt(1);
end;


Var
  pghost,pgport,pgoptions,pgtty,dbname,myuser,passwd : Pchar;
  nFields,i : longint;
  conn : PPGConn;
  res : PPGresult;
  dummy : string;

begin
  pghost := 'localhost';        { host name of the backend server }
  pgport := '5432';        { port of the backend server }
  pgoptions := NiL;     { special options to start up the backend server }
  pgtty := NiL;         { debugging tty for the backend server }
  myuser:='mymotif';
  passwd:='wxwpxh';

  if paramcount=1 then
    begin
    dummy:=paramstr(1)+#0;
    dbname:=@dummy[1];
    end
  else
    dbName := 'testdb';


  { make a connection to the database }
  {conn := PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);}
  conn := PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName,myuser,passwd);

  { check to see that the backend connection was successfully made }
  if (PQstatus(conn) = CONNECTION_BAD) then
    begin
    Writeln (stderr, 'Connection to database ',dbname,' failed.');
    Writeln (stderr, PQerrorMessage(conn));
    exit_nicely(conn);
    end;

  res := PQexec(conn, 'select * from userdeatail');
  if (PQresultStatus(res) <> PGRES_TUPLES_OK) then
    begin
    Writeln (stderr, 'select command failed.');
    PQclear(res);
    exit_nicely(conn);
    end;


  { first, print out the attribute names }
  nFields := PQnfields(res);
  Write ('|',PQfname(res, 0),space (4-strlen(PQfname(res, 0))) );
  Write ('|',PQfname(res, 1),space (20-strlen(PQfname(res, 1))) );
  Write ('|',PQfname(res, 2),space (40-strlen(PQfname(res, 2))) );
  writeln ('|');
  writeln ('+----+--------------------+----------------------------------------+');

  { next, print out the instances }
  for i := 0 to PQntuples(res)-1 do
    begin
    write('|',PQgetvalue(res, i, 0),space (4-strlen(PQgetvalue(res, i,0))));
    write('|',PQgetvalue(res, i, 1),space (20-strlen(PQgetvalue(res, i,1))));
    write('|',PQgetvalue(res, i, 2),space (40-strlen(PQgetvalue(res, i,2))));
    writeln ('|');
    end;

  PQclear(res);

  { close the connection to the database and cleanup }
  PQfinish(conn);
end.
相關文章
相關標籤/搜索