99 * - graph_algo_centrality.c
1010 */
1111
12+ #include <limits.h>
1213#include <stdio.h>
1314#include <stdlib.h>
1415#include <string.h>
@@ -274,6 +275,90 @@ static char* resolve_string_arg(ast_node *node, const char *params_json)
274275 return NULL ;
275276}
276277
278+ /*
279+ * Resolve a function argument to a int value.
280+ * Handles AST_NODE_LITERAL (integer) and AST_NODE_PARAMETER (via params_json).
281+ * Returns int on success, default_value on failure.
282+ */
283+ static int resolve_int_arg (ast_node * node , const char * params_json , int default_value )
284+ {
285+ if (!node ) return default_value ;
286+
287+ if (node -> type == AST_NODE_LITERAL ) {
288+ cypher_literal * lit = (cypher_literal * )node ;
289+ if (lit && lit -> base .type == AST_NODE_LITERAL && lit -> literal_type == LITERAL_INTEGER ) {
290+ return (int ) lit -> value .integer ;
291+ }
292+ return default_value ;
293+ }
294+
295+ if (node -> type == AST_NODE_PARAMETER ) {
296+ cypher_parameter * param = (cypher_parameter * )node ;
297+ if (!params_json || !param -> name ) return default_value ;
298+
299+ property_type ptype ;
300+ char str_buf [256 ];
301+ int rc = get_param_value (params_json , param -> name , & ptype , str_buf , sizeof (str_buf ));
302+ if (rc == 0 && ptype == PROP_TYPE_INTEGER ) {
303+ int64_t int_buf = * (int64_t * )str_buf ;
304+ if (int_buf - INT_MIN <= (int64_t )INT_MAX - INT_MIN ) {
305+ return (int )int_buf ;
306+ }
307+ }
308+
309+ return default_value ;
310+ }
311+
312+ return default_value ;
313+ }
314+
315+ /*
316+ * Resolve a function argument to a double value.
317+ * Handles AST_NODE_LITERAL (double) and AST_NODE_PARAMETER (via params_json).
318+ * Returns double on success, default_value on failure.
319+ */
320+ static double resolve_double_arg (ast_node * node , const char * params_json , double default_value )
321+ {
322+ if (!node ) return default_value ;
323+
324+ if (node -> type == AST_NODE_LITERAL ) {
325+ cypher_literal * lit = (cypher_literal * )node ;
326+ if (lit && lit -> base .type == AST_NODE_LITERAL ) {
327+ if (lit -> literal_type == LITERAL_DECIMAL ) {
328+ return lit -> value .decimal ;
329+ } else if (lit -> literal_type == LITERAL_INTEGER ) {
330+ return (double )lit -> value .integer ;
331+ }
332+ }
333+
334+ return default_value ;
335+ }
336+
337+ if (node -> type == AST_NODE_PARAMETER ) {
338+ cypher_parameter * param = (cypher_parameter * )node ;
339+ if (!params_json || !param -> name ) return default_value ;
340+
341+ property_type ptype ;
342+ char str_buf [256 ];
343+ int rc = get_param_value (params_json , param -> name , & ptype , str_buf , sizeof (str_buf ));
344+
345+ if (rc == 0 && ptype == PROP_TYPE_REAL ) {
346+ return * (double * )str_buf ;
347+ }
348+
349+ if (rc == 0 && ptype == PROP_TYPE_INTEGER ) {
350+ int64_t int_buf = * (int64_t * )str_buf ;
351+ if (int_buf - INT_MIN <= (int64_t )INT_MAX - INT_MIN ) {
352+ return (double )int_buf ;
353+ }
354+ }
355+
356+ return default_value ;
357+ }
358+
359+ return default_value ;
360+ }
361+
277362/* Detect graph algorithm in RETURN clause */
278363graph_algo_params detect_graph_algorithm (cypher_return * return_clause , const char * params_json )
279364{
@@ -306,23 +391,12 @@ graph_algo_params detect_graph_algorithm(cypher_return *return_clause, const cha
306391 params .type = GRAPH_ALGO_PAGERANK ;
307392
308393 if (func -> args && func -> args -> count >= 1 ) {
309- cypher_literal * damp_lit = (cypher_literal * )func -> args -> items [0 ];
310- if (damp_lit && damp_lit -> base .type == AST_NODE_LITERAL ) {
311- if (damp_lit -> literal_type == LITERAL_DECIMAL ) {
312- params .damping = damp_lit -> value .decimal ;
313- } else if (damp_lit -> literal_type == LITERAL_INTEGER ) {
314- params .damping = (double )damp_lit -> value .integer ;
315- }
316- }
394+ params .damping = resolve_double_arg ((ast_node * )func -> args -> items [0 ], params_json , params .damping );
317395 }
318396 if (func -> args && func -> args -> count >= 2 ) {
319- cypher_literal * iter_lit = (cypher_literal * )func -> args -> items [1 ];
320- if (iter_lit && iter_lit -> base .type == AST_NODE_LITERAL &&
321- iter_lit -> literal_type == LITERAL_INTEGER ) {
322- params .iterations = iter_lit -> value .integer ;
323- if (params .iterations < 1 ) params .iterations = 1 ;
324- if (params .iterations > 100 ) params .iterations = 100 ;
325- }
397+ params .iterations = resolve_int_arg ((ast_node * )func -> args -> items [1 ], params_json , params .iterations );
398+ if (params .iterations < 1 ) params .iterations = 1 ;
399+ if (params .iterations > 100 ) params .iterations = 100 ;
326400 }
327401 return params ;
328402 }
@@ -333,32 +407,17 @@ graph_algo_params detect_graph_algorithm(cypher_return *return_clause, const cha
333407 params .top_k = 10 ;
334408
335409 if (func -> args && func -> args -> count >= 1 ) {
336- cypher_literal * k_lit = (cypher_literal * )func -> args -> items [0 ];
337- if (k_lit && k_lit -> base .type == AST_NODE_LITERAL &&
338- k_lit -> literal_type == LITERAL_INTEGER ) {
339- params .top_k = k_lit -> value .integer ;
340- if (params .top_k < 1 ) params .top_k = 1 ;
341- if (params .top_k > 1000 ) params .top_k = 1000 ;
342- }
410+ params .top_k = resolve_int_arg ((ast_node * )func -> args -> items [0 ], params_json , params .top_k );
411+ if (params .top_k < 1 ) params .top_k = 1 ;
412+ if (params .top_k > 1000 ) params .top_k = 1000 ;
343413 }
344414 if (func -> args && func -> args -> count >= 2 ) {
345- cypher_literal * damp_lit = (cypher_literal * )func -> args -> items [1 ];
346- if (damp_lit && damp_lit -> base .type == AST_NODE_LITERAL ) {
347- if (damp_lit -> literal_type == LITERAL_DECIMAL ) {
348- params .damping = damp_lit -> value .decimal ;
349- } else if (damp_lit -> literal_type == LITERAL_INTEGER ) {
350- params .damping = (double )damp_lit -> value .integer ;
351- }
352- }
415+ params .damping = resolve_double_arg ((ast_node * )func -> args -> items [1 ], params_json , params .damping );
353416 }
354417 if (func -> args && func -> args -> count >= 3 ) {
355- cypher_literal * iter_lit = (cypher_literal * )func -> args -> items [2 ];
356- if (iter_lit && iter_lit -> base .type == AST_NODE_LITERAL &&
357- iter_lit -> literal_type == LITERAL_INTEGER ) {
358- params .iterations = iter_lit -> value .integer ;
359- if (params .iterations < 1 ) params .iterations = 1 ;
360- if (params .iterations > 100 ) params .iterations = 100 ;
361- }
418+ params .iterations = resolve_int_arg ((ast_node * )func -> args -> items [2 ], params_json , params .iterations );
419+ if (params .iterations < 1 ) params .iterations = 1 ;
420+ if (params .iterations > 100 ) params .iterations = 100 ;
362421 }
363422 return params ;
364423 }
@@ -369,13 +428,9 @@ graph_algo_params detect_graph_algorithm(cypher_return *return_clause, const cha
369428 params .iterations = 10 ;
370429
371430 if (func -> args && func -> args -> count >= 1 ) {
372- cypher_literal * iter_lit = (cypher_literal * )func -> args -> items [0 ];
373- if (iter_lit && iter_lit -> base .type == AST_NODE_LITERAL &&
374- iter_lit -> literal_type == LITERAL_INTEGER ) {
375- params .iterations = iter_lit -> value .integer ;
376- if (params .iterations < 1 ) params .iterations = 1 ;
377- if (params .iterations > 100 ) params .iterations = 100 ;
378- }
431+ params .iterations = resolve_int_arg ((ast_node * )func -> args -> items [0 ], params_json , params .iterations );
432+ if (params .iterations < 1 ) params .iterations = 1 ;
433+ if (params .iterations > 100 ) params .iterations = 100 ;
379434 }
380435 return params ;
381436 }
@@ -436,14 +491,7 @@ graph_algo_params detect_graph_algorithm(cypher_return *return_clause, const cha
436491
437492 /* Optional resolution parameter */
438493 if (func -> args && func -> args -> count >= 1 ) {
439- cypher_literal * res_lit = (cypher_literal * )func -> args -> items [0 ];
440- if (res_lit && res_lit -> base .type == AST_NODE_LITERAL ) {
441- if (res_lit -> literal_type == LITERAL_DECIMAL ) {
442- params .resolution = res_lit -> value .decimal ;
443- } else if (res_lit -> literal_type == LITERAL_INTEGER ) {
444- params .resolution = (double )res_lit -> value .integer ;
445- }
446- }
494+ params .resolution = resolve_double_arg ((ast_node * )func -> args -> items [0 ], params_json , params .resolution );
447495 }
448496 return params ;
449497 }
@@ -483,11 +531,7 @@ graph_algo_params detect_graph_algorithm(cypher_return *return_clause, const cha
483531 params .source_id = resolve_string_arg ((ast_node * )func -> args -> items [0 ], params_json );
484532 }
485533 if (func -> args && func -> args -> count >= 2 ) {
486- cypher_literal * depth_lit = (cypher_literal * )func -> args -> items [1 ];
487- if (depth_lit && depth_lit -> base .type == AST_NODE_LITERAL &&
488- depth_lit -> literal_type == LITERAL_INTEGER ) {
489- params .max_depth = (int )depth_lit -> value .integer ;
490- }
534+ params .max_depth = resolve_int_arg ((ast_node * )func -> args -> items [1 ], params_json , -1 );
491535 }
492536 return params ;
493537 }
@@ -502,11 +546,7 @@ graph_algo_params detect_graph_algorithm(cypher_return *return_clause, const cha
502546 params .source_id = resolve_string_arg ((ast_node * )func -> args -> items [0 ], params_json );
503547 }
504548 if (func -> args && func -> args -> count >= 2 ) {
505- cypher_literal * depth_lit = (cypher_literal * )func -> args -> items [1 ];
506- if (depth_lit && depth_lit -> base .type == AST_NODE_LITERAL &&
507- depth_lit -> literal_type == LITERAL_INTEGER ) {
508- params .max_depth = (int )depth_lit -> value .integer ;
509- }
549+ params .max_depth = resolve_int_arg ((ast_node * )func -> args -> items [1 ], params_json , -1 );
510550 }
511551 return params ;
512552 }
@@ -540,24 +580,13 @@ graph_algo_params detect_graph_algorithm(cypher_return *return_clause, const cha
540580 }
541581 /* Check for threshold: nodeSimilarity(0.5) */
542582 else if (func -> args && func -> args -> count >= 1 ) {
543- cypher_literal * thresh_lit = (cypher_literal * )func -> args -> items [0 ];
544- if (thresh_lit && thresh_lit -> base .type == AST_NODE_LITERAL ) {
545- if (thresh_lit -> literal_type == LITERAL_DECIMAL ) {
546- params .threshold = thresh_lit -> value .decimal ;
547- } else if (thresh_lit -> literal_type == LITERAL_INTEGER ) {
548- params .threshold = (double )thresh_lit -> value .integer ;
549- }
550- }
583+ params .threshold = resolve_double_arg ((ast_node * )func -> args -> items [0 ], params_json , params .threshold );
551584 }
552585
553586 /* Check for top_k as last argument */
554587 if (func -> args && func -> args -> count >= 2 && !params .source_id ) {
555588 /* nodeSimilarity(threshold, top_k) */
556- cypher_literal * topk_lit = (cypher_literal * )func -> args -> items [1 ];
557- if (topk_lit && topk_lit -> base .type == AST_NODE_LITERAL &&
558- topk_lit -> literal_type == LITERAL_INTEGER ) {
559- params .top_k = (int )topk_lit -> value .integer ;
560- }
589+ params .top_k = resolve_int_arg ((ast_node * )func -> args -> items [1 ], params_json , params .top_k );
561590 }
562591
563592 return params ;
@@ -574,11 +603,7 @@ graph_algo_params detect_graph_algorithm(cypher_return *return_clause, const cha
574603 params .source_id = resolve_string_arg ((ast_node * )func -> args -> items [0 ], params_json );
575604 }
576605 if (func -> args && func -> args -> count >= 2 ) {
577- cypher_literal * k_lit = (cypher_literal * )func -> args -> items [1 ];
578- if (k_lit && k_lit -> base .type == AST_NODE_LITERAL &&
579- k_lit -> literal_type == LITERAL_INTEGER ) {
580- params .k = (int )k_lit -> value .integer ;
581- }
606+ params .k = resolve_int_arg ((ast_node * )func -> args -> items [1 ], params_json , params .k );
582607 }
583608
584609 return params ;
@@ -591,13 +616,9 @@ graph_algo_params detect_graph_algorithm(cypher_return *return_clause, const cha
591616
592617 /* Optional iterations parameter */
593618 if (func -> args && func -> args -> count >= 1 ) {
594- cypher_literal * iter_lit = (cypher_literal * )func -> args -> items [0 ];
595- if (iter_lit && iter_lit -> base .type == AST_NODE_LITERAL &&
596- iter_lit -> literal_type == LITERAL_INTEGER ) {
597- params .iterations = (int )iter_lit -> value .integer ;
598- if (params .iterations < 1 ) params .iterations = 1 ;
599- if (params .iterations > 1000 ) params .iterations = 1000 ;
600- }
619+ params .iterations = resolve_int_arg ((ast_node * )func -> args -> items [0 ], params_json , params .iterations );
620+ if (params .iterations < 1 ) params .iterations = 1 ;
621+ if (params .iterations > 1000 ) params .iterations = 1000 ;
601622 }
602623 return params ;
603624 }
0 commit comments