# How to Load Existing Graph Data into the Store Module in Codebase Memory MCP

> Load existing graph data into Codebase Memory MCP's store module by opening the SQLite database with cbm_store_open_path or cbm_store_open_path_query and using the CRUD API.

- Repository: [Martin Vogel/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp)
- Tags: how-to-guide
- Published: 2026-07-05

---

**Yes, you can load existing graph data by opening the SQLite database file using `cbm_store_open_path()` for read-write access or `cbm_store_open_path_query()` for read-only analysis, then querying via the high-level CRUD API.**

The store module in DeusData/codebase-memory-mcp serves as a thin abstraction layer over SQLite, persisting code-knowledge graphs in database files containing tables like `projects`, `nodes`, `edges`, and `file_hashes`. Loading existing graph data requires understanding how to initialize the store handle and validate the underlying database schema.

## Understanding the Store Module Architecture

### The SQLite Database Structure

Graphs are stored as standard SQLite files (`.db`) located in the cache directory (`$CBM_CACHE_DIR`) or custom paths you specify. These files contain relational tables representing the code-knowledge graph, including `projects`, `nodes`, `edges`, and `file_hashes`. When you load existing graph data, you are simply opening this SQLite file through the store API.

### The cbm_store_t Handle

The opaque type `cbm_store_t` (defined in [`src/store/store.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.h)) encapsulates a `sqlite3 *db` handle alongside cached prepared statements (`stmt_*`). This abstraction keeps the rest of the codebase independent of SQLite specifics while ensuring safety-related pragmas remain active.

## Opening Methods for Loading Graph Data

The module provides three entry points for opening a database, depending on your access requirements:

- **`cbm_store_open_path(const char *db_path)`**: Opens or creates a read-write store. Use this when loading existing graph data for modification, such as adding new nodes or updating edges.
- **`cbm_store_open_path_query(const char *db_path)`**: Opens a read-only store without `SQLITE_OPEN_CREATE` or write pragmas. Ideal for analysis-only workflows like search or graph traversal.
- **`cbm_store_open_memory(void)`**: Creates an in-memory store for testing scenarios where persistence is unnecessary.

### The Internal Opening Process

When you call `cbm_store_open_path` or `cbm_store_open_path_query`, the internal function `store_open_internal` (in [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c)) executes the following steps:

1. Allocates the handle and opens the SQLite file with `sqlite3_open_v2`.
2. Registers safety-critical SQLite functions including `regexp`, `iregexp`, `cbm_cosine_i8`, and `cbm_camel_split`.
3. Applies pragmas (foreign keys, mmap size, WAL mode) via `configure_pragmas`.
4. Initializes the schema (`init_schema`) if the file is new, or verifies compatibility otherwise.
5. Creates default user indexes via `create_user_indexes`.

## Step-by-Step Workflow to Load an Existing Graph

Follow this sequence to load and query existing graph data:

1. **Locate the database file** – typically stored under `$CBM_CACHE_DIR` or your specified path.
2. **Open the store** using `cbm_store_open_path()` for modifications or `cbm_store_open_path_query()` for read-only access.
3. **Execute queries** using high-level functions like `cbm_store_find_node_by_qn()` or `cbm_store_search()`.
4. **Close the store** with `cbm_store_close()` when finished.

## Handling Edge Cases and Validation

### Schema Version Mismatches

The store checks for the presence of the `local_name_gen` column (used by the `IMPORTS` edge type). If this column is missing, `store_open_internal` aborts, forcing you to rebuild the database.

### Read-Only Filesystems

`cbm_store_open_path_query` handles read-only filesystems by first attempting `SQLITE_OPEN_READONLY`. If this fails due to WAL-shm file creation issues, it falls back to an immutable URI (`file://…?immutable=1`) as implemented in lines 733-889 of [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c).

### Corruption Detection

Call `cbm_store_check_integrity()` to validate the `projects` table row count and `root_path` format. A false return indicates the database should be deleted and re-indexed.

## Importing from Checkpoints

To import an entire dump from another store (such as a checkpoint file), use `cbm_store_restore_from(dst, src)`. This function copies all pages via SQLite's backup API, declared in [`src/store/store.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.h) and implemented in [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c).

## Code Examples

### Loading for Read-Write Access

```c
#include <stdio.h>
#include "store/store.h"

/* Load an existing graph for read-write access */
cbm_store_t *store = cbm_store_open_path("/path/to/project.db");
if (!store) {
    fprintf(stderr, "Failed to open graph: %s\n", cbm_store_error(store));
    exit(1);
}

/* Find a node by qualified name */
cbm_node_t node;
int rc = cbm_store_find_node_by_qn(store, "myproject", "my.module.Class.method", &node);
if (rc == CBM_STORE_OK) {
    printf("Found node id=%lld label=%s\n", node.id, node.label);
    cbm_node_free_fields(&node);
} else {
    printf("Node not found (rc=%d)\n", rc);
}

/* Perform a regex search */
cbm_search_params_t params = {0};
params.project      = "myproject";
params.name_pattern = ".*Service$";
params.limit        = 20;
cbm_search_output_t out;
rc = cbm_store_search(store, &params, &out);
if (rc == CBM_STORE_OK) {
    for (int i = 0; i < out.count; ++i) {
        printf("- %s (%s)\n", out.results[i].node.qualified_name,
               out.results[i].node.label);
    }
    cbm_store_search_free(&out);
}

cbm_store_close(store);

```

### Loading for Read-Only Analysis

```c
#include <stdio.h>
#include "store/store.h"

/* Open existing graph read-only */
cbm_store_t *store = cbm_store_open_path_query("/path/to/project.db");
if (!store) {
    fprintf(stderr, "Graph file not found or unreadable.\n");
    exit(1);
}

/* Run vector search */
const char *keywords[] = {"auth", "token"};
cbm_vector_result_t *vec_res;
int vec_cnt;
int rc = cbm_store_vector_search(store,
                                 "myproject",
                                 keywords, 2,
                                 10,
                                 &vec_res, &vec_cnt);
if (rc == CBM_STORE_OK) {
    for (int i = 0; i < vec_cnt; ++i) {
        printf("%s (score %.2f)\n", vec_res[i].qualified_name, vec_res[i].score);
    }
    cbm_store_free_vector_results(vec_res, vec_cnt);
}
cbm_store_close(store);

```

## Summary

- Use `cbm_store_open_path()` to load existing graph data for modifications or `cbm_store_open_path_query()` for read-only analysis.
- The store module in [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c) handles SQLite initialization, schema validation, and safety pragmas automatically.
- Validate database integrity with `cbm_store_check_integrity()` before operations to detect corruption.
- Import complete graph dumps using `cbm_store_restore_from()` via the SQLite backup API.
- All high-level operations (`cbm_store_search`, `cbm_store_find_node_by_qn`) work directly on the loaded graph without requiring raw SQL.

## Frequently Asked Questions

### Can I load a graph database from a read-only filesystem?

Yes. When using `cbm_store_open_path_query()`, the function automatically falls back to an immutable URI (`file://…?immutable=1`) if the standard read-only open fails due to WAL-shm file restrictions. This logic is implemented in lines 733-889 of [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c).

### What happens if the database schema is outdated?

The `store_open_internal` function checks for the `local_name_gen` column presence. If this column is missing (indicating an older schema version), the function aborts the opening process, forcing you to delete the old database and rebuild it from source.

### Is it possible to import data from another graph file?

Yes. Use `cbm_store_restore_from(dst, src)` to copy all pages from a source database to a destination database using SQLite's backup API. This is useful for restoring from checkpoint files or merging graph data.

### Why should I use the store API instead of raw SQL?

All direct SQL execution is funneled through `cbm_store_exec()`, which validates the store's state and maintains the ATTACH/DETACH authorizer. This design prevents unsafe operations and ensures that SQLite-specific details remain abstracted from the rest of the codebase.