DEV Community

Tito Osadebey
Tito Osadebey

Posted on

Ultimate Guide to Open Source Contribution (Part 2)

In the previous article, we presented a basic template to Open Source contributions and as stated also, we would be delving into how we can use that template to contribute to Apache AGE.

For a practical approach, we are looking at how the cos() function was implemented in AGE.

Note: Before creating a function in AGE, it should supported by Neo4j Cypher and/or PostgreSQL else there should be a very valid reason.

Firstly, we check similar functions to see the structure to follow accordingly and then implement in age--1.3.0.sql and src/backend/utils/adt/agtype.c files.

In age--1.3.0.sql, the function is declared:

CREATE FUNCTION ag_catalog.age_cos(variadic "any")
RETURNS agtype
LANGUAGE c
IMMUTABLE
PARALLEL SAFE
AS 'MODULE_PATHNAME';
Enter fullscreen mode Exit fullscreen mode

Then the function is created or added in agtype.c:

PG_FUNCTION_INFO_V1(age_cos);

Datum age_cos(PG_FUNCTION_ARGS)
{
    int nargs;
    Datum *args;
    bool *nulls;
    Oid *types;
    agtype_value agtv_result;
    float8 angle;
    float8 result;
    bool is_null = true;

    /* extract argument values */
    nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);

    /* check number of args */
    if (nargs != 1)
        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                        errmsg("cos() invalid number of arguments")));

    /* check for a null input */
    if (nargs < 0 || nulls[0])
        PG_RETURN_NULL();

    /*
     * cos() supports integer, float, and numeric or the agtype integer, float,
     * and numeric for the angle
     */

    angle = get_float_compatible_arg(args[0], types[0], "cos", &is_null);

    /* check for a agtype null input */
    if (is_null)
        PG_RETURN_NULL();

    /* We need the numeric input as a float8 so that we can pass it off to PG */
    result = DatumGetFloat8(DirectFunctionCall1(dcos,
                                                Float8GetDatum(angle)));

    /* build the result */
    agtv_result.type = AGTV_FLOAT;
    agtv_result.val.float_value = result;

    PG_RETURN_POINTER(agtype_value_to_agtype(&agtv_result));
}
Enter fullscreen mode Exit fullscreen mode

After creating a function, you should also write tests for that function to ensure it works efficiently. These tests are added to files in the regress/ directory in the repository depending on the function added. In the case of cos() function, the files we are interested in are regress/expected/expr.out and regress/sql/expr.sql.

These files are used to test the functions and compare the output of different files. If the output or result from expr.sql is different from that in expr.out then the tests will fail. Hence, ensure the tests pass before making a pull request.

Conclusion
This is just a basic guide to contributing to an open source project like AGE. The steps stated in the first article can be implemented in any project. Remember, the most important part of contribution is testing, this ensures you don't push a code that causes "hiroshima" to the project.

References
Apache AGE website
Apache AGE project

Top comments (0)