|
|
@ -61,15 +61,13 @@ export function do_tag_query(query, database) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export const MatchTypeEnum = { |
|
|
|
export const MatchTypeEnum = { |
|
|
|
MATCH_EQUALS: 1, |
|
|
|
MATCH_IMAGE_NAME_EQUALS: 1, |
|
|
|
MATCH_NATURAL: 2, |
|
|
|
MATCH_IMAGE_NAME_NATURAL: 2, |
|
|
|
}; |
|
|
|
MATCH_ALBUM_EQUALS: 3, // Match on the full name (relative path) of the relevant album, if any
|
|
|
|
|
|
|
|
MATCH_ALBUM_EQUALS_OR_CHILD: 4, // Match on the full name (relative path) of the relevant album, if any, or any of its children
|
|
|
|
export const MatchAgainstEnum = { |
|
|
|
MATCH_ALBUM_NATURAL: 5, |
|
|
|
MATCH_IMAGE_NAME: 1, // Match on the name of the relevant image(s), if any
|
|
|
|
MATCH_ALBUM_NAME_EQUALS: 6, // Match on the local album name (excluding parents)
|
|
|
|
MATCH_ALBUM_NAME: 2, // Match on the name of the relevant album(s), if any
|
|
|
|
MATCH_TAG_EQUALS: 7, // Match on the name of the relevant tag(s), if any
|
|
|
|
MATCH_ALBUM_NAME_IN_TREE: 3, // Match on any album name in the album tree branch, including parents
|
|
|
|
|
|
|
|
MATCH_TAG_NAME: 4, // Match on the name of the relevant tag(s), if any
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export const ResultTypeEnum = { |
|
|
|
export const ResultTypeEnum = { |
|
|
@ -116,10 +114,10 @@ export class NegationFilter extends ResultFilter { |
|
|
|
|
|
|
|
|
|
|
|
simplify() { |
|
|
|
simplify() { |
|
|
|
var f = this.body.simplify(); |
|
|
|
var f = this.body.simplify(); |
|
|
|
if(f.is_true()) { |
|
|
|
if (f.is_true()) { |
|
|
|
return new ConstFilter(this.result_type, false); |
|
|
|
return new ConstFilter(this.result_type, false); |
|
|
|
} |
|
|
|
} |
|
|
|
if(f.is_false()) { |
|
|
|
if (f.is_false()) { |
|
|
|
return new ConstFilter(this.result_type, true); |
|
|
|
return new ConstFilter(this.result_type, true); |
|
|
|
} |
|
|
|
} |
|
|
|
return this; |
|
|
|
return this; |
|
|
@ -127,52 +125,39 @@ export class NegationFilter extends ResultFilter { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export class MatchingFilter extends ResultFilter { |
|
|
|
export class MatchingFilter extends ResultFilter { |
|
|
|
constructor(rtype, against, from, mtype) { |
|
|
|
constructor(rtype, from, mtype) { |
|
|
|
super(rtype); |
|
|
|
super(rtype); |
|
|
|
this.match_against = against; |
|
|
|
|
|
|
|
this.match_from = from; |
|
|
|
this.match_from = from; |
|
|
|
this.match_type = mtype; |
|
|
|
this.match_type = mtype; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// What string to match against.
|
|
|
|
|
|
|
|
match_against = MatchAgainstEnum.MATCH_IMAGE_NAME; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// optional string used in the filtering
|
|
|
|
// optional string used in the filtering
|
|
|
|
match_from = ""; |
|
|
|
match_from = ""; |
|
|
|
|
|
|
|
|
|
|
|
// How to use the matching string
|
|
|
|
// What and how to match
|
|
|
|
match_type = MatchTypeEnum.MATCH_EQUALS; |
|
|
|
match_type = MatchTypeEnum.MATCH_IMAGE_NAME_EQUALS; |
|
|
|
|
|
|
|
|
|
|
|
to_sql_where() { |
|
|
|
to_sql_where() { |
|
|
|
var expr; |
|
|
|
if (this.match_type == MatchTypeEnum.MATCH_IMAGE_NAME_EQUALS) { |
|
|
|
if(this.match_against === MatchAgainstEnum.MATCH_IMAGE_NAME) { |
|
|
|
|
|
|
|
if(this.match_type === MatchTypeEnum.MATCH_EQUALS) { |
|
|
|
|
|
|
|
return '(Images.name="' + this.match_from + '")'; |
|
|
|
return '(Images.name="' + this.match_from + '")'; |
|
|
|
} else if(this.match_type === MatchTypeEnum.MATCH_NATURAL) { |
|
|
|
} else if (this.match_type == MatchTypeEnum.MATCH_IMAGE_NAME_NATURAL) { |
|
|
|
expr = '".*' + escape_regex(this.match_from) + '.*"'; |
|
|
|
return '(LOWER(Images.name) REGEXP LOWER(".*' |
|
|
|
return "(LOWER(Images.name) REGEXP LOWER(" + expr +"))"; |
|
|
|
+ escape_regex(this.match_from) |
|
|
|
} |
|
|
|
+ ')).*"'; |
|
|
|
} else if(this.match_against === MatchAgainstEnum.MATCH_TAG_NAME) { |
|
|
|
} else if (this.match_type == MatchTypeEnum.MATCH_ALBUM_EQUALS) { |
|
|
|
if(this.match_type === MatchTypeEnum.MATCH_EQUALS) { |
|
|
|
return '(Albums.relativePath = "' + this.match_from + '")'; |
|
|
|
return '(Tags.name="' + this.match_from + '")'; |
|
|
|
} else if (this.match_type == MatchTypeEnum.MATCH_ALBUM_EQUALS_OR_CHILD) { |
|
|
|
} else if(this.match_type === MatchTypeEnum.MATCH_NATURAL) { |
|
|
|
return '(Albums.relativePath REGEXP "' |
|
|
|
expr = '".*' + escape_regex(this.match_from) + '.*"'; |
|
|
|
+ escape_regex(this.match_from) |
|
|
|
return '(LOWER(Tags.name) REGEXP LOWER("' + expr + '"))'; |
|
|
|
+ '(\/[^\/]+)*")'; |
|
|
|
} |
|
|
|
} else if (this.match_type == MatchTypeEnum.MATCH_ALBUM_NATURAL) { |
|
|
|
} else if(this.match_against === MatchAgainstEnum.MATCH_ALBUM_NAME) { |
|
|
|
|
|
|
|
if(this.match_type === MatchTypeEnum.MATCH_EQUALS) { |
|
|
|
|
|
|
|
expr = '\/(.*\/)*' + escape_regex(this.match_from); |
|
|
|
|
|
|
|
return '(Albums.relativePath REGEXP "' + expr + '")'; |
|
|
|
|
|
|
|
} else if(this.match_type === MatchTypeEnum.MATCH_NATURAL) { |
|
|
|
|
|
|
|
throw new Error("Natural matching on album names is not yet supported."); |
|
|
|
throw new Error("Natural matching on album names is not yet supported."); |
|
|
|
} |
|
|
|
} else if (this.match_type == MatchTypeEnum.MATCH_ALBUM_NAME_EQUALS) { |
|
|
|
} else if(this.match_against === MatchAgainstEnum.MATCH_ALBUM_NAME_IN_TREE) { |
|
|
|
return '(Albums.relativePath REGEXP "\/(.*\/)*' |
|
|
|
if(this.match_type === MatchTypeEnum.MATCH_EQUALS) { |
|
|
|
+ escape_regex(this.match_from) |
|
|
|
expr = escape_regex(this.match_from) + '(\/[^\/]+)*'; |
|
|
|
+ '(\/[^\/]+)*")'; |
|
|
|
return '(Albums.relativePath REGEXP "' + expr + '")'; |
|
|
|
} else if (this.match_type == MatchTypeEnum.MATCH_TAG_EQUALS) { |
|
|
|
} else if(this.match_type === MatchTypeEnum.MATCH_NATURAL) { |
|
|
|
return '(Tags.name="' + this.match_from + '")'; |
|
|
|
throw new Error("Natural matching on album tree names is not yet supported."); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log(this); |
|
|
|
console.log(this); |
|
|
@ -210,20 +195,20 @@ export class LogicalOperatorFilter extends ResultFilter { |
|
|
|
var a = this.sub_filter_a.simplify(); |
|
|
|
var a = this.sub_filter_a.simplify(); |
|
|
|
var b = this.sub_filter_b.simplify(); |
|
|
|
var b = this.sub_filter_b.simplify(); |
|
|
|
|
|
|
|
|
|
|
|
if(this.operator === LogicalOperatorEnum.OR) { |
|
|
|
if (this.operator === LogicalOperatorEnum.OR) { |
|
|
|
if(a.is_true() || b.is_true()) { |
|
|
|
if (a.is_true() || b.is_true()) { |
|
|
|
return new ConstFilter(this.return_type, true); |
|
|
|
return new ConstFilter(this.return_type, true); |
|
|
|
} |
|
|
|
} |
|
|
|
if(a.is_false()) { return b; } |
|
|
|
if (a.is_false()) { return b; } |
|
|
|
if(b.is_false()) { return a; } |
|
|
|
if (b.is_false()) { return a; } |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(this.operator === LogicalOperatorEnum.AND) { |
|
|
|
if (this.operator === LogicalOperatorEnum.AND) { |
|
|
|
if(a.is_false() || b.is_false()) { |
|
|
|
if (a.is_false() || b.is_false()) { |
|
|
|
return new ConstFilter(this.return_type, false); |
|
|
|
return new ConstFilter(this.return_type, false); |
|
|
|
} |
|
|
|
} |
|
|
|
if(a.is_true()) { return b; } |
|
|
|
if (a.is_true()) { return b; } |
|
|
|
if(b.is_true()) { return a; } |
|
|
|
if (b.is_true()) { return a; } |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return this; |
|
|
|
return this; |
|
|
@ -278,7 +263,7 @@ export function maybe_tag_query(user_query) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function filter_is_const_false(filter) { |
|
|
|
export function filter_is_const_false(filter) { |
|
|
|
if(filter instanceof ConstFilter && filter.constval === false) { |
|
|
|
if (filter instanceof ConstFilter && filter.constval === false) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
// TODO resolve recursively
|
|
|
|
// TODO resolve recursively
|
|
|
@ -293,45 +278,41 @@ function filter_from_text_segment(result_type, segment) { |
|
|
|
// Option 1: match on image name
|
|
|
|
// Option 1: match on image name
|
|
|
|
name_filter = new MatchingFilter( |
|
|
|
name_filter = new MatchingFilter( |
|
|
|
result_type, |
|
|
|
result_type, |
|
|
|
MatchAgainstEnum.MATCH_IMAGE_NAME, |
|
|
|
|
|
|
|
segment['text'], |
|
|
|
segment['text'], |
|
|
|
MatchTypeEnum.MATCH_NATURAL |
|
|
|
MatchTypeEnum.MATCH_IMAGE_NAME_NATURAL |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// Option 2: match on album path
|
|
|
|
// Option 2: match on album path (TODO: need natural matching)
|
|
|
|
var album_filter = new MatchingFilter( |
|
|
|
var album_filter = new MatchingFilter( |
|
|
|
result_type, |
|
|
|
result_type, |
|
|
|
MatchAgainstEnum.MATCH_ALBUM_NAME, |
|
|
|
|
|
|
|
segment['text'], |
|
|
|
segment['text'], |
|
|
|
MatchTypeEnum.MATCH_EQUALS |
|
|
|
MatchTypeEnum.MATCH_ALBUM_NAME_EQUALS |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
filter = new LogicalOperatorFilter(result_type, name_filter, album_filter, LogicalOperatorEnum.OR); |
|
|
|
filter = new LogicalOperatorFilter(result_type, name_filter, album_filter, LogicalOperatorEnum.OR); |
|
|
|
if(segment['negated']) { |
|
|
|
if (segment['negated']) { |
|
|
|
filter = new NegationFilter(result_type, filter); |
|
|
|
filter = new NegationFilter(result_type, filter); |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (result_type === ResultTypeEnum.ALBUM) { |
|
|
|
} else if (result_type === ResultTypeEnum.ALBUM) { |
|
|
|
// TODO: We need a natural matcher for album names
|
|
|
|
// TODO: We need a natural matcher for album names
|
|
|
|
name_filter = new MatchingFilter( |
|
|
|
name_filter = new MatchingFilter( |
|
|
|
result_type, |
|
|
|
result_type, |
|
|
|
MatchAgainstEnum.MATCH_ALBUM_NAME, |
|
|
|
|
|
|
|
segment['text'], |
|
|
|
segment['text'], |
|
|
|
MatchTypeEnum.MATCH_EQUALS |
|
|
|
MatchTypeEnum.MATCH_ALBUM_NAME_EQUALS |
|
|
|
); |
|
|
|
); |
|
|
|
filter = name_filter; |
|
|
|
filter = name_filter; |
|
|
|
if(segment['negated']) { |
|
|
|
if (segment['negated']) { |
|
|
|
filter = new NegationFilter(result_type, filter); |
|
|
|
filter = new NegationFilter(result_type, filter); |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (result_type === ResultTypeEnum.TAG) { |
|
|
|
} else if (result_type === ResultTypeEnum.TAG) { |
|
|
|
// Match against the tag name.
|
|
|
|
// Match against the tag name.
|
|
|
|
name_filter = new MatchingFilter( |
|
|
|
name_filter = new MatchingFilter( |
|
|
|
result_type, |
|
|
|
result_type, |
|
|
|
MatchAgainstEnum.MATCH_TAG_NAME, |
|
|
|
|
|
|
|
segment['text'], |
|
|
|
segment['text'], |
|
|
|
MatchTypeEnum.MATCH_EQUALS |
|
|
|
MatchTypeEnum.MATCH_TAG_NAME_EQUALS |
|
|
|
); |
|
|
|
); |
|
|
|
filter = name_filter; |
|
|
|
filter = name_filter; |
|
|
|
if(segment['negated']) { |
|
|
|
if (segment['negated']) { |
|
|
|
filter = new NegationFilter(result_type, filter); |
|
|
|
filter = new NegationFilter(result_type, filter); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -362,10 +343,11 @@ export function user_query_from_search_string(search_string) { |
|
|
|
|
|
|
|
|
|
|
|
export function user_query_from_browsed_album(album_path) { |
|
|
|
export function user_query_from_browsed_album(album_path) { |
|
|
|
var r = new UserQuery(); |
|
|
|
var r = new UserQuery(); |
|
|
|
var match_type = MatchTypeEnum.MATCH_EQUALS; |
|
|
|
r.image_filter = new MatchingFilter( |
|
|
|
var match_against = MatchAgainstEnum.MATCH_ALBUM_NAME_IN_TREE; |
|
|
|
ResultTypeEnum.IMAGE, |
|
|
|
var match_text = album_path; |
|
|
|
album_path, |
|
|
|
r.image_filter = new MatchingFilter(ResultTypeEnum.IMAGE, match_against, match_text, match_type, false).simplify(); |
|
|
|
MatchTypeEnum.MATCH_ALBUM_EQUALS_OR_CHILD, |
|
|
|
|
|
|
|
false).simplify(); |
|
|
|
r.album_filter = new ConstFilter(ResultTypeEnum.ALBUM, false).simplify(); |
|
|
|
r.album_filter = new ConstFilter(ResultTypeEnum.ALBUM, false).simplify(); |
|
|
|
|
|
|
|
|
|
|
|
return r; |
|
|
|
return r; |
|
|
@ -373,10 +355,11 @@ export function user_query_from_browsed_album(album_path) { |
|
|
|
|
|
|
|
|
|
|
|
export function user_query_from_browsed_tag(name) { |
|
|
|
export function user_query_from_browsed_tag(name) { |
|
|
|
var r = new UserQuery(); |
|
|
|
var r = new UserQuery(); |
|
|
|
var match_type = MatchTypeEnum.MATCH_EQUALS; |
|
|
|
r.image_filter = new MatchingFilter( |
|
|
|
var match_text = name; |
|
|
|
ResultTypeEnum.IMAGE, |
|
|
|
var match_against = MatchAgainstEnum.MATCH_TAG_NAME; |
|
|
|
name, |
|
|
|
r.image_filter = new MatchingFilter(ResultTypeEnum.IMAGE, match_against, match_text, match_type, false).simplify(); |
|
|
|
MatchTypeEnum.MATCH_TAG_EQUALS, |
|
|
|
|
|
|
|
false).simplify(); |
|
|
|
r.album_filter = new ConstFilter(ResultTypeEnum.ALBUM, false).simplify(); |
|
|
|
r.album_filter = new ConstFilter(ResultTypeEnum.ALBUM, false).simplify(); |
|
|
|
r.tag_filter = new ConstFilter(ResultTypeEnum.TAG, false).simplify(); |
|
|
|
r.tag_filter = new ConstFilter(ResultTypeEnum.TAG, false).simplify(); |
|
|
|
|
|
|
|
|
|
|
|