Skip to content

Commit 00fbe64

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 7261f49 commit 00fbe64

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)