Skip to content

Commit b2c548b

Browse files
sqlite: implement Database#location()
1 parent f665396 commit b2c548b

File tree

3 files changed

+59
-12
lines changed

3 files changed

+59
-12
lines changed

src/node_sqlite.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4582,13 +4582,34 @@ class IsInTransactionOperation : private OperationBase {
45824582
}
45834583
};
45844584

4585+
class LocationOperation : private OperationBase {
4586+
public:
4587+
LocationOperation(Global<Promise::Resolver>&& resolver,
4588+
std::pmr::string&& db_name)
4589+
: OperationBase(std::move(resolver)), db_name_(std::move(db_name)) {}
4590+
4591+
OperationResult operator()(sqlite3* connection) {
4592+
const char* location = sqlite3_db_filename(connection, db_name_.c_str());
4593+
transfer::literal location_literal{transfer::null{}};
4594+
if (location && location[0] != '\0') {
4595+
location_literal = transfer::text{location, std::strlen(location)};
4596+
}
4597+
return OperationResult::ResolveValue(
4598+
this, transfer::value{std::move(location_literal)});
4599+
}
4600+
4601+
private:
4602+
std::pmr::string db_name_;
4603+
};
4604+
45854605
using Operation = std::variant<ExecOperation,
45864606
StatementGetOperation,
45874607
StatementAllOperation,
45884608
StatementRunOperation,
45894609
PrepareStatementOperation,
45904610
FinalizeStatementOperation,
45914611
IsInTransactionOperation,
4612+
LocationOperation,
45924613
CloseOperation>;
45934614

45944615
template <typename T, typename V>
@@ -4891,6 +4912,7 @@ v8::Local<v8::FunctionTemplate> CreateDatabaseConstructorTemplate(
48914912
SetProtoMethod(isolate, tmpl, "prepare", Database::Prepare);
48924913
SetProtoMethod(isolate, tmpl, "exec", Database::Exec);
48934914
SetProtoMethod(isolate, tmpl, "isInTransaction", Database::IsInTransaction);
4915+
SetProtoMethod(isolate, tmpl, "location", Database::Location);
48944916

48954917
Local<String> sqlite_type_key = FIXED_ONE_BYTE_STRING(isolate, "sqlite-type");
48964918
Local<v8::Symbol> sqlite_type_symbol =
@@ -5106,6 +5128,29 @@ Statement::Statement(Environment* env,
51065128
}
51075129
}
51085130

5131+
void Database::Location(const v8::FunctionCallbackInfo<v8::Value>& args) {
5132+
Database* db;
5133+
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
5134+
Environment* env = Environment::GetCurrent(args);
5135+
REJECT_AND_RETURN_ON_INVALID_STATE(
5136+
env, args, !db->IsOpen(), "database is not open");
5137+
5138+
std::pmr::string db_name;
5139+
if (args.Length() > 0) {
5140+
REJECT_AND_RETURN_ON_INVALID_ARG_TYPE(
5141+
env,
5142+
args,
5143+
!args[0]->IsString(),
5144+
"The \"dbName\" argument must be a string.");
5145+
Utf8Value db_name_utf8(env->isolate(), args[0].As<String>());
5146+
db_name = std::pmr::string(*db_name_utf8, db_name_utf8.length());
5147+
} else {
5148+
db_name = "main";
5149+
}
5150+
args.GetReturnValue().Set(
5151+
db->Schedule<LocationOperation>(std::move(db_name)));
5152+
}
5153+
51095154
Statement::~Statement() {
51105155
if (!IsDisposed()) {
51115156
// Our operations keep a BaseObjectPtr to this Statement, so we can be sure

src/node_sqlite.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ class Database final : public DatabaseCommon {
471471
static void Prepare(const v8::FunctionCallbackInfo<v8::Value>& args);
472472
static void Exec(const v8::FunctionCallbackInfo<v8::Value>& args);
473473
static void IsInTransaction(const v8::FunctionCallbackInfo<v8::Value>& args);
474+
static void Location(const v8::FunctionCallbackInfo<v8::Value>& args);
474475
// static void CreateTagStore(const v8::FunctionCallbackInfo<v8::Value>&
475476
// args); static void Location(const v8::FunctionCallbackInfo<v8::Value>&
476477
// args); static void EnableLoadExtension(

test/parallel/test-sqlite-database-async.mjs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -560,40 +560,41 @@ suite('Database.prototype.isInTransaction()', { timeout: 1000 }, () => {
560560
});
561561
});
562562

563-
suite.skip('Database.prototype.location()', { timeout: 1000 }, () => {
564-
test('throws if database is not open', (t) => {
563+
suite('Database.prototype.location()', { timeout: 1000 }, () => {
564+
test('throws if database is not open', async (t) => {
565565
const db = new Database(nextDb(), { open: false });
566566

567-
t.assert.throws(() => {
568-
db.location();
567+
await t.assert.rejects(async () => {
568+
await db.location();
569569
}, {
570570
code: 'ERR_INVALID_STATE',
571571
message: /database is not open/,
572572
});
573573
});
574574

575-
test('throws if provided dbName is not string', (t) => {
575+
test('throws if provided dbName is not string', async (t) => {
576576
const db = new Database(nextDb());
577577
t.after(async () => { await db.close(); });
578578

579-
t.assert.throws(() => {
580-
db.location(null);
579+
await t.assert.rejects(async () => {
580+
await db.location(null);
581581
}, {
582582
code: 'ERR_INVALID_ARG_TYPE',
583583
message: /The "dbName" argument must be a string/,
584584
});
585585
});
586586

587-
test('returns null when connected to in-memory database', (t) => {
587+
test('returns null when connected to in-memory database', async (t) => {
588588
const db = new Database(':memory:');
589-
t.assert.strictEqual(db.location(), null);
589+
t.after(async () => { await db.close(); });
590+
t.assert.strictEqual(await db.location(), null);
590591
});
591592

592-
test('returns db path when connected to a persistent database', (t) => {
593+
test('returns db path when connected to a persistent database', async (t) => {
593594
const dbPath = nextDb();
594595
const db = new Database(dbPath);
595596
t.after(async () => { await db.close(); });
596-
t.assert.strictEqual(db.location(), dbPath);
597+
t.assert.strictEqual(await db.location(), dbPath);
597598
});
598599

599600
test('returns that specific db path when attached', async (t) => {
@@ -608,7 +609,7 @@ suite.skip('Database.prototype.location()', { timeout: 1000 }, () => {
608609
const escapedPath = otherPath.replace("'", "''");
609610
await db.exec(`ATTACH DATABASE '${escapedPath}' AS other`);
610611

611-
t.assert.strictEqual(db.location('other'), otherPath);
612+
t.assert.strictEqual(await db.location('other'), otherPath);
612613
});
613614
});
614615

0 commit comments

Comments
 (0)