Skip to content

Commit 4299a25

Browse files
committed
sqlite,src: refactor sqlite value conversion
1 parent 1de917b commit 4299a25

File tree

1 file changed

+82
-83
lines changed

1 file changed

+82
-83
lines changed

src/node_sqlite.cc

Lines changed: 82 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,63 @@ using v8::Value;
6767
} \
6868
} while (0)
6969

70+
#define SQLITE_VALUE_TO_JS( \
71+
from, unreachable_message, isolate, use_big_int_args, ...) \
72+
switch (sqlite3_##from##_type(__VA_ARGS__)) { \
73+
case SQLITE_INTEGER: { \
74+
sqlite3_int64 val = sqlite3_##from##_int64(__VA_ARGS__); \
75+
if (use_big_int_args) { \
76+
return BigInt::New(isolate, val); \
77+
} else if (std::abs(val) <= kMaxSafeJsInteger) { \
78+
return Number::New(isolate, val); \
79+
} else { \
80+
return MaybeLocal<Value>(); \
81+
} \
82+
break; \
83+
} \
84+
case SQLITE_FLOAT: { \
85+
return Number::New(isolate, sqlite3_##from##_double(__VA_ARGS__)); \
86+
break; \
87+
} \
88+
case SQLITE_TEXT: { \
89+
const char* v = \
90+
reinterpret_cast<const char*>(sqlite3_##from##_text(__VA_ARGS__)); \
91+
return String::NewFromUtf8(isolate, v).As<Value>(); \
92+
} \
93+
case SQLITE_NULL: \
94+
return Null(isolate); \
95+
case SQLITE_BLOB: { \
96+
size_t size = static_cast<size_t>(sqlite3_##from##_bytes(__VA_ARGS__)); \
97+
auto data = reinterpret_cast<const uint8_t*>( \
98+
sqlite3_##from##_blob(__VA_ARGS__)); \
99+
auto store = ArrayBuffer::NewBackingStore(isolate, size); \
100+
memcpy(store->Data(), data, size); \
101+
auto ab = ArrayBuffer::New(isolate, std::move(store)); \
102+
return Uint8Array::New(ab, 0, size); \
103+
} \
104+
default: \
105+
UNREACHABLE(unreachable_message); \
106+
}
107+
108+
MaybeLocal<Value> SQLiteValueToJS(Isolate* isolate,
109+
bool use_big_int_args,
110+
sqlite3_value* sqlite_value) {
111+
SQLITE_VALUE_TO_JS(
112+
value, "Bad SQLite value", isolate, use_big_int_args, sqlite_value);
113+
}
114+
115+
MaybeLocal<Value> SQLiteValueToJS(Isolate* isolate,
116+
bool use_big_int_args,
117+
sqlite3_stmt* stmt,
118+
int column) {
119+
SQLITE_VALUE_TO_JS(column,
120+
"Bad SQLite column type",
121+
isolate,
122+
use_big_int_args,
123+
stmt,
124+
column);
125+
}
126+
70127
inline MaybeLocal<Object> CreateSQLiteError(Isolate* isolate,
71128
const char* message) {
72129
Local<String> js_msg;
@@ -356,51 +413,18 @@ void UserDefinedFunction::xFunc(sqlite3_context* ctx,
356413

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

406430
Local<Value> local;
@@ -1511,45 +1535,20 @@ bool StatementSync::BindValue(const Local<Value>& value, const int index) {
15111535
}
15121536

15131537
MaybeLocal<Value> StatementSync::ColumnToValue(const int column) {
1514-
switch (sqlite3_column_type(statement_, column)) {
1515-
case SQLITE_INTEGER: {
1516-
sqlite3_int64 value = sqlite3_column_int64(statement_, column);
1517-
if (use_big_ints_) {
1518-
return BigInt::New(env()->isolate(), value);
1519-
} else if (std::abs(value) <= kMaxSafeJsInteger) {
1520-
return Number::New(env()->isolate(), value);
1521-
} else {
1522-
THROW_ERR_OUT_OF_RANGE(env()->isolate(),
1523-
"The value of column %d is too large to be "
1524-
"represented as a JavaScript number: %" PRId64,
1525-
column,
1526-
value);
1527-
return MaybeLocal<Value>();
1528-
}
1529-
}
1530-
case SQLITE_FLOAT:
1531-
return Number::New(env()->isolate(),
1532-
sqlite3_column_double(statement_, column));
1533-
case SQLITE_TEXT: {
1534-
const char* value = reinterpret_cast<const char*>(
1535-
sqlite3_column_text(statement_, column));
1536-
return String::NewFromUtf8(env()->isolate(), value).As<Value>();
1537-
}
1538-
case SQLITE_NULL:
1539-
return Null(env()->isolate());
1540-
case SQLITE_BLOB: {
1541-
size_t size =
1542-
static_cast<size_t>(sqlite3_column_bytes(statement_, column));
1543-
auto data = reinterpret_cast<const uint8_t*>(
1544-
sqlite3_column_blob(statement_, column));
1545-
auto store = ArrayBuffer::NewBackingStore(env()->isolate(), size);
1546-
memcpy(store->Data(), data, size);
1547-
auto ab = ArrayBuffer::New(env()->isolate(), std::move(store));
1548-
return Uint8Array::New(ab, 0, size);
1549-
}
1550-
default:
1551-
UNREACHABLE("Bad SQLite column type");
1538+
Isolate* isolate = env()->isolate();
1539+
MaybeLocal<Value> js_val =
1540+
SQLiteValueToJS(isolate, use_big_ints_, statement_, column);
1541+
1542+
if (js_val.IsEmpty()) {
1543+
THROW_ERR_OUT_OF_RANGE(isolate,
1544+
"The value of column %d is too large to be "
1545+
"represented as a JavaScript number: %" PRId64,
1546+
column,
1547+
sqlite3_column_int64(statement_, column));
1548+
return MaybeLocal<Value>();
15521549
}
1550+
1551+
return js_val;
15531552
}
15541553

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

0 commit comments

Comments
 (0)