Skip to content

Commit

Permalink
gpgk: 出力ファイルが既に存在するとき、破棄して新しいものを作成(上書き保存) (#344)
Browse files Browse the repository at this point in the history
close #339 

- 既存の実装
  - DBファイルがすでに存在する場合、それに接続した
- 変更後
  - DBファイルがすでに存在する場合、まずそれを削除する

他のsink(例えばgeojson)でも、 `File::create` 、つまり存在したら破棄して新しいものを作成している: [create
- Rust By Example
日本語版](https://doc.rust-jp.rs/rust-by-example-ja/std_misc/file/create.html)


DBの中身を全部drop、なども可能ではあるが、ややこしいので、1ファイルで存在するSQLiteであるため、ファイルを削除するという方式をとっている。

~~元のSink実装では、 `output_path` が `sqlite://~`
であることも想定していたが、そのようなユースケースは今のところないこと、そのようなURLの場合はファイル削除がややこしいことなどから、その分岐自体を削除し、他のsinkと同様にoutput_pathはファイルパスであるという想定にしている。~~
→ `"sqlite::memory:"` で使いたいケースがあるので、残す。ただし、ファイルパスの場合のみ、まずファイルを削除する。

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit


- **新機能**
-
データベースを初期化するための`from_path`メソッドが削除され、URLを使用してデータベースを初期化する`from_url`メソッドが導入されました。
- **バグ修正**
-
`GpkgSink`の初期化ロジックが修正され、`output_path`が存在する場合はそのファイルを削除してから`GpkgHandler`インスタンスを作成するように変更されました。

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
sorami authored Feb 27, 2024
1 parent 6ca3d72 commit dc69114
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 13 deletions.
12 changes: 0 additions & 12 deletions nusamai-gpkg/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::table::TableInfo;
use indexmap::IndexMap;
use sqlx::{sqlite::*, ConnectOptions};
use sqlx::{Acquire, Pool, Row};
use std::path::Path;
use thiserror::Error;
use url::Url;

Expand All @@ -12,22 +11,11 @@ pub struct GpkgHandler {

#[derive(Error, Debug)]
pub enum GpkgError {
#[error("Database file already exists: {0}")]
DatabaseExists(String),
#[error("SQLx error: {0}")]
SqlxError(#[from] sqlx::Error),
}

impl GpkgHandler {
/// Create and initialize new GeoPackage database at the specified path
pub async fn from_path(path: &Path) -> Result<Self, GpkgError> {
if path.exists() {
return Err(GpkgError::DatabaseExists(format!("{:?}", path)));
}
let url = Url::parse(&format!("sqlite://{}", path.to_str().unwrap())).unwrap();
Self::from_url(&url).await
}

/// Create and initialize new GeoPackage database at the specified URL
pub async fn from_url(url: &Url) -> Result<Self, GpkgError> {
let conn_opts = SqliteConnectOptions::from_url(url)?
Expand Down
1 change: 0 additions & 1 deletion nusamai/src/sink/geojson/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ impl DataSink for GeoJsonSink {
},
|| {
// Write GeoJSON to a file

let mut file = File::create(&self.output_path)?;
let mut writer = BufWriter::with_capacity(1024 * 1024, &mut file);

Expand Down
7 changes: 7 additions & 0 deletions nusamai/src/sink/gpkg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,17 @@ impl GpkgSink {
schema: &Schema,
) -> Result<()> {
let mut handler = if self.output_path.to_string_lossy().starts_with("sqlite:") {
// note: unlike the case of the file system path, the database is not cleared even if it already exists
// this is mainly expected to be used with `sqlite::memory:` for the testing purpose
GpkgHandler::from_url(&Url::parse(self.output_path.to_str().unwrap()).unwrap())
.await
.unwrap()
} else {
// delete the db file first is already exists
if self.output_path.exists() {
std::fs::remove_file(&self.output_path).unwrap();
};

GpkgHandler::from_url(
&Url::parse(&format!("sqlite://{}", self.output_path.to_str().unwrap())).unwrap(),
)
Expand Down

0 comments on commit dc69114

Please sign in to comment.