search-input-query-parser 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,7 @@
1
1
  import { describe, expect, test } from "@jest/globals";
2
- import { searchQueryToSql, searchStringToSql } from "./search-query-to-sql";
2
+ import { searchQueryToIlikeSql, searchStringToIlikeSql } from "./search-query-to-ilike-sql";
3
+ import { searchQueryToTsVectorSql } from "./search-query-to-tsvector-sql";
4
+ import { searchQueryToParadeDbSql } from "./search-query-to-paradedb-sql";
3
5
  import { parseSearchInputQuery } from "./parser";
4
6
  import type { SearchQuery, FieldSchema } from "./parser";
5
7
 
@@ -19,14 +21,14 @@ describe("Search Query to SQL Converter", () => {
19
21
  { name: "user_id", type: "number" },
20
22
  ];
21
23
 
22
- const testSqlConversion = (
24
+ const testIlikeConversion = (
23
25
  query: string,
24
26
  expectedSql: string,
25
27
  expectedValues: any[]
26
28
  ) => {
27
29
  const parsedQuery = parseSearchInputQuery(query, schemas);
28
30
  expect(parsedQuery.type).toBe("SEARCH_QUERY");
29
- const result = searchQueryToSql(
31
+ const result = searchQueryToIlikeSql(
30
32
  parsedQuery as SearchQuery,
31
33
  searchableColumns,
32
34
  schemas
@@ -37,7 +39,7 @@ describe("Search Query to SQL Converter", () => {
37
39
 
38
40
  describe("Basic Term Conversion", () => {
39
41
  test("converts single search term", () => {
40
- testSqlConversion(
42
+ testIlikeConversion(
41
43
  "boots",
42
44
  "(lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1))",
43
45
  ["%boots%"]
@@ -45,7 +47,7 @@ describe("Search Query to SQL Converter", () => {
45
47
  });
46
48
 
47
49
  test("converts quoted search term", () => {
48
- testSqlConversion(
50
+ testIlikeConversion(
49
51
  '"red shoes"',
50
52
  "(lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1))",
51
53
  ["%red shoes%"]
@@ -53,13 +55,13 @@ describe("Search Query to SQL Converter", () => {
53
55
  });
54
56
 
55
57
  test("escapes special characters in search terms", () => {
56
- // testSqlConversion(
58
+ // testIlikeConversion(
57
59
  // "100%",
58
60
  // "(lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1))",
59
61
  // ["%100\\%%"]
60
62
  // );
61
63
 
62
- testSqlConversion(
64
+ testIlikeConversion(
63
65
  "under_score",
64
66
  "(lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1))",
65
67
  ["%under\\_score%"]
@@ -69,27 +71,27 @@ describe("Search Query to SQL Converter", () => {
69
71
 
70
72
  describe("Field Value Conversion", () => {
71
73
  test("converts simple field:value pairs", () => {
72
- // testSqlConversion("color:red", "lower(color) LIKE lower($1)", ["%red%"]);
74
+ // testIlikeConversion("color:red", "lower(color) LIKE lower($1)", ["%red%"]);
73
75
  });
74
76
 
75
77
  test("converts field values with spaces", () => {
76
- testSqlConversion('status:"in progress"', "lower(status) LIKE lower($1)", [
78
+ testIlikeConversion('status:"in progress"', "lower(status) LIKE lower($1)", [
77
79
  "%in progress%",
78
80
  ]);
79
81
  });
80
82
 
81
83
  test("handles special date fields", () => {
82
- testSqlConversion("date:2024-01-01", "date = $1", [
84
+ testIlikeConversion("date:2024-01-01", "date = $1", [
83
85
  "2024-01-01",
84
86
  ]);
85
87
  });
86
88
 
87
89
  test("handles ID fields", () => {
88
- testSqlConversion("user_id:123", "user_id = $1", [123]);
90
+ testIlikeConversion("user_id:123", "user_id = $1", [123]);
89
91
  });
90
92
 
91
93
  test("escapes special characters in field values", () => {
92
- testSqlConversion("category:100%", "lower(category) LIKE lower($1)", [
94
+ testIlikeConversion("category:100%", "lower(category) LIKE lower($1)", [
93
95
  "%100\\%%",
94
96
  ]);
95
97
  });
@@ -97,7 +99,7 @@ describe("Search Query to SQL Converter", () => {
97
99
 
98
100
  describe("Logical Operators", () => {
99
101
  test("converts AND expressions", () => {
100
- testSqlConversion(
102
+ testIlikeConversion(
101
103
  "comfortable AND leather",
102
104
  "((lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1)) AND (lower(title) LIKE lower($2) OR lower(description) LIKE lower($2) OR lower(content) LIKE lower($2)))",
103
105
  ["%comfortable%", "%leather%"]
@@ -105,7 +107,7 @@ describe("Search Query to SQL Converter", () => {
105
107
  });
106
108
 
107
109
  test("converts OR expressions", () => {
108
- testSqlConversion(
110
+ testIlikeConversion(
109
111
  "leather OR suede",
110
112
  "((lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1)) OR (lower(title) LIKE lower($2) OR lower(description) LIKE lower($2) OR lower(content) LIKE lower($2)))",
111
113
  ["%leather%", "%suede%"]
@@ -113,7 +115,7 @@ describe("Search Query to SQL Converter", () => {
113
115
  });
114
116
 
115
117
  test("converts mixed operators", () => {
116
- testSqlConversion(
118
+ testIlikeConversion(
117
119
  "comfortable AND (leather OR suede)",
118
120
  "((lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1)) AND ((lower(title) LIKE lower($2) OR lower(description) LIKE lower($2) OR lower(content) LIKE lower($2)) OR (lower(title) LIKE lower($3) OR lower(description) LIKE lower($3) OR lower(content) LIKE lower($3))))",
119
121
  ["%comfortable%", "%leather%", "%suede%"]
@@ -123,7 +125,7 @@ describe("Search Query to SQL Converter", () => {
123
125
 
124
126
  describe("NOT SQL Conversion", () => {
125
127
  test("converts simple NOT expressions", () => {
126
- testSqlConversion(
128
+ testIlikeConversion(
127
129
  "NOT test",
128
130
  "NOT (lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1))",
129
131
  ["%test%"]
@@ -131,19 +133,19 @@ describe("Search Query to SQL Converter", () => {
131
133
  });
132
134
 
133
135
  test("converts NOT with field:value", () => {
134
- testSqlConversion("NOT status:active", "NOT lower(status) LIKE lower($1)", [
136
+ testIlikeConversion("NOT status:active", "NOT lower(status) LIKE lower($1)", [
135
137
  "%active%",
136
138
  ]);
137
139
  });
138
140
 
139
141
  test("converts complex NOT expressions", () => {
140
- testSqlConversion(
142
+ testIlikeConversion(
141
143
  "boots AND NOT leather",
142
144
  "((lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1)) AND NOT (lower(title) LIKE lower($2) OR lower(description) LIKE lower($2) OR lower(content) LIKE lower($2)))",
143
145
  ["%boots%", "%leather%"]
144
146
  );
145
147
 
146
- testSqlConversion(
148
+ testIlikeConversion(
147
149
  "NOT (color:red OR color:blue)",
148
150
  "NOT (lower(color) LIKE lower($1) OR lower(color) LIKE lower($2))",
149
151
  ["%red%", "%blue%"]
@@ -153,7 +155,7 @@ describe("Search Query to SQL Converter", () => {
153
155
 
154
156
  describe("Complex Queries", () => {
155
157
  test("converts complex field and term combinations", () => {
156
- testSqlConversion(
158
+ testIlikeConversion(
157
159
  'category:"winter boots" AND (color:black OR color:brown)',
158
160
  "(lower(category) LIKE lower($1) AND (lower(color) LIKE lower($2) OR lower(color) LIKE lower($3)))",
159
161
  ["%winter boots%", "%black%", "%brown%"]
@@ -161,7 +163,7 @@ describe("Search Query to SQL Converter", () => {
161
163
  });
162
164
 
163
165
  test("converts nested expressions with multiple operators", () => {
164
- testSqlConversion(
166
+ testIlikeConversion(
165
167
  '(color:red OR color:blue) AND category:"winter boots" AND available:true',
166
168
  "(((lower(color) LIKE lower($1) OR lower(color) LIKE lower($2)) AND lower(category) LIKE lower($3)) AND lower(available) LIKE lower($4))",
167
169
  ["%red%", "%blue%", "%winter boots%", "%true%"]
@@ -169,7 +171,7 @@ describe("Search Query to SQL Converter", () => {
169
171
  });
170
172
 
171
173
  test("handles mixed fields and search terms", () => {
172
- testSqlConversion(
174
+ testIlikeConversion(
173
175
  'boots AND color:black AND "winter gear"',
174
176
  "(((lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1)) AND lower(color) LIKE lower($2)) AND (lower(title) LIKE lower($3) OR lower(description) LIKE lower($3) OR lower(content) LIKE lower($3)))",
175
177
  ["%boots%", "%black%", "%winter gear%"]
@@ -179,7 +181,7 @@ describe("Search Query to SQL Converter", () => {
179
181
 
180
182
  describe("Edge Cases", () => {
181
183
  test("handles empty query", () => {
182
- const result = searchQueryToSql(
184
+ const result = searchQueryToIlikeSql(
183
185
  { type: "SEARCH_QUERY", expression: null },
184
186
  searchableColumns
185
187
  );
@@ -189,23 +191,23 @@ describe("Search Query to SQL Converter", () => {
189
191
 
190
192
  test("throws error for invalid query syntax", () => {
191
193
  expect(() =>
192
- searchStringToSql("AND", searchableColumns, schemas)
194
+ searchStringToIlikeSql("AND", searchableColumns, schemas)
193
195
  ).toThrow("Parse error");
194
196
  expect(() =>
195
- searchStringToSql("field:", searchableColumns, schemas)
197
+ searchStringToIlikeSql("field:", searchableColumns, schemas)
196
198
  ).toThrow("Parse error");
197
199
  });
198
200
 
199
201
  test("throws error for invalid fields", () => {
200
202
  expect(() =>
201
- searchStringToSql("invalid_field:value", searchableColumns, schemas)
203
+ searchStringToIlikeSql("invalid_field:value", searchableColumns, schemas)
202
204
  ).toThrow('Parse error: Invalid field: "invalid_field"');
203
205
  });
204
206
  });
205
207
 
206
208
  describe("Parameter Counting", () => {
207
209
  test("maintains correct parameter count in complex queries", () => {
208
- testSqlConversion(
210
+ testIlikeConversion(
209
211
  'term1 AND field1:value1 OR (term2 AND field2:"value 2")',
210
212
  "(((lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1)) AND lower(field1) LIKE lower($2)) OR ((lower(title) LIKE lower($3) OR lower(description) LIKE lower($3) OR lower(content) LIKE lower($3)) AND lower(field2) LIKE lower($4)))",
211
213
  ["%term1%", "%value1%", "%term2%", "%value 2%"]
@@ -215,7 +217,7 @@ describe("Search Query to SQL Converter", () => {
215
217
 
216
218
  describe("Special Character Handling", () => {
217
219
  test("escapes SQL wildcards", () => {
218
- testSqlConversion(
220
+ testIlikeConversion(
219
221
  "prefix% AND suffix_",
220
222
  "((lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1)) AND (lower(title) LIKE lower($2) OR lower(description) LIKE lower($2) OR lower(content) LIKE lower($2)))",
221
223
  ["%prefix\\%%", "%suffix\\_%"]
@@ -223,7 +225,7 @@ describe("Search Query to SQL Converter", () => {
223
225
  });
224
226
 
225
227
  test("handles quoted strings with escaped characters", () => {
226
- testSqlConversion(
228
+ testIlikeConversion(
227
229
  '"value\\"with\\"quotes"',
228
230
  "(lower(title) LIKE lower($1) OR lower(description) LIKE lower($1) OR lower(content) LIKE lower($1))",
229
231
  ['%value"with"quotes%']
@@ -233,15 +235,15 @@ describe("Search Query to SQL Converter", () => {
233
235
 
234
236
  describe("Range Query Conversion", () => {
235
237
  test("converts comparison operators for numbers", () => {
236
- testSqlConversion("price:>100", "price > $1", [100]);
237
- testSqlConversion("price:>=100", "price >= $1", [100]);
238
- testSqlConversion("price:<50", "price < $1", [50]);
239
- testSqlConversion("price:<=50", "price <= $1", [50]);
238
+ testIlikeConversion("price:>100", "price > $1", [100]);
239
+ testIlikeConversion("price:>=100", "price >= $1", [100]);
240
+ testIlikeConversion("price:<50", "price < $1", [50]);
241
+ testIlikeConversion("price:<=50", "price <= $1", [50]);
240
242
  });
241
243
 
242
244
  test("converts between ranges for numbers", () => {
243
- testSqlConversion("price:10..20", "price BETWEEN $1 AND $2", [10, 20]);
244
- testSqlConversion(
245
+ testIlikeConversion("price:10..20", "price BETWEEN $1 AND $2", [10, 20]);
246
+ testIlikeConversion(
245
247
  "amount:50.99..100.50",
246
248
  "amount BETWEEN $1 AND $2",
247
249
  [50.99, 100.5]
@@ -249,15 +251,15 @@ describe("Search Query to SQL Converter", () => {
249
251
  });
250
252
 
251
253
  test("converts open-ended ranges for numbers", () => {
252
- testSqlConversion("price:10..", "price >= $1", [10]);
253
- testSqlConversion("price:..20", "price <= $1", [20]);
254
+ testIlikeConversion("price:10..", "price >= $1", [10]);
255
+ testIlikeConversion("price:..20", "price <= $1", [20]);
254
256
  });
255
257
 
256
258
  test("converts date ranges", () => {
257
- testSqlConversion("date:>2024-01-01", "date > $1", [
259
+ testIlikeConversion("date:>2024-01-01", "date > $1", [
258
260
  "2024-01-01",
259
261
  ]);
260
- testSqlConversion(
262
+ testIlikeConversion(
261
263
  "date:2024-01-01..2024-12-31",
262
264
  "date BETWEEN $1 AND $2",
263
265
  ["2024-01-01", "2024-12-31"]
@@ -265,17 +267,17 @@ describe("Search Query to SQL Converter", () => {
265
267
  });
266
268
 
267
269
  test("converts complex expressions with ranges", () => {
268
- testSqlConversion(
270
+ testIlikeConversion(
269
271
  "price:>100 AND amount:<50",
270
272
  "(price > $1 AND amount < $2)",
271
273
  [100, 50]
272
274
  );
273
- testSqlConversion(
275
+ testIlikeConversion(
274
276
  "price:10..20 OR amount:>=100",
275
277
  "(price BETWEEN $1 AND $2 OR amount >= $3)",
276
278
  [10, 20, 100]
277
279
  );
278
- testSqlConversion(
280
+ testIlikeConversion(
279
281
  "(price:>100 AND amount:<50) OR date:>=2024-01-01",
280
282
  "((price > $1 AND amount < $2) OR date >= $3)",
281
283
  [100, 50, "2024-01-01"]
@@ -283,7 +285,7 @@ describe("Search Query to SQL Converter", () => {
283
285
  });
284
286
 
285
287
  test("mixes ranges with regular field searches", () => {
286
- testSqlConversion(
288
+ testIlikeConversion(
287
289
  'title:"winter boots" AND price:10..20',
288
290
  "(lower(title) LIKE lower($1) AND price BETWEEN $2 AND $3)",
289
291
  ["%winter boots%", 10, 20]
@@ -291,7 +293,7 @@ describe("Search Query to SQL Converter", () => {
291
293
  });
292
294
 
293
295
  test("handles multiple date ranges in one query", () => {
294
- testSqlConversion(
296
+ testIlikeConversion(
295
297
  "date:>=2024-01-01 AND date:<=2024-12-31",
296
298
  "(date >= $1 AND date <= $2)",
297
299
  ["2024-01-01", "2024-12-31"]
@@ -299,7 +301,7 @@ describe("Search Query to SQL Converter", () => {
299
301
  });
300
302
 
301
303
  test("handles decimal numbers in ranges", () => {
302
- testSqlConversion(
304
+ testIlikeConversion(
303
305
  "price:10.5..20.99",
304
306
  "price BETWEEN $1 AND $2",
305
307
  [10.5, 20.99]
@@ -307,16 +309,16 @@ describe("Search Query to SQL Converter", () => {
307
309
  });
308
310
 
309
311
  test("preserves numeric precision", () => {
310
- testSqlConversion("price:>=99.99", "price >= $1", [99.99]);
312
+ testIlikeConversion("price:>=99.99", "price >= $1", [99.99]);
311
313
  });
312
314
 
313
315
  test("handles negative numbers in ranges", () => {
314
- testSqlConversion(
316
+ testIlikeConversion(
315
317
  "amount:-10..10",
316
318
  "amount BETWEEN $1 AND $2",
317
319
  [-10, 10]
318
320
  );
319
- testSqlConversion("amount:<-10", "amount < $1", [-10]);
321
+ testIlikeConversion("amount:<-10", "amount < $1", [-10]);
320
322
  });
321
323
  });
322
324
 
@@ -328,12 +330,11 @@ describe("Search Query to SQL Converter", () => {
328
330
  ) => {
329
331
  const parsedQuery = parseSearchInputQuery(query, schemas);
330
332
  expect(parsedQuery.type).toBe("SEARCH_QUERY");
331
- const result = searchQueryToSql(
333
+ const result = searchQueryToTsVectorSql(
332
334
  parsedQuery as SearchQuery,
333
335
  searchableColumns,
334
336
  schemas,
335
337
  {
336
- searchType: "tsvector",
337
338
  language: "english",
338
339
  }
339
340
  );
@@ -382,13 +383,10 @@ describe("Search Query to SQL Converter", () => {
382
383
  ) => {
383
384
  const parsedQuery = parseSearchInputQuery(query, schemas);
384
385
  expect(parsedQuery.type).toBe("SEARCH_QUERY");
385
- const result = searchQueryToSql(
386
+ const result = searchQueryToParadeDbSql(
386
387
  parsedQuery as SearchQuery,
387
388
  searchableColumns,
388
- schemas,
389
- {
390
- searchType: "paradedb",
391
- }
389
+ schemas
392
390
  );
393
391
  expect(result.text).toBe(expectedSql);
394
392
  expect(result.values).toEqual(expectedValues);
@@ -6,6 +6,16 @@ import {
6
6
  WildcardPattern,
7
7
  } from "./parser";
8
8
 
9
+ export {
10
+ searchStringToIlikeSql,
11
+ searchQueryToIlikeSql,
12
+ } from "./search-query-to-ilike-sql";
13
+ export { searchQueryToTsVectorSql, searchStringToTsVectorSql } from "./search-query-to-tsvector-sql";
14
+ export {
15
+ searchQueryToParadeDbSql,
16
+ searchStringToParadeDbSql,
17
+ } from "./search-query-to-paradedb-sql";
18
+
9
19
  export interface SqlQueryResult {
10
20
  text: string;
11
21
  values: any[];