30
30
namespace oss_fuzz {
31
31
namespace indexer {
32
32
namespace {
33
+
34
+ // Note: We could in principle enforce UNIQUE constraints on `reference` foreign
35
+ // key pairs, as well as those of `virtual_method_link` and
36
+ // `entity_translation_unit` (as an extreme, non-ID fields of e.g. `location`
37
+ // could also be made into a UNIQUE tuple). But those are unique by construction
38
+ // now and we hope to avoid the overhead of checking those constraints.
39
+
33
40
const char kCreateDb [] =
34
41
" PRAGMA foreign_keys = ON;\n "
35
42
" PRAGMA user_version = " SCHEMA_VERSION
@@ -87,6 +94,25 @@ const char kCreateDb[] =
87
94
" CREATE INDEX virtual_method_link_parent ON virtual_method_link("
88
95
" parent_entity_id);\n " ;
89
96
97
+ const char kCreateIncrementalIndexingSupportTables [] =
98
+ " CREATE TABLE translation_unit(\n "
99
+ " id INTEGER PRIMARY KEY,\n "
100
+ " path TEXT);\n "
101
+ " \n "
102
+ " CREATE TABLE entity_translation_unit(\n "
103
+ " id INTEGER PRIMARY KEY,\n "
104
+ " entity_id INT NOT NULL,\n "
105
+ " tu_id INT NOT NULL,\n "
106
+ " FOREIGN KEY (entity_id) REFERENCES entity(id),\n "
107
+ " FOREIGN KEY (tu_id) REFERENCES translation_unit(id));\n "
108
+ " \n "
109
+ " CREATE TABLE reference_translation_unit(\n "
110
+ " id INTEGER PRIMARY KEY,\n "
111
+ " reference_id INT NOT NULL,\n "
112
+ " tu_id INT NOT NULL,\n "
113
+ " FOREIGN KEY (reference_id) REFERENCES reference(id),\n "
114
+ " FOREIGN KEY (tu_id) REFERENCES translation_unit(id));\n " ;
115
+
90
116
const char kInsertLocation [] =
91
117
" INSERT INTO location\n "
92
118
" (id, dirname, basename, start_line, end_line)\n "
@@ -109,6 +135,21 @@ const char kInsertLink[] =
109
135
" (id, parent_entity_id, child_entity_id)\n "
110
136
" VALUES (?1, ?2, ?3);" ;
111
137
138
+ const char kInsertTranslationUnit [] =
139
+ " INSERT INTO translation_unit\n "
140
+ " (id, path)\n "
141
+ " VALUES (?1, ?2);" ;
142
+
143
+ const char kInsertEntityTranslationUnit [] =
144
+ " INSERT INTO entity_translation_unit\n "
145
+ " (id, entity_id, tu_id)\n "
146
+ " VALUES (?1, ?2, ?3);" ;
147
+
148
+ const char kInsertReferenceTranslationUnit [] =
149
+ " INSERT INTO reference_translation_unit\n "
150
+ " (id, reference_id, tu_id)\n "
151
+ " VALUES (?1, ?2, ?3);" ;
152
+
112
153
const char kFinalizeDb [] =
113
154
" VACUUM;\n "
114
155
" REINDEX;\n "
@@ -163,8 +204,8 @@ bool InsertLocations(sqlite3* db, absl::Span<const Location> locations) {
163
204
164
205
bool InsertEntities (sqlite3* db, absl::Span<const Entity> entities) {
165
206
// `substitute_entity_id` foreign key can refer to a yet-unadded entity.
166
- if (sqlite3_exec (db, " PRAGMA foreign_keys = OFF;" , nullptr ,
167
- nullptr , nullptr ) != SQLITE_OK) {
207
+ if (sqlite3_exec (db, " PRAGMA foreign_keys = OFF;" , nullptr , nullptr ,
208
+ nullptr ) != SQLITE_OK) {
168
209
LOG (ERROR) << " sqlite disabling foreign keys failed: `"
169
210
<< sqlite3_errmsg (db) << " `" ;
170
211
return false ;
@@ -261,8 +302,8 @@ bool InsertEntities(sqlite3* db, absl::Span<const Entity> entities) {
261
302
std::move (cleanup).Cancel ();
262
303
sqlite3_finalize (insert_entity);
263
304
264
- if (sqlite3_exec (db, " PRAGMA foreign_keys = ON;" , nullptr , nullptr , nullptr )
265
- != SQLITE_OK) {
305
+ if (sqlite3_exec (db, " PRAGMA foreign_keys = ON;" , nullptr , nullptr ,
306
+ nullptr ) != SQLITE_OK) {
266
307
LOG (ERROR) << " sqlite re-enabling foreign keys failed: `"
267
308
<< sqlite3_errmsg (db) << " `" ;
268
309
return false ;
@@ -320,7 +361,7 @@ bool InsertVirtualMethodLinks(sqlite3* db,
320
361
return false ;
321
362
}
322
363
323
- for (ReferenceId i = 0 ; i < links.size (); ++i) {
364
+ for (VirtualMethodLinkId i = 0 ; i < links.size (); ++i) {
324
365
const VirtualMethodLink& link = links[i];
325
366
if (sqlite3_bind_int64 (insert_link, 1 , i) != SQLITE_OK ||
326
367
sqlite3_bind_int64 (insert_link, 2 , link.parent ()) != SQLITE_OK ||
@@ -332,7 +373,7 @@ bool InsertVirtualMethodLinks(sqlite3* db,
332
373
}
333
374
334
375
if (sqlite3_step (insert_link) != SQLITE_DONE) {
335
- LOG (ERROR) << " sqlite executing insert_reference failed: `"
376
+ LOG (ERROR) << " sqlite executing insert_link failed: `"
336
377
<< sqlite3_errmsg (db) << " `" ;
337
378
sqlite3_finalize (insert_link);
338
379
return false ;
@@ -345,6 +386,126 @@ bool InsertVirtualMethodLinks(sqlite3* db,
345
386
sqlite3_finalize (insert_link);
346
387
return true ;
347
388
}
389
+
390
+ bool InsertTranslationUnits (
391
+ sqlite3* db, absl::Span<const TranslationUnit> translation_units) {
392
+ sqlite3_stmt* insert_tu = nullptr ;
393
+ if (sqlite3_prepare_v2 (db, kInsertTranslationUnit ,
394
+ sizeof (kInsertTranslationUnit ), &insert_tu,
395
+ nullptr ) != SQLITE_OK) {
396
+ LOG (ERROR) << " sqlite compiling prepared statement failed: `"
397
+ << sqlite3_errmsg (db) << " `" ;
398
+ return false ;
399
+ }
400
+
401
+ for (TranslationUnitId i = 0 ; i < translation_units.size (); ++i) {
402
+ const TranslationUnit& tu = translation_units[i];
403
+ if (sqlite3_bind_int64 (insert_tu, 1 , i) != SQLITE_OK ||
404
+ sqlite3_bind_text (insert_tu, 2 , tu.index_path ().data (),
405
+ tu.index_path ().size (), SQLITE_STATIC) != SQLITE_OK) {
406
+ LOG (ERROR) << " sqlite binding insert_tu failed: `" << sqlite3_errmsg (db)
407
+ << " `" ;
408
+ sqlite3_finalize (insert_tu);
409
+ return false ;
410
+ }
411
+
412
+ if (sqlite3_step (insert_tu) != SQLITE_DONE) {
413
+ LOG (ERROR) << " sqlite executing insert_tu failed: `" << sqlite3_errmsg (db)
414
+ << " `" ;
415
+ sqlite3_finalize (insert_tu);
416
+ return false ;
417
+ }
418
+
419
+ sqlite3_reset (insert_tu);
420
+ sqlite3_clear_bindings (insert_tu);
421
+ }
422
+
423
+ sqlite3_finalize (insert_tu);
424
+ return true ;
425
+ }
426
+
427
+ bool InsertEntityTranslationUnits (
428
+ sqlite3* db,
429
+ absl::Span<const EntityTranslationUnit> entity_translation_units) {
430
+ sqlite3_stmt* insert_entity_tu = nullptr ;
431
+ if (sqlite3_prepare_v2 (db, kInsertEntityTranslationUnit ,
432
+ sizeof (kInsertEntityTranslationUnit ),
433
+ &insert_entity_tu, nullptr ) != SQLITE_OK) {
434
+ LOG (ERROR) << " sqlite compiling prepared statement failed: `"
435
+ << sqlite3_errmsg (db) << " `" ;
436
+ return false ;
437
+ }
438
+
439
+ for (EntityTranslationUnitId i = 0 ; i < entity_translation_units.size ();
440
+ ++i) {
441
+ const EntityTranslationUnit& entity_tu = entity_translation_units[i];
442
+ if (sqlite3_bind_int64 (insert_entity_tu, 1 , i) != SQLITE_OK ||
443
+ sqlite3_bind_int64 (insert_entity_tu, 2 , entity_tu.entity_id ()) !=
444
+ SQLITE_OK ||
445
+ sqlite3_bind_int64 (insert_entity_tu, 3 , entity_tu.tu_id ()) !=
446
+ SQLITE_OK) {
447
+ LOG (ERROR) << " sqlite binding insert_entity_tu failed: `"
448
+ << sqlite3_errmsg (db) << " `" ;
449
+ sqlite3_finalize (insert_entity_tu);
450
+ return false ;
451
+ }
452
+
453
+ if (sqlite3_step (insert_entity_tu) != SQLITE_DONE) {
454
+ LOG (ERROR) << " sqlite executing insert_entity_tu failed: `"
455
+ << sqlite3_errmsg (db) << " `" ;
456
+ sqlite3_finalize (insert_entity_tu);
457
+ return false ;
458
+ }
459
+
460
+ sqlite3_reset (insert_entity_tu);
461
+ sqlite3_clear_bindings (insert_entity_tu);
462
+ }
463
+
464
+ sqlite3_finalize (insert_entity_tu);
465
+ return true ;
466
+ }
467
+
468
+ bool InsertReferenceTranslationUnits (
469
+ sqlite3* db,
470
+ absl::Span<const ReferenceTranslationUnit> reference_translation_units) {
471
+ sqlite3_stmt* insert_reference_tu = nullptr ;
472
+ if (sqlite3_prepare_v2 (db, kInsertReferenceTranslationUnit ,
473
+ sizeof (kInsertReferenceTranslationUnit ),
474
+ &insert_reference_tu, nullptr ) != SQLITE_OK) {
475
+ LOG (ERROR) << " sqlite compiling prepared statement failed: `"
476
+ << sqlite3_errmsg (db) << " `" ;
477
+ return false ;
478
+ }
479
+
480
+ for (ReferenceTranslationUnitId i = 0 ; i < reference_translation_units.size ();
481
+ ++i) {
482
+ const ReferenceTranslationUnit& reference_tu =
483
+ reference_translation_units[i];
484
+ if (sqlite3_bind_int64 (insert_reference_tu, 1 , i) != SQLITE_OK ||
485
+ sqlite3_bind_int64 (insert_reference_tu, 2 ,
486
+ reference_tu.reference_id ()) != SQLITE_OK ||
487
+ sqlite3_bind_int64 (insert_reference_tu, 3 , reference_tu.tu_id ()) !=
488
+ SQLITE_OK) {
489
+ LOG (ERROR) << " sqlite binding insert_reference_tu failed: `"
490
+ << sqlite3_errmsg (db) << " `" ;
491
+ sqlite3_finalize (insert_reference_tu);
492
+ return false ;
493
+ }
494
+
495
+ if (sqlite3_step (insert_reference_tu) != SQLITE_DONE) {
496
+ LOG (ERROR) << " sqlite executing insert_reference_tu failed: `"
497
+ << sqlite3_errmsg (db) << " `" ;
498
+ sqlite3_finalize (insert_reference_tu);
499
+ return false ;
500
+ }
501
+
502
+ sqlite3_reset (insert_reference_tu);
503
+ sqlite3_clear_bindings (insert_reference_tu);
504
+ }
505
+
506
+ sqlite3_finalize (insert_reference_tu);
507
+ return true ;
508
+ }
348
509
} // anonymous namespace
349
510
350
511
bool SaveAsSqlite (const FlatIndex& index, const std::string& path) {
@@ -391,6 +552,39 @@ bool SaveAsSqlite(const FlatIndex& index, const std::string& path) {
391
552
return false ;
392
553
}
393
554
555
+ if (index.incremental_indexing_metadata .has_value ()) {
556
+ const IncrementalIndexingMetadata& metadata =
557
+ *index.incremental_indexing_metadata ;
558
+
559
+ LOG (INFO) << " creating incremental indexing support tables" ;
560
+ if (sqlite3_exec (db, kCreateIncrementalIndexingSupportTables , nullptr ,
561
+ nullptr , &error) != SQLITE_OK) {
562
+ LOG (ERROR) << " incremental indexing support table creation failed: `"
563
+ << error << " `" ;
564
+ sqlite3_close (db);
565
+ return false ;
566
+ }
567
+
568
+ LOG (INFO) << " inserting translation units" ;
569
+ if (!InsertTranslationUnits (db, metadata.translation_units )) {
570
+ sqlite3_close (db);
571
+ return false ;
572
+ }
573
+
574
+ LOG (INFO) << " inserting entity - translation unit pairs" ;
575
+ if (!InsertEntityTranslationUnits (db, metadata.entity_translation_units )) {
576
+ sqlite3_close (db);
577
+ return false ;
578
+ }
579
+
580
+ LOG (INFO) << " inserting reference - translation unit pairs" ;
581
+ if (!InsertReferenceTranslationUnits (
582
+ db, metadata.reference_translation_units )) {
583
+ sqlite3_close (db);
584
+ return false ;
585
+ }
586
+ }
587
+
394
588
LOG (INFO) << " finalizing database" ;
395
589
if (sqlite3_exec (db, kFinalizeDb , nullptr , nullptr , &error) != SQLITE_OK) {
396
590
LOG (ERROR) << " database finalization failed: `" << error << " `" ;
@@ -427,5 +621,6 @@ bool SaveAsSqlite(const FlatIndex& index, const std::string& path) {
427
621
sqlite3_close (db);
428
622
return backup_success;
429
623
}
624
+
430
625
} // namespace indexer
431
626
} // namespace oss_fuzz
0 commit comments