diff --git a/.gitignore b/.gitignore index a38bca38..056b3728 100755 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ Cargo.lock canyon_tester/ macro_utils.rs .vscode/ -postgres-data/ \ No newline at end of file +postgres-data/ +mysql-data/ \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 341a28dd..c5063ad6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,6 @@ members = [ "canyon_entities", "canyon_migrations", "canyon_macros", - "tests" ] @@ -31,6 +30,9 @@ canyon_macros = { workspace = true, path = "canyon_macros" } # To be marked as opt deps tokio-postgres = { workspace = true, optional = true } tiberius = { workspace = true, optional = true } +mysql_async = { workspace = true, optional = true } +mysql_common = { workspace = true, optional = true } + [workspace.dependencies] canyon_crud = { version = "0.4.2", path = "canyon_crud" } @@ -43,6 +45,8 @@ tokio = { version = "1.27.0", features = ["full"] } tokio-util = { version = "0.7.4", features = ["compat"] } tokio-postgres = { version = "0.7.2", features = ["with-chrono-0_4"] } tiberius = { version = "0.12.1", features = ["tds73", "chrono", "integrated-auth-gssapi"] } +mysql_async = { version = "0.32.2" } +mysql_common = { version = "0.30.6", features = [ "chrono" ]} chrono = { version = "0.4", features = ["serde"] } # Just from TP better? serde = { version = "1.0.138", features = ["derive"] } @@ -54,12 +58,14 @@ lazy_static = "1.4.0" toml = "0.7.3" async-trait = "0.1.68" walkdir = "2.3.3" -regex = "1.5" +regex = "1.9.3" partialdebug = "0.2.0" quote = "1.0.9" proc-macro2 = "1.0.27" + + [workspace.package] version = "0.4.2" edition = "2021" @@ -73,4 +79,5 @@ description = "A Rust ORM and QueryBuilder" [features] postgres = ["tokio-postgres", "canyon_connection/postgres", "canyon_crud/postgres", "canyon_migrations/postgres", "canyon_macros/postgres"] mssql = ["tiberius", "canyon_connection/mssql", "canyon_crud/mssql", "canyon_migrations/mssql", "canyon_macros/mssql"] +mysql = ["mysql_async", "mysql_common", "canyon_connection/mysql", "canyon_crud/mysql", "canyon_migrations/mysql", "canyon_macros/mysql"] migrations = ["canyon_migrations", "canyon_macros/migrations"] diff --git a/bash_aliases.sh b/bash_aliases.sh old mode 100644 new mode 100755 diff --git a/canyon_connection/Cargo.toml b/canyon_connection/Cargo.toml index fd37fd4e..fac88ef5 100644 --- a/canyon_connection/Cargo.toml +++ b/canyon_connection/Cargo.toml @@ -15,6 +15,9 @@ tokio-util = { workspace = true } tokio-postgres = { workspace = true, optional = true } tiberius = { workspace = true, optional = true } +mysql_async = { workspace = true, optional = true } +mysql_common = { workspace = true, optional = true } + futures = { workspace = true } indexmap = { workspace = true } @@ -28,3 +31,6 @@ walkdir = { workspace = true } [features] postgres = ["tokio-postgres"] mssql = ["tiberius", "async-std"] +mysql = ["mysql_async","mysql_common"] + + diff --git a/canyon_connection/src/canyon_database_connector.rs b/canyon_connection/src/canyon_database_connector.rs index 7196e948..438f3548 100644 --- a/canyon_connection/src/canyon_database_connector.rs +++ b/canyon_connection/src/canyon_database_connector.rs @@ -2,12 +2,14 @@ use serde::Deserialize; #[cfg(feature = "mssql")] use async_std::net::TcpStream; +#[cfg(feature = "mysql")] +use mysql_async::Pool; #[cfg(feature = "mssql")] use tiberius::{AuthMethod, Config}; #[cfg(feature = "postgres")] use tokio_postgres::{Client, NoTls}; -use crate::datasources::DatasourceConfig; +use crate::datasources::{Auth, DatasourceConfig}; /// Represents the current supported databases by Canyon #[derive(Deserialize, Debug, Eq, PartialEq, Clone, Copy)] @@ -18,6 +20,19 @@ pub enum DatabaseType { #[serde(alias = "sqlserver", alias = "mssql")] #[cfg(feature = "mssql")] SqlServer, + #[serde(alias = "mysql")] + #[cfg(feature = "mysql")] + MySQL, +} + +impl From<&Auth> for DatabaseType { + fn from(value: &Auth) -> Self { + match value { + crate::datasources::Auth::Postgres(_) => DatabaseType::PostgreSql, + crate::datasources::Auth::SqlServer(_) => DatabaseType::SqlServer, + crate::datasources::Auth::MySQL(_) => DatabaseType::MySQL, + } + } } /// A connection with a `PostgreSQL` database @@ -33,6 +48,12 @@ pub struct SqlServerConnection { pub client: &'static mut tiberius::Client, } +/// A connection with a `Mysql` database +#[cfg(feature = "mysql")] +pub struct MysqlConnection { + pub client: Pool, +} + /// The Canyon database connection handler. When the client's program /// starts, Canyon gets the information about the desired datasources, /// process them and generates a pool of 1 to 1 database connection for @@ -42,6 +63,8 @@ pub enum DatabaseConnection { Postgres(PostgreSqlConnection), #[cfg(feature = "mssql")] SqlServer(SqlServerConnection), + #[cfg(feature = "mysql")] + MySQL(MysqlConnection), } unsafe impl Send for DatabaseConnection {} @@ -64,6 +87,10 @@ impl DatabaseConnection { crate::datasources::Auth::SqlServer(_) => { panic!("Found SqlServer auth configuration for a PostgreSQL datasource") } + #[cfg(feature = "mysql")] + crate::datasources::Auth::MySQL(_) => { + panic!("Found MySql auth configuration for a PostgreSQL datasource") + } }; let (new_client, new_connection) = tokio_postgres::connect( &format!( @@ -109,6 +136,10 @@ impl DatabaseConnection { } crate::datasources::SqlServerAuth::Integrated => AuthMethod::Integrated, }, + #[cfg(feature = "mysql")] + crate::datasources::Auth::MySQL(_) => { + panic!("Found PostgreSQL auth configuration for a SqlServer database") + } }); // on production, it is not a good idea to do this. We should upgrade @@ -136,6 +167,41 @@ impl DatabaseConnection { )), })) } + #[cfg(feature = "mysql")] + DatabaseType::MySQL => { + let (user, password) = match &datasource.auth { + #[cfg(feature = "mssql")] + crate::datasources::Auth::SqlServer(_) => { + panic!("Found SqlServer auth configuration for a PostgreSQL datasource") + } + #[cfg(feature = "postgres")] + crate::datasources::Auth::Postgres(_) => { + panic!("Found MySql auth configuration for a PostgreSQL datasource") + } + #[cfg(feature = "mysql")] + crate::datasources::Auth::MySQL(mysql_auth) => match mysql_auth { + crate::datasources::MySQLAuth::Basic { username, password } => { + (username, password) + } + }, + }; + + //TODO add options to optionals params in url + + let url = format!( + "mysql://{}:{}@{}:{}/{}", + user, + password, + datasource.properties.host, + datasource.properties.port.unwrap_or_default(), + datasource.properties.db_name + ); + let mysql_connection = Pool::from_url(url)?; + + Ok(DatabaseConnection::MySQL(MysqlConnection { + client: { mysql_connection }, + })) + } } } @@ -143,7 +209,7 @@ impl DatabaseConnection { pub fn postgres_connection(&self) -> &PostgreSqlConnection { match self { DatabaseConnection::Postgres(conn) => conn, - #[cfg(all(feature = "postgres", feature = "mssql"))] + #[cfg(all(feature = "postgres", feature = "mssql", feature = "mysql"))] _ => panic!(), } } @@ -152,7 +218,16 @@ impl DatabaseConnection { pub fn sqlserver_connection(&mut self) -> &mut SqlServerConnection { match self { DatabaseConnection::SqlServer(conn) => conn, - #[cfg(all(feature = "postgres", feature = "mssql"))] + #[cfg(all(feature = "postgres", feature = "mssql", feature = "mysql"))] + _ => panic!(), + } + } + + #[cfg(feature = "mysql")] + pub fn mysql_connection(&self) -> &MysqlConnection { + match self { + DatabaseConnection::MySQL(conn) => conn, + #[cfg(all(feature = "postgres", feature = "mssql", feature = "mysql"))] _ => panic!(), } } @@ -166,13 +241,14 @@ mod database_connection_handler { /// Tests the behaviour of the `DatabaseType::from_datasource(...)` #[test] fn check_from_datasource() { - #[cfg(all(feature = "postgres", feature = "mssql"))] + #[cfg(all(feature = "postgres", feature = "mssql", feature = "mysql"))] { const CONFIG_FILE_MOCK_ALT_ALL: &str = r#" [canyon_sql] datasources = [ {name = 'PostgresDS', auth = { postgresql = { basic = { username = "postgres", password = "postgres" } } }, properties.host = 'localhost', properties.db_name = 'triforce', properties.migrations='enabled' }, - {name = 'SqlServerDS', auth = { sqlserver = { basic = { username = "sa", password = "SqlServer-10" } } }, properties.host = '192.168.0.250.1', properties.port = 3340, properties.db_name = 'triforce2', properties.migrations='disabled' } + {name = 'SqlServerDS', auth = { sqlserver = { basic = { username = "sa", password = "SqlServer-10" } } }, properties.host = '192.168.0.250.1', properties.port = 3340, properties.db_name = 'triforce2', properties.migrations='disabled' }, + {name = 'MysqlDS', auth = { mysql = { basic = { username = "root", password = "root" } } }, properties.host = '192.168.0.250.1', properties.port = 3340, properties.db_name = 'triforce2', properties.migrations='disabled' } ] "#; let config: CanyonSqlConfig = toml::from_str(CONFIG_FILE_MOCK_ALT_ALL) @@ -185,6 +261,10 @@ mod database_connection_handler { config.canyon_sql.datasources[1].get_db_type(), DatabaseType::SqlServer ); + assert_eq!( + config.canyon_sql.datasources[2].get_db_type(), + DatabaseType::MySQL + ); } #[cfg(feature = "postgres")] @@ -218,5 +298,22 @@ mod database_connection_handler { DatabaseType::SqlServer ); } + + #[cfg(feature = "mysql")] + { + const CONFIG_FILE_MOCK_ALT_MYSQL: &str = r#" + [canyon_sql] + datasources = [ + {name = 'MysqlDS', auth = { mysql = { basic = { username = "root", password = "root" } } }, properties.host = '192.168.0.250.1', properties.port = 3340, properties.db_name = 'triforce2', properties.migrations='disabled' } + ] + "#; + + let config: CanyonSqlConfig = toml::from_str(CONFIG_FILE_MOCK_ALT_MYSQL) + .expect("A failure happened retrieving the [canyon_sql] section"); + assert_eq!( + config.canyon_sql.datasources[0].get_db_type(), + DatabaseType::MySQL + ); + } } } diff --git a/canyon_connection/src/datasources.rs b/canyon_connection/src/datasources.rs index 9571c343..ccfd3694 100644 --- a/canyon_connection/src/datasources.rs +++ b/canyon_connection/src/datasources.rs @@ -11,7 +11,7 @@ fn load_ds_config_from_array() { [canyon_sql] datasources = [ {name = 'PostgresDS', auth = { postgresql = { basic = { username = "postgres", password = "postgres" } } }, properties.host = 'localhost', properties.db_name = 'triforce', properties.migrations='enabled' }, - ] + ] "#; let config: CanyonSqlConfig = toml::from_str(CONFIG_FILE_MOCK_ALT_PG) .expect("A failure happened retrieving the [canyon_sql] section"); @@ -64,6 +64,33 @@ fn load_ds_config_from_array() { assert_eq!(ds_2.auth, Auth::SqlServer(SqlServerAuth::Integrated)); } + #[cfg(feature = "mysql")] + { + const CONFIG_FILE_MOCK_ALT_MYSQL: &str = r#" + [canyon_sql] + datasources = [ + {name = 'MysqlDS', auth = { mysql = { basic = { username = "root", password = "root" } } }, properties.host = '192.168.0.250.1', properties.port = 3340, properties.db_name = 'triforce2', properties.migrations='disabled' } + ] + "#; + let config: CanyonSqlConfig = toml::from_str(CONFIG_FILE_MOCK_ALT_MYSQL) + .expect("A failure happened retrieving the [canyon_sql] section"); + + let ds_1 = &config.canyon_sql.datasources[0]; + + assert_eq!(ds_1.name, "MysqlDS"); + assert_eq!(ds_1.get_db_type(), DatabaseType::MySQL); + assert_eq!( + ds_1.auth, + Auth::MySQL(MySQLAuth::Basic { + username: "root".to_string(), + password: "root".to_string() + }) + ); + assert_eq!(ds_1.properties.host, "192.168.0.250.1"); + assert_eq!(ds_1.properties.port, Some(3340)); + assert_eq!(ds_1.properties.db_name, "triforce2"); + assert_eq!(ds_1.properties.migrations, Some(Migrations::Disabled)); + } } /// #[derive(Deserialize, Debug, Clone)] @@ -90,18 +117,23 @@ impl DatasourceConfig { Auth::Postgres(_) => DatabaseType::PostgreSql, #[cfg(feature = "mssql")] Auth::SqlServer(_) => DatabaseType::SqlServer, + #[cfg(feature = "mysql")] + Auth::MySQL(_) => DatabaseType::MySQL, } } } #[derive(Deserialize, Debug, Clone, PartialEq)] pub enum Auth { - #[serde(alias = "PostgreSQL", alias = "postgresql", alias = "postgres")] + #[serde(alias = "PostgresSQL", alias = "postgresql", alias = "postgres")] #[cfg(feature = "postgres")] Postgres(PostgresAuth), #[serde(alias = "SqlServer", alias = "sqlserver", alias = "mssql")] #[cfg(feature = "mssql")] SqlServer(SqlServerAuth), + #[serde(alias = "MYSQL", alias = "mysql", alias = "MySQL")] + #[cfg(feature = "mysql")] + MySQL(MySQLAuth), } #[derive(Deserialize, Debug, Clone, PartialEq)] @@ -120,6 +152,13 @@ pub enum SqlServerAuth { Integrated, } +#[derive(Deserialize, Debug, Clone, PartialEq)] +#[cfg(feature = "mysql")] +pub enum MySQLAuth { + #[serde(alias = "Basic", alias = "basic")] + Basic { username: String, password: String }, +} + #[derive(Deserialize, Debug, Clone)] pub struct DatasourceProperties { pub host: String, diff --git a/canyon_connection/src/lib.rs b/canyon_connection/src/lib.rs index fed9f31f..fd5d009e 100644 --- a/canyon_connection/src/lib.rs +++ b/canyon_connection/src/lib.rs @@ -2,6 +2,8 @@ pub extern crate async_std; pub extern crate futures; pub extern crate lazy_static; +#[cfg(feature = "mysql")] +pub extern crate mysql_async; #[cfg(feature = "mssql")] pub extern crate tiberius; pub extern crate tokio; @@ -104,3 +106,19 @@ pub fn get_database_connection<'a>( ) } } + +pub fn get_database_config<'a>( + datasource_name: &str, + datasources_config: &'a [DatasourceConfig], +) -> &'a DatasourceConfig { + if datasource_name.is_empty() { + datasources_config + .get(0) + .unwrap_or_else(|| panic!("Not exist datasource")) + } else { + datasources_config + .iter() + .find(|dc| dc.name == datasource_name) + .unwrap_or_else(|| panic!("Not found datasource expected {datasource_name}")) + } +} diff --git a/canyon_crud/Cargo.toml b/canyon_crud/Cargo.toml index 123a44fe..dfdd3ddb 100644 --- a/canyon_crud/Cargo.toml +++ b/canyon_crud/Cargo.toml @@ -12,11 +12,17 @@ description.workspace = true [dependencies] tokio-postgres = { workspace = true, optional = true } tiberius = { workspace = true, optional = true } +mysql_async = { workspace = true, optional = true } +mysql_common = { workspace = true, optional = true } + chrono = { workspace = true } async-trait = { workspace = true } canyon_connection = { workspace = true } +regex = { workspace = true } + [features] postgres = ["tokio-postgres", "canyon_connection/postgres"] mssql = ["tiberius", "canyon_connection/mssql"] +mysql = ["mysql_async","mysql_common", "canyon_connection/mysql"] diff --git a/canyon_crud/src/bounds.rs b/canyon_crud/src/bounds.rs index d46bf863..27ffb97f 100644 --- a/canyon_crud/src/bounds.rs +++ b/canyon_crud/src/bounds.rs @@ -2,15 +2,16 @@ use crate::{ crud::{CrudOperations, Transaction}, mapper::RowMapper, }; - -#[cfg(feature = "postgres")] -use canyon_connection::tokio_postgres::{self, types::ToSql}; - +#[cfg(feature = "mysql")] +use canyon_connection::mysql_async::{self, prelude::ToValue}; #[cfg(feature = "mssql")] use canyon_connection::tiberius::{self, ColumnData, IntoSql}; +#[cfg(feature = "postgres")] +use canyon_connection::tokio_postgres::{self, types::ToSql}; use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Utc}; -use std::any::Any; + +use std::{any::Any, borrow::Cow}; /// Created for retrieve the field's name of a field of a struct, giving /// the Canyon's autogenerated enum with the variants that maps this @@ -100,16 +101,23 @@ impl Row for tiberius::Row { } } +#[cfg(feature = "mysql")] +impl Row for mysql_async::Row { + fn as_any(&self) -> &dyn Any { + self + } +} + /// Generic abstraction for hold a Column type that will be one of the Column /// types present in the dependent crates // #[derive(Copy, Clone)] pub struct Column<'a> { - name: &'a str, + name: Cow<'a, str>, type_: ColumnType, } impl<'a> Column<'a> { - pub fn name(&self) -> &'_ str { - self.name + pub fn name(&self) -> &str { + &self.name } pub fn column_type(&self) -> &ColumnType { &self.type_ @@ -137,6 +145,12 @@ impl Type for tiberius::ColumnType { self } } +#[cfg(feature = "mysql")] +impl Type for mysql_async::consts::ColumnType { + fn as_any(&self) -> &dyn Any { + self + } +} /// Wrapper over the dependencies Column's types pub enum ColumnType { @@ -144,6 +158,8 @@ pub enum ColumnType { Postgres(tokio_postgres::types::Type), #[cfg(feature = "mssql")] SqlServer(tiberius::ColumnType), + #[cfg(feature = "mysql")] + MySQL(mysql_async::consts::ColumnType), } pub trait RowOperations { @@ -155,6 +171,10 @@ pub trait RowOperations { fn get_mssql<'a, Output>(&'a self, col_name: &'a str) -> Output where Output: tiberius::FromSql<'a>; + #[cfg(feature = "mysql")] + fn get_mysql<'a, Output>(&'a self, col_name: &'a str) -> Output + where + Output: mysql_async::prelude::FromValue; #[cfg(feature = "postgres")] fn get_postgres_opt<'a, Output>(&'a self, col_name: &'a str) -> Option @@ -165,6 +185,11 @@ pub trait RowOperations { where Output: tiberius::FromSql<'a>; + #[cfg(feature = "mysql")] + fn get_mysql_opt<'a, Output>(&'a self, col_name: &'a str) -> Option + where + Output: mysql_async::prelude::FromValue; + fn columns(&self) -> Vec; } @@ -192,6 +217,15 @@ impl RowOperations for &dyn Row { panic!() // TODO into result and propagate } + #[cfg(feature = "mysql")] + fn get_mysql<'a, Output>(&'a self, col_name: &'a str) -> Output + where + Output: mysql_async::prelude::FromValue, + { + self.get_mysql_opt(col_name) + .expect("Failed to obtain a column in the MySql") + } + #[cfg(feature = "postgres")] fn get_postgres_opt<'a, Output>(&'a self, col_name: &'a str) -> Option where @@ -213,6 +247,16 @@ impl RowOperations for &dyn Row { }; panic!() // TODO into result and propagate } + #[cfg(feature = "mysql")] + fn get_mysql_opt<'a, Output>(&'a self, col_name: &'a str) -> Option + where + Output: mysql_async::prelude::FromValue, + { + if let Some(row) = self.as_any().downcast_ref::() { + return row.get::(col_name); + }; + panic!() // TODO into result and propagate + } fn columns(&self) -> Vec { let mut cols = vec![]; @@ -227,7 +271,7 @@ impl RowOperations for &dyn Row { .iter() .for_each(|c| { cols.push(Column { - name: c.name(), + name: Cow::from(c.name()), type_: ColumnType::Postgres(c.type_().to_owned()), }) }) @@ -243,12 +287,23 @@ impl RowOperations for &dyn Row { .iter() .for_each(|c| { cols.push(Column { - name: c.name(), + name: Cow::from(c.name()), type_: ColumnType::SqlServer(c.column_type()), }) }) }; } + #[cfg(feature = "mysql")] + { + if let Some(mysql_row) = self.as_any().downcast_ref::() { + mysql_row.columns_ref().iter().for_each(|c| { + cols.push(Column { + name: c.name_str(), + type_: ColumnType::MySQL(c.column_type()), + }) + }) + } + } cols } @@ -261,6 +316,8 @@ pub trait QueryParameter<'a>: std::fmt::Debug + Sync + Send { fn as_postgres_param(&self) -> &(dyn ToSql + Sync); #[cfg(feature = "mssql")] fn as_sqlserver_param(&self) -> ColumnData<'_>; + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue; } /// The implementation of the [`canyon_connection::tiberius`] [`IntoSql`] for the @@ -278,6 +335,8 @@ impl<'a> IntoSql<'a> for &'a dyn QueryParameter<'a> { } } +//TODO Pending to review and see if it is necessary to apply something similar to the previous implementation. + impl<'a> QueryParameter<'a> for bool { #[cfg(feature = "postgres")] fn as_postgres_param(&self) -> &(dyn ToSql + Sync) { @@ -287,6 +346,10 @@ impl<'a> QueryParameter<'a> for bool { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::Bit(Some(*self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn ToValue { + self + } } impl<'a> QueryParameter<'a> for i16 { #[cfg(feature = "postgres")] @@ -297,6 +360,10 @@ impl<'a> QueryParameter<'a> for i16 { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I16(Some(*self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for &i16 { #[cfg(feature = "postgres")] @@ -307,6 +374,10 @@ impl<'a> QueryParameter<'a> for &i16 { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I16(Some(**self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option { #[cfg(feature = "postgres")] @@ -317,6 +388,10 @@ impl<'a> QueryParameter<'a> for Option { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I16(*self) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option<&i16> { #[cfg(feature = "postgres")] @@ -327,6 +402,10 @@ impl<'a> QueryParameter<'a> for Option<&i16> { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I16(Some(*self.unwrap())) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for i32 { #[cfg(feature = "postgres")] @@ -337,6 +416,10 @@ impl<'a> QueryParameter<'a> for i32 { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I32(Some(*self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for &i32 { #[cfg(feature = "postgres")] @@ -347,6 +430,10 @@ impl<'a> QueryParameter<'a> for &i32 { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I32(Some(**self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option { #[cfg(feature = "postgres")] @@ -357,6 +444,10 @@ impl<'a> QueryParameter<'a> for Option { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I32(*self) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option<&i32> { #[cfg(feature = "postgres")] @@ -367,6 +458,10 @@ impl<'a> QueryParameter<'a> for Option<&i32> { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I32(Some(*self.unwrap())) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for f32 { #[cfg(feature = "postgres")] @@ -377,6 +472,10 @@ impl<'a> QueryParameter<'a> for f32 { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::F32(Some(*self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for &f32 { #[cfg(feature = "postgres")] @@ -387,6 +486,10 @@ impl<'a> QueryParameter<'a> for &f32 { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::F32(Some(**self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option { #[cfg(feature = "postgres")] @@ -397,6 +500,10 @@ impl<'a> QueryParameter<'a> for Option { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::F32(*self) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option<&f32> { #[cfg(feature = "postgres")] @@ -409,6 +516,10 @@ impl<'a> QueryParameter<'a> for Option<&f32> { *self.expect("Error on an f32 value on QueryParameter<'_>"), )) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for f64 { #[cfg(feature = "postgres")] @@ -419,6 +530,10 @@ impl<'a> QueryParameter<'a> for f64 { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::F64(Some(*self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for &f64 { #[cfg(feature = "postgres")] @@ -426,10 +541,13 @@ impl<'a> QueryParameter<'a> for &f64 { self } #[cfg(feature = "mssql")] - #[cfg(feature = "mssql")] fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::F64(Some(**self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option { #[cfg(feature = "postgres")] @@ -440,6 +558,10 @@ impl<'a> QueryParameter<'a> for Option { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::F64(*self) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option<&f64> { #[cfg(feature = "postgres")] @@ -452,6 +574,10 @@ impl<'a> QueryParameter<'a> for Option<&f64> { *self.expect("Error on an f64 value on QueryParameter<'_>"), )) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for i64 { #[cfg(feature = "postgres")] @@ -462,6 +588,10 @@ impl<'a> QueryParameter<'a> for i64 { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I64(Some(*self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for &i64 { #[cfg(feature = "postgres")] @@ -472,6 +602,10 @@ impl<'a> QueryParameter<'a> for &i64 { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I64(Some(**self)) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option { #[cfg(feature = "postgres")] @@ -482,6 +616,10 @@ impl<'a> QueryParameter<'a> for Option { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I64(*self) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option<&i64> { #[cfg(feature = "postgres")] @@ -492,6 +630,10 @@ impl<'a> QueryParameter<'a> for Option<&i64> { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::I64(Some(*self.unwrap())) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for String { #[cfg(feature = "postgres")] @@ -502,6 +644,10 @@ impl<'a> QueryParameter<'a> for String { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::String(Some(std::borrow::Cow::Owned(self.to_owned()))) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for &String { #[cfg(feature = "postgres")] @@ -512,6 +658,10 @@ impl<'a> QueryParameter<'a> for &String { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::String(Some(std::borrow::Cow::Borrowed(self))) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option { #[cfg(feature = "postgres")] @@ -525,6 +675,10 @@ impl<'a> QueryParameter<'a> for Option { None => ColumnData::String(None), } } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option<&String> { #[cfg(feature = "postgres")] @@ -538,6 +692,10 @@ impl<'a> QueryParameter<'a> for Option<&String> { None => ColumnData::String(None), } } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for &'_ str { #[cfg(feature = "postgres")] @@ -548,6 +706,10 @@ impl<'a> QueryParameter<'a> for &'_ str { fn as_sqlserver_param(&self) -> ColumnData<'_> { ColumnData::String(Some(std::borrow::Cow::Borrowed(*self))) } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option<&'_ str> { #[cfg(feature = "postgres")] @@ -561,6 +723,10 @@ impl<'a> QueryParameter<'a> for Option<&'_ str> { None => ColumnData::String(None), } } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for NaiveDate { #[cfg(feature = "postgres")] @@ -571,6 +737,10 @@ impl<'a> QueryParameter<'a> for NaiveDate { fn as_sqlserver_param(&self) -> ColumnData<'_> { self.into_sql() } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option { #[cfg(feature = "postgres")] @@ -581,6 +751,10 @@ impl<'a> QueryParameter<'a> for Option { fn as_sqlserver_param(&self) -> ColumnData<'_> { self.into_sql() } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for NaiveTime { #[cfg(feature = "postgres")] @@ -591,6 +765,10 @@ impl<'a> QueryParameter<'a> for NaiveTime { fn as_sqlserver_param(&self) -> ColumnData<'_> { self.into_sql() } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option { #[cfg(feature = "postgres")] @@ -601,6 +779,10 @@ impl<'a> QueryParameter<'a> for Option { fn as_sqlserver_param(&self) -> ColumnData<'_> { self.into_sql() } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for NaiveDateTime { #[cfg(feature = "postgres")] @@ -611,6 +793,10 @@ impl<'a> QueryParameter<'a> for NaiveDateTime { fn as_sqlserver_param(&self) -> ColumnData<'_> { self.into_sql() } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } impl<'a> QueryParameter<'a> for Option { #[cfg(feature = "postgres")] @@ -621,7 +807,13 @@ impl<'a> QueryParameter<'a> for Option { fn as_sqlserver_param(&self) -> ColumnData<'_> { self.into_sql() } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + self + } } + +//TODO pending impl<'a> QueryParameter<'a> for DateTime { #[cfg(feature = "postgres")] fn as_postgres_param(&self) -> &(dyn ToSql + Sync) { @@ -631,7 +823,12 @@ impl<'a> QueryParameter<'a> for DateTime { fn as_sqlserver_param(&self) -> ColumnData<'_> { self.into_sql() } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + todo!() + } } + impl<'a> QueryParameter<'a> for Option> { #[cfg(feature = "postgres")] fn as_postgres_param(&self) -> &(dyn ToSql + Sync) { @@ -641,7 +838,12 @@ impl<'a> QueryParameter<'a> for Option> { fn as_sqlserver_param(&self) -> ColumnData<'_> { self.into_sql() } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + todo!() + } } + impl<'a> QueryParameter<'a> for DateTime { #[cfg(feature = "postgres")] fn as_postgres_param(&self) -> &(dyn ToSql + Sync) { @@ -651,7 +853,12 @@ impl<'a> QueryParameter<'a> for DateTime { fn as_sqlserver_param(&self) -> ColumnData<'_> { self.into_sql() } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + todo!() + } } + impl<'a> QueryParameter<'a> for Option> { #[cfg(feature = "postgres")] fn as_postgres_param(&self) -> &(dyn ToSql + Sync) { @@ -661,4 +868,8 @@ impl<'a> QueryParameter<'a> for Option> { fn as_sqlserver_param(&self) -> ColumnData<'_> { self.into_sql() } + #[cfg(feature = "mysql")] + fn as_mysql_param(&self) -> &dyn mysql_async::prelude::ToValue { + todo!() + } } diff --git a/canyon_crud/src/crud.rs b/canyon_crud/src/crud.rs index f5c6d37e..981c24f1 100644 --- a/canyon_crud/src/crud.rs +++ b/canyon_crud/src/crud.rs @@ -1,6 +1,6 @@ +use async_trait::async_trait; use std::fmt::Display; -use async_trait::async_trait; use canyon_connection::canyon_database_connector::DatabaseConnection; use canyon_connection::{get_database_connection, CACHED_DATABASE_CONN}; @@ -11,6 +11,11 @@ use crate::query_elements::query_builder::{ }; use crate::rows::CanyonRows; +#[cfg(feature = "mysql")] +pub const DETECT_PARAMS_IN_QUERY: &str = r"\$([\d])+"; +#[cfg(feature = "mysql")] +pub const DETECT_QUOTE_IN_QUERY: &str = r#"\"|\\"#; + /// This traits defines and implements a query against a database given /// an statement `stmt` and the params to pass the to the client. /// @@ -52,6 +57,11 @@ pub trait Transaction { ) .await } + #[cfg(feature = "mysql")] + DatabaseConnection::MySQL(_) => { + mysql_query_launcher::launch::(database_conn, stmt.to_string(), params.as_ref()) + .await + } } } } @@ -146,9 +156,10 @@ where #[cfg(feature = "postgres")] mod postgres_query_launcher { + use canyon_connection::canyon_database_connector::DatabaseConnection; + use crate::bounds::QueryParameter; use crate::rows::CanyonRows; - use canyon_connection::canyon_database_connector::DatabaseConnection; pub async fn launch<'a, T>( db_conn: &DatabaseConnection, @@ -217,3 +228,104 @@ mod sqlserver_query_launcher { )) } } + +#[cfg(feature = "mysql")] +mod mysql_query_launcher { + use std::sync::Arc; + + use mysql_async::prelude::Query; + use mysql_async::QueryWithParams; + use mysql_async::Value; + + use canyon_connection::canyon_database_connector::DatabaseConnection; + + use crate::bounds::QueryParameter; + use crate::rows::CanyonRows; + use mysql_async::Row; + use mysql_common::constants::ColumnType; + use mysql_common::row; + + use super::reorder_params; + use crate::crud::{DETECT_PARAMS_IN_QUERY, DETECT_QUOTE_IN_QUERY}; + use regex::Regex; + + pub async fn launch<'a, T>( + db_conn: &DatabaseConnection, + stmt: String, + params: &'a [&'_ dyn QueryParameter<'_>], + ) -> Result, Box<(dyn std::error::Error + Send + Sync + 'static)>> { + let mysql_connection = db_conn.mysql_connection().client.get_conn().await?; + + let stmt_with_escape_characters = regex::escape(&stmt); + let query_string = + Regex::new(DETECT_PARAMS_IN_QUERY)?.replace_all(&stmt_with_escape_characters, "?"); + + let mut query_string = Regex::new(DETECT_QUOTE_IN_QUERY)? + .replace_all(&query_string, "") + .to_string(); + + let mut is_insert = false; + if let Some(index_start_clausule_returning) = query_string.find(" RETURNING") { + query_string.truncate(index_start_clausule_returning); + is_insert = true; + } + + let params_query: Vec = + reorder_params(&stmt, params, |f| f.as_mysql_param().to_value()); + + let query_with_params = QueryWithParams { + query: query_string, + params: params_query, + }; + + let mut query_result = query_with_params + .run(mysql_connection) + .await + .expect("Error executing query in mysql"); + + let result_rows = if is_insert { + let last_insert = query_result + .last_insert_id() + .map(Value::UInt) + .expect("Error getting pk id in insert"); + + vec![row::new_row( + vec![last_insert], + Arc::new([mysql_async::Column::new(ColumnType::MYSQL_TYPE_UNKNOWN)]), + )] + } else { + query_result + .collect::() + .await + .expect("Error resolved trait FromRow in mysql") + }; + + Ok(CanyonRows::MySQL(result_rows)) + } +} + +#[cfg(feature = "mysql")] +fn reorder_params( + stmt: &str, + params: &[&'_ dyn QueryParameter<'_>], + fn_parser: impl Fn(&&dyn QueryParameter<'_>) -> T, +) -> Vec { + let mut ordered_params = vec![]; + let rg = regex::Regex::new(DETECT_PARAMS_IN_QUERY) + .expect("Error create regex with detect params pattern expression"); + + for positional_param in rg.find_iter(stmt) { + let pp: &str = positional_param.as_str(); + let pp_index = pp[1..] // param $1 -> get 1 + .parse::() + .expect("Error parse mapped parameter to usized.") + - 1; + + let element = params + .get(pp_index) + .expect("Error obtaining the element of the mapping against parameters."); + ordered_params.push(fn_parser(element)); + } + + ordered_params +} diff --git a/canyon_crud/src/mapper.rs b/canyon_crud/src/mapper.rs index 66cb91d2..252df1ce 100644 --- a/canyon_crud/src/mapper.rs +++ b/canyon_crud/src/mapper.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "mysql")] +use canyon_connection::mysql_async; #[cfg(feature = "mssql")] use canyon_connection::tiberius; #[cfg(feature = "postgres")] @@ -13,4 +15,6 @@ pub trait RowMapper>: Sized { fn deserialize_postgresql(row: &tokio_postgres::Row) -> T; #[cfg(feature = "mssql")] fn deserialize_sqlserver(row: &tiberius::Row) -> T; + #[cfg(feature = "mysql")] + fn deserialize_mysql(row: &mysql_async::Row) -> T; } diff --git a/canyon_crud/src/query_elements/operators.rs b/canyon_crud/src/query_elements/operators.rs index 30637bad..015ced03 100644 --- a/canyon_crud/src/query_elements/operators.rs +++ b/canyon_crud/src/query_elements/operators.rs @@ -1,5 +1,7 @@ +use canyon_connection::canyon_database_connector::DatabaseType; + pub trait Operator { - fn as_str(&self, placeholder_counter: usize) -> String; + fn as_str(&self, placeholder_counter: usize, datasource_type: &DatabaseType) -> String; } /// Enumerated type for represent the comparison operations @@ -20,7 +22,7 @@ pub enum Comp { } impl Operator for Comp { - fn as_str(&self, placeholder_counter: usize) -> String { + fn as_str(&self, placeholder_counter: usize, _datasource_type: &DatabaseType) -> String { match *self { Self::Eq => format!(" = ${placeholder_counter}"), Self::Neq => format!(" <> ${placeholder_counter}"), @@ -42,13 +44,26 @@ pub enum Like { } impl Operator for Like { - fn as_str(&self, placeholder_counter: usize) -> String { + fn as_str(&self, placeholder_counter: usize, datasource_type: &DatabaseType) -> String { + let type_data_to_cast_str = match datasource_type { + #[cfg(feature = "postgres")] + DatabaseType::PostgreSql => "VARCHAR", + #[cfg(feature = "mssql")] + DatabaseType::SqlServer => "VARCHAR", + #[cfg(feature = "mysql")] + DatabaseType::MySQL => "CHAR", + }; + match *self { Like::Full => { - format!(" LIKE CONCAT('%', CAST(${placeholder_counter} AS VARCHAR) ,'%')") + format!(" LIKE CONCAT('%', CAST(${placeholder_counter} AS {type_data_to_cast_str}) ,'%')") } - Like::Left => format!(" LIKE CONCAT('%', CAST(${placeholder_counter} AS VARCHAR))"), - Like::Right => format!(" LIKE CONCAT(CAST(${placeholder_counter} AS VARCHAR) ,'%')"), + Like::Left => format!( + " LIKE CONCAT('%', CAST(${placeholder_counter} AS {type_data_to_cast_str}))" + ), + Like::Right => format!( + " LIKE CONCAT(CAST(${placeholder_counter} AS {type_data_to_cast_str}) ,'%')" + ), } } } diff --git a/canyon_crud/src/query_elements/query_builder.rs b/canyon_crud/src/query_elements/query_builder.rs index e6987d47..e25ff9fe 100644 --- a/canyon_crud/src/query_elements/query_builder.rs +++ b/canyon_crud/src/query_elements/query_builder.rs @@ -1,5 +1,9 @@ use std::fmt::Debug; +use canyon_connection::{ + canyon_database_connector::DatabaseType, get_database_config, DATASOURCES, +}; + use crate::{ bounds::{FieldIdentifier, FieldValueIdentifier, QueryParameter}, crud::{CrudOperations, Transaction}, @@ -138,6 +142,7 @@ where { query: Query<'a, T>, datasource_name: &'a str, + datasource_type: DatabaseType, } unsafe impl<'a, T> Send for QueryBuilder<'a, T> where @@ -158,6 +163,9 @@ where Self { query, datasource_name, + datasource_type: DatabaseType::from( + &get_database_config(datasource_name, &DATASOURCES).auth, + ), } } @@ -180,8 +188,9 @@ where pub fn r#where>(&mut self, r#where: Z, op: impl Operator) { let (column_name, value) = r#where.value(); - let where_ = - String::from(" WHERE ") + column_name + &op.as_str(self.query.params.len() + 1); + let where_ = String::from(" WHERE ") + + column_name + + &op.as_str(self.query.params.len() + 1, &self.datasource_type); self.query.sql.push_str(&where_); self.query.params.push(value); @@ -190,7 +199,9 @@ where pub fn and>(&mut self, r#and: Z, op: impl Operator) { let (column_name, value) = r#and.value(); - let and_ = String::from(" AND ") + column_name + &op.as_str(self.query.params.len() + 1); + let and_ = String::from(" AND ") + + column_name + + &op.as_str(self.query.params.len() + 1, &self.datasource_type); self.query.sql.push_str(&and_); self.query.params.push(value); @@ -199,7 +210,9 @@ where pub fn or>(&mut self, r#and: Z, op: impl Operator) { let (column_name, value) = r#and.value(); - let and_ = String::from(" OR ") + column_name + &op.as_str(self.query.params.len() + 1); + let and_ = String::from(" OR ") + + column_name + + &op.as_str(self.query.params.len() + 1, &self.datasource_type); self.query.sql.push_str(&and_); self.query.params.push(value); diff --git a/canyon_crud/src/rows.rs b/canyon_crud/src/rows.rs index d8d35070..517592a6 100644 --- a/canyon_crud/src/rows.rs +++ b/canyon_crud/src/rows.rs @@ -13,6 +13,9 @@ pub enum CanyonRows { Postgres(Vec), #[cfg(feature = "mssql")] Tiberius(Vec), + #[cfg(feature = "mysql")] + MySQL(Vec), + UnusableTypeMarker(PhantomData), } @@ -33,6 +36,14 @@ impl CanyonRows { } } + #[cfg(feature = "mysql")] + pub fn get_mysql_rows(&self) -> &Vec { + match self { + Self::MySQL(v) => v, + _ => panic!("This branch will never ever should be reachable"), + } + } + /// Consumes `self` and returns the wrapped [`std::vec::Vec`] with the instances of T pub fn into_results>(self) -> Vec where @@ -43,6 +54,8 @@ impl CanyonRows { Self::Postgres(v) => v.iter().map(|row| Z::deserialize_postgresql(row)).collect(), #[cfg(feature = "mssql")] Self::Tiberius(v) => v.iter().map(|row| Z::deserialize_sqlserver(row)).collect(), + #[cfg(feature = "mysql")] + Self::MySQL(v) => v.iter().map(|row| Z::deserialize_mysql(row)).collect(), _ => panic!("This branch will never ever should be reachable"), } } @@ -54,6 +67,8 @@ impl CanyonRows { Self::Postgres(v) => v.len(), #[cfg(feature = "mssql")] Self::Tiberius(v) => v.len(), + #[cfg(feature = "mysql")] + Self::MySQL(v) => v.len(), _ => panic!("This branch will never ever should be reachable"), } } @@ -65,6 +80,8 @@ impl CanyonRows { Self::Postgres(v) => v.is_empty(), #[cfg(feature = "mssql")] Self::Tiberius(v) => v.is_empty(), + #[cfg(feature = "mysql")] + Self::MySQL(v) => v.is_empty(), _ => panic!("This branch will never ever should be reachable"), } } diff --git a/canyon_macros/Cargo.toml b/canyon_macros/Cargo.toml index 763fde8d..8b8a2852 100755 --- a/canyon_macros/Cargo.toml +++ b/canyon_macros/Cargo.toml @@ -27,4 +27,6 @@ canyon_migrations = { workspace = true, optional = true } [features] postgres = ["canyon_connection/postgres", "canyon_crud/postgres", "canyon_migrations/postgres"] mssql = ["canyon_connection/mssql", "canyon_crud/mssql", "canyon_migrations/mssql"] +mysql = ["canyon_connection/mysql", "canyon_crud/mysql", "canyon_migrations/mysql"] + migrations = ["canyon_migrations"] diff --git a/canyon_macros/src/lib.rs b/canyon_macros/src/lib.rs index 160f6ece..6f094fff 100755 --- a/canyon_macros/src/lib.rs +++ b/canyon_macros/src/lib.rs @@ -2,6 +2,8 @@ extern crate proc_macro; mod canyon_entity_macro; #[cfg(feature = "migrations")] +use canyon_macro::main_with_queries; + mod canyon_macro; mod query_operations; mod utils; @@ -12,9 +14,6 @@ use proc_macro2::{Ident, TokenStream}; use quote::{quote, ToTokens}; use syn::{DeriveInput, Fields, Type, Visibility}; -#[cfg(feature = "migrations")] -use canyon_macro::main_with_queries; - use query_operations::{ delete::{generate_delete_query_tokens, generate_delete_tokens}, insert::{generate_insert_tokens, generate_multiple_insert_tokens}, @@ -531,55 +530,38 @@ pub fn implement_row_mapper_for_type(input: proc_macro::TokenStream) -> proc_mac } }); + let init_field_values_mysql = fields.iter().map(|(_vis, ident, _ty)| { + let ident_name = ident.to_string(); + quote! { + #ident: row.get(#ident_name) + .expect(format!("Failed to retrieve the {} field", #ident_name).as_ref()) + } + }); + // The type of the Struct let ty = ast.ident; - let postgres_enabled = cfg!(feature = "postgres"); - let mssql_enabled = cfg!(feature = "mssql"); - - let tokens = if postgres_enabled && mssql_enabled { - quote! { - impl canyon_sql::crud::RowMapper for #ty { - fn deserialize_postgresql(row: &canyon_sql::db_clients::tokio_postgres::Row) -> #ty { - Self { - #(#init_field_values),* - } - } - fn deserialize_sqlserver(row: &canyon_sql::db_clients::tiberius::Row) -> #ty { - Self { - #(#init_field_values_sqlserver),* - } + let tokens = quote! { + impl canyon_sql::crud::RowMapper for #ty { + #[cfg(feature="postgres")] + fn deserialize_postgresql(row: &canyon_sql::db_clients::tokio_postgres::Row) -> #ty { + Self { + #(#init_field_values),* } } - } - } else if postgres_enabled { - quote! { - impl canyon_sql::crud::RowMapper for #ty { - fn deserialize_postgresql(row: &canyon_sql::db_clients::tokio_postgres::Row) -> #ty { - Self { - #(#init_field_values),* - } + #[cfg(feature="mssql")] + fn deserialize_sqlserver(row: &canyon_sql::db_clients::tiberius::Row) -> #ty { + Self { + #(#init_field_values_sqlserver),* } } - } - } else if mssql_enabled { - quote! { - impl canyon_sql::crud::RowMapper for #ty { - fn deserialize_sqlserver(row: &canyon_sql::db_clients::tiberius::Row) -> #ty { - Self { - #(#init_field_values_sqlserver),* - } + #[cfg(feature="mysql")] + fn deserialize_mysql(row: &canyon_sql::db_clients::mysql_async::Row) -> #ty { + Self { + #(#init_field_values_mysql),* } } } - } else { - quote! { - panic!( - "Reached a branch in the implementation of the Row Mapper macro that should never be reached.\ - This is a severe bug of Canyon-SQL. Please, open us an issue at \ - https://github.com/zerodaycode/Canyon-SQL/issues and let us know about that failure." - ) - } }; tokens.into() diff --git a/canyon_macros/src/query_operations/insert.rs b/canyon_macros/src/query_operations/insert.rs index 329399f0..c6e5e205 100644 --- a/canyon_macros/src/query_operations/insert.rs +++ b/canyon_macros/src/query_operations/insert.rs @@ -38,58 +38,6 @@ pub fn generate_insert_tokens(macro_data: &MacroTokens, table_schema_data: &Stri let pk_ident = &pk_data.0; let pk_type = &pk_data.1; - let postgres_enabled = cfg!(feature = "postgres"); - let mssql_enabled = cfg!(feature = "mssql"); - - let match_rows = if postgres_enabled && mssql_enabled { - quote! { - canyon_sql::crud::CanyonRows::Postgres(mut v) => { - self.#pk_ident = v - .get(0) - .ok_or("Failed getting the returned IDs for an insert")? - .get::<&str, #pk_type>(#primary_key); - Ok(()) - } - canyon_sql::crud::CanyonRows::Tiberius(mut v) => { - self.#pk_ident = v - .get(0) - .ok_or("Failed getting the returned IDs for a multi insert")? - .get::<#pk_type, &str>(#primary_key) - .ok_or("SQL Server primary key type failed to be set as value")?; - Ok(()) - } - } - } else if postgres_enabled { - quote! { - canyon_sql::crud::CanyonRows::Postgres(mut v) => { - self.#pk_ident = v - .get(0) - .ok_or("Failed getting the returned IDs for an insert")? - .get::<&str, #pk_type>(#primary_key); - Ok(()) - } - } - } else if mssql_enabled { - quote! { - canyon_sql::crud::CanyonRows::Tiberius(mut v) => { - self.#pk_ident = v - .get(0) - .ok_or("Failed getting the returned IDs for a multi insert")? - .get::<#pk_type, &str>(#primary_key) - .ok_or("SQL Server primary key type failed to be set as value")?; - Ok(()) - } - } - } else { - quote! { - panic!( - "Reached a branch in the implementation of the Row Mapper macro that should never be reached.\ - This is a severe bug of Canyon-SQL. Please, open us an issue at \ - https://github.com/zerodaycode/Canyon-SQL/issues and let us know about that failure." - ) - } - }; - quote! { #remove_pk_value_from_fn_entry; @@ -108,7 +56,32 @@ pub fn generate_insert_tokens(macro_data: &MacroTokens, table_schema_data: &Stri ).await?; match rows { - #match_rows + #[cfg(feature = "postgres")] + canyon_sql::crud::CanyonRows::Postgres(mut v) => { + self.#pk_ident = v + .get(0) + .ok_or("Failed getting the returned IDs for an insert")? + .get::<&str, #pk_type>(#primary_key); + Ok(()) + }, + #[cfg(feature = "mssql")] + canyon_sql::crud::CanyonRows::Tiberius(mut v) => { + self.#pk_ident = v + .get(0) + .ok_or("Failed getting the returned IDs for a multi insert")? + .get::<#pk_type, &str>(#primary_key) + .ok_or("SQL Server primary key type failed to be set as value")?; + Ok(()) + }, + #[cfg(feature = "mysql")] + canyon_sql::crud::CanyonRows::MySQL(mut v) => { + self.#pk_ident = v + .get(0) + .ok_or("Failed getting the returned IDs for a multi insert")? + .get::<#pk_type,usize>(0) + .ok_or("MYSQL primary key type failed to be set as value")?; + Ok(()) + }, _ => panic!("Reached the panic match arm of insert for the DatabaseConnection type") // TODO remove when the generics will be refactored } } @@ -259,70 +232,6 @@ pub fn generate_multiple_insert_tokens( let pk_ident = &pk_data.0; let pk_type = &pk_data.1; - let postgres_enabled = cfg!(feature = "postgres"); - let mssql_enabled = cfg!(feature = "mssql"); - - let match_multi_insert_rows = if postgres_enabled && mssql_enabled { - quote! { - canyon_sql::crud::CanyonRows::Postgres(mut v) => { - for (idx, instance) in instances.iter_mut().enumerate() { - instance.#pk_ident = v - .get(idx) - .expect("Failed getting the returned IDs for a multi insert") - .get::<&str, #pk_type>(#pk); - } - - Ok(()) - } - canyon_sql::crud::CanyonRows::Tiberius(mut v) => { - for (idx, instance) in instances.iter_mut().enumerate() { - instance.#pk_ident = v - .get(idx) - .expect("Failed getting the returned IDs for a multi insert") - .get::<#pk_type, &str>(#pk) - .expect("SQL Server primary key type failed to be set as value"); - } - - Ok(()) - } - } - } else if postgres_enabled { - quote! { - canyon_sql::crud::CanyonRows::Postgres(mut v) => { - for (idx, instance) in instances.iter_mut().enumerate() { - instance.#pk_ident = v - .get(idx) - .expect("Failed getting the returned IDs for a multi insert") - .get::<&str, #pk_type>(#pk); - } - - Ok(()) - } - } - } else if mssql_enabled { - quote! { - canyon_sql::crud::CanyonRows::Tiberius(mut v) => { - for (idx, instance) in instances.iter_mut().enumerate() { - instance.#pk_ident = v - .get(idx) - .expect("Failed getting the returned IDs for a multi insert") - .get::<#pk_type, &str>(#pk) - .expect("SQL Server primary key type failed to be set as value"); - } - - Ok(()) - } - } - } else { - quote! { - panic!( - "Reached a branch in the implementation of the Row Mapper macro that should never be reached.\ - This is a severe bug of Canyon-SQL. Please, open us an issue at \ - https://github.com/zerodaycode/Canyon-SQL/issues and let us know about that failure." - ) - } - }; - quote! { mapped_fields = #column_names .split(", ") @@ -392,7 +301,40 @@ pub fn generate_multiple_insert_tokens( ).await?; match multi_insert_result { - #match_multi_insert_rows + #[cfg(feature="postgres")] + canyon_sql::crud::CanyonRows::Postgres(mut v) => { + for (idx, instance) in instances.iter_mut().enumerate() { + instance.#pk_ident = v + .get(idx) + .expect("Failed getting the returned IDs for a multi insert") + .get::<&str, #pk_type>(#pk); + } + + Ok(()) + }, + #[cfg(feature="mssql")] + canyon_sql::crud::CanyonRows::Tiberius(mut v) => { + for (idx, instance) in instances.iter_mut().enumerate() { + instance.#pk_ident = v + .get(idx) + .expect("Failed getting the returned IDs for a multi insert") + .get::<#pk_type, &str>(#pk) + .expect("SQL Server primary key type failed to be set as value"); + } + + Ok(()) + }, + #[cfg(feature="mysql")] + canyon_sql::crud::CanyonRows::MySQL(mut v) => { + for (idx, instance) in instances.iter_mut().enumerate() { + instance.#pk_ident = v + .get(idx) + .expect("Failed getting the returned IDs for a multi insert") + .get::<#pk_type,usize>(0) + .expect("MYSQL primary key type failed to be set as value"); + } + Ok(()) + }, _ => panic!() // TODO remove when the generics will be refactored } } diff --git a/canyon_macros/src/query_operations/select.rs b/canyon_macros/src/query_operations/select.rs index 5a5a4e15..82a1a5b5 100644 --- a/canyon_macros/src/query_operations/select.rs +++ b/canyon_macros/src/query_operations/select.rs @@ -148,49 +148,25 @@ pub fn generate_count_tokens( ) -> TokenStream { let ty = macro_data.ty; let ty_str = &ty.to_string(); - let stmt = format!("SELECT COUNT (*) FROM {table_schema_data}"); + let stmt = format!("SELECT COUNT(*) FROM {table_schema_data}"); - let postgres_enabled = cfg!(feature = "postgres"); - let mssql_enabled = cfg!(feature = "mssql"); - - let result_handling = if postgres_enabled && mssql_enabled { - quote! { - canyon_sql::crud::CanyonRows::Postgres(mut v) => Ok( - v.remove(0).get::<&str, i64>("count") - ), - canyon_sql::crud::CanyonRows::Tiberius(mut v) => - v.remove(0) - .get::(0) - .map(|c| c as i64) - .ok_or(format!("Failure in the COUNT query for MSSQL for: {}", #ty_str).into()) - .into(), - _ => panic!() // TODO remove when the generics will be refactored - } - } else if postgres_enabled { - quote! { - canyon_sql::crud::CanyonRows::Postgres(mut v) => Ok( + let result_handling = quote! { + #[cfg(feature="postgres")] + canyon_sql::crud::CanyonRows::Postgres(mut v) => Ok( v.remove(0).get::<&str, i64>("count") ), - _ => panic!() // TODO remove when the generics will be refactored - } - } else if mssql_enabled { - quote! { - canyon_sql::crud::CanyonRows::Tiberius(mut v) => + #[cfg(feature="mssql")] + canyon_sql::crud::CanyonRows::Tiberius(mut v) => v.remove(0) .get::(0) .map(|c| c as i64) .ok_or(format!("Failure in the COUNT query for MSSQL for: {}", #ty_str).into()) .into(), + #[cfg(feature="mysql")] + canyon_sql::crud::CanyonRows::MySQL(mut v) => v.remove(0) + .get::(0) + .ok_or(format!("Failure in the COUNT query for MYSQL for: {}", #ty_str).into()), _ => panic!() // TODO remove when the generics will be refactored - } - } else { - quote! { - panic!( - "Reached a branch in the implementation of the Row Mapper macro that should never be reached.\ - This is a severe bug of Canyon-SQL. Please, open us an issue at \ - https://github.com/zerodaycode/Canyon-SQL/issues and let us know about that failure." - ) - } }; quote! { @@ -380,7 +356,7 @@ pub fn generate_find_by_foreign_key_tokens( }; fk_quotes.push(( - quote!{ #quoted_method_signature; }, + quote! { #quoted_method_signature; }, quote! { /// Searches the parent entity (if exists) for this type #quoted_method_signature { diff --git a/canyon_migrations/Cargo.toml b/canyon_migrations/Cargo.toml index ba353b76..ec9a31db 100644 --- a/canyon_migrations/Cargo.toml +++ b/canyon_migrations/Cargo.toml @@ -17,6 +17,9 @@ canyon_entities = { workspace = true } tokio = { workspace = true } tokio-postgres = { workspace = true, optional = true } tiberius = { workspace = true, optional = true } +mysql_async = { workspace = true, optional = true } +mysql_common = { workspace = true, optional = true } + async-trait = { workspace = true } @@ -30,3 +33,5 @@ syn = { version = "1.0.86", features = ["full", "parsing"] } # TODO Pending to r [features] postgres = ["tokio-postgres", "canyon_connection/postgres", "canyon_crud/postgres"] mssql = ["tiberius", "canyon_connection/mssql", "canyon_crud/mssql"] +mysql = ["mysql_async","mysql_common", "canyon_connection/mysql", "canyon_crud/mysql"] + diff --git a/canyon_migrations/src/migrations/handler.rs b/canyon_migrations/src/migrations/handler.rs index 24dfb1c4..3d00da8b 100644 --- a/canyon_migrations/src/migrations/handler.rs +++ b/canyon_migrations/src/migrations/handler.rs @@ -94,6 +94,8 @@ impl Migrations { DatabaseType::PostgreSql => constants::postgresql_queries::FETCH_PUBLIC_SCHEMA, #[cfg(feature = "mssql")] DatabaseType::SqlServer => constants::mssql_queries::FETCH_PUBLIC_SCHEMA, + #[cfg(feature = "mysql")] + DatabaseType::MySQL => todo!("Not implemented fetch database in mysql"), }; Self::query(query, [], datasource_name) @@ -291,5 +293,7 @@ fn check_for_table_name( DatabaseType::PostgreSql => table.table_name == res_row.get_postgres::<&str>("table_name"), #[cfg(feature = "mssql")] DatabaseType::SqlServer => table.table_name == res_row.get_mssql::<&str>("table_name"), + #[cfg(feature = "mysql")] + DatabaseType::MySQL => todo!(), } } diff --git a/canyon_migrations/src/migrations/information_schema.rs b/canyon_migrations/src/migrations/information_schema.rs index 74709619..9e165eee 100644 --- a/canyon_migrations/src/migrations/information_schema.rs +++ b/canyon_migrations/src/migrations/information_schema.rs @@ -67,6 +67,8 @@ impl ColumnMetadataTypeValue { } _ => Self::NoneValue, }, + #[cfg(feature = "mysql")] + ColumnType::MySQL(_) => todo!(), } } } diff --git a/canyon_migrations/src/migrations/memory.rs b/canyon_migrations/src/migrations/memory.rs index 1d822fd1..80fbe3ad 100644 --- a/canyon_migrations/src/migrations/memory.rs +++ b/canyon_migrations/src/migrations/memory.rs @@ -248,6 +248,8 @@ impl CanyonMemory { DatabaseType::PostgreSql => constants::postgresql_queries::CANYON_MEMORY_TABLE, #[cfg(feature = "mssql")] DatabaseType::SqlServer => constants::mssql_queries::CANYON_MEMORY_TABLE, + #[cfg(feature = "mysql")] + DatabaseType::MySQL => todo!("Memory table in mysql not implemented"), }; Self::query(query, [], datasource_name) diff --git a/canyon_migrations/src/migrations/processor.rs b/canyon_migrations/src/migrations/processor.rs index 425c1b0d..aee9a89e 100644 --- a/canyon_migrations/src/migrations/processor.rs +++ b/canyon_migrations/src/migrations/processor.rs @@ -807,7 +807,9 @@ impl DatabaseOperation for TableOperation { .join(", ") ) .replace('"', "") - } + }, + #[cfg(feature = "mysql")] DatabaseType::MySQL => todo!() + } } @@ -830,7 +832,9 @@ impl DatabaseOperation for TableOperation { be an allowed behaviour for now, only with the table_name parameter on the CanyonEntity annotation. */ - format!("exec sp_rename '{old_table_name}', '{new_table_name}';") + format!("exec sp_rename '{old_table_name}', '{new_table_name}';"), + #[cfg(feature = "mysql")] DatabaseType::MySQL => todo!() + } } @@ -848,7 +852,9 @@ impl DatabaseOperation for TableOperation { FOREIGN KEY ({_column_foreign_key}) REFERENCES {_table_to_reference} ({_column_to_reference});" ), #[cfg(feature = "mssql")] DatabaseType::SqlServer => - todo!("[MS-SQL -> Operation still won't supported by Canyon for Sql Server]") + todo!("[MS-SQL -> Operation still won't supported by Canyon for Sql Server]"), + #[cfg(feature = "mysql")] DatabaseType::MySQL => todo!() + } } @@ -859,7 +865,9 @@ impl DatabaseOperation for TableOperation { "ALTER TABLE {_table_with_foreign_key} DROP CONSTRAINT {_constraint_name};", ), #[cfg(feature = "mssql")] DatabaseType::SqlServer => - todo!("[MS-SQL -> Operation still won't supported by Canyon for Sql Server]") + todo!("[MS-SQL -> Operation still won't supported by Canyon for Sql Server]"), + #[cfg(feature = "mysql")] DatabaseType::MySQL => todo!() + } } @@ -871,7 +879,9 @@ impl DatabaseOperation for TableOperation { _entity_field.field_name ), #[cfg(feature = "mssql")] DatabaseType::SqlServer => - todo!("[MS-SQL -> Operation still won't supported by Canyon for Sql Server]") + todo!("[MS-SQL -> Operation still won't supported by Canyon for Sql Server]"), + #[cfg(feature = "mysql")] DatabaseType::MySQL => todo!() + } } @@ -880,7 +890,9 @@ impl DatabaseOperation for TableOperation { #[cfg(feature = "postgres")] DatabaseType::PostgreSql => format!("ALTER TABLE {table_name} DROP CONSTRAINT {primary_key_name} CASCADE;"), #[cfg(feature = "mssql")] DatabaseType::SqlServer => - format!("ALTER TABLE {table_name} DROP CONSTRAINT {primary_key_name} CASCADE;") + format!("ALTER TABLE {table_name} DROP CONSTRAINT {primary_key_name} CASCADE;"), + #[cfg(feature = "mysql")] DatabaseType::MySQL => todo!() + } } }; @@ -932,7 +944,9 @@ impl DatabaseOperation for ColumnOperation { table_name, entity_field.field_name, to_sqlserver_syntax(entity_field) - ) + ), + #[cfg(feature = "mysql")] DatabaseType::MySQL => todo!() + } ColumnOperation::DeleteColumn(table_name, column_name) => { // TODO Check if operation for SQL server is different @@ -946,7 +960,10 @@ impl DatabaseOperation for ColumnOperation { _entity_field.field_name, to_postgres_alter_syntax(_entity_field) ), #[cfg(feature = "mssql")] DatabaseType::SqlServer => - todo!("[MS-SQL -> Operation still won't supported by Canyon for Sql Server]") + todo!("[MS-SQL -> Operation still won't supported by Canyon for Sql Server]"), + #[cfg(feature = "mysql")] DatabaseType::MySQL => todo!() + + } ColumnOperation::AlterColumnDropNotNull(table_name, entity_field) => match db_type { @@ -956,7 +973,9 @@ impl DatabaseOperation for ColumnOperation { format!( "ALTER TABLE \"{table_name}\" ALTER COLUMN {} {} NULL", entity_field.field_name, to_sqlserver_alter_syntax(entity_field) - ) + ), + #[cfg(feature = "mysql")] DatabaseType::MySQL => todo!() + } #[cfg(feature = "mssql")] ColumnOperation::DropNotNullBeforeDropColumn(table_name, column_name, column_datatype) => format!( @@ -982,7 +1001,9 @@ impl DatabaseOperation for ColumnOperation { "ALTER TABLE \"{table_name}\" ALTER COLUMN {} {} NOT NULL", entity_field.field_name, to_sqlserver_alter_syntax(entity_field) - ) + ), + #[cfg(feature = "mysql")] DatabaseType::MySQL => todo!() + } } diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 04c21b89..d24de91c 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -27,3 +27,14 @@ services: environment: MSSQL_SA_PASSWORD: "SqlServer-10" ACCEPT_EULA: "Y" + mysql: + image: mysql:latest + container_name: mysql + environment: + MYSQL_ROOT_PASSWORD: root + ports: + - '3307:3306' + volumes: + - ./mysql-data:/var/lib/mysql + - ./mysql/create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql + - ./mysql/fill_tables.sql:/docker-entrypoint-initdb.d/fill_tables.sql \ No newline at end of file diff --git a/docker/mysql/create_tables.sql b/docker/mysql/create_tables.sql new file mode 100644 index 00000000..8963767c --- /dev/null +++ b/docker/mysql/create_tables.sql @@ -0,0 +1,44 @@ +CREATE DATABASE public; + +CREATE TABLE public.league ( + id INT AUTO_INCREMENT PRIMARY KEY, + ext_id BIGINT NOT NULL, + slug TEXT NOT NULL, + name TEXT NOT NULL, + region TEXT NOT NULL, + image_url TEXT NOT NULL +); + +CREATE TABLE public.tournament ( + id INT AUTO_INCREMENT PRIMARY KEY, + ext_id BIGINT NOT NULL, + slug TEXT NOT NULL, + start_date DATE NOT NULL, + end_date DATE NOT NULL, + league INT, + FOREIGN KEY (league) REFERENCES league(id) + +); + +CREATE TABLE public.player ( + id INT AUTO_INCREMENT PRIMARY KEY, + ext_id BIGINT NOT NULL, + first_name TEXT NOT NULL, + last_name TEXT NOT NULL, + summoner_name TEXT NOT NULL, + image_url TEXT, + role TEXT NOT NULL +); + +CREATE TABLE public.team ( + id INT AUTO_INCREMENT PRIMARY KEY, + ext_id BIGINT NOT NULL, + slug TEXT NOT NULL, + name TEXT NOT NULL, + code TEXT NOT NULL, + image_url TEXT NOT NULL, + alt_image_url TEXT, + bg_image_url TEXT, + home_league INT, + FOREIGN KEY (home_league) REFERENCES league(id) +); diff --git a/docker/mysql/fill_tables.sql b/docker/mysql/fill_tables.sql new file mode 100644 index 00000000..84eff356 --- /dev/null +++ b/docker/mysql/fill_tables.sql @@ -0,0 +1,275 @@ +-- Values for league table +INSERT INTO public.league VALUES (1, 100695891328981122, 'european-masters', 'European Masters', 'EUROPE', 'http://static.lolesports.com/leagues/EM_Bug_Outline1.png'); +INSERT INTO public.league VALUES (2, 101097443346691685, 'turkey-academy-league', 'TAL', 'TURKEY', 'http://static.lolesports.com/leagues/1592516072459_TAL-01-FullonDark.png'); +INSERT INTO public.league VALUES (3, 101382741235120470, 'lla', 'LLA', 'LATIN AMERICA', 'http://static.lolesports.com/leagues/1592516315279_LLA-01-FullonDark.png'); +INSERT INTO public.league VALUES (4, 104366947889790212, 'pcs', 'PCS', 'HONG KONG, MACAU, TAIWAN', 'http://static.lolesports.com/leagues/1592515942679_PCS-01-FullonDark.png'); +INSERT INTO public.league VALUES (5, 105266074488398661, 'superliga', 'SuperLiga', 'EUROPE', 'http://static.lolesports.com/leagues/SL21-V-white.png'); +INSERT INTO public.league VALUES (6, 105266088231437431, 'ultraliga', 'Ultraliga', 'EUROPE', 'http://static.lolesports.com/leagues/1639390623717_ULTRALIGA_logo_sq_cyan.png'); +INSERT INTO public.league VALUES (7, 105266091639104326, 'primeleague', 'Prime League', 'EUROPE', 'http://static.lolesports.com/leagues/PrimeLeagueResized.png'); +INSERT INTO public.league VALUES (8, 105266094998946936, 'pg_nationals', 'PG Nationals', 'EUROPE', 'http://static.lolesports.com/leagues/PG_Nationals_Logo_White.png'); +INSERT INTO public.league VALUES (9, 105266098308571975, 'nlc', 'NLC', 'EUROPE', 'http://static.lolesports.com/leagues/1641490922073_nlc_logo.png'); +INSERT INTO public.league VALUES (10, 105266101075764040, 'liga_portuguesa', 'Liga Portuguesa', 'EUROPE', 'http://static.lolesports.com/leagues/1649884876085_LPLOL_2021_ISO_G-c389e9ae85c243e4f76a8028bbd9ca1609c2d12bc47c3709a9250d1b3ca43f58.png'); +INSERT INTO public.league VALUES (11, 105266103462388553, 'lfl', 'La Ligue Française', 'EUROPE', 'http://static.lolesports.com/leagues/LFL_Logo_2020_black1.png'); +INSERT INTO public.league VALUES (12, 105266106309666619, 'hitpoint_masters', 'Hitpoint Masters', 'EUROPE', 'http://static.lolesports.com/leagues/1641465237186_HM_white.png'); +INSERT INTO public.league VALUES (13, 105266108767593290, 'greek_legends', 'Greek Legends League', 'EUROPE', 'http://static.lolesports.com/leagues/GLL_LOGO_WHITE.png'); +INSERT INTO public.league VALUES (14, 105266111679554379, 'esports_balkan_league', 'Esports Balkan League', 'EUROPE', 'http://static.lolesports.com/leagues/1625735031226_ebl_crest-whitePNG.png'); +INSERT INTO public.league VALUES (15, 105549980953490846, 'cblol_academy', 'CBLOL Academy', 'BRAZIL', 'http://static.lolesports.com/leagues/cblol-acad-white.png'); +INSERT INTO public.league VALUES (16, 105709090213554609, 'lco', 'LCO', 'OCEANIA', 'http://static.lolesports.com/leagues/lco-color-white.png'); +INSERT INTO public.league VALUES (17, 106827757669296909, 'ljl_academy', 'LJL Academy', 'JAPAN', 'http://static.lolesports.com/leagues/1630062215891_ljl-al_logo_gradient.png'); +INSERT INTO public.league VALUES (18, 107213827295848783, 'vcs', 'VCS', 'VIETNAM', 'http://static.lolesports.com/leagues/1635953171501_LOL_VCS_Full_White.png'); +INSERT INTO public.league VALUES (19, 107407335299756365, 'elite_series', 'Elite Series', 'EUROPE', 'http://static.lolesports.com/leagues/1641287979138_EliteSeriesMarkWhite.png'); +INSERT INTO public.league VALUES (20, 107581050201097472, 'honor_division', 'Honor Division', 'LATIN AMERICA', 'http://static.lolesports.com/leagues/1641750781829_divhonormxwhite.png'); +INSERT INTO public.league VALUES (21, 107581669166925444, 'elements_league', 'Elements League', 'LATIN AMERICA', 'http://static.lolesports.com/leagues/1642593573670_LOGO_ELEMENTS_White.png'); +INSERT INTO public.league VALUES (22, 107582133359724496, 'volcano_discover_league', 'Volcano League', 'LATIN AMERICA', 'http://static.lolesports.com/leagues/1643106609661_VOLCANO-VERTICAL-ColorLight.png'); +INSERT INTO public.league VALUES (23, 107582580502415838, 'claro_gaming_stars_league', 'Stars League', 'LATIN AMERICA', 'http://static.lolesports.com/leagues/1642595169468_CLARO-GAMING-STARS-LEAGUE-B.png'); +INSERT INTO public.league VALUES (24, 107598636564896416, 'master_flow_league', 'Master Flow League', 'LATIN AMERICA', 'http://static.lolesports.com/leagues/1643794656405_LMF-White.png'); +INSERT INTO public.league VALUES (25, 107598951349015984, 'honor_league', 'Honor League', 'LATIN AMERICA', 'http://static.lolesports.com/leagues/1643036660690_lhe-ColorLight.png'); +INSERT INTO public.league VALUES (26, 107603541524308819, 'movistar_fiber_golden_league', 'Golden League', 'LATIN AMERICA', 'http://static.lolesports.com/leagues/1642445572375_MovistarLeague.png'); +INSERT INTO public.league VALUES (27, 107898214974993351, 'college_championship', 'College Championship', 'NORTH AMERICA', 'http://static.lolesports.com/leagues/1646396098648_CollegeChampionshiplogo.png'); +INSERT INTO public.league VALUES (28, 107921249454961575, 'proving_grounds', 'Proving Grounds', 'NORTH AMERICA', 'http://static.lolesports.com/leagues/1646747578708_download8.png'); +INSERT INTO public.league VALUES (29, 108001239847565215, 'tft_esports', 'TFT Last Chance Qualifier', 'INTERNATIONAL', 'http://static.lolesports.com/leagues/1649439858579_tftesport.png'); +INSERT INTO public.league VALUES (30, 98767975604431411, 'worlds', 'Worlds', 'INTERNATIONAL', 'http://static.lolesports.com/leagues/1592594612171_WorldsDarkBG.png'); +INSERT INTO public.league VALUES (31, 98767991295297326, 'all-star', 'All-Star Event', 'INTERNATIONAL', 'http://static.lolesports.com/leagues/1592594737227_ASEDarkBG.png'); +INSERT INTO public.league VALUES (32, 98767991299243165, 'lcs', 'LCS', 'NORTH AMERICA', 'http://static.lolesports.com/leagues/LCSNew-01-FullonDark.png'); +INSERT INTO public.league VALUES (33, 98767991302996019, 'lec', 'LEC', 'EUROPE', 'http://static.lolesports.com/leagues/1592516184297_LEC-01-FullonDark.png'); +INSERT INTO public.league VALUES (34, 98767991310872058, 'lck', 'LCK', 'KOREA', 'http://static.lolesports.com/leagues/lck-color-on-black.png'); +INSERT INTO public.league VALUES (35, 98767991314006698, 'lpl', 'LPL', 'CHINA', 'http://static.lolesports.com/leagues/1592516115322_LPL-01-FullonDark.png'); +INSERT INTO public.league VALUES (36, 98767991325878492, 'msi', 'MSI', 'INTERNATIONAL', 'http://static.lolesports.com/leagues/1592594634248_MSIDarkBG.png'); +INSERT INTO public.league VALUES (37, 98767991332355509, 'cblol-brazil', 'CBLOL', 'BRAZIL', 'http://static.lolesports.com/leagues/cblol-logo-symbol-offwhite.png'); +INSERT INTO public.league VALUES (38, 98767991335774713, 'lck_challengers_league', 'LCK Challengers', 'KOREA', 'http://static.lolesports.com/leagues/lck-cl-white.png'); +INSERT INTO public.league VALUES (39, 98767991343597634, 'turkiye-sampiyonluk-ligi', 'TCL', 'TURKEY', 'https://lolstatic-a.akamaihd.net/esports-assets/production/league/turkiye-sampiyonluk-ligi-8r9ofb9.png'); +INSERT INTO public.league VALUES (40, 98767991349978712, 'ljl-japan', 'LJL', 'JAPAN', 'http://static.lolesports.com/leagues/1592516354053_LJL-01-FullonDark.png'); +INSERT INTO public.league VALUES (41, 98767991355908944, 'lcl', 'LCL', 'COMMONWEALTH OF INDEPENDENT STATES', 'http://static.lolesports.com/leagues/1593016885758_LCL-01-FullonDark.png'); +INSERT INTO public.league VALUES (42, 99332500638116286, 'lcs-academy', 'LCS Academy', 'NORTH AMERICA', 'http://static.lolesports.com/leagues/lcs-academy-purple.png'); + + +-- Values for player table +INSERT INTO public.player VALUES (1, 98767975906852059, 'Jaehyeok', 'Park', 'Ruler', 'http://static.lolesports.com/players/1642153903692_GEN_Ruler_F.png', 'bottom'); +INSERT INTO public.player VALUES (2, 102186485482484390, 'Hyeonjun', 'Choi', 'Doran', 'http://static.lolesports.com/players/1642153880932_GEN_Doran_F.png', 'top'); +INSERT INTO public.player VALUES (3, 98767975916458257, 'Wangho ', 'Han', 'Peanut', 'http://static.lolesports.com/players/1642153896918_GEN_peanut_A.png', 'jungle'); +INSERT INTO public.player VALUES (4, 99871276342168416, 'Jihun', 'Jung', 'Chovy', 'http://static.lolesports.com/players/1642153873969_GEN_Chovy_F.png', 'mid'); +INSERT INTO public.player VALUES (5, 99871276332909841, 'Siu', 'Son', 'Lehends', 'http://static.lolesports.com/players/1642153887731_GEN_Lehends_F.png', 'support'); +INSERT INTO public.player VALUES (6, 104266797862156067, 'Youngjae', 'Ko', 'YoungJae', 'http://static.lolesports.com/players/1642153913037_GEN_YoungJae_F.png', 'jungle'); +INSERT INTO public.player VALUES (7, 103495716560217968, 'Hyoseong', 'Oh', 'Vsta', 'http://static.lolesports.com/players/1642154102606_HLE_Vsta_F.png', 'support'); +INSERT INTO public.player VALUES (8, 104266795407626462, 'Dongju', 'Lee', 'DuDu', 'http://static.lolesports.com/players/1642154060441_HLE_DuDu_F.png', 'top'); +INSERT INTO public.player VALUES (9, 106267386230851795, 'Junghyeun', 'Kim', 'Willer', 'http://static.lolesports.com/players/1642154110676_HLE_Willer_F.png', 'jungle'); +INSERT INTO public.player VALUES (10, 100725844995692264, 'Janggyeom', 'Kim', 'OnFleek', 'http://static.lolesports.com/players/1642154084709_HLE_Onfleek_F.png', 'jungle'); +INSERT INTO public.player VALUES (11, 105320683858945274, 'Hongjo', 'Kim', 'Karis', 'http://static.lolesports.com/players/1642154066010_HLE_Karis_F.png', 'mid'); +INSERT INTO public.player VALUES (12, 104287359934240404, 'Jaehoon', 'Lee', 'SamD', 'http://static.lolesports.com/players/1642154094651_HLE_SamD_F.png', 'bottom'); +INSERT INTO public.player VALUES (13, 103461966870841210, 'Wyllian', 'Adriano', 'asta', 'http://static.lolesports.com/players/1643226025146_Astacopy.png', 'jungle'); +INSERT INTO public.player VALUES (14, 107559111166843860, 'Felipe', 'Boal', 'Boal', 'http://static.lolesports.com/players/1644095483228_BOALcopiar.png', 'top'); +INSERT INTO public.player VALUES (15, 107559255871511679, 'Giovani', 'Baldan', 'Mito', 'http://static.lolesports.com/players/1643226193262_Mitocopy.png', 'top'); +INSERT INTO public.player VALUES (16, 103478281329357326, 'Arthur', 'Machado', 'Tutsz', 'http://static.lolesports.com/players/1643226293749_Tutszcopy.png', 'mid'); +INSERT INTO public.player VALUES (17, 103743599797538329, 'Luiz Felipe', 'Lobo', 'Flare', 'http://static.lolesports.com/players/1643226082718_Flarecopy.png', 'bottom'); +INSERT INTO public.player VALUES (18, 99566408210057665, 'Natan', 'Braz', 'fNb', 'http://static.lolesports.com/players/1643226467130_Fnbcopiar.png', 'top'); +INSERT INTO public.player VALUES (19, 99566407771166805, 'Filipe', 'Brombilla', 'Ranger', 'http://static.lolesports.com/players/1643226495379_Rangercopiar.png', 'jungle'); +INSERT INTO public.player VALUES (20, 107559327426244686, 'Vinícius', 'Corrêa', 'StineR', 'http://static.lolesports.com/players/1643226666563_Silhueta.png', 'jungle'); +INSERT INTO public.player VALUES (21, 99566407784212776, 'Bruno', 'Farias', 'Envy', 'http://static.lolesports.com/players/1643226430923_Envycopiar.png', 'mid'); +INSERT INTO public.player VALUES (22, 107559338252333149, 'Gabriel', 'Furuuti', 'Fuuu', 'http://static.lolesports.com/players/1643226717192_Silhueta.png', 'mid'); +INSERT INTO public.player VALUES (23, 105397181199735591, 'Lucas', 'Fensterseifer', 'Netuno', 'http://static.lolesports.com/players/1644095521735_Netunocopiar.png', 'bottom'); +INSERT INTO public.player VALUES (24, 98767975947296513, 'Ygor', 'Freitas', 'RedBert', 'http://static.lolesports.com/players/1643226527904_Redbertcopiar.png', 'support'); +INSERT INTO public.player VALUES (25, 100754278890207800, 'Geonyeong', 'Mun', 'Steal', 'http://static.lolesports.com/players/1644905307225_dfm_steal.png', 'jungle'); +INSERT INTO public.player VALUES (26, 99566404536983507, 'Chanju', 'Lee', 'Yaharong', 'http://static.lolesports.com/players/1644905328869_dfm_yaharong.png', 'mid'); +INSERT INTO public.player VALUES (27, 104016425624023728, 'Jiyoong', 'Lee', 'Harp', 'http://static.lolesports.com/players/1644905257358_dfm_harp.png', 'support'); +INSERT INTO public.player VALUES (28, 98767991750309549, 'Danil', 'Reshetnikov', 'Diamondprox', 'http://static.lolesports.com/players/Diamondproxcopy.png', 'jungle'); +INSERT INTO public.player VALUES (29, 105700748891875072, 'Nikita ', 'Gudkov', 'Griffon ', 'http://static.lolesports.com/players/1642071116433_placeholder.png', 'mid'); +INSERT INTO public.player VALUES (30, 105700946934214905, 'YEVHEN', 'ZAVALNYI', 'Mytant', 'http://static.lolesports.com/players/1642071138150_placeholder.png', 'bottom'); +INSERT INTO public.player VALUES (31, 98767991755955790, 'Eduard', 'Abgaryan', 'Edward', 'https://lolstatic-a.akamaihd.net/esports-assets/production/player/gosu-pepper-88anxcql.png', 'support'); +INSERT INTO public.player VALUES (32, 106301600611225723, 'Mark', 'Leksin', 'Dreampull', 'http://static.lolesports.com/players/placeholder.jpg', 'top'); +INSERT INTO public.player VALUES (33, 107721938219680332, 'Azamat', 'Atkanov', 'TESLA', 'http://static.lolesports.com/players/1643706327509_placeholder.png', 'support'); +INSERT INTO public.player VALUES (34, 100725844988653773, 'Su', 'Heo', 'ShowMaker', 'http://static.lolesports.com/players/1642153659258_DK_ShowMaker_F.png', 'mid'); +INSERT INTO public.player VALUES (35, 102483272156027229, 'Daegil', 'Seo', 'deokdam', 'http://static.lolesports.com/players/1642153629340_DK_deokdam_F.png', 'bottom'); +INSERT INTO public.player VALUES (36, 101388913291808185, 'Hyeonggyu', 'Kim', 'Kellin', 'http://static.lolesports.com/players/1642153649009_DK_Kellin_F.png', 'support'); +INSERT INTO public.player VALUES (37, 105705431649727017, 'Taeyoon', 'Noh', 'Burdol', 'http://static.lolesports.com/players/1642153598672_DK_Burdol_F.png', 'top'); +INSERT INTO public.player VALUES (38, 103729432252832975, 'Yongho', 'Yoon', 'Hoya', 'http://static.lolesports.com/players/1642153639500_DK_Hoya_F.png', 'top'); +INSERT INTO public.player VALUES (39, 105320703008048707, 'Dongbum', 'Kim', 'Croco', 'http://static.lolesports.com/players/1642154712531_LSB_Croco_R.png', 'jungle'); +INSERT INTO public.player VALUES (40, 105501829364113001, 'Hobin', 'Jeon', 'Howling', 'http://static.lolesports.com/players/1642154731703_LSB_Howling_F.png', 'top'); +INSERT INTO public.player VALUES (41, 104284310661848687, 'Juhyeon', 'Lee', 'Clozer', 'http://static.lolesports.com/players/1642154706000_LSB_Clozer_R.png', 'mid'); +INSERT INTO public.player VALUES (42, 100725844996918206, 'Jaeyeon', 'Kim', 'Dove', 'http://static.lolesports.com/players/1642154719503_LSB_Dove_R.png', 'top'); +INSERT INTO public.player VALUES (43, 105530583598805234, 'Myeongjun', 'Lee', 'Envyy', 'http://static.lolesports.com/players/1642154726047_LSB_Envyy_F.png', 'bottom'); +INSERT INTO public.player VALUES (44, 105530584812980593, 'Jinhong', 'Kim', 'Kael', 'http://static.lolesports.com/players/1642154745002_LSB_Kael_F.png', 'support'); +INSERT INTO public.player VALUES (45, 105501834624360050, 'Sanghoon', 'Yoon', 'Ice', 'http://static.lolesports.com/players/1642154738262_LSB_Ice_F.png', 'bottom'); +INSERT INTO public.player VALUES (46, 99322214647978964, 'Daniele', 'di Mauro', 'Jiizuke', 'http://static.lolesports.com/players/eg-jiizuke-2021.png', 'mid'); +INSERT INTO public.player VALUES (47, 100787602257283436, 'Minh Loc', 'Pham', 'Zeros', 'https://lolstatic-a.akamaihd.net/esports-assets/production/player/zeros-4keddu17.png', 'top'); +INSERT INTO public.player VALUES (48, 104327502738107767, 'Nicolás', 'Rivero', 'Kiefer', 'http://static.lolesports.com/players/1643047365591_Kiefer-2.png', 'mid'); +INSERT INTO public.player VALUES (49, 102179902322952953, 'Manuel', 'Scala', 'Pancake', 'http://static.lolesports.com/players/1643047550782_Pancake-5.png', 'bottom'); +INSERT INTO public.player VALUES (50, 105516185566739968, 'Cristóbal', 'Arróspide', 'Zothve', 'http://static.lolesports.com/players/1643047287141_Zothve-9.png', 'top'); +INSERT INTO public.player VALUES (51, 99871352196477603, 'Gwanghyeop', 'Kim', 'Hoglet', 'http://static.lolesports.com/players/1643047312405_Hoglet-8.png', 'jungle'); +INSERT INTO public.player VALUES (52, 99871352193690418, 'Changhun', 'Han', 'Luci', 'http://static.lolesports.com/players/1643047438703_Luci-5.png', 'support'); +INSERT INTO public.player VALUES (53, 107635899693202699, 'Thomas', 'Garnsworthy', 'Tronthepom', 'https://static.lolesports.com/players/download.png', 'top'); +INSERT INTO public.player VALUES (54, 107635905118503535, 'James', 'Craig', 'Voice', 'https://static.lolesports.com/players/download.png', 'bottom'); +INSERT INTO public.player VALUES (55, 107635907168238086, 'Rocco', 'Potter', 'rocco521', 'https://static.lolesports.com/players/download.png', 'support'); +INSERT INTO public.player VALUES (56, 107635918452357647, 'Reuben', 'Best', 'Reufury', 'https://static.lolesports.com/players/download.png', 'mid'); +INSERT INTO public.player VALUES (57, 107647480732814180, 'Bryce', 'Zhou', 'Meifan', 'https://static.lolesports.com/players/download.png', 'jungle'); +INSERT INTO public.player VALUES (58, 107657801460158111, 'Benny', 'Nguyen', 'District 1', 'https://static.lolesports.com/players/download.png', 'jungle'); +INSERT INTO public.player VALUES (59, 105709372540742118, 'Blake', 'Schlage', 'Azus', 'http://static.lolesports.com/players/silhouette.png', 'top'); +INSERT INTO public.player VALUES (60, 106350759376304634, 'Shao', 'Zhong', 'Akano', 'https://static.lolesports.com/players/download.png', 'jungle'); +INSERT INTO public.player VALUES (61, 107634941727734818, 'Jeremy', 'Lim', 'foreigner', 'https://static.lolesports.com/players/download.png', 'jungle'); +INSERT INTO public.player VALUES (62, 105709381466108761, 'Reuben', 'Salb', 'Piglet', 'http://static.lolesports.com/players/silhouette.png', 'bottom'); +INSERT INTO public.player VALUES (63, 105747861836427633, 'Yi', 'Chen', 'Thomas Shen', 'https://static.lolesports.com/players/download.png', 'bottom'); +INSERT INTO public.player VALUES (64, 107657786356796634, 'Robert', 'Wells', 'Tyran', 'https://static.lolesports.com/players/download.png', 'top'); +INSERT INTO public.player VALUES (65, 107657790493529410, 'Da Woon', 'Jeung', 'DaJeung', 'https://static.lolesports.com/players/download.png', 'mid'); +INSERT INTO public.player VALUES (66, 107657793079479518, 'Rhett', 'Wiggins', 'Vxpir', 'https://static.lolesports.com/players/download.png', 'support'); +INSERT INTO public.player VALUES (67, 107698225510856278, 'Benson', 'Tsai', 'Entrust', 'https://static.lolesports.com/players/download.png', 'support'); +INSERT INTO public.player VALUES (68, 103525219435043049, 'Lachlan', 'Keene-O''Keefe', 'N0body', 'https://lolstatic-a.akamaihd.net/esports-assets/production/player/n0body-einjqvyk.png', 'top'); +INSERT INTO public.player VALUES (69, 101389749294612370, 'Janik', 'Bartels', 'Jenax', 'http://static.lolesports.com/players/1642003381408_jenax.png', 'top'); +INSERT INTO public.player VALUES (70, 101383793865143549, 'Erik', 'Wessén', 'Treatz', 'http://static.lolesports.com/players/1642003495533_treatz.png', 'support'); +INSERT INTO public.player VALUES (71, 101389737455173027, 'Daniyal ', 'Gamani', 'Sertuss', 'http://static.lolesports.com/players/1642003453914_sertuss.png', 'mid'); +INSERT INTO public.player VALUES (72, 99322214588927915, 'Erberk ', 'Demir', 'Gilius', 'http://static.lolesports.com/players/1642003341615_gilius.png', 'jungle'); +INSERT INTO public.player VALUES (73, 99322214668103078, 'Matti', 'Sormunen', 'WhiteKnight', 'http://static.lolesports.com/players/1642003243059_white-knight.png', 'top'); +INSERT INTO public.player VALUES (74, 100312190807221865, 'Nikolay ', 'Akatov', 'Zanzarah', 'http://static.lolesports.com/players/1642003282324_zanzarah.png', 'jungle'); +INSERT INTO public.player VALUES (75, 99322214243134013, 'Hampus ', 'Abrahamsson', 'promisq', 'http://static.lolesports.com/players/1642003205916_promisq.png', 'support'); +INSERT INTO public.player VALUES (76, 99322214620375780, 'Kasper', 'Kobberup', 'Kobbe', 'http://static.lolesports.com/players/1642003168563_kobbe.png', 'bottom'); +INSERT INTO public.player VALUES (77, 99322214238585389, 'Patrik', 'Jiru', 'Patrik', 'http://static.lolesports.com/players/1642004060212_patrik.png', 'bottom'); +INSERT INTO public.player VALUES (78, 105519722481834694, 'Mark', 'van Woensel', 'Markoon', 'http://static.lolesports.com/players/1642003998089_markoon.png', 'jungle'); +INSERT INTO public.player VALUES (79, 105519724699493915, 'Hendrik', 'Reijenga', 'Advienne', 'http://static.lolesports.com/players/1642003935782_advienne.png', 'support'); +INSERT INTO public.player VALUES (80, 99322214616775017, 'Erlend', 'Holm', 'Nukeduck', 'http://static.lolesports.com/players/1642004031937_nukeduck.png', 'mid'); +INSERT INTO public.player VALUES (81, 101389713973624205, 'Finn', 'Wiestål', 'Finn', 'http://static.lolesports.com/players/1642003970167_finn.png', 'top'); +INSERT INTO public.player VALUES (82, 99322214629661297, 'Mihael', 'Mehle', 'Mikyx', 'http://static.lolesports.com/players/G2_MIKYX2021_summer.png', 'support'); +INSERT INTO public.player VALUES (83, 100482247959137902, 'Emil', 'Larsson', 'Larssen', 'http://static.lolesports.com/players/1642003206398_larssen.png', 'mid'); +INSERT INTO public.player VALUES (84, 99322214598412197, 'Andrei', 'Pascu', 'Odoamne', 'http://static.lolesports.com/players/1642003264169_odoamne.png', 'top'); +INSERT INTO public.player VALUES (85, 102181528883745160, 'Adrian', 'Trybus', 'Trymbi', 'http://static.lolesports.com/players/1642003301461_trymbi.png', 'support'); +INSERT INTO public.player VALUES (86, 99566406053904433, 'Geun-seong', 'Kim', 'Malrang', 'http://static.lolesports.com/players/1642003233110_malrang.png', 'jungle'); +INSERT INTO public.player VALUES (87, 103536921420956640, 'Markos', 'Stamkopoulos', 'Comp', 'http://static.lolesports.com/players/1642003175488_comp.png', 'bottom'); +INSERT INTO public.player VALUES (88, 101388912808637770, 'Hanxi', 'Xia', 'Chelizi', 'http://static.lolesports.com/players/1593128001829_silhouette.png', 'top'); +INSERT INTO public.player VALUES (89, 105516474039500339, 'Fei-Yang', 'Luo', 'Captain', 'http://static.lolesports.com/players/silhouette.png', 'mid'); +INSERT INTO public.player VALUES (90, 106368709696011395, 'Seung Min', 'Han', 'Patch', 'http://static.lolesports.com/players/silhouette.png', 'support'); +INSERT INTO public.player VALUES (91, 107597376599119596, 'HAOTIAN', 'BI', 'yaoyao', 'http://static.lolesports.com/players/1641805668544_placeholder.png', 'support'); +INSERT INTO public.player VALUES (92, 101388912811586896, 'Zhilin', 'Su', 'Southwind', 'http://static.lolesports.com/players/1593129903866_ig-southwind-web.png', 'support'); +INSERT INTO public.player VALUES (93, 101388912810603854, 'Wang', 'Ding', 'Puff', 'http://static.lolesports.com/players/1593129891452_ig-puff-web.png', 'bottom'); +INSERT INTO public.player VALUES (94, 104287371427354335, 'Zhi-Peng', 'Tian', 'New', 'http://static.lolesports.com/players/1593132511529_rng-new-web.png', 'top'); +INSERT INTO public.player VALUES (95, 107597380474228562, 'WANG', 'XIN', 'frigid', 'http://static.lolesports.com/players/1641805726386_placeholder.png', 'jungle'); +INSERT INTO public.player VALUES (96, 104287365097341858, 'Peng', 'Guo', 'ppgod', 'http://static.lolesports.com/players/1593135580022_v5-ppgod-web.png', 'support'); +INSERT INTO public.player VALUES (97, 103478281359738222, 'Qi-Shen ', 'Ying', 'Photic', 'https://lolstatic-a.akamaihd.net/esports-assets/production/player/photic-k1ttlyxh.png', 'bottom'); +INSERT INTO public.player VALUES (98, 103478281402167891, 'Xiao-Long ', 'Li', 'XLB', 'http://static.lolesports.com/players/1593132528126_rng-xlb-web.png', 'jungle'); +INSERT INTO public.player VALUES (99, 102186438403674539, 'Jaewon', 'Lee', 'Rich', 'http://static.lolesports.com/players/ns-rich.png', 'top'); +INSERT INTO public.player VALUES (100, 99124844346233375, 'Onur', 'Ünalan', 'Zergsting', 'http://static.lolesports.com/players/1633542837856_gs-zergsting-w21.png', 'support'); + + +-- Values for team table +INSERT INTO public.team VALUES (1, 100205573495116443, 'geng', 'Gen.G', 'GEN', 'http://static.lolesports.com/teams/1631819490111_geng-2021-worlds.png', 'http://static.lolesports.com/teams/1592589327624_Gen.GGEN-03-FullonLight.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/geng-bnm75bf5.png', 34); +INSERT INTO public.team VALUES (2, 100205573496804586, 'hanwha-life-esports', 'Hanwha Life Esports', 'HLE', 'http://static.lolesports.com/teams/1631819564399_hle-2021-worlds.png', 'http://static.lolesports.com/teams/hle-2021-color-on-light2.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/hanwha-life-esports-7kh5kjdc.png', 34); +INSERT INTO public.team VALUES (3, 100205576307813373, 'flamengo-esports', 'Flamengo Esports', 'FLA', 'http://static.lolesports.com/teams/1642953977323_Monograma_Branco-Vermelho.png', 'http://static.lolesports.com/teams/1642953977326_Monograma_Branco-Vermelho.png', NULL, 37); +INSERT INTO public.team VALUES (4, 100205576309502431, 'furia', 'FURIA', 'FUR', 'http://static.lolesports.com/teams/FURIA---black.png', 'http://static.lolesports.com/teams/FURIA---black.png', 'http://static.lolesports.com/teams/FuriaUppercutFUR.png', 37); +INSERT INTO public.team VALUES (5, 100285330168091787, 'detonation-focusme', 'DetonatioN FocusMe', 'DFM', 'http://static.lolesports.com/teams/1631820630246_dfm-2021-worlds.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/detonation-focusme-ajvyc8cy.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/detonation-focusme-4pgp383l.png', 40); +INSERT INTO public.team VALUES (6, 100289931264192378, 'team-spirit', 'Team Spirit', 'TSPT', 'http://static.lolesports.com/teams/1643720491696_Whitelogo.png', 'http://static.lolesports.com/teams/1643720491697_Blacklogo.png', NULL, 41); +INSERT INTO public.team VALUES (7, 100725845018863243, 'dwg-kia', 'DWG KIA', 'DK', 'http://static.lolesports.com/teams/1631819456274_dwg-kia-2021-worlds.png', 'http://static.lolesports.com/teams/DK-FullonLight.png', 'http://static.lolesports.com/teams/DamwonGamingDWG.png', 34); +INSERT INTO public.team VALUES (8, 100725845022060229, 'liiv-sandbox', 'Liiv SANDBOX', 'LSB', 'http://static.lolesports.com/teams/liiv-sandbox-new.png', 'http://static.lolesports.com/teams/liiv-sandbox-new.png', NULL, 34); +INSERT INTO public.team VALUES (9, 101157821444002947, 'nexus-blitz-pro-a', 'Nexus Blitz Blue', 'NXB', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/nexus-blitz-pro-a-esrcx58b.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/nexus-blitz-pro-a-3w3j1cwx.png', NULL, 31); +INSERT INTO public.team VALUES (10, 101157821447017610, 'nexus-blitz-pro-b', 'Nexus Blitz Red', 'NXR', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/nexus-blitz-pro-b-j6s80wmi.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/nexus-blitz-pro-b-kjtp467.png', NULL, 31); +INSERT INTO public.team VALUES (11, 101383792559569368, 'all-knights', 'All Knights', 'AK', 'http://static.lolesports.com/teams/AK-Black-BG.png', 'http://static.lolesports.com/teams/AK-White-BG.png', NULL, 3); +INSERT INTO public.team VALUES (12, 101383792887446028, 'mammoth', 'MAMMOTH', 'MEC', 'http://static.lolesports.com/teams/1643079304055_RedMammothIcon.png', 'http://static.lolesports.com/teams/1643079304062_RedMammothIcon.png', NULL, 16); +INSERT INTO public.team VALUES (13, 101383792891050518, 'gravitas', 'Gravitas', 'GRV', 'http://static.lolesports.com/teams/gravitas-logo.png', 'http://static.lolesports.com/teams/gravitas-logo.png', NULL, 16); +INSERT INTO public.team VALUES (14, 101383793567806688, 'sk-gaming', 'SK Gaming', 'SK', 'http://static.lolesports.com/teams/1643979272144_SK_Monochrome.png', 'http://static.lolesports.com/teams/1643979272151_SK_Monochrome.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/sk-gaming-2cd63tzz.png', 33); +INSERT INTO public.team VALUES (15, 101383793569248484, 'astralis', 'Astralis', 'AST', 'http://static.lolesports.com/teams/AST-FullonDark.png', 'http://static.lolesports.com/teams/AST-FullonLight.png', 'http://static.lolesports.com/teams/AstralisAST.png', 33); +INSERT INTO public.team VALUES (16, 101383793572656373, 'excel', 'EXCEL', 'XL', 'http://static.lolesports.com/teams/Excel_FullColor2.png', 'http://static.lolesports.com/teams/Excel_FullColor1.png', 'http://static.lolesports.com/teams/ExcelXL.png', 33); +INSERT INTO public.team VALUES (17, 101383793574360315, 'rogue', 'Rogue', 'RGE', 'http://static.lolesports.com/teams/1631819715136_rge-2021-worlds.png', NULL, 'http://static.lolesports.com/teams/1632941190948_RGE.png', 33); +INSERT INTO public.team VALUES (18, 101388912911039804, 'thunder-talk-gaming', 'Thunder Talk Gaming', 'TT', 'http://static.lolesports.com/teams/TT-FullonDark.png', 'http://static.lolesports.com/teams/TT-FullonLight.png', 'http://static.lolesports.com/teams/TTTT.png', 35); +INSERT INTO public.team VALUES (19, 101388912914513220, 'victory-five', 'Victory Five', 'V5', 'http://static.lolesports.com/teams/1592592149333_VictoryFiveV5-01-FullonDark.png', 'http://static.lolesports.com/teams/1592592149336_VictoryFiveV5-03-FullonLight.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/victory-five-ha9mq1rv.png', 35); +INSERT INTO public.team VALUES (20, 101422616509070746, 'galatasaray-espor', 'Galatasaray Espor', 'GS', 'http://static.lolesports.com/teams/1631820533570_galatasaray-2021-worlds.png', 'http://static.lolesports.com/teams/1631820533572_galatasaray-2021-worlds.png', 'http://static.lolesports.com/teams/1632941006301_GalatasarayGS.png', 39); +INSERT INTO public.team VALUES (21, 101428372598668846, 'burning-core', 'Burning Core', 'BC', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/burning-core-7q0431w1.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/burning-core-8a63k0iu.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/burning-core-fnmfa2td.png', 40); +INSERT INTO public.team VALUES (22, 101428372600307248, 'rascal-jester', 'Rascal Jester', 'RJ', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/rascal-jester-e0g6cud0.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/rascal-jester-g32ay08v.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/rascal-jester-guqjh8kb.png', 40); +INSERT INTO public.team VALUES (23, 101428372602011186, 'v3-esports', 'V3 Esports', 'V3', 'http://static.lolesports.com/teams/v3_500x500.png', 'http://static.lolesports.com/teams/v3_500x500.png', NULL, 40); +INSERT INTO public.team VALUES (24, 101428372603715124, 'crest-gaming-act', 'Crest Gaming Act', 'CGA', 'http://static.lolesports.com/teams/1630058341510_cga_512px.png', 'http://static.lolesports.com/teams/1630058341513_cga_512px.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/crest-gaming-act-7pkgpqa.png', 40); +INSERT INTO public.team VALUES (25, 101428372605353526, 'sengoku-gaming', 'Sengoku Gaming', 'SG', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/sengoku-gaming-ikyxjlfn.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/sengoku-gaming-gnat0l9c.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/sengoku-gaming-3rd8ifie.png', 40); +INSERT INTO public.team VALUES (26, 101428372607057464, 'axiz', 'AXIZ', 'AXZ', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/axiz-frilmkic.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/axiz-fpemv4d2.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/axiz-9hiwgh3l.png', 40); +INSERT INTO public.team VALUES (27, 101428372830010965, 'alpha-esports', 'Alpha Esports', 'ALF', 'http://static.lolesports.com/teams/1592588479686_AlphaEsportsALF-01-FullonDark.png', 'http://static.lolesports.com/teams/1592588479688_AlphaEsportsALF-03-FullonLight.png', NULL, 4); +INSERT INTO public.team VALUES (28, 101978171843206569, 'vega-squadron', 'Vega Squadron', 'VEG', 'http://static.lolesports.com/teams/vega.png', 'http://static.lolesports.com/teams/vega.png', NULL, 41); +INSERT INTO public.team VALUES (29, 102141671181705193, 'michigan-state-university', 'Michigan State University', 'MSU', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/michigan-state-university-au4vndaf.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/michigan-state-university-c5mv9du0.png', NULL, NULL); +INSERT INTO public.team VALUES (30, 102141671182557163, 'university-of-illinois', 'University of Illinois', 'UI', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/university-of-illinois-bwvscsri.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/university-of-illinois-b3jros5r.png', NULL, NULL); +INSERT INTO public.team VALUES (31, 102141671183409133, 'maryville-university', 'Maryville University', 'MU', 'http://static.lolesports.com/teams/1647541915472_200x200_MU_Logo.png', 'http://static.lolesports.com/teams/1647541915475_200x200_MU_Logo.png', NULL, 28); +INSERT INTO public.team VALUES (32, 102141671185047537, 'uci-esports', 'UCI Esports', 'UCI', 'http://static.lolesports.com/teams/1641604280633_UCI.png', 'http://static.lolesports.com/teams/1641548061305_LOLESPORTSICON.png', NULL, NULL); +INSERT INTO public.team VALUES (33, 102141671185899507, 'university-of-western-ontario', 'University of Western Ontario', 'UWO', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/university-of-western-ontario-9q0nn3lw.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/university-of-western-ontario-6csb5dft.png', NULL, NULL); +INSERT INTO public.team VALUES (34, 102141671186685941, 'university-of-waterloo', 'University of Waterloo', 'UW', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/university-of-waterloo-2wuni11l.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/university-of-waterloo-aghmypqf.png', NULL, NULL); +INSERT INTO public.team VALUES (35, 102141671187668983, 'nc-state-university', 'NC State University', 'NCSU', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/nc-state-university-it42b898.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/nc-state-university-6ey19n1w.png', NULL, NULL); +INSERT INTO public.team VALUES (36, 102235771678061291, 'fastpay-wildcats', 'fastPay Wildcats', 'IW', 'http://static.lolesports.com/teams/fastpay-wildcats.png', 'http://static.lolesports.com/teams/fastpay-wildcats.png', NULL, 39); +INSERT INTO public.team VALUES (37, 102747101565183056, 'nongshim-redforce', 'NongShim REDFORCE', 'NS', 'http://static.lolesports.com/teams/NSFullonDark.png', 'http://static.lolesports.com/teams/NSFullonLight.png', 'http://static.lolesports.com/teams/NongshimRedForceNS.png', 34); +INSERT INTO public.team VALUES (38, 102787200120306562, 'mousesports', 'Mousesports', 'MOUZ', 'http://static.lolesports.com/teams/1639486346996_PRM_MOUZ-FullColorDarkBG.png', 'http://static.lolesports.com/teams/1639486346999_PRM_MOUZ-FullColorDarkBG.png', NULL, NULL); +INSERT INTO public.team VALUES (39, 102787200124959636, 'crvena-zvezda-esports', 'Crvena Zvezda Esports', 'CZV', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/crvena-zvezda-esports-ddtlzzhd.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/crvena-zvezda-esports-ddtlzzhd.png', NULL, 1); +INSERT INTO public.team VALUES (40, 102787200126663579, 'giants', 'Giants', 'GIA', 'http://static.lolesports.com/teams/1641412992057_escudowhite.png', 'http://static.lolesports.com/teams/1641412992058_escudo_black.png', NULL, NULL); +INSERT INTO public.team VALUES (41, 102787200129022886, 'esuba', 'eSuba', 'ESB', 'http://static.lolesports.com/teams/1629209489523_esuba_full_pos.png', 'http://static.lolesports.com/teams/1629209489525_esuba_full_pos.png', NULL, NULL); +INSERT INTO public.team VALUES (42, 102787200130988976, 'asus-rog-elite', 'ASUS ROG Elite', 'ASUS', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/asus-rog-elite-iouou6l.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/asus-rog-elite-cz4z103n.png', NULL, NULL); +INSERT INTO public.team VALUES (43, 102787200132955066, 'for-the-win-esports', 'For The Win Esports', 'FTW', 'http://static.lolesports.com/teams/LPLOL_FTW-Logo1.png', 'http://static.lolesports.com/teams/LPLOL_FTW-Logo1.png', NULL, NULL); +INSERT INTO public.team VALUES (44, 102787200134790084, 'hma-fnatic-rising', 'HMA Fnatic Rising', 'FNCR', 'http://static.lolesports.com/teams/NLC_FNCR-logo.png', 'http://static.lolesports.com/teams/NLC_FNCR-logo.png', NULL, NULL); +INSERT INTO public.team VALUES (45, 102787200136756173, 'berlin-international-gaming', 'Berlin International Gaming', 'BIG', 'http://static.lolesports.com/teams/BIG-Logo-2020-White1.png', 'http://static.lolesports.com/teams/BIG-Logo-2020-White1.png', NULL, 7); +INSERT INTO public.team VALUES (46, 102787200138722262, 'devilsone', 'Devils.One', 'DV1', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/devilsone-bfe3xkh.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/devilsone-dmj5ivct.png', NULL, 6); +INSERT INTO public.team VALUES (47, 102787200143309800, 'ensure', 'eNsure', 'EN', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/ensure-5hi6e2cg.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/ensure-fehdkert.png', NULL, 1); +INSERT INTO public.team VALUES (48, 102787200145472495, 'defusekids', 'Defusekids', 'DKI', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/defusekids-finmimok.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/defusekids-wu2z0pj.png', NULL, NULL); +INSERT INTO public.team VALUES (49, 102787200147504121, 'campus-party-sparks', 'Campus Party Sparks', 'SPK', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/campus-party-sparks-5h2d1rjh.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/campus-party-sparks-72ccff49.png', NULL, NULL); +INSERT INTO public.team VALUES (50, 102787200149928963, 'we-love-gaming', 'We Love Gaming', 'WLG', 'http://static.lolesports.com/teams/WLGlogo.png', 'http://static.lolesports.com/teams/WLGlogo.png', NULL, NULL); +INSERT INTO public.team VALUES (51, 102787200151698443, 'vitalitybee', 'Vitality.Bee', 'VITB', 'http://static.lolesports.com/teams/Vitality-logo-color-outline-rgb.png', 'http://static.lolesports.com/teams/Vitality-logo-color-outline-rgb.png', NULL, 1); +INSERT INTO public.team VALUES (52, 102787200153467923, 'bcn-squad', 'BCN Squad', 'BCN', 'http://static.lolesports.com/teams/SL_BCN-Logo_White.png', 'http://static.lolesports.com/teams/SL_BCN-Logo_Dark.png', NULL, NULL); +INSERT INTO public.team VALUES (53, 102787200155434012, 'jdxl', 'JD|XL', 'JDXL', 'http://static.lolesports.com/teams/1641489535868_jdxl.png', NULL, NULL, 9); +INSERT INTO public.team VALUES (54, 102787200157400101, 'falkn', 'FALKN', 'FKN', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/falkn-j72aqsqk.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/falkn-dhvtpixb.png', NULL, 1); +INSERT INTO public.team VALUES (55, 102787200159169580, 'godsent', 'Godsent', 'GOD', 'http://static.lolesports.com/teams/NLC_GOD-light.png', 'http://static.lolesports.com/teams/NLC_GOD-dark.png', NULL, NULL); +INSERT INTO public.team VALUES (56, 102825747701670848, 'azules-esports', 'Azules Esports', 'UCH', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/azules-esports-ak2khbqa.png', NULL, 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/azules-esports-e8yjxxki.png', NULL); +INSERT INTO public.team VALUES (57, 103461966951059521, 'evil-geniuses', 'Evil Geniuses', 'EG', 'http://static.lolesports.com/teams/1592590374862_EvilGeniusesEG-01-FullonDark.png', 'http://static.lolesports.com/teams/1592590374875_EvilGeniusesEG-03-FullonLight.png', 'http://static.lolesports.com/teams/1590003096057_EvilGeniusesEG.png', 32); +INSERT INTO public.team VALUES (58, 103461966965149786, 'mad-lions', 'MAD Lions', 'MAD', 'http://static.lolesports.com/teams/1631819614211_mad-2021-worlds.png', 'http://static.lolesports.com/teams/1592591395341_MadLionsMAD-03-FullonLight.png', 'http://static.lolesports.com/teams/MAD.png', 33); +INSERT INTO public.team VALUES (59, 103461966971048042, 'eg-academy', 'EG Academy', 'EG', 'http://static.lolesports.com/teams/1592590391188_EvilGeniusesEG-01-FullonDark.png', 'http://static.lolesports.com/teams/1592590391200_EvilGeniusesEG-03-FullonLight.png', 'http://static.lolesports.com/teams/1590003135776_EvilGeniusesEG.png', 28); +INSERT INTO public.team VALUES (60, 103461966975897718, 'imt-academy', 'IMT Academy', 'IMT', 'http://static.lolesports.com/teams/imt-new-color.png', 'http://static.lolesports.com/teams/imt-new-color.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/immortals-academy-hmxmnvhe.png', 28); +INSERT INTO public.team VALUES (61, 103461966981927044, 'dig-academy', 'DIG Academy', 'DIG', 'http://static.lolesports.com/teams/DIG-FullonDark.png', 'http://static.lolesports.com/teams/DIG-FullonLight.png', 'http://static.lolesports.com/teams/DignitasDIG.png', 28); +INSERT INTO public.team VALUES (62, 103461966986776720, 'ultra-prime', 'Ultra Prime', 'UP', 'http://static.lolesports.com/teams/ultraprime.png', 'http://static.lolesports.com/teams/ultraprime.png', NULL, 35); +INSERT INTO public.team VALUES (63, 103495716836203404, '5-ronin', '5 Ronin', '5R', 'http://static.lolesports.com/teams/5R_LOGO.png', 'http://static.lolesports.com/teams/5R_LOGO.png', NULL, 39); +INSERT INTO public.team VALUES (100, 104211666442891296, 'ogaming', 'O''Gaming', 'OGA', 'http://static.lolesports.com/teams/1590143833802_Ays7Gjmu_400x400.jpg', NULL, NULL, NULL); +INSERT INTO public.team VALUES (64, 103495716886587312, 'besiktas', 'Beşiktaş', 'BJK', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/besiktas-e-sports-club-dlw48ntu.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/besiktas-e-sports-club-6ttscu28.png', NULL, 39); +INSERT INTO public.team VALUES (65, 103535282113853330, '5-ronin-akademi', '5 Ronin Akademi', '5R', 'http://static.lolesports.com/teams/5R_LOGO.png', 'http://static.lolesports.com/teams/5R_LOGO.png', NULL, 2); +INSERT INTO public.team VALUES (66, 103535282119620510, 'fukuoka-softbank-hawks-gaming', 'Fukuoka SoftBank HAWKS gaming', 'SHG', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/fukuoka-softbank-hawks-gaming-b99n2uq2.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/fukuoka-softbank-hawks-gaming-4i3ympnq.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/fukuoka-softbank-hawks-gaming-4fl2jmuh.png', 40); +INSERT INTO public.team VALUES (67, 103535282124208038, 'pentanetgg', 'Pentanet.GG', 'PGG', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/pentanetgg-3vnqnv03.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/pentanetgg-3d4g4sbh.png', NULL, 16); +INSERT INTO public.team VALUES (68, 103535282135552642, 'papara-supermassive-blaze-akademi', 'Papara SuperMassive Blaze Akademi', 'SMB', 'http://static.lolesports.com/teams/1628521896643_SMBA_WHITE.png', 'http://static.lolesports.com/teams/1628521896646_SMBA_BLACK.png', NULL, 2); +INSERT INTO public.team VALUES (69, 103535282138043022, 'fenerbahce-espor-akademi', 'Fenerbahçe Espor Akademi', 'FB', 'http://static.lolesports.com/teams/1642680283028_BANPICK_FB.png', 'http://static.lolesports.com/teams/1642680283035_BANPICK_FB.png', NULL, 2); +INSERT INTO public.team VALUES (70, 103535282140533402, 'besiktas-akademi', 'Beşiktaş Akademi', 'BJK', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/besiktas-akademi-6dlbk21d.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/besiktas-akademi-fobrhai9.png', NULL, 2); +INSERT INTO public.team VALUES (71, 103535282143744679, 'dark-passage-akademi', 'Dark Passage Akademi', 'DP', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/dark-passage-akademi-9ehs6q0l.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/dark-passage-akademi-h4x5hq6.png', NULL, 2); +INSERT INTO public.team VALUES (72, 103535282146169523, 'info-yatrm-aurora-akademi', 'Info Yatırım Aurora Akademi', 'AUR', 'http://static.lolesports.com/teams/1642680351930_BANPICK_AUR.png', 'http://static.lolesports.com/teams/1642680351936_BANPICK_AUR.png', NULL, 2); +INSERT INTO public.team VALUES (73, 103535282148790975, 'galakticos-akademi', 'GALAKTICOS Akademi', 'GAL', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/galakticos-akademi-4x1ww2pc.png', 'https://lolstatic-a.akamaihd.net/esports-assets/production/team/galakticos-akademi-dv3kn0pg.png', NULL, 2); +INSERT INTO public.team VALUES (74, 103535282158162659, 'fastpay-wildcats-akademi', 'fastPay Wildcats Akademi', 'IW', 'http://static.lolesports.com/teams/1582880891336_IW.png', 'http://static.lolesports.com/teams/1582880891351_IW.png', NULL, 2); +INSERT INTO public.team VALUES (75, 103877554248683116, 'schalke-04-evolution', 'Schalke 04 Evolution', 'S04E', 'http://static.lolesports.com/teams/S04_Standard_Logo1.png', 'http://static.lolesports.com/teams/S04_Standard_Logo1.png', NULL, NULL); +INSERT INTO public.team VALUES (76, 103877589042434434, 'gamerlegion', 'GamerLegion', 'GL', 'http://static.lolesports.com/teams/1585046217463_220px-Team_GamerLegionlogo_square.png', NULL, NULL, 1); +INSERT INTO public.team VALUES (77, 103877625775457850, 'movistar-riders', 'Movistar Riders', 'MRS', 'http://static.lolesports.com/teams/1585046777741_220px-Movistar_Riderslogo_square.png', NULL, NULL, NULL); +INSERT INTO public.team VALUES (78, 103877675241047720, 'ldlc-ol', 'LDLC OL', 'LDLC', 'http://static.lolesports.com/teams/LFL-LDLC-logo.png', 'http://static.lolesports.com/teams/LFL-LDLC-logo.png', NULL, 1); +INSERT INTO public.team VALUES (79, 103877737868887783, 'saim-se', 'SAIM SE', 'SSB', 'http://static.lolesports.com/teams/1585048488568_220px-SAIM_SElogo_square.png', 'http://static.lolesports.com/teams/1585048488582_220px-SAIM_SElogo_square.png', NULL, NULL); +INSERT INTO public.team VALUES (80, 103877756742242918, 'racoon', 'Racoon', 'RCN', 'http://static.lolesports.com/teams/1585048776551_220px-Racoon_(Italian_Team)logo_square.png', 'http://static.lolesports.com/teams/1585048776564_220px-Racoon_(Italian_Team)logo_square.png', NULL, NULL); +INSERT INTO public.team VALUES (81, 103877774634323825, 'ydn-gamers', 'YDN Gamers', 'YDN', 'http://static.lolesports.com/teams/1587638409857_LOGO_YDN_-trasp.png', 'http://static.lolesports.com/teams/1587638409876_LOGO_YDN_-trasp.png', NULL, NULL); +INSERT INTO public.team VALUES (82, 103877879209300619, 'vipers-inc', 'Vipers Inc', 'VIP', 'http://static.lolesports.com/teams/1585050644953_220px-Vipers_Inclogo_square.png', 'http://static.lolesports.com/teams/1585050644968_220px-Vipers_Inclogo_square.png', NULL, NULL); +INSERT INTO public.team VALUES (83, 103877891572305836, 'team-singularity', 'Team Singularity', 'SNG', 'http://static.lolesports.com/teams/NLC_SNG-light.png', 'http://static.lolesports.com/teams/NLC_SNG-logo.png', NULL, 9); +INSERT INTO public.team VALUES (84, 103877908090914662, 'kenty', 'Kenty', 'KEN', 'http://static.lolesports.com/teams/1585051086000_220px-Kentylogo_square.png', 'http://static.lolesports.com/teams/1585051086014_220px-Kentylogo_square.png', NULL, NULL); +INSERT INTO public.team VALUES (85, 103877925817094140, 'pigsports', 'PIGSPORTS', 'PIG', 'http://static.lolesports.com/teams/PIGSPORTS_PIG-Logo1.png', 'http://static.lolesports.com/teams/PIGSPORTS_PIG-Logo1.png', NULL, NULL); +INSERT INTO public.team VALUES (86, 103877951616192529, 'cyber-gaming', 'Cyber Gaming', 'CG', 'http://static.lolesports.com/teams/1585051749524_220px-Cyber_Gaminglogo_square.png', 'http://static.lolesports.com/teams/1585051749529_220px-Cyber_Gaminglogo_square.png', NULL, NULL); +INSERT INTO public.team VALUES (87, 103877976717529187, 'intrepid-fox-gaming', 'Intrepid Fox Gaming', 'IF', 'http://static.lolesports.com/teams/1585052132267_220px-Intrepid_Fox_Gaminglogo_square.png', 'http://static.lolesports.com/teams/1585052132281_220px-Intrepid_Fox_Gaminglogo_square.png', NULL, NULL); +INSERT INTO public.team VALUES (88, 103878020539746273, 'egn-esports', 'EGN Esports', 'EGN', 'http://static.lolesports.com/teams/LPLOL_EGN-Logo1.png', 'http://static.lolesports.com/teams/LPLOL_EGN-Logo1.png', NULL, NULL); +INSERT INTO public.team VALUES (89, 103935421249833954, 'mad-lions-madrid', 'MAD Lions Madrid', 'MADM', 'http://static.lolesports.com/teams/SL_MADM-Logo_white.png', 'http://static.lolesports.com/teams/SL_MADM-Logo_dark.png', NULL, 5); +INSERT INTO public.team VALUES (90, 103935446548920777, 'misfits-premier', 'Misfits Premier', 'MSFP', 'http://static.lolesports.com/teams/LFL-MSFP-logo.png', 'http://static.lolesports.com/teams/LFL-MSFP-logo.png', NULL, NULL); +INSERT INTO public.team VALUES (91, 103935468920814040, 'gamersorigin', 'GamersOrigin', 'GO', 'http://static.lolesports.com/teams/1588178480033_logoGO_2020_G_Blanc.png', 'http://static.lolesports.com/teams/1588178480035_logoGO_2020_G_Noir.png', NULL, 11); +INSERT INTO public.team VALUES (92, 103935523328473675, 'k1ck-neosurf', 'K1CK Neosurf', 'K1', 'http://static.lolesports.com/teams/1585930223604_K1ck_Neosurflogo_square.png', NULL, NULL, NULL); +INSERT INTO public.team VALUES (93, 103935530333072898, 'ago-rogue', 'AGO Rogue', 'RGO', 'http://static.lolesports.com/teams/1585930330127_AGO_ROGUElogo_square.png', NULL, NULL, 1); +INSERT INTO public.team VALUES (94, 103935567188806885, 'energypot-wizards', 'Energypot Wizards', 'EWIZ', 'http://static.lolesports.com/teams/1585930892362_Energypot_Wizardslogo_square.png', NULL, NULL, NULL); +INSERT INTO public.team VALUES (95, 103935642731826448, 'sector-one', 'Sector One', 'S1', 'http://static.lolesports.com/teams/1641288621852_1024x1024_sector_one_nameless_white.png', 'http://static.lolesports.com/teams/1641288621854_1024x1024_sector_one_nameless_black.png', NULL, 19); +INSERT INTO public.team VALUES (96, 103963647433204351, 'm19', 'M19', 'M19', 'http://static.lolesports.com/teams/1586359360406_M19logo_square.png', NULL, NULL, NULL); +INSERT INTO public.team VALUES (97, 103963715924353674, 'dragon-army', 'Dragon Army', 'DA', 'http://static.lolesports.com/teams/1586360405423_440px-Dragon_Armylogo_square.png', NULL, NULL, 41); +INSERT INTO public.team VALUES (98, 103963753080578719, 'crowcrowd-moscow', 'CrowCrowd Moscow', 'CC', 'http://static.lolesports.com/teams/Logo_CC.png', NULL, NULL, 41); +INSERT INTO public.team VALUES (99, 104202382255290736, 'rensga', 'RENSGA', 'RNS', 'http://static.lolesports.com/teams/LogoRensgaEsports.png', 'http://static.lolesports.com/teams/LogoRensgaEsports.png', 'http://static.lolesports.com/teams/RensgaRNS.png', 37); + + +-- Values for tournament table +INSERT INTO public.tournament VALUES (1, 107893386210553711, 'european_masters_spring_2022_main_event', '2022-04-13', '2022-05-08', 1); +INSERT INTO public.tournament VALUES (2, 107530554766055254, 'lla_opening_2022', '2022-01-28', '2022-04-17', 3); +INSERT INTO public.tournament VALUES (3, 107693721179065689, 'pcs_2022_spring', '2022-02-11', '2022-04-18', 4); +INSERT INTO public.tournament VALUES (4, 107468241207873310, 'superliga_2022_spring', '2022-01-09', '2022-05-01', 5); +INSERT INTO public.tournament VALUES (5, 107416436272657995, 'ultraliga_2022_spring', '2022-01-01', '2022-05-01', 6); +INSERT INTO public.tournament VALUES (6, 107417741193036913, 'prime_2022_spring', '2022-01-01', '2022-05-01', 7); +INSERT INTO public.tournament VALUES (7, 107457033672415830, 'pg_spring', '2022-01-17', '2022-05-01', 8); +INSERT INTO public.tournament VALUES (8, 107417432877679361, 'nlc_2022_spring', '2022-01-01', '2022-05-15', 9); +INSERT INTO public.tournament VALUES (9, 107468370558963709, 'lfl_2022_spring', '2022-01-09', '2022-05-01', 11); +INSERT INTO public.tournament VALUES (10, 107565607659994755, 'cblol_academy_2022', '2022-01-24', '2022-04-18', 15); +INSERT INTO public.tournament VALUES (11, 107439320897210747, 'lco_spring_2022', '2022-01-23', '2022-04-29', 16); +INSERT INTO public.tournament VALUES (12, 107563481236862420, 'eslol_spring', '2022-01-16', '2022-05-01', 19); +INSERT INTO public.tournament VALUES (13, 107682708465517027, 'discover_volcano_league_opening_2022', '2022-01-25', '2022-04-16', 22); +INSERT INTO public.tournament VALUES (14, 107728324355999617, 'master_flow_league_opening_2022', '2022-01-26', '2022-04-24', 24); +INSERT INTO public.tournament VALUES (15, 107677841285321565, 'honor_league_opening_2022', '2022-01-24', '2022-04-16', 25); +INSERT INTO public.tournament VALUES (16, 107921288851375933, 'proving_grounds_spring_2022', '2022-03-16', '2022-04-16', 28); +INSERT INTO public.tournament VALUES (17, 108097587668586485, 'tft_emea_lcq_2022', '2022-04-16', '2022-04-16', 29); +INSERT INTO public.tournament VALUES (18, 107458367237283414, 'lcs_spring_2022', '2022-02-04', '2022-04-25', 32); +INSERT INTO public.tournament VALUES (19, 107417059262120466, 'lec_2022_spring', '2022-01-01', '2022-05-15', 33); +INSERT INTO public.tournament VALUES (20, 107417779630700437, 'lpl_spring_2022', '2022-01-10', '2022-05-01', 35); +INSERT INTO public.tournament VALUES (21, 107405837336179496, 'cblol_2022_split1', '2022-01-22', '2022-04-23', 37); +INSERT INTO public.tournament VALUES (22, 107417471555810057, 'lcl_spring_2022', '2022-02-11', '2022-04-16', 41); +INSERT INTO public.tournament VALUES (23, 107418086627198298, 'lcs_academy_2022_spring', '2022-01-19', '2022-05-31', 42); diff --git a/src/lib.rs b/src/lib.rs index d89f79b2..307d8b08 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,9 @@ pub mod connection { #[cfg(feature = "mssql")] pub use canyon_connection::canyon_database_connector::DatabaseConnection::SqlServer; + + #[cfg(feature = "mysql")] + pub use canyon_connection::canyon_database_connector::DatabaseConnection::MySQL; } /// Crud module serves to reexport the public elements of the `canyon_crud` crate, @@ -53,6 +56,8 @@ pub mod query { /// Reexport the available database clients within Canyon pub mod db_clients { + #[cfg(feature = "mysql")] + pub use canyon_connection::mysql_async; #[cfg(feature = "mssql")] pub use canyon_connection::tiberius; #[cfg(feature = "postgres")] diff --git a/tests/Cargo.toml b/tests/Cargo.toml index da6b0dfc..ef9ee7f0 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -14,3 +14,4 @@ path = "canyon_integration_tests.rs" [features] postgres = ["canyon_sql/postgres"] mssql = ["canyon_sql/mssql"] +mysql = ["canyon_sql/mysql"] \ No newline at end of file diff --git a/tests/canyon.toml b/tests/canyon.toml index 0b0614a4..73c0b023 100644 --- a/tests/canyon.toml +++ b/tests/canyon.toml @@ -22,3 +22,15 @@ sqlserver = { basic = { username = 'sa', password = 'SqlServer-10' } } host = 'localhost' port = 1434 db_name = 'master' + + +[[canyon_sql.datasources]] +name = 'mysql_docker' + +[canyon_sql.datasources.auth] +mysql = { basic = { username = 'root', password = 'root' } } + +[canyon_sql.datasources.properties] +host = 'localhost' +port = 3307 +db_name = 'public' \ No newline at end of file diff --git a/tests/constants.rs b/tests/constants.rs index dd3a268b..26bea3fd 100644 --- a/tests/constants.rs +++ b/tests/constants.rs @@ -4,6 +4,8 @@ pub const PSQL_DS: &str = "postgres_docker"; #[cfg(feature = "mssql")] pub const SQL_SERVER_DS: &str = "sqlserver_docker"; +#[cfg(feature = "mysql")] +pub const MYSQL_DS: &str = "mysql_docker"; #[cfg(all(feature = "postgres", feature = "migrations"))] pub static FETCH_PUBLIC_SCHEMA: &str = diff --git a/tests/crud/delete_operations.rs b/tests/crud/delete_operations.rs index 6420e553..31d1b0ef 100644 --- a/tests/crud/delete_operations.rs +++ b/tests/crud/delete_operations.rs @@ -2,10 +2,13 @@ ///! generates and executes *INSERT* statements use canyon_sql::crud::CrudOperations; +#[cfg(feature = "mysql")] +use crate::constants::MYSQL_DS; #[cfg(feature = "postgres")] use crate::constants::PSQL_DS; #[cfg(feature = "mssql")] use crate::constants::SQL_SERVER_DS; + use crate::tests_models::league::*; /// Deletes a row from the database that is mapped into some instance of a `T` entity. @@ -64,7 +67,7 @@ fn test_crud_delete_method_operation() { /// Same as the delete test, but performing the operations with the specified datasource #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_delete_datasource_method_operation() { +fn test_crud_delete_datasource_mssql_method_operation() { // For test the delete, we will insert a new instance of the database, and then, // after inspect it, we will proceed to delete it let mut new_league: League = League { @@ -107,3 +110,50 @@ fn test_crud_delete_datasource_method_operation() { None ); } + +/// Same as the delete test, but performing the operations with the specified datasource +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_delete_datasource_mysql_method_operation() { + // For test the delete, we will insert a new instance of the database, and then, + // after inspect it, we will proceed to delete it + let mut new_league: League = League { + id: Default::default(), + ext_id: 7892635306594_i64, + slug: "some-new-league".to_string(), + name: "Some New League".to_string(), + region: "Bahía de cochinos".to_string(), + image_url: "https://nobodyspectsandimage.io".to_string(), + }; + + // We insert the instance on the database, on the `League` entity + new_league + .insert_datasource(MYSQL_DS) + .await + .expect("Failed insert operation"); + assert_eq!( + new_league.id, + League::find_by_pk_datasource(&new_league.id, MYSQL_DS) + .await + .expect("Request error") + .expect("None value") + .id + ); + + // Now that we have an instance mapped to some entity by a primary key, we can now + // remove that entry from the database with the delete operation + new_league + .delete_datasource(MYSQL_DS) + .await + .expect("Failed to delete the operation"); + + // To check the success, we can query by the primary key value and check if, after unwrap() + // the result of the operation, the find by primary key contains Some(v) or None + // Remember that `find_by_primary_key(&dyn QueryParameter<'a>) -> Result>, Err> + assert_eq!( + League::find_by_pk_datasource(&new_league.id, MYSQL_DS) + .await + .expect("Unwrapping the result, letting the Option"), + None + ); +} diff --git a/tests/crud/foreign_key_operations.rs b/tests/crud/foreign_key_operations.rs index 471dd639..21cae200 100644 --- a/tests/crud/foreign_key_operations.rs +++ b/tests/crud/foreign_key_operations.rs @@ -10,8 +10,11 @@ ///! For more info: TODO -> Link to the docs of the foreign key chapter use canyon_sql::crud::CrudOperations; +#[cfg(feature = "mssql")] +use crate::constants::MYSQL_DS; #[cfg(feature = "mssql")] use crate::constants::SQL_SERVER_DS; + use crate::tests_models::league::*; use crate::tests_models::tournament::*; @@ -42,7 +45,7 @@ fn test_crud_search_by_foreign_key() { /// Same as the search by foreign key, but with the specified datasource #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_search_by_foreign_key_datasource() { +fn test_crud_search_by_foreign_key_datasource_mssql() { let some_tournament: Tournament = Tournament::find_by_pk_datasource(&10, SQL_SERVER_DS) .await .expect("Result variant of the query is err") @@ -65,6 +68,32 @@ fn test_crud_search_by_foreign_key_datasource() { } } +/// Same as the search by foreign key, but with the specified datasource +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_search_by_foreign_key_datasource_mysql() { + let some_tournament: Tournament = Tournament::find_by_pk_datasource(&10, MYSQL_DS) + .await + .expect("Result variant of the query is err") + .expect("No result found for the given parameter"); + + // We can get the parent entity for the retrieved child instance + let parent_entity: Option = some_tournament + .search_league_datasource(MYSQL_DS) + .await + .expect("Result variant of the query is err"); + + // These are tests, and we could unwrap the result contained in the option, because + // it always should exist that search for the data inserted when the docker starts. + // But, just for change the style a little bit and offer more options about how to + // handle things done with Canyon + if let Some(league) = parent_entity { + assert_eq!(some_tournament.league, league.id) + } else { + assert_eq!(parent_entity, None) + } +} + /// Given an entity `U` that is know as the "parent" side of the relation with another /// entity `T`, for example, we can ask to the parent for the childrens that belongs /// to `U`. @@ -93,7 +122,7 @@ fn test_crud_search_reverse_side_foreign_key() { /// but with the specified datasource #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_search_reverse_side_foreign_key_datasource() { +fn test_crud_search_reverse_side_foreign_key_datasource_mssql() { let some_league: League = League::find_by_pk_datasource(&1, SQL_SERVER_DS) .await .expect("Result variant of the query is err") @@ -110,3 +139,25 @@ fn test_crud_search_reverse_side_foreign_key_datasource() { .iter() .for_each(|t| assert_eq!(t.league, some_league.id)); } + +/// Same as the search by the reverse side of a foreign key relation +/// but with the specified datasource +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_search_reverse_side_foreign_key_datasource_mysql() { + let some_league: League = League::find_by_pk_datasource(&1, MYSQL_DS) + .await + .expect("Result variant of the query is err") + .expect("No result found for the given parameter"); + + // Computes how many tournaments are pointing to the retrieved league + let child_tournaments: Vec = + Tournament::search_league_childrens_datasource(&some_league, MYSQL_DS) + .await + .expect("Result variant of the query is err"); + + assert!(!child_tournaments.is_empty()); + child_tournaments + .iter() + .for_each(|t| assert_eq!(t.league, some_league.id)); +} diff --git a/tests/crud/insert_operations.rs b/tests/crud/insert_operations.rs index d52fa868..898182b6 100644 --- a/tests/crud/insert_operations.rs +++ b/tests/crud/insert_operations.rs @@ -2,8 +2,11 @@ ///! generates and executes *INSERT* statements use canyon_sql::crud::CrudOperations; +#[cfg(feature = "mysql")] +use crate::constants::MYSQL_DS; #[cfg(feature = "mssql")] use crate::constants::SQL_SERVER_DS; + use crate::tests_models::league::*; /// Inserts a new record on the database, given an entity that is @@ -58,7 +61,7 @@ fn test_crud_insert_operation() { /// the specified datasource #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_insert_datasource_operation() { +fn test_crud_insert_datasource_mssql_operation() { let mut new_league: League = League { id: Default::default(), ext_id: 7892635306594_i64, @@ -86,6 +89,38 @@ fn test_crud_insert_datasource_operation() { assert_eq!(new_league.id, inserted_league.id); } +/// Same as the insert operation above, but targeting the database defined in +/// the specified datasource +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_insert_datasource_mysql_operation() { + let mut new_league: League = League { + id: Default::default(), + ext_id: 7892635306594_i64, + slug: "some-new-league".to_string(), + name: "Some New League".to_string(), + region: "Bahía de cochinos".to_string(), + image_url: "https://nobodyspectsandimage.io".to_string(), + }; + + // We insert the instance on the database, on the `League` entity + new_league + .insert_datasource(MYSQL_DS) + .await + .expect("Failed insert datasource operation"); + + // Now, in the `id` field of the instance, we have the autogenerated + // value for the primary key field, which is id. So, we can query the + // database again with the find by primary key operation to check if + // the value was really inserted + let inserted_league = League::find_by_pk_datasource(&new_league.id, MYSQL_DS) + .await + .expect("Failed the query to the database") + .expect("No entity found for the primary key value passed in"); + + assert_eq!(new_league.id, inserted_league.id); +} + /// The multi insert operation is a shorthand for insert multiple instances of *T* /// in the database at once. /// @@ -160,7 +195,7 @@ fn test_crud_multi_insert_operation() { /// Same as the multi insert above, but with the specified datasource #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_multi_insert_datasource_operation() { +fn test_crud_multi_insert_datasource_mssql_operation() { let mut new_league_mi: League = League { id: Default::default(), ext_id: 54376478_i64, @@ -218,3 +253,65 @@ fn test_crud_multi_insert_datasource_operation() { assert_eq!(new_league_mi_2.id, inserted_league_2.id); assert_eq!(new_league_mi_3.id, inserted_league_3.id); } + +/// Same as the multi insert above, but with the specified datasource +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_multi_insert_datasource_mysql_operation() { + let mut new_league_mi: League = League { + id: Default::default(), + ext_id: 54376478_i64, + slug: "some-new-random-league".to_string(), + name: "Some New Random League".to_string(), + region: "Unknown".to_string(), + image_url: "https://what-a-league.io".to_string(), + }; + let mut new_league_mi_2: League = League { + id: Default::default(), + ext_id: 3475689769678906_i64, + slug: "new-league-2".to_string(), + name: "New League 2".to_string(), + region: "Really unknown".to_string(), + image_url: "https://what-an-unknown-league.io".to_string(), + }; + let mut new_league_mi_3: League = League { + id: Default::default(), + ext_id: 46756867_i64, + slug: "a-new-multinsert".to_string(), + name: "New League 3".to_string(), + region: "The dark side of the moon".to_string(), + image_url: "https://interplanetary-league.io".to_string(), + }; + + // Insert the instance as database entities + new_league_mi + .insert_datasource(MYSQL_DS) + .await + .expect("Failed insert datasource operation"); + new_league_mi_2 + .insert_datasource(MYSQL_DS) + .await + .expect("Failed insert datasource operation"); + new_league_mi_3 + .insert_datasource(MYSQL_DS) + .await + .expect("Failed insert datasource operation"); + + // Recover the inserted data by primary key + let inserted_league = League::find_by_pk_datasource(&new_league_mi.id, MYSQL_DS) + .await + .expect("[1] - Failed the query to the database") + .expect("[1] - No entity found for the primary key value passed in"); + let inserted_league_2 = League::find_by_pk_datasource(&new_league_mi_2.id, MYSQL_DS) + .await + .expect("[2] - Failed the query to the database") + .expect("[2] - No entity found for the primary key value passed in"); + let inserted_league_3 = League::find_by_pk_datasource(&new_league_mi_3.id, MYSQL_DS) + .await + .expect("[3] - Failed the query to the database") + .expect("[3] - No entity found for the primary key value passed in"); + + assert_eq!(new_league_mi.id, inserted_league.id); + assert_eq!(new_league_mi_2.id, inserted_league_2.id); + assert_eq!(new_league_mi_3.id, inserted_league_3.id); +} diff --git a/tests/crud/querybuilder_operations.rs b/tests/crud/querybuilder_operations.rs index 4bc205f6..f4d03f38 100644 --- a/tests/crud/querybuilder_operations.rs +++ b/tests/crud/querybuilder_operations.rs @@ -1,3 +1,8 @@ +#[cfg(feature = "mysql")] +use crate::constants::MYSQL_DS; +#[cfg(feature = "mssql")] +use crate::constants::SQL_SERVER_DS; + ///! Tests for the QueryBuilder available operations within Canyon. /// ///! QueryBuilder are the way of obtain more flexibility that with @@ -9,10 +14,7 @@ use canyon_sql::{ query::{operators::Comp, operators::Like, ops::QueryBuilder}, }; -#[cfg(feature = "mssql")] -use crate::constants::SQL_SERVER_DS; use crate::tests_models::league::*; -#[cfg(feature = "mssql")] use crate::tests_models::player::*; use crate::tests_models::tournament::*; @@ -78,7 +80,7 @@ fn test_crud_find_with_querybuilder_and_fulllike() { /// with the parameters that modifies the base SQL to SELECT * FROM #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_find_with_querybuilder_and_fulllike_datasource() { +fn test_crud_find_with_querybuilder_and_fulllike_datasource_mssql() { // Find all the leagues with "LC" in their name let mut filtered_leagues_result = League::select_query_datasource(SQL_SERVER_DS); filtered_leagues_result.r#where(LeagueFieldValue::name(&"LC"), Like::Full); @@ -89,6 +91,21 @@ fn test_crud_find_with_querybuilder_and_fulllike_datasource() { ) } +/// Builds a new SQL statement for retrieves entities of the `T` type, filtered +/// with the parameters that modifies the base SQL to SELECT * FROM +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_find_with_querybuilder_and_fulllike_datasource_mysql() { + // Find all the leagues with "LC" in their name + let mut filtered_leagues_result = League::select_query_datasource(MYSQL_DS); + filtered_leagues_result.r#where(LeagueFieldValue::name(&"LC"), Like::Full); + + assert_eq!( + filtered_leagues_result.read_sql(), + "SELECT * FROM league WHERE name LIKE CONCAT('%', CAST($1 AS CHAR) ,'%')" + ) +} + /// Builds a new SQL statement for retrieves entities of the `T` type, filtered /// with the parameters that modifies the base SQL to SELECT * FROM #[cfg(feature = "postgres")] @@ -108,7 +125,7 @@ fn test_crud_find_with_querybuilder_and_leftlike() { /// with the parameters that modifies the base SQL to SELECT * FROM #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_find_with_querybuilder_and_leftlike_datasource() { +fn test_crud_find_with_querybuilder_and_leftlike_datasource_mssql() { // Find all the leagues whose name ends with "CK" let mut filtered_leagues_result = League::select_query(); filtered_leagues_result.r#where(LeagueFieldValue::name(&"CK"), Like::Left); @@ -119,6 +136,21 @@ fn test_crud_find_with_querybuilder_and_leftlike_datasource() { ) } +/// Builds a new SQL statement for retrieves entities of the `T` type, filtered +/// with the parameters that modifies the base SQL to SELECT * FROM +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_find_with_querybuilder_and_leftlike_datasource_mysql() { + // Find all the leagues whose name ends with "CK" + let mut filtered_leagues_result = League::select_query_datasource(MYSQL_DS); + filtered_leagues_result.r#where(LeagueFieldValue::name(&"CK"), Like::Left); + + assert_eq!( + filtered_leagues_result.read_sql(), + "SELECT * FROM league WHERE name LIKE CONCAT('%', CAST($1 AS CHAR))" + ) +} + /// Builds a new SQL statement for retrieves entities of the `T` type, filtered /// with the parameters that modifies the base SQL to SELECT * FROM #[cfg(feature = "postgres")] @@ -138,7 +170,7 @@ fn test_crud_find_with_querybuilder_and_rightlike() { /// with the parameters that modifies the base SQL to SELECT * FROM #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_find_with_querybuilder_and_rightlike_datasource() { +fn test_crud_find_with_querybuilder_and_rightlike_datasource_mssql() { // Find all the leagues whose name starts with "LC" let mut filtered_leagues_result = League::select_query_datasource(SQL_SERVER_DS); filtered_leagues_result.r#where(LeagueFieldValue::name(&"LC"), Like::Right); @@ -148,11 +180,25 @@ fn test_crud_find_with_querybuilder_and_rightlike_datasource() { "SELECT * FROM league WHERE name LIKE CONCAT(CAST($1 AS VARCHAR) ,'%')" ) } +/// Builds a new SQL statement for retrieves entities of the `T` type, filtered +/// with the parameters that modifies the base SQL to SELECT * FROM +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_find_with_querybuilder_and_rightlike_datasource_mysql() { + // Find all the leagues whose name starts with "LC" + let mut filtered_leagues_result = League::select_query_datasource(MYSQL_DS); + filtered_leagues_result.r#where(LeagueFieldValue::name(&"LC"), Like::Right); + + assert_eq!( + filtered_leagues_result.read_sql(), + "SELECT * FROM league WHERE name LIKE CONCAT(CAST($1 AS CHAR) ,'%')" + ) +} /// Same than the above but with the specified datasource #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_find_with_querybuilder_datasource() { +fn test_crud_find_with_querybuilder_datasource_mssql() { // Find all the players where its ID column value is greater that 50 let filtered_find_players = Player::select_query_datasource(SQL_SERVER_DS) .r#where(PlayerFieldValue::id(&50), Comp::Gt) @@ -162,6 +208,19 @@ fn test_crud_find_with_querybuilder_datasource() { assert!(!filtered_find_players.unwrap().is_empty()); } +/// Same than the above but with the specified datasource +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_find_with_querybuilder_datasource_mysql() { + // Find all the players where its ID column value is greater that 50 + let filtered_find_players = Player::select_query_datasource(MYSQL_DS) + .r#where(PlayerFieldValue::id(&50), Comp::Gt) + .query() + .await; + + assert!(!filtered_find_players.unwrap().is_empty()); +} + /// Updates the values of the range on entries defined by the constraint parameters /// in the database entity #[cfg(feature = "postgres")] @@ -202,7 +261,7 @@ fn test_crud_update_with_querybuilder() { /// Same as above, but with the specified datasource #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_update_with_querybuilder_datasource() { +fn test_crud_update_with_querybuilder_datasource_mssql() { // Find all the leagues with ID less or equals that 7 // and where it's region column value is equals to 'Korea' let mut q = Player::update_query_datasource(SQL_SERVER_DS); @@ -229,6 +288,37 @@ fn test_crud_update_with_querybuilder_datasource() { }); } +/// Same as above, but with the specified datasource +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_update_with_querybuilder_datasource_mysql() { + // Find all the leagues with ID less or equals that 7 + // and where it's region column value is equals to 'Korea' + + let mut q = Player::update_query_datasource(MYSQL_DS); + q.set(&[ + (PlayerField::summoner_name, "Random updated player name"), + (PlayerField::first_name, "I am an updated first name"), + ]) + .r#where(PlayerFieldValue::id(&1), Comp::Gt) + .and(PlayerFieldValue::id(&8), Comp::Lt) + .query() + .await + .expect("Failed to update records with the querybuilder"); + + let found_updated_values = Player::select_query_datasource(MYSQL_DS) + .r#where(PlayerFieldValue::id(&1), Comp::Gt) + .and(PlayerFieldValue::id(&7), Comp::LtEq) + .query() + .await + .expect("Failed to retrieve database League entries with the querybuilder"); + + found_updated_values.iter().for_each(|player| { + assert_eq!(player.summoner_name, "Random updated player name"); + assert_eq!(player.first_name, "I am an updated first name"); + }); +} + /// Deletes entries from the mapped entity `T` that are in the ranges filtered /// with the QueryBuilder /// @@ -251,7 +341,7 @@ fn test_crud_delete_with_querybuilder() { /// Same as the above delete, but with the specified datasource #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_delete_with_querybuilder_datasource() { +fn test_crud_delete_with_querybuilder_datasource_mssql() { Player::delete_query_datasource(SQL_SERVER_DS) .r#where(PlayerFieldValue::id(&120), Comp::Gt) .and(PlayerFieldValue::id(&130), Comp::Lt) @@ -267,6 +357,25 @@ fn test_crud_delete_with_querybuilder_datasource() { .is_empty()); } +/// Same as the above delete, but with the specified datasource +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_delete_with_querybuilder_datasource_mysql() { + Player::delete_query_datasource(MYSQL_DS) + .r#where(PlayerFieldValue::id(&120), Comp::Gt) + .and(PlayerFieldValue::id(&130), Comp::Lt) + .query() + .await + .expect("Error connecting with the database when we are going to delete data! :)"); + + assert!(Player::select_query_datasource(MYSQL_DS) + .r#where(PlayerFieldValue::id(&122), Comp::Eq) + .query() + .await + .unwrap() + .is_empty()); +} + /// Tests for the generated SQL query after use the /// WHERE clause #[canyon_sql::macros::canyon_tokio_test] diff --git a/tests/crud/select_operations.rs b/tests/crud/select_operations.rs index 9f9a6f5c..76d263f2 100644 --- a/tests/crud/select_operations.rs +++ b/tests/crud/select_operations.rs @@ -1,5 +1,8 @@ #![allow(clippy::nonminimal_bool)] +#[cfg(feature = "mysql")] +use crate::constants::MYSQL_DS; + #[cfg(feature = "mssql")] use crate::constants::SQL_SERVER_DS; ///! Integration tests for the CRUD operations available in `Canyon` that @@ -42,7 +45,7 @@ fn test_crud_find_all_unchecked() { /// and using the specified datasource #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_find_all_datasource() { +fn test_crud_find_all_datasource_mssql() { let find_all_result: Result, Box> = League::find_all_datasource(SQL_SERVER_DS).await; // Connection doesn't return an error @@ -50,6 +53,16 @@ fn test_crud_find_all_datasource() { assert!(!find_all_result.unwrap().is_empty()); } +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_find_all_datasource_mysql() { + let find_all_result: Result, Box> = + League::find_all_datasource(MYSQL_DS).await; + // Connection doesn't return an error + assert!(!find_all_result.is_err()); + assert!(!find_all_result.unwrap().is_empty()); +} + /// Same as the `find_all_datasource()`, but with the unchecked variant and the specified dataosource, /// returning directly `Vec` and not `Result, Err>` #[cfg(feature = "mssql")] @@ -85,11 +98,10 @@ fn test_crud_find_by_pk() { /// Tests the behaviour of a SELECT * FROM {table_name} WHERE = , where the pk is /// defined with the #[primary_key] attribute over some field of the type. /// -/// Uses the *specified datasource* in the second parameter of the function call. -#[cfg(feature = "postgres")] +/// Uses the *specified datasource mssql* in the second parameter of the function call. #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_find_by_pk_datasource() { +fn test_crud_find_by_pk_datasource_mssql() { let find_by_pk_result: Result, Box> = League::find_by_pk_datasource(&27, SQL_SERVER_DS).await; assert!(find_by_pk_result.as_ref().unwrap().is_some()); @@ -106,6 +118,29 @@ fn test_crud_find_by_pk_datasource() { ); } +/// Tests the behaviour of a SELECT * FROM {table_name} WHERE = , where the pk is +/// defined with the #[primary_key] attribute over some field of the type. +/// +/// Uses the *specified datasource mysql* in the second parameter of the function call. +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_find_by_pk_datasource_mysql() { + let find_by_pk_result: Result, Box> = + League::find_by_pk_datasource(&27, MYSQL_DS).await; + assert!(find_by_pk_result.as_ref().unwrap().is_some()); + + let some_league = find_by_pk_result.unwrap().unwrap(); + assert_eq!(some_league.id, 27); + assert_eq!(some_league.ext_id, 107898214974993351_i64); + assert_eq!(some_league.slug, "college_championship"); + assert_eq!(some_league.name, "College Championship"); + assert_eq!(some_league.region, "NORTH AMERICA"); + assert_eq!( + some_league.image_url, + "http://static.lolesports.com/leagues/1646396098648_CollegeChampionshiplogo.png" + ); +} + /// Counts how many rows contains an entity on the target database. #[cfg(feature = "postgres")] #[canyon_sql::macros::canyon_tokio_test] @@ -117,10 +152,10 @@ fn test_crud_count_operation() { } /// Counts how many rows contains an entity on the target database using -/// the specified datasource +/// the specified datasource mssql #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_count_datasource_operation() { +fn test_crud_count_datasource_operation_mssql() { assert_eq!( League::find_all_datasource(SQL_SERVER_DS) .await @@ -129,3 +164,14 @@ fn test_crud_count_datasource_operation() { League::count_datasource(SQL_SERVER_DS).await.unwrap() ); } + +/// Counts how many rows contains an entity on the target database using +/// the specified datasource mysql +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_count_datasource_operation_mysql() { + assert_eq!( + League::find_all_datasource(MYSQL_DS).await.unwrap().len() as i64, + League::count_datasource(MYSQL_DS).await.unwrap() + ); +} diff --git a/tests/crud/update_operations.rs b/tests/crud/update_operations.rs index e4085560..18283cb7 100644 --- a/tests/crud/update_operations.rs +++ b/tests/crud/update_operations.rs @@ -1,10 +1,12 @@ +use crate::tests_models::league::*; ///! Integration tests for the CRUD operations available in `Canyon` that ///! generates and executes *UPDATE* statements use canyon_sql::crud::CrudOperations; +#[cfg(feature = "mysql")] +use crate::constants::MYSQL_DS; #[cfg(feature = "mssql")] use crate::constants::SQL_SERVER_DS; -use crate::tests_models::league::*; /// Update operation is a *CRUD* method defined for some entity `T`, that works by appliying /// some change to a Rust's entity instance, and persisting them into the database. @@ -59,7 +61,7 @@ fn test_crud_update_method_operation() { /// Same as the above test, but with the specified datasource. #[cfg(feature = "mssql")] #[canyon_sql::macros::canyon_tokio_test] -fn test_crud_update_datasource_method_operation() { +fn test_crud_update_datasource_mssql_method_operation() { // We first retrieve some entity from the database. Note that we must make // the retrieved instance mutable of clone it to a new mutable resource let mut updt_candidate: League = League::find_by_pk_datasource(&1, SQL_SERVER_DS) @@ -96,3 +98,45 @@ fn test_crud_update_datasource_method_operation() { .await .expect("Failed to restablish the initial value update operation"); } + +/// Same as the above test, but with the specified datasource. +#[cfg(feature = "mysql")] +#[canyon_sql::macros::canyon_tokio_test] +fn test_crud_update_datasource_mysql_method_operation() { + // We first retrieve some entity from the database. Note that we must make + // the retrieved instance mutable of clone it to a new mutable resource + + let mut updt_candidate: League = League::find_by_pk_datasource(&1, MYSQL_DS) + .await + .expect("[1] - Failed the query to the database") + .expect("[1] - No entity found for the primary key value passed in"); + + // The ext_id field value is extracted from the sql scripts under the + // docker/sql folder. We are retrieving the first entity inserted at the + // wake up time of the database, and now checking some of its properties. + assert_eq!(updt_candidate.ext_id, 100695891328981122_i64); + + // Modify the value, and perform the update + let updt_value: i64 = 59306442534_i64; + updt_candidate.ext_id = updt_value; + updt_candidate + .update_datasource(MYSQL_DS) + .await + .expect("Failed the update operation"); + + // Retrieve it again, and check if the value was really updated + let updt_entity: League = League::find_by_pk_datasource(&1, MYSQL_DS) + .await + .expect("[2] - Failed the query to the database") + .expect("[2] - No entity found for the primary key value passed in"); + + assert_eq!(updt_entity.ext_id, updt_value); + + // We rollback the changes to the initial value to don't broke other tests + // the next time that will run + updt_candidate.ext_id = 100695891328981122_i64; + updt_candidate + .update_datasource(MYSQL_DS) + .await + .expect("Failed to restablish the initial value update operation"); +}