• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rogerpadilla / uql / 23827122695

01 Apr 2026 01:14AM UTC coverage: 94.943% (-0.08%) from 95.021%
23827122695

push

github

rogerpadilla
chore: remove changelog and update gitHead in package.json

2903 of 3222 branches covered (90.1%)

Branch coverage included in aggregate %.

5133 of 5242 relevant lines covered (97.92%)

353.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.82
/packages/uql-orm/src/dialect/mysqlLikeSqlDialect.ts
1
import SqlString from 'sqlstring';
2
import type { QueryContext, QuerySizeComparisonOps } from '../type/index.js';
3
import { AbstractSqlDialect } from './abstractSqlDialect.js';
4
import { buildElemMatchConditions } from './jsonArrayElemMatchUtils.js';
5

6
/**
7
 * Shared JSON-array / JSON-object operator implementation between MySQL and MariaDB.
8
 *
9
 * Both dialects support the MySQL-compatible JSON functions/operators used by:
10
 * - `$size` (JSON_LENGTH)
11
 * - `$all` (JSON_CONTAINS)
12
 * - `$elemMatch` (JSON_TABLE, or fast JSON_CONTAINS for the simple case)
13
 */
14
export abstract class MysqlLikeSqlDialect extends AbstractSqlDialect {
15
  override escape(value: unknown): string {
16
    return SqlString.escape(value);
2✔
17
  }
18

19
  protected override numericCast(expr: string): string {
20
    return `CAST(${expr} AS DECIMAL)`;
8✔
21
  }
22

23
  protected override ilikeExpr(f: string, ph: string): string {
24
    return `${f} LIKE ${ph}`;
30✔
25
  }
26

27
  protected override neExpr(field: string, ph: string): string {
28
    // MySQL/MariaDB null-safe inequality: true when values differ or one side is NULL.
29
    return `NOT (${field} <=> ${ph})`;
32✔
30
  }
31

32
  protected override jsonAll(ctx: QueryContext, jsonField: string, value: unknown): string {
33
    return `JSON_CONTAINS(${jsonField}, ${this.addValue(ctx.values, JSON.stringify(value))})`;
2✔
34
  }
35

36
  protected override jsonSize(ctx: QueryContext, jsonField: string, value: number | QuerySizeComparisonOps): string {
37
    const tmpCtx = this.createContext();
8✔
38
    this.buildSizeComparison(tmpCtx, () => tmpCtx.append(`JSON_LENGTH(${jsonField})`), value);
10✔
39
    ctx.pushValue(...tmpCtx.values);
8✔
40
    return tmpCtx.sql;
8✔
41
  }
42

43
  protected override jsonElemMatch(ctx: QueryContext, jsonField: string, match: Record<string, unknown>): string {
44
    const isPrimitiveElement = Object.keys(match).some((k) => k.startsWith('$'));
38✔
45

46
    if (isPrimitiveElement) {
8!
47
      const ops = Object.entries(match);
×
48
      const conditions = ops.map(([op, opVal]) =>
×
49
        this.buildJsonFieldCondition(ctx, () => 'jt.elem_text', '', op, opVal),
×
50
      );
51
      return `EXISTS (SELECT 1 FROM JSON_TABLE(${jsonField}, '$[*]' COLUMNS (elem_text TEXT PATH '$')) AS jt WHERE ${conditions.join(
×
52
        ' AND ',
53
      )})`;
54
    }
55

56
    const hasOperators = Object.values(match).some(
8✔
57
      (v) => v && typeof v === 'object' && !Array.isArray(v) && Object.keys(v).some((k) => k.startsWith('$')),
8✔
58
    );
59

60
    if (!hasOperators) {
8✔
61
      return `JSON_CONTAINS(${jsonField}, ${this.addValue(ctx.values, JSON.stringify([match]))})`;
2✔
62
    }
63

64
    const fields = Object.keys(match);
6✔
65
    const columns = fields.map((f) => `${this.escapeId(f, true)} TEXT PATH '$.${this.escapeJsonKey(f)}'`).join(', ');
36✔
66

67
    const conditions = buildElemMatchConditions(
6✔
68
      match,
69
      (field, op, opVal) => this.buildJsonFieldCondition(ctx, (f) => `jt.${this.escapeId(f, true)}`, field, op, opVal),
36✔
70
      (field, val) => `jt.${this.escapeId(field, true)} = ${this.addValue(ctx.values, val)}`,
×
71
    );
72

73
    return `EXISTS (SELECT 1 FROM JSON_TABLE(${jsonField}, '$[*]' COLUMNS (${columns})) AS jt WHERE ${conditions.join(
6✔
74
      ' AND ',
75
    )})`;
76
  }
77
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc