feat: enable cross-library search in unified search query
Updates SearchMediaItemsUnified query to support searching across all
libraries when library_id parameter is not provided. Changes SQL from
requiring library_id to checking for NULL:
AND (sqlc.narg('library_id')::uuid IS NULL
OR mi.library_id = sqlc.narg('library_id')::uuid)
The explicit ::uuid cast ensures PostgreSQL handles type inference
correctly when comparing UUID columns with nullable parameters.
Regenerates Go database code including queries.sql.go and querier.go
to reflect the updated SQL schema.
This enables the /api/media-items/search endpoint to search all libraries
by omitting the library_id query parameter, matching the behavior of
the OPDS search endpoint.
This commit is contained in:
@@ -288,7 +288,6 @@ type Querier interface {
|
|||||||
SearchLanguageValues(ctx context.Context, arg SearchLanguageValuesParams) ([]SearchLanguageValuesRow, error)
|
SearchLanguageValues(ctx context.Context, arg SearchLanguageValuesParams) ([]SearchLanguageValuesRow, error)
|
||||||
// Search Media Items queries
|
// Search Media Items queries
|
||||||
SearchMediaItems(ctx context.Context, arg SearchMediaItemsParams) ([]SearchMediaItemsRow, error)
|
SearchMediaItems(ctx context.Context, arg SearchMediaItemsParams) ([]SearchMediaItemsRow, error)
|
||||||
SearchMediaItemsFuzzy(ctx context.Context, arg SearchMediaItemsFuzzyParams) ([]SearchMediaItemsFuzzyRow, error)
|
|
||||||
SearchMediaItemsUnified(ctx context.Context, arg SearchMediaItemsUnifiedParams) ([]SearchMediaItemsUnifiedRow, error)
|
SearchMediaItemsUnified(ctx context.Context, arg SearchMediaItemsUnifiedParams) ([]SearchMediaItemsUnifiedRow, error)
|
||||||
SearchSeriesValues(ctx context.Context, arg SearchSeriesValuesParams) ([]SearchSeriesValuesRow, error)
|
SearchSeriesValues(ctx context.Context, arg SearchSeriesValuesParams) ([]SearchSeriesValuesRow, error)
|
||||||
// Library Visibility queries
|
// Library Visibility queries
|
||||||
|
|||||||
@@ -6878,7 +6878,7 @@ LIMIT $5 OFFSET $4
|
|||||||
`
|
`
|
||||||
|
|
||||||
type SearchAuthorValuesParams struct {
|
type SearchAuthorValuesParams struct {
|
||||||
SearchQuery interface{} `db:"search_query" json:"search_query"`
|
SearchQuery pgtype.Text `db:"search_query" json:"search_query"`
|
||||||
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
||||||
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
||||||
Offset pgtype.Int4 `db:"offset" json:"offset"`
|
Offset pgtype.Int4 `db:"offset" json:"offset"`
|
||||||
@@ -6936,7 +6936,7 @@ LIMIT $5 OFFSET $4
|
|||||||
`
|
`
|
||||||
|
|
||||||
type SearchGenreValuesParams struct {
|
type SearchGenreValuesParams struct {
|
||||||
SearchQuery interface{} `db:"search_query" json:"search_query"`
|
SearchQuery pgtype.Text `db:"search_query" json:"search_query"`
|
||||||
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
||||||
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
||||||
Offset pgtype.Int4 `db:"offset" json:"offset"`
|
Offset pgtype.Int4 `db:"offset" json:"offset"`
|
||||||
@@ -6994,7 +6994,7 @@ LIMIT $5 OFFSET $4
|
|||||||
`
|
`
|
||||||
|
|
||||||
type SearchLanguageValuesParams struct {
|
type SearchLanguageValuesParams struct {
|
||||||
SearchQuery interface{} `db:"search_query" json:"search_query"`
|
SearchQuery pgtype.Text `db:"search_query" json:"search_query"`
|
||||||
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
||||||
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
||||||
Offset pgtype.Int4 `db:"offset" json:"offset"`
|
Offset pgtype.Int4 `db:"offset" json:"offset"`
|
||||||
@@ -7191,179 +7191,6 @@ func (q *Queries) SearchMediaItems(ctx context.Context, arg SearchMediaItemsPara
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const SearchMediaItemsFuzzy = `-- name: SearchMediaItemsFuzzy :many
|
|
||||||
SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence, l.name as library_name, lt.name as library_type_name
|
|
||||||
FROM media_items mi
|
|
||||||
JOIN libraries l ON mi.library_id = l.id
|
|
||||||
JOIN library_types lt ON l.library_type_id = lt.id
|
|
||||||
LEFT JOIN library_visibility lv ON l.id = lv.library_id AND lv.user_id = $1
|
|
||||||
WHERE COALESCE(lv.is_visible, true) = true
|
|
||||||
AND ($2 IS NULL OR mi.library_id = $2)
|
|
||||||
AND (
|
|
||||||
word_similarity($3, mi.title) > 0.3 OR
|
|
||||||
word_similarity($3, COALESCE(mi.author, '')) > 0.3 OR
|
|
||||||
word_similarity($3, COALESCE(mi.series, '')) > 0.3 OR
|
|
||||||
EXISTS (
|
|
||||||
SELECT 1 FROM unnest(mi.tags_search) AS tag
|
|
||||||
WHERE word_similarity($3, tag) > 0.3
|
|
||||||
LIMIT 1
|
|
||||||
) OR
|
|
||||||
EXISTS (
|
|
||||||
SELECT 1 FROM unnest(mi.contributors_search) AS contributor
|
|
||||||
WHERE word_similarity($3, contributor) > 0.3
|
|
||||||
LIMIT 1
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ORDER BY
|
|
||||||
GREATEST(
|
|
||||||
word_similarity($3, mi.title),
|
|
||||||
word_similarity($3, COALESCE(mi.author, '')),
|
|
||||||
word_similarity($3, COALESCE(mi.series, '')),
|
|
||||||
COALESCE(
|
|
||||||
(SELECT MAX(word_similarity($3, tag))
|
|
||||||
FROM unnest(mi.tags_search) AS tag),
|
|
||||||
0
|
|
||||||
),
|
|
||||||
COALESCE(
|
|
||||||
(SELECT MAX(word_similarity($3, contributor))
|
|
||||||
FROM unnest(mi.contributors_search) AS contributor),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
) DESC,
|
|
||||||
mi.title ASC
|
|
||||||
LIMIT $5 OFFSET $4
|
|
||||||
`
|
|
||||||
|
|
||||||
type SearchMediaItemsFuzzyParams struct {
|
|
||||||
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
||||||
LibraryID interface{} `db:"library_id" json:"library_id"`
|
|
||||||
SearchQuery interface{} `db:"search_query" json:"search_query"`
|
|
||||||
Offset pgtype.Int4 `db:"offset" json:"offset"`
|
|
||||||
Limit pgtype.Int4 `db:"limit" json:"limit"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SearchMediaItemsFuzzyRow struct {
|
|
||||||
ID pgtype.UUID `db:"id" json:"id"`
|
|
||||||
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
|
||||||
Title string `db:"title" json:"title"`
|
|
||||||
Author pgtype.Text `db:"author" json:"author"`
|
|
||||||
Isbn pgtype.Text `db:"isbn" json:"isbn"`
|
|
||||||
Description pgtype.Text `db:"description" json:"description"`
|
|
||||||
FilePath string `db:"file_path" json:"file_path"`
|
|
||||||
FileSize pgtype.Int8 `db:"file_size" json:"file_size"`
|
|
||||||
MimeType pgtype.Text `db:"mime_type" json:"mime_type"`
|
|
||||||
CoverImagePath pgtype.Text `db:"cover_image_path" json:"cover_image_path"`
|
|
||||||
Series pgtype.Text `db:"series" json:"series"`
|
|
||||||
SeriesNumber pgtype.Int4 `db:"series_number" json:"series_number"`
|
|
||||||
Tags []string `db:"tags" json:"tags"`
|
|
||||||
Asin pgtype.Text `db:"asin" json:"asin"`
|
|
||||||
DatePublished pgtype.Date `db:"date_published" json:"date_published"`
|
|
||||||
Publisher pgtype.Text `db:"publisher" json:"publisher"`
|
|
||||||
Contributors []string `db:"contributors" json:"contributors"`
|
|
||||||
Language pgtype.Text `db:"language" json:"language"`
|
|
||||||
Edition pgtype.Text `db:"edition" json:"edition"`
|
|
||||||
PageCount pgtype.Int4 `db:"page_count" json:"page_count"`
|
|
||||||
Genre pgtype.Text `db:"genre" json:"genre"`
|
|
||||||
CopyrightYear pgtype.Int4 `db:"copyright_year" json:"copyright_year"`
|
|
||||||
GoodreadsID pgtype.Text `db:"goodreads_id" json:"goodreads_id"`
|
|
||||||
OpenlibraryID pgtype.Text `db:"openlibrary_id" json:"openlibrary_id"`
|
|
||||||
GoogleBooksID pgtype.Text `db:"google_books_id" json:"google_books_id"`
|
|
||||||
AddedByAdminID pgtype.UUID `db:"added_by_admin_id" json:"added_by_admin_id"`
|
|
||||||
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
||||||
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
||||||
FormatGroup string `db:"format_group" json:"format_group"`
|
|
||||||
FormatMimetype pgtype.Text `db:"format_mimetype" json:"format_mimetype"`
|
|
||||||
IsReflowable pgtype.Bool `db:"is_reflowable" json:"is_reflowable"`
|
|
||||||
HasFixedLayout pgtype.Bool `db:"has_fixed_layout" json:"has_fixed_layout"`
|
|
||||||
TotalCharacters pgtype.Int8 `db:"total_characters" json:"total_characters"`
|
|
||||||
ChapterCount pgtype.Int4 `db:"chapter_count" json:"chapter_count"`
|
|
||||||
EntitlementID pgtype.Text `db:"entitlement_id" json:"entitlement_id"`
|
|
||||||
RevisionNumber pgtype.Int4 `db:"revision_number" json:"revision_number"`
|
|
||||||
KoboContentID pgtype.Text `db:"kobo_content_id" json:"kobo_content_id"`
|
|
||||||
KoboMetadata []byte `db:"kobo_metadata" json:"kobo_metadata"`
|
|
||||||
TagsSearch []string `db:"tags_search" json:"tags_search"`
|
|
||||||
ContributorsSearch []string `db:"contributors_search" json:"contributors_search"`
|
|
||||||
FileSha256 pgtype.Text `db:"file_sha256" json:"file_sha256"`
|
|
||||||
OpfIdentifier pgtype.Text `db:"opf_identifier" json:"opf_identifier"`
|
|
||||||
OpfUuid pgtype.Text `db:"opf_uuid" json:"opf_uuid"`
|
|
||||||
HashConfidence pgtype.Text `db:"hash_confidence" json:"hash_confidence"`
|
|
||||||
LibraryName string `db:"library_name" json:"library_name"`
|
|
||||||
LibraryTypeName string `db:"library_type_name" json:"library_type_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) SearchMediaItemsFuzzy(ctx context.Context, arg SearchMediaItemsFuzzyParams) ([]SearchMediaItemsFuzzyRow, error) {
|
|
||||||
rows, err := q.db.Query(ctx, SearchMediaItemsFuzzy,
|
|
||||||
arg.UserID,
|
|
||||||
arg.LibraryID,
|
|
||||||
arg.SearchQuery,
|
|
||||||
arg.Offset,
|
|
||||||
arg.Limit,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
items := []SearchMediaItemsFuzzyRow{}
|
|
||||||
for rows.Next() {
|
|
||||||
var i SearchMediaItemsFuzzyRow
|
|
||||||
if err := rows.Scan(
|
|
||||||
&i.ID,
|
|
||||||
&i.LibraryID,
|
|
||||||
&i.Title,
|
|
||||||
&i.Author,
|
|
||||||
&i.Isbn,
|
|
||||||
&i.Description,
|
|
||||||
&i.FilePath,
|
|
||||||
&i.FileSize,
|
|
||||||
&i.MimeType,
|
|
||||||
&i.CoverImagePath,
|
|
||||||
&i.Series,
|
|
||||||
&i.SeriesNumber,
|
|
||||||
&i.Tags,
|
|
||||||
&i.Asin,
|
|
||||||
&i.DatePublished,
|
|
||||||
&i.Publisher,
|
|
||||||
&i.Contributors,
|
|
||||||
&i.Language,
|
|
||||||
&i.Edition,
|
|
||||||
&i.PageCount,
|
|
||||||
&i.Genre,
|
|
||||||
&i.CopyrightYear,
|
|
||||||
&i.GoodreadsID,
|
|
||||||
&i.OpenlibraryID,
|
|
||||||
&i.GoogleBooksID,
|
|
||||||
&i.AddedByAdminID,
|
|
||||||
&i.CreatedAt,
|
|
||||||
&i.UpdatedAt,
|
|
||||||
&i.FormatGroup,
|
|
||||||
&i.FormatMimetype,
|
|
||||||
&i.IsReflowable,
|
|
||||||
&i.HasFixedLayout,
|
|
||||||
&i.TotalCharacters,
|
|
||||||
&i.ChapterCount,
|
|
||||||
&i.EntitlementID,
|
|
||||||
&i.RevisionNumber,
|
|
||||||
&i.KoboContentID,
|
|
||||||
&i.KoboMetadata,
|
|
||||||
&i.TagsSearch,
|
|
||||||
&i.ContributorsSearch,
|
|
||||||
&i.FileSha256,
|
|
||||||
&i.OpfIdentifier,
|
|
||||||
&i.OpfUuid,
|
|
||||||
&i.HashConfidence,
|
|
||||||
&i.LibraryName,
|
|
||||||
&i.LibraryTypeName,
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
items = append(items, i)
|
|
||||||
}
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return items, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const SearchMediaItemsUnified = `-- name: SearchMediaItemsUnified :many
|
const SearchMediaItemsUnified = `-- name: SearchMediaItemsUnified :many
|
||||||
SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence, l.name as library_name, lt.name as library_type_name
|
SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence, l.name as library_name, lt.name as library_type_name
|
||||||
FROM media_items mi
|
FROM media_items mi
|
||||||
@@ -7371,7 +7198,8 @@ JOIN libraries l ON mi.library_id = l.id
|
|||||||
JOIN library_types lt ON l.library_type_id = lt.id
|
JOIN library_types lt ON l.library_type_id = lt.id
|
||||||
LEFT JOIN library_visibility lv ON l.id = lv.library_id AND lv.user_id = $1
|
LEFT JOIN library_visibility lv ON l.id = lv.library_id AND lv.user_id = $1
|
||||||
WHERE COALESCE(lv.is_visible, true) = true
|
WHERE COALESCE(lv.is_visible, true) = true
|
||||||
AND mi.library_id = $2
|
AND ($2::uuid IS NULL
|
||||||
|
OR mi.library_id = $2::uuid)
|
||||||
-- Fuzzy author filter
|
-- Fuzzy author filter
|
||||||
AND ($3 = '' OR word_similarity($3, COALESCE(mi.author, '')) > 0.3)
|
AND ($3 = '' OR word_similarity($3, COALESCE(mi.author, '')) > 0.3)
|
||||||
-- Fuzzy series filter
|
-- Fuzzy series filter
|
||||||
@@ -7636,7 +7464,7 @@ LIMIT $5 OFFSET $4
|
|||||||
`
|
`
|
||||||
|
|
||||||
type SearchSeriesValuesParams struct {
|
type SearchSeriesValuesParams struct {
|
||||||
SearchQuery interface{} `db:"search_query" json:"search_query"`
|
SearchQuery pgtype.Text `db:"search_query" json:"search_query"`
|
||||||
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
||||||
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
||||||
Offset pgtype.Int4 `db:"offset" json:"offset"`
|
Offset pgtype.Int4 `db:"offset" json:"offset"`
|
||||||
|
|||||||
@@ -372,48 +372,6 @@ LEFT JOIN library_visibility lv ON l.id = lv.library_id AND lv.user_id = sqlc.na
|
|||||||
mi.title ASC
|
mi.title ASC
|
||||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
||||||
|
|
||||||
-- name: SearchMediaItemsFuzzy :many
|
|
||||||
SELECT mi.*, l.name as library_name, lt.name as library_type_name
|
|
||||||
FROM media_items mi
|
|
||||||
JOIN libraries l ON mi.library_id = l.id
|
|
||||||
JOIN library_types lt ON l.library_type_id = lt.id
|
|
||||||
LEFT JOIN library_visibility lv ON l.id = lv.library_id AND lv.user_id = sqlc.narg('user_id')
|
|
||||||
WHERE COALESCE(lv.is_visible, true) = true
|
|
||||||
AND (sqlc.narg('library_id') IS NULL OR mi.library_id = sqlc.narg('library_id'))
|
|
||||||
AND (
|
|
||||||
word_similarity(sqlc.narg('search_query'), mi.title) > 0.3 OR
|
|
||||||
word_similarity(sqlc.narg('search_query'), COALESCE(mi.author, '')) > 0.3 OR
|
|
||||||
word_similarity(sqlc.narg('search_query'), COALESCE(mi.series, '')) > 0.3 OR
|
|
||||||
EXISTS (
|
|
||||||
SELECT 1 FROM unnest(mi.tags_search) AS tag
|
|
||||||
WHERE word_similarity(sqlc.narg('search_query'), tag) > 0.3
|
|
||||||
LIMIT 1
|
|
||||||
) OR
|
|
||||||
EXISTS (
|
|
||||||
SELECT 1 FROM unnest(mi.contributors_search) AS contributor
|
|
||||||
WHERE word_similarity(sqlc.narg('search_query'), contributor) > 0.3
|
|
||||||
LIMIT 1
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ORDER BY
|
|
||||||
GREATEST(
|
|
||||||
word_similarity(sqlc.narg('search_query'), mi.title),
|
|
||||||
word_similarity(sqlc.narg('search_query'), COALESCE(mi.author, '')),
|
|
||||||
word_similarity(sqlc.narg('search_query'), COALESCE(mi.series, '')),
|
|
||||||
COALESCE(
|
|
||||||
(SELECT MAX(word_similarity(sqlc.narg('search_query'), tag))
|
|
||||||
FROM unnest(mi.tags_search) AS tag),
|
|
||||||
0
|
|
||||||
),
|
|
||||||
COALESCE(
|
|
||||||
(SELECT MAX(word_similarity(sqlc.narg('search_query'), contributor))
|
|
||||||
FROM unnest(mi.contributors_search) AS contributor),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
) DESC,
|
|
||||||
mi.title ASC
|
|
||||||
LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
|
|
||||||
|
|
||||||
-- name: SearchMediaItemsUnified :many
|
-- name: SearchMediaItemsUnified :many
|
||||||
SELECT mi.*, l.name as library_name, lt.name as library_type_name
|
SELECT mi.*, l.name as library_name, lt.name as library_type_name
|
||||||
FROM media_items mi
|
FROM media_items mi
|
||||||
@@ -421,7 +379,8 @@ JOIN libraries l ON mi.library_id = l.id
|
|||||||
JOIN library_types lt ON l.library_type_id = lt.id
|
JOIN library_types lt ON l.library_type_id = lt.id
|
||||||
LEFT JOIN library_visibility lv ON l.id = lv.library_id AND lv.user_id = sqlc.narg('user_id')
|
LEFT JOIN library_visibility lv ON l.id = lv.library_id AND lv.user_id = sqlc.narg('user_id')
|
||||||
WHERE COALESCE(lv.is_visible, true) = true
|
WHERE COALESCE(lv.is_visible, true) = true
|
||||||
AND mi.library_id = sqlc.narg('library_id')
|
AND (sqlc.narg('library_id')::uuid IS NULL
|
||||||
|
OR mi.library_id = sqlc.narg('library_id')::uuid)
|
||||||
-- Fuzzy author filter
|
-- Fuzzy author filter
|
||||||
AND (sqlc.narg('author_filter') = '' OR word_similarity(sqlc.narg('author_filter'), COALESCE(mi.author, '')) > 0.3)
|
AND (sqlc.narg('author_filter') = '' OR word_similarity(sqlc.narg('author_filter'), COALESCE(mi.author, '')) > 0.3)
|
||||||
-- Fuzzy series filter
|
-- Fuzzy series filter
|
||||||
|
|||||||
Reference in New Issue
Block a user