Skip to content

Deparse #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/pg-parser/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
BasedOnStyle: Google
IndentWidth: 2
ColumnLimit: 0
AllowShortIfStatementsOnASingleLine: false
49 changes: 40 additions & 9 deletions packages/pg-parser/Makefile
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
AUTOCONF = autoconf
AUTOMAKE = automake
ACLOCAL = aclocal
AUTORECONF = autoreconf
AUTORECONF_FLAGS = -fiv

PROTOBUF_TYPE_GENERATOR = tsx scripts/generate-types.ts

SRC_DIR = bindings
OUTPUT_DIR = wasm/$(LIBPG_QUERY_VERSION)
OUTPUT_JS = $(OUTPUT_DIR)/pg-parser.js
OUTPUT_WASM = $(OUTPUT_DIR)/pg-parser.wasm
OUTPUT_D_TS = pg-parser.d.ts
OUTPUT_FILES = $(OUTPUT_JS) $(OUTPUT_WASM) $(OUTPUT_D_TS)
WASM_MODULE_NAME := PgParserModule

include $(SRC_DIR)/Filelists.mk
OBJ_FILES = $(SRC_FILES:.c=.o)
INCLUDE = $(SRC_DIR)/include

CFLAGS = -Oz -Wall -std=c11
LDFLAGS = -Wl,--gc-sections,--strip-all \
LDFLAGS = -Wl,--gc-sections,--strip-all

EMSCRIPTEN_FLAGS = \
--no-entry \
-sFILESYSTEM=0 \
-sFILESYSTEM=1 \
-sALLOW_MEMORY_GROWTH=1 \
-sEXPORT_NAME="$(WASM_MODULE_NAME)" \
-sEXPORTED_RUNTIME_METHODS=ccall,cwrap,getValue,UTF8ToString \
-sEXPORTED_RUNTIME_METHODS=ccall,cwrap,getValue,UTF8ToString,HEAPU8 \
-sMODULARIZE=1 \
-sEXPORT_ES6=1

Expand All @@ -29,25 +39,46 @@ LIBPG_QUERY_SRC_DIR = $(LIBPG_QUERY_DIR)/src
LIBPG_QUERY_LIB = $(LIBPG_QUERY_DIR)/libpg_query.a
LIBPG_QUERY_STAMP = $(LIBPG_QUERY_DIR)/.stamp
LIBPG_QUERY_VERSION := $(firstword $(subst -, ,$(LIBPG_QUERY_TAG)))
LIBPG_QUERY_PROTOBUF_DIR = $(LIBPG_QUERY_DIR)/protobuf
LIBPG_QUERY_PROTOBUF_C_DIR = $(LIBPG_QUERY_DIR)/vendor/protobuf-c
LIBPG_QUERY_PROTOBUF_C_SRC_FILES = $(wildcard $(LIBPG_QUERY_PROTOBUF_C_DIR)/*.c)
LIBPG_QUERY_PROTOBUF_C_OBJ_FILES = $(LIBPG_QUERY_PROTOBUF_C_SRC_FILES:.c=.o)

JANSSON_REPO = https://github.com/akheron/jansson.git
JANSSON_TAG = v2.14.1
JANSSON_DIR = $(VENDOR_DIR)/jansson/$(JANSSON_TAG)
JANSSON_SRC_DIR = $(JANSSON_DIR)/src
JANSSON_LIB = $(JANSSON_SRC_DIR)/.libs/libjansson.a
JANSSON_STAMP = $(JANSSON_DIR)/.stamp

.DEFAULT_GOAL := build

$(OUTPUT_JS): $(OBJ_FILES) $(LIBPG_QUERY_LIB)
$(OUTPUT_FILES): $(OBJ_FILES) $(LIBPG_QUERY_LIB) $(JANSSON_LIB)
@mkdir -p $(OUTPUT_DIR)
$(CC) $(LDFLAGS) -L$(LIBPG_QUERY_DIR) -lpg_query -o $(OUTPUT_JS) $(OBJ_FILES) --closure 0 --emit-tsd $(OUTPUT_D_TS)
$(CC) $(LDFLAGS) $(EMSCRIPTEN_FLAGS) -o $(OUTPUT_JS) $(OBJ_FILES) $(LIBPG_QUERY_LIB) $(JANSSON_LIB) --closure 0 --emit-tsd $(OUTPUT_D_TS)
$(PROTOBUF_TYPE_GENERATOR) -i $(LIBPG_QUERY_DIR)/protobuf/pg_query.proto -o $(OUTPUT_DIR)

%.o: %.c | $(LIBPG_QUERY_LIB)
$(CC) -I$(LIBPG_QUERY_DIR) -I$(INCLUDE) $(CFLAGS) -c $< -o $@
$(OBJ_FILES): %.o: %.c | $(LIBPG_QUERY_LIB) $(JANSSON_LIB)
$(CC) -I$(LIBPG_QUERY_DIR) -I$(LIBPG_QUERY_DIR)/vendor -I$(JANSSON_SRC_DIR) -I$(INCLUDE) $(CFLAGS) -c $< -o $@

$(LIBPG_QUERY_LIB): $(LIBPG_QUERY_STAMP)
$(MAKE) -C $(LIBPG_QUERY_DIR) build

$(JANSSON_LIB): $(JANSSON_STAMP)
cd $(JANSSON_DIR) && \
$(AUTORECONF) -i && \
emconfigure ./configure --host=wasm32 && \
$(MAKE)

$(LIBPG_QUERY_STAMP):
git clone --depth 1 --branch $(LIBPG_QUERY_TAG) $(LIBPG_QUERY_REPO) $(LIBPG_QUERY_DIR)
git clone -c advice.detachedHead=false --depth 1 --branch $(LIBPG_QUERY_TAG) $(LIBPG_QUERY_REPO) $(LIBPG_QUERY_DIR)
touch $@

$(JANSSON_STAMP):
git clone -c advice.detachedHead=false --depth 1 --branch $(JANSSON_TAG) $(JANSSON_REPO) $(JANSSON_DIR)
touch $@

build: $(OUTPUT_JS)
build: $(OUTPUT_FILES)

clean:
rm -rf $(OUTPUT_DIR)
Expand Down
4 changes: 3 additions & 1 deletion packages/pg-parser/bindings/Filelists.mk
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
SRC_FILES= \
$(SRC_DIR)/parse.c
$(SRC_DIR)/parse.c \
$(SRC_DIR)/protobuf-json.c \
$(SRC_DIR)/protobuf2json/protobuf2json.c
2 changes: 1 addition & 1 deletion packages/pg-parser/bindings/include/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

#define EXPORT(name) __attribute__((export_name(name)))

#endif // MACROS_H
#endif // MACROS_H
100 changes: 100 additions & 0 deletions packages/pg-parser/bindings/include/protobuf2json.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2014-2016 Oleg Efimov <[email protected]>
*
* protobuf2json-c is free software; you can redistribute it
* and/or modify it under the terms of the MIT license.
* See LICENSE for details.
*/

#ifndef PROTOBUF2JSON_H
#define PROTOBUF2JSON_H 1

#include <jansson.h>
#include <protobuf-c/protobuf-c.h>

/* Common errors */
#define PROTOBUF2JSON_ERR_CANNOT_ALLOCATE_MEMORY -001
#define PROTOBUF2JSON_ERR_UNSUPPORTED_FIELD_TYPE -002
#define PROTOBUF2JSON_ERR_UNKNOWN_ENUM_VALUE -003

/* protobuf2json_string */
#define PROTOBUF2JSON_ERR_CANNOT_DUMP_STRING -101
/* protobuf2json_file */
#define PROTOBUF2JSON_ERR_CANNOT_DUMP_FILE -102
/* protobuf2json */
#define PROTOBUF2JSON_ERR_JANSSON_INTERNAL -201

/*json2protobuf_string*/
#define PROTOBUF2JSON_ERR_CANNOT_PARSE_STRING -301
/* json2protobuf_file */
#define PROTOBUF2JSON_ERR_CANNOT_PARSE_FILE -302
/* json2protobuf */
#define PROTOBUF2JSON_ERR_UNKNOWN_FIELD -401
#define PROTOBUF2JSON_ERR_IS_NOT_OBJECT -402
#define PROTOBUF2JSON_ERR_IS_NOT_ARRAY -403
#define PROTOBUF2JSON_ERR_IS_NOT_INTEGER -404
#define PROTOBUF2JSON_ERR_IS_NOT_INTEGER_OR_REAL -405
#define PROTOBUF2JSON_ERR_IS_NOT_BOOLEAN -406
#define PROTOBUF2JSON_ERR_IS_NOT_STRING -407
#define PROTOBUF2JSON_ERR_REQUIRED_IS_MISSING -408
/*#define PROTOBUF2JSON_ERR_DUPLICATE_FIELD -???*/

#ifdef __cplusplus
extern "C" {
#endif

/* === Protobuf -> JSON === */

int protobuf2json_object(
ProtobufCMessage *protobuf_message,
json_t **json_object,
char *error_string,
size_t error_size);

int protobuf2json_string(
ProtobufCMessage *protobuf_message,
size_t json_flags,
char **json_string,
char *error_string,
size_t error_size);

int protobuf2json_file(
ProtobufCMessage *protobuf_message,
size_t json_flags,
char *json_file,
char *fopen_mode,
char *error_string,
size_t error_size);

/* === JSON -> Protobuf === */

int json2protobuf_object(
json_t *json_object,
const ProtobufCMessageDescriptor *protobuf_message_descriptor,
ProtobufCMessage **protobuf_message,
char *error_string,
size_t error_size);

int json2protobuf_string(
char *json_string,
size_t json_flags,
const ProtobufCMessageDescriptor *protobuf_message_descriptor,
ProtobufCMessage **protobuf_message,
char *error_string,
size_t error_size);

int json2protobuf_file(
char *json_file,
size_t json_flags,
const ProtobufCMessageDescriptor *protobuf_message_descriptor,
ProtobufCMessage **protobuf_message,
char *error_string,
size_t error_size);

/* === END === */

#ifdef __cplusplus
}
#endif

#endif /* PROTOBUF2JSON_H */
33 changes: 25 additions & 8 deletions packages/pg-parser/bindings/parse.c
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
#include <stdio.h>
#include <stdlib.h>
#include "pg_query.h"

#include "macros.h"
#include "pg_query.h"

EXPORT("parse_sql")
PgQueryParseResult *parse_sql(char *sql)
{
PgQueryParseResult *result = (PgQueryParseResult *)malloc(sizeof(PgQueryParseResult));
*result = pg_query_parse(sql);
PgQueryProtobufParseResult *parse_sql(char *sql) {
PgQueryProtobufParseResult *result = (PgQueryProtobufParseResult *)malloc(sizeof(PgQueryProtobufParseResult));
*result = pg_query_parse_protobuf(sql);
return result;
}

EXPORT("deparse_sql")
PgQueryDeparseResult *deparse_sql(PgQueryProtobuf *parse_tree) {
PgQueryDeparseResult *result = (PgQueryDeparseResult *)malloc(sizeof(PgQueryDeparseResult));
printf("Deparse parse tree: %p\n", parse_tree);
printf("Deparse parse tree length: %d\n", parse_tree->len);
*result = pg_query_deparse_protobuf(*parse_tree);
printf("Deparse error: %p\n", result->error);
printf("Deparse result: %s\n", result->query);
return result;
}

EXPORT("free_parse_result")
void free_parse_result(PgQueryParseResult *result)
{
pg_query_free_parse_result(*result);
void free_parse_result(PgQueryProtobufParseResult *result) {
pg_query_free_protobuf_parse_result(*result);
free(result);
}

EXPORT("free_deparse_result")
void free_deparse_result(PgQueryDeparseResult *result) {
pg_query_free_deparse_result(*result);
free(result);
}
137 changes: 137 additions & 0 deletions packages/pg-parser/bindings/protobuf-json.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#define _POSIX_C_SOURCE 200809L

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "macros.h"
#include "pg_query.h"
#include "protobuf/pg_query.pb-c.h"
#include "protobuf2json.h"

typedef struct {
char *json_string;
char *error;
} ProtobufToJsonResult;

typedef struct {
PgQueryProtobuf protobuf;
char *error;
} JsonToProtobufResult;

EXPORT("protobuf_to_json")
ProtobufToJsonResult *protobuf_to_json(PgQueryProtobuf *protobuf) {
ProtobufToJsonResult *result = (ProtobufToJsonResult *)malloc(sizeof(ProtobufToJsonResult));

// Unpack the protobuf binary data back into a message
PgQuery__ParseResult *parse_result = pg_query__parse_result__unpack(NULL, protobuf->len, (uint8_t *)protobuf->data);
if (!parse_result) {
result->error = strdup("Failed to unpack protobuf message");
return result;
}
printf("size of protobuf: %zu\n", pg_query__parse_result__get_packed_size(parse_result));

char *error = (char *)malloc(sizeof(char) * 256);

// Convert the protobuf message to a JSON string
int ret = protobuf2json_string(
&parse_result->base,
0,
&result->json_string,
error,
256);

free(parse_result);

if (ret != 0) {
result->error = error;
return result;
}

free(error);
return result;
}

EXPORT("json_to_protobuf")
JsonToProtobufResult *json_to_protobuf(char *json_string) {
JsonToProtobufResult *result = (JsonToProtobufResult *)malloc(sizeof(JsonToProtobufResult));
ProtobufCMessage *protobuf_message = NULL;

char *error = (char *)malloc(sizeof(char) * 256);

printf("json_string: %s\n", json_string);

// Convert the JSON string to a protobuf message
int ret = json2protobuf_string(
json_string,
0,
&pg_query__parse_result__descriptor,
&protobuf_message,
error,
256);

if (ret != 0) {
result->error = error;
return result;
}

free(error);

PgQuery__ParseResult *parse_result = (PgQuery__ParseResult *)protobuf_message;

printf("size of protobuf: %zu\n", pg_query__parse_result__get_packed_size(parse_result));

char *error2 = (char *)malloc(sizeof(char) * 256);
char *json_string_reparsed = NULL;

// Convert the protobuf message to a JSON string
protobuf2json_string(
&parse_result->base,
0,
&json_string_reparsed,
error2,
256);

printf("json_string after reparse: %s\n", json_string_reparsed);

result->protobuf.len = pg_query__parse_result__get_packed_size(parse_result);
result->protobuf.data = malloc(sizeof(char) * result->protobuf.len);
// result->protobuf.len = protobuf_c_message_get_packed_size(protobuf_message);
// result->protobuf.data = malloc(sizeof(char) * result->protobuf.len);

// Pack the protobuf message into binary data
pg_query__parse_result__pack(parse_result, (uint8_t *)result->protobuf.data);
// protobuf_c_message_pack(protobuf_message, (uint8_t *)result->protobuf.data);

printf("pointer of result: %p\n", result);
printf("pointer of result->protobuf: %p\n", &result->protobuf);
printf("result->protobuf.len: %d\n", result->protobuf.len);

// Free the protobuf message since we've packed it
// protobuf_c_message_free_unpacked((ProtobufCMessage *)protobuf_message, NULL);

return result;
}

EXPORT("free_protobuf_to_json_result")
void free_protobuf_to_json_result(ProtobufToJsonResult *result) {
if (result->json_string) {
free(result->json_string);
}
if (result->error) {
free(result->error);
}
free(result);
}

EXPORT("free_json_to_protobuf_result")
void free_json_to_protobuf_result(JsonToProtobufResult *result) {
if (result->protobuf.data) {
free(result->protobuf.data);
}
if (result->error) {
free(result->error);
}
free(result);
}
Loading