compileWheres method

String compileWheres(
  1. List<Map<String, dynamic>> wheres
)

Compile the "where" portion of the query.

Implementation

String compileWheres(List<Map<String, dynamic>> wheres) {
  if (wheres.isEmpty) return '';

  final lines = <String>[];
  for (final where in wheres) {
    final type = where['type'] as String;
    final boolean = where['boolean'] as String;

    String sql;
    switch (type) {
      case 'Raw':
        sql = where['sql'];
        break;
      case 'Basic':
        sql = '${wrap(where['column'])} ${where['operator']} ?';
        break;
      case 'In':
        final values = where['values'] as List;
        if (values.isEmpty) {
          sql = '0 = 1';
        } else {
          final placeholders = List.filled(values.length, '?').join(', ');
          sql = '${wrap(where['column'])} IN ($placeholders)';
        }
        break;
      case 'NotIn':
        final values = where['values'] as List;
        if (values.isEmpty) {
          sql = '1 = 1';
        } else {
          final placeholders = List.filled(values.length, '?').join(', ');
          sql = '${wrap(where['column'])} NOT IN ($placeholders)';
        }
        break;
      case 'Null':
        sql = '${wrap(where['column'])} IS NULL';
        break;
      case 'NotNull':
        sql = '${wrap(where['column'])} IS NOT NULL';
        break;
      case 'Between':
        sql = '${wrap(where['column'])} BETWEEN ? AND ?';
        break;
      case 'NotBetween':
        sql = '${wrap(where['column'])} NOT BETWEEN ? AND ?';
        break;
      case 'Date':
        sql = 'DATE(${wrap(where['column'])}) ${where['operator']} ?';
        break;
      case 'Time':
        sql = 'TIME(${wrap(where['column'])}) ${where['operator']} ?';
        break;
      case 'Year':
        sql = 'YEAR(${wrap(where['column'])}) ${where['operator']} ?';
        break;
      case 'Month':
        sql = 'MONTH(${wrap(where['column'])}) ${where['operator']} ?';
        break;
      case 'Day':
        sql = 'DAY(${wrap(where['column'])}) ${where['operator']} ?';
        break;
      case 'Column':
        sql =
            '${wrap(where['first'])} ${where['operator']} ${wrap(where['second'])}';
        break;
      case 'Nested':
        final nestedQuery = where['query'];
        final nestedWheres =
            (nestedQuery as dynamic).wheres as List<Map<String, dynamic>>;

        final nestedSql = compileWheres(nestedWheres);
        if (nestedSql.isEmpty) continue;

        // Remove leading WHERE and boolean if present (AND/OR)
        var cleanSql = nestedSql.replaceFirst('WHERE ', '');
        cleanSql = cleanSql.replaceFirst(RegExp(r'^(AND|OR)\s+'), '');
        sql = '($cleanSql)';
        break;
      case 'InSub':
        final subquery = (where['query'] as dynamic).toSql();
        sql = '${wrap(where['column'])} IN ($subquery)';
        break;
      case 'Exists':
        final subquery = (where['query'] as dynamic).toSql();
        sql = 'EXISTS ($subquery)';
        break;
      case 'NotExists':
        final subquery = (where['query'] as dynamic).toSql();
        sql = 'NOT EXISTS ($subquery)';
        break;
      case 'FullText':
        final columns =
            (where['columns'] as List<String>).map(wrap).join(', ');
        final mode = where['mode'] == 'boolean'
            ? 'IN BOOLEAN MODE'
            : where['mode'] == 'query_expansion' ||
                    where['mode'] == 'expansion'
                ? 'WITH QUERY EXPANSION'
                : 'IN NATURAL LANGUAGE MODE';
        sql = 'MATCH ($columns) AGAINST (? $mode)';
        break;
      case 'BetweenColumns':
        sql =
            '${wrap(where['column'])} BETWEEN ${wrap(where['start'])} AND ${wrap(where['end'])}';
        break;
      case 'NotBetweenColumns':
        sql =
            '${wrap(where['column'])} NOT BETWEEN ${wrap(where['start'])} AND ${wrap(where['end'])}';
        break;
      case 'JsonContains':
        final path = where['path'] != null ? ', ?' : '';
        sql = 'JSON_CONTAINS(${wrap(where['column'])}, ?$path)';
        break;
      case 'JsonContainsKey':
        sql = 'JSON_CONTAINS_PATH(${wrap(where['column'])}, \'one\', ?)';
        break;
      case 'JsonDoesntContain':
        final path = where['path'] != null ? ', ?' : '';
        sql = 'NOT JSON_CONTAINS(${wrap(where['column'])}, ?$path)';
        break;
      case 'JsonLength':
        final path = where['path'] != null ? ', ?' : '';
        sql =
            'JSON_LENGTH(${wrap(where['column'])}$path) ${where['operator']} ?';
        break;
      default:
        continue;
    }

    if (lines.isNotEmpty) {
      sql = '$boolean $sql';
    }
    lines.add(sql);
  }

  if (lines.isEmpty) return '';
  return 'WHERE ${lines.join(' ')}';
}