SQLsmith  v1.2.1-5-gfacd7a8
A random SQL query generator
sqlite.cc
1 #include <stdexcept>
2 #include <cassert>
3 #include <cstring>
4 #include "sqlite.hh"
5 #include <iostream>
6 
7 #ifndef HAVE_BOOST_REGEX
8 #include <regex>
9 #else
10 #include <boost/regex.hpp>
11 using boost::regex;
12 using boost::smatch;
13 using boost::regex_match;
14 #endif
15 
16 using namespace std;
17 
18 static regex e_syntax("near \".*\": syntax error");
19 static regex e_user_abort("callback requested query abort");
20 
21 extern "C" {
22 #include <sqlite3.h>
23 #include <unistd.h>
24 }
25 
26 extern "C" int my_sqlite3_busy_handler(void *, int)
27 {
28  throw std::runtime_error("sqlite3 timeout");
29 }
30 
31 extern "C" int callback(void *arg, int argc, char **argv, char **azColName)
32 {
33  (void)arg;
34 
35  int i;
36  for(i=0; i<argc; i++){
37  printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
38  }
39  printf("\n");
40  return 0;
41 }
42 
43 extern "C" int table_callback(void *arg, int argc, char **argv, char **azColName)
44 {
45  (void) argc; (void) azColName;
46  auto tables = (vector<table> *)arg;
47  bool view = (string("view") == argv[0]);
48  table tab(argv[2], "main", !view, !view);
49  tables->push_back(tab);
50  return 0;
51 }
52 
53 extern "C" int column_callback(void *arg, int argc, char **argv, char **azColName)
54 {
55  (void) argc; (void) azColName;
56  table *tab = (table *)arg;
57  column c(argv[1], sqltype::get(argv[2]));
58  tab->columns().push_back(c);
59  return 0;
60 }
61 
62 sqlite_connection::sqlite_connection(std::string &conninfo)
63 {
64  assert(sqlite3_libversion_number()==SQLITE_VERSION_NUMBER);
65  assert(strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0);
66  assert(strcmp(sqlite3_libversion(),SQLITE_VERSION)==0);
67  rc = sqlite3_open_v2(conninfo.c_str(), &db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_URI, 0);
68  if (rc) {
69  throw std::runtime_error(sqlite3_errmsg(db));
70  }
71 }
72 
73 void sqlite_connection::q(const char *query)
74 {
75  rc = sqlite3_exec(db, query, callback, 0, &zErrMsg);
76  if( rc!=SQLITE_OK ){
77  auto e = std::runtime_error(zErrMsg);
78  sqlite3_free(zErrMsg);
79  throw e;
80  }
81 }
82 
83 sqlite_connection::~sqlite_connection()
84 {
85  if (db)
86  sqlite3_close(db);
87 }
88 
89 schema_sqlite::schema_sqlite(std::string &conninfo, bool no_catalog)
90  : sqlite_connection(conninfo)
91 {
92  std::string query = "SELECT * FROM main.sqlite_master where type in ('table', 'view')";
93 
94  if (no_catalog)
95  query+= " AND name NOT like 'sqlite_%%'";
96 
97  version = "SQLite " SQLITE_VERSION " " SQLITE_SOURCE_ID;
98 
99 // sqlite3_busy_handler(db, my_sqlite3_busy_handler, 0);
100  cerr << "Loading tables...";
101 
102  rc = sqlite3_exec(db, query.c_str(), table_callback, (void *)&tables, &zErrMsg);
103  if (rc!=SQLITE_OK) {
104  auto e = std::runtime_error(zErrMsg);
105  sqlite3_free(zErrMsg);
106  throw e;
107  }
108 
109  if (!no_catalog)
110  {
111  // sqlite_master doesn't list itself, do it manually
112  table tab("sqlite_master", "main", false, false);
113  tables.push_back(tab);
114  }
115 
116  cerr << "done." << endl;
117 
118  cerr << "Loading columns and constraints...";
119 
120  for (auto t = tables.begin(); t != tables.end(); ++t) {
121  string q("pragma table_info(");
122  q += t->name;
123  q += ");";
124 
125  rc = sqlite3_exec(db, q.c_str(), column_callback, (void *)&*t, &zErrMsg);
126  if (rc!=SQLITE_OK) {
127  auto e = std::runtime_error(zErrMsg);
128  sqlite3_free(zErrMsg);
129  throw e;
130  }
131  }
132 
133  cerr << "done." << endl;
134 
135 #define BINOP(n,t) do {op o(#n,sqltype::get(#t),sqltype::get(#t),sqltype::get(#t)); register_operator(o); } while(0)
136 
137  BINOP(||, TEXT);
138  BINOP(*, INTEGER);
139  BINOP(/, INTEGER);
140 
141  BINOP(+, INTEGER);
142  BINOP(-, INTEGER);
143 
144  BINOP(>>, INTEGER);
145  BINOP(<<, INTEGER);
146 
147  BINOP(&, INTEGER);
148  BINOP(|, INTEGER);
149 
150  BINOP(<, INTEGER);
151  BINOP(<=, INTEGER);
152  BINOP(>, INTEGER);
153  BINOP(>=, INTEGER);
154 
155  BINOP(=, INTEGER);
156  BINOP(<>, INTEGER);
157  BINOP(IS, INTEGER);
158  BINOP(IS NOT, INTEGER);
159 
160  BINOP(AND, INTEGER);
161  BINOP(OR, INTEGER);
162 
163 #define FUNC(n,r) do { \
164  routine proc("", "", sqltype::get(#r), #n); \
165  register_routine(proc); \
166  } while(0)
167 
168 #define FUNC1(n,r,a) do { \
169  routine proc("", "", sqltype::get(#r), #n); \
170  proc.argtypes.push_back(sqltype::get(#a)); \
171  register_routine(proc); \
172  } while(0)
173 
174 #define FUNC2(n,r,a,b) do { \
175  routine proc("", "", sqltype::get(#r), #n); \
176  proc.argtypes.push_back(sqltype::get(#a)); \
177  proc.argtypes.push_back(sqltype::get(#b)); \
178  register_routine(proc); \
179  } while(0)
180 
181 #define FUNC3(n,r,a,b,c) do { \
182  routine proc("", "", sqltype::get(#r), #n); \
183  proc.argtypes.push_back(sqltype::get(#a)); \
184  proc.argtypes.push_back(sqltype::get(#b)); \
185  proc.argtypes.push_back(sqltype::get(#c)); \
186  register_routine(proc); \
187  } while(0)
188 
189  FUNC(last_insert_rowid, INTEGER);
190  FUNC(random, INTEGER);
191  FUNC(sqlite_source_id, TEXT);
192  FUNC(sqlite_version, TEXT);
193  FUNC(total_changes, INTEGER);
194 
195  FUNC1(abs, INTEGER, REAL);
196  FUNC1(hex, TEXT, TEXT);
197  FUNC1(length, INTEGER, TEXT);
198  FUNC1(lower, TEXT, TEXT);
199  FUNC1(ltrim, TEXT, TEXT);
200  FUNC1(quote, TEXT, TEXT);
201  FUNC1(randomblob, TEXT, INTEGER);
202  FUNC1(round, INTEGER, REAL);
203  FUNC1(rtrim, TEXT, TEXT);
204  FUNC1(soundex, TEXT, TEXT);
205  FUNC1(sqlite_compileoption_get, TEXT, INTEGER);
206  FUNC1(sqlite_compileoption_used, INTEGER, TEXT);
207  FUNC1(trim, TEXT, TEXT);
208  FUNC1(typeof, TEXT, INTEGER);
209  FUNC1(typeof, TEXT, NUMERIC);
210  FUNC1(typeof, TEXT, REAL);
211  FUNC1(typeof, TEXT, TEXT);
212  FUNC1(unicode, INTEGER, TEXT);
213  FUNC1(upper, TEXT, TEXT);
214  FUNC1(zeroblob, TEXT, INTEGER);
215 
216  FUNC2(glob, INTEGER, TEXT, TEXT);
217  FUNC2(instr, INTEGER, TEXT, TEXT);
218  FUNC2(like, INTEGER, TEXT, TEXT);
219  FUNC2(ltrim, TEXT, TEXT, TEXT);
220  FUNC2(rtrim, TEXT, TEXT, TEXT);
221  FUNC2(trim, TEXT, TEXT, TEXT);
222  FUNC2(round, INTEGER, REAL, INTEGER);
223  FUNC2(substr, TEXT, TEXT, INTEGER);
224 
225  FUNC3(substr, TEXT, TEXT, INTEGER, INTEGER);
226  FUNC3(replace, TEXT, TEXT, TEXT, TEXT);
227 
228 
229 #define AGG(n,r, a) do { \
230  routine proc("", "", sqltype::get(#r), #n); \
231  proc.argtypes.push_back(sqltype::get(#a)); \
232  register_aggregate(proc); \
233  } while(0)
234 
235  AGG(avg, INTEGER, INTEGER);
236  AGG(avg, REAL, REAL);
237  AGG(count, INTEGER, REAL);
238  AGG(count, INTEGER, TEXT);
239  AGG(count, INTEGER, INTEGER);
240  AGG(group_concat, TEXT, TEXT);
241  AGG(max, REAL, REAL);
242  AGG(max, INTEGER, INTEGER);
243  AGG(sum, REAL, REAL);
244  AGG(sum, INTEGER, INTEGER);
245  AGG(total, REAL, INTEGER);
246  AGG(total, REAL, REAL);
247 
248  booltype = sqltype::get("INTEGER");
249  inttype = sqltype::get("INTEGER");
250 
251  internaltype = sqltype::get("internal");
252  arraytype = sqltype::get("ARRAY");
253 
254  true_literal = "1";
255  false_literal = "0";
256 
257  generate_indexes();
258  sqlite3_close(db);
259  db = 0;
260 }
261 
262 dut_sqlite::dut_sqlite(std::string &conninfo)
263  : sqlite_connection(conninfo)
264 {
265  q("PRAGMA main.auto_vacuum = 2");
266 }
267 
268 extern "C" int dut_callback(void *arg, int argc, char **argv, char **azColName)
269 {
270  (void) arg; (void) argc; (void) argv; (void) azColName;
271  return SQLITE_ABORT;
272 }
273 
274 void dut_sqlite::test(const std::string &stmt)
275 {
276  alarm(6);
277  rc = sqlite3_exec(db, stmt.c_str(), dut_callback, 0, &zErrMsg);
278  if( rc!=SQLITE_OK ){
279  try {
280  if (regex_match(zErrMsg, e_syntax))
281  throw dut::syntax(zErrMsg);
282  else if (regex_match(zErrMsg, e_user_abort)) {
283  sqlite3_free(zErrMsg);
284  return;
285  } else
286  throw dut::failure(zErrMsg);
287  } catch (dut::failure &e) {
288  sqlite3_free(zErrMsg);
289  throw;
290  }
291  }
292 }
293 
schema and dut classes for SQLite 3