c07c8b0923cfe021e8f1e9d8ff1cbbb7ef410902
[ftsbench.git] / mysqldriver.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <time.h>
6 #include <errno.h>
7 #include <sys/types.h>
8 #include <netinet/in.h>
9
10 #include <mysql.h>
11 #include "ftsbench.h"
12
13 typedef struct ftsMY {
14         ftsDB   db;
15         MYSQL   *conn;
16         int     flags;
17         MYSQL_STMT              *prepareStmt;
18         StringBuf       b;
19 } ftsMY;
20
21 static void
22 execQuery(ftsDB *adb, char **words, int flags) {
23         ftsMY *db = (ftsMY*)adb;
24         static MYSQL_BIND       data;
25         MYSQL_RES       *res;
26
27         if ( db->prepareStmt == NULL ) {
28                 db->prepareStmt = mysql_stmt_init(db->conn);
29                 if ( db->prepareStmt == NULL ) {
30                         fprintf(stderr,"mysql_stmt_init failed: %s\n", mysql_error(db->conn));
31                         exit(1);
32                 }
33
34 #define SEARCH_QUERY "SELECT count(*) FROM ftsbench WHERE MATCH(body) AGAINST ( ? IN BOOLEAN MODE);"
35                 if ( mysql_stmt_prepare( db->prepareStmt, SEARCH_QUERY, strlen(SEARCH_QUERY) ) != 0 ) {
36                         fprintf(stderr,"mysql_stmt_init failed: %s\n", mysql_error(db->conn));
37                         exit(1);
38                 }
39
40                 if ( mysql_stmt_param_count(db->prepareStmt) != 1 ) {
41                         fprintf(stderr,"mysql_stmt_param_count: invalid parameter count\n");
42                         exit(1);
43                 }
44
45                 memset(&data, 0, sizeof(MYSQL_BIND));
46                 data.buffer_type = MYSQL_TYPE_BLOB;
47                 data.length = (unsigned long*)&(db->b.strlen);
48
49                 db->flags = flags;
50         }
51
52     db->b.strlen = 0;
53                  
54         while( *words ) {
55                 if ( db->flags & FLG_OR)
56                         sb_add(&db->b, " ", 1);
57                 else
58                         sb_add(&db->b, " +", 2);
59
60                 sb_add(&db->b, *words, -1);
61                 words++;
62         }
63
64         data.buffer = db->b.str;
65         data.buffer_length = db->b.strlen;
66
67         if ( mysql_stmt_bind_param(db->prepareStmt, &data) ) {
68                 fprintf(stderr,"mysql_stmt_bind_param failed: %s\n", mysql_error(db->conn));
69                 exit(1);
70         }
71
72         if ( mysql_stmt_execute( db->prepareStmt ) ) {
73                 fprintf(stderr,"mysql_stmt_execute failed: %s\n", mysql_error(db->conn));
74                 exit(1);
75         }
76
77         res = mysql_store_result(db->conn);
78         if ( res == NULL ) {
79                 if  ( mysql_errno(db->conn)!=0 ) {
80                         fprintf(stderr,"mysql_store_result failed: %s\n", mysql_error(db->conn));
81                         exit(1);
82                 }
83         } else
84                 mysql_free_result(res);
85
86         pthread_mutex_lock(&(db->db.nqueryMutex));
87         db->db.nquery ++;
88         pthread_mutex_unlock(&(db->db.nqueryMutex));
89 }
90
91 static void
92 startCreateScheme(ftsDB *adb, int flags) {
93         ftsMY *db = (ftsMY*)adb;
94
95         db->flags = flags;
96         if ( flags & FLG_FUNC )
97                 printf("Flag 'func' is ignored by MySQL\n");
98
99         if ( flags & (FLG_GIN | FLG_GIST) )
100                 printf("MySQL doesn't distinguish 'gin' and 'gist' flags\n");
101
102         if ( mysql_query(db->conn, "DROP TABLE IF EXISTS ftsbench CASCADE;")!= 0 ) {
103                 fprintf(stderr,"mysql_query failed: %s\n", mysql_error(db->conn));
104                 exit(1);
105         }
106
107         if ( mysql_query(db->conn, "CREATE TABLE ftsbench (id int not null, body text) ENGINE MyISAM;")!= 0 ) {
108                 fprintf(stderr,"mysql_query failed: %s\n", mysql_error(db->conn));
109                 exit(1);
110         }
111 }
112
113 static void
114 finishCreateScheme(ftsDB *adb) {
115         ftsMY *db = (ftsMY*)adb;
116
117         if  ( db->flags & (FLG_GIN | FLG_GIST) ) {
118                 printf("(create index, ");
119                 fflush(stdout);
120
121                 if ( mysql_query(db->conn, "CREATE FULLTEXT INDEX fts ON ftsbench (body);")!= 0 ) {
122                         fprintf(stderr,"mysql_query failed: %s\n", mysql_error(db->conn));
123                         exit(1);
124                 }
125         } else {
126                 printf("(");
127                 fflush(stdout);
128         }
129
130         printf("optimize");
131         fflush(stdout);
132         if ( mysql_query(db->conn, "OPTIMIZE TABLE ftsbench;")!= 0 ) {
133                 fprintf(stderr,"mysql_query failed: %s\n", mysql_error(db->conn));
134                 exit(1);
135         }
136
137         printf(") ");
138         fflush(stdout);
139 }
140
141 static void
142 InsertRow(ftsDB *adb, int id, char *txt) {
143         ftsMY *db = (ftsMY*)adb;
144         static MYSQL_BIND       data[2];
145         static unsigned long    txtlen;
146
147         if ( db->prepareStmt == NULL ) {
148                 db->prepareStmt = mysql_stmt_init(db->conn);
149                 if ( db->prepareStmt == NULL ) {
150                         fprintf(stderr,"mysql_stmt_init failed: %s\n", mysql_error(db->conn));
151                         exit(1);
152                 }
153
154 #define INSERT_QUERY "INSERT INTO ftsbench (id, body) VALUES ( ? , ? );"
155                 if ( mysql_stmt_prepare( db->prepareStmt, INSERT_QUERY, strlen(INSERT_QUERY) ) != 0 ) {
156                         fprintf(stderr,"mysql_stmt_init failed: %s\n", mysql_error(db->conn));
157                         exit(1);
158                 }
159
160                 if ( mysql_stmt_param_count(db->prepareStmt) != 2 ) {
161                         fprintf(stderr,"mysql_stmt_param_count: invalid parameter count\n");
162                         exit(1);
163                 }
164
165                 memset(data, 0, sizeof(data));
166                 data[0].buffer_type = MYSQL_TYPE_LONG;
167                 data[1].buffer_type = MYSQL_TYPE_BLOB;
168                 data[1].length = &txtlen;
169
170         }
171
172         data[0].buffer = &id;
173
174         txtlen = (unsigned long) strlen(txt);
175         data[1].buffer = txt;
176         data[1].buffer_length = txtlen;
177
178         if ( mysql_stmt_bind_param(db->prepareStmt, data) ) {
179                 fprintf(stderr,"mysql_stmt_bind_param failed: %s\n", mysql_error(db->conn));
180                 exit(1);
181         }
182
183         if ( mysql_stmt_execute( db->prepareStmt ) ) {
184                 fprintf(stderr,"mysql_stmt_execute failed: %s\n", mysql_error(db->conn));
185                 exit(1);
186         }
187 }
188
189 ftsDB* 
190 MYInit(char * connstr) {
191         ftsMY   *db = (ftsMY*)malloc(sizeof(ftsMY));
192
193         memset(db,0,sizeof(ftsMY));
194
195         db->conn = mysql_init(NULL);
196
197         if ( !mysql_real_connect(db->conn, NULL, NULL, NULL, connstr, 0, NULL, 0) ) {
198                 fprintf(stderr,"mysql_real_connect failed: %s\n", mysql_error(db->conn));
199                 exit(1);
200         }
201
202         db->db.execQuery = execQuery;
203         db->db.startCreateScheme = startCreateScheme;
204         db->db.finishCreateScheme = finishCreateScheme;
205         db->db.InsertRow = InsertRow;
206         
207         return (ftsDB*)db;
208 }