1 /* This is free and unencumbered software released into the public domain.  */
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sqlite3.h>
7 
8 #define TRUE 1
9 #define FALSE 0
10 
escape(const char * message)11 char* escape(const char *message) {
12     int i, count = 0, length_orig = strlen(message);
13     for (i = 0; i < length_orig; i++) {
14         if (strchr("\"\\", message[i])) {
15             count++;
16         }
17     }
18     char *copy = malloc(length_orig + count + 1);
19     char *p = copy;
20     while (*message) {
21         if (strchr("\"\\", *message)) {
22             *p = '\\';
23             p++;
24         }
25         *p = *message;
26         message++;
27         p++;
28     }
29     *p = '\0';
30     return copy;
31 }
32 
send_error(int code,const char * message)33 void send_error(int code, const char *message) {
34     char *escaped = escape(message);
35     printf("error %d \"%s\"\n", code, escaped);
36     free(escaped);
37 }
38 
39 typedef struct {
40     char *buffer;
41     size_t size;
42 } buffer;
43 
buffer_create()44 buffer* buffer_create() {
45     buffer *buffer = malloc(sizeof(*buffer));
46     buffer->size = 4096;
47     buffer->buffer = malloc(buffer->size * sizeof(char));
48     return buffer;
49 }
50 
buffer_grow(buffer * buffer)51 int buffer_grow(buffer *buffer) {
52     unsigned factor = 2;
53     char *newbuffer = realloc(buffer->buffer, buffer->size * factor);
54     if (newbuffer == NULL) {
55         return FALSE;
56     }
57     buffer->buffer = newbuffer;
58     buffer->size *= factor;
59     return TRUE;
60 }
61 
buffer_read(buffer * buffer,size_t count)62 int buffer_read(buffer *buffer, size_t count) {
63     while (buffer->size < count + 1) {
64         if (buffer_grow(buffer) == FALSE) {
65             return FALSE;
66         }
67     }
68     size_t in = fread((void *) buffer->buffer, 1, count, stdin);
69     buffer->buffer[count] = '\0';
70     return in == count;
71 }
72 
buffer_free(buffer * buffer)73 void buffer_free(buffer *buffer) {
74     free(buffer->buffer);
75     free(buffer);
76 }
77 
main(int argc,char ** argv)78 int main(int argc, char **argv) {
79     char *file = NULL;
80     if (argc != 2) {
81         fprintf(stderr,
82                 "error: require exactly one argument, the DB filename\n");
83         exit(EXIT_FAILURE);
84     } else {
85         file = argv[1];
86     }
87 
88     /* On Windows stderr is not always unbuffered. */
89 #if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__)
90     setvbuf(stderr, NULL, _IONBF, 0);
91 #endif
92 
93     sqlite3* db = NULL;
94     if (sqlite3_initialize() != SQLITE_OK) {
95         fprintf(stderr, "error: failed to initialize sqlite\n");
96         exit(EXIT_FAILURE);
97     }
98     int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
99     if (sqlite3_open_v2(file, &db, flags, NULL) != SQLITE_OK) {
100         fprintf(stderr, "error: failed to open %s\n", file);
101         exit(EXIT_FAILURE);
102     }
103 
104     buffer *input = buffer_create();
105     while (TRUE) {
106         printf("#\n");
107         fflush(stdout);
108 
109         /* Gather input from Emacs. */
110         unsigned length;
111         int result = scanf("%u ", &length);
112         if (result == EOF) {
113             break;
114         } else if (result != 1) {
115             send_error(SQLITE_ERROR, "middleware parsing error");
116             break;  /* stream out of sync: quit program */
117         }
118         if (!buffer_read(input, length)) {
119             send_error(SQLITE_NOMEM, "middleware out of memory");
120             continue;
121         }
122 
123         /* Parse SQL statement. */
124         sqlite3_stmt *stmt = NULL;
125         result = sqlite3_prepare_v2(db, input->buffer, length, &stmt, NULL);
126         if (result != SQLITE_OK) {
127             send_error(sqlite3_errcode(db), sqlite3_errmsg(db));
128             continue;
129         }
130 
131         /* Print out rows. */
132         int first = TRUE, ncolumns = sqlite3_column_count(stmt);
133         printf("(");
134         while (sqlite3_step(stmt) == SQLITE_ROW) {
135             if (first) {
136                 printf("(");
137                 first = FALSE;
138             } else {
139                 printf("\n (");
140             }
141             int i;
142             for (i = 0; i < ncolumns; i++) {
143                 if (i > 0) {
144                     printf(" ");
145                 }
146                 int type = sqlite3_column_type(stmt, i);
147                 switch (type) {
148                 case SQLITE_INTEGER:
149                     printf("%lld", sqlite3_column_int64(stmt, i));
150                     break;
151                 case SQLITE_FLOAT:
152                     printf("%f", sqlite3_column_double(stmt, i));
153                     break;
154                 case SQLITE_NULL:
155                     printf("nil");
156                     break;
157                 case SQLITE_TEXT:
158                     fwrite(sqlite3_column_text(stmt, i), 1,
159                            sqlite3_column_bytes(stmt, i), stdout);
160                     break;
161                 case SQLITE_BLOB:
162                     printf("nil");
163                     break;
164                 }
165             }
166             printf(")");
167         }
168         printf(")\n");
169         if (sqlite3_finalize(stmt) != SQLITE_OK) {
170             /* Despite any error code, the statement is still freed.
171              * http://stackoverflow.com/a/8391872
172              */
173             send_error(sqlite3_errcode(db), sqlite3_errmsg(db));
174         } else {
175             printf("success\n");
176         }
177     }
178     buffer_free(input);
179 
180     sqlite3_close(db);
181     sqlite3_shutdown();
182     return EXIT_SUCCESS;
183 }
184