My Project
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sqlite3gen.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2015 by Dimitri van Heesch.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation under the terms of the GNU General Public License is hereby
7  * granted. No representations are made about the suitability of this software
8  * for any purpose. It is provided "as is" without express or implied warranty.
9  * See the GNU General Public License for more details.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15 
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include "settings.h"
19 #include "message.h"
20 
21 #if USE_SQLITE3
22 
23 #include "qtbc.h"
24 #include "sqlite3gen.h"
25 #include "doxygen.h"
26 #include "config.h"
27 #include "util.h"
28 #include "docparser.h"
29 #include "language.h"
30 
31 #include "dot.h"
32 #include "arguments.h"
33 #include "classlist.h"
34 #include "filedef.h"
35 #include "namespacedef.h"
36 #include "filename.h"
37 #include "groupdef.h"
38 #include "pagedef.h"
39 #include "dirdef.h"
40 
41 #include <qdir.h>
42 #include <string.h>
43 #include <sqlite3.h>
44 
45 //#define DBG_CTX(x) printf x
46 #define DBG_CTX(x) do { } while(0)
47 
48 const char * schema_queries[][2] = {
49  { "includes",
50  "CREATE TABLE IF NOT EXISTS includes (\n"
51  "\t-- #include relations.\n"
52  "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
53  "\tlocal INTEGER NOT NULL,\n"
54  "\tid_src INTEGER NOT NULL, -- File id of the includer.\n"
55  "\tid_dst INTEGER NOT NULL -- File id of the includee.\n"
56  ");\n"
57  "CREATE UNIQUE INDEX idx_includes ON includes\n"
58  "\t(local, id_src, id_dst);"
59  },
60  { "innerclass",
61  "CREATE TABLE IF NOT EXISTS innerclass (\n"
62  "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
63  "\trefid INTEGER NOT NULL,\n"
64  "\tprot INTEGER NOT NULL,\n"
65  "\tname TEXT NOT NULL\n"
66  ");"
67  },
68  { "files",
69  "CREATE TABLE IF NOT EXISTS files (\n"
70  "\t-- Names of source files and includes.\n"
71  "\tname TEXT PRIMARY KEY NOT NULL\n"
72  ");"
73  },
74  { "refids",
75  "CREATE TABLE IF NOT EXISTS refids (\n"
76  "\trefid TEXT PRIMARY KEY NOT NULL\n"
77  ");"
78  },
79  { "xrefs",
80  "CREATE TABLE IF NOT EXISTS xrefs (\n"
81  "\t-- Cross reference relation.\n"
82  "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
83  "\trefid_src INTEGER NOT NULL, -- referrer id.\n"
84  "\trefid_dst INTEGER NOT NULL, -- referee id.\n"
85  "\tid_file INTEGER NOT NULL, -- file where the reference is happening.\n"
86  "\tline INTEGER NOT NULL, -- line where the reference is happening.\n"
87  "\tcolumn INTEGER NOT NULL -- column where the reference is happening.\n"
88  ");\n"
89  "CREATE UNIQUE INDEX idx_xrefs ON xrefs\n"
90  "\t(refid_src, refid_dst, id_file, line, column);"
91  },
92  { "memberdef",
93  "CREATE TABLE IF NOT EXISTS memberdef (\n"
94  "\t-- All processed identifiers.\n"
95  "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
96  "\trefid INTEGER NOT NULL, -- see the refids table\n"
97  "\tname TEXT NOT NULL,\n"
98  "\tdefinition TEXT,\n"
99  "\ttype TEXT,\n"
100  "\targsstring TEXT,\n"
101  "\tscope TEXT,\n"
102  "\tinitializer TEXT,\n"
103  "\tbitfield TEXT,\n"
104  "\tread TEXT,\n"
105  "\twrite TEXT,\n"
106  "\tprot INTEGER DEFAULT 0, -- 0:public 1:protected 2:private 3:package\n"
107  "\tstatic INTEGER DEFAULT 0, -- 0:no 1:yes\n"
108  "\tconst INTEGER DEFAULT 0, -- 0:no 1:yes\n"
109  "\texplicit INTEGER DEFAULT 0, -- 0:no 1:yes\n"
110  "\tinline INTEGER DEFAULT 0, -- 0:no 1:yes\n"
111  "\tfinal INTEGER DEFAULT 0, -- 0:no 1:yes\n"
112  "\tsealed INTEGER DEFAULT 0, -- 0:no 1:yes\n"
113  "\tnew INTEGER DEFAULT 0, -- 0:no 1:yes\n"
114  "\toptional INTEGER DEFAULT 0, -- 0:no 1:yes\n"
115  "\trequired INTEGER DEFAULT 0, -- 0:no 1:yes\n"
116  "\tvolatile INTEGER DEFAULT 0, -- 0:no 1:yes\n"
117  "\tvirt INTEGER DEFAULT 0, -- 0:no 1:virtual 2:pure-virtual\n"
118  "\tmutable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
119  "\tinitonly INTEGER DEFAULT 0, -- 0:no 1:yes\n"
120  "\tattribute INTEGER DEFAULT 0, -- 0:no 1:yes\n"
121  "\tproperty INTEGER DEFAULT 0, -- 0:no 1:yes\n"
122  "\treadonly INTEGER DEFAULT 0, -- 0:no 1:yes\n"
123  "\tbound INTEGER DEFAULT 0, -- 0:no 1:yes\n"
124  "\tconstrained INTEGER DEFAULT 0, -- 0:no 1:yes\n"
125  "\ttransient INTEGER DEFAULT 0, -- 0:no 1:yes\n"
126  "\tmaybevoid INTEGER DEFAULT 0, -- 0:no 1:yes\n"
127  "\tmaybedefault INTEGER DEFAULT 0, -- 0:no 1:yes\n"
128  "\tmaybeambiguous INTEGER DEFAULT 0, -- 0:no 1:yes\n"
129  "\treadable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
130  "\twritable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
131  "\tgettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
132  "\tprivategettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
133  "\tprotectedgettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
134  "\tsettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
135  "\tprivatesettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
136  "\tprotectedsettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
137  "\taccessor INTEGER DEFAULT 0, -- 0:no 1:assign 2:copy 3:retain 4:string 5:weak\n"
138  "\taddable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
139  "\tremovable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
140  "\traisable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
142  "\tkind INTEGER DEFAULT 0, -- 0:define 1:function 2:variable 3:typedef 4:enum 5:enumvalue 6:signal 7:slot 8:friend 9:DCOP 10:property 11:event\n"
143  "\tbodystart INTEGER DEFAULT 0, -- starting line of definition\n"
144  "\tbodyend INTEGER DEFAULT 0, -- ending line of definition\n"
145  "\tid_bodyfile INTEGER DEFAULT 0, -- file of definition\n"
146  "\tid_file INTEGER NOT NULL, -- file where this identifier is located\n"
147  "\tline INTEGER NOT NULL, -- line where this identifier is located\n"
148  "\tcolumn INTEGER NOT NULL, -- column where this identifier is located\n"
150  "\tdetaileddescription TEXT,\n"
151  "\tbriefdescription TEXT,\n"
152  "\tinbodydescription TEXT\n"
153  ");"
154  },
155  { "compounddef",
156  "CREATE TABLE IF NOT EXISTS compounddef (\n"
157  "\t-- class/struct definitions.\n"
158  "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
159  "\tname TEXT NOT NULL,\n"
160  "\tkind TEXT NOT NULL,\n"
161  "\trefid INTEGER NOT NULL,\n"
162  "\tprot INTEGER NOT NULL,\n"
163  "\tid_file INTEGER NOT NULL,\n"
164  "\tline INTEGER NOT NULL,\n"
165  "\tcolumn INTEGER NOT NULL\n"
166  ");"
167  },
168  { "basecompoundref",
169  "CREATE TABLE IF NOT EXISTS basecompoundref (\n"
170  "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
171  "\tbase TEXT NOT NULL,\n"
172  "\tderived TEXT NOT NULL,\n"
173  "\trefid INTEGER NOT NULL,\n"
174  "\tprot INTEGER NOT NULL,\n"
175  "\tvirt INTEGER NOT NULL\n"
176  ");"
177  },
178  { "derivedcompoundref",
179  "CREATE TABLE IF NOT EXISTS derivedcompoundref (\n"
180  "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
181  "\tbase TEXT NOT NULL,\n"
182  "\tderived TEXT NOT NULL,\n"
183  "\trefid INTEGER NOT NULL,\n"
184  "\tprot INTEGER NOT NULL,\n"
185  "\tvirt INTEGER NOT NULL\n"
186  ");"
187  },
188  { "params",
189  "CREATE TABLE IF NOT EXISTS params (\n"
190  "\t-- All processed parameters.\n"
191  "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
192  "\tattributes TEXT,\n"
193  "\ttype TEXT,\n"
194  "\tdeclname TEXT,\n"
195  "\tdefname TEXT,\n"
196  "\tarray TEXT,\n"
197  "\tdefval TEXT,\n"
198  "\tbriefdescription TEXT\n"
199  ");"
200  },
201  { "memberdef_params",
202  "CREATE TABLE IF NOT EXISTS memberdef_params (\n"
203  "\t-- Junction table for memberdef parameters.\n"
204  "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
205  "\tid_memberdef INTEGER NOT NULL,\n"
206  "\tid_param INTEGER NOT NULL\n"
207  ");"
208  },
209  { "innernamespaces",
210  "CREATE TABLE IF NOT EXISTS innernamespaces (\n"
211  "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
212  "\trefid INTEGER NOT NULL,\n"
213  "\tname TEXT NOT NULL\n"
214  ");"
215  }
216 };
217 
219 struct SqlStmt {
220  const char *query;
221  sqlite3_stmt *stmt;
222 };
224 SqlStmt incl_insert = { "INSERT INTO includes "
225  "( local, id_src, id_dst ) "
226  "VALUES "
227  "(:local,:id_src,:id_dst )"
228  ,NULL
229 };
230 SqlStmt incl_select = { "SELECT COUNT(*) FROM includes WHERE "
231  "local=:local AND id_src=:id_src AND id_dst=:id_dst"
232  ,NULL
233 };
235 SqlStmt innerclass_insert={"INSERT INTO innerclass "
236  "( refid, prot, name )"
237  "VALUES "
238  "(:refid,:prot,:name )"
239  ,NULL
240 };
242 SqlStmt files_select = {"SELECT rowid FROM files WHERE name=:name"
243  ,NULL
244 };
245 SqlStmt files_insert = {"INSERT INTO files "
246  "( name )"
247  "VALUES "
248  "(:name )"
249  ,NULL
250 };
252 SqlStmt refids_select = {"SELECT rowid FROM refids WHERE "
253  "refid=:refid"
254  ,NULL
255 };
256 SqlStmt refids_insert = {"INSERT INTO refids "
257  "( refid )"
258  "VALUES "
259  "(:refid )"
260  ,NULL
261 };
263 SqlStmt xrefs_insert= {"INSERT INTO xrefs "
264  "( refid_src, refid_dst, id_file, line, column )"
265  "VALUES "
266  "(:refid_src,:refid_dst,:id_file,:line,:column )"
267  ,NULL
268 };
270 SqlStmt memberdef_insert={"INSERT INTO memberdef "
271  "("
272  "refid,"
273  "name,"
274  "definition,"
275  "type,"
276  "argsstring,"
277  "scope,"
278  "initializer,"
279  "bitfield,"
280  "read,"
281  "write,"
282  "prot,"
283  "static,"
284  "const,"
285  "explicit,"
286  "inline,"
287  "final,"
288  "sealed,"
289  "new,"
290  "optional,"
291  "required,"
292  "volatile,"
293  "virt,"
294  "mutable,"
295  "initonly,"
296  "attribute,"
297  "property,"
298  "readonly,"
299  "bound,"
300  "constrained,"
301  "transient,"
302  "maybevoid,"
303  "maybedefault,"
304  "maybeambiguous,"
305  "readable,"
306  "writable,"
307  "gettable,"
308  "protectedsettable,"
309  "protectedgettable,"
310  "settable,"
311  "privatesettable,"
312  "privategettable,"
313  "accessor,"
314  "addable,"
315  "removable,"
316  "raisable,"
317  "kind,"
318  "bodystart,"
319  "bodyend,"
320  "id_bodyfile,"
321  "id_file,"
322  "line,"
323  "column,"
324  "detaileddescription,"
325  "briefdescription,"
326  "inbodydescription"
327  ")"
328  "VALUES "
329  "("
330  ":refid,"
331  ":name,"
332  ":definition,"
333  ":type,"
334  ":argsstring,"
335  ":scope,"
336  ":initializer,"
337  ":bitfield,"
338  ":read,"
339  ":write,"
340  ":prot,"
341  ":static,"
342  ":const,"
343  ":explicit,"
344  ":inline,"
345  ":final,"
346  ":sealed,"
347  ":new,"
348  ":optional,"
349  ":required,"
350  ":volatile,"
351  ":virt,"
352  ":mutable,"
353  ":initonly,"
354  ":attribute,"
355  ":property,"
356  ":readonly,"
357  ":bound,"
358  ":constrained,"
359  ":transient,"
360  ":maybevoid,"
361  ":maybedefault,"
362  ":maybeambiguous,"
363  ":readable,"
364  ":writable,"
365  ":gettable,"
366  ":privategettable,"
367  ":protectedgettable,"
368  ":settable,"
369  ":privatesettable,"
370  ":privategettable,"
371  ":accessor,"
372  ":addable,"
373  ":removable,"
374  ":raisable,"
375  ":kind,"
376  ":bodystart,"
377  ":bodyend,"
378  ":id_bodyfile,"
379  ":id_file,"
380  ":line,"
381  ":column,"
382  ":detaileddescription,"
383  ":briefdescription,"
384  ":inbodydescription"
385  ")"
386  ,NULL
387 };
389 SqlStmt compounddef_insert={"INSERT INTO compounddef "
390  "( name, kind, prot, refid, id_file, line, column ) "
391  "VALUES "
392  "(:name,:kind,:prot,:refid,:id_file,:line,:column )"
393  ,NULL
394 };
396 SqlStmt basecompoundref_insert={"INSERT INTO basecompoundref "
397  "( base, derived, refid, prot, virt ) "
398  "VALUES "
399  "(:base,:derived,:refid,:prot,:virt )"
400  ,NULL
401 };
403 SqlStmt derivedcompoundref_insert={"INSERT INTO derivedcompoundref "
404  "( refid, prot, virt, base, derived ) "
405  "VALUES "
406  "(:refid,:prot,:virt,:base,:derived )"
407  ,NULL
408 };
410 SqlStmt params_select = { "SELECT rowid FROM params WHERE "
411  "(attributes IS NULL OR attributes=:attributes) AND "
412  "(type IS NULL OR type=:type) AND "
413  "(declname IS NULL OR declname=:declname) AND "
414  "(defname IS NULL OR defname=:defname) AND "
415  "(array IS NULL OR array=:array) AND "
416  "(defval IS NULL OR defval=:defval) AND "
417  "(briefdescription IS NULL OR briefdescription=:briefdescription)"
418  ,NULL
419 };
420 SqlStmt params_insert = { "INSERT INTO params "
421  "( attributes, type, declname, defname, array, defval, briefdescription ) "
422  "VALUES "
423  "(:attributes,:type,:declname,:defname,:array,:defval,:briefdescription)"
424  ,NULL
425 };
427 SqlStmt memberdef_params_insert={ "INSERT INTO memberdef_params "
428  "( id_memberdef, id_param)"
429  "VALUES "
430  "(:id_memberdef,:id_param)"
431  ,NULL
432 };
434 SqlStmt innernamespace_insert={"INSERT INTO innernamespaces "
435  "( refid, name)"
436  "VALUES "
437  "(:refid,:name)",
438  NULL
439 };
440 
441 
442 class TextGeneratorSqlite3Impl : public TextGeneratorIntf
443 {
444  public:
445  TextGeneratorSqlite3Impl(StringList &l) : l(l) {
446  l.setAutoDelete(TRUE);
447  }
448  void writeString(const char * /*s*/,bool /*keepSpaces*/) const
449  {
450  }
451  void writeBreak(int) const
452  {
453  DBG_CTX(("writeBreak\n"));
454  }
455  void writeLink(const char * /*extRef*/,const char *file,
456  const char *anchor,const char * /*text*/
457  ) const
458  {
459  QCString *rs=new QCString(file);
460  if (anchor)
461  {
462  rs->append("_1").append(anchor);
463  }
464  l.append(rs);
465  }
466  private:
467  StringList &l;
468  // the list is filled by linkifyText and consumed by the caller
469 };
470 
471 
472 static void bindTextParameter(SqlStmt &s,const char *name,const char *value, bool _static=TRUE)
473 {
474  int idx = sqlite3_bind_parameter_index(s.stmt, name);
475  sqlite3_bind_text(s.stmt, idx, value, -1, _static==TRUE?SQLITE_STATIC:SQLITE_TRANSIENT);
476 }
477 
478 static void bindIntParameter(SqlStmt &s,const char *name,int value)
479 {
480  int idx = sqlite3_bind_parameter_index(s.stmt, name);
481  sqlite3_bind_int(s.stmt, idx, value);
482 }
483 
484 static int step(sqlite3 *db, SqlStmt &s,bool getRowId=FALSE, bool select=FALSE)
485 {
486  int rowid=-1;
487  int rc = sqlite3_step(s.stmt);
488  if (rc!=SQLITE_DONE && rc!=SQLITE_ROW)
489  {
490  msg("sqlite3_step failed: %s\n", sqlite3_errmsg(db));
491  sqlite3_clear_bindings(s.stmt);
492  return -1;
493  }
494  if (getRowId && select) rowid = sqlite3_column_int(s.stmt, 0); // works on selects, doesnt on inserts
495  if (getRowId && !select) rowid = sqlite3_last_insert_rowid(db); //works on inserts, doesnt on selects
496  sqlite3_reset(s.stmt);
497  sqlite3_clear_bindings(s.stmt); // XXX When should this really be called
498  return rowid;
499 }
500 
501 static int insertFile(sqlite3 *db, const char* name)
502 {
503  int rowid=-1;
504  if (name==0) return rowid;
505 
506  bindTextParameter(files_select,":name",name);
507  rowid=step(db,files_select,TRUE,TRUE);
508  if (rowid==0)
509  {
510  bindTextParameter(files_insert,":name",name);
511  rowid=step(db,files_insert,TRUE);
512  }
513  return rowid;
514 }
515 
516 static int insertRefid(sqlite3 *db, const char *refid)
517 {
518  int rowid=-1;
519  if (refid==0) return rowid;
520 
521  bindTextParameter(refids_select,":refid",refid);
522  rowid=step(db,refids_select,TRUE,TRUE);
523  if (rowid==0)
524  {
525  bindTextParameter(refids_insert,":refid",refid);
526  rowid=step(db,refids_insert,TRUE);
527  }
528  return rowid;
529 }
530 
531 
532 static void insertMemberReference(sqlite3 *db, int refid_src, int refid_dst,
533  int id_file, int line, int column)
534 {
535  if (id_file==-1||refid_src==-1||refid_dst==-1)
536  return;
537 
538  bindIntParameter(xrefs_insert,":refid_src",refid_src);
539  bindIntParameter(xrefs_insert,":refid_dst",refid_dst);
540  bindIntParameter(xrefs_insert,":id_file",id_file);
541  bindIntParameter(xrefs_insert,":line",line);
542  bindIntParameter(xrefs_insert,":column",column);
543  step(db,xrefs_insert);
544 }
545 
546 static void insertMemberReference(sqlite3 *db, MemberDef *src, MemberDef *dst)
547 {
548  QCString qrefid_dst = dst->getOutputFileBase() + "_1" + dst->anchor();
549  QCString qrefid_src = src->getOutputFileBase() + "_1" + src->anchor();
550  if (dst->getStartBodyLine()!=-1 && dst->getBodyDef())
551  {
552  int refid_src = insertRefid(db,qrefid_src.data());
553  int refid_dst = insertRefid(db,qrefid_dst.data());
554  int id_file = insertFile(db,"no-file"); // TODO: replace no-file with proper file
555  insertMemberReference(db,refid_src,refid_dst,id_file,dst->getStartBodyLine(),-1);
556  }
557 }
558 
559 static void insertMemberFunctionParams(sqlite3 *db,int id_memberdef,MemberDef *md,Definition *def)
560 {
561  ArgumentList *declAl = md->declArgumentList();
562  ArgumentList *defAl = md->argumentList();
563  if (declAl!=0 && declAl->count()>0)
564  {
565  ArgumentListIterator declAli(*declAl);
566  ArgumentListIterator defAli(*defAl);
567  Argument *a;
568  for (declAli.toFirst();(a=declAli.current());++declAli)
569  {
570  Argument *defArg = defAli.current();
571 
572  if (!a->attrib.isEmpty())
573  {
574  bindTextParameter(params_select,":attributes",a->attrib.data());
575  bindTextParameter(params_insert,":attributes",a->attrib.data());
576  }
577  if (!a->type.isEmpty())
578  {
579  StringList l;
580  linkifyText(TextGeneratorSqlite3Impl(l),def,md->getBodyDef(),md,a->type);
581 
582  StringListIterator li(l);
583  QCString *s;
584  while ((s=li.current()))
585  {
586  QCString qrefid_src = md->getOutputFileBase() + "_1" + md->anchor();
587  int refid_src = insertRefid(db,qrefid_src.data());
588  int refid_dst = insertRefid(db,s->data());
589  int id_file = insertFile(db,stripFromPath(def->getDefFileName()));
590  insertMemberReference(db,refid_src,refid_dst,id_file,md->getDefLine(),-1);
591  ++li;
592  }
593  bindTextParameter(params_select,":type",a->type.data());
594  bindTextParameter(params_insert,":type",a->type.data());
595  }
596  if (!a->name.isEmpty())
597  {
598  bindTextParameter(params_select,":declname",a->name.data());
599  bindTextParameter(params_insert,":declname",a->name.data());
600  }
601  if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name)
602  {
603  bindTextParameter(params_select,":defname",defArg->name.data());
604  bindTextParameter(params_insert,":defname",defArg->name.data());
605  }
606  if (!a->array.isEmpty())
607  {
608  bindTextParameter(params_select,":array",a->array.data());
609  bindTextParameter(params_insert,":array",a->array.data());
610  }
611  if (!a->defval.isEmpty())
612  {
613  StringList l;
614  linkifyText(TextGeneratorSqlite3Impl(l),def,md->getBodyDef(),md,a->defval);
615  bindTextParameter(params_select,":defval",a->defval.data());
616  bindTextParameter(params_insert,":defval",a->defval.data());
617  }
618  if (defArg) ++defAli;
619 
620  int id_param=step(db,params_select,TRUE,TRUE);
621  if (id_param==0) {
622  id_param=step(db,params_insert,TRUE);
623  }
624 
625  bindIntParameter(memberdef_params_insert,":id_memberdef",id_memberdef);
626  bindIntParameter(memberdef_params_insert,":id_param",id_param);
627  step(db,memberdef_params_insert);
628  }
629  }
630 }
631 
632 static void insertMemberDefineParams(sqlite3 *db,int id_memberdef,MemberDef *md,Definition *def)
633 {
634  if (md->argumentList()->count()==0) // special case for "foo()" to
635  // disguish it from "foo".
636  {
637  DBG_CTX(("no params\n"));
638  }
639  else
640  {
642  Argument *a;
643  for (ali.toFirst();(a=ali.current());++ali)
644  {
645  bindTextParameter(params_insert,":defname",a->type.data());
646  int id_param=step(db,params_insert,TRUE);
647 
648  bindIntParameter(memberdef_params_insert,":id_memberdef",id_memberdef);
649  bindIntParameter(memberdef_params_insert,":id_param",id_param);
650  step(db,memberdef_params_insert);
651  }
652  }
653 }
654 
655 
656 static void stripQualifiers(QCString &typeStr)
657 {
658  bool done=FALSE;
659  while (!done)
660  {
661  if (typeStr.stripPrefix("static "));
662  else if (typeStr.stripPrefix("virtual "));
663  else if (typeStr.stripPrefix("volatile "));
664  else if (typeStr=="virtual") typeStr="";
665  else done=TRUE;
666  }
667 }
668 
669 static int prepareStatement(sqlite3 *db, SqlStmt &s)
670 {
671  int rc;
672  rc = sqlite3_prepare_v2(db,s.query,-1,&s.stmt,0);
673  if (rc!=SQLITE_OK)
674  {
675  msg("prepare failed for %s\n%s\n", s.query, sqlite3_errmsg(db));
676  return -1;
677  }
678  return rc;
679 }
680 
681 static int prepareStatements(sqlite3 *db)
682 {
683  if (
684  -1==prepareStatement(db, memberdef_insert) ||
685  -1==prepareStatement(db, files_insert) ||
686  -1==prepareStatement(db, files_select) ||
687  -1==prepareStatement(db, refids_insert) ||
688  -1==prepareStatement(db, refids_select) ||
689  -1==prepareStatement(db, incl_insert)||
690  -1==prepareStatement(db, incl_select)||
691  -1==prepareStatement(db, params_insert) ||
692  -1==prepareStatement(db, params_select) ||
693  -1==prepareStatement(db, xrefs_insert) ||
694  -1==prepareStatement(db, innerclass_insert) ||
695  -1==prepareStatement(db, compounddef_insert) ||
696  -1==prepareStatement(db, basecompoundref_insert) ||
697  -1==prepareStatement(db, derivedcompoundref_insert) ||
698  -1==prepareStatement(db, memberdef_params_insert)||
699  -1==prepareStatement(db, innernamespace_insert)
700  )
701  {
702  return -1;
703  }
704  return 0;
705 }
706 
707 static void beginTransaction(sqlite3 *db)
708 {
709  char * sErrMsg = 0;
710  sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
711 }
712 
713 static void endTransaction(sqlite3 *db)
714 {
715  char * sErrMsg = 0;
716  sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &sErrMsg);
717 }
718 
719 static void pragmaTuning(sqlite3 *db)
720 {
721  char * sErrMsg = 0;
722  sqlite3_exec(db, "PRAGMA synchronous = OFF", NULL, NULL, &sErrMsg);
723  sqlite3_exec(db, "PRAGMA journal_mode = MEMORY", NULL, NULL, &sErrMsg);
724  sqlite3_exec(db, "PRAGMA temp_store = MEMORY;", NULL, NULL, &sErrMsg);
725 }
726 
727 static int initializeSchema(sqlite3* db)
728 {
729  int rc;
730  sqlite3_stmt *stmt = 0;
731 
732  msg("Initializing DB schema...\n");
733  for (unsigned int k = 0; k < sizeof(schema_queries) / sizeof(schema_queries[0]); k++)
734  {
735  const char *q = schema_queries[k][1];
736  // create table
737  rc = sqlite3_prepare_v2(db, q, -1, &stmt, 0);
738  if (rc != SQLITE_OK)
739  {
740  msg("failed to prepare query: %s\n\t%s\n", q, sqlite3_errmsg(db));
741  return -1;
742  }
743  rc = sqlite3_step(stmt);
744  if (rc != SQLITE_DONE)
745  {
746  msg("failed to execute query: %s\n\t%s\n", q, sqlite3_errmsg(db));
747  return -1;
748  }
749  sqlite3_finalize(stmt);
750  }
751  return 0;
752 }
753 
755 static void writeInnerClasses(sqlite3*db,const ClassSDict *cl)
756 {
757  if (!cl) return;
758 
759  ClassSDict::Iterator cli(*cl);
760  ClassDef *cd;
761  for (cli.toFirst();(cd=cli.current());++cli)
762  {
763  if (!cd->isHidden() && cd->name().find('@')==-1) // skip anonymous scopes
764  {
765  int refid = insertRefid(db, cd->getOutputFileBase());
766  bindIntParameter(innerclass_insert,":refid", refid);
767  bindIntParameter(innerclass_insert,":prot",cd->protection());
768  bindTextParameter(innerclass_insert,":name",cd->name());
769  step(db,innerclass_insert);
770  }
771  }
772 }
773 
774 
775 static void writeInnerNamespaces(sqlite3 *db,const NamespaceSDict *nl)
776 {
777  if (nl)
778  {
779  NamespaceSDict::Iterator nli(*nl);
780  NamespaceDef *nd;
781  for (nli.toFirst();(nd=nli.current());++nli)
782  {
783  if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymouse scopes
784  {
785  int refid = insertRefid(db, nd->getOutputFileBase());
786  bindIntParameter(innernamespace_insert,":refid",refid);
787  bindTextParameter(innernamespace_insert,":name",nd->name(),FALSE);
788  step(db,innernamespace_insert);
789  }
790  }
791  }
792 }
793 
794 
795 static void writeTemplateArgumentList(sqlite3* db,
796  ArgumentList * al,
797  Definition * scope,
798  FileDef * fileScope)
799 {
800  if (al)
801  {
802  ArgumentListIterator ali(*al);
803  Argument *a;
804  for (ali.toFirst();(a=ali.current());++ali)
805  {
806  if (!a->type.isEmpty())
807  {
808  #warning linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->type);
809  bindTextParameter(params_select,":type",a->type);
810  bindTextParameter(params_insert,":type",a->type);
811  }
812  if (!a->name.isEmpty())
813  {
814  bindTextParameter(params_select,":declname",a->name);
815  bindTextParameter(params_insert,":declname",a->name);
816  bindTextParameter(params_select,":defname",a->name);
817  bindTextParameter(params_insert,":defname",a->name);
818  }
819  if (!a->defval.isEmpty())
820  {
821  #warning linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->defval);
822  bindTextParameter(params_select,":defval",a->defval);
823  bindTextParameter(params_insert,":defval",a->defval);
824  }
825  if (!step(db,params_select,TRUE,TRUE))
826  step(db,params_insert);
827  }
828  }
829 }
830 
831 static void writeMemberTemplateLists(sqlite3* db,MemberDef *md)
832 {
833  ArgumentList *templMd = md->templateArguments();
834  if (templMd) // function template prefix
835  {
836  writeTemplateArgumentList(db,templMd,md->getClassDef(),md->getFileDef());
837  }
838 }
839 static void writeTemplateList(sqlite3*db,ClassDef *cd)
840 {
842 }
844 
846 static void generateSqlite3ForMember(sqlite3*db,MemberDef *md,Definition *def)
847 {
848  // + declaration/definition arg lists
849  // + reimplements
850  // + reimplementedBy
851  // + exceptions
852  // + const/volatile specifiers
853  // - examples
854  // + source definition
855  // + source references
856  // + source referenced by
857  // - body code
858  // + template arguments
859  // (templateArguments(), definitionTemplateParameterLists())
860  // - call graph
861 
862  // enum values are written as part of the enum
863  if (md->memberType()==MemberType_EnumValue) return;
864  if (md->isHidden()) return;
865  //if (md->name().at(0)=='@') return; // anonymous member
866 
867  // group members are only visible in their group
868  //if (def->definitionType()!=Definition::TypeGroup && md->getGroupDef()) return;
869  QCString memType;
870 
871  // memberdef
872  QCString qrefid = md->getOutputFileBase() + "_1" + md->anchor();
873  int refid = insertRefid(db, qrefid.data());
874 
875  bindIntParameter(memberdef_insert,":refid", refid);
876  bindIntParameter(memberdef_insert,":kind",md->memberType());
877  bindIntParameter(memberdef_insert,":prot",md->protection());
878 
879  bindIntParameter(memberdef_insert,":static",md->isStatic());
880 
881  bool isFunc=FALSE;
882  switch (md->memberType())
883  {
884  case MemberType_Function: // fall through
885  case MemberType_Signal: // fall through
886  case MemberType_Friend: // fall through
887  case MemberType_DCOP: // fall through
888  case MemberType_Slot:
889  isFunc=TRUE;
890  break;
891  default:
892  break;
893  }
894 
895  if (isFunc)
896  {
897  ArgumentList *al = md->argumentList();
898  if (al!=0)
899  {
900  bindIntParameter(memberdef_insert,":const",al->constSpecifier);
901  bindIntParameter(memberdef_insert,":volatile",al->volatileSpecifier);
902  }
903  bindIntParameter(memberdef_insert,":explicit",md->isExplicit());
904  bindIntParameter(memberdef_insert,":inline",md->isInline());
905  bindIntParameter(memberdef_insert,":final",md->isFinal());
906  bindIntParameter(memberdef_insert,":sealed",md->isSealed());
907  bindIntParameter(memberdef_insert,":new",md->isNew());
908  bindIntParameter(memberdef_insert,":optional",md->isOptional());
909  bindIntParameter(memberdef_insert,":required",md->isRequired());
910 
911  bindIntParameter(memberdef_insert,":virt",md->virtualness());
912  }
913 
914  if (md->memberType() == MemberType_Variable)
915  {
916  bindIntParameter(memberdef_insert,":mutable",md->isMutable());
917  bindIntParameter(memberdef_insert,":initonly",md->isInitonly());
918  bindIntParameter(memberdef_insert,":attribute",md->isAttribute());
919  bindIntParameter(memberdef_insert,":property",md->isProperty());
920  bindIntParameter(memberdef_insert,":readonly",md->isReadonly());
921  bindIntParameter(memberdef_insert,":bound",md->isBound());
922  bindIntParameter(memberdef_insert,":removable",md->isRemovable());
923  bindIntParameter(memberdef_insert,":constrained",md->isConstrained());
924  bindIntParameter(memberdef_insert,":transient",md->isTransient());
925  bindIntParameter(memberdef_insert,":maybevoid",md->isMaybeVoid());
926  bindIntParameter(memberdef_insert,":maybedefault",md->isMaybeDefault());
927  bindIntParameter(memberdef_insert,":maybeambiguous",md->isMaybeAmbiguous());
928  if (md->bitfieldString())
929  {
930  QCString bitfield = md->bitfieldString();
931  if (bitfield.at(0)==':') bitfield=bitfield.mid(1);
932  bindTextParameter(memberdef_insert,":bitfield",bitfield.stripWhiteSpace());
933  }
934  }
935  else if (md->memberType() == MemberType_Property)
936  {
937  bindIntParameter(memberdef_insert,":readable",md->isReadable());
938  bindIntParameter(memberdef_insert,":writable",md->isWritable());
939  bindIntParameter(memberdef_insert,":gettable",md->isGettable());
940  bindIntParameter(memberdef_insert,":privategettable",md->isPrivateGettable());
941  bindIntParameter(memberdef_insert,":protectedgettable",md->isProtectedGettable());
942  bindIntParameter(memberdef_insert,":settable",md->isSettable());
943  bindIntParameter(memberdef_insert,":privatesettable",md->isPrivateSettable());
944  bindIntParameter(memberdef_insert,":protectedsettable",md->isProtectedSettable());
945  if (md->isAssign() || md->isCopy() || md->isRetain()
946  || md->isStrong() || md->isWeak())
947  {
948  int accessor=0;
949  if (md->isAssign()) accessor = 1;
950  else if (md->isCopy()) accessor = 2;
951  else if (md->isRetain()) accessor = 3;
952  else if (md->isStrong()) accessor = 4;
953  else if (md->isWeak()) accessor = 5;
954 
955  bindIntParameter(memberdef_insert,":accessor",accessor);
956  }
957  bindTextParameter(memberdef_insert,":read",md->getReadAccessor());
958  bindTextParameter(memberdef_insert,":write",md->getWriteAccessor());
959  }
960  else if (md->memberType() == MemberType_Event)
961  {
962  bindIntParameter(memberdef_insert,":addable",md->isAddable());
963  bindIntParameter(memberdef_insert,":removable",md->isRemovable());
964  bindIntParameter(memberdef_insert,":raisable",md->isRaisable());
965  }
966 
967  // + declaration/definition arg lists
968  if (md->memberType()!=MemberType_Define &&
970  )
971  {
972  if (md->memberType()!=MemberType_Typedef)
973  {
975  }
976  QCString typeStr = md->typeString();
977  stripQualifiers(typeStr);
978  StringList l;
979  linkifyText(TextGeneratorSqlite3Impl(l),def,md->getBodyDef(),md,typeStr);
980  if (typeStr.data())
981  {
982  bindTextParameter(memberdef_insert,":type",typeStr.data(),FALSE);
983  }
984 
985  if (md->definition())
986  {
987  bindTextParameter(memberdef_insert,":definition",md->definition());
988  }
989 
990  if (md->argsString())
991  {
992  bindTextParameter(memberdef_insert,":argsstring",md->argsString());
993  }
994  }
995 
996  bindTextParameter(memberdef_insert,":name",md->name());
997 
998  // Extract references from initializer
1000  {
1001  bindTextParameter(memberdef_insert,":initializer",md->initializer().data());
1002 
1003  StringList l;
1004  linkifyText(TextGeneratorSqlite3Impl(l),def,md->getBodyDef(),md,md->initializer());
1005  StringListIterator li(l);
1006  QCString *s;
1007  while ((s=li.current()))
1008  {
1009  if (md->getBodyDef())
1010  {
1011  DBG_CTX(("initializer:%s %s %s %d\n",
1012  md->anchor().data(),
1013  s->data(),
1014  md->getBodyDef()->getDefFileName().data(),
1015  md->getStartBodyLine()));
1016  QCString qrefid_src = md->getOutputFileBase() + "_1" + md->anchor();
1017  int refid_src = insertRefid(db,qrefid_src.data());
1018  int refid_dst = insertRefid(db,s->data());
1019  int id_file = insertFile(db,stripFromPath(md->getBodyDef()->getDefFileName()));
1020  insertMemberReference(db,refid_src,refid_dst,id_file,md->getStartBodyLine(),-1);
1021  }
1022  ++li;
1023  }
1024  }
1025 
1026  if ( md->getScopeString() )
1027  {
1028  bindTextParameter(memberdef_insert,":scope",md->getScopeString().data(),FALSE);
1029  }
1030 
1031  // +Brief, detailed and inbody description
1032  bindTextParameter(memberdef_insert,":briefdescription",md->briefDescription(),FALSE);
1033  bindTextParameter(memberdef_insert,":detaileddescription",md->documentation(),FALSE);
1034  bindTextParameter(memberdef_insert,":inbodydescription",md->inbodyDocumentation(),FALSE);
1035 
1036  // File location
1037  if (md->getDefLine() != -1)
1038  {
1039  int id_file = insertFile(db,stripFromPath(md->getDefFileName()));
1040  if (id_file!=-1)
1041  {
1042  bindIntParameter(memberdef_insert,":id_file",id_file);
1043  bindIntParameter(memberdef_insert,":line",md->getDefLine());
1044  bindIntParameter(memberdef_insert,":column",md->getDefColumn());
1045 
1046  if (md->getStartBodyLine()!=-1)
1047  {
1048  int id_bodyfile = insertFile(db,stripFromPath(md->getBodyDef()->absFilePath()));
1049  if (id_bodyfile == -1)
1050  {
1051  sqlite3_clear_bindings(memberdef_insert.stmt);
1052  }
1053  else
1054  {
1055  bindIntParameter(memberdef_insert,":id_bodyfile",id_bodyfile);
1056  bindIntParameter(memberdef_insert,":bodystart",md->getStartBodyLine());
1057  bindIntParameter(memberdef_insert,":bodyend",md->getEndBodyLine());
1058  }
1059  }
1060  }
1061  }
1062 
1063  int id_memberdef=step(db,memberdef_insert,TRUE);
1064 
1065  if (isFunc)
1066  {
1067  insertMemberFunctionParams(db,id_memberdef,md,def);
1068  }
1069  else if (md->memberType()==MemberType_Define &&
1070  md->argsString())
1071  {
1072  insertMemberDefineParams(db,id_memberdef,md,def);
1073  }
1074 
1075  // + source references
1076  // The cross-references in initializers only work when both the src and dst
1077  // are defined.
1078  MemberSDict *mdict = md->getReferencesMembers();
1079  if (mdict!=0)
1080  {
1081  MemberSDict::IteratorDict mdi(*mdict);
1082  MemberDef *rmd;
1083  for (mdi.toFirst();(rmd=mdi.current());++mdi)
1084  {
1085  insertMemberReference(db,md,rmd);//,mdi.currentKey());
1086  }
1087  }
1088  // + source referenced by
1089  mdict = md->getReferencedByMembers();
1090  if (mdict!=0)
1091  {
1092  MemberSDict::IteratorDict mdi(*mdict);
1093  MemberDef *rmd;
1094  for (mdi.toFirst();(rmd=mdi.current());++mdi)
1095  {
1096  insertMemberReference(db,rmd,md);//,mdi.currentKey());
1097  }
1098  }
1099 }
1100 
1101 static void generateSqlite3Section(sqlite3*db,
1102  Definition *d,
1103  MemberList *ml,const char * /*kind*/,const char * /*header*/=0,
1104  const char * /*documentation*/=0)
1105 {
1106  if (ml==0) return;
1107  MemberListIterator mli(*ml);
1108  MemberDef *md;
1109  int count=0;
1110  for (mli.toFirst();(md=mli.current());++mli)
1111  {
1112  // namespace members are also inserted in the file scope, but
1113  // to prevent this duplication in the XML output, we filter those here.
1114  if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0)
1115  {
1116  count++;
1117  }
1118  }
1119  if (count==0) return; // empty list
1120  for (mli.toFirst();(md=mli.current());++mli)
1121  {
1122  // namespace members are also inserted in the file scope, but
1123  // to prevent this duplication in the XML output, we filter those here.
1124  //if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0)
1125  {
1126  generateSqlite3ForMember(db,md,d);
1127  }
1128  }
1129 }
1130 
1131 
1132 static void generateSqlite3ForClass(sqlite3 *db, ClassDef *cd)
1133 {
1134  // + list of direct super classes
1135  // + list of direct sub classes
1136  // + include file
1137  // + list of inner classes
1138  // - template argument list(s)
1139  // + member groups
1140  // + list of all members
1141  // - brief description
1142  // - detailed description
1143  // - inheritance DOT diagram
1144  // - collaboration DOT diagram
1145  // - user defined member sections
1146  // - standard member sections
1147  // - detailed member documentation
1148  // - examples using the class
1149 
1150  if (cd->isReference()) return; // skip external references.
1151  if (cd->isHidden()) return; // skip hidden classes.
1152  if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
1153  if (cd->templateMaster()!=0) return; // skip generated template instances.
1154 
1155  msg("Generating Sqlite3 output for class %s\n",cd->name().data());
1156 
1157  bindTextParameter(compounddef_insert,":name",cd->name());
1158  bindTextParameter(compounddef_insert,":kind",cd->compoundTypeString(),FALSE);
1159  bindIntParameter(compounddef_insert,":prot",cd->protection());
1160  int refid = insertRefid(db, cd->getOutputFileBase());
1161  bindIntParameter(compounddef_insert,":refid", refid);
1162 
1163  int id_file = insertFile(db,stripFromPath(cd->getDefFileName()));
1164  bindIntParameter(compounddef_insert,":id_file",id_file);
1165  bindIntParameter(compounddef_insert,":line",cd->getDefLine());
1166  bindIntParameter(compounddef_insert,":column",cd->getDefColumn());
1167 
1168  step(db,compounddef_insert);
1169 
1170  // + list of direct super classes
1171  if (cd->baseClasses())
1172  {
1173  BaseClassListIterator bcli(*cd->baseClasses());
1174  BaseClassDef *bcd;
1175  for (bcli.toFirst();(bcd=bcli.current());++bcli)
1176  {
1177  int refid = insertRefid(db, bcd->classDef->getOutputFileBase());
1178  bindIntParameter(basecompoundref_insert,":refid", refid);
1179  bindIntParameter(basecompoundref_insert,":prot",bcd->prot);
1180  bindIntParameter(basecompoundref_insert,":virt",bcd->virt);
1181 
1182  if (!bcd->templSpecifiers.isEmpty())
1183  {
1184  bindTextParameter(basecompoundref_insert,":base",insertTemplateSpecifierInScope(bcd->classDef->name(),bcd->templSpecifiers),FALSE);
1185  }
1186  else
1187  {
1188  bindTextParameter(basecompoundref_insert,":base",bcd->classDef->displayName(),FALSE);
1189  }
1190  bindTextParameter(basecompoundref_insert,":derived",cd->displayName(),FALSE);
1191  step(db,basecompoundref_insert);
1192  }
1193  }
1194 
1195  // + list of direct sub classes
1196  if (cd->subClasses())
1197  {
1198  BaseClassListIterator bcli(*cd->subClasses());
1199  BaseClassDef *bcd;
1200  for (bcli.toFirst();(bcd=bcli.current());++bcli)
1201  {
1202  bindTextParameter(derivedcompoundref_insert,":base",cd->displayName(),FALSE);
1203  if (!bcd->templSpecifiers.isEmpty())
1204  {
1205  bindTextParameter(derivedcompoundref_insert,":derived",insertTemplateSpecifierInScope(bcd->classDef->name(),bcd->templSpecifiers),FALSE);
1206  }
1207  else
1208  {
1209  bindTextParameter(derivedcompoundref_insert,":derived",bcd->classDef->displayName(),FALSE);
1210  }
1211  int refid = insertRefid(db, bcd->classDef->getOutputFileBase());
1212  bindIntParameter(derivedcompoundref_insert,":refid", refid);
1213  bindIntParameter(derivedcompoundref_insert,":prot",bcd->prot);
1214  bindIntParameter(derivedcompoundref_insert,":virt",bcd->virt);
1215  step(db,derivedcompoundref_insert);
1216  }
1217  }
1218 
1219  // + include file
1220  IncludeInfo *ii=cd->includeInfo();
1221  if (ii)
1222  {
1223  QCString nm = ii->includeName;
1224  if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
1225  if (!nm.isEmpty())
1226  {
1227  int id_dst=insertFile(db,nm);
1228  if (id_dst!=-1) {
1229  bindIntParameter(incl_select,":local",ii->local);
1230  bindIntParameter(incl_select,":id_src",id_file);
1231  bindIntParameter(incl_select,":id_dst",id_dst);
1232  int count=step(db,incl_select,TRUE,TRUE);
1233  if (count==0)
1234  {
1235  bindIntParameter(incl_insert,":local",ii->local);
1236  bindIntParameter(incl_insert,":id_src",id_file);
1237  bindIntParameter(incl_insert,":id_dst",id_dst);
1238  step(db,incl_insert);
1239  }
1240  }
1241  }
1242  }
1243  // + list of inner classes
1244  writeInnerClasses(db,cd->getClassSDict());
1245 
1246  // - template argument list(s)
1247  writeTemplateList(db,cd);
1248 
1249  // + member groups
1250  if (cd->getMemberGroupSDict())
1251  {
1253  MemberGroup *mg;
1254  for (;(mg=mgli.current());++mgli)
1255  {
1256  generateSqlite3Section(db,cd,mg->members(),"user-defined",mg->header(),
1257  mg->documentation());
1258  }
1259  }
1260 
1261  // + list of all members
1262  QListIterator<MemberList> mli(cd->getMemberLists());
1263  MemberList *ml;
1264  for (mli.toFirst();(ml=mli.current());++mli)
1265  {
1266  if ((ml->listType()&MemberListType_detailedLists)==0)
1267  {
1268  generateSqlite3Section(db,cd,ml,"user-defined");//g_xmlSectionMapper.find(ml->listType()));
1269  }
1270  }
1271 }
1272 
1273 static void generateSqlite3ForNamespace(sqlite3 *db, NamespaceDef *nd)
1274 {
1275  // + contained class definitions
1276  // + contained namespace definitions
1277  // + member groups
1278  // + normal members
1279  // - brief desc
1280  // - detailed desc
1281  // - location
1282  // - files containing (parts of) the namespace definition
1283 
1284  if (nd->isReference() || nd->isHidden()) return; // skip external references
1285 
1286  // + contained class definitions
1287  writeInnerClasses(db,nd->getClassSDict());
1288 
1289  // + contained namespace definitions
1291 
1292  // + member groups
1293  if (nd->getMemberGroupSDict())
1294  {
1296  MemberGroup *mg;
1297  for (;(mg=mgli.current());++mgli)
1298  {
1299  generateSqlite3Section(db,nd,mg->members(),"user-defined",mg->header(),
1300  mg->documentation());
1301  }
1302  }
1303 
1304  // + normal members
1305  QListIterator<MemberList> mli(nd->getMemberLists());
1306  MemberList *ml;
1307  for (mli.toFirst();(ml=mli.current());++mli)
1308  {
1309  if ((ml->listType()&MemberListType_declarationLists)!=0)
1310  {
1311  generateSqlite3Section(db,nd,ml,"user-defined");//g_xmlSectionMapper.find(ml->listType()));
1312  }
1313  }
1314 }
1315 
1316 static void generateSqlite3ForFile(sqlite3 *db, FileDef *fd)
1317 {
1318  // + includes files
1319  // + includedby files
1320  // - include graph
1321  // - included by graph
1322  // + contained class definitions
1323  // + contained namespace definitions
1324  // + member groups
1325  // + normal members
1326  // - brief desc
1327  // - detailed desc
1328  // - source code
1329  // - location
1330  // - number of lines
1331 
1332  if (fd->isReference()) return; // skip external references
1333 
1334  // + includes files
1335  IncludeInfo *ii;
1336  if (fd->includeFileList())
1337  {
1338  QListIterator<IncludeInfo> ili(*fd->includeFileList());
1339  for (ili.toFirst();(ii=ili.current());++ili)
1340  {
1341  int id_src=insertFile(db,fd->absFilePath().data());
1342  int id_dst=insertFile(db,ii->includeName.data());
1343  bindIntParameter(incl_select,":local",ii->local);
1344  bindIntParameter(incl_select,":id_src",id_src);
1345  bindIntParameter(incl_select,":id_dst",id_dst);
1346  if (step(db,incl_select,TRUE,TRUE)==0) {
1347  bindIntParameter(incl_insert,":local",ii->local);
1348  bindIntParameter(incl_insert,":id_src",id_src);
1349  bindIntParameter(incl_insert,":id_dst",id_dst);
1350  step(db,incl_insert);
1351  }
1352  }
1353  }
1354 
1355  // + includedby files
1356  if (fd->includedByFileList())
1357  {
1358  QListIterator<IncludeInfo> ili(*fd->includedByFileList());
1359  for (ili.toFirst();(ii=ili.current());++ili)
1360  {
1361  int id_src=insertFile(db,ii->includeName);
1362  int id_dst=insertFile(db,fd->absFilePath());
1363  bindIntParameter(incl_select,":local",ii->local);
1364  bindIntParameter(incl_select,":id_src",id_src);
1365  bindIntParameter(incl_select,":id_dst",id_dst);
1366  if (step(db,incl_select,TRUE,TRUE)==0) {
1367  bindIntParameter(incl_insert,":local",ii->local);
1368  bindIntParameter(incl_insert,":id_src",id_src);
1369  bindIntParameter(incl_insert,":id_dst",id_dst);
1370  step(db,incl_insert);
1371  }
1372  }
1373  }
1374 
1375  // + contained class definitions
1376  if (fd->getClassSDict())
1377  {
1378  writeInnerClasses(db,fd->getClassSDict());
1379  }
1380 
1381  // + contained namespace definitions
1382  if (fd->getNamespaceSDict())
1383  {
1385  }
1386 
1387  // + member groups
1388  if (fd->getMemberGroupSDict())
1389  {
1391  MemberGroup *mg;
1392  for (;(mg=mgli.current());++mgli)
1393  {
1394  generateSqlite3Section(db,fd,mg->members(),"user-defined",mg->header(),
1395  mg->documentation());
1396  }
1397  }
1398 
1399  // + normal members
1400  QListIterator<MemberList> mli(fd->getMemberLists());
1401  MemberList *ml;
1402  for (mli.toFirst();(ml=mli.current());++mli)
1403  {
1404  if ((ml->listType()&MemberListType_declarationLists)!=0)
1405  {
1406  generateSqlite3Section(db,fd,ml,"user-defined");//g_xmlSectionMapper.find(ml->listType()));
1407  }
1408  }
1409 }
1410 
1411 static void generateSqlite3ForGroup(sqlite3*db,GroupDef *gd)
1412 {
1413 #warning WorkInProgress
1414 }
1415 
1416 static void generateSqlite3ForDir(sqlite3 *db,DirDef *dd)
1417 {
1418 #warning WorkInProgress
1419 }
1420 
1421 static void generateSqlite3ForPage(sqlite3 *db,PageDef *pd,bool isExample)
1422 {
1423 #warning WorkInProgress
1424 }
1427 void generateSqlite3()
1428 {
1429  // + classes
1430  // + namespaces
1431  // + files
1432  // + groups
1433  // + related pages
1434  // + examples
1435  // + main page
1436 
1437  QCString outputDirectory = Config_getString(OUTPUT_DIRECTORY);
1438  QDir sqlite3Dir(outputDirectory);
1439  sqlite3 *db;
1440  sqlite3_initialize();
1441  int rc = sqlite3_open_v2(outputDirectory+"/doxygen_sqlite3.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
1442  if (rc != SQLITE_OK)
1443  {
1444  sqlite3_close(db);
1445  msg("database open failed: %s\n", "doxygen_sqlite3.db");
1446  return;
1447  }
1448  beginTransaction(db);
1449  pragmaTuning(db);
1450 
1451  if (-1==initializeSchema(db))
1452  return;
1453 
1454  if ( -1 == prepareStatements(db) )
1455  {
1456  err("sqlite generator: prepareStatements failed!");
1457  return;
1458  }
1459 
1460  // + classes
1462  ClassDef *cd;
1463  for (cli.toFirst();(cd=cli.current());++cli)
1464  {
1465  msg("Generating Sqlite3 output for class %s\n",cd->name().data());
1466  generateSqlite3ForClass(db,cd);
1467  }
1468 
1469  // + namespaces
1471  NamespaceDef *nd;
1472  for (nli.toFirst();(nd=nli.current());++nli)
1473  {
1474  msg("Generating Sqlite3 output for namespace %s\n",nd->name().data());
1475  generateSqlite3ForNamespace(db,nd);
1476  }
1477 
1478  // + files
1480  FileName *fn;
1481  for (;(fn=fnli.current());++fnli)
1482  {
1483  FileNameIterator fni(*fn);
1484  FileDef *fd;
1485  for (;(fd=fni.current());++fni)
1486  {
1487  msg("Generating Sqlite3 output for file %s\n",fd->name().data());
1488  generateSqlite3ForFile(db,fd);
1489  }
1490  }
1491 
1492  // + groups
1494  GroupDef *gd;
1495  for (;(gd=gli.current());++gli)
1496  {
1497  msg("Generating Sqlite3 output for group %s\n",gd->name().data());
1498  generateSqlite3ForGroup(db,gd);
1499  }
1500 
1501  // + page
1502  {
1504  PageDef *pd=0;
1505  for (pdi.toFirst();(pd=pdi.current());++pdi)
1506  {
1507  msg("Generating Sqlite3 output for page %s\n",pd->name().data());
1508  generateSqlite3ForPage(db,pd,FALSE);
1509  }
1510  }
1511 
1512  // + dirs
1513  {
1514  DirDef *dir;
1516  for (sdi.toFirst();(dir=sdi.current());++sdi)
1517  {
1518  msg("Generating Sqlite3 output for dir %s\n",dir->name().data());
1519  generateSqlite3ForDir(db,dir);
1520  }
1521  }
1522 
1523  // + examples
1524  {
1526  PageDef *pd=0;
1527  for (pdi.toFirst();(pd=pdi.current());++pdi)
1528  {
1529  msg("Generating Sqlite3 output for example %s\n",pd->name().data());
1530  generateSqlite3ForPage(db,pd,TRUE);
1531  }
1532  }
1533 
1534  // + main page
1535  if (Doxygen::mainPage)
1536  {
1537  msg("Generating Sqlite3 output for the main page\n");
1538  generateSqlite3ForPage(db,Doxygen::mainPage,FALSE);
1539  }
1540 
1541  endTransaction(db);
1542 }
1543 
1544 #else // USE_SQLITE3
1546 {
1547  err("sqlite3 support has not been compiled in!");
1548 }
1549 #endif
1550 // vim: noai:ts=2:sw=2:ss=2:expandtab