3 #include "sqlite++/sqlite.hxx"
17 db_.
execute (
"CREATE TABLE IF NOT EXISTS files ("
18 " id INTEGER PRIMARY KEY,"
22 db_.
execute (
"CREATE TABLE IF NOT EXISTS commands ("
23 " fileId INTEGER REFERENCES files(id),"
27 db_.
execute (
"CREATE TABLE IF NOT EXISTS includes ("
28 " sourceId INTEGER REFERENCES files(id),"
29 " includedId INTEGER REFERENCES files(id)"
31 db_.
execute (
"CREATE TABLE IF NOT EXISTS tags ("
32 " fileId INTEGER REFERENCES files(id),"
44 db_.
execute (
"CREATE TABLE IF NOT EXISTS options ( "
50 int setCompileCommand (
const std::string & fileName,
51 const std::string & directory,
52 const std::vector<std::string> & args) {
53 int fileId = addFile_ (fileName);
54 addInclude (fileId, fileId);
56 db_.
prepare (
"DELETE FROM commands "
61 db_.
prepare (
"INSERT INTO commands VALUES (?,?,?)")
64 .
bind (serialize_ (args))
70 void getCompileCommand (
const std::string & fileName,
71 std::string & directory,
72 std::vector<std::string> & args) {
73 int fileId = fileId_ (fileName);
75 = db_.
prepare (
"SELECT commands.directory, commands.args "
77 "INNER JOIN commands ON includes.sourceId = commands.fileId "
78 "WHERE includes.includedId = ?")
81 switch (stmt.
step()) {
83 throw std::runtime_error (
"no compilation command for file `"
87 std::string serializedArgs;
88 stmt >> directory >> serializedArgs;
89 deserialize_ (serializedArgs, args);
93 std::string nextFile () {
95 = db_.
prepare (
"SELECT included.name, included.indexed, source.name, "
96 " count(source.name) AS sourceCount "
98 "INNER JOIN files AS source ON source.id = includes.sourceId "
99 "INNER JOIN files AS included ON included.id = includes.includedId "
100 "GROUP BY included.id "
101 "ORDER BY sourceCount ");
102 while (stmt.
step() == SQLITE_ROW) {
103 std::string includedName;
105 std::string sourceName;
106 stmt >> includedName >> indexed >> sourceName;
108 struct stat fileStat;
109 stat (includedName.c_str(), &fileStat);
110 int modified = fileStat.st_mtime;
112 if (modified > indexed) {
121 db_.
execute (
"DELETE FROM tags");
122 db_.
execute (
"UPDATE files SET indexed = 0");
126 db_.
execute (
"BEGIN TRANSACTION");
130 db_.
execute (
"END TRANSACTION");
133 bool beginFile (
const std::string & fileName) {
134 int fileId = addFile_ (fileName);
139 = db_.
prepare (
"SELECT indexed FROM files WHERE id = ?")
145 struct stat fileStat;
146 stat (fileName.c_str(), &fileStat);
147 int modified = fileStat.st_mtime;
149 if (modified > indexed) {
151 db_.
prepare (
"DELETE FROM includes WHERE sourceId=?").
bind (fileId).
step();
164 void addInclude (
const int includedId,
167 int res = db_.
prepare (
"SELECT * FROM includes "
172 if (res == SQLITE_DONE) {
173 db_.
prepare (
"INSERT INTO includes VALUES (?,?)")
174 .
bind (sourceId) . bind (includedId)
179 void addInclude (
const std::string & includedFile,
180 const std::string & sourceFile) {
181 int includedId = fileId_ (includedFile);
182 int sourceId = fileId_ (sourceFile);
183 if (includedId == -1 || sourceId == -1)
184 throw std::runtime_error (
"Cannot add inclusion for unknown files `"
185 + includedFile +
"' and `" + sourceFile +
"'");
186 addInclude (includedId, sourceId);
189 void addTag (
const std::string & usr,
190 const std::string & kind,
191 const std::string & spelling,
192 const std::string & fileName,
193 const int line1,
const int col1,
const int offset1,
194 const int line2,
const int col2,
const int offset2,
195 bool isDeclaration) {
196 int fileId = fileId_ (fileName);
202 db_.
prepare (
"SELECT * FROM tags "
208 if (stmt.
step() == SQLITE_DONE) {
209 db_.
prepare (
"INSERT INTO tags VALUES (?,?,?,?,?,?,?,?,?,?,?)")
227 std::string spelling;
229 Json::Value json ()
const {
232 json[
"line1"] = line1;
233 json[
"line2"] = line2;
236 json[
"offset1"] = offset1;
237 json[
"offset2"] = offset2;
239 json[
"spelling"] = spelling;
252 std::string spelling;
254 Json::Value json ()
const {
258 json[
"line1"] = line1;
259 json[
"line2"] = line2;
263 json[
"spelling"] = spelling;
272 Json::Value json ()
const {
274 json[
"ref"] = ref.json();
275 json[
"def"] = def.json();
280 std::vector<RefDef> findDefinition (
const std::string fileName,
282 int fileId = fileId_ (fileName);
284 db_.
prepare (
"SELECT ref.offset1, ref.offset2, ref.kind, ref.spelling,"
285 " def.usr, defFile.name,"
286 " def.line1, def.line2, def.col1, def.col2, "
287 " def.kind, def.spelling "
289 "INNER JOIN tags AS def ON def.usr = ref.usr "
290 "INNER JOIN files AS defFile ON def.fileId = defFile.id "
291 "WHERE def.isDecl = 1 "
292 " AND ref.fileId = ? "
293 " AND ref.offset1 <= ? "
294 " AND ref.offset2 >= ? "
295 "ORDER BY (ref.offset2 - ref.offset1)")
300 std::vector<RefDef> ret;
301 while (stmt.
step() == SQLITE_ROW) {
306 stmt >> ref.offset1 >> ref.offset2 >> ref.kind >> ref.spelling
307 >> def.usr >> def.file
308 >> def.line1 >> def.line2 >> def.col1 >> def.col2
309 >> def.kind >> def.spelling;
311 ret.push_back(refDef);
316 std::vector<Reference> grep (
const std::string usr) {
318 db_.
prepare(
"SELECT ref.line1, ref.line2, ref.col1, ref.col2, "
319 " ref.offset1, ref.offset2, refFile.name, ref.kind "
321 "INNER JOIN files AS refFile ON ref.fileId = refFile.id "
325 std::vector<Reference> ret;
326 while (stmt.
step() == SQLITE_ROW) {
328 stmt >> ref.line1 >> ref.line2 >> ref.col1 >> ref.col2
329 >> ref.offset1 >> ref.offset2 >> ref.file >> ref.kind;
335 void setOption (
const std::string & name,
const std::string & value) {
336 db_.
prepare (
"DELETE FROM options "
341 db_.
prepare (
"INSERT INTO options "
348 void setOption (
const std::string & name,
const std::vector<std::string> & value) {
349 setOption (name, serialize_(value));
353 std::string getOption (
const std::string & name) {
355 db_.
prepare (
"SELECT value FROM options "
360 if (stmt.
step() == SQLITE_ROW) {
363 throw std::runtime_error (
"No stored value for option: `" + name +
"'");
370 std::vector<std::string> getOption (
const std::string & name,
const Vector & v) {
371 std::vector<std::string> ret;
372 deserialize_ (getOption (name), ret);
377 int fileId_ (
const std::string & fileName) {
379 = db_.
prepare (
"SELECT id FROM files WHERE name=?")
383 if (stmt.
step() == SQLITE_ROW) {
390 int addFile_ (
const std::string & fileName) {
391 int id = fileId_ (fileName);
393 db_.
prepare (
"INSERT INTO files VALUES (NULL, ?, 0)")
402 std::string serialize_ (
const std::vector<std::string> & v) {
406 for ( ; it != end ; ++it) {
410 Json::FastWriter writer;
411 return writer.write (json);
414 void deserialize_ (
const std::string & s, std::vector<std::string> & v) {
417 if (! reader.parse (s, json)) {
418 throw std::runtime_error (reader.getFormattedErrorMessages());
421 for (
int i=0 ; i<json.size() ; ++i) {
422 v.push_back (json[i].asString());