| 3950 | } |
| 3951 | |
| 3952 | static int arch_boundaries(cbm_store_t *s, const char *project, const char *path, |
| 3953 | cbm_cross_pkg_boundary_t **out_arr, int *out_count) { |
| 3954 | char norm[CBM_SZ_512]; |
| 3955 | char like[CBM_SZ_512]; |
| 3956 | bool scoped = arch_path_prepare(path, norm, sizeof(norm), like, sizeof(like)); |
| 3957 | char nsqlbuf[ST_SQL_BUF]; |
| 3958 | const char *nbase = |
| 3959 | "SELECT id, qualified_name, file_path FROM nodes WHERE project=?1 AND label IN " |
| 3960 | "('Function','Method','Class')"; |
| 3961 | if (scoped) { |
| 3962 | snprintf(nsqlbuf, sizeof(nsqlbuf), "%s%s ORDER BY id", nbase, arch_path_scope_sql()); |
| 3963 | } else { |
| 3964 | snprintf(nsqlbuf, sizeof(nsqlbuf), "%s ORDER BY id", nbase); |
| 3965 | } |
| 3966 | sqlite3_stmt *nstmt = NULL; |
| 3967 | if (sqlite3_prepare_v2(s->db, nsqlbuf, CBM_NOT_FOUND, &nstmt, NULL) != SQLITE_OK) { |
| 3968 | store_set_error_sqlite(s, "arch_boundaries_nodes"); |
| 3969 | return CBM_STORE_ERR; |
| 3970 | } |
| 3971 | bind_text(nstmt, SKIP_ONE, project); |
| 3972 | if (scoped) { |
| 3973 | arch_bind_path_scope(nstmt, ST_COL_2, ST_COL_3, norm, like); |
| 3974 | } |
| 3975 | |
| 3976 | int ncap = CBM_SZ_256; |
| 3977 | int nn = 0; |
| 3978 | int64_t *nids = malloc(ncap * sizeof(int64_t)); |
| 3979 | char **npkgs = malloc(ncap * sizeof(char *)); |
| 3980 | |
| 3981 | while (sqlite3_step(nstmt) == SQLITE_ROW) { |
| 3982 | if (nn >= ncap) { |
| 3983 | ncap *= ST_GROWTH; |
| 3984 | nids = safe_realloc(nids, ncap * sizeof(int64_t)); |
| 3985 | npkgs = safe_realloc(npkgs, ncap * sizeof(char *)); |
| 3986 | } |
| 3987 | int64_t nid = sqlite3_column_int64(nstmt, 0); |
| 3988 | nids[nn] = nid; |
| 3989 | const char *qn = (const char *)sqlite3_column_text(nstmt, SKIP_ONE); |
| 3990 | npkgs[nn] = heap_strdup(cbm_qn_to_package(qn)); |
| 3991 | nn++; |
| 3992 | } |
| 3993 | sqlite3_finalize(nstmt); |
| 3994 | |
| 3995 | /* Scan edges, count cross-package calls */ |
| 3996 | const char *esql = "SELECT source_id, target_id FROM edges WHERE project=?1 AND type='CALLS'"; |
| 3997 | sqlite3_stmt *estmt = NULL; |
| 3998 | if (sqlite3_prepare_v2(s->db, esql, CBM_NOT_FOUND, &estmt, NULL) != SQLITE_OK) { |
| 3999 | for (int i = 0; i < nn; i++) { |
| 4000 | free(npkgs[i]); |
| 4001 | } |
| 4002 | free(nids); |
| 4003 | free(npkgs); |
| 4004 | store_set_error_sqlite(s, "arch_boundaries_edges"); |
| 4005 | return CBM_STORE_ERR; |
| 4006 | } |
| 4007 | bind_text(estmt, SKIP_ONE, project); |
| 4008 | |
| 4009 | int bcap = CBM_SZ_32; |
no test coverage detected