Changeset: ef14cbd647eb for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/ef14cbd647eb Branch: nested Log Message:
merge newjson diffs (truncated from 397 to 300 lines): diff --git a/sql/backends/monet5/CMakeLists.txt b/sql/backends/monet5/CMakeLists.txt --- a/sql/backends/monet5/CMakeLists.txt +++ b/sql/backends/monet5/CMakeLists.txt @@ -187,6 +187,7 @@ target_include_directories(sql target_link_libraries(sql PRIVATE monetdb_config_header + json sqlstorage sqlcommon batstore @@ -226,6 +227,7 @@ install(TARGETS DESTINATION ${CMAKE_INSTALL_LIBDIR}) add_subdirectory(generator) +add_subdirectory(vaults/json) if(WITH_UDF) add_subdirectory(UDF) endif() diff --git a/sql/backends/monet5/vaults/json/CMakeLists.txt b/sql/backends/monet5/vaults/json/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/sql/backends/monet5/vaults/json/CMakeLists.txt @@ -0,0 +1,47 @@ +#[[ +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Copyright 2024, 2025 MonetDB Foundation; +# Copyright August 2008 - 2023 MonetDB B.V.; +# Copyright 1997 - July 2008 CWI. +#]] + +add_library(json OBJECT) +#if(MONETDB_STATIC) +# add_library(json STATIC) +#else() +# add_library(json SHARED) +#endif() + +target_sources(json + PRIVATE + json.c) + +target_include_directories(json + PRIVATE + $<TARGET_PROPERTY:mal,INTERFACE_INCLUDE_DIRECTORIES> + $<TARGET_PROPERTY:malmodules,INTERFACE_INCLUDE_DIRECTORIES> + $<TARGET_PROPERTY:atoms,INTERFACE_INCLUDE_DIRECTORIES> + $<TARGET_PROPERTY:sql,INTERFACE_INCLUDE_DIRECTORIES> + $<TARGET_PROPERTY:sqlcommon,INTERFACE_INCLUDE_DIRECTORIES> + $<TARGET_PROPERTY:sqlserver,INTERFACE_INCLUDE_DIRECTORIES> + $<TARGET_PROPERTY:sqlstorage,INTERFACE_INCLUDE_DIRECTORIES> + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> + $<INSTALL_INTERFACE:${INCLUDEDIR}/monetdb>) + +target_link_libraries(json + PRIVATE + monetdb_config_header + sqlinclude + monetdb5 + bat + stream +) + +set_target_properties(json + PROPERTIES + POSITION_INDEPENDENT_CODE ON) diff --git a/sql/backends/monet5/vaults/json/json.c b/sql/backends/monet5/vaults/json/json.c new file mode 100644 --- /dev/null +++ b/sql/backends/monet5/vaults/json/json.c @@ -0,0 +1,295 @@ +/* + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2024 MonetDB Foundation; + * Copyright August 2008 - 2023 MonetDB B.V.; + * Copyright 1997 - July 2008 CWI. + */ + +#include "monetdb_config.h" +#include "rel_file_loader.h" +#include "rel_exp.h" + +#include "mal_instruction.h" +#include "mal_interpreter.h" +#include "mal_parser.h" +#include "mal_builder.h" +#include "mal_namespace.h" +#include "mal_exception.h" +#include "mal_linker.h" +#include "mal_backend.h" +#include "sql_types.h" +#include "rel_bin.h" +#include "json.h" +#include "mutils.h" + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#include <unistd.h> +// #include <glob.h> // not available on Windows + + +typedef struct JSONFileHandle { + allocator *sa; + char *filename; + int fd; + size_t size; +} JSONFileHandle; + + +static JSONFileHandle * +json_open(const char *fname, allocator *sa) +{ + if (!sa) + return NULL; + int fd = MT_open(fname, O_RDONLY); + if (fd < 0){ + // TODO add relevant trace component + TRC_ERROR(SQL_EXECUTION, "Error opening file %s", fname); + return NULL; + } + struct stat stb; + if (MT_stat(fname, &stb) != 0) { + TRC_ERROR(SQL_EXECUTION, "Error stat file %s", fname); + close(fd); + return NULL; + } + JSONFileHandle *res = sa_alloc(sa, sizeof(JSONFileHandle)); + res->sa = sa; + res->filename = sa_strdup(sa, fname); + res->fd = fd; + res->size = stb.st_size; + return res; +} + +static void +json_close(JSONFileHandle *jfh) +{ + if (jfh && jfh->fd) + close(jfh->fd); +} + + +static char * +read_json_file(JSONFileHandle *jfh) +{ + char *content = NULL; + if (jfh) { + unsigned int length = (unsigned int)jfh->size; + content = sa_zalloc(jfh->sa, length + 1); + if (content) { + ssize_t nbytes = read(jfh->fd, content, length); + if (nbytes < 0) + return NULL; + content[length + 1] = '\0'; + } + } + return content; +} + + +static size_t +append_terms(allocator *sa, JSON *jt, size_t offset, BAT *b, char **error) +{ + JSONterm *t = jt->elm + offset; + char *v = NULL; + JSONterm *prev = offset > 0 ? (jt->elm + (offset - 1)) : NULL; + JSONterm *next = offset < (size_t)jt->free ? jt->elm + (offset + 1): NULL; + switch(t->kind) { + case JSON_ARRAY: + if ( (prev == NULL && next && next->kind > JSON_ARRAY) + || (prev && prev->kind == JSON_ARRAY) ) { + // array of basic types or array of arrays + v = sa_strndup(sa, t->value, t->valuelen); + size_t depth = 0; + do { + offset += 1; + next = offset < (size_t)jt->free ? jt->elm + offset : NULL; + if (next && next->kind <=JSON_ARRAY) + depth ++; + if ((depth > 0 && next && (next->kind == JSON_VALUE || next->kind == 0)) + || (depth > 0 && next == NULL)) + depth --; + } while((next && next->kind != JSON_VALUE) || depth > 0); + } else { + offset += 1; + } + break; + case JSON_OBJECT: + v = sa_strndup(sa, t->value, t->valuelen); + size_t depth = 0; + do { + offset += 1; + next = offset < (size_t)jt->free ? jt->elm + offset : NULL; + if (next && next->kind <=JSON_ARRAY) + depth ++; + if ((depth > 0 && next && (next->kind == JSON_VALUE || next->kind == 0)) + || (depth > 0 && next == NULL)) + depth --; + } while((next && next->kind != JSON_VALUE) || depth > 0); + break; + case JSON_ELEMENT: + case JSON_STRING: + case JSON_NUMBER: + // should not happen + assert(0); + break; + case JSON_VALUE: + offset +=1; + break; + default: + *error = createException(SQL, "json.append_terms", "unknown json term"); + break; + } + if (v) { + if (BUNappend(b, v, false) != GDK_SUCCEED) { + *error = createException(SQL, "json.append_terms", "BUNappend failed!"); + } + } + return offset; +} + + +static str +json_relation(mvc *sql, sql_subfunc *f, char *filename, list *res_exps, char *tname) +{ + (void) filename; + char *res = MAL_SUCCEED; + list *types = sa_list(sql->sa); + list *names = sa_list(sql->sa); + // use file name as columnn name ? + char *cname = sa_strdup(sql->sa, "json"); + list_append(names, cname); + sql_schema *jsons = mvc_bind_schema(sql, "sys"); + if (!jsons) + return NULL; + sql_subtype *st = SA_NEW(sql->sa, sql_subtype); + st->digits = st->scale = 0; + st->multiset = 0; + st->type = schema_bind_type(sql, jsons, "json"); + list_append(types, st); + sql_exp *ne = exp_column(sql->sa, a_create(sql->sa, tname), cname, st, CARD_MULTI, 1, 0, 0); + set_basecol(ne); + ne->alias.label = -(sql->nid++); + list_append(res_exps, ne); + f->tname = tname; + f->res = types; + f->coltypes = types; + f->colnames = names; + return res; +} + + +static void * +json_load(void *BE, sql_subfunc *f, char *filename, sql_exp *topn) +{ + (void) topn; // TODO include topn + backend *be = BE; + allocator *sa = be->mvc->sa; + sql_subtype *tpe = f->res->h->data; + const char *tname = f->tname; + const char *cname = f->colnames->h->data; + + stmt *s = stmt_none(be); + InstrPtr q = newStmt(be->mb, "json", "read_json"); + q = pushStr(be->mb, q, filename); + pushInstruction(be->mb, q); + s->nr = getDestVar(q); + s->q = q; + s->nrcols = 1; + s->op4.typeval = *tpe; + // is alias essential here? + s = stmt_alias(be, s, 1, a_create(sa, tname), cname); + return s; +} + +int TYPE_json; + +static str +JSONprelude(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +{ + (void)cntxt; (void)mb; (void)stk; (void)pci; + TYPE_json = ATOMindex("json"); + + fl_register("json", &json_relation, &json_load); + return MAL_SUCCEED; +} + +static str _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org