Skip to content

Commit

Permalink
Merge pull request duckdb#1982 from hawkfish/hawkfish-jsdate
Browse files Browse the repository at this point in the history
Issue duckdb#1900: Node.js Date support
  • Loading branch information
Mytherin authored Jul 13, 2021
2 parents f11ec54 + ee8a1e9 commit 0c5d616
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/main/prepared_statement_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void PreparedStatementData::Bind(vector<Value> values) {
if (!values[i].TryCastAs(it->second[0]->type())) {
throw BinderException(
"Type mismatch for binding parameter with index %llu, expected type %s but got type %s", i + 1,
values[i].type().ToString().c_str(), it->second[0]->type().ToString().c_str());
it->second[0]->type().ToString().c_str(), values[i].type().ToString().c_str());
}
for (auto &target : it->second) {
*target = values[i];
Expand Down
2 changes: 1 addition & 1 deletion tools/nodejs/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
],
'defines': [
'NAPI_DISABLE_CPP_EXCEPTIONS=1',
"NAPI_VERSION=3"],
"NAPI_VERSION=5"],
"cflags_cc": [
"-frtti",
"-fexceptions"
Expand Down
30 changes: 23 additions & 7 deletions tools/nodejs/src/statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ Statement::~Statement() {

// A Napi InstanceOf for Javascript Objects "Date" and "RegExp"
static bool other_instance_of(Napi::Object source, const char *object_type) {
if (strncmp(object_type, "Date", 4) == 0) {
return source.InstanceOf(source.Env().Global().Get("Date").As<Napi::Function>());
} else if (strncmp(object_type, "RegExp", 6) == 0) {
return source.InstanceOf(source.Env().Global().Get("RegExp").As<Napi::Function>());
if (strcmp(object_type, "Date") == 0) {
return source.InstanceOf(source.Env().Global().Get(object_type).As<Napi::Function>());
} else if (strcmp(object_type, "RegExp") == 0) {
return source.InstanceOf(source.Env().Global().Get(object_type).As<Napi::Function>());
}

return false;
Expand All @@ -105,9 +105,16 @@ static duckdb::Value bind_parameter(const Napi::Value source) {
} else if (source.IsBuffer()) {
Napi::Buffer<char> buffer = source.As<Napi::Buffer<char>>();
return duckdb::Value::BLOB(std::string(buffer.Data(), buffer.Length()));
} else if (other_instance_of(source.As<Napi::Object>(), "Date")) {
// FIXME
// return new Values::Float(pos, source.ToNumber().DoubleValue());
#if (NAPI_VERSION > 4)
} else if (source.IsDate()) {
const auto micros = int64_t(source.As<Napi::Date>().ValueOf()) * duckdb::Interval::MICROS_PER_MSEC;
if (micros % duckdb::Interval::MICROS_PER_DAY) {
return duckdb::Value::TIMESTAMP(duckdb::timestamp_t(micros));
} else {
const auto days = int32_t(micros / duckdb::Interval::MICROS_PER_DAY);
return duckdb::Value::DATE(duckdb::date_t(days));
}
#endif
} else if (source.IsObject()) {
return duckdb::Value(source.ToString().Utf8Value());
}
Expand Down Expand Up @@ -152,6 +159,15 @@ static Napi::Value convert_chunk(Napi::Env &env, std::vector<std::string> names,
case duckdb::LogicalTypeId::HUGEINT: {
value = Napi::Number::New(env, dval.GetValue<double>());
} break;
#if (NAPI_VERSION > 4)
case duckdb::LogicalTypeId::DATE: {
const auto scale = duckdb::Interval::SECS_PER_DAY * duckdb::Interval::MSECS_PER_SEC;
value = Napi::Date::New(env, double(dval.GetValue<int64_t>() * scale));
} break;
case duckdb::LogicalTypeId::TIMESTAMP: {
value = Napi::Date::New(env, double(dval.GetValue<int64_t>() / duckdb::Interval::MICROS_PER_MSEC));
} break;
#endif
case duckdb::LogicalTypeId::VARCHAR: {
value = Napi::String::New(env, dval.str_value);
} break;
Expand Down
14 changes: 10 additions & 4 deletions tools/nodejs/test/serialization.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,30 @@ describe('serialize(fn)', function() {

it('should call the callback', function(done) {
db.serialize(function() {
db.run("CREATE TABLE foo (txt text, num int, flt double, blb blob)");
db.run("CREATE TABLE foo (txt text, num int, flt double, blb blob, d date, ts timestamp)");

var stmt = db.prepare("INSERT INTO foo VALUES(?, ?, ?, ?)");
var stmt = db.prepare("INSERT INTO foo VALUES(?, ?, ?, ?, ?, ?)");
for (var i = 0; i < count; i++) {
stmt.run('String ' + i, i, i * Math.PI, null, function(err) {
var d = new Date(Date.UTC(2018, 0, i));
var ts = new Date(Date.UTC(2021, 6, 10, 0, 0, i));
stmt.run('String ' + i, i, i * Math.PI, null, d, ts, function(err) {
if (err) throw err;
inserted++;
});
}
stmt.finalize();

db.all("SELECT txt, num, flt, blb FROM foo ORDER BY num", function(err, rows) {
db.all("SELECT txt, num, flt, blb, d, ts FROM foo ORDER BY num", function(err, rows) {
if (err) throw err;
for (var i = 0; i < rows.length; i++) {
var d = new Date(Date.UTC(2018, 0, i));
var ts = new Date(Date.UTC(2021, 6, 10, 0, 0, i));
assert.equal(rows[i].txt, 'String ' + i);
assert.equal(rows[i].num, i);
assert.equal(rows[i].flt, i * Math.PI);
assert.equal(rows[i].blb, null);
assert.equal(rows[i].d.toString(), d.toString());
assert.equal(rows[i].ts.toString(), ts.toString());
retrieved++;
}
done();
Expand Down

0 comments on commit 0c5d616

Please sign in to comment.