Skip to content

Commit

Permalink
feat(minato): impl $.regex (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hieuzest authored Jan 30, 2024
1 parent b15354a commit 70109f6
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 8 deletions.
11 changes: 5 additions & 6 deletions packages/mongo/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,9 @@ function transformFieldQuery(query: Query.FieldQuery, key: string, filters: Filt
} else if (prop === '$regexFor') {
filters.push({
$expr: {
$function: {
body: function (data: string, value: string) {
return new RegExp(data, 'i').test(value)
}.toString(),
args: ['$' + key, query.$regexFor],
lang: 'js',
$regexMatch: {
input: query[prop],
regex: '$' + key,
},
},
})
Expand Down Expand Up @@ -105,6 +102,8 @@ export class Transformer {
$array: (arg, group) => this.transformEvalExpr(arg),
$object: (arg, group) => this.transformEvalExpr(arg),

$regex: (arg, group) => ({ $regexMatch: { input: this.eval(arg[0], group), regex: this.eval(arg[1], group) } }),

$length: (arg, group) => ({ $size: this.eval(arg, group) }),
$nin: (arg, group) => ({ $not: { $in: arg.map(val => this.eval(val, group)) } }),

Expand Down
2 changes: 2 additions & 0 deletions packages/mysql/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ class MySQLBuilder extends Builder {
escape(value: any, field?: Field<any>) {
if (value instanceof Date) {
value = Time.template('yyyy-MM-dd hh:mm:ss', value)
} else if (value instanceof RegExp) {
value = value.source
} else if (!field && !!value && typeof value === 'object') {
return `json_extract(${this.quote(JSON.stringify(value))}, '$')`
}
Expand Down
6 changes: 5 additions & 1 deletion packages/postgres/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ class PostgresBuilder extends Builder {
return `coalesce(${args.map(arg => this.parseEval(arg, type)).join(', ')})`
},

$regex: ([key, value]) => `${this.parseEval(key)} ~ ${this.parseEval(value)}`,

// number
$add: (args) => `(${args.map(arg => this.parseEval(arg, 'double precision')).join(' + ')})`,
$multiply: (args) => `(${args.map(arg => this.parseEval(arg, 'double precision')).join(' * ')})`,
Expand Down Expand Up @@ -291,7 +293,7 @@ class PostgresBuilder extends Builder {

parseEval(expr: any, outtype: boolean | string = false): string {
this.state.sqlType = 'raw'
if (typeof expr === 'string' || typeof expr === 'number' || typeof expr === 'boolean' || expr instanceof Date) {
if (typeof expr === 'string' || typeof expr === 'number' || typeof expr === 'boolean' || expr instanceof Date || expr instanceof RegExp) {
return this.escape(expr)
}
return outtype ? this.jsonUnquote(this.parseEvalExpr(expr), false, typeof outtype === 'string' ? outtype : undefined) : this.parseEvalExpr(expr)
Expand Down Expand Up @@ -373,6 +375,8 @@ class PostgresBuilder extends Builder {
escape(value: any, field?: Field<any>) {
if (value instanceof Date) {
value = formatTime(value)
} else if (value instanceof RegExp) {
value = value.source
} else if (!field && !!value && typeof value === 'object') {
return `${this.quote(JSON.stringify(value))}::jsonb`
}
Expand Down
3 changes: 2 additions & 1 deletion packages/sql-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export class Builder {

// string
$concat: (args) => `concat(${args.map(arg => this.parseEval(arg)).join(', ')})`,
$regex: ([key, value]) => `${this.parseEval(key)} regexp ${this.parseEval(value)}`,

// logical
$or: (args) => this.logicalOr(args.map(arg => this.parseEval(arg))),
Expand Down Expand Up @@ -390,7 +391,7 @@ export class Builder {

parseEval(expr: any, unquote: boolean = true): string {
this.state.sqlType = 'raw'
if (typeof expr === 'string' || typeof expr === 'number' || typeof expr === 'boolean' || expr instanceof Date) {
if (typeof expr === 'string' || typeof expr === 'number' || typeof expr === 'boolean' || expr instanceof Date || expr instanceof RegExp) {
return this.escape(expr)
}
return unquote ? this.jsonUnquote(this.parseEvalExpr(expr)) : this.parseEvalExpr(expr)
Expand Down
1 change: 1 addition & 0 deletions packages/sqlite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class SQLiteBuilder extends Builder {

escape(value: any, field?: Field<any>) {
if (value instanceof Date) value = +value
else if (value instanceof RegExp) value = value.source
return super.escape(value, field)
}

Expand Down
8 changes: 8 additions & 0 deletions packages/tests/src/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,14 @@ namespace QueryOperators {
text: /^.*foo$/,
})).eventually.to.have.length(1).with.nested.property('[0].text').equal('awesome foo')
})

regexBy && regexFor && it('$.regex', async () => {
await expect(database.get('temp1', row => $.regex('foo bar', row.regex))).eventually.to.have.length(2)
await expect(database.get('temp1', row => $.regex('baz', row.regex))).eventually.to.have.length(1)
await expect(database.get('temp1', row => $.regex(row.text, /^.*foo.*$/))).eventually.to.have.length(2)
await expect(database.get('temp1', row => $.regex(row.text, /^.*bar.*$/))).eventually.to.have.length(2)
await expect(database.get('temp1', row => $.regex(row.text, row.regex))).eventually.to.have.length(2)
})
}

export const bitwise = function Bitwise(database: Database<Tables>) {
Expand Down

0 comments on commit 70109f6

Please sign in to comment.