Skip to content

Commit 120050d

Browse files
geeksilva97aduh95
authored andcommitted
sqlite,src: refactor sqlite value conversion
PR-URL: #57571 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent 06dcb31 commit 120050d

File tree

2 files changed

+61
-85
lines changed

2 files changed

+61
-85
lines changed

src/node_sqlite.cc

Lines changed: 60 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,54 @@ using v8::Value;
6666
} \
6767
} while (0)
6868

69+
#define SQLITE_VALUE_TO_JS(from, isolate, use_big_int_args, result, ...) \
70+
do { \
71+
switch (sqlite3_##from##_type(__VA_ARGS__)) { \
72+
case SQLITE_INTEGER: { \
73+
sqlite3_int64 val = sqlite3_##from##_int64(__VA_ARGS__); \
74+
if ((use_big_int_args)) { \
75+
(result) = BigInt::New((isolate), val); \
76+
} else if (std::abs(val) <= kMaxSafeJsInteger) { \
77+
(result) = Number::New((isolate), val); \
78+
} else { \
79+
THROW_ERR_OUT_OF_RANGE((isolate), \
80+
"Value is too large to be represented as a " \
81+
"JavaScript number: %" PRId64, \
82+
val); \
83+
} \
84+
break; \
85+
} \
86+
case SQLITE_FLOAT: { \
87+
(result) = \
88+
Number::New((isolate), sqlite3_##from##_double(__VA_ARGS__)); \
89+
break; \
90+
} \
91+
case SQLITE_TEXT: { \
92+
const char* v = \
93+
reinterpret_cast<const char*>(sqlite3_##from##_text(__VA_ARGS__)); \
94+
(result) = String::NewFromUtf8((isolate), v).As<Value>(); \
95+
break; \
96+
} \
97+
case SQLITE_NULL: { \
98+
(result) = Null((isolate)); \
99+
break; \
100+
} \
101+
case SQLITE_BLOB: { \
102+
size_t size = \
103+
static_cast<size_t>(sqlite3_##from##_bytes(__VA_ARGS__)); \
104+
auto data = reinterpret_cast<const uint8_t*>( \
105+
sqlite3_##from##_blob(__VA_ARGS__)); \
106+
auto store = ArrayBuffer::NewBackingStore((isolate), size); \
107+
memcpy(store->Data(), data, size); \
108+
auto ab = ArrayBuffer::New((isolate), std::move(store)); \
109+
(result) = Uint8Array::New(ab, 0, size); \
110+
break; \
111+
} \
112+
default: \
113+
UNREACHABLE("Bad SQLite value"); \
114+
} \
115+
} while (0)
116+
69117
inline MaybeLocal<Object> CreateSQLiteError(Isolate* isolate,
70118
const char* message) {
71119
Local<String> js_msg;
@@ -354,51 +402,13 @@ void UserDefinedFunction::xFunc(sqlite3_context* ctx,
354402

355403
for (int i = 0; i < argc; ++i) {
356404
sqlite3_value* value = argv[i];
357-
MaybeLocal<Value> js_val;
358-
359-
switch (sqlite3_value_type(value)) {
360-
case SQLITE_INTEGER: {
361-
sqlite3_int64 val = sqlite3_value_int64(value);
362-
if (self->use_bigint_args_) {
363-
js_val = BigInt::New(isolate, val);
364-
} else if (std::abs(val) <= kMaxSafeJsInteger) {
365-
js_val = Number::New(isolate, val);
366-
} else {
367-
// Ignore the SQLite error because a JavaScript exception is being
368-
// thrown.
369-
self->db_->SetIgnoreNextSQLiteError(true);
370-
sqlite3_result_error(ctx, "", 0);
371-
THROW_ERR_OUT_OF_RANGE(isolate,
372-
"Value is too large to be represented as a "
373-
"JavaScript number: %" PRId64,
374-
val);
375-
return;
376-
}
377-
break;
378-
}
379-
case SQLITE_FLOAT:
380-
js_val = Number::New(isolate, sqlite3_value_double(value));
381-
break;
382-
case SQLITE_TEXT: {
383-
const char* v =
384-
reinterpret_cast<const char*>(sqlite3_value_text(value));
385-
js_val = String::NewFromUtf8(isolate, v).As<Value>();
386-
break;
387-
}
388-
case SQLITE_NULL:
389-
js_val = Null(isolate);
390-
break;
391-
case SQLITE_BLOB: {
392-
size_t size = static_cast<size_t>(sqlite3_value_bytes(value));
393-
auto data = reinterpret_cast<const uint8_t*>(sqlite3_value_blob(value));
394-
auto store = ArrayBuffer::NewBackingStore(isolate, size);
395-
memcpy(store->Data(), data, size);
396-
auto ab = ArrayBuffer::New(isolate, std::move(store));
397-
js_val = Uint8Array::New(ab, 0, size);
398-
break;
399-
}
400-
default:
401-
UNREACHABLE("Bad SQLite value");
405+
MaybeLocal<Value> js_val = MaybeLocal<Value>();
406+
SQLITE_VALUE_TO_JS(value, isolate, self->use_bigint_args_, js_val, value);
407+
if (js_val.IsEmpty()) {
408+
// Ignore the SQLite error because a JavaScript exception is pending.
409+
self->db_->SetIgnoreNextSQLiteError(true);
410+
sqlite3_result_error(ctx, "", 0);
411+
return;
402412
}
403413

404414
Local<Value> local;
@@ -1531,45 +1541,11 @@ bool StatementSync::BindValue(const Local<Value>& value, const int index) {
15311541
}
15321542

15331543
MaybeLocal<Value> StatementSync::ColumnToValue(const int column) {
1534-
switch (sqlite3_column_type(statement_, column)) {
1535-
case SQLITE_INTEGER: {
1536-
sqlite3_int64 value = sqlite3_column_int64(statement_, column);
1537-
if (use_big_ints_) {
1538-
return BigInt::New(env()->isolate(), value);
1539-
} else if (std::abs(value) <= kMaxSafeJsInteger) {
1540-
return Number::New(env()->isolate(), value);
1541-
} else {
1542-
THROW_ERR_OUT_OF_RANGE(env()->isolate(),
1543-
"The value of column %d is too large to be "
1544-
"represented as a JavaScript number: %" PRId64,
1545-
column,
1546-
value);
1547-
return MaybeLocal<Value>();
1548-
}
1549-
}
1550-
case SQLITE_FLOAT:
1551-
return Number::New(env()->isolate(),
1552-
sqlite3_column_double(statement_, column));
1553-
case SQLITE_TEXT: {
1554-
const char* value = reinterpret_cast<const char*>(
1555-
sqlite3_column_text(statement_, column));
1556-
return String::NewFromUtf8(env()->isolate(), value).As<Value>();
1557-
}
1558-
case SQLITE_NULL:
1559-
return Null(env()->isolate());
1560-
case SQLITE_BLOB: {
1561-
size_t size =
1562-
static_cast<size_t>(sqlite3_column_bytes(statement_, column));
1563-
auto data = reinterpret_cast<const uint8_t*>(
1564-
sqlite3_column_blob(statement_, column));
1565-
auto store = ArrayBuffer::NewBackingStore(env()->isolate(), size);
1566-
memcpy(store->Data(), data, size);
1567-
auto ab = ArrayBuffer::New(env()->isolate(), std::move(store));
1568-
return Uint8Array::New(ab, 0, size);
1569-
}
1570-
default:
1571-
UNREACHABLE("Bad SQLite column type");
1572-
}
1544+
Isolate* isolate = env()->isolate();
1545+
MaybeLocal<Value> js_val = MaybeLocal<Value>();
1546+
SQLITE_VALUE_TO_JS(
1547+
column, isolate, use_big_ints_, js_val, statement_, column);
1548+
return js_val;
15731549
}
15741550

15751551
MaybeLocal<Name> StatementSync::ColumnNameToName(const int column) {

test/parallel/test-sqlite-statement-sync.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ suite('StatementSync.prototype.setReadBigInts()', () => {
332332
bad.get();
333333
}, {
334334
code: 'ERR_OUT_OF_RANGE',
335-
message: /^The value of column 0 is too large.*: 9007199254740992$/,
335+
message: /^Value is too large to be represented as a JavaScript number: 9007199254740992$/,
336336
});
337337
const good = db.prepare(`SELECT ${Number.MAX_SAFE_INTEGER} + 1`);
338338
good.setReadBigInts(true);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy