| 2064 | } |
| 2065 | |
| 2066 | static int count_degrees_direction(cbm_store_t *s, const int64_t *node_ids, int id_count, |
| 2067 | const char *in_clause, bool has_type, const char *edge_type, |
| 2068 | bool inbound, int *out_counts) { |
| 2069 | char sql[ST_SQL_BUF]; |
| 2070 | const char *id_col = inbound ? "target_id" : "source_id"; |
| 2071 | if (has_type) { |
| 2072 | snprintf(sql, sizeof(sql), |
| 2073 | "SELECT %s, COUNT(*) FROM edges " |
| 2074 | "WHERE %s IN (%s) AND type = ? GROUP BY %s", |
| 2075 | id_col, id_col, in_clause, id_col); |
| 2076 | } else { |
| 2077 | snprintf(sql, sizeof(sql), |
| 2078 | "SELECT %s, COUNT(*) FROM edges " |
| 2079 | "WHERE %s IN (%s) GROUP BY %s", |
| 2080 | id_col, id_col, in_clause, id_col); |
| 2081 | } |
| 2082 | |
| 2083 | sqlite3_stmt *stmt = NULL; |
| 2084 | if (sqlite3_prepare_v2(s->db, sql, CBM_NOT_FOUND, &stmt, NULL) != SQLITE_OK) { |
| 2085 | return CBM_STORE_ERR; |
| 2086 | } |
| 2087 | |
| 2088 | for (int i = 0; i < id_count; i++) { |
| 2089 | sqlite3_bind_int64(stmt, i + SKIP_ONE, node_ids[i]); |
| 2090 | } |
| 2091 | if (has_type) { |
| 2092 | bind_text(stmt, id_count + SKIP_ONE, edge_type); |
| 2093 | } |
| 2094 | |
| 2095 | while (sqlite3_step(stmt) == SQLITE_ROW) { |
| 2096 | int64_t nid = sqlite3_column_int64(stmt, 0); |
| 2097 | int cnt = sqlite3_column_int(stmt, SKIP_ONE); |
| 2098 | for (int i = 0; i < id_count; i++) { |
| 2099 | if (node_ids[i] == nid) { |
| 2100 | out_counts[i] = cnt; |
| 2101 | break; |
| 2102 | } |
| 2103 | } |
| 2104 | } |
| 2105 | sqlite3_finalize(stmt); |
| 2106 | return CBM_STORE_OK; |
| 2107 | } |
| 2108 | |
| 2109 | int cbm_store_batch_count_degrees(cbm_store_t *s, const int64_t *node_ids, int id_count, |
| 2110 | const char *edge_type, int *out_in, int *out_out) { |
no test coverage detected