Repository: dotnet/efcore
File: src/EFCore.Relational/Query/QuerySqlGenerator.cs (C#)

Code before:
        _relationalCommandBuilder.Append(" LIKE ");

        Visit(likeExpression.Pattern);

        if (likeExpression.EscapeChar != null)
        {
            _relationalCommandBuilder.Append(" ESCAPE ");
            Visit(likeExpression.EscapeChar);
        }
    }

    /// <summary>
    ///     Generates SQL for a COLLATE expression.
    /// </summary>
    /// <param name="collateExpression">The <see cref="CollateExpression" /> for which to generate SQL.</param>
    protected override Expression VisitCollate(CollateExpression collateExpression)
    {
        Visit(collateExpression.Operand);

        // In some databases (e.g. SQL Server), collations aren't regular identifirs (like column or table names), and so shouldn't be
        // quoted. However, we still default to quoting to prevent cases where arbitrary collation name inputs get integrated into the SQL.
        // Providers which don't supporting quoting of collation names should override this method to provide sanitization logic,
        // e.g. throwing if the name contains any but a restricted set of characters.
        _relationalCommandBuilder
            .Append(" COLLATE ")
            .Append(_sqlGenerationHelper.DelimitIdentifier(collateExpression.Collation));

        return collateExpression;
    }

    /// <summary>
    ///     Generates SQL for a DISTINCT () clause in an aggregate function invocation.
    /// </summary>
    /// <param name="distinctExpression">The <see cref="DistinctExpression" /> for which to generate SQL.</param>
    protected override Expression VisitDistinct(DistinctExpression distinctExpression)
    {
        _relationalCommandBuilder.Append("DISTINCT (");
        Visit(distinctExpression.Operand);
        _relationalCommandBuilder.Append(")");

        return distinctExpression;
    }

    /// <summary>
    ///     Generates SQL for a CASE clause CASE/WHEN construct.
    /// </summary>
    /// <param name="caseExpression">The <see cref="CaseExpression" /> for which to generate SQL.</param>
    protected override Expression VisitCase(CaseExpression caseExpression)
    {
        _relationalCommandBuilder.Append("CASE");


Review comment (suggestion):
The change to quote collation names by default in the relational base class may break SQLite, which also doesn't support quoted collation names. The migration tests in test/EFCore.Sqlite.FunctionalTests/Migrations/MigrationsSqliteTest.cs show unquoted collation names (e.g., "COLLATE NOCASE" on lines 45, 501, 511-512, 956). SQLite likely needs the same validation logic override as SQL Server to prevent quoting and validate collation names. Consider adding a similar VisitCollate override in SqliteQuerySqlGenerator and validation in SqliteMigrationsSqlGenerator.

Code after:
        _relationalCommandBuilder.Append(" LIKE ");

        Visit(likeExpression.Pattern);

        if (likeExpression.EscapeChar != null)
        {
            _relationalCommandBuilder.Append(" ESCAPE ");
            Visit(likeExpression.EscapeChar);
        }
    }

    /// <summary>
    ///     Generates SQL for a COLLATE expression.
    /// </summary>
    /// <param name="collateExpression">The <see cref="CollateExpression" /> for which to generate SQL.</param>
    protected override Expression VisitCollate(CollateExpression collateExpression)
    {
        Visit(collateExpression.Operand);

        // In some databases (e.g. SQL Server), collations aren't regular identifiers (like column or table names), and so shouldn't be
        // quoted. However, we still default to quoting to prevent cases where arbitrary collation name inputs get integrated into the SQL.
        // Providers which don't support quoting of collation names should override this method to provide sanitization logic,
        // e.g. throwing if the name contains any but a restricted set of characters.
        _relationalCommandBuilder
            .Append(" COLLATE ")
            .Append(_sqlGenerationHelper.DelimitIdentifier(collateExpression.Collation));

        return collateExpression;
    }

    /// <summary>
    ///     Generates SQL for a DISTINCT () clause in an aggregate function invocation.
    /// </summary>
    /// <param name="distinctExpression">The <see cref="DistinctExpression" /> for which to generate SQL.</param>
    protected override Expression VisitDistinct(DistinctExpression distinctExpression)
    {
        _relationalCommandBuilder.Append("DISTINCT (");
        Visit(distinctExpression.Operand);
        _relationalCommandBuilder.Append(")");

        return distinctExpression;
    }

    /// <summary>
    ///     Generates SQL for a CASE clause CASE/WHEN construct.
    /// </summary>
    /// <param name="caseExpression">The <see cref="CaseExpression" /> for which to generate SQL.</param>
    protected override Expression VisitCase(CaseExpression caseExpression)
    {
        _relationalCommandBuilder.Append("CASE");