Skip to content

Commit 3e31d3a

Browse files
committed
json selectors in where
1 parent 25a7253 commit 3e31d3a

5 files changed

Lines changed: 101 additions & 51 deletions

File tree

packages/inquire-pglite/tests/Connection.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,21 @@ describe('Connection Tests', () => {
165165
expect(nested[0].references.foo).to.equal('bar');
166166
expect(nested[0].active).to.equal(false);
167167
expect(nested[0].created).to.be.instanceOf(Date);
168+
169+
const native = await engine
170+
.select<Profile>('*')
171+
.from('profile')
172+
.where('references:foo = ?', [ 'bar' ]);
173+
174+
expect(native.length).to.equal(1);
175+
expect(native[0].id).to.equal(2);
176+
expect(native[0].name).to.equal('Jane Doe');
177+
expect(native[0].age).to.equal(31);
178+
expect(native[0].tags[0]).to.equal('foo');
179+
expect(native[0].tags[1]).to.equal('zoo');
180+
expect(native[0].references.foo).to.equal('bar');
181+
expect(native[0].active).to.equal(false);
182+
expect(native[0].created).to.be.instanceOf(Date);
168183
}).timeout(20000);
169184

170185
it('Should filter by json array', async () => {

packages/inquire/src/builder/Select.ts

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,11 @@ export default class Select<R = unknown> implements WhereBuilder {
4848
*/
4949
protected _offset: number = 0;
5050

51-
/**
52-
* Notation used to indicate to traverse through JSON
53-
* columns, default is colon (ex. data:info.name)
54-
*/
55-
protected _selector = ':';
56-
5751
/**
5852
* The columns to select.
5953
*/
6054
protected _selectors: Selector[] = [];
6155

62-
/**
63-
* The separator for JSON selectors,
64-
* default is dot (ex. data.info.name)
65-
*/
66-
protected _separator = '.';
67-
6856
/**
6957
* The sort order.
7058
*/
@@ -88,22 +76,6 @@ export default class Select<R = unknown> implements WhereBuilder {
8876
public set engine(engine: Engine | undefined) {
8977
this._engine = engine;
9078
}
91-
92-
/**
93-
* Sets the notation used to indicate to traverse through JSON
94-
* columns, default is colon (ex. data:info.name)
95-
*/
96-
public set selector(selector: string) {
97-
this._selector = selector;
98-
}
99-
100-
/**
101-
* Sets the separator for JSON selectors,
102-
* default is dot (ex. data.info.name)
103-
*/
104-
public set separator(separator: string) {
105-
this._separator = separator;
106-
}
10779

10880
/**
10981
* Set select, quote and action
@@ -127,8 +99,6 @@ export default class Select<R = unknown> implements WhereBuilder {
12799
limit: this._limit,
128100
offset: this._offset,
129101
selectors: this._selectors,
130-
selector: this._selector,
131-
separator: this._separator,
132102
sort: this._sort,
133103
where: this._where
134104
}

packages/inquire/src/dialect/Mysql.ts

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ export class MysqlDialect implements Dialect {
4747
//Recommended quote character
4848
public readonly q = q;
4949

50+
//used for json notation
51+
public separator: string = '.';
52+
public splitter: string = ':';
53+
5054
/**
5155
* Converts alter builder to query and values
5256
*/
@@ -485,6 +489,7 @@ export class MysqlDialect implements Dialect {
485489
});
486490

487491
query.push(`SELECT ${columns.join(', ')}`);
492+
488493
const table = `${this.q}${build.from.name}${this.q}`;
489494
if (build.from.alias) {
490495
const alias = `${this.q}${build.from.alias}${this.q}`;
@@ -514,17 +519,34 @@ export class MysqlDialect implements Dialect {
514519
if (build.where.length > 0 || build.json.length > 0) {
515520
const filters: string[] = [];
516521
if (build.where.length) {
517-
filters.push(...build.where.map(filter => {
518-
values.push(...filter.values);
519-
return filter.clause;
520-
}));
522+
//find json phrases
523+
// - ex. data:info.name
524+
// - ex. profile.data:info
525+
// - ex. profile.data:info.name
526+
const jsonSelector = new RegExp(
527+
`([a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+){0,1}\\${this.splitter}`
528+
+ `[a-zA-Z0-9_]+(\\${this.separator}[a-zA-Z0-9_]+)*)`,
529+
'g'
530+
);
531+
filters.push(...build.where.map(filter => {
532+
values.push(...filter.values);
533+
//then replace with XJsonDialect.parse().extract
534+
return filter.clause.replace(jsonSelector, match => {
535+
const json = MysqlJsonDialect.parse(
536+
match,
537+
this.splitter,
538+
this.separator
539+
);
540+
return json ? json.extract : match;
541+
});
542+
}));
521543
}
522544
build.json.forEach(filter => {
523545
const { query, replace } = filter;
524546
const json = MysqlJsonDialect.parse(
525547
filter.selector,
526-
build.selector,
527-
build.separator
548+
this.splitter,
549+
this.separator
528550
);
529551
//if invalid JSON selector, skip it
530552
if (!json) return;
@@ -563,11 +585,11 @@ export class MysqlDialect implements Dialect {
563585
if (build.sort.length) {
564586
const sort = build.sort.map(sort => {
565587
//if the sort column is using the selector ":" notation
566-
if (sort.column.name.includes(build.selector)) {
588+
if (sort.column.name.includes(this.splitter)) {
567589
const json = MysqlJsonDialect.parse(
568590
sort.column.name,
569-
build.selector,
570-
build.separator
591+
this.splitter,
592+
this.separator
571593
);
572594
//if invalid JSON selector, skip it
573595
if (!json) return '';

packages/inquire/src/dialect/Pgsql.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ export class PgsqlDialect implements Dialect {
4848
//Recommended quote character
4949
public readonly q = q;
5050

51+
//used for json notation
52+
public separator: string = '.';
53+
public splitter: string = ':';
54+
5155
/**
5256
* Converts alter builder to query and values
5357
*/
@@ -500,6 +504,7 @@ export class PgsqlDialect implements Dialect {
500504
});
501505

502506
query.push(`SELECT ${columns.join(', ')}`);
507+
503508
const table = `${this.q}${build.from.name}${this.q}`;
504509
if (build.from.alias) {
505510
const alias = `${this.q}${build.from.alias}${this.q}`;
@@ -529,18 +534,35 @@ export class PgsqlDialect implements Dialect {
529534
if (build.where.length > 0 || build.json.length > 0) {
530535
const filters: string[] = [];
531536
if (build.where.length) {
537+
//find json phrases
538+
// - ex. data:info.name
539+
// - ex. profile.data:info
540+
// - ex. profile.data:info.name
541+
const jsonSelector = new RegExp(
542+
`([a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+){0,1}\\${this.splitter}`
543+
+ `[a-zA-Z0-9_]+(\\${this.separator}[a-zA-Z0-9_]+)*)`,
544+
'g'
545+
);
532546
filters.push(...build.where.map(filter => {
533547
values.push(...filter.values);
534-
return filter.clause;
548+
//then replace with XJsonDialect.parse().extract
549+
return filter.clause.replace(jsonSelector, match => {
550+
const json = PgsqlJsonDialect.parse(
551+
match,
552+
this.splitter,
553+
this.separator
554+
);
555+
return json ? json.extract : match;
556+
});
535557
}));
536558
}
537559
build.json.forEach(filter => {
538560
const { query, replace } = filter;
539561
//convert builder selector to json dialect
540562
const json = PgsqlJsonDialect.parse(
541563
filter.selector,
542-
build.selector,
543-
build.separator
564+
this.splitter,
565+
this.separator
544566
);
545567
//if invalid JSON selector, skip it
546568
if (!json) return;
@@ -580,11 +602,11 @@ export class PgsqlDialect implements Dialect {
580602
if (build.sort.length) {
581603
const sort = build.sort.map(sort => {
582604
//if the sort column is using the selector ":" notation
583-
if (sort.column.name.includes(build.selector)) {
605+
if (sort.column.name.includes(this.splitter)) {
584606
const json = PgsqlJsonDialect.parse(
585607
sort.column.name,
586-
build.selector,
587-
build.separator
608+
this.splitter,
609+
this.separator
588610
);
589611
//if invalid JSON selector, skip it
590612
if (!json) return '';

packages/inquire/src/dialect/Sqlite.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ export class SqliteDialect implements Dialect {
4848
//Recommended quote character
4949
public readonly q = q;
5050

51+
//used for json notation
52+
public separator: string = '.';
53+
public splitter: string = ':';
54+
5155
/**
5256
* Converts alter builder to query and values
5357
*
@@ -473,18 +477,35 @@ export class SqliteDialect implements Dialect {
473477
if (build.where.length > 0 || build.json.length > 0) {
474478
const filters: string[] = [];
475479
if (build.where.length) {
480+
//find json phrases
481+
// - ex. data:info.name
482+
// - ex. profile.data:info
483+
// - ex. profile.data:info.name
484+
const jsonSelector = new RegExp(
485+
`([a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+){0,1}\\${this.splitter}`
486+
+ `[a-zA-Z0-9_]+(\\${this.separator}[a-zA-Z0-9_]+)*)`,
487+
'g'
488+
);
476489
filters.push(...build.where.map(filter => {
477490
values.push(...filter.values);
478-
return filter.clause;
491+
//then replace with XJsonDialect.parse().extract
492+
return filter.clause.replace(jsonSelector, match => {
493+
const json = SqliteJsonDialect.parse(
494+
match,
495+
this.splitter,
496+
this.separator
497+
);
498+
return json ? json.extract : match;
499+
});
479500
}));
480501
}
481502
build.json.forEach(filter => {
482503
const { query, replace } = filter;
483504
//convert builder selector to json dialect
484505
const json = SqliteJsonDialect.parse(
485506
filter.selector,
486-
build.selector,
487-
build.separator
507+
this.splitter,
508+
this.separator
488509
);
489510
//if invalid JSON selector, skip it
490511
if (!json) return;
@@ -522,11 +543,11 @@ export class SqliteDialect implements Dialect {
522543
if (build.sort.length) {
523544
const sort = build.sort.map(sort => {
524545
//if the sort column is using the selector ":" notation
525-
if (sort.column.name.includes(build.selector)) {
546+
if (sort.column.name.includes(this.splitter)) {
526547
const json = SqliteJsonDialect.parse(
527548
sort.column.name,
528-
build.selector,
529-
build.separator
549+
this.splitter,
550+
this.separator
530551
);
531552
//if invalid JSON selector, skip it
532553
if (!json) return '';

0 commit comments

Comments
 (0)