Skip to main content
Glama
data.cpp9.64 kB
#define JS_VALUE_TO_SQLITE(to, value, isolate, ...) \ if (value->IsNumber()) { \ return sqlite3_##to##_double( \ __VA_ARGS__, \ value.As<v8::Number>()->Value() \ ); \ } else if (value->IsBigInt()) { \ bool lossless; \ int64_t v = value.As<v8::BigInt>()->Int64Value(&lossless); \ if (lossless) { \ return sqlite3_##to##_int64(__VA_ARGS__, v); \ } \ } else if (value->IsString()) { \ v8::String::Utf8Value utf8(isolate, value.As<v8::String>()); \ return sqlite3_##to##_text( \ __VA_ARGS__, \ *utf8, \ utf8.length(), \ SQLITE_TRANSIENT \ ); \ } else if (node::Buffer::HasInstance(value)) { \ const char* data = node::Buffer::Data(value); \ return sqlite3_##to##_blob( \ __VA_ARGS__, \ data ? data : "", \ node::Buffer::Length(value), \ SQLITE_TRANSIENT \ ); \ } else if (value->IsNull() || value->IsUndefined()) { \ return sqlite3_##to##_null(__VA_ARGS__); \ } #define SQLITE_VALUE_TO_JS(from, isolate, safe_ints, ...) \ switch (sqlite3_##from##_type(__VA_ARGS__)) { \ case SQLITE_INTEGER: \ if (safe_ints) { \ return v8::BigInt::New( \ isolate, \ sqlite3_##from##_int64(__VA_ARGS__) \ ); \ } \ case SQLITE_FLOAT: \ return v8::Number::New( \ isolate, \ sqlite3_##from##_double(__VA_ARGS__) \ ); \ case SQLITE_TEXT: \ return StringFromUtf8( \ isolate, \ reinterpret_cast<const char*>(sqlite3_##from##_text(__VA_ARGS__)), \ sqlite3_##from##_bytes(__VA_ARGS__) \ ); \ case SQLITE_BLOB: \ return node::Buffer::Copy( \ isolate, \ static_cast<const char*>(sqlite3_##from##_blob(__VA_ARGS__)), \ sqlite3_##from##_bytes(__VA_ARGS__) \ ).ToLocalChecked(); \ default: \ assert(sqlite3_##from##_type(__VA_ARGS__) == SQLITE_NULL); \ return v8::Null(isolate); \ } \ assert(false); namespace Data { static const char FLAT = 0; static const char PLUCK = 1; static const char EXPAND = 2; static const char RAW = 3; v8::Local<v8::Value> GetValueJS(v8::Isolate* isolate, sqlite3_stmt* handle, int column, bool safe_ints) { SQLITE_VALUE_TO_JS(column, isolate, safe_ints, handle, column); } v8::Local<v8::Value> GetValueJS(v8::Isolate* isolate, sqlite3_value* value, bool safe_ints) { SQLITE_VALUE_TO_JS(value, isolate, safe_ints, value); } v8::Local<v8::Value> GetExpandedRowJS(v8::Isolate* isolate, v8::Local<v8::Context> ctx, sqlite3_stmt* handle, bool safe_ints) { v8::Local<v8::Object> row = v8::Object::New(isolate); int column_count = sqlite3_column_count(handle); for (int i = 0; i < column_count; ++i) { const char* table_raw = sqlite3_column_table_name(handle, i); v8::Local<v8::String> table = InternalizedFromUtf8(isolate, table_raw == NULL ? "$" : table_raw, -1); v8::Local<v8::String> column = InternalizedFromUtf8(isolate, sqlite3_column_name(handle, i), -1); v8::Local<v8::Value> value = Data::GetValueJS(isolate, handle, i, safe_ints); if (row->HasOwnProperty(ctx, table).FromJust()) { row->Get(ctx, table).ToLocalChecked().As<v8::Object>()->Set(ctx, column, value).FromJust(); } else { v8::Local<v8::Object> nested = v8::Object::New(isolate); row->Set(ctx, table, nested).FromJust(); nested->Set(ctx, column, value).FromJust(); } } return row; } #if !defined(NODE_MODULE_VERSION) || NODE_MODULE_VERSION < 127 v8::Local<v8::Value> GetFlatRowJS(v8::Isolate* isolate, v8::Local<v8::Context> ctx, sqlite3_stmt* handle, bool safe_ints) { v8::Local<v8::Object> row = v8::Object::New(isolate); int column_count = sqlite3_column_count(handle); for (int i = 0; i < column_count; ++i) { row->Set(ctx, InternalizedFromUtf8(isolate, sqlite3_column_name(handle, i), -1), Data::GetValueJS(isolate, handle, i, safe_ints) ).FromJust(); } return row; } v8::Local<v8::Value> GetRawRowJS(v8::Isolate* isolate, v8::Local<v8::Context> ctx, sqlite3_stmt* handle, bool safe_ints) { v8::Local<v8::Array> row = v8::Array::New(isolate); int column_count = sqlite3_column_count(handle); for (int i = 0; i < column_count; ++i) { row->Set(ctx, i, Data::GetValueJS(isolate, handle, i, safe_ints)).FromJust(); } return row; } v8::Local<v8::Value> GetRowJS(v8::Isolate* isolate, v8::Local<v8::Context> ctx, sqlite3_stmt* handle, bool safe_ints, char mode) { if (mode == FLAT) return GetFlatRowJS(isolate, ctx, handle, safe_ints); if (mode == PLUCK) return GetValueJS(isolate, handle, 0, safe_ints); if (mode == EXPAND) return GetExpandedRowJS(isolate, ctx, handle, safe_ints); if (mode == RAW) return GetRawRowJS(isolate, ctx, handle, safe_ints); assert(false); return v8::Local<v8::Value>(); } #else v8::Local<v8::Value> GetFlatRowJS(v8::Isolate* isolate, sqlite3_stmt* handle, bool safe_ints) { int column_count = sqlite3_column_count(handle); v8::LocalVector<v8::Name> keys(isolate); v8::LocalVector<v8::Value> values(isolate); keys.reserve(column_count); values.reserve(column_count); for (int i = 0; i < column_count; ++i) { keys.emplace_back( InternalizedFromUtf8(isolate, sqlite3_column_name(handle, i), -1).As<v8::Name>() ); values.emplace_back( Data::GetValueJS(isolate, handle, i, safe_ints) ); } return v8::Object::New( isolate, GET_PROTOTYPE(v8::Object::New(isolate)), keys.data(), values.data(), column_count ); } v8::Local<v8::Value> GetRawRowJS(v8::Isolate* isolate, sqlite3_stmt* handle, bool safe_ints) { int column_count = sqlite3_column_count(handle); v8::LocalVector<v8::Value> row(isolate); row.reserve(column_count); for (int i = 0; i < column_count; ++i) { row.emplace_back(Data::GetValueJS(isolate, handle, i, safe_ints)); } return v8::Array::New(isolate, row.data(), row.size()); } v8::Local<v8::Value> GetRowJS(v8::Isolate* isolate, v8::Local<v8::Context> ctx, sqlite3_stmt* handle, bool safe_ints, char mode) { if (mode == FLAT) return GetFlatRowJS(isolate, handle, safe_ints); if (mode == PLUCK) return GetValueJS(isolate, handle, 0, safe_ints); if (mode == EXPAND) return GetExpandedRowJS(isolate, ctx, handle, safe_ints); if (mode == RAW) return GetRawRowJS(isolate, handle, safe_ints); assert(false); return v8::Local<v8::Value>(); } #endif void GetArgumentsJS(v8::Isolate* isolate, v8::Local<v8::Value>* out, sqlite3_value** values, int argument_count, bool safe_ints) { assert(argument_count > 0); for (int i = 0; i < argument_count; ++i) { out[i] = Data::GetValueJS(isolate, values[i], safe_ints); } } int BindValueFromJS(v8::Isolate* isolate, sqlite3_stmt* handle, int index, v8::Local<v8::Value> value) { JS_VALUE_TO_SQLITE(bind, value, isolate, handle, index); return value->IsBigInt() ? SQLITE_TOOBIG : -1; } void ResultValueFromJS(v8::Isolate* isolate, sqlite3_context* invocation, v8::Local<v8::Value> value, DataConverter* converter) { JS_VALUE_TO_SQLITE(result, value, isolate, invocation); converter->ThrowDataConversionError(invocation, value->IsBigInt()); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mnehmos/mnehmos.synch.mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server