2 votes

Comment échapper aux guillemets simples lors de la création d'une chaîne de requête avec jooq ?

J'essaie de créer une chaîne de requête jooq de la façon suivante

DSL.using(SQLDialect.MYSQL)
            .select(
                    ImmutableList.of(DSL.field("Name"))
            .from(DSL.table("Account"))
            .where(DSL.field("Name").eq("Yaswanth's Company"))).toString()

La chaîne de requête résultante a le guillemet simple échappé avec un autre guillemet simple qui est la manière par défaut de mySQL d'échapper les guillemets simples.

"select Name from Account where Name = 'Yaswanth''s Company'"

Mais j'aurais besoin que le guillemet simple soit échappé par une barre oblique inverse, car je forme la chaîne de requête pour Salesforce. (ce qui s'appelle SOQL).

J'ai besoin de la chaîne de requête de cette façon

"select Name from Account where Name = 'Yaswanth\\'s Company'"

J'ai regardé le code de la bibliothèque de jooq et ceci est codé en dur dans la classe DefaultBinding.

private final String escape(Object val, Context<?> context) {
    String result = val.toString();

    if (needsBackslashEscaping(context.configuration()))
        result = result.replace("\\", "\\\\");

    return result.replace("'", "''");
}

Existe-t-il un moyen pour moi de remplacer ce comportement par défaut par une configuration ou des paramètres qui peuvent être transmis par DSL.using(*, *) ?

1voto

Lukas Eder Points 48046

La plupart des bases de données SQL suivent la norme SQL qui consiste à doubler le guillemet simple pour l'échappement, mais il est certainement judicieux de rendre cette fonctionnalité configurable. Nous allons probablement faire cela pour jOOQ 3.10 avec #5873 .

En attendant, la meilleure solution pour vous est d'écrire votre propre liaison des types de données pour tous les types de chaînes de caractères et remplacer l'option DefaultBinding comportement lors de la génération de la chaîne SQL. Quelque chose du genre de ceci :

Configuration de la génération du code

Utilisation de <forcedTypes/>

<forcedType>
    <userType>java.lang.String</userType>
    <binding>com.example.AlternativeEscapingStringBinding</binding>
    <!-- add other vendor-specific string type names here -->
    <types>(?i:N?(VAR)?CHAR|TEXT|N?CLOB)</types>
</forcedType>

Liaison des types de données

public class AlternativeEscapingStringBinding implements Binding<String, String> {
    ...

    @Override
    public void sql(BindingSQLContext<String> ctx) throws SQLException {
        if (ctx.paramType() == ParamType.INLINED) 
            if (ctx.value() == null)
                ctx.render().sql('null');
            else
                ctx.render()
                   .sql('\'')
                   .sql(ctx.value().replace("'", "\\'"))
                   .sql('\'');
        else
            ctx.render().sql('?');
    }
}

Si vous n'utilisez pas le générateur de code

Vous pouvez toujours appliquer manuellement vos propres liaisons de type de données à vos champs en tant que tels :

DSL.field("Name", SQLDataType.VARCHAR
                             .asConvertedDataType(new AlternativeEscapingStringBinding()));

Tu devras juste te souvenir de ça à chaque fois...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X