diff --git a/src/backend/utils/adt/age_global_graph.c b/src/backend/utils/adt/age_global_graph.c index 6f30060ae..c34e51ee3 100644 --- a/src/backend/utils/adt/age_global_graph.c +++ b/src/backend/utils/adt/age_global_graph.c @@ -1237,12 +1237,10 @@ Datum age_delete_global_graphs(PG_FUNCTION_ARGS) { char *graph_name = NULL; - graph_name = strndup(agtv_temp->val.string.val, - agtv_temp->val.string.len); + graph_name = pnstrdup(agtv_temp->val.string.val, + agtv_temp->val.string.len); success = delete_specific_GRAPH_global_contexts(graph_name); - - free(graph_name); } else { diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c index be838cbd0..02fc3221c 100644 --- a/src/backend/utils/adt/agtype.c +++ b/src/backend/utils/adt/agtype.c @@ -181,6 +181,17 @@ static agtype_value *agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo); agtype_value *agtype_composite_to_agtype_value_binary(agtype *a); static agtype_value *tostring_helper(Datum arg, Oid type, char *msghdr); + +void *repalloc_check(void *ptr, size_t len) +{ + if (ptr != NULL) + { + return repalloc(ptr, len); + } + + return palloc(len); +} + /* * Due to how pfree can be implemented, it may not check for a passed NULL. This * wrapper does just that, it will only call pfree is the pointer passed is not @@ -5580,7 +5591,7 @@ static char *get_label_name(const char *graph_name, graphid element_graphid) result = NameStr(*DatumGetName(heap_getattr(tuple, Anum_ag_label_name, tupdesc, &column_is_null))); /* duplicate it */ - result = strdup(result); + result = pstrdup(result); /* end the scan and close the relation */ systable_endscan(scan_desc); @@ -5673,8 +5684,8 @@ Datum age_startnode(PG_FUNCTION_ARGS) Assert(AGT_ROOT_IS_SCALAR(agt_arg)); agtv_object = get_ith_agtype_value_from_container(&agt_arg->root, 0); Assert(agtv_object->type == AGTV_STRING); - graph_name = strndup(agtv_object->val.string.val, - agtv_object->val.string.len); + graph_name = pnstrdup(agtv_object->val.string.val, + agtv_object->val.string.len); /* get the edge */ agt_arg = AG_GET_ARG_AGTYPE_P(1); @@ -5708,8 +5719,6 @@ Datum age_startnode(PG_FUNCTION_ARGS) result = get_vertex(graph_name, label_name, start_id); - free(label_name); - return result; } @@ -5738,8 +5747,8 @@ Datum age_endnode(PG_FUNCTION_ARGS) Assert(AGT_ROOT_IS_SCALAR(agt_arg)); agtv_object = get_ith_agtype_value_from_container(&agt_arg->root, 0); Assert(agtv_object->type == AGTV_STRING); - graph_name = strndup(agtv_object->val.string.val, - agtv_object->val.string.len); + graph_name = pnstrdup(agtv_object->val.string.val, + agtv_object->val.string.len); /* get the edge */ agt_arg = AG_GET_ARG_AGTYPE_P(1); @@ -5773,8 +5782,6 @@ Datum age_endnode(PG_FUNCTION_ARGS) result = get_vertex(graph_name, label_name, end_id); - free(label_name); - return result; } @@ -6401,11 +6408,10 @@ Datum age_tofloat(PG_FUNCTION_ARGS) NumericGetDatum(agtv_value->val.numeric))); else if (agtv_value->type == AGTV_STRING) { - string = strndup(agtv_value->val.string.val, - agtv_value->val.string.len); + string = pnstrdup(agtv_value->val.string.val, + agtv_value->val.string.len); result = float8in_internal_null(string, NULL, "double precision", string, &is_valid); - free(string); if (!is_valid) PG_RETURN_NULL(); } @@ -6703,8 +6709,8 @@ Datum age_tointeger(PG_FUNCTION_ARGS) { char *endptr; /* we need a null terminated cstring */ - string = strndup(agtv_value->val.string.val, - agtv_value->val.string.len); + string = pnstrdup(agtv_value->val.string.val, + agtv_value->val.string.len); /* convert it if it is a regular integer string */ result = strtoi64(string, &endptr, 10); @@ -6718,7 +6724,6 @@ Datum age_tointeger(PG_FUNCTION_ARGS) f = float8in_internal_null(string, NULL, "double precision", string, &is_valid); - free(string); /* * If the conversions failed or it's a special float value, * return null. @@ -6731,10 +6736,6 @@ Datum age_tointeger(PG_FUNCTION_ARGS) result = (int64) f; } - else - { - free(string); - } } else { diff --git a/src/backend/utils/load/ag_load_edges.c b/src/backend/utils/load/ag_load_edges.c index 67049431c..931c6e0dc 100644 --- a/src/backend/utils/load/ag_load_edges.c +++ b/src/backend/utils/load/ag_load_edges.c @@ -36,8 +36,8 @@ void edge_field_cb(void *field, size_t field_len, void *data) if (cr->cur_field == cr->alloc) { cr->alloc *= 2; - cr->fields = realloc(cr->fields, sizeof(char *) * cr->alloc); - cr->fields_len = realloc(cr->header, sizeof(size_t *) * cr->alloc); + cr->fields = repalloc_check(cr->fields, sizeof(char *) * cr->alloc); + cr->fields_len = repalloc_check(cr->header, sizeof(size_t *) * cr->alloc); if (cr->fields == NULL) { cr->error = 1; @@ -48,7 +48,7 @@ void edge_field_cb(void *field, size_t field_len, void *data) } cr->fields_len[cr->cur_field] = field_len; cr->curr_row_length += field_len; - cr->fields[cr->cur_field] = strndup((char*)field, field_len); + cr->fields[cr->cur_field] = pnstrdup((char*)field, field_len); cr->cur_field += 1; } @@ -78,13 +78,13 @@ void edge_row_cb(int delim __attribute__((unused)), void *data) { cr->header_num = cr->cur_field; cr->header_row_length = cr->curr_row_length; - cr->header_len = (size_t* )malloc(sizeof(size_t *) * cr->cur_field); - cr->header = malloc((sizeof (char*) * cr->cur_field)); + cr->header_len = (size_t* )palloc(sizeof(size_t *) * cr->cur_field); + cr->header = palloc((sizeof (char*) * cr->cur_field)); for (i = 0; icur_field; i++) { cr->header_len[i] = cr->fields_len[i]; - cr->header[i] = strndup(cr->fields[i], cr->header_len[i]); + cr->header[i] = pnstrdup(cr->fields[i], cr->header_len[i]); } } else @@ -133,7 +133,7 @@ void edge_row_cb(int delim __attribute__((unused)), void *data) for (i = 0; i < n_fields; ++i) { - free(cr->fields[i]); + pfree_if_not_null(cr->fields[i]); } if (cr->error) @@ -192,6 +192,10 @@ int create_edges_from_csv_file(char *file_path, (errmsg("Failed to initialize csv parser\n"))); } + p.malloc_func = palloc; + p.realloc_func = repalloc_check; + p.free_func = pfree_if_not_null; + csv_set_space_func(&p, is_space); csv_set_term_func(&p, is_term); @@ -202,47 +206,52 @@ int create_edges_from_csv_file(char *file_path, (errmsg("Failed to open %s\n", file_path))); } - label_seq_name = get_label_seq_relation_name(label_name); - - memset((void*)&cr, 0, sizeof(csv_edge_reader)); - cr.alloc = 128; - cr.fields = malloc(sizeof(char *) * cr.alloc); - cr.fields_len = malloc(sizeof(size_t *) * cr.alloc); - cr.header_row_length = 0; - cr.curr_row_length = 0; - cr.graph_name = graph_name; - cr.graph_oid = graph_oid; - cr.label_name = label_name; - cr.label_id = label_id; - cr.label_seq_relid = get_relname_relid(label_seq_name, graph_oid); - cr.load_as_agtype = load_as_agtype; - - /* Initialize the batch insert state */ - init_batch_insert(&cr.batch_state, label_name, graph_oid); - - while ((bytes_read=fread(buf, 1, 1024, fp)) > 0) + PG_TRY(); { - if (csv_parse(&p, buf, bytes_read, edge_field_cb, - edge_row_cb, &cr) != bytes_read) + label_seq_name = get_label_seq_relation_name(label_name); + + memset((void*)&cr, 0, sizeof(csv_edge_reader)); + cr.alloc = 128; + cr.fields = palloc(sizeof(char *) * cr.alloc); + cr.fields_len = palloc(sizeof(size_t *) * cr.alloc); + cr.header_row_length = 0; + cr.curr_row_length = 0; + cr.graph_name = graph_name; + cr.graph_oid = graph_oid; + cr.label_name = label_name; + cr.label_id = label_id; + cr.label_seq_relid = get_relname_relid(label_seq_name, graph_oid); + cr.load_as_agtype = load_as_agtype; + + /* Initialize the batch insert state */ + init_batch_insert(&cr.batch_state, label_name, graph_oid); + + while ((bytes_read=fread(buf, 1, 1024, fp)) > 0) { - ereport(ERROR, (errmsg("Error while parsing file: %s\n", - csv_strerror(csv_error(&p))))); + if (csv_parse(&p, buf, bytes_read, edge_field_cb, + edge_row_cb, &cr) != bytes_read) + { + ereport(ERROR, (errmsg("Error while parsing file: %s\n", + csv_strerror(csv_error(&p))))); + } } - } - csv_fini(&p, edge_field_cb, edge_row_cb, &cr); + csv_fini(&p, edge_field_cb, edge_row_cb, &cr); - /* Finish any remaining batch inserts */ - finish_batch_insert(&cr.batch_state); + /* Finish any remaining batch inserts */ + finish_batch_insert(&cr.batch_state); - if (ferror(fp)) + if (ferror(fp)) + { + ereport(ERROR, (errmsg("Error while reading file %s\n", file_path))); + } + } + PG_FINALLY(); { - ereport(ERROR, (errmsg("Error while reading file %s\n", file_path))); + fclose(fp); + csv_free(&p); } + PG_END_TRY(); - fclose(fp); - - free(cr.fields); - csv_free(&p); return EXIT_SUCCESS; -} \ No newline at end of file +} diff --git a/src/backend/utils/load/ag_load_labels.c b/src/backend/utils/load/ag_load_labels.c index 4a04f3cd8..1e86bbda4 100644 --- a/src/backend/utils/load/ag_load_labels.c +++ b/src/backend/utils/load/ag_load_labels.c @@ -39,8 +39,8 @@ void vertex_field_cb(void *field, size_t field_len, void *data) if (cr->cur_field == cr->alloc) { cr->alloc *= 2; - cr->fields = realloc(cr->fields, sizeof(char *) * cr->alloc); - cr->fields_len = realloc(cr->header, sizeof(size_t *) * cr->alloc); + cr->fields = repalloc_check(cr->fields, sizeof(char *) * cr->alloc); + cr->fields_len = repalloc_check(cr->header, sizeof(size_t *) * cr->alloc); if (cr->fields == NULL) { cr->error = 1; @@ -51,7 +51,7 @@ void vertex_field_cb(void *field, size_t field_len, void *data) } cr->fields_len[cr->cur_field] = field_len; cr->curr_row_length += field_len; - cr->fields[cr->cur_field] = strndup((char *) field, field_len); + cr->fields[cr->cur_field] = pnstrdup((char *) field, field_len); cr->cur_field += 1; } @@ -70,13 +70,13 @@ void vertex_row_cb(int delim __attribute__((unused)), void *data) { cr->header_num = cr->cur_field; cr->header_row_length = cr->curr_row_length; - cr->header_len = (size_t* )malloc(sizeof(size_t *) * cr->cur_field); - cr->header = malloc((sizeof (char*) * cr->cur_field)); + cr->header_len = (size_t* )palloc(sizeof(size_t *) * cr->cur_field); + cr->header = palloc((sizeof (char*) * cr->cur_field)); for (i = 0; icur_field; i++) { cr->header_len[i] = cr->fields_len[i]; - cr->header[i] = strndup(cr->fields[i], cr->header_len[i]); + cr->header[i] = pnstrdup(cr->fields[i], cr->header_len[i]); } } else @@ -129,7 +129,7 @@ void vertex_row_cb(int delim __attribute__((unused)), void *data) for (i = 0; i < n_fields; ++i) { - free(cr->fields[i]); + pfree_if_not_null(cr->fields[i]); } if (cr->error) @@ -189,6 +189,10 @@ int create_labels_from_csv_file(char *file_path, (errmsg("Failed to initialize csv parser\n"))); } + p.malloc_func = palloc; + p.realloc_func = repalloc_check; + p.free_func = pfree_if_not_null; + csv_set_space_func(&p, is_space); csv_set_term_func(&p, is_term); @@ -199,62 +203,67 @@ int create_labels_from_csv_file(char *file_path, (errmsg("Failed to open %s\n", file_path))); } - label_seq_name = get_label_seq_relation_name(label_name); - - memset((void*)&cr, 0, sizeof(csv_vertex_reader)); - - cr.alloc = 2048; - cr.fields = malloc(sizeof(char *) * cr.alloc); - cr.fields_len = malloc(sizeof(size_t *) * cr.alloc); - cr.header_row_length = 0; - cr.curr_row_length = 0; - cr.graph_name = graph_name; - cr.graph_oid = graph_oid; - cr.label_name = label_name; - cr.label_id = label_id; - cr.id_field_exists = id_field_exists; - cr.label_seq_relid = get_relname_relid(label_seq_name, graph_oid); - cr.load_as_agtype = load_as_agtype; - - if (cr.id_field_exists) + PG_TRY(); { - /* - * Set the curr_seq_num since we will need it to compare with - * incoming entry_id. - * - * We cant use currval because it will error out if nextval was - * not called before in the session. - */ - cr.curr_seq_num = nextval_internal(cr.label_seq_relid, true); - } + label_seq_name = get_label_seq_relation_name(label_name); + + memset((void*)&cr, 0, sizeof(csv_vertex_reader)); + + cr.alloc = 2048; + cr.fields = palloc(sizeof(char *) * cr.alloc); + cr.fields_len = palloc(sizeof(size_t *) * cr.alloc); + cr.header_row_length = 0; + cr.curr_row_length = 0; + cr.graph_name = graph_name; + cr.graph_oid = graph_oid; + cr.label_name = label_name; + cr.label_id = label_id; + cr.id_field_exists = id_field_exists; + cr.label_seq_relid = get_relname_relid(label_seq_name, graph_oid); + cr.load_as_agtype = load_as_agtype; + + if (cr.id_field_exists) + { + /* + * Set the curr_seq_num since we will need it to compare with + * incoming entry_id. + * + * We cant use currval because it will error out if nextval was + * not called before in the session. + */ + cr.curr_seq_num = nextval_internal(cr.label_seq_relid, true); + } - /* Initialize the batch insert state */ - init_batch_insert(&cr.batch_state, label_name, graph_oid); + /* Initialize the batch insert state */ + init_batch_insert(&cr.batch_state, label_name, graph_oid); - while ((bytes_read=fread(buf, 1, 1024, fp)) > 0) - { - if (csv_parse(&p, buf, bytes_read, vertex_field_cb, - vertex_row_cb, &cr) != bytes_read) + while ((bytes_read=fread(buf, 1, 1024, fp)) > 0) { - ereport(ERROR, (errmsg("Error while parsing file: %s\n", - csv_strerror(csv_error(&p))))); + if (csv_parse(&p, buf, bytes_read, vertex_field_cb, + vertex_row_cb, &cr) != bytes_read) + { + ereport(ERROR, (errmsg("Error while parsing file: %s\n", + csv_strerror(csv_error(&p))))); + } } - } - csv_fini(&p, vertex_field_cb, vertex_row_cb, &cr); + csv_fini(&p, vertex_field_cb, vertex_row_cb, &cr); - /* Finish any remaining batch inserts */ - finish_batch_insert(&cr.batch_state); + /* Finish any remaining batch inserts */ + finish_batch_insert(&cr.batch_state); - if (ferror(fp)) + if (ferror(fp)) + { + ereport(ERROR, (errmsg("Error while reading file %s\n", + file_path))); + } + } + PG_FINALLY(); { - ereport(ERROR, (errmsg("Error while reading file %s\n", - file_path))); + fclose(fp); + csv_free(&p); } + PG_END_TRY(); - fclose(fp); - - free(cr.fields); - csv_free(&p); return EXIT_SUCCESS; } \ No newline at end of file diff --git a/src/include/utils/agtype.h b/src/include/utils/agtype.h index 486775320..ab2ba08cc 100644 --- a/src/include/utils/agtype.h +++ b/src/include/utils/agtype.h @@ -556,6 +556,7 @@ void pfree_agtype_value(agtype_value* value); void pfree_agtype_value_content(agtype_value* value); void pfree_agtype_in_state(agtype_in_state* value); void pfree_if_not_null(void *ptr); +void *repalloc_check(void *ptr, size_t len); agtype_value *agtype_value_from_cstring(char *str, int len); /* Oid accessors for AGTYPE */ Oid get_AGTYPEOID(void);