-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
488 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DATABASE_URL=postgres://leetcode:leetcode-password@localhost/leetcode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "lc-0511-game-play-analysis-i" | ||
version = "0.1.0" | ||
edition = "2021" | ||
publish = false | ||
|
||
[dependencies] | ||
diesel = { version = "2.2.0", default-features = false, features = [ "chrono", "postgres", "r2d2" ] } | ||
dotenvy = "0.15.7" | ||
env_logger = "0.11.3" | ||
log = "0.4.21" | ||
r2d2 = "0.8.10" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# For documentation on how to configure this file, | ||
# see https://diesel.rs/guides/configuring-diesel-cli | ||
|
||
[print_schema] | ||
file = "src/schema.rs" | ||
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"] | ||
|
||
[migrations_directory] | ||
dir = "/home/shaohua/dev/rust/TheAlgorithms/src/leetcode/0511.game-play-analysis-i/migrations" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
version: "3.0" | ||
services: | ||
leetcode_db: | ||
image: postgres:15.3 | ||
restart: always | ||
ports: | ||
- 127.0.0.1:5432:5432 | ||
environment: | ||
POSTGRES_PASSWORD: leetcode-password | ||
POSTGRES_USER: leetcode | ||
POSTGRES_DB: leetcode | ||
volumes: | ||
- ./db:/var/lib/postgresql |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
# | ||
|
||
[问题描述](../problems/) |
Empty file.
6 changes: 6 additions & 0 deletions
6
...eetcode/0511.game-play-analysis-i/migrations/00000000000000_diesel_initial_setup/down.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
-- This file was automatically created by Diesel to setup helper functions | ||
-- and other internal bookkeeping. This file is safe to edit, any future | ||
-- changes will be added to existing projects as new migrations. | ||
|
||
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); | ||
DROP FUNCTION IF EXISTS diesel_set_updated_at(); |
36 changes: 36 additions & 0 deletions
36
src/leetcode/0511.game-play-analysis-i/migrations/00000000000000_diesel_initial_setup/up.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
-- This file was automatically created by Diesel to setup helper functions | ||
-- and other internal bookkeeping. This file is safe to edit, any future | ||
-- changes will be added to existing projects as new migrations. | ||
|
||
|
||
|
||
|
||
-- Sets up a trigger for the given table to automatically set a column called | ||
-- `updated_at` whenever the row is modified (unless `updated_at` was included | ||
-- in the modified columns) | ||
-- | ||
-- # Example | ||
-- | ||
-- ```sql | ||
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); | ||
-- | ||
-- SELECT diesel_manage_updated_at('users'); | ||
-- ``` | ||
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ | ||
BEGIN | ||
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s | ||
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); | ||
END; | ||
$$ LANGUAGE plpgsql; | ||
|
||
CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ | ||
BEGIN | ||
IF ( | ||
NEW IS DISTINCT FROM OLD AND | ||
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at | ||
) THEN | ||
NEW.updated_at := current_timestamp; | ||
END IF; | ||
RETURN NEW; | ||
END; | ||
$$ LANGUAGE plpgsql; |
2 changes: 2 additions & 0 deletions
2
src/leetcode/0511.game-play-analysis-i/migrations/2024-06-01-053932_activity/down.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
-- This file should undo anything in `up.sql` | ||
DROP TABLE activity; |
16 changes: 16 additions & 0 deletions
16
src/leetcode/0511.game-play-analysis-i/migrations/2024-06-01-053932_activity/up.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
-- Your SQL goes here | ||
|
||
CREATE TABLE IF NOT EXISTS activity | ||
( | ||
player_id INTEGER NOT NULL, | ||
device_id INTEGER NOT NULL, | ||
event_date DATE NOT NULL DEFAULT CURRENT_DATE, | ||
games_played INTEGER NOT NULL, | ||
PRIMARY KEY (player_id, event_date) | ||
); | ||
|
||
INSERT INTO activity (player_id, device_id, event_date, games_played) VALUES ('1', '2', '2016-03-01', '5'); | ||
INSERT INTO activity (player_id, device_id, event_date, games_played) VALUES ('1', '2', '2016-05-02', '6'); | ||
INSERT INTO activity (player_id, device_id, event_date, games_played) VALUES ('2', '3', '2017-06-25', '1'); | ||
INSERT INTO activity (player_id, device_id, event_date, games_played) VALUES ('3', '1', '2016-03-02', '0'); | ||
INSERT INTO activity (player_id, device_id, event_date, games_played) VALUES ('3', '4', '2018-07-03', '5'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* | ||
* Copyright (c) 2024 Xu Shaohua <[email protected]>. All rights reserved. | ||
* Use of this source is governed by General Public License that can be found | ||
* in the LICENSE file. | ||
*/ | ||
|
||
SELECT player_id, MIN(event_date) AS first_login | ||
FROM activity | ||
GROUP BY player_id; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright (c) 2024 Xu Shaohua <[email protected]>. All rights reserved. | ||
// Use of this source is governed by General Public License that can be found | ||
// in the LICENSE file. | ||
|
||
use diesel::pg::PgConnection; | ||
use diesel::r2d2::{ConnectionManager, Pool}; | ||
|
||
use crate::error::{Error, ErrorKind}; | ||
|
||
pub type DbPool = Pool<ConnectionManager<PgConnection>>; | ||
|
||
/// Create postgres database connection pool. | ||
/// | ||
/// # Errors | ||
/// | ||
/// Returns error if: | ||
/// - No `DATABASE_URL` is set in current environment. | ||
/// - Failed to connect to database. | ||
pub fn get_connection_pool() -> Result<DbPool, Error> { | ||
let url = std::env::var("DATABASE_URL").map_err(|err| { | ||
Error::from_string( | ||
ErrorKind::ConfigError, | ||
format!("DATABASE_URL is not set in environment, err: {err:?}"), | ||
) | ||
})?; | ||
let manager = ConnectionManager::<PgConnection>::new(&url); | ||
|
||
Pool::builder() | ||
.test_on_check_out(true) | ||
.build(manager) | ||
.map_err(|err| { | ||
Error::from_string( | ||
ErrorKind::DbConnError, | ||
format!("Failed to create connection pool, url: {url}, err: {err:?}"), | ||
) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// Copyright (c) 2022 Xu Shaohua <[email protected]>. All rights reserved. | ||
// Use of this source is governed by GNU General Public License | ||
// that can be found in the LICENSE file. | ||
|
||
#![allow(clippy::enum_variant_names)] | ||
|
||
use diesel::result::DatabaseErrorKind; | ||
use std::fmt::{Display, Formatter}; | ||
use std::io; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
pub enum ErrorKind { | ||
ConfigError, | ||
|
||
DbConnError, | ||
DbGeneralError, | ||
DbUniqueViolationError, | ||
DbForeignKeyViolationError, | ||
DbNotFoundError, | ||
|
||
IoError, | ||
} | ||
|
||
unsafe impl Send for ErrorKind {} | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct Error { | ||
kind: ErrorKind, | ||
message: String, | ||
} | ||
|
||
impl Display for Error { | ||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{:?}: {}", self.kind, self.message) | ||
} | ||
} | ||
|
||
impl std::error::Error for Error {} | ||
|
||
#[allow(dead_code)] | ||
impl Error { | ||
#[must_use] | ||
pub fn new(kind: ErrorKind, message: &str) -> Self { | ||
Self { | ||
kind, | ||
message: message.to_owned(), | ||
} | ||
} | ||
|
||
#[must_use] | ||
pub const fn from_string(kind: ErrorKind, message: String) -> Self { | ||
Self { kind, message } | ||
} | ||
|
||
#[must_use] | ||
pub const fn kind(&self) -> ErrorKind { | ||
self.kind | ||
} | ||
|
||
#[must_use] | ||
pub fn message(&self) -> &str { | ||
&self.message | ||
} | ||
} | ||
|
||
impl From<io::Error> for Error { | ||
fn from(err: io::Error) -> Self { | ||
Self::from_string(ErrorKind::IoError, err.to_string()) | ||
} | ||
} | ||
|
||
impl From<r2d2::Error> for Error { | ||
fn from(err: r2d2::Error) -> Self { | ||
Self::from_string(ErrorKind::DbConnError, format!("r2d2 err: {err}")) | ||
} | ||
} | ||
|
||
impl From<diesel::result::Error> for Error { | ||
fn from(err: diesel::result::Error) -> Self { | ||
match &err { | ||
diesel::result::Error::DatabaseError(kind, _info) => match kind { | ||
DatabaseErrorKind::UniqueViolation => { | ||
Self::from_string(ErrorKind::DbUniqueViolationError, err.to_string()) | ||
} | ||
DatabaseErrorKind::ForeignKeyViolation => { | ||
Self::from_string(ErrorKind::DbForeignKeyViolationError, err.to_string()) | ||
} | ||
_ => Self::from_string(ErrorKind::DbGeneralError, err.to_string()), | ||
}, | ||
diesel::result::Error::NotFound => { | ||
Self::from_string(ErrorKind::DbNotFoundError, err.to_string()) | ||
} | ||
_ => Self::from_string(ErrorKind::DbGeneralError, err.to_string()), | ||
} | ||
} | ||
} | ||
|
||
impl From<std::num::ParseIntError> for Error { | ||
fn from(err: std::num::ParseIntError) -> Self { | ||
Self::from_string(ErrorKind::ConfigError, err.to_string()) | ||
} | ||
} | ||
|
||
impl From<std::ffi::OsString> for Error { | ||
fn from(err: std::ffi::OsString) -> Self { | ||
Self::from_string( | ||
ErrorKind::ConfigError, | ||
format!("OsString to String err: {err:?}"), | ||
) | ||
} | ||
} | ||
|
||
impl From<dotenvy::Error> for Error { | ||
fn from(err: dotenvy::Error) -> Self { | ||
Self::from_string(ErrorKind::ConfigError, format!("dotenv err: {err:?}")) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Copyright (c) 2024 Xu Shaohua <[email protected]>. All rights reserved. | ||
// Use of this source is governed by General Public License that can be found | ||
// in the LICENSE file. | ||
|
||
use diesel::connection::SimpleConnection; | ||
use std::env; | ||
use std::fs; | ||
|
||
mod db; | ||
mod error; | ||
|
||
use error::Error; | ||
|
||
fn main() -> Result<(), Error> { | ||
dotenvy::dotenv()?; | ||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); | ||
|
||
let pool = db::get_connection_pool()?; | ||
let mut conn = pool.get()?; | ||
for arg in env::args().skip(1) { | ||
let sql_content: String = fs::read_to_string(arg)?; | ||
conn.batch_execute(&sql_content)?; | ||
} | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// @generated automatically by Diesel CLI. | ||
|
||
diesel::table! { | ||
activity (player_id, event_date) { | ||
player_id -> Int4, | ||
device_id -> Int4, | ||
event_date -> Date, | ||
games_played -> Int4, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright (c) 2024 Xu Shaohua <[email protected]>. All rights reserved. | ||
// Use of this source is governed by General Public License that can be found | ||
// in the LICENSE file. | ||
|
||
use diesel::pg::PgConnection; | ||
use diesel::r2d2::{ConnectionManager, Pool}; | ||
|
||
use crate::error::{Error, ErrorKind}; | ||
|
||
pub type DbPool = Pool<ConnectionManager<PgConnection>>; | ||
|
||
/// Create postgres database connection pool. | ||
/// | ||
/// # Errors | ||
/// | ||
/// Returns error if: | ||
/// - No `DATABASE_URL` is set in current environment. | ||
/// - Failed to connect to database. | ||
pub fn get_connection_pool() -> Result<DbPool, Error> { | ||
let url = std::env::var("DATABASE_URL").map_err(|err| { | ||
Error::from_string( | ||
ErrorKind::ConfigError, | ||
format!("DATABASE_URL is not set in environment, err: {err:?}"), | ||
) | ||
})?; | ||
let manager = ConnectionManager::<PgConnection>::new(&url); | ||
|
||
Pool::builder() | ||
.test_on_check_out(true) | ||
.build(manager) | ||
.map_err(|err| { | ||
Error::from_string( | ||
ErrorKind::DbConnError, | ||
format!("Failed to create connection pool, url: {url}, err: {err:?}"), | ||
) | ||
}) | ||
} |
Oops, something went wrong.