1 /* Copyright (C) 2000-2001, 2003-2004, 2006 MySQL AB
2    Use is subject to license terms
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */
16 
17 #include <mysql.h>
18 #include <stdio.h>
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 
24 typedef unsigned char uchar;
25 static void die(char* fmt, ...);
26 static void safe_query(MYSQL* mysql, char* query, int read_ok);
27 static void run_query_batch(int* order, int num_queries);
28 static void permute(int *order, int num_queries);
29 static void permute_aux(int *order, int num_queries, int* fixed);
30 static void dump_result(MYSQL* mysql, char* query);
31 
32 int count = 0;
33 
34 
35 struct query
36 {
37   MYSQL* mysql;
38   char* query;
39   int read_ok;
40   int pri;
41   int dump_result;
42 };
43 
44 MYSQL lock, sel, del_ins;
45 
46 struct query queries[] =
47 {
48   {&del_ins, "insert delayed into foo values(1)", 1, 0, 0},
49   {&del_ins, "insert delayed into foo values(1)", 1, 0, 0},
50   {&lock, "lock tables foo write", 1, 1, 0},
51   {&lock, "unlock tables", 1,2, 0},
52   {&sel, "select * from foo", 0,0, 0},
53   {&del_ins, "insert  into foo values(4)", 0,3, 0},
54   {0,0,0}
55 };
56 
die(char * fmt,...)57 static void die(char* fmt, ...)
58 {
59   va_list args;
60   va_start(args, fmt);
61   fprintf(stderr, "ERROR: ");
62   vfprintf(stderr, fmt, args);
63   fprintf(stderr, "\n");
64   va_end(args);
65   exit(1);
66 }
67 
permute(int * order,int num_queries)68 static void permute(int *order, int num_queries)
69 {
70   int *fixed;
71   if(num_queries < 2) return;
72   if(!(fixed = (int*)malloc(num_queries * sizeof(int))))
73     die("malloc() failed");
74 
75   memset(fixed, 0, num_queries * sizeof(int));
76   permute_aux(order, num_queries, fixed);
77 
78   free(fixed);
79 }
80 
order_ok(int * order,int num_queries)81 static order_ok(int *order, int num_queries)
82 {
83   int i,j, pri_i, pri_j;
84   for(i = 0; i < num_queries; i++)
85     {
86       if((pri_i = queries[order[i]].pri))
87 	for(j = i + 1; j < num_queries; j++)
88 	  {
89 	    pri_j = queries[order[j]].pri;
90 	    if(pri_j && pri_i > pri_j)
91 	      return 0;
92 	  }
93     }
94 
95   return 1;
96 }
97 
permute_aux(int * order,int num_queries,int * fixed)98 static void permute_aux(int *order, int num_queries, int* fixed)
99 {
100   int *p,*p1,j,i,tmp, num_free = 0;
101   p = fixed;
102   for(i = 0; i < num_queries; i++, p++)
103     {
104       if(!*p)
105 	{
106 	  num_free++;
107 	  *p = 1;
108 	  for(j = 0, p1 = fixed ;
109 	      j < num_queries; j++,p1++)
110 	    {
111 	      if(!*p1)
112 		{
113 		  tmp = order[i];
114 		  order[i] = order[j];
115 		  order[j] = tmp;
116 		  *p1 = 1;
117 		  permute_aux(order, num_queries, fixed);
118 		  tmp = order[i];
119 		  order[i] = order[j];
120 		  order[j] = tmp;
121 		  *p1 = 0;
122 		}
123 	    }
124 	  *p = 0;
125 	}
126     }
127 
128   /*printf("num_free = %d\n", num_free); */
129 
130   if(num_free <= 1)
131     {
132       count++;
133       if(order_ok(order, num_queries))
134         run_query_batch(order, num_queries);
135     }
136 }
137 
run_query_batch(int * order,int num_queries)138 static void run_query_batch(int* order, int num_queries)
139 {
140   int i;
141   struct query* q;
142   int *save_order;
143   safe_query(&lock, "delete from foo", 1);
144   save_order = order;
145   for(i = 0; i < num_queries; i++,order++)
146     {
147       q = queries + *order;
148       printf("query='%s'\n", q->query);
149       safe_query(q->mysql, q->query, q->read_ok);
150     }
151   order = save_order;
152   for(i = 0; i < num_queries; i++,order++)
153     {
154       q = queries + *order;
155       if(q->dump_result)
156        dump_result(q->mysql, q->query);
157     }
158   printf("\n");
159 
160 }
161 
safe_net_read(NET * net,char * query)162 static void safe_net_read(NET* net, char* query)
163 {
164   int len;
165   len = my_net_read(net);
166   if(len == packet_error || !len)
167     die("Error running query '%s'", query);
168   if(net->read_pos[0] == 255)
169     die("Error running query '%s'", query);
170 }
171 
172 
safe_query(MYSQL * mysql,char * query,int read_ok)173 static void safe_query(MYSQL* mysql, char* query, int read_ok)
174 {
175   int len;
176   NET* net = &mysql->net;
177   net_clear(net);
178   if(net_write_command(net,(uchar)COM_QUERY, query,strlen(query)))
179     die("Error running query '%s': %s", query, mysql_error(mysql));
180   if(read_ok)
181     {
182       safe_net_read(net, query);
183     }
184 }
185 
dump_result(MYSQL * mysql,char * query)186 static void dump_result(MYSQL* mysql, char* query)
187 {
188   MYSQL_RES* res;
189   safe_net_read(&mysql->net, query);
190   res = mysql_store_result(mysql);
191   if(res)
192    mysql_free_result(res);
193 }
194 
init_order(int * num_queries)195 static int* init_order(int* num_queries)
196 {
197   struct query* q;
198   int *order, *order_end, *p;
199   int n,i;
200 
201   for(q = queries; q->mysql; q++)
202     ;
203 
204   n = q - queries;
205   if(!(order = (int*) malloc(n * sizeof(int))))
206     die("malloc() failed");
207   order_end = order + n;
208   for(p = order,i = 0; p < order_end; p++,i++)
209     *p = i;
210   *num_queries = n;
211   return order;
212 }
213 
main()214 int main()
215 {
216   char* user = "root", *pass = "", *host = "localhost", *db = "test";
217   int *order, num_queries;
218   order = init_order(&num_queries);
219   if(!mysql_init(&lock) || !mysql_init(&sel) || !mysql_init(&del_ins))
220     die("error in mysql_init()");
221 
222   mysql_options(&lock, MYSQL_READ_DEFAULT_GROUP, "mysql");
223   mysql_options(&sel, MYSQL_READ_DEFAULT_GROUP, "mysql");
224   mysql_options(&del_ins, MYSQL_READ_DEFAULT_GROUP, "mysql");
225 
226   if(!mysql_real_connect(&lock, host, user, pass, db, 0,0,0 ) ||
227      !mysql_real_connect(&sel, host, user, pass, db, 0,0,0 ) ||
228      !mysql_real_connect(&del_ins, host, user, pass, db, 0,0,0 ))
229     die("Error in mysql_real_connect(): %s", mysql_error(&lock));
230   lock.reconnect= sel.reconnect= del_ins.reconnect= 1;
231 
232   permute(order, num_queries);
233   printf("count = %d\n", count);
234 
235   mysql_close(&lock);
236   mysql_close(&sel);
237   mysql_close(&del_ins);
238   free(order);
239 }
240