/[global]/global/libutil/dbop.c
ViewVC logotype

Diff of /global/libutil/dbop.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.18 by shigio, Sun Oct 31 07:03:51 2004 UTC revision 1.19 by shigio, Sat Nov 6 09:25:16 2004 UTC
# Line 47  Line 47 
47  #include "strlimcpy.h"  #include "strlimcpy.h"
48  #include "test.h"  #include "test.h"
49    
 #ifdef USE_POSTGRES  
   
 PGconn *conn = NULL;  
   
 static int pgop_load_tagfile(const char *, STRBUF *);  
 static int pgop_extract_from_tagfile(const char *, const char *, char *, int);  
 DBOP *pgop_open(const char *, int, int, int);  
 char *pgop_get(DBOP *, const char *);  
 void pgop_put(DBOP *, const char *, const char *, const char *);  
 void pgop_delete(DBOP *, const char *);  
 char *pgop_getkey_by_fid(DBOP *, const char *);  
 void pgop_delete_by_fid(DBOP *, const char *);  
 void pgop_update(DBOP *, const char *, const char *, const char *);  
 char *pgop_first(DBOP *, const char *, regex_t *, int);  
 char *pgop_next(DBOP *);  
 char *pgop_lastdat(DBOP *);  
 void pgop_close(DBOP *);  
 #endif /* USE_POSTGRES */  
   
50  int print_statistics = 0;  int print_statistics = 0;
 char *postgres_info;  
   
 /*  
  * dbop_setinfo: set info string.  
  *  
  *      i)      info    info string  
  *  
  * Currently this method is used only for postgres.  
  */  
 void  
 dbop_setinfo(info)  
         char *info;  
 {  
         postgres_info = info;  
 }  
51  /*  /*
52   * dbop_open: open db database.   * dbop_open: open db database.
53   *   *
# Line 91  dbop_setinfo(info) Line 57  dbop_setinfo(info)
57   *      i)      flags   *      i)      flags
58   *                      DBOP_DUP: allow duplicate records.   *                      DBOP_DUP: allow duplicate records.
59   *                      DBOP_REMOVE: remove on closed.   *                      DBOP_REMOVE: remove on closed.
  *                      DBOP_POSTGRES: use postgres database  
60   *      r)              descripter for dbop_xxx()   *      r)              descripter for dbop_xxx()
61   */   */
62  DBOP *  DBOP *
# Line 106  dbop_open(path, mode, perm, flags) Line 71  dbop_open(path, mode, perm, flags)
71          DBOP *dbop;          DBOP *dbop;
72          BTREEINFO info;          BTREEINFO info;
73    
 #ifdef USE_POSTGRES  
         if (mode != 1 && pgop_load_tagfile(path, NULL))  
                 flags |= DBOP_POSTGRES;  
         if (flags & DBOP_POSTGRES)  
                 return pgop_open(path, mode, perm, flags);  
 #endif /* USE_POSTGRES */  
74          /*          /*
75           * setup arguments.           * setup arguments.
76           */           */
# Line 175  dbop_get(dbop, name) Line 134  dbop_get(dbop, name)
134          DBT key, dat;          DBT key, dat;
135          int status;          int status;
136    
 #ifdef USE_POSTGRES  
         if (dbop->openflags & DBOP_POSTGRES)  
                 return pgop_get(dbop, name);  
 #endif  
137          key.data = (char *)name;          key.data = (char *)name;
138          key.size = strlen(name)+1;          key.size = strlen(name)+1;
139    
# Line 200  dbop_get(dbop, name) Line 155  dbop_get(dbop, name)
155   *      i)      dbop    descripter   *      i)      dbop    descripter
156   *      i)      name    key   *      i)      name    key
157   *      i)      data    data   *      i)      data    data
  *      i)      fid     file id (only for postgres)  
158   */   */
159  void  void
160  dbop_put(dbop, name, data, fid)  dbop_put(dbop, name, data)
161          DBOP *dbop;          DBOP *dbop;
162          const char *name;          const char *name;
163          const char *data;          const char *data;
         const char *fid;  
164  {  {
165          DB *db = dbop->db;          DB *db = dbop->db;
166          DBT key, dat;          DBT key, dat;
# Line 218  dbop_put(dbop, name, data, fid) Line 171  dbop_put(dbop, name, data, fid)
171                  die("primary key size == 0.");                  die("primary key size == 0.");
172          if (len > MAXKEYLEN)          if (len > MAXKEYLEN)
173                  die("primary key too long.");                  die("primary key too long.");
 #ifdef USE_POSTGRES  
         if (dbop->openflags & DBOP_POSTGRES)  
                 return pgop_put(dbop, name, data, fid);  
 #endif  
174          key.data = (char *)name;          key.data = (char *)name;
175          key.size = strlen(name)+1;          key.size = strlen(name)+1;
176          dat.data = (char *)data;          dat.data = (char *)data;
# Line 251  dbop_delete(dbop, path) Line 200  dbop_delete(dbop, path)
200          DBT key;          DBT key;
201          int status;          int status;
202    
 #ifdef USE_POSTGRES  
         if (dbop->openflags & DBOP_POSTGRES)  
                 return pgop_delete(dbop, path);  
 #endif  
203          if (path) {          if (path) {
204                  key.data = (char *)path;                  key.data = (char *)path;
205                  key.size = strlen(path)+1;                  key.size = strlen(path)+1;
# Line 270  dbop_delete(dbop, path) Line 215  dbop_delete(dbop, path)
215   *      i)      dbop    descripter   *      i)      dbop    descripter
216   *      i)      key     key   *      i)      key     key
217   *      i)      dat     data   *      i)      dat     data
  *      i)      fid     file id  
218   */   */
219  void  void
220  dbop_update(dbop, key, dat, fid)  dbop_update(dbop, key, dat)
221          DBOP *dbop;          DBOP *dbop;
222          const char *key;          const char *key;
223          const char *dat;          const char *dat;
         const char *fid;  
224  {  {
225  #ifdef USE_POSTGRES          dbop_put(dbop, key, dat);
         if (dbop->openflags & DBOP_POSTGRES)  
                 pgop_update(dbop, key, dat, fid);  
         else  
 #endif  
                 dbop_put(dbop, key, dat, fid);  
226  }  }
 #ifdef USE_POSTGRES  
 /*  
  * dbop_getkey_by_fid: get key by fid.  
  *  
  *      i)      dbop    descripter  
  *      i)      fid     file id  
  *      r)              pointer to data  
  */  
 char    *  
 dbop_getkey_by_fid(dbop, fid)  
         DBOP *dbop;  
         const char *fid;  
 {  
         assert(dbop->openflags & DBOP_POSTGRES);  
         return pgop_getkey_by_fid(dbop, fid);  
 }  
 /*  
  * dbop_delete_by_fid: delete record by fid.  
  *  
  *      i)      dbop    descripter  
  *      i)      fid     file id  
  */  
 void  
 dbop_delete_by_fid(dbop, fid)  
         DBOP *dbop;  
         const char *fid;  
 {  
         assert(dbop->openflags & DBOP_POSTGRES);  
         return pgop_delete_by_fid(dbop, fid);  
 }  
 #endif  
227  /*  /*
228   * dbop_first: get first record.   * dbop_first: get first record.
229   *   *
# Line 342  int    flags; Line 249  int    flags;
249          DBT key, dat;          DBT key, dat;
250          int status;          int status;
251    
 #ifdef USE_POSTGRES  
         if (dbop->openflags & DBOP_POSTGRES)  
                 return pgop_first(dbop, name, preg, flags);  
 #endif  
   
252          dbop->preg = preg;          dbop->preg = preg;
253          if (flags & DBOP_PREFIX && !name)          if (flags & DBOP_PREFIX && !name)
254                  flags &= ~DBOP_PREFIX;                  flags &= ~DBOP_PREFIX;
# Line 421  dbop_next(dbop) Line 323  dbop_next(dbop)
323          DBT key, dat;          DBT key, dat;
324          int status;          int status;
325    
 #ifdef USE_POSTGRES  
         if (dbop->openflags & DBOP_POSTGRES)  
                 return pgop_next(dbop);  
 #endif  
   
326          while ((status = (*db->seq)(db, &key, &dat, R_NEXT)) == RET_SUCCESS) {          while ((status = (*db->seq)(db, &key, &dat, R_NEXT)) == RET_SUCCESS) {
327                  assert(dat.data != NULL);                  assert(dat.data != NULL);
328                  if (flags & DBOP_KEY && *((char *)key.data) == ' ')                  if (flags & DBOP_KEY && *((char *)key.data) == ' ')
# Line 478  dbop_close(dbop) Line 375  dbop_close(dbop)
375  {  {
376          DB *db = dbop->db;          DB *db = dbop->db;
377    
 #ifdef USE_POSTGRES  
         if (dbop->openflags & DBOP_POSTGRES)  
                 return pgop_close(dbop);  
 #endif  
   
378          (void)db->close(db);          (void)db->close(db);
379          if (dbop->openflags & DBOP_REMOVE)          if (dbop->openflags & DBOP_REMOVE)
380                  (void)unlink(dbop->dbname);                  (void)unlink(dbop->dbname);
# Line 490  dbop_close(dbop) Line 382  dbop_close(dbop)
382                  die("cannot change file mode.");                  die("cannot change file mode.");
383          (void)free(dbop);          (void)free(dbop);
384  }  }
 #ifdef USE_POSTGRES  
 /*  
  * pgop_execute: execute sql statement.  
  *  
  *      i)      dbop    dbop descripter  
  *      i)      sql     sql statement  
  *      i)      line    line number  
  */  
 static void  
 pgop_execute(dbop, sql, line)  
         DBOP *dbop;  
         char *sql;  
         int line;  
 {  
         extern int debug;  
   
         if (debug)  
                 fprintf(stderr, "sql: '%s' at %d\n", sql, line);  
         if (dbop->res)  
                 PQclear(dbop->res);  
         if (*sql == '@') {  
                 dbop->res = PQexec(conn, sql + 1);  
         } else {  
                 dbop->res = PQexec(conn, sql);  
                 if (!dbop->res ||  
                 (PQresultStatus(dbop->res) != PGRES_COMMAND_OK &&  
                 PQresultStatus(dbop->res) != PGRES_TUPLES_OK)) {  
                         fprintf(stderr, "%s: SQL statement failed at %d.\n", progname, line);  
                         fprintf(stderr, "sql: %s\n", sql);  
                         fprintf(stderr, "postgres: %s", PQerrorMessage(conn));  
                         PQfinish(conn);  
                         abort();  
                         exit(1);  
                 }  
         }  
 }  
 /*  
  * pgop_connect: connect to databse server.  
  *  
  *      i)      info    connect string  
  */  
 static void  
 pgop_connect(info)  
         const char *info;  
 {  
         if (conn)  
                 return;  
         conn = PQconnectdb(info);  
         if (PQstatus(conn) == CONNECTION_BAD) {  
                 fprintf(stderr, "%s: Connection to database failed.\n", progname);  
                 fprintf(stderr, "PQconnectdb('%s')", info);  
                 fprintf(stderr, "postgres: %s", PQerrorMessage(conn));  
                 PQfinish(conn);  
                 exit(1);  
         }  
 }  
 /*  
  * pgop_load_tagfile: load tag file.  
  *  
  *      i)      path    path of tag file  
  *      o)      sb      contents of tag file  
  *      r)              1: postgres tag file loaded  
  *                      0: file not exist or is not postgres tag file  
  */  
 static int  
 pgop_load_tagfile(path, sb)  
         const char *path;  
         STRBUF *sb;  
 {  
         char *p;  
         int alloc = 0;  
         int ispostgres = 0;  
         FILE *fp = fopen(path, "r");  
   
         if (fp == NULL)  
                 return 0;  
         if (sb == NULL) {  
                 sb = strbuf_open(0);  
                 alloc = 1;  
         }  
         if (strbuf_fgets(sb, fp, STRBUF_NOCRLF) == NULL)  
                 die("%s is empty.", path);  
         fclose(fp);  
         p = strbuf_value(sb);  
         if (!strncmp(p, "postgres: ", strlen("postgres: ")))  
                 ispostgres = 1;  
         if (alloc)  
                 strbuf_close(sb);  
         return ispostgres;  
 }  
 /*  
  * pgop_extract_from_tagfile: extract a parameter from loaded tag file.  
  *  
  *      i)      contents contents of loaded tag file  
  *      i)      key     key  
  *      o)      buf     buffer  
  *      i)      size    size of buf  
  *      r)              1: exist, 0: not exist  
  */  
 static int  
 pgop_extract_from_tagfile(contents, key, buf, size)  
         const char *contents;  
         const char *key;  
         char *buf;  
         int size;  
 {  
         STRBUF *sb = strbuf_open(0);  
         char *p, *limit = buf + size;  
   
         strbuf_putc(sb, ' ');  
         strbuf_puts(sb, key);  
         strbuf_putc(sb, '=');  
         p = locatestring(contents, strbuf_value(sb), MATCH_FIRST);  
         if (p == NULL)  
                 return 0;  
         p += strbuf_getlen(sb);  
         while (*p && *p != ' ') {  
                 if (buf >= limit)  
                         die("parameter in postgres tag file too long. '%s'", key);  
                 *buf++ = *p++;  
         }  
         *buf = 0;  
         return 1;  
 }  
 /*  
  * pgop_open: open postgres table.  
  *  
  *      i)      path    tag file path  
  *      i)      mode    0: read, 1: write, 2: update  
  *      i)      perm    permission for chmod(2)  
  *      i)      flags   flags  
  */  
 DBOP *  
 pgop_open(path, mode, perm, flags)  
         const char *path;  
         int mode;  
         int perm;  
         int flags;  
 {  
         DBOP *dbop;  
         STRBUF *sb;  
         char sql[1024], dir[MAXPATHLEN+1], *name;  
         FILE *fp;  
   
         /*  
          * make dbop discripter.  
          */  
         if (!(dbop = (DBOP *)malloc(sizeof(DBOP))))  
                 die("short of memory.");  
         /*  
          * make table name.  
          */  
         snprintf(dir, sizeof(dir), "%s", path);  
         if (!(name = strrchr(dir, '/'))) {  
                 name = (char *)path;  
                 dir[0] = 0;  
         } else  
                 *name++ = 0;  
         strlimcpy(dbop->tblname, name, sizeof(dbop->tblname));  
         dbop->res = NULL;  
         dbop->mode = mode;  
         dbop->openflags = flags;  
         dbop->lastdat   = NULL;  
   
         if (mode == 1) {  
                 /*  
                  * if the -P option includes info string then use it.  
                  */  
                 if (postgres_info) {  
                         snprintf(sql, sizeof(sql), "postgres: %s\n", postgres_info);  
                 } else {  
                         /*  
                          * else if GTAGS exist then load from 'GTAGS'.  
                          */  
                         sb = strbuf_open(0);  
                         strcat(dir, "/GTAGS");  
                         if (pgop_load_tagfile(dir, sb))  
                                 snprintf(sql, sizeof(sql), "%s\n", strbuf_value(sb));  
                         else  
                                 die("Please specify info string for PQconnectdb(3) using --postgres='info'.");  
                         strbuf_close(sb);  
                 }  
                 fp = fopen(path, "w");  
                 if (fp == NULL)  
                         die("cannot create '%s'.", path);  
                 fputs(sql, fp);  
                 fclose(fp);  
                 chmod(path, perm);  
         }  
         /*  
          * load postgres tag file and make a connection.  
          */  
         {  
                 char *p;  
   
                 sb = strbuf_open(0);  
                 if (!pgop_load_tagfile(path, sb))  
                         die("%s not found.", path);  
                 /* skip 'postgres: ' */  
                 p = strbuf_value(sb);  
                 if (strchr(p, ':'))  
                         p = strchr(p, ':') + 1;  
                 while (*p == ' ')  
                         p++;  
                 /* make connection to postgres */  
                 pgop_connect(p);  
                 strbuf_close(sb);  
         }  
   
         /*  
          * create table (GTAGS, GRTAGS, GSYMS, GPATH).  
          */  
         if (mode == 1) {  
                 snprintf(sql, sizeof(sql), "@DROP TABLE %s", dbop->tblname);  
                 pgop_execute(dbop, sql, __LINE__);  
                 snprintf(sql, sizeof(sql),  
                 "CREATE TABLE %s (key TEXT, dat TEXT, fid INT4)", dbop->tblname);  
                 pgop_execute(dbop, sql, __LINE__);  
                 snprintf(sql, sizeof(sql), "GRANT ALL ON %s TO public", dbop->tblname);  
                 pgop_execute(dbop, sql, __LINE__);  
                 /*  
                  * Create order for speed up:  
                  * GTAGS,GRTAGS,GSYMS  
                  *              create table -> put data -> create index  
                  * GPATH        create table -> create index -> put data  
                  */  
                 if (!strcmp(name, "GPATH")) {  
                         snprintf(sql, sizeof(sql),  
                         "CREATE INDEX %s_i1 ON %s (key)", dbop->tblname, dbop->tblname);  
                         pgop_execute(dbop, sql, __LINE__);  
                         snprintf(sql, sizeof(sql),  
                         "CREATE INDEX %s_i2 ON %s (fid)", dbop->tblname, dbop->tblname);  
                         pgop_execute(dbop, sql, __LINE__);  
                 }  
         }  
         /* construct SQL statement. */  
         /*  
          * pgop_delete(), pgop_delete_by_fid()  
          */  
         sb = strbuf_open(0);  
         strbuf_puts(sb, "DELETE FROM ");  
         strbuf_puts(sb, dbop->tblname);  
         strbuf_puts(sb, " WHERE ");  
         strbuf_puts(sb, "fid = ");  
         dbop->delete_stmt = sb;  
         dbop->delete_stmt_len = strbuf_getlen(sb);  
         /*  
          * pgop_get(), pgop_getkey_by_fid()  
          */  
         sb = strbuf_open(0);  
         strbuf_puts(sb, "SELECT * FROM ");  
         strbuf_puts(sb, dbop->tblname);  
         strbuf_puts(sb, " WHERE ");  
         dbop->get_stmt = sb;  
         dbop->get_stmt_len = strbuf_getlen(sb);  
         /*  
          * pgop_put()  
          */  
         sb = strbuf_open(0);  
         strbuf_puts(sb, "INSERT INTO ");  
         strbuf_puts(sb, dbop->tblname);  
         strbuf_puts(sb, " VALUES ");  
         dbop->put_stmt = sb;  
         dbop->put_stmt_len = strbuf_getlen(sb);  
         /*  
          * pgop_first(), pgop_next()  
          */  
         sb = strbuf_open(0);  
         strbuf_puts(sb, "FETCH 1 FROM c_");  
         strbuf_puts(sb, dbop->tblname);  
         dbop->fetch_stmt = sb;  
         dbop->fetch_stmt_len = strbuf_getlen(sb);  
   
         return dbop;  
 }  
   
 /*  
  * pgop_get: get data by a key.  
  *  
  *      i)      dbop    descripter  
  *      i)      name    name  
  *      r)              pointer to data  
  */  
 char    *  
 pgop_get(dbop, name)  
         DBOP *dbop;  
         const char *name;  
 {  
         STRBUF *sb = dbop->get_stmt;  
   
         strbuf_setlen(sb, dbop->get_stmt_len);          /* truncate */  
         strbuf_puts(sb, "key = ");  
         strbuf_putc(sb, '\'');  
         strbuf_puts(sb, name);  
         strbuf_putc(sb, '\'');  
         pgop_execute(dbop, strbuf_value(sb), __LINE__);  
         if (PQntuples(dbop->res) == 0)  
                 return NULL;  
         dbop->lastdat = PQgetvalue(dbop->res, 0, 1);  
         return dbop->lastdat;  
 }  
 /*  
  * pgop_put: put data by a key.  
  *  
  *      i)      dbop    descripter  
  *      i)      name    key  
  *      i)      data    data  
  *      i)      fid     file id  
  */  
 void  
 pgop_put(dbop, key, dat, fid)  
         DBOP *dbop;  
         const char *key;  
         const char *dat;  
         const char *fid;  
 {  
         STRBUF *sb = dbop->put_stmt;  
         const char *p;  
   
         strbuf_setlen(sb, dbop->put_stmt_len);          /* truncate */  
         strbuf_puts(sb, "('");  
         strbuf_puts(sb, key);  
         strbuf_puts(sb, "', '");  
         for (p = dat; *p; p++) {  
                 switch (*p) {  
                 case '\\':  
                 case '\'':  
                         strbuf_putc(sb, '\\');  
                         break;  
                 }  
                 strbuf_putc(sb, *p);  
         }  
         strbuf_puts(sb, "', ");  
         strbuf_puts(sb, fid);  
         strbuf_puts(sb, ")");  
         pgop_execute(dbop, strbuf_value(sb), __LINE__);  
 }  
 /*  
  * pgop_delete: delete record by a key.  
  *  
  *      i)      dbop    descripter  
  *      i)      path    path name  
  */  
 void  
 pgop_delete(dbop, path)  
         DBOP *dbop;  
         const char *path;  
 {  
         STRBUF *sb = dbop->delete_stmt;  
   
         strbuf_setlen(sb, dbop->delete_stmt_len);       /* truncate */  
         strbuf_puts(sb, path);  
         pgop_execute(dbop, strbuf_value(sb), __LINE__);  
 }  
 /*  
  * pgop_getkey_by_fid: get key by fid.  
  *  
  *      i)      dbop    descripter  
  *      i)      fid     file id  
  *      r)              pointer to data  
  */  
 char    *  
 pgop_getkey_by_fid(dbop, fid)  
         DBOP *dbop;  
         const char *fid;  
 {  
         STRBUF *sb = dbop->get_stmt;  
   
         strbuf_setlen(sb, dbop->get_stmt_len);  /* truncate */  
         strbuf_puts(sb, "fid = ");  
         strbuf_puts(sb, fid);  
         pgop_execute(dbop, strbuf_value(sb), __LINE__);  
         if (PQntuples(dbop->res) == 0)  
                 return NULL;  
         dbop->lastdat = PQgetvalue(dbop->res, 0, 1);  
         return PQgetvalue(dbop->res, 0, 0);  
 }  
 /*  
  * pgop_delete_by_fid: delete record by fid.  
  *  
  *      i)      dbop    descripter  
  *      i)      fid     file id  
  */  
 void  
 pgop_delete_by_fid(dbop, fid)  
         DBOP *dbop;  
         const char *fid;  
 {  
         STRBUF *sb = dbop->delete_stmt;  
   
         strbuf_setlen(sb, dbop->delete_stmt_len);       /* truncate */  
         strbuf_puts(sb, fid);  
         pgop_execute(dbop, strbuf_value(sb), __LINE__);  
 }  
 /*  
  * pgop_update: update record.  
  *  
  *      i)      dbop    descripter  
  *      i)      key     key  
  *      i)      dat     data  
  *      i)      fid     file id  
  */  
 void  
 pgop_update(dbop, key, dat, fid)  
         DBOP *dbop;  
         const char *key;  
         const char *dat;  
         const char *fid;  
 {  
         char *p;  
         STRBUF *sb = strbuf_open(0);  
   
         strbuf_puts(sb, "UPDATE ");  
         strbuf_puts(sb, dbop->tblname);  
         strbuf_puts(sb, " SET dat = ");  
         strbuf_puts(sb, dat);  
         strbuf_puts(sb, " WHERE key = '");  
         strbuf_puts(sb, key);  
         strbuf_puts(sb, "'");  
         pgop_execute(dbop, strbuf_value(sb), __LINE__);  
         p = PQcmdTuples(dbop->res);  
         if (!p || !*p || !strcmp(p, "0"))  
                 (void)pgop_put(dbop, key, dat, fid);  
 }  
 /*  
  * pgop_first: get first record.  
  *  
  *      i)      dbop    dbop descripter  
  *      i)      name    key value or prefix  
  *                      includes regular expression: ~ read  
  *                      !=NULL: = read  
  *                      ==NULL: sequential read  
  *      i)      preg    compiled regular expression if any.  
  *      i)      flags   following pgop_next call take over this.  
  *                      DBOP_KEY        read key part  
  *                      DBOP_PREFIX     prefix read  
  *                                      only valied when sequential read  
  *      r)              data  
  */  
 char    *  
 pgop_first(dbop, name, preg, flags)  
         DBOP *dbop;  
         const char *name;  
         regex_t *preg;  
         int     flags;  
 {  
         STRBUF *sb = strbuf_open(0);  
   
         dbop->preg = preg;  
         dbop->ioflags = flags;  
         if (dbop->ioflags & DBOP_PREFIX && !name)  
                 dbop->ioflags &= ~DBOP_PREFIX;  
         pgop_execute(dbop, "BEGIN", __LINE__);  
         /*  
          * construct SQL for read tags.  
          */  
         strbuf_puts(sb, "DECLARE c_");  
         strbuf_puts(sb, dbop->tblname);  
         strbuf_puts(sb, " CURSOR FOR SELECT key, dat FROM ");  
         strbuf_puts(sb, dbop->tblname);  
         if (name) {  
                 strbuf_puts(sb, " WHERE key");  
                 if (isregex(name) || dbop->ioflags & DBOP_PREFIX) {  
                         strbuf_puts(sb, " ~ '");  
                         if (dbop->ioflags & DBOP_PREFIX)  
                                 strbuf_putc(sb, '^');  
                         strbuf_puts(sb, name);  
                         strbuf_puts(sb, "'");  
                 } else {  
                         strbuf_puts(sb, " = '");  
                         strbuf_puts(sb, name);  
                         strbuf_puts(sb, "'");  
                 }  
         }  
         strbuf_puts(sb, " ORDER BY key");  
         pgop_execute(dbop, strbuf_value(sb), __LINE__);  
         strbuf_close(sb);  
         for (;;) {  
                 pgop_execute(dbop, strbuf_value(dbop->fetch_stmt), __LINE__);  
                 if (PQntuples(dbop->res) == 0) {  
                         STRBUF *sb = strbuf_open(0);  
                         strbuf_puts(sb, "CLOSE c_");  
                         strbuf_puts(sb, dbop->tblname);  
                         pgop_execute(dbop, strbuf_value(sb), __LINE__);  
                         strbuf_close(sb);  
                         pgop_execute(dbop, "COMMIT", __LINE__);  
                         return NULL;  
                 }  
                 if (preg && regexec(preg, PQgetvalue(dbop->res, 0, 0), 0, 0, 0) != 0)  
                         continue;  
                 dbop->lastdat = PQgetvalue(dbop->res, 0, 1);  
                 if (dbop->lastdat && *(dbop->lastdat) != ' ')  
                         break;  
         }  
         return PQgetvalue(dbop->res, 0, (dbop->ioflags & DBOP_KEY) ? 0 : 1);  
 }  
 /*  
  * pgop_next: get next record.  
  *  
  *      i)      dbop    dbop descripter  
  *      r)              data  
  *  
  * Db_next always skip meta records.  
  */  
 char    *  
 pgop_next(dbop)  
         DBOP *dbop;  
 {  
         char *fetch = strbuf_value(dbop->fetch_stmt);  
         for (;;) {  
                 pgop_execute(dbop, fetch, __LINE__);  
                 if (PQntuples(dbop->res) == 0) {  
                         STRBUF *sb = strbuf_open(0);  
                         strbuf_puts(sb, "CLOSE c_");  
                         strbuf_puts(sb, dbop->tblname);  
                         pgop_execute(dbop, strbuf_value(sb), __LINE__);  
                         strbuf_close(sb);  
                         pgop_execute(dbop, "COMMIT", __LINE__);  
                         return NULL;  
                 }  
                 if (dbop->preg && regexec(dbop->preg, PQgetvalue(dbop->res, 0, 0), 0, 0, 0) != 0)  
                         continue;  
                 dbop->lastdat = PQgetvalue(dbop->res, 0, 1);  
                 if (dbop->lastdat && *(dbop->lastdat) != ' ')  
                         break;  
         }  
   
         return PQgetvalue(dbop->res, 0, (dbop->ioflags & DBOP_KEY) ? 0 : 1);  
 }  
 /*  
  * pgop_lastdat: get last data  
  *  
  *      i)      dbop    dbop descripter  
  *      r)              last data  
  */  
 char *  
 pgop_lastdat(dbop)  
         DBOP *dbop;  
 {  
         return dbop->lastdat;  
 }  
 /*  
  * pgop_close: close db  
  *  
  *      i)      dbop    dbop descripter  
  */  
 void  
 pgop_close(dbop)  
         DBOP *dbop;  
 {  
         if (dbop->mode == 1 && strncmp(dbop->tblname, "GPATH", strlen("GPATH"))) {  
                 char sql[1024];  
   
                 snprintf(sql, sizeof(sql),  
                 "CREATE INDEX %s_i1 ON %s (key)", dbop->tblname, dbop->tblname);  
                 pgop_execute(dbop, sql, __LINE__);  
                 snprintf(sql, sizeof(sql),  
                 "CREATE INDEX %s_i2 ON %s (fid)", dbop->tblname, dbop->tblname);  
                 pgop_execute(dbop, sql, __LINE__);  
         }  
         if (dbop->res)  
                 PQclear(dbop->res);  
         (void)free(dbop);  
 }  
 #endif /* USE_POSTGRES */  

Legend:
Removed from v.1.18  
changed lines
  Added in v.1.19

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26