chiark / gitweb /
WIP routesearch; New SQL_DISTINCT_{DECL,STEP}
[ypp-sc-tools.db-live.git] / yarrg / rssql.c
1
2 #include "rscommon.h"
3
4 sqlite3 *db;
5 sqlite3_stmt *ss_ipair;
6
7 int islandtablesz;
8
9 DEBUG_DEFINE_DEBUGF(sql);
10
11 static int busy_handler(void *u, int previous) {
12   debugf("[[DB BUSY %d]]",previous);
13   sysassert(! usleep(5000) );
14   return 1;
15 }
16
17 void setup_sql(void) {
18   sqlite3_stmt *sst;
19   
20   SQL_MUST( sqlite3_open("OCEAN-Midnight.db", &db) );
21   SQL_MUST( sqlite3_busy_handler(db, busy_handler, 0) );
22
23   sst= sql_prepare("BEGIN","(begin)");
24   assert( !SQL_STEP(sst) );
25   sqlite3_finalize(sst);
26
27   islandtablesz= 1 + sql_single_int("SELECT max(islandid) FROM islands");
28   debugf("SQL islandtablesz=%d\n",islandtablesz);
29 }
30
31 int sql_single_int(const char *stmt) {
32   sqlite3_stmt *sst;
33   sst= sql_prepare(stmt,"(single int)");
34   assert( SQL_STEP(sst) );
35   int rv= sqlite3_column_int(sst,0);
36   sqlite3_finalize(sst);
37   return rv;
38 }
39
40 void sql_fatal(const char *stmt_what, int sqr, const char *act_what) {
41   fatal("SQL call failed, stmt %s code %d: %s: %s",
42         stmt_what, sqr, sqlite3_errmsg(db), act_what);
43 }
44
45 void sql_bind(sqlite3_stmt *ss, int index, int value,
46               const char *ss_what, const char *val_what) {
47   debugf("SQL BIND %s #%d = %d = %s\n", ss_what, index, value, val_what);
48   int sqr= sqlite3_bind_int(ss, index, value);
49   if (sqr) sql_fatal(ss_what, sqr,
50                      masprintf("bind #%d (%s)", index, val_what));
51 }
52   
53 sqlite3_stmt *sql_prepare(const char *stmt, const char *what) {
54   sqlite3_stmt *ssr;
55   debugf("SQL PREPARE %s [[\n%s\n]]\n", what, stmt);
56   SQL_MUST( sqlite3_prepare(db, stmt, -1, &ssr, 0) );
57   return ssr;
58 }
59
60 int sql_step_distinct(sqlite3_stmt *ssh, const char *ssh_string,
61                       const char *file, int line,
62                       int *cols, int ncols, int nkeycols) {
63   for (;;) {
64     if (!sql_step(ssh, ssh_string, file, line)) return 0;
65
66     int i;
67     for (i=0; i<ncols; i++) {
68       int v= sqlite3_column_int(ssh, i);
69       if (v == cols[i]) continue;
70       
71       assert(i<nkeycols);
72       cols[i++]= v;
73       for ( ; i<ncols; i++)
74         cols[i]= sqlite3_column_int(ssh, i);
75       return 1;
76     }
77   }
78 }
79
80 int sql_step(sqlite3_stmt *ssh, const char *ssh_string,
81              const char *file, int line) {
82   for (;;) {
83     int sqr;
84     sqr= sqlite3_step((ssh));
85     switch (sqr) {
86     case SQLITE_DONE:
87       debugf("SQL %s DONE\n",ssh_string);
88       return 0;
89     case SQLITE_ROW:
90       if (DEBUGP(sql)) {
91         int i;
92         fprintf(debug,"SQL %s R",ssh_string);
93         for (i=0; i<sqlite3_column_count(ssh); i++) {
94           fputc('\t',debug);
95           const char *txt= (const char*)sqlite3_column_text(ssh,i);
96           fputs(txt ? txt : "<null>", debug);
97         }
98         fputs("\n",debug);
99       }
100       return 1;
101     default: fatal("SQL step failed at %s:%d: code %d: %s: %s",
102                    file, line, sqr, sqlite3_errmsg(db), ssh_string);
103     }
104   }
105 }