532d8b0c33da011422412ba54981877a221498b9
[sdk] / eda / drivers / PostgreSQL.ec
1 import "eda"
2
3 #include "libpq-fe.h"
4
5 static class PgSQLDataSource : DataSourceDriver
6 {
7    class_property(name) = "PostgreSQL";
8
9    String locator;
10    //PGconn * conn;
11
12    String BuildLocator(DataSource ds)
13    {
14       char r[MAX_F_STRING];
15       char t[MAX_LOCATION];
16
17       /*
18       host
19       hostaddr
20       port
21       dbname
22       user
23       password
24       connect_timeout
25       options
26       tty
27       sslmode
28       requiressl
29       krbsrvname
30       service
31       */
32
33       r[0] = '\0';
34       if(ds.host)
35          sprintf(t, "host=%s ", ds.host), strcat(r, t);
36       if(ds.port)
37          sprintf(t, "port=%s ", ds.port), strcat(r, t);
38       if(ds.user)
39          sprintf(t, "user=%s ", ds.user), strcat(r, t);
40       if(ds.pass)
41          sprintf(t, "password=%s ", ds.pass), strcat(r, t);
42       return CopyString(r);
43    }
44
45    uint GetDatabasesCount()
46    {
47       return 0;
48    }
49
50    ~PgSQLDataSource()
51    {
52       /*if(conn)
53          PQfinish(conn);*/
54    }
55
56    bool Connect(const String locator)
57    {
58       /*char loc[16384];
59       strcpy(loc, locator);
60       strcat(loc, " dbname=postgres ");*/
61       this.locator = CopyString(locator);
62       /*conn = PQconnectdb(locator);
63       if(PQstatus(conn) != CONNECTION_OK)
64       {
65          Logf("Connection to database failed: %s", PQerrorMessage(conn));
66          return false;
67       }*/
68       return true;
69    }
70
71    void Status()
72    {
73       Log("Status: Feeling groovy!\n");
74    }
75
76    bool RenameDatabase(const String name, const String rename)
77    {
78    }
79
80    bool DeleteDatabase(const String name)
81    {
82    }
83
84    Database OpenDatabase(const String name, CreateOptions createOptions)
85    {
86       char dbLocator[MAX_F_STRING];
87       PGconn * conn;
88       PgSQLDatabase db;
89
90       //PGconn *PQconnectStart(const char *conninfo);
91       //PostgresPollingStatusType PQconnectPoll(PGconn *conn);
92       //void PQreset(PGconn *conn);
93       //int PQresetStart(PGconn *conn);
94       //PostgresPollingStatusType PQresetPoll(PGconn *conn);
95
96       /*switch(PQstatus(conn))
97       {
98          case CONNECTION_STARTED:
99             feedback = "Connecting...";
100             break;
101          case CONNECTION_MADE:
102             feedback = "Connected to server...";
103             break;
104          case CONNECTION_AWAITING_RESPONSE:
105          case CONNECTION_AUTH_OK:
106          case CONNECTION_SSL_STARTUP:
107          case CONNECTION_SETENV:
108          default:
109             feedback = "Connecting...";
110       }*/
111
112       sprintf(dbLocator, "%s dbname=%s ", locator, name);
113       conn = PQconnectdb(dbLocator);
114       if(PQstatus(conn) != CONNECTION_OK)
115       {
116          Logf("Connection to database failed: %s", PQerrorMessage(conn));
117          return null;
118       }
119       db = PgSQLDatabase { conn = conn };
120       return db;
121    }
122 }
123
124 class PgSQLDatabase : Database
125 {
126    PGconn * conn;
127
128    /*
129    char *PQuser(const PGconn *conn);
130    char *PQpass(const PGconn *conn);
131    char *PQhost(const PGconn *conn);
132    char *PQport(const PGconn *conn);
133    char *PQtty(const PGconn *conn);
134    char *PQoptions(const PGconn *conn);
135    ConnStatusType PQstatus(const PGconn *conn);
136    PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
137    const char *PQparameterStatus(const PGconn *conn, const char *paramName);
138    int PQprotocolVersion(const PGconn *conn);
139    int PQserverVersion(const PGconn *conn);
140    char *PQerrorMessage(const PGconn *conn);
141    int PQsocket(const PGconn *conn);
142    int PQbackendPID(const PGconn *conn);
143    SSL *PQgetssl(const PGconn *conn);
144    */
145
146    ~PgSQLDatabase()
147    {
148       if(conn)
149          PQfinish(conn);
150    }
151
152    String GetName()
153    {
154       return conn ? PQdb(conn) : null;
155    }
156
157    uint ObjectsCount(ObjectType type)
158    {
159       // TODO
160       return 0;
161    }
162
163    bool RenameObject(ObjectType type, const String name, const String rename)
164    {
165       // TODO
166       return false;
167    }
168
169    bool DeleteObject(ObjectType type, const String name)
170    {
171       // TODO
172       return false;
173    }
174
175    Table OpenTable(const String name, OpenOptions options)
176    {
177       char t[MAX_F_STRING];
178       String sql = null;
179       switch(options.type)
180       {
181          case queryRows:
182             break;
183          case tableRows:
184             sprintf(t, "SELECT * FROM %s;", name);
185             sql = t;
186             break;
187          case viewRows:
188          case processesList:
189          case databasesList:
190          case tablesList:
191             break;
192          case fieldsList:
193             break;
194       }
195       if(sql)
196       {
197          ExecStatusType status;
198          PgSQLTable tbl { };
199          tbl.res = PQexec(conn, sql);
200          //PGresult *PQexecParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes,
201          //             const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
202          //PGresult *PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes);
203          //PGresult *PQexecPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues,
204          //             const int *paramLengths, const int *paramFormats, int resultFormat);
205          //PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName);
206          //PGresult *PQdescribePortal(PGconn *conn, const char *portalName);
207          //char *PQresultErrorMessage(const PGresult *res);
208          //char *PQresultErrorField(const PGresult *res, int fieldcode);
209          /*
210          PG_DIAG_SEVERITY
211          PG_DIAG_SQLSTATE
212          PG_DIAG_MESSAGE_PRIMARY
213          PG_DIAG_MESSAGE_DETAIL
214          PG_DIAG_MESSAGE_HINT
215          PG_DIAG_STATEMENT_POSITION
216          PG_DIAG_INTERNAL_POSITION
217          PG_DIAG_INTERNAL_QUERY
218          PG_DIAG_CONTEXT
219          PG_DIAG_SOURCE_FILE
220          PG_DIAG_SOURCE_LINE
221          PG_DIAG_SOURCE_FUNCTION
222          */
223          //PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);
224
225          //asynch
226          //int PQsendQuery(PGconn *conn, const char *command);
227          //int PQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes,
228          //       const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
229          //int PQsendPrepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes);
230          //int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues,
231          //       const int *paramLengths, const int *paramFormats, int resultFormat);
232          //int PQsendDescribePrepared(PGconn *conn, const char *stmtName);
233          //int PQsendDescribePortal(PGconn *conn, const char *portalName);
234          //PGresult *PQgetResult(PGconn *conn);
235          //int PQconsumeInput(PGconn *conn);
236          //int PQisBusy(PGconn *conn);
237          //int PQsetnonblocking(PGconn *conn, int arg);
238          //int PQisnonblocking(const PGconn *conn);
239          //int PQflush(PGconn *conn);
240          //PGcancel *PQgetCancel(PGconn *conn);
241          //void PQfreeCancel(PGcancel *cancel);
242          //int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);
243          //int PQrequestCancel(PGconn *conn);
244
245          if(tbl.res)
246             status = PQresultStatus(tbl.res);
247          else
248             status = PGRES_FATAL_ERROR;
249          switch(status)
250          {
251             case PGRES_EMPTY_QUERY:    //The string sent to the server was empty.
252             case PGRES_COPY_OUT:       //Copy Out (from server) data transfer started.
253             case PGRES_COPY_IN:        //Copy In (to server) data transfer started.
254             case PGRES_BAD_RESPONSE:   //The server's response was not understood.
255             case PGRES_NONFATAL_ERROR: //A nonfatal error (a notice or warning) occurred.
256             case PGRES_FATAL_ERROR:    //A fatal error occurred.
257             case PGRES_COMMAND_OK:     //Successful completion of a command returning no data.
258                Logf("Open table failed: %s", PQresStatus(status));
259                break;
260             case PGRES_TUPLES_OK:      //Successful completion of a command returning data (such as a SELECT or SHOW).
261                return tbl;
262          }
263          //int PQbinaryTuples(const PGresult *res);   // returns 0 for textual and 1 for binary
264          delete tbl;
265       }
266       return null;
267    }
268 }
269
270 class PgSQLTable : Table
271 {
272    PGresult * res;
273
274    ~PgSQLTable()
275    {
276       if(res)
277          PQclear(res);
278    }
279
280    String GetName()
281    {
282       return null;
283    }
284
285    Field GetFirstField()
286    {
287       return null;
288    }
289
290    uint GetFieldsCount()
291    {
292       return res ? PQnfields(res) : 0;
293    }
294
295    uint GetRowsCount()
296    {
297       return res ? PQntuples(res) : 0;
298    }
299
300    DriverRow CreateRow()
301    {
302       return null;
303    }
304
305    Field AddField(const String name, Class type, int length)
306    {
307       return null;
308    }
309
310    //char *PQfname(const PGresult *res, int column_number);
311    //Oid PQftable(const PGresult *res, int column_number);
312    //int PQftablecol(const PGresult *res, int column_number);
313    //int PQfformat(const PGresult *res, int column_number);
314    //Oid PQftype(const PGresult *res, int column_number);
315    //int PQfmod(const PGresult *res, int column_number);
316    //int PQfsize(const PGresult *res, int column_number);
317    //int PQbinaryTuples(const PGresult *res);
318    //char *PQgetvalue(const PGresult *res, int row_number, int column_number);
319    //int PQgetisnull(const PGresult *res, int row_number, int column_number);
320    //int PQgetlength(const PGresult *res, int row_number, int column_number);
321    //int PQnparams(const PGresult *res);
322    //Oid PQparamtype(const PGresult *res, int param_number);
323    //void PQprint(FILE *fout,      /* output stream */ const PGresult *res, const PQprintOpt *po);
324
325    //char *PQcmdStatus(PGresult *res);
326    //char *PQcmdTuples(PGresult *res);
327    //Oid PQoidValue(const PGresult *res);
328    //char *PQoidStatus(const PGresult *res);
329
330    //size_t PQescapeStringConn (PGconn *conn, char *to, const char *from, size_t length, int *error);
331    //size_t PQescapeString (char *to, const char *from, size_t length);
332
333    //unsigned char *PQescapeByteaConn(PGconn *conn, const unsigned char *from, size_t from_length, size_t *to_length);
334    //unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length);
335    //unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length);
336    //void PQfreemem(void *ptr);
337
338    Field FindField(const String name)
339    {
340       if(res)
341       {
342          int num = PQfnumber(res, name);
343          if(num != -1)
344          {
345             PgSQLField fld { num = num };
346             return fld;
347          }
348       }
349       return null;
350    }
351
352    bool Index(int count, FieldIndex * fieldIndexes)
353    {
354       return false;
355    }
356 }
357
358 static class PgSQLField : Field
359 {
360 public:
361    PgSQLTable tbl;
362
363    Class type;
364    int length;
365
366    int num;
367
368    //int PQfformat(const PGresult *res, int column_number); // returns 0 for textual and 1 for binary
369    //Oid PQftype(const PGresult *res, int column_number);
370          //query the system table pg_type to obtain the names and properties of the various data types
371    //int PQfmod(const PGresult *res, int column_number);
372    //int PQfsize(const PGresult *res, int column_number);
373
374    String GetName() { return (tbl && tbl.res) ? PQfname(tbl.res, num) : null; }
375    Class GetType() { return type; }
376    int GetLength() { return length; }
377    Field GetNext() { return next; }
378    Field GetPrev() { return prev; }
379
380    ~PgSQLField()
381    {
382    }
383
384    void Free() { delete this; }
385 }
386
387
388 //char *PQgetvalue(const PGresult *res, int row_number, int column_number);
389 //int PQgetisnull(const PGresult *res, int row_number, int column_number);
390 //int PQgetlength(const PGresult *res, int row_number, int column_number);
391
392 //void PQprint(FILE *fout,      /* output stream */
393 //             const PGresult *res,
394 //             const PQprintOpt *po);
395
396 //typedef struct {
397 //    pqbool  header;      /* print output field headings and row count */
398 //    pqbool  align;       /* fill align the fields */
399 //    pqbool  standard;    /* old brain dead format */
400 //    pqbool  html3;       /* output HTML tables */
401 //    pqbool  expanded;    /* expand tables */
402 //    pqbool  pager;       /* use pager for output if needed */
403 //    char    *fieldSep;   /* field separator */
404 //    char    *tableOpt;   /* attributes for HTML table element */
405 //    char    *caption;    /* HTML table caption */
406 //    char    **fieldName; /* null-terminated array of replacement field names */
407 //} PQprintOpt;
408
409 static class PgSQLRow : DriverRow
410 {
411    PgSQLTable tbl;
412    int _num;
413
414    property int num
415    {
416       set
417       {
418          _num = value;
419       }
420    }
421
422    ~PgSQLRow()
423    {
424    }
425
426    bool GetData(PgSQLField field, typed_object & data)
427    {
428    }
429
430    bool SetData(PgSQLField field, typed_object data)
431    {
432    }
433
434    bool Nil()
435    {
436       return _num == -1;
437    }
438
439    bool Select(MoveOptions move)
440    {
441       int rowsCount = tbl.GetRowsCount();
442       if(rowsCount)
443       {
444          switch(move)
445          {
446             case first:
447                num = -1;
448             case next:
449                num = _num + 1;
450                if(_num != rowsCount)
451                   return true;
452                num = -1;
453                break;
454             case last:
455                num = rowsCount;
456             case previous:
457                num = _num - 1;
458                if(_num != -1)
459                   return true;
460                break;
461             case middle:
462             case nil:
463                num = -1;
464                break;
465          }
466       }
467       return false;
468    }
469
470    int CompareRowPath(char * apath, PgSQLField field, typed_object data)
471    {
472    }
473
474    int CompareRowNum(int num, PgSQLField field, typed_object data)
475    {
476    }
477
478    int CompareRow(PgSQLField field, typed_object data)
479    {
480    }
481
482    bool Find(PgSQLField field, MoveOptions move, MatchOptions match, typed_object data)
483    {
484       return false;
485    }
486
487    bool Add()
488    {
489    }
490
491    bool Delete()
492    {
493       return false;
494    }
495 }