From 606a439352dfdc5e9958c5426ed8bfc2aa8d797e Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Wed, 2 Oct 2024 02:32:20 -0400 Subject: [PATCH] all queries for tags --- ...6c3bd7e76e96b0bf603f77f6a9b2d4fcda18d.json | 36 +++++++++ ...354baa8d5cd81170dd06d66d7f414505d538b.json | 12 +++ .../src/queries/tags/list_tags_for_entity.rs | 6 +- .../lib/mysql_queries/src/queries/tags/mod.rs | 3 +- .../src/queries/tags/select_matching_tags.rs | 79 +++++++++++++++++++ .../queries/tags/update_tags_for_entity.rs | 16 +++- 6 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 .sqlx/query-3929e9fe74e75fad7252681880c6c3bd7e76e96b0bf603f77f6a9b2d4fcda18d.json create mode 100644 .sqlx/query-c7e848e4c906a34ac5a4ad8cc73354baa8d5cd81170dd06d66d7f414505d538b.json create mode 100644 crates/lib/mysql_queries/src/queries/tags/select_matching_tags.rs diff --git a/.sqlx/query-3929e9fe74e75fad7252681880c6c3bd7e76e96b0bf603f77f6a9b2d4fcda18d.json b/.sqlx/query-3929e9fe74e75fad7252681880c6c3bd7e76e96b0bf603f77f6a9b2d4fcda18d.json new file mode 100644 index 0000000000..7a9a0b0ef6 --- /dev/null +++ b/.sqlx/query-3929e9fe74e75fad7252681880c6c3bd7e76e96b0bf603f77f6a9b2d4fcda18d.json @@ -0,0 +1,36 @@ +{ + "db_name": "MySQL", + "query": "\nSELECT\n t.token as `token: tokens::tokens::tags::TagToken`,\n t.tag_value\n\nFROM\n tags AS t\nJOIN tag_uses AS u\n ON t.token = u.tag_token\nWHERE\n u.entity_type = ?\n AND u.entity_token = ?\n AND u.maybe_deleted_at IS NULL\nORDER BY t.id DESC\nLIMIT 500\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "token: tokens::tokens::tags::TagToken", + "type_info": { + "type": "VarString", + "flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE", + "char_set": 224, + "max_size": 128 + } + }, + { + "ordinal": 1, + "name": "tag_value", + "type_info": { + "type": "VarString", + "flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE", + "char_set": 224, + "max_size": 1020 + } + } + ], + "parameters": { + "Right": 2 + }, + "nullable": [ + false, + false + ] + }, + "hash": "3929e9fe74e75fad7252681880c6c3bd7e76e96b0bf603f77f6a9b2d4fcda18d" +} diff --git a/.sqlx/query-c7e848e4c906a34ac5a4ad8cc73354baa8d5cd81170dd06d66d7f414505d538b.json b/.sqlx/query-c7e848e4c906a34ac5a4ad8cc73354baa8d5cd81170dd06d66d7f414505d538b.json new file mode 100644 index 0000000000..2ce40bca04 --- /dev/null +++ b/.sqlx/query-c7e848e4c906a34ac5a4ad8cc73354baa8d5cd81170dd06d66d7f414505d538b.json @@ -0,0 +1,12 @@ +{ + "db_name": "MySQL", + "query": "\nINSERT INTO tags\nSET\n token = ?,\n tag_value = ?\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "c7e848e4c906a34ac5a4ad8cc73354baa8d5cd81170dd06d66d7f414505d538b" +} diff --git a/crates/lib/mysql_queries/src/queries/tags/list_tags_for_entity.rs b/crates/lib/mysql_queries/src/queries/tags/list_tags_for_entity.rs index 6705f095b1..05abc661a8 100644 --- a/crates/lib/mysql_queries/src/queries/tags/list_tags_for_entity.rs +++ b/crates/lib/mysql_queries/src/queries/tags/list_tags_for_entity.rs @@ -4,7 +4,7 @@ use tokens::tokens::tags::TagToken; use crate::utils::transactor::Transactor; -pub struct Tag { +pub struct EntityTag { pub token: TagToken, pub tag_value: String, } @@ -12,7 +12,7 @@ pub struct Tag { pub async fn list_tags_for_entity( tag_entity: TagUseEntity, transactor: Transactor<'_, '_>, -) -> AnyhowResult> { +) -> AnyhowResult> { let (entity_type, entity_token) = tag_entity.get_composite_keys(); @@ -51,7 +51,7 @@ LIMIT 500 }; Ok(results.into_iter() - .map(|record| Tag { + .map(|record| EntityTag { token: record.token, tag_value: record.tag_value, }) diff --git a/crates/lib/mysql_queries/src/queries/tags/mod.rs b/crates/lib/mysql_queries/src/queries/tags/mod.rs index 6bf5eba512..1a3004feb5 100644 --- a/crates/lib/mysql_queries/src/queries/tags/mod.rs +++ b/crates/lib/mysql_queries/src/queries/tags/mod.rs @@ -1,3 +1,4 @@ pub mod list_tags_for_entity; pub mod create_tag; -pub mod update_tags_for_entity; \ No newline at end of file +pub mod update_tags_for_entity; +mod select_matching_tags; \ No newline at end of file diff --git a/crates/lib/mysql_queries/src/queries/tags/select_matching_tags.rs b/crates/lib/mysql_queries/src/queries/tags/select_matching_tags.rs new file mode 100644 index 0000000000..3ffd04d8f5 --- /dev/null +++ b/crates/lib/mysql_queries/src/queries/tags/select_matching_tags.rs @@ -0,0 +1,79 @@ +use crate::utils::transactor::Transactor; +use errors::AnyhowResult; +use sqlx::mysql::MySqlRow; +use sqlx::{FromRow, MySql, QueryBuilder, Row}; +use tokens::tokens::tags::TagToken; + +pub struct MatchingTag { + pub token: TagToken, + pub tag_value: String, +} + +pub async fn list_tags_for_entity( + tag_values: &[&str], + transactor: Transactor<'_, '_>, +) -> AnyhowResult> { + if tag_values.is_empty() { + return Ok(Vec::new()) // This prevents a SQL error when the IN clause is empty. + } + + let tag_values = tag_values.iter() + .map(|tag| tag.trim().to_lowercase()) + .collect::>(); + + let mut query_builder: QueryBuilder = QueryBuilder::new( + r#" +SELECT + t.token as `token: tokens::tokens::tags::TagToken`, + t.tag_value + +FROM + tags AS t +WHERE + t.tag_value IN ( + "#, + ); + + let mut separated = query_builder.separated(", "); + + for tag_value in tag_values.iter() { + separated.push_bind(tag_value); + } + + separated.push_unseparated(") "); + + let query = query_builder.build_query_as::(); + + let results = match transactor { + Transactor::Pool { pool } => { + query.fetch_all(pool).await? + }, + Transactor::Connection { connection } => { + query.fetch_all(connection).await? + }, + Transactor::Transaction { transaction } => { + query.fetch_all(&mut **transaction).await? + }, + }; + + Ok(results.into_iter() + .map(|record| MatchingTag { + token: record.token, + tag_value: record.tag_value, + }) + .collect()) +} + +struct RawTag { + token: TagToken, + tag_value: String, +} + +impl FromRow<'_, MySqlRow> for RawTag { + fn from_row(row: &MySqlRow) -> Result { + Ok(Self { + token: TagToken::new(row.try_get("token")?), + tag_value: row.try_get("tag_value")?, + }) + } +} diff --git a/crates/lib/mysql_queries/src/queries/tags/update_tags_for_entity.rs b/crates/lib/mysql_queries/src/queries/tags/update_tags_for_entity.rs index 62f3be2415..e11e13e1ad 100644 --- a/crates/lib/mysql_queries/src/queries/tags/update_tags_for_entity.rs +++ b/crates/lib/mysql_queries/src/queries/tags/update_tags_for_entity.rs @@ -1,8 +1,19 @@ use composite_identifiers::by_table::tag_uses::tag_use_entity::TagUseEntity; use errors::AnyhowResult; use sqlx::pool::PoolConnection; -use sqlx::{Acquire, Executor, MySql, QueryBuilder, Transaction}; +use sqlx::{Acquire, Executor, FromRow, MySql, QueryBuilder, Transaction}; +use sqlx::mysql::MySqlRow; +use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType; +use enums::by_table::media_files::media_file_class::MediaFileClass; +use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory; +use enums::by_table::media_files::media_file_origin_category::MediaFileOriginCategory; +use enums::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType; +use enums::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory; +use enums::by_table::media_files::media_file_type::MediaFileType; +use enums::common::visibility::Visibility; +use tokens::tokens::media_files::MediaFileToken; use tokens::tokens::tags::TagToken; +use crate::queries::beta_keys::get_beta_key_by_value::RawRecord; pub async fn update_tags_for_entity( entity: TagUseEntity, @@ -59,7 +70,8 @@ async fn insert_query( tags: &[TagToken], transaction: &mut Transaction<'_, MySql>, ) -> AnyhowResult<()> { - let mut query_builder: QueryBuilder = QueryBuilder::new("INSERT INTO tag_uses "); + // NB: Insert ignore will insert non-duplicate rows and silently ignore duplicates + let mut query_builder: QueryBuilder = QueryBuilder::new("INSERT IGNORE INTO tag_uses "); query_builder.push(" (entity_type, entity_token, tag_token) VALUES ");