| 3860 | } |
| 3861 | |
| 3862 | static int arch_hotspots(cbm_store_t *s, const char *project, const char *path, |
| 3863 | cbm_architecture_info_t *out) { |
| 3864 | char norm[CBM_SZ_512]; |
| 3865 | char like[CBM_SZ_512]; |
| 3866 | bool scoped = arch_path_prepare(path, norm, sizeof(norm), like, sizeof(like)); |
| 3867 | char sqlbuf[ST_SQL_BUF]; |
| 3868 | const char *base = "SELECT n.name, n.qualified_name, COUNT(*) as fan_in " |
| 3869 | "FROM nodes n JOIN edges e ON e.target_id = n.id AND e.type = 'CALLS' " |
| 3870 | "WHERE n.project=?1 AND n.label IN ('Function', 'Method') " |
| 3871 | "AND (json_extract(n.properties, '$.is_test') IS NULL OR " |
| 3872 | "json_extract(n.properties, '$.is_test') != 1) " |
| 3873 | "AND n.file_path NOT LIKE '%test%'"; |
| 3874 | if (scoped) { |
| 3875 | snprintf(sqlbuf, sizeof(sqlbuf), |
| 3876 | "%s AND (n.file_path = ?2 OR n.file_path LIKE ?3) " |
| 3877 | "GROUP BY n.id ORDER BY fan_in DESC LIMIT 10", |
| 3878 | base); |
| 3879 | } else { |
| 3880 | snprintf(sqlbuf, sizeof(sqlbuf), "%s GROUP BY n.id ORDER BY fan_in DESC LIMIT 10", base); |
| 3881 | } |
| 3882 | sqlite3_stmt *stmt = NULL; |
| 3883 | if (sqlite3_prepare_v2(s->db, sqlbuf, CBM_NOT_FOUND, &stmt, NULL) != SQLITE_OK) { |
| 3884 | store_set_error_sqlite(s, "arch_hotspots"); |
| 3885 | return CBM_STORE_ERR; |
| 3886 | } |
| 3887 | bind_text(stmt, SKIP_ONE, project); |
| 3888 | if (scoped) { |
| 3889 | arch_bind_path_scope(stmt, ST_COL_2, ST_COL_3, norm, like); |
| 3890 | } |
| 3891 | |
| 3892 | int cap = ST_INIT_CAP_8; |
| 3893 | int n = 0; |
| 3894 | cbm_hotspot_t *arr = calloc(cap, sizeof(cbm_hotspot_t)); |
| 3895 | while (sqlite3_step(stmt) == SQLITE_ROW) { |
| 3896 | if (n >= cap) { |
| 3897 | cap *= ST_GROWTH; |
| 3898 | arr = safe_realloc(arr, cap * sizeof(cbm_hotspot_t)); |
| 3899 | } |
| 3900 | arr[n].name = heap_strdup((const char *)sqlite3_column_text(stmt, 0)); |
| 3901 | arr[n].qualified_name = heap_strdup((const char *)sqlite3_column_text(stmt, SKIP_ONE)); |
| 3902 | arr[n].fan_in = sqlite3_column_int(stmt, CBM_SZ_2); |
| 3903 | n++; |
| 3904 | } |
| 3905 | sqlite3_finalize(stmt); |
| 3906 | out->hotspots = arr; |
| 3907 | out->hotspot_count = n; |
| 3908 | return CBM_STORE_OK; |
| 3909 | } |
| 3910 | |
| 3911 | /* Look up package name for a node ID in the parallel arrays. nids must be |
| 3912 | * sorted ascending (the node query orders by id) — a linear scan here is |
no test coverage detected