{********************************************************} { } { Zeos Database Objects } { Plain interface to libpq.dll } { } { Copyright (c) 1999-2001 Sergey Seroukhov } { } {********************************************************} unit ZLibPgSql; interface uses {$IFNDEF LINUX}Windows,{$ELSE} Libc, {$ENDIF} Classes, ZSqlTypes; {$IFNDEF LINUX} {$INCLUDE ..\Zeos.inc} {$ELSE} {$INCLUDE ../Zeos.inc} {$ENDIF} {***************** Plain API Constants definition ****************} const {$IFNDEF LINUX} DEFAULT_DLL_LOCATION = 'libpq.dll'; {$ELSE} DEFAULT_DLL_LOCATION = 'libpq.so'; {$ENDIF} { Type Lengths } NAMEDATALEN = 32; { OIDNAMELEN should be set to NAMEDATALEN + sizeof(Oid) } OIDNAMELEN = 36; INV_WRITE = $00020000; INV_READ = $00040000; SEEK_SET = 0; SEEK_CUR = 1; SEEK_END = 2; {****************** Plain API Types definition *****************} type Oid = Integer; { Application-visible enum types } ConnStatusType = ( CONNECTION_OK, CONNECTION_BAD ); ExecStatusType = ( PGRES_EMPTY_QUERY, PGRES_COMMAND_OK, { a query command that doesn't return anything was executed properly by the backend } PGRES_TUPLES_OK, { a query command that returns tuples was executed properly by the backend, PGresult contains the result tuples } PGRES_COPY_OUT, { Copy Out data transfer in progress } PGRES_COPY_IN, { Copy In data transfer in progress } PGRES_BAD_RESPONSE, { an unexpected response was recv'd from the backend } PGRES_NONFATAL_ERROR, PGRES_FATAL_ERROR ); { String descriptions of the ExecStatusTypes } pgresStatus = array[$00..$ff] of PChar; { PGconn encapsulates a connection to the backend. The contents of this struct are not supposed to be known to applications. } PGconn = Pointer; PPGconn = Pointer; { PGresult encapsulates the result of a query (or more precisely, of a single SQL command --- a query string given to PQsendQuery can contain multiple commands and thus return multiple PGresult objects). The contents of this struct are not supposed to be known to applications. } PGresult = Pointer; PPGresult = Pointer; { PGnotify represents the occurrence of a NOTIFY message. Ideally this would be an opaque typedef, but it's so simple that it's unlikely to change. NOTE: in Postgres 6.4 and later, the be_pid is the notifying backend's, whereas in earlier versions it was always your own backend's PID. } PGnotify = packed record relname: array [0..NAMEDATALEN-1] of Char; { name of relation containing data } be_pid: Integer; { process id of backend } end; PPGnotify = ^PGnotify; { PQnoticeProcessor is the function type for the notice-message callback. } PQnoticeProcessor = procedure(arg: Pointer; message: PChar); cdecl; { Print options for PQprint() } { We can't use the conventional "bool", because we are designed to be included in a user's program, and user may already have that type defined. Pqbool, on the other hand, is unlikely to be used. } PPChar = array[00..$ff] of PChar; PQprintOpt = packed record header: TBool; { print output field headings and row count } align: TBool; { fill align the fields } standard: TBool; { old brain dead format } html3: TBool; { output html tables } expanded: TBool; { expand tables } pager: TBool; { use pager for output if needed } fieldSep: PChar; { field separator } tableOpt: PChar; { insert to HTML } caption: PChar; { HTML
} fieldName: PPChar; { null terminated array of repalcement field names } end; PPQprintOpt = ^PQprintOpt; { ---------------- Structure for the conninfo parameter definitions returned by PQconndefaults ---------------- } PQconninfoOption = packed record keyword: PChar; { The keyword of the option } envvar: PChar; { Fallback environment variable name } compiled: PChar; { Fallback compiled in default value } val: PChar; { Options value } lab: PChar; { Label for field in connect dialog } dispchar: PChar; { Character to display for this field in a connect dialog. Values are: "" Display entered value as is "*" Password field - hide value "D" Debug options - don't create a field by default } dispsize: Integer; { Field size in characters for dialog } end; PPQConninfoOption = ^PQconninfoOption; { ---------------- PQArgBlock -- structure for PQfn() arguments ---------------- } PQArgBlock = packed record len: Integer; isint: Integer; case u: Boolean of True: (ptr: PInteger); { can't use void (dec compiler barfs) } False: (_int: Integer); end; PPQArgBlock = ^PQArgBlock; {************** Plain API Function types definition *************} { === in fe-connect.c === } TPQconnectdb = function(ConnInfo: PChar): PPGconn; cdecl; TPQsetdbLogin = function(Host, Port, Options, Tty, Db, User, Passwd: PChar): PPGconn; cdecl; TPQconndefaults = function: PPQconninfoOption; cdecl; TPQfinish = procedure(Handle: PPGconn); cdecl; TPQreset = procedure(Handle: PPGconn); cdecl; TPQrequestCancel = function(Handle: PPGconn): Integer; cdecl; TPQdb = function(Handle: PPGconn): PChar; cdecl; TPQuser = function(Handle: PPGconn): PChar; cdecl; TPQpass = function(Handle: PPGconn): PChar; cdecl; TPQhost = function(Handle: PPGconn): PChar; cdecl; TPQport = function(Handle: PPGconn): PChar; cdecl; TPQtty = function(Handle: PPGconn): PChar; cdecl; TPQoptions = function(Handle: PPGconn): PChar; cdecl; TPQstatus = function(Handle: PPGconn): ConnStatusType; cdecl; TPQerrorMessage = function(Handle: PPGconn): PChar; cdecl; TPQsocket = function(Handle: PPGconn): Integer; cdecl; TPQbackendPID = function(Handle: PPGconn): Integer; cdecl; TPQtrace = procedure(Handle: PPGconn; DebugPort: Pointer); cdecl; TPQuntrace = procedure(Handle: PPGconn); cdecl; TPQsetNoticeProcessor = procedure(Handle: PPGconn; Proc: PQnoticeProcessor; Arg: Pointer); cdecl; { === in fe-exec.c === } TPQexec = function(Handle: PPGconn; Query: PChar): PPGresult; cdecl; TPQnotifies = function(Handle: PPGconn): PPGnotify; cdecl; TPQnotifyFree = procedure(Handle: PPGnotify);cdecl; TPQsendQuery = function(Handle: PPGconn; Query: PChar): Integer; cdecl; TPQgetResult = function(Handle: PPGconn): PPGresult; cdecl; TPQisBusy = function(Handle: PPGconn): Integer; cdecl; TPQconsumeInput = function(Handle: PPGconn): Integer; cdecl; TPQgetline = function(Handle: PPGconn; Str: PChar; length: Integer): Integer; cdecl; TPQputline = function(Handle: PPGconn; Str: PChar): Integer; cdecl; TPQgetlineAsync = function(Handle: PPGconn; Buffer: PChar; BufSize: Integer): Integer; cdecl; TPQputnbytes = function(Handle: PPGconn; Buffer: PChar; NBytes: Integer): Integer; cdecl; TPQendcopy = function(Handle: PPGconn): Integer; cdecl; TPQfn = function(Handle: PPGconn; fnid: Integer; result_buf, result_len: PInteger; result_is_int: Integer; args: PPQArgBlock; nargs: Integer): PPGresult; cdecl; TPQresultStatus = function(Result: PPGresult): ExecStatusType; cdecl; TPQresultErrorMessage = function(Result: PPGresult): PChar; cdecl; TPQntuples = function(Result: PPGresult): Integer; cdecl; TPQnfields = function(Result: PPGresult): Integer; cdecl; TPQbinaryTuples = function(Result: PPGresult): Integer; cdecl; TPQfname = function(Result: PPGresult; field_num: Integer): PChar; cdecl; TPQfnumber = function(Result: PPGresult; field_name: PChar): Integer; cdecl; TPQftype = function(Result: PPGresult; field_num: Integer): Oid; cdecl; TPQfsize = function(Result: PPGresult; field_num: Integer): Integer; cdecl; TPQfmod = function(Result: PPGresult; field_num: Integer): Integer; cdecl; TPQcmdStatus = function(Result: PPGresult): PChar; cdecl; TPQoidValue = function(Result: PPGresult): Oid; cdecl; TPQoidStatus = function(Result: PPGresult): PChar; cdecl; TPQcmdTuples = function(Result: PPGresult): PChar; cdecl; TPQgetvalue = function(Result: PPGresult; tup_num, field_num: Integer): PChar; cdecl; TPQgetlength = function(Result: PPGresult; tup_num, field_num: Integer): Integer; cdecl; TPQgetisnull = function(Result: PPGresult; tup_num, field_num: Integer): Integer; cdecl; TPQclear = procedure(Result: PPGresult); cdecl; TPQmakeEmptyPGresult = function(Handle: PPGconn; status: ExecStatusType): PPGresult; cdecl; { === in fe-lobj.c === } Tlo_open = function(Handle: PPGconn; lobjId: Oid; mode: Integer): Integer; cdecl; Tlo_close = function(Handle: PPGconn; fd: Integer): Integer; cdecl; Tlo_read = function(Handle: PPGconn; fd: Integer; buf: PChar; len: Integer): Integer; cdecl; Tlo_write = function(Handle: PPGconn; fd: Integer; buf: PChar; len: Integer): Integer; cdecl; Tlo_lseek = function(Handle: PPGconn; fd, offset, whence: Integer): Integer; cdecl; Tlo_creat = function(Handle: PPGconn; mode: Integer): Oid; cdecl; Tlo_tell = function(Handle: PPGconn; fd: Integer): Integer; cdecl; Tlo_unlink = function(Handle: PPGconn; lobjId: Oid): Integer; cdecl; Tlo_import = function(Handle: PPGconn; filename: PChar): Oid; cdecl; Tlo_export = function(Handle: PPGconn; lobjId: Oid; filename: PChar): Integer; cdecl; {************* Plain API Function variables definition ************} var { === in fe-connect.c === } PQconnectdb: TPQconnectdb; PQsetdbLogin: TPQsetdbLogin; PQconndefaults: TPQconndefaults; PQfinish: TPQfinish; PQreset: TPQreset; PQrequestCancel: TPQrequestCancel; PQdb: TPQdb; PQuser: TPQuser; PQpass: TPQpass; PQhost: TPQhost; PQport: TPQport; PQtty: TPQtty; PQoptions: TPQoptions; PQstatus: TPQstatus; PQerrorMessage: TPQerrorMessage; PQsocket: TPQsocket; PQbackendPID: TPQbackendPID; PQtrace: TPQtrace; PQuntrace: TPQuntrace; PQsetNoticeProcessor: TPQsetNoticeProcessor; { === in fe-exec.c === } PQexec: TPQexec; PQnotifies: TPQnotifies; PQnotifyFree: TPQnotifyFree; PQsendQuery: TPQsendQuery; PQgetResult: TPQgetResult; PQisBusy: TPQisBusy; PQconsumeInput: TPQconsumeInput; PQgetline: TPQgetline; PQputline: TPQputline; PQgetlineAsync: TPQgetlineAsync; PQputnbytes: TPQputnbytes; PQendcopy: TPQendcopy; PQfn: TPQfn; PQresultStatus: TPQresultStatus; PQresultErrorMessage: TPQresultErrorMessage; PQntuples: TPQntuples; PQnfields: TPQnfields; PQbinaryTuples: TPQbinaryTuples; PQfname: TPQfname; PQfnumber: TPQfnumber; PQftype: TPQftype; PQfsize: TPQfsize; PQfmod: TPQfmod; PQcmdStatus: TPQcmdStatus; PQoidValue: TPQoidValue; PQoidStatus: TPQoidStatus; PQcmdTuples: TPQcmdTuples; PQgetvalue: TPQgetvalue; PQgetlength: TPQgetlength; PQgetisnull: TPQgetisnull; PQclear: TPQclear; PQmakeEmptyPGresult: TPQmakeEmptyPGresult; { === in fe-lobj.c === } lo_open: Tlo_open; lo_close: Tlo_close; lo_read: Tlo_read; lo_write: Tlo_write; lo_lseek: Tlo_lseek; lo_creat: Tlo_creat; lo_tell: Tlo_tell; lo_unlink: Tlo_unlink; lo_import: Tlo_import; lo_export: Tlo_export; function PgSqlLoadLib: Boolean; const DLL: string = DEFAULT_DLL_LOCATION; {$IFNDEF LINUX} hDLL: THandle = 0; {$ELSE} hDLL: Pointer = nil; {$ENDIF} implementation uses SysUtils, ZDBaseConst; function TryGetProcAddr(ProcName: PChar): Pointer; begin {$IFDEF LINUX} Result := dlsym(hDLL, ProcName); if Result = nil then {$ELSE} Result := GetProcAddress(hDLL, ProcName); if not Assigned(Result) then {$ENDIF} raise Exception.Create(ProcName + ' not found'); end; { Initialize PostgreSQL dynamic library } function PgSqlLoadLib: Boolean; begin {$IFDEF LINUX} if hDLL = nil then hDLL := dlopen(PChar(DLL), RTLD_GLOBAL); if hDLL <> nil then {$ELSE} if hDLL = 0 then hDLL := LoadLibrary(PChar(DLL)); if hDLL <> 0 then {$ENDIF} begin { === in fe-connect.c === } @PQconnectdb := TryGetProcAddr('PQconnectdb'); @PQsetdbLogin := TryGetProcAddr('PQsetdbLogin'); @PQconndefaults := TryGetProcAddr('PQconndefaults'); @PQfinish := TryGetProcAddr('PQfinish'); @PQreset := TryGetProcAddr('PQreset'); @PQrequestCancel := TryGetProcAddr('PQrequestCancel'); @PQdb := TryGetProcAddr('PQdb'); @PQuser := TryGetProcAddr('PQuser'); @PQpass := TryGetProcAddr('PQpass'); @PQhost := TryGetProcAddr('PQhost'); @PQport := TryGetProcAddr('PQport'); @PQtty := TryGetProcAddr('PQtty'); @PQoptions := TryGetProcAddr('PQoptions'); @PQstatus := TryGetProcAddr('PQstatus'); @PQerrorMessage := TryGetProcAddr('PQerrorMessage'); @PQsocket := TryGetProcAddr('PQsocket'); @PQbackendPID := TryGetProcAddr('PQbackendPID'); @PQtrace := TryGetProcAddr('PQtrace'); @PQuntrace := TryGetProcAddr('PQuntrace'); @PQsetNoticeProcessor := TryGetProcAddr('PQsetNoticeProcessor'); { === in fe-exec.c === } @PQexec := TryGetProcAddr('PQexec'); @PQnotifies := TryGetProcAddr('PQnotifies'); {$IFNDEF LINUX} @PQnotifyFree := TryGetProcAddr('PQnotifyFree'); {$ENDIF} @PQsendQuery := TryGetProcAddr('PQsendQuery'); @PQgetResult := TryGetProcAddr('PQgetResult'); @PQisBusy := TryGetProcAddr('PQisBusy'); @PQconsumeInput := TryGetProcAddr('PQconsumeInput'); @PQgetline := TryGetProcAddr('PQgetline'); @PQputline := TryGetProcAddr('PQputline'); @PQgetlineAsync := TryGetProcAddr('PQgetlineAsync'); @PQputnbytes := TryGetProcAddr('PQputnbytes'); @PQendcopy := TryGetProcAddr('PQendcopy'); @PQfn := TryGetProcAddr('PQfn'); @PQresultStatus := TryGetProcAddr('PQresultStatus'); @PQresultErrorMessage := TryGetProcAddr('PQresultErrorMessage'); @PQntuples := TryGetProcAddr('PQntuples'); @PQnfields := TryGetProcAddr('PQnfields'); @PQbinaryTuples := TryGetProcAddr('PQbinaryTuples'); @PQfname := TryGetProcAddr('PQfname'); @PQfnumber := TryGetProcAddr('PQfnumber'); @PQftype := TryGetProcAddr('PQftype'); @PQfsize := TryGetProcAddr('PQfsize'); @PQfmod := TryGetProcAddr('PQfmod'); @PQcmdStatus := TryGetProcAddr('PQcmdStatus'); @PQoidValue := TryGetProcAddr('PQoidValue'); @PQoidStatus := TryGetProcAddr('PQoidStatus'); @PQcmdTuples := TryGetProcAddr('PQcmdTuples'); @PQgetvalue := TryGetProcAddr('PQgetvalue'); @PQgetlength := TryGetProcAddr('PQgetlength'); @PQgetisnull := TryGetProcAddr('PQgetisnull'); @PQclear := TryGetProcAddr('PQclear'); @PQmakeEmptyPGresult := TryGetProcAddr('PQmakeEmptyPGresult'); { === in fe-lobj.c === } @lo_open := TryGetProcAddr('lo_open'); @lo_close := TryGetProcAddr('lo_close'); @lo_read := TryGetProcAddr('lo_read'); @lo_write := TryGetProcAddr('lo_write'); @lo_lseek := TryGetProcAddr('lo_lseek'); @lo_creat := TryGetProcAddr('lo_creat'); @lo_tell := TryGetProcAddr('lo_tell'); @lo_unlink := TryGetProcAddr('lo_unlink'); @lo_import := TryGetProcAddr('lo_import'); @lo_export := TryGetProcAddr('lo_export'); Result := True; end else raise Exception.Create(Format(SLibraryNotFound,[DLL])); end; initialization finalization {$IFDEF LINUX} if hDLL <> nil then dlclose(hDLL); hDLL := nil; {$ELSE} if hDLL <> 0 then FreeLibrary(hDLL); {$ENDIF} end.