You've already forked pigallery2
mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-07-17 01:32:29 +02:00
changing mysql collate and charset to be case insensitive
This commit is contained in:
@ -100,7 +100,7 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (queryFilter.recursive) {
|
if (queryFilter.recursive) {
|
||||||
qb.orWhere('directory.name LIKE :text COLLATE utf8_general_ci', {text: '%' + queryFilter.directory + '%'});
|
qb.orWhere('directory.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + queryFilter.directory + '%'});
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,8 @@ export class SQLConnection {
|
|||||||
port: 3306,
|
port: 3306,
|
||||||
username: config.mysql.username,
|
username: config.mysql.username,
|
||||||
password: config.mysql.password,
|
password: config.mysql.password,
|
||||||
database: config.mysql.database
|
database: config.mysql.database,
|
||||||
|
charset: 'utf8mb4'
|
||||||
};
|
};
|
||||||
} else if (config.type === DatabaseType.sqlite) {
|
} else if (config.type === DatabaseType.sqlite) {
|
||||||
driver = {
|
driver = {
|
||||||
|
@ -40,7 +40,7 @@ export class SearchManager implements ISearchManager {
|
|||||||
(await photoRepository
|
(await photoRepository
|
||||||
.createQueryBuilder('photo')
|
.createQueryBuilder('photo')
|
||||||
.select('DISTINCT(photo.metadata.keywords)')
|
.select('DISTINCT(photo.metadata.keywords)')
|
||||||
.where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.where('photo.metadata.keywords LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
||||||
.getRawMany())
|
.getRawMany())
|
||||||
.map(r => <Array<string>>(<string>r.metadataKeywords).split(','))
|
.map(r => <Array<string>>(<string>r.metadataKeywords).split(','))
|
||||||
@ -52,7 +52,7 @@ export class SearchManager implements ISearchManager {
|
|||||||
result = result.concat(this.encapsulateAutoComplete((await personRepository
|
result = result.concat(this.encapsulateAutoComplete((await personRepository
|
||||||
.createQueryBuilder('person')
|
.createQueryBuilder('person')
|
||||||
.select('DISTINCT(person.name)')
|
.select('DISTINCT(person.name)')
|
||||||
.where('person.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.where('person.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
||||||
.orderBy('person.name')
|
.orderBy('person.name')
|
||||||
.getRawMany())
|
.getRawMany())
|
||||||
@ -62,9 +62,9 @@ export class SearchManager implements ISearchManager {
|
|||||||
.createQueryBuilder('photo')
|
.createQueryBuilder('photo')
|
||||||
.select('photo.metadata.positionData.country as country, ' +
|
.select('photo.metadata.positionData.country as country, ' +
|
||||||
'photo.metadata.positionData.state as state, photo.metadata.positionData.city as city')
|
'photo.metadata.positionData.state as state, photo.metadata.positionData.city as city')
|
||||||
.where('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.where('photo.metadata.positionData.country LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.groupBy('photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city')
|
.groupBy('photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city')
|
||||||
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
||||||
.getRawMany())
|
.getRawMany())
|
||||||
@ -78,7 +78,7 @@ export class SearchManager implements ISearchManager {
|
|||||||
result = result.concat(this.encapsulateAutoComplete((await photoRepository
|
result = result.concat(this.encapsulateAutoComplete((await photoRepository
|
||||||
.createQueryBuilder('media')
|
.createQueryBuilder('media')
|
||||||
.select('DISTINCT(media.name)')
|
.select('DISTINCT(media.name)')
|
||||||
.where('media.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.where('media.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
||||||
.getRawMany())
|
.getRawMany())
|
||||||
.map(r => r.name), SearchTypes.photo));
|
.map(r => r.name), SearchTypes.photo));
|
||||||
@ -87,7 +87,7 @@ export class SearchManager implements ISearchManager {
|
|||||||
result = result.concat(this.encapsulateAutoComplete((await photoRepository
|
result = result.concat(this.encapsulateAutoComplete((await photoRepository
|
||||||
.createQueryBuilder('media')
|
.createQueryBuilder('media')
|
||||||
.select('DISTINCT(media.metadata.caption) as caption')
|
.select('DISTINCT(media.metadata.caption) as caption')
|
||||||
.where('media.metadata.caption LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.where('media.metadata.caption LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
||||||
.getRawMany())
|
.getRawMany())
|
||||||
.map(r => r.caption), SearchTypes.photo));
|
.map(r => r.caption), SearchTypes.photo));
|
||||||
@ -96,7 +96,7 @@ export class SearchManager implements ISearchManager {
|
|||||||
result = result.concat(this.encapsulateAutoComplete((await videoRepository
|
result = result.concat(this.encapsulateAutoComplete((await videoRepository
|
||||||
.createQueryBuilder('media')
|
.createQueryBuilder('media')
|
||||||
.select('DISTINCT(media.name)')
|
.select('DISTINCT(media.name)')
|
||||||
.where('media.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.where('media.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
||||||
.getRawMany())
|
.getRawMany())
|
||||||
.map(r => r.name), SearchTypes.video));
|
.map(r => r.name), SearchTypes.video));
|
||||||
@ -104,7 +104,7 @@ export class SearchManager implements ISearchManager {
|
|||||||
result = result.concat(this.encapsulateAutoComplete((await directoryRepository
|
result = result.concat(this.encapsulateAutoComplete((await directoryRepository
|
||||||
.createQueryBuilder('dir')
|
.createQueryBuilder('dir')
|
||||||
.select('DISTINCT(dir.name)')
|
.select('DISTINCT(dir.name)')
|
||||||
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.where('dir.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
|
||||||
.getRawMany())
|
.getRawMany())
|
||||||
.map(r => r.name), SearchTypes.directory));
|
.map(r => r.name), SearchTypes.directory));
|
||||||
@ -142,31 +142,31 @@ export class SearchManager implements ISearchManager {
|
|||||||
|
|
||||||
if (!searchType || searchType === SearchTypes.directory) {
|
if (!searchType || searchType === SearchTypes.directory) {
|
||||||
subQuery.leftJoin('media.directory', 'directory')
|
subQuery.leftJoin('media.directory', 'directory')
|
||||||
.orWhere('directory.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
.orWhere('directory.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!searchType || searchType === SearchTypes.photo || searchType === SearchTypes.video) {
|
if (!searchType || searchType === SearchTypes.photo || searchType === SearchTypes.video) {
|
||||||
subQuery.orWhere('media.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
subQuery.orWhere('media.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!searchType || searchType === SearchTypes.photo) {
|
if (!searchType || searchType === SearchTypes.photo) {
|
||||||
subQuery.orWhere('media.metadata.caption LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
subQuery.orWhere('media.metadata.caption LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'});
|
||||||
}
|
}
|
||||||
if (!searchType || searchType === SearchTypes.person) {
|
if (!searchType || searchType === SearchTypes.person) {
|
||||||
subQuery
|
subQuery
|
||||||
.leftJoin('media.metadata.faces', 'faces')
|
.leftJoin('media.metadata.faces', 'faces')
|
||||||
.leftJoin('faces.person', 'person')
|
.leftJoin('faces.person', 'person')
|
||||||
.orWhere('person.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
.orWhere('person.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!searchType || searchType === SearchTypes.position) {
|
if (!searchType || searchType === SearchTypes.position) {
|
||||||
subQuery.orWhere('media.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
subQuery.orWhere('media.metadata.positionData.country LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('media.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('media.metadata.positionData.state LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('media.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
.orWhere('media.metadata.positionData.city LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'});
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!searchType || searchType === SearchTypes.keyword) {
|
if (!searchType || searchType === SearchTypes.keyword) {
|
||||||
subQuery.orWhere('media.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'});
|
subQuery.orWhere('media.metadata.keywords LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'});
|
||||||
}
|
}
|
||||||
|
|
||||||
return subQuery;
|
return subQuery;
|
||||||
@ -187,7 +187,7 @@ export class SearchManager implements ISearchManager {
|
|||||||
result.directories = await connection
|
result.directories = await connection
|
||||||
.getRepository(DirectoryEntity)
|
.getRepository(DirectoryEntity)
|
||||||
.createQueryBuilder('dir')
|
.createQueryBuilder('dir')
|
||||||
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.where('dir.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.limit(201)
|
.limit(201)
|
||||||
.getMany();
|
.getMany();
|
||||||
|
|
||||||
@ -217,13 +217,13 @@ export class SearchManager implements ISearchManager {
|
|||||||
.leftJoin('media.directory', 'directory')
|
.leftJoin('media.directory', 'directory')
|
||||||
.leftJoin('media.metadata.faces', 'faces')
|
.leftJoin('media.metadata.faces', 'faces')
|
||||||
.leftJoin('faces.person', 'person')
|
.leftJoin('faces.person', 'person')
|
||||||
.where('media.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.where('media.metadata.keywords LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('media.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('media.metadata.positionData.country LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('media.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('media.metadata.positionData.state LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('media.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('media.metadata.positionData.city LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('media.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('media.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('media.metadata.caption LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('media.metadata.caption LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.orWhere('person.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.orWhere('person.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
,
|
,
|
||||||
'innerMedia',
|
'innerMedia',
|
||||||
'media.id=innerMedia.id')
|
'media.id=innerMedia.id')
|
||||||
@ -238,7 +238,7 @@ export class SearchManager implements ISearchManager {
|
|||||||
result.directories = await connection
|
result.directories = await connection
|
||||||
.getRepository(DirectoryEntity)
|
.getRepository(DirectoryEntity)
|
||||||
.createQueryBuilder('dir')
|
.createQueryBuilder('dir')
|
||||||
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
|
.where('dir.name LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + text + '%'})
|
||||||
.limit(10)
|
.limit(10)
|
||||||
.getMany();
|
.getMany();
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import {Column, Entity, Index, ManyToOne, OneToMany, PrimaryGeneratedColumn, Uni
|
|||||||
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
|
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
|
||||||
import {MediaEntity} from './MediaEntity';
|
import {MediaEntity} from './MediaEntity';
|
||||||
import {FileEntity} from './FileEntity';
|
import {FileEntity} from './FileEntity';
|
||||||
|
import {columnCharsetCS} from './EntityUtils';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Unique(['name', 'path'])
|
@Unique(['name', 'path'])
|
||||||
@ -12,7 +13,7 @@ export class DirectoryEntity implements DirectoryDTO {
|
|||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
@Column()
|
@Column(columnCharsetCS)
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
|
17
backend/model/sql/enitites/EntityUtils.ts
Normal file
17
backend/model/sql/enitites/EntityUtils.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import {Config} from '../../../../common/config/private/Config';
|
||||||
|
import {DatabaseType} from '../../../../common/config/private/IPrivateConfig';
|
||||||
|
import {ColumnOptions} from 'typeorm/decorator/options/ColumnOptions';
|
||||||
|
|
||||||
|
export class ColumnCharsetCS implements ColumnOptions {
|
||||||
|
|
||||||
|
public get charset(): string {
|
||||||
|
return Config.Server.database.type === DatabaseType.mysql ? 'utf8mb4' : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get collation(): string {
|
||||||
|
return Config.Server.database.type === DatabaseType.mysql ? 'utf8mb4_bin' : null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const columnCharsetCS = new ColumnCharsetCS();
|
@ -1,6 +1,7 @@
|
|||||||
import {Column, Entity, ManyToOne, PrimaryGeneratedColumn, Index} from 'typeorm';
|
import {Column, Entity, ManyToOne, PrimaryGeneratedColumn, Index} from 'typeorm';
|
||||||
import {DirectoryEntity} from './DirectoryEntity';
|
import {DirectoryEntity} from './DirectoryEntity';
|
||||||
import {FileDTO} from '../../../../common/entities/FileDTO';
|
import {FileDTO} from '../../../../common/entities/FileDTO';
|
||||||
|
import {columnCharsetCS} from './EntityUtils';
|
||||||
|
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@ -10,7 +11,7 @@ export class FileEntity implements FileDTO {
|
|||||||
@PrimaryGeneratedColumn({unsigned: true})
|
@PrimaryGeneratedColumn({unsigned: true})
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
@Column('text')
|
@Column(columnCharsetCS)
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
|
@ -4,6 +4,9 @@ import {MediaDimension, MediaDTO, MediaMetadata} from '../../../../common/entiti
|
|||||||
import {OrientationTypes} from 'ts-exif-parser';
|
import {OrientationTypes} from 'ts-exif-parser';
|
||||||
import {CameraMetadataEntity, PositionMetaDataEntity} from './PhotoEntity';
|
import {CameraMetadataEntity, PositionMetaDataEntity} from './PhotoEntity';
|
||||||
import {FaceRegionEntry} from './FaceRegionEntry';
|
import {FaceRegionEntry} from './FaceRegionEntry';
|
||||||
|
import {Config} from '../../../../common/config/private/Config';
|
||||||
|
import {DatabaseType} from '../../../../common/config/private/IPrivateConfig';
|
||||||
|
import {columnCharsetCS} from './EntityUtils';
|
||||||
|
|
||||||
export class MediaDimensionEntity implements MediaDimension {
|
export class MediaDimensionEntity implements MediaDimension {
|
||||||
|
|
||||||
@ -55,6 +58,8 @@ export class MediaMetadataEntity implements MediaMetadata {
|
|||||||
duration: number;
|
duration: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: fix inheritance once its working in typeorm
|
// TODO: fix inheritance once its working in typeorm
|
||||||
@Entity()
|
@Entity()
|
||||||
@Unique(['name', 'directory'])
|
@Unique(['name', 'directory'])
|
||||||
@ -65,7 +70,7 @@ export abstract class MediaEntity implements MediaDTO {
|
|||||||
@PrimaryGeneratedColumn({unsigned: true})
|
@PrimaryGeneratedColumn({unsigned: true})
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
@Column()
|
@Column(columnCharsetCS)
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@Index()
|
@Index()
|
||||||
|
28
common/entities/TaskDTO.ts
Normal file
28
common/entities/TaskDTO.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
export interface TaskType {
|
||||||
|
name: string;
|
||||||
|
parameter: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TaskTriggerType {
|
||||||
|
scheduled, periodic
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskTrigger {
|
||||||
|
type: TaskTriggerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ScheduledTaskTrigger extends TaskTrigger {
|
||||||
|
type: TaskTriggerType.scheduled;
|
||||||
|
time: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PeriodicTaskTrigger extends TaskTrigger {
|
||||||
|
type: TaskTriggerType.periodic;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TaskDTO {
|
||||||
|
priority: number;
|
||||||
|
type: TaskType;
|
||||||
|
trigger: TaskTrigger;
|
||||||
|
}
|
@ -184,7 +184,7 @@ describe('Typeorm integration', () => {
|
|||||||
const photos = await pr
|
const photos = await pr
|
||||||
.createQueryBuilder('media')
|
.createQueryBuilder('media')
|
||||||
.orderBy('media.metadata.creationDate', 'ASC')
|
.orderBy('media.metadata.creationDate', 'ASC')
|
||||||
.where('media.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + photo.metadata.positionData.city + '%'})
|
.where('media.metadata.positionData.city LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + photo.metadata.positionData.city + '%'})
|
||||||
.innerJoinAndSelect('media.directory', 'directory')
|
.innerJoinAndSelect('media.directory', 'directory')
|
||||||
.limit(10)
|
.limit(10)
|
||||||
.getMany();
|
.getMany();
|
||||||
@ -206,7 +206,7 @@ describe('Typeorm integration', () => {
|
|||||||
const photos = await pr
|
const photos = await pr
|
||||||
.createQueryBuilder('media')
|
.createQueryBuilder('media')
|
||||||
.orderBy('media.metadata.creationDate', 'ASC')
|
.orderBy('media.metadata.creationDate', 'ASC')
|
||||||
.where('media.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + city + '%'})
|
.where('media.metadata.positionData.city LIKE :text COLLATE utf8mb4_general_ci', {text: '%' + city + '%'})
|
||||||
.innerJoinAndSelect('media.directory', 'directory')
|
.innerJoinAndSelect('media.directory', 'directory')
|
||||||
.limit(10)
|
.limit(10)
|
||||||
.getMany();
|
.getMany();
|
||||||
|
@ -44,6 +44,7 @@ class IndexingManagerTest extends IndexingManager {
|
|||||||
// to help WebStorm to handle the test cases
|
// to help WebStorm to handle the test cases
|
||||||
declare let describe: any;
|
declare let describe: any;
|
||||||
declare const after: any;
|
declare const after: any;
|
||||||
|
declare const it: any;
|
||||||
describe = SQLTestHelper.describe;
|
describe = SQLTestHelper.describe;
|
||||||
|
|
||||||
describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
|
describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
|
||||||
@ -80,6 +81,29 @@ describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
it('should support case sensitive file names', async () => {
|
||||||
|
const gm = new GalleryManagerTest();
|
||||||
|
const im = new IndexingManagerTest();
|
||||||
|
|
||||||
|
const parent = TestHelper.getRandomizedDirectoryEntry();
|
||||||
|
const p1 = TestHelper.getRandomizedPhotoEntry(parent, 'Photo1');
|
||||||
|
const p2 = TestHelper.getRandomizedPhotoEntry(parent, 'Photo2');
|
||||||
|
p1.name = 'test.jpg';
|
||||||
|
p2.name = 'Test.jpg';
|
||||||
|
|
||||||
|
DirectoryDTO.removeReferences(parent);
|
||||||
|
await im.saveToDB(Utils.clone(parent));
|
||||||
|
|
||||||
|
const conn = await SQLConnection.getConnection();
|
||||||
|
const selected = await gm.selectParentDir(conn, parent.name, parent.path);
|
||||||
|
await gm.fillParentDir(conn, selected);
|
||||||
|
|
||||||
|
DirectoryDTO.removeReferences(selected);
|
||||||
|
removeIds(selected);
|
||||||
|
expect(Utils.clone(Utils.removeNullOrEmptyObj(selected)))
|
||||||
|
.to.deep.equal(Utils.clone(Utils.removeNullOrEmptyObj(parent)));
|
||||||
|
});
|
||||||
|
|
||||||
it('should save parent directory', async () => {
|
it('should save parent directory', async () => {
|
||||||
const gm = new GalleryManagerTest();
|
const gm = new GalleryManagerTest();
|
||||||
const im = new IndexingManagerTest();
|
const im = new IndexingManagerTest();
|
||||||
|
Reference in New Issue
Block a user