Skip to content

Commit b0d1a53

Browse files
committed
feat: 🎸 Support sea_orm::ColumnTrait with fully-qualification
1 parent eb42083 commit b0d1a53

File tree

3 files changed

+176
-13
lines changed

3 files changed

+176
-13
lines changed

.github/workflows/test.yaml

+32-9
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,18 @@ jobs:
88
runs-on: ubuntu-latest
99
strategy:
1010
matrix:
11-
sea-query: ["0.30", "0.31"]
12-
sqlx: ["0.7", "0.8"]
11+
sea:
12+
- { sea-orm: "1.0", sea-query: "0.31" }
13+
use-sea-orm:
14+
- true
15+
- false
16+
sqlx:
17+
- "0.7"
18+
- "0.8"
19+
exclude:
20+
- sea: { sea-orm: "1.0", sea-query: "0.31" }
21+
use-sea-orm: true
22+
sqlx: "0.8"
1323
steps:
1424
- uses: actions/checkout@v4
1525
- name: Setup Rust stable toolchain
@@ -18,17 +28,30 @@ jobs:
1828
components: rustfmt
1929
- name: Update dependencies
2030
run: |
21-
cargo add sea-query@${{ matrix.sea-query }}
22-
cargo add --dev sqlx@${{ matrix.sqlx }}
23-
cargo add --dev sqlx-postgres@${{ matrix.sqlx }}
31+
cargo remove sea-orm sea-query
32+
cargo remove --dev sea-orm sea-query sqlx sqlx-postgres
33+
cargo add sea-query@${{ matrix.sea.sea-query }}
34+
if [ "${{ matrix.use-sea-orm }}" == "true" ]; then
35+
cargo add sea-orm@${{ matrix.sea.sea-orm }} --features macros
36+
fi
37+
cargo add --dev sqlx@${{ matrix.sqlx }} sqlx-postgres@${{ matrix.sqlx }}
38+
cat Cargo.toml
39+
- name: Generate feature flags
40+
id: generate-flags
41+
run: |
42+
if [ "${{ matrix.use-sea-orm }}" == "true" ]; then
43+
echo "feature_flags=--all-features" >> $GITHUB_OUTPUT
44+
else
45+
echo "feature_flags=" >> $GITHUB_OUTPUT
46+
fi
2447
- name: Restore cache
2548
uses: Swatinem/rust-cache@v2
2649
- name: Check code (dependencies only)
27-
run: cargo +nightly check
50+
run: cargo +nightly check ${{ steps.generate-flags.outputs.feature_flags }}
2851
- name: Check code (with dev-dependencies)
29-
run: cargo +nightly check --all-targets
52+
run: cargo +nightly check --all-targets ${{ steps.generate-flags.outputs.feature_flags }}
3053
- name: Check test
31-
run: cargo +nightly test
54+
run: cargo +nightly test ${{ steps.generate-flags.outputs.feature_flags }}
3255

3356
rust-lint:
3457
timeout-minutes: 10
@@ -48,6 +71,6 @@ jobs:
4871
- name: Check format
4972
run: cargo +nightly fmt --all -- --check
5073
- name: Check clippy
51-
run: cargo clippy -- -D warnings
74+
run: cargo clippy --all-features -- -D warnings
5275
- name: Check sort
5376
run: cargo sort -w -c

Cargo.toml

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
[package]
22
name = "sea-query-common-like"
3-
version = "0.1.4"
3+
version = "1.0.0"
44
authors = ["mpyw <[email protected]>"]
55
edition = "2021"
66
rust-version = "1.80.0"
77
description = "A Rust crate for enhancing sea_query with typical LIKE search support, including escape sequences for patterns (%fuzzy%, prefix%, %suffix) and multi-column fuzzy search."
88
repository = "https://github.com/yumemi-inc/sea-query-common-like"
99
license = "MIT"
1010
include = ["/src", "LICENSE"]
11-
keywords = ["sea_query", "sql", "database", "LIKE", "search"]
11+
keywords = ["sea-orm", "sea-query", "sql", "LIKE", "search"]
1212
categories = ["database", "web-programming"]
1313

1414
[dependencies]
1515
fancy-regex = { version = "0.13", default-features = false }
1616
regex = { version = "1", default-features = false, features = ["unicode-gencat"] }
17-
sea-query = { version = ">=0.30, <0.32", default-features = false }
17+
sea-orm = { version = ">=1.0, <1.1", default-features = false, optional = true }
18+
sea-query = { version = ">=0.31, <0.32", default-features = false }
1819

1920
[dev-dependencies]
20-
sea-query = ">=0.30, <0.32"
21+
sea-orm = { version = ">=1.0, <1.1", features = ["macros"] }
22+
sea-query = ">=0.31, <0.32"
2123
sqlformat = "0.2.4"
2224
sqlx = ">=0.7, <0.9"
2325
sqlx-postgres = ">=0.7, <0.9"
26+
27+
[features]
28+
default = []
29+
with-sea-orm = ["dep:sea-orm"]

src/lib.rs

+134
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ use regex::Regex;
99
use sea_query::{Cond, Condition, Expr, IntoColumnRef, IntoLikeExpr, LikeExpr};
1010
use std::sync::LazyLock;
1111

12+
#[cfg(feature = "with-sea-orm")]
13+
use sea_orm::ColumnTrait;
14+
1215
/// Represents a keyword used for `LIKE` search with different matching types.
1316
#[derive(Debug, Clone, Eq, PartialEq)]
1417
pub struct Keyword {
@@ -99,6 +102,10 @@ static SEPARATOR_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"\p{Zs}++
99102
/// ),
100103
/// );
101104
/// ```
105+
///
106+
/// # Examples (`with-sea-orm`)
107+
///
108+
/// See [`fuzzy_separated`] examples.
102109
pub fn prefix<T: Into<String>>(text: T) -> Keyword {
103110
Keyword {
104111
ty: KeywordType::Prefix,
@@ -163,6 +170,10 @@ pub fn prefix<T: Into<String>>(text: T) -> Keyword {
163170
/// ),
164171
/// );
165172
/// ```
173+
///
174+
/// # Examples (`with-sea-orm`)
175+
///
176+
/// See [`fuzzy_separated`] examples.
166177
pub fn suffix<T: Into<String>>(text: T) -> Keyword {
167178
Keyword {
168179
ty: KeywordType::Suffix,
@@ -229,6 +240,10 @@ pub fn suffix<T: Into<String>>(text: T) -> Keyword {
229240
/// ),
230241
/// );
231242
/// ```
243+
///
244+
/// # Examples (`with-sea-orm`)
245+
///
246+
/// See [`fuzzy_separated`] examples.
232247
pub fn fuzzy<T: Into<String>>(text: T) -> Keyword {
233248
Keyword {
234249
ty: KeywordType::Fuzzy,
@@ -306,6 +321,83 @@ pub fn fuzzy<T: Into<String>>(text: T) -> Keyword {
306321
/// ),
307322
/// );
308323
/// ```
324+
///
325+
/// # Examples (`with-sea-orm`)
326+
///
327+
/// ```
328+
/// use sea_query::all;
329+
/// use sea_query_common_like::fuzzy_separated;
330+
/// use sqlformat::{format, FormatOptions, QueryParams};
331+
///
332+
/// #[cfg(feature = "with-sea-orm")]
333+
/// use sea_orm::{ColumnTrait, DbBackend, EntityTrait, QueryFilter, QueryTrait};
334+
///
335+
/// #[cfg(feature = "with-sea-orm")]
336+
/// mod book {
337+
/// use sea_orm::entity::prelude::*;
338+
///
339+
/// #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
340+
/// #[sea_orm(schema_name = "book", table_name = "books")]
341+
/// pub struct Model {
342+
/// #[sea_orm(primary_key, auto_increment = false)]
343+
/// pub id: Uuid,
344+
/// #[sea_orm(column_type = "Text")]
345+
/// pub title: String,
346+
/// #[sea_orm(column_type = "Text")]
347+
/// pub author: String,
348+
/// pub deleted_at: Option<DateTimeWithTimeZone>,
349+
/// }
350+
///
351+
/// #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
352+
/// pub enum Relation {
353+
/// }
354+
///
355+
/// impl ActiveModelBehavior for ActiveModel {}
356+
/// }
357+
///
358+
/// #[cfg(feature = "with-sea-orm")]
359+
/// assert_eq!(
360+
/// format(
361+
/// book::Entity::find()
362+
/// .filter(all![
363+
/// fuzzy_separated("1% 99% Edison").into_condition_for_orm_columns([book::Column::Title, book::Column::Author]),
364+
/// book::Column::DeletedAt.is_null(),
365+
/// ])
366+
/// .build(DbBackend::Postgres)
367+
/// .to_string()
368+
/// .as_str(),
369+
/// &QueryParams::default(),
370+
/// FormatOptions::default(),
371+
/// ),
372+
/// format(
373+
/// r#"
374+
/// SELECT
375+
/// "books"."id",
376+
/// "books"."title",
377+
/// "books"."author",
378+
/// "books"."deleted_at"
379+
/// FROM
380+
/// "book"."books"
381+
/// WHERE
382+
/// (
383+
/// "books"."title" LIKE '%1!%%' ESCAPE '!'
384+
/// OR "books"."author" LIKE '%1!%%' ESCAPE '!'
385+
/// )
386+
/// AND (
387+
/// "books"."title" LIKE '%99!%%' ESCAPE '!'
388+
/// OR "books"."author" LIKE '%99!%%' ESCAPE '!'
389+
/// )
390+
/// AND (
391+
/// "books"."title" LIKE '%Edison%' ESCAPE '!'
392+
/// OR "books"."author" LIKE '%Edison%' ESCAPE '!'
393+
/// )
394+
/// AND "books"."deleted_at" IS NULL
395+
/// "#,
396+
/// &QueryParams::default(),
397+
/// FormatOptions::default(),
398+
/// ),
399+
/// );
400+
/// ```
309401
pub fn fuzzy_separated<T: Into<String>>(text: T) -> Keywords {
310402
keywords(
311403
SEPARATOR_REGEX
@@ -382,6 +474,10 @@ pub fn fuzzy_separated<T: Into<String>>(text: T) -> Keywords {
382474
/// ),
383475
/// );
384476
/// ```
477+
///
478+
/// # Examples (`with-sea-orm`)
479+
///
480+
/// See [`fuzzy_separated`] examples.
385481
pub fn keywords<T: Into<Keyword>, Iter: IntoIterator<Item = T>>(texts: Iter) -> Keywords {
386482
Keywords(texts.into_iter().map(Into::into).collect())
387483
}
@@ -436,6 +532,25 @@ impl Keyword {
436532
.map(|col| Expr::col(col).like(self.clone()))
437533
.fold(Cond::all(), Cond::add)
438534
}
535+
536+
/// Generate a [`Condition`] for a single column with the `LIKE` pattern using a fully-qualified column name with `sea-orm`.
537+
#[cfg(feature = "with-sea-orm")]
538+
pub fn into_condition_for_orm_column<C>(self, column: C) -> Condition
539+
where
540+
C: ColumnTrait,
541+
{
542+
self.into_condition_for_orm_columns([column])
543+
}
544+
545+
/// Generate a [`Condition`] for multiple columns with the `LIKE` pattern using fully-qualified column names with `sea-orm`.
546+
#[cfg(feature = "with-sea-orm")]
547+
pub fn into_condition_for_orm_columns<C, Iter>(self, columns: Iter) -> Condition
548+
where
549+
C: ColumnTrait,
550+
Iter: IntoIterator<Item = C>,
551+
{
552+
self.into_condition_for_columns(columns.into_iter().map(|col| col.as_column_ref()))
553+
}
439554
}
440555

441556
/// Methods for converting [`Keywords`] into [`sea_query::Condition`] for a single or multiple columns.
@@ -461,4 +576,23 @@ impl Keywords {
461576
})
462577
.fold(Cond::all(), Cond::add)
463578
}
579+
580+
/// Generate a [`Condition`] for a single column with multiple `LIKE` patterns using a fully-qualified column name with `sea-orm`.
581+
#[cfg(feature = "with-sea-orm")]
582+
pub fn into_condition_for_orm_column<C>(self, column: C) -> Condition
583+
where
584+
C: ColumnTrait,
585+
{
586+
self.into_condition_for_orm_columns([column])
587+
}
588+
589+
/// Generate a [`Condition`] for multiple columns with multiple `LIKE` patterns using fully-qualified column names with `sea-orm`.
590+
#[cfg(feature = "with-sea-orm")]
591+
pub fn into_condition_for_orm_columns<C, Iter>(self, columns: Iter) -> Condition
592+
where
593+
C: ColumnTrait,
594+
Iter: IntoIterator<Item = C>,
595+
{
596+
self.into_condition_for_columns(columns.into_iter().map(|col| col.as_column_ref()))
597+
}
464598
}

0 commit comments

Comments
 (0)