Repository: duckdb/duckdb
File: tools/nodejs/src/statement.cpp (C++)

Code before:
		auto &connection = statement.connection_ref->connection;
		std::vector<std::unique_ptr<duckdb::SQLStatement>> statements;
		try {
			if (connection == nullptr) {
				throw duckdb::ConnectionException("Connection was never established or has been closed already");
			}
			statements = connection->ExtractStatements(statement.sql);
			if (statements.empty()) {
				throw duckdb::InvalidInputException("No statement to prepare!");
			}
		} catch (const duckdb::Exception &ex) {
			statement.statement = duckdb::make_unique<duckdb::PreparedStatement>(duckdb::PreservedError(ex));
			return;
		} catch (std::exception &ex) {
			statement.statement = duckdb::make_unique<duckdb::PreparedStatement>(duckdb::PreservedError(ex));
			return;
		}

		// if there are multiple statements, we directly execute the statements besides the last one
		// we only return the result of the last statement to the user, unless one of the previous statements fails
		for (idx_t i = 0; i + 1 < statements.size(); i++) {
			auto pending_query = connection->PendingQuery(std::move(statements[i]));
			auto res = pending_query->Execute();

			if (res->HasError()) {
				res->ThrowError();
			}
		}

		statement.statement = connection->Prepare(std::move(statements.back()));
	}

	void Callback() override {
		auto &statement = Get<Statement>();
		auto env = statement.Env();
		Napi::HandleScope scope(env);

		auto cb = callback.Value();
		if (statement.statement->HasError()) {
			cb.MakeCallback(statement.Value(), {Utils::CreateError(env, statement.statement->error.Message())});
			return;
		}
		cb.MakeCallback(statement.Value(), {env.Null(), statement.Value()});
	}
};

Statement::Statement(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Statement>(info) {

	Napi::Env env = info.Env();
	int length = info.Length();


Review comment (bug):
Should we throw an error here? Could you perhaps try triggering this (e.g. `SELECT * FROM non_existent_table; SELECT 42`)

Code after:
			throw duckdb::ConnectionException("Connection was never established or has been closed already");
		}

		// Prepare all statements
		statements = connection->ExtractStatements(statement.sql);
		if (statements.empty()) {
			throw duckdb::InvalidInputException("No statement to prepare!");
		}

		// if there are multiple statements, we directly execute the statements besides the last one
		// we only return the result of the last statement to the user, unless one of the previous statements fails
		for (idx_t i = 0; i + 1 < statements.size(); i++) {
			auto pending_query = connection->PendingQuery(std::move(statements[i]));
			auto res = pending_query->Execute();
			if (res->HasError()) {
				return duckdb::make_unique<duckdb::PreparedStatement>(res->GetErrorObject());
			}
		}

		return connection->Prepare(std::move(statements.back()));
	} catch (const duckdb::Exception &ex) {
		return duckdb::make_unique<duckdb::PreparedStatement>(duckdb::PreservedError(ex));
	} catch (std::exception &ex) {
		return duckdb::make_unique<duckdb::PreparedStatement>(duckdb::PreservedError(ex));
	}
}

struct PrepareTask : public Task {
	PrepareTask(Statement &statement, Napi::Function callback) : Task(statement, callback) {
	}

	void DoWork() override {
		auto &statement = Get<Statement>();
		statement.statement = PrepareManyInternal(statement);
	}

	void Callback() override {
		auto &statement = Get<Statement>();
		auto env = statement.Env();
		Napi::HandleScope scope(env);

		auto cb = callback.Value();
		if (statement.statement->HasError()) {
			cb.MakeCallback(statement.Value(), {Utils::CreateError(env, statement.statement->error.Message())});
			return;
		}
		cb.MakeCallback(statement.Value(), {env.Null(), statement.Value()});
	}
};

Statement::Statement(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Statement>(info) {