trafodion-codereview mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From traflm <...@git.apache.org>
Subject [GitHub] incubator-trafodion pull request #833: jira 2227 : support json fuction - JS...
Date Thu, 17 Nov 2016 15:56:10 GMT
Github user traflm commented on a diff in the pull request:

    https://github.com/apache/incubator-trafodion/pull/833#discussion_r88481672
  
    --- Diff: core/sql/common/ComJSONFuncs.cpp ---
    @@ -0,0 +1,793 @@
    +/*-------------------------------------------------------------------------
    + *
    + * jsonfuncs.c
    + *		Functions to process JSON data types.
    + *
    + * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
    + * Portions Copyright (c) 1994, Regents of the University of California
    + *
    + * IDENTIFICATION
    + *	  src/backend/utils/adt/jsonfuncs.c
    + *
    + *-------------------------------------------------------------------------
    + */
    +/**********************************************************************
    +// @@@ START COPYRIGHT @@@
    +//
    +// Licensed to the Apache Software Foundation (ASF) under one
    +// or more contributor license agreements.  See the NOTICE file
    +// distributed with this work for additional information
    +// regarding copyright ownership.  The ASF licenses this file
    +// to you under the Apache License, Version 2.0 (the
    +// "License"); you may not use this file except in compliance
    +// with the License.  You may obtain a copy of the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing,
    +// software distributed under the License is distributed on an
    +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    +// KIND, either express or implied.  See the License for the
    +// specific language governing permissions and limitations
    +// under the License.
    +//
    +// @@@ END COPYRIGHT @@@
    +**********************************************************************/
    +
    +#include "ComJSONStringInfo.h"
    +#include "ComJSON.h"
    +#include <stdarg.h>
    +#include <limits.h>
    +#include <errno.h>
    +#include <stdlib.h>
    +#include <string.h>
    +#include "str.h"
    +
    +/* semantic action functions for json_get* functions */
    +static JsonReturnType get_object_start(void *state);
    +static JsonReturnType get_object_end(void *state);
    +static JsonReturnType get_object_field_start(void *state, char *fname, bool isnull);
    +static JsonReturnType get_object_field_end(void *state, char *fname, bool isnull);
    +static JsonReturnType get_array_start(void *state);
    +static JsonReturnType get_array_end(void *state);
    +static JsonReturnType get_array_element_start(void *state, bool isnull);
    +static JsonReturnType get_array_element_end(void *state, bool isnull);
    +static JsonReturnType get_scalar(void *state, char *token, JsonTokenType tokentype);
    +
    +/* common worker function for json getter functions */
    +static JsonReturnType get_path_all(bool as_text, char *json, short nargs, va_list args,
char **result);
    +static JsonReturnType get_worker(char *json, char **tpath, int *ipath, int npath,
    +                                 bool normalize_results, char **result);
    +
    +
    +/* semantic action functions for json_array_length */
    +static void alen_object_start(void *state);
    +static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
    +static void alen_array_element_start(void *state, bool isnull);
    +
    +/* common workers for json{b}_each* functions */
    +
    +/* semantic action functions for json_each */
    +static void each_object_field_start(void *state, char *fname, bool isnull);
    +static void each_object_field_end(void *state, char *fname, bool isnull);
    +static void each_array_start(void *state);
    +static void each_scalar(void *state, char *token, JsonTokenType tokentype);
    +
    +/* semantic action functions for json_array_elements */
    +static void elements_object_start(void *state);
    +static void elements_array_element_start(void *state, bool isnull);
    +static void elements_array_element_end(void *state, bool isnull);
    +static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
    +
    +/* semantic action functions for json_strip_nulls */
    +static void sn_object_start(void *state);
    +static void sn_object_end(void *state);
    +static void sn_array_start(void *state);
    +static void sn_array_end(void *state);
    +static void sn_object_field_start(void *state, char *fname, bool isnull);
    +static void sn_array_element_start(void *state, bool isnull);
    +static void sn_scalar(void *state, char *token, JsonTokenType tokentype);
    +
    +/* state for json_object_keys */
    +typedef struct OkeysState
    +{
    +    JsonLexContext *lex;
    +    char	  **result;
    +    int			result_size;
    +    int			result_count;
    +    int			sent_count;
    +} OkeysState;
    +
    +/* state for json_get* functions */
    +typedef struct GetState
    +{
    +    JsonLexContext *lex;
    +    char	   *tresult;
    +    char	   *result_start;
    +    bool		normalize_results;
    +    bool		next_scalar;
    +    int			npath;			/* length of each path-related array */
    +    char	  **path_names;		/* field name(s) being sought */
    +    int		   *path_indexes;	/* array index(es) being sought */
    +    bool	   *pathok;			/* is path matched to current depth? */
    +    int		   *array_cur_index;	/* current element index at each path level */
    +} GetState;
    +
    +/* state for json_array_length */
    +typedef struct AlenState
    +{
    +    JsonLexContext *lex;
    +    int			count;
    +} AlenState;
    +
    +
    +/* state for json_array_elements */
    +typedef struct ElementsState
    +{
    +    JsonLexContext *lex;
    +    const char *function_name;
    +    char	   *result_start;
    +    bool		normalize_results;
    +    bool		next_scalar;
    +    char	   *normalized_scalar;
    +} ElementsState;
    +
    +/* state for json_strip_nulls */
    +typedef struct StripnullState
    +{
    +    JsonLexContext *lex;
    +    StringInfo	strval;
    +    bool		skip_next_null;
    +} StripnullState;
    +
    +JsonReturnType
    +json_extract_path(char **result, char *json, short nargs, ...)
    +{
    +    JsonReturnType ret = JSON_OK;
    +    va_list args;
    +    va_start(args, nargs);
    +    ret = get_path_all(true, json, nargs, args, result);
    +    va_end(args);
    +    return ret;
    +}
    +
    +JsonReturnType
    +json_extract_path_text(char **result, char *json, short nargs, ...)
    +{
    +    JsonReturnType ret = JSON_OK;
    +    va_list args;
    +    va_start(args, nargs);
    +    ret = get_path_all(true, json, nargs, args, result);
    +    va_end(args);
    +    return ret;
    +}
    +
    +/*
    + * common routine for extract_path functions
    + */
    +static JsonReturnType
    +get_path_all(bool as_text, char *json, short nargs, va_list args, char **result)
    +{
    +    bool	   *pathnulls;
    +    char	  **tpath;
    +    int		   *ipath;
    +    int			i;
    +    JsonReturnType ret = JSON_OK;
    +
    +    tpath = (char **)malloc(nargs * sizeof(char *));
    +    ipath = (int *)malloc(nargs * sizeof(int));
    +
    +    for (i = 0; i < nargs; i++)
    +    {
    +        tpath[i] = va_arg(args, char *);
    +
    +        /*
    +         * we have no idea at this stage what structure the document is so
    +         * just convert anything in the path that we can to an integer and set
    +         * all the other integers to INT_MIN which will never match.
    +         */
    +        if (*tpath[i] != '\0')
    +        {
    +            long		ind;
    +            char	   *endptr;
    +
    +            errno = 0;
    +            ind = strtol(tpath[i], &endptr, 10);
    +            if (*endptr == '\0' && errno == 0 && ind <= INT_MAX &&
ind >= INT_MIN)
    +                ipath[i] = (int) ind;
    +            else
    +                ipath[i] = INT_MIN;
    +        }
    +        else
    +            ipath[i] = INT_MIN;
    +    }
    +
    +    ret = get_worker(json, tpath, ipath, nargs, as_text, result);
    +
    +    if (tpath != NULL)
    +        free(tpath);
    +    if (ipath != NULL)
    +        free(ipath);
    +    return ret;
    +}
    +
    +JsonReturnType json_object_field_text(char *json, char *fieldName, char **result)
    +{
    +    return get_worker(json, &fieldName, NULL, 1, true, result);
    +}
    +
    +static JsonReturnType
    +get_worker(char *json,
    +           char **tpath,
    +           int *ipath,
    +           int npath,
    +           bool normalize_results,
    +           char **result)
    +{
    +    JsonLexContext *lex = makeJsonLexContext(json, true);
    +    JsonSemAction *sem = (JsonSemAction *)malloc(sizeof(JsonSemAction));
    +    GetState   *state = (GetState *)malloc(sizeof(GetState));
    +    JsonReturnType ret;
    +
    +    memset(sem, 0, sizeof(JsonSemAction));
    +    memset(state, 0, sizeof(GetState));
    +
    +    if(npath < 0)
    +        return JSON_UNEXPECTED_ERROR;
    +
    +    state->lex = lex;
    +    /* is it "_as_text" variant? */
    +    state->normalize_results = normalize_results;
    +    state->npath = npath;
    +    state->path_names = tpath;
    +    state->path_indexes = ipath;
    +    state->pathok = (bool *)malloc(sizeof(bool) * npath);
    +    state->array_cur_index = (int *)malloc(sizeof(int) * npath);
    +
    +    if (npath > 0)
    +        state->pathok[0] = true;
    +
    +    sem->semstate = (void *) state;
    +
    +    /*
    +     * Not all variants need all the semantic routines. Only set the ones that
    +     * are actually needed for maximum efficiency.
    +     */
    +    sem->scalar = get_scalar;
    +    if (npath == 0)
    +    {
    +        sem->object_start = get_object_start;
    +        sem->object_end = get_object_end;
    +        sem->array_start = get_array_start;
    +        sem->array_end = get_array_end;
    +    }
    +    if (tpath != NULL)
    +    {
    +        sem->object_field_start = get_object_field_start;
    +        sem->object_field_end = get_object_field_end;
    +    }
    +    if (ipath != NULL)
    +    {
    +        sem->array_start = get_array_start;
    +        sem->array_element_start = get_array_element_start;
    +        sem->array_element_end = get_array_element_end;
    +    }
    +
    +    ret = pg_parse_json(lex, sem);
    +    if (ret == JSON_OK)
    +        *result = state->tresult;
    +    else
    +        *result = NULL;
    +
    +    if (lex != NULL)
    +    {
    +        if (lex->strval != NULL)
    +        {
    +            if (lex->strval->data != NULL)
    +                free(lex->strval->data);
    +            free(lex->strval);
    +        }
    +        free(lex);
    +    }
    +    if (sem != NULL)
    +        free(sem);
    +    if (state != NULL)
    +        free(state);
    +    return ret;
    +}
    +
    +static JsonReturnType
    +get_object_start(void *state)
    +{
    +    GetState   *_state = (GetState *) state;
    +    int			lex_level = _state->lex->lex_level;
    +
    +    if (lex_level == 0 && _state->npath == 0)
    +    {
    +        /*
    +         * Special case: we should match the entire object.  We only need this
    +         * at outermost level because at nested levels the match will have
    +         * been started by the outer field or array element callback.
    +         */
    +        _state->result_start = _state->lex->token_start;
    +    }
    +    return JSON_OK;
    +}
    +
    +static JsonReturnType
    +get_object_end(void *state)
    +{
    +    GetState   *_state = (GetState *) state;
    +    int			lex_level = _state->lex->lex_level;
    +
    +    if (lex_level == 0 && _state->npath == 0)
    +    {
    +        /* Special case: return the entire object */
    +        char	   *start = _state->result_start;
    +        int			len = _state->lex->prev_token_terminator - start;
    +
    +        //_state->tresult = cstring_to_text_with_len(start, len);
    +        _state->tresult = (char *)malloc(len + 1);
    --- End diff --
    
    not clear where this malloc memory will be free?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

Mime
View raw message