Skip to content

Commit c66f022

Browse files
committed
Fix session usage
1 parent 44a196f commit c66f022

File tree

5 files changed

+223
-0
lines changed

5 files changed

+223
-0
lines changed

lib/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## libchdb `Query` function binding
2+
3+
```bash
4+
npm install
5+
6+
# install dependencies
7+
./update_libchdb.sh
8+
9+
# build the dynamic library
10+
node-gyp build
11+
```

lib/chdb.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#pragma once
2+
3+
#ifdef __cplusplus
4+
# include <cstddef>
5+
# include <cstdint>
6+
extern "C" {
7+
#else
8+
# include <stddef.h>
9+
# include <stdint.h>
10+
#endif
11+
12+
#define CHDB_EXPORT __attribute__((visibility("default")))
13+
struct CHDB_EXPORT local_result
14+
{
15+
char * buf;
16+
size_t len;
17+
void * _vec; // std::vector<char> *, for freeing
18+
double elapsed;
19+
uint64_t rows_read;
20+
uint64_t bytes_read;
21+
};
22+
23+
CHDB_EXPORT struct local_result * query_stable(int argc, char ** argv);
24+
CHDB_EXPORT void free_result(struct local_result * result);
25+
26+
#ifdef __cplusplus
27+
}
28+
#endif

lib/chdb_node.cpp

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#include "chdb.h"
2+
#include "chdb_node.h"
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <string.h>
6+
#include <iostream>
7+
#include <napi.h>
8+
9+
#define MAX_FORMAT_LENGTH 64
10+
#define MAX_PATH_LENGTH 4096
11+
#define MAX_ARG_COUNT 6
12+
13+
// Utility function to construct argument string
14+
void construct_arg(char *dest, const char *prefix, const char *value,
15+
size_t dest_size) {
16+
snprintf(dest, dest_size, "%s%s", prefix, value);
17+
}
18+
19+
// Generalized query function
20+
char *general_query(int argc, char *args[]) {
21+
struct local_result *result = query_stable(argc, args);
22+
23+
if (result == NULL) {
24+
return NULL;
25+
} else {
26+
return result->buf;
27+
}
28+
}
29+
30+
// Query function without session
31+
char *Query(const char *query, const char *format) {
32+
char dataFormat[MAX_FORMAT_LENGTH];
33+
char *dataQuery;
34+
char *args[MAX_ARG_COUNT] = {"clickhouse", "--multiquery", NULL, NULL};
35+
int argc = 4;
36+
37+
construct_arg(dataFormat, "--output-format=", format, MAX_FORMAT_LENGTH);
38+
args[2] = dataFormat;
39+
40+
dataQuery = (char *)malloc(strlen(query) + strlen("--query=") + 1);
41+
if (dataQuery == NULL) {
42+
return NULL;
43+
}
44+
construct_arg(dataQuery, "--query=", query,
45+
strlen(query) + strlen("--query=") + 1);
46+
args[3] = dataQuery;
47+
48+
char *result = general_query(argc, args);
49+
free(dataQuery);
50+
return result;
51+
}
52+
53+
// QuerySession function will save the session to the path
54+
// queries with same path will use the same session
55+
char *QuerySession(const char *query, const char *format, const char *path) {
56+
char dataFormat[MAX_FORMAT_LENGTH];
57+
char dataPath[MAX_PATH_LENGTH];
58+
char *dataQuery;
59+
char *args[MAX_ARG_COUNT] = {"clickhouse", "--multiquery", NULL, NULL, NULL};
60+
int argc = 5;
61+
62+
construct_arg(dataFormat, "--output-format=", format, MAX_FORMAT_LENGTH);
63+
args[2] = dataFormat;
64+
65+
dataQuery = (char *)malloc(strlen(query) + strlen("--query=") + 1);
66+
if (dataQuery == NULL) {
67+
return NULL;
68+
}
69+
construct_arg(dataQuery, "--query=", query,
70+
strlen(query) + strlen("--query=") + 1);
71+
args[3] = dataQuery;
72+
73+
construct_arg(dataPath, "--path=", path, MAX_PATH_LENGTH);
74+
args[4] = dataPath;
75+
76+
char *result = general_query(argc, args);
77+
free(dataQuery);
78+
return result;
79+
}
80+
81+
Napi::String QueryWrapper(const Napi::CallbackInfo &info) {
82+
Napi::Env env = info.Env();
83+
84+
// Check argument types and count
85+
if (info.Length() < 2 || !info[0].IsString() || !info[1].IsString()) {
86+
Napi::TypeError::New(env, "String expected").ThrowAsJavaScriptException();
87+
return Napi::String::New(env, "");
88+
}
89+
90+
// Get the arguments
91+
std::string query = info[0].As<Napi::String>().Utf8Value();
92+
std::string format = info[1].As<Napi::String>().Utf8Value();
93+
94+
// Call the native function
95+
char *result = Query(query.c_str(), format.c_str());
96+
97+
// Return the result
98+
return Napi::String::New(env, result);
99+
}
100+
101+
Napi::String QuerySessionWrapper(const Napi::CallbackInfo &info) {
102+
Napi::Env env = info.Env();
103+
104+
// Check argument types and count
105+
if (info.Length() < 3 || !info[0].IsString() || !info[1].IsString() ||
106+
!info[2].IsString()) {
107+
Napi::TypeError::New(env, "String expected").ThrowAsJavaScriptException();
108+
return Napi::String::New(env, "");
109+
}
110+
111+
// Get the arguments
112+
std::string query = info[0].As<Napi::String>().Utf8Value();
113+
std::string format = info[1].As<Napi::String>().Utf8Value();
114+
std::string path = info[2].As<Napi::String>().Utf8Value();
115+
116+
// std::cerr << query << std::endl;
117+
// std::cerr << format << std::endl;
118+
// std::cerr << path << std::endl;
119+
// Call the native function
120+
char *result = QuerySession(query.c_str(), format.c_str(), path.c_str());
121+
if (result == NULL) {
122+
// std::cerr << "result is null" << std::endl;
123+
return Napi::String::New(env, "");
124+
}
125+
126+
// Return the result
127+
return Napi::String::New(env, result);
128+
}
129+
130+
Napi::Object Init(Napi::Env env, Napi::Object exports) {
131+
// Export the functions
132+
exports.Set("Query", Napi::Function::New(env, QueryWrapper));
133+
exports.Set("QuerySession", Napi::Function::New(env, QuerySessionWrapper));
134+
return exports;
135+
}
136+
137+
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)

lib/chdb_node.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#pragma once
2+
3+
char *Query(const char *query, const char *format);
4+
char *QuerySession(const char *query, const char *format, const char *path);

lib/update_libchdb.sh

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
#!/bin/bash
3+
4+
# Get the newest release version
5+
LATEST_RELEASE=$(curl --silent "https://api.github.com/repos/chdb-io/chdb/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
6+
7+
# Download the correct version based on the platform
8+
case "$(uname -s)" in
9+
Linux)
10+
if [[ $(uname -m) == "aarch64" ]]; then
11+
PLATFORM="linux-aarch64-libchdb.tar.gz"
12+
else
13+
PLATFORM="linux-x86_64-libchdb.tar.gz"
14+
fi
15+
;;
16+
Darwin)
17+
if [[ $(uname -m) == "arm64" ]]; then
18+
PLATFORM="macos-arm64-libchdb.tar.gz"
19+
else
20+
PLATFORM="macos-x86_64-libchdb.tar.gz"
21+
fi
22+
;;
23+
*)
24+
echo "Unsupported platform"
25+
exit 1
26+
;;
27+
esac
28+
29+
DOWNLOAD_URL="https://github.com/chdb-io/chdb/releases/download/$LATEST_RELEASE/$PLATFORM"
30+
31+
echo "Downloading $PLATFORM from $DOWNLOAD_URL"
32+
33+
# Download the file
34+
curl -L -o libchdb.tar.gz $DOWNLOAD_URL
35+
36+
# Untar the file
37+
tar -xzf libchdb.tar.gz
38+
39+
# Set execute permission for libchdb.so
40+
chmod +x libchdb.so
41+
42+
# Clean up
43+
rm -f libchdb.tar.gz

0 commit comments

Comments
 (0)