@@ -116,6 +116,65 @@ duckdb_timestamp_struct GetTimestampPartsFromObject(Napi::Object timestamp_parts
116
116
return { date, time };
117
117
}
118
118
119
+ duckdb_hugeint GetHugeIntFromBigInt (Napi::Env env, Napi::BigInt bigint) {
120
+ int sign_bit;
121
+ size_t word_count = 2 ;
122
+ uint64_t words[2 ];
123
+ bigint.ToWords (&sign_bit, &word_count, words);
124
+ if (word_count > 2 ) {
125
+ throw Napi::Error::New (env, " bigint out of hugeint range" );
126
+ }
127
+ uint64_t lower = word_count > 0 ? (sign_bit ? -1 : 1 ) * words[0 ] : 0 ;
128
+ int64_t upper = word_count > 1 ? (sign_bit ? -1 : 1 ) * words[1 ] : (word_count > 0 && sign_bit ? -1 : 0 );
129
+ return { lower, upper };
130
+ }
131
+
132
+ Napi::BigInt MakeBigIntFromHugeInt (Napi::Env env, duckdb_hugeint hugeint) {
133
+ int sign_bit = hugeint.upper < 0 ? 1 : 0 ;
134
+ size_t word_count = hugeint.upper == -1 ? 1 : 2 ;
135
+ uint64_t words[2 ];
136
+ words[0 ] = (sign_bit ? -1 : 1 ) * hugeint.lower ;
137
+ words[1 ] = (sign_bit ? -1 : 1 ) * hugeint.upper ;
138
+ return Napi::BigInt::New (env, sign_bit, word_count, words);
139
+ }
140
+
141
+ duckdb_uhugeint GetUHugeIntFromBigInt (Napi::Env env, Napi::BigInt bigint) {
142
+ int sign_bit;
143
+ size_t word_count = 2 ;
144
+ uint64_t words[2 ];
145
+ bigint.ToWords (&sign_bit, &word_count, words);
146
+ if (word_count > 2 || sign_bit) {
147
+ throw Napi::Error::New (env, " bigint out of uhugeint range" );
148
+ }
149
+ uint64_t lower = word_count > 0 ? words[0 ] : 0 ;
150
+ uint64_t upper = word_count > 1 ? words[1 ] : 0 ;
151
+ return { lower, upper };
152
+ }
153
+
154
+ Napi::BigInt MakeBigIntFromUHugeInt (Napi::Env env, duckdb_uhugeint uhugeint) {
155
+ int sign_bit = 0 ;
156
+ size_t word_count = 2 ;
157
+ uint64_t words[2 ];
158
+ words[0 ] = uhugeint.lower ;
159
+ words[1 ] = uhugeint.upper ;
160
+ return Napi::BigInt::New (env, sign_bit, word_count, words);
161
+ }
162
+
163
+ Napi::Object MakeDecimalObject (Napi::Env env, duckdb_decimal decimal) {
164
+ auto decimal_obj = Napi::Object::New (env);
165
+ decimal_obj.Set (" width" , Napi::Number::New (env, decimal.width ));
166
+ decimal_obj.Set (" scale" , Napi::Number::New (env, decimal.scale ));
167
+ decimal_obj.Set (" value" , MakeBigIntFromHugeInt (env, decimal.value ));
168
+ return decimal_obj;
169
+ }
170
+
171
+ duckdb_decimal GetDecimalFromObject (Napi::Env env, Napi::Object decimal_obj) {
172
+ uint8_t width = decimal_obj.Get (" width" ).As <Napi::Number>().Uint32Value ();
173
+ uint8_t scale = decimal_obj.Get (" scale" ).As <Napi::Number>().Uint32Value ();
174
+ auto value = GetHugeIntFromBigInt (env, decimal_obj.Get (" value" ).As <Napi::BigInt>());
175
+ return { width, scale, value };
176
+ }
177
+
119
178
// Externals
120
179
121
180
template <typename T>
@@ -1230,17 +1289,8 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
1230
1289
// function hugeint_to_double(hugeint: bigint): number
1231
1290
Napi::Value hugeint_to_double (const Napi::CallbackInfo& info) {
1232
1291
auto env = info.Env ();
1233
- auto hugeint_as_bigint = info[0 ].As <Napi::BigInt>();
1234
- int sign_bit;
1235
- size_t word_count = 2 ;
1236
- uint64_t words[2 ];
1237
- hugeint_as_bigint.ToWords (&sign_bit, &word_count, words);
1238
- if (word_count > 2 ) {
1239
- throw Napi::Error::New (env, " bigint out of hugeint range" );
1240
- }
1241
- uint64_t lower = word_count > 0 ? (sign_bit ? -1 : 1 ) * words[0 ] : 0 ;
1242
- int64_t upper = word_count > 1 ? (sign_bit ? -1 : 1 ) * words[1 ] : (word_count > 0 && sign_bit ? -1 : 0 );
1243
- duckdb_hugeint hugeint = { lower, upper };
1292
+ auto bigint = info[0 ].As <Napi::BigInt>();
1293
+ auto hugeint = GetHugeIntFromBigInt (env, bigint);
1244
1294
auto output_double = duckdb_hugeint_to_double (hugeint);
1245
1295
return Napi::Number::New (env, output_double);
1246
1296
}
@@ -1251,29 +1301,15 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
1251
1301
auto env = info.Env ();
1252
1302
auto input_double = info[0 ].As <Napi::Number>().DoubleValue ();
1253
1303
auto hugeint = duckdb_double_to_hugeint (input_double);
1254
- int sign_bit = input_double < 0 ? 1 : 0 ;
1255
- size_t word_count = hugeint.upper == -1 ? 1 : 2 ;
1256
- uint64_t words[2 ];
1257
- words[0 ] = (sign_bit ? -1 : 1 ) * hugeint.lower ;
1258
- words[1 ] = (sign_bit ? -1 : 1 ) * hugeint.upper ;
1259
- return Napi::BigInt::New (env, sign_bit, word_count, words);
1304
+ return MakeBigIntFromHugeInt (env, hugeint);
1260
1305
}
1261
1306
1262
1307
// DUCKDB_API double duckdb_uhugeint_to_double(duckdb_uhugeint val);
1263
1308
// function uhugeint_to_double(uhugeint: bigint): number
1264
1309
Napi::Value uhugeint_to_double (const Napi::CallbackInfo& info) {
1265
1310
auto env = info.Env ();
1266
- auto uhugeint_as_bigint = info[0 ].As <Napi::BigInt>();
1267
- int sign_bit;
1268
- size_t word_count = 2 ;
1269
- uint64_t words[2 ];
1270
- uhugeint_as_bigint.ToWords (&sign_bit, &word_count, words);
1271
- if (word_count > 2 || sign_bit) {
1272
- throw Napi::Error::New (env, " bigint out of uhugeint range" );
1273
- }
1274
- uint64_t lower = word_count > 0 ? words[0 ] : 0 ;
1275
- uint64_t upper = word_count > 1 ? words[1 ] : 0 ;
1276
- duckdb_uhugeint uhugeint = { lower, upper };
1311
+ auto bigint = info[0 ].As <Napi::BigInt>();
1312
+ auto uhugeint = GetUHugeIntFromBigInt (env, bigint);
1277
1313
auto output_double = duckdb_uhugeint_to_double (uhugeint);
1278
1314
return Napi::Number::New (env, output_double);
1279
1315
}
@@ -1284,26 +1320,28 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
1284
1320
auto env = info.Env ();
1285
1321
auto input_double = info[0 ].As <Napi::Number>().DoubleValue ();
1286
1322
auto uhugeint = duckdb_double_to_uhugeint (input_double);
1287
- int sign_bit = 0 ;
1288
- size_t word_count = 2 ;
1289
- uint64_t words[2 ];
1290
- words[0 ] = uhugeint.lower ;
1291
- words[1 ] = uhugeint.upper ;
1292
- return Napi::BigInt::New (env, sign_bit, word_count, words);
1323
+ return MakeBigIntFromUHugeInt (env, uhugeint);
1293
1324
}
1294
1325
1295
1326
// DUCKDB_API duckdb_decimal duckdb_double_to_decimal(double val, uint8_t width, uint8_t scale);
1296
1327
// function double_to_decimal(double: number, width: number, scale: number): Decimal
1297
1328
Napi::Value double_to_decimal (const Napi::CallbackInfo& info) {
1298
1329
auto env = info.Env ();
1299
- throw Napi::Error::New (env, " Not implemented yet" );
1330
+ auto input_double = info[0 ].As <Napi::Number>().DoubleValue ();
1331
+ auto width = info[1 ].As <Napi::Number>().Uint32Value ();
1332
+ auto scale = info[2 ].As <Napi::Number>().Uint32Value ();
1333
+ auto decimal = duckdb_double_to_decimal (input_double, width, scale);
1334
+ return MakeDecimalObject (env, decimal);
1300
1335
}
1301
1336
1302
1337
// DUCKDB_API double duckdb_decimal_to_double(duckdb_decimal val);
1303
1338
// function decimal_to_double(decimal: Decimal): number
1304
1339
Napi::Value decimal_to_double (const Napi::CallbackInfo& info) {
1305
1340
auto env = info.Env ();
1306
- throw Napi::Error::New (env, " Not implemented yet" );
1341
+ auto decimal_obj = info[0 ].As <Napi::Object>();
1342
+ auto decimal = GetDecimalFromObject (env, decimal_obj);
1343
+ auto output_double = duckdb_decimal_to_double (decimal);
1344
+ return Napi::Number::New (env, output_double);
1307
1345
}
1308
1346
1309
1347
// DUCKDB_API duckdb_state duckdb_prepare(duckdb_connection connection, const char *query, duckdb_prepared_statement *out_prepared_statement);
0 commit comments