Changeset: 382382a88fc3 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/382382a88fc3 Modified Files: sql/backends/monet5/vaults/json/json.c Branch: newjson Log Message:
load json file into json column diffs (truncated from 309 to 300 lines): diff --git a/sql/backends/monet5/vaults/json/json.c b/sql/backends/monet5/vaults/json/json.c --- a/sql/backends/monet5/vaults/json/json.c +++ b/sql/backends/monet5/vaults/json/json.c @@ -87,127 +87,65 @@ read_json_file(JSONFileHandle *jfh) return content; } -typedef struct jobject { - struct jobject *parent; - list *fields; -} jobject; - -static jobject * -new_jobject(allocator *sa, jobject *parent) -{ - jobject *res = SA_NEW(sa, jobject); - res->parent = parent; - res->fields = sa_list(sa); - return res; -} static size_t -json2subtypes(mvc *sql, JSONterm *t, sql_alias **alias_pptr, list *types, list *exps, list *names, jobject **parent_pptr) +append_terms(allocator *sa, JSON *jt, size_t offset, BAT *b, char **error) { - sql_subtype *tpe = NULL; - sql_exp *ne = NULL; - sql_alias *nalias = NULL; - const char *cname = NULL; - size_t offset = 1; - jobject *parent = *parent_pptr; - sql_alias *alias = *alias_pptr; - + 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: - tpe = sql_create_subtype(sql->sa, SA_ZNEW(sql->sa, sql_type), 0, 0); - tpe->type->composite = true; - tpe->multiset = MS_ARRAY; - cname = alias->name; - // append to parent fields - if (parent && parent->fields) { - sql_arg *field = sql_create_arg(sql->sa, cname, tpe, false); // ?inout - list_append(parent->fields, field); + 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; } - ne = exp_column(sql->sa, alias, cname, tpe, CARD_MULTI, 1, 0, 0); - list_append(types, tpe); - list_append(exps , ne); - list_append(names, (char*)cname); - nalias = &ne->alias; - *alias_pptr = nalias; - offset += json2subtypes(sql, t+1, alias_pptr, types, exps, names, parent_pptr); break; case JSON_OBJECT: - tpe = sql_create_subtype(sql->sa, SA_ZNEW(sql->sa, sql_type), 0, 0); - tpe->type->composite = true; - // new object - jobject *jo = new_jobject(sql->sa, parent); - tpe->type->d.fields = jo->fields; - cname = alias->name; - if (parent) { - sql_arg *field = sql_create_arg(sql->sa, cname, tpe, false); // ?inout - list_append(parent->fields, field); - } - ne = exp_column(sql->sa, alias, cname, tpe, CARD_MULTI, 1, 0, 0); - set_basecol(ne); - ne->alias.label = -(sql->nid++); - list_append(exps, ne); - list_append(types, tpe); - list_append(names, (char*)cname); - nalias = &ne->alias; - *alias_pptr = nalias; - *parent_pptr = jo; - offset += json2subtypes(sql, t+1, alias_pptr, types, exps, names, parent_pptr); + 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: - cname = sa_strndup(sql->sa, t->value, t->valuelen); - nalias = a_create(sql->sa, cname); - nalias->parent = alias; - *alias_pptr = nalias; - offset += json2subtypes(sql, t+1, alias_pptr, types, exps, names, parent_pptr); - break; case JSON_STRING: - tpe = sql_bind_localtype("str"); - cname = alias->name; - // append to parent fields - if (parent) { - sql_arg *field = sql_create_arg(sql->sa, cname, tpe, false); // ?inout - list_append(parent->fields, field); - } - ne = exp_column(sql->sa, alias->parent, cname, tpe, CARD_MULTI, 1, 0, 0); - set_basecol(ne); - ne->alias.label = -(sql->nid++); - list_append(exps, ne); - list_append(types, tpe); - list_append(names, (char*)cname); - // adjust one level - *alias_pptr = alias->parent; - offset += json2subtypes(sql, t+1, alias_pptr, types, exps, names, parent_pptr); - break; case JSON_NUMBER: - tpe = sql_bind_localtype("int"); - cname = alias->name; - // append to parent fields - if (parent) { - sql_arg *field = sql_create_arg(sql->sa, cname, tpe, false); // ?inout - list_append(parent->fields, field); - } - ne = exp_column(sql->sa, alias->parent, cname, tpe, CARD_MULTI, 1, 0, 0); - set_basecol(ne); - ne->alias.label = -(sql->nid++); - list_append(exps, ne); - list_append(types, tpe); - list_append(names, (char*)cname); - // adjust one level - *alias_pptr = alias->parent; - offset += json2subtypes(sql, t+1, alias_pptr, types, exps, names, parent_pptr); + // should not happen + assert(0); break; case JSON_VALUE: - // break one level - if (parent) - *parent_pptr = parent->parent; - if (alias) - *alias_pptr = alias->parent; + offset +=1; break; default: - // error ? - offset = 0; + *error = createException(SQL, "json.appent_terms", "unknown json term"); break; } + if (v) { + if (BUNappend(b, v, false) != GDK_SUCCEED) { + *error = createException(SQL, "json.appent_terms", "BUNappend failed!"); + } + } return offset; } @@ -215,40 +153,22 @@ json2subtypes(mvc *sql, JSONterm *t, sql 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); + char *cname = sa_strdup(sql->sa, "json"); + list_append(names, cname); + sql_subtype *tpe = sql_bind_localtype("str"); + list_append(types, tpe); + sql_exp *ne = exp_column(sql->sa, a_create(sql->sa, tname), cname, tpe, CARD_MULTI, 1, 0, 0); + set_basecol(ne); + ne->alias.label = -(sql->nid++); + list_append(res_exps, ne); f->tname = tname; - allocator *sa = sa_create(NULL); - JSONFileHandle *jfh = json_open(filename, sa); - const char* json_str = NULL; - if (jfh) { - json_str = read_json_file(jfh); - json_close(jfh); - } - JSON *jt = JSONparse(json_str); // should take allocator - if (jt && jt->error == NULL) { - list *types = sa_list(sql->sa); - list *names = sa_list(sql->sa); - size_t offset = 0; - sql_alias *alias = a_create(sql->sa, tname); - jobject *jo = NULL; - do { - size_t prev_offset = offset; - offset += json2subtypes(sql, jt->elm + offset, &alias, types, res_exps, names, &jo); - if (offset == prev_offset) { - res = createException(SQL, SQLSTATE(42000), "json" "json2subtypes failure for %s", filename); - break; - } - } while(offset < (size_t)jt->free); - JSONfree(jt); - if (res == MAL_SUCCEED) { - f->res = types; - f->coltypes = types; - f->colnames = names; - } - } else { - res = jt ? jt->error : createException(SQL, SQLSTATE(42000), "json" "Failure parsing %s", filename); - } - sa_destroy(sa); + f->res = types; + f->coltypes = types; + f->colnames = names; return res; } @@ -256,18 +176,23 @@ json_relation(mvc *sql, sql_subfunc *f, static void * json_load(void *BE, sql_subfunc *f, char *filename, sql_exp *topn) { - (void) f; - (void) 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->nrcols = 1; s->q = q; - //s->op4.typeval = *st; - //s = stmt_alias(be, s, i+1, "bla", column_name); + s->nrcols = 1; + s->op4.typeval = *tpe; + // is alias essential here? + s = stmt_alias(be, s, 1, a_create(sa, tname), cname); return s; } @@ -297,13 +222,40 @@ JSONread_json(Client cntxt, MalBlkPtr mb allocator *sa = sa_create(NULL); JSONFileHandle *jfh = json_open(fname, sa); const char* json_str = NULL; + JSON *jt = NULL; + BAT *b = NULL; if (jfh) { json_str = read_json_file(jfh); json_close(jfh); } - JSON *jt = JSONparse(json_str); - // TODO do something - JSONfree(jt); + if (json_str) + jt = JSONparse(json_str); + if (jt) { + if (jt->error == NULL) { + b = COLnew(0, TYPE_str, 0, TRANSIENT); + size_t offset = 0; + char *error = NULL; + // append terms + do { + offset = append_terms(sa, jt, offset, b, &error); + if (error) { + msg = error; + break; + } + } while(offset < (size_t)jt->free); + if (msg == MAL_SUCCEED) { + bat *res = getArgReference_bat(stk, pci, 0); + *res = b->batCacheid; + BBPkeepref(b); + } else + BBPreclaim(b); + } else { + msg = jt->error; + } + JSONfree(jt); + } else { + msg = createException(SQL, "json.read_json", "JSONparse error"); + } sa_destroy(sa); return msg; } _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org