@@ -2260,20 +2260,41 @@ bool StatementSync::BindValue(const Local<Value>& value, const int index) {
22602260 // Dates could be supported by converting them to numbers. However, there
22612261 // would not be a good way to read the values back from SQLite with the
22622262 // original type.
2263+ Isolate* isolate = env ()->isolate ();
22632264 int r;
22642265 if (value->IsNumber ()) {
2265- double val = value.As <Number>()->Value ();
2266+ const double val = value.As <Number>()->Value ();
22662267 r = sqlite3_bind_double (statement_, index, val);
22672268 } else if (value->IsString ()) {
2268- Utf8Value val (env ()->isolate (), value.As <String>());
2269- r = sqlite3_bind_text (
2270- statement_, index, *val, val.length (), SQLITE_TRANSIENT);
2269+ Utf8Value val (isolate, value.As <String>());
2270+ if (val.IsAllocated ()) {
2271+ // Avoid an extra SQLite copy for large strings by transferring ownership
2272+ // of the malloc()'d buffer to SQLite.
2273+ char * data = *val;
2274+ const sqlite3_uint64 length =
2275+ static_cast <sqlite3_uint64>(val.length ());
2276+ val.Release ();
2277+ r = sqlite3_bind_text64 (
2278+ statement_, index, data, length, std::free, SQLITE_UTF8);
2279+ } else {
2280+ // Stack-backed buffer: SQLite must make its own copy.
2281+ r = sqlite3_bind_text64 (statement_,
2282+ index,
2283+ *val,
2284+ static_cast <sqlite3_uint64>(val.length ()),
2285+ SQLITE_TRANSIENT,
2286+ SQLITE_UTF8);
2287+ }
22712288 } else if (value->IsNull ()) {
22722289 r = sqlite3_bind_null (statement_, index);
22732290 } else if (value->IsArrayBufferView ()) {
22742291 ArrayBufferViewContents<uint8_t > buf (value);
2275- r = sqlite3_bind_blob (
2276- statement_, index, buf.data (), buf.length (), SQLITE_TRANSIENT);
2292+ r = sqlite3_bind_blob64 (
2293+ statement_,
2294+ index,
2295+ buf.data (),
2296+ static_cast <sqlite3_uint64>(buf.length ()),
2297+ SQLITE_TRANSIENT);
22772298 } else if (value->IsBigInt ()) {
22782299 bool lossless;
22792300 int64_t as_int = value.As <BigInt>()->Int64Value (&lossless);
@@ -2284,13 +2305,13 @@ bool StatementSync::BindValue(const Local<Value>& value, const int index) {
22842305 r = sqlite3_bind_int64 (statement_, index, as_int);
22852306 } else {
22862307 THROW_ERR_INVALID_ARG_TYPE (
2287- env ()-> isolate () ,
2308+ isolate,
22882309 " Provided value cannot be bound to SQLite parameter %d." ,
22892310 index);
22902311 return false ;
22912312 }
22922313
2293- CHECK_ERROR_OR_THROW (env ()-> isolate () , db_.get (), r, SQLITE_OK, false );
2314+ CHECK_ERROR_OR_THROW (isolate, db_.get (), r, SQLITE_OK, false );
22942315 return true ;
22952316}
22962317
0 commit comments