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