Search in sources :

Example 1 with QueryPart

use of org.jooq.QueryPart in project jOOQ by jOOQ.

the class Function method toSQLArguments1.

final void toSQLArguments1(Context<?> ctx, QueryPartList<QueryPart> args) {
    if (distinct) {
        ctx.keyword("distinct");
        // [#2883] PostgreSQL can use the DISTINCT keyword with formal row value expressions.
        if (ctx.family() == POSTGRES && args.size() > 1) {
            ctx.sql('(');
        } else {
            ctx.sql(' ');
        }
    }
    if (!args.isEmpty()) {
        if (filter == null || HSQLDB == ctx.family() || POSTGRES_9_4.precedes(ctx.dialect())) {
            ctx.visit(args);
        } else {
            QueryPartList<Field<?>> expressions = new QueryPartList<Field<?>>();
            for (QueryPart argument : args) expressions.add(DSL.when(filter, argument == ASTERISK ? one() : argument));
            ctx.visit(expressions);
        }
    }
    if (distinct)
        if (ctx.family() == POSTGRES && args.size() > 1)
            ctx.sql(')');
    if (ignoreNulls) {
        ctx.sql(' ').keyword("ignore nulls");
    } else if (respectNulls) {
        ctx.sql(' ').keyword("respect nulls");
    }
}
Also used : Field(org.jooq.Field) SortField(org.jooq.SortField) QueryPart(org.jooq.QueryPart)

Example 2 with QueryPart

use of org.jooq.QueryPart in project jOOQ by jOOQ.

the class Tools method renderAndBind.

/**
     * Render and bind a list of {@link QueryPart} to plain SQL
     * <p>
     * This will perform two actions:
     * <ul>
     * <li>When {@link RenderContext} is provided, it will render plain SQL to
     * the context, substituting {numbered placeholders} and bind values if
     * {@link RenderContext#inline()} is set</li>
     * <li>When {@link BindContext} is provided, it will bind the list of
     * {@link QueryPart} according to the {numbered placeholders} and bind
     * values in the sql string</li>
     * </ul>
     */
@SuppressWarnings("null")
static final void renderAndBind(Context<?> ctx, String sql, List<QueryPart> substitutes) {
    RenderContext render = (RenderContext) ((ctx instanceof RenderContext) ? ctx : null);
    BindContext bind = (BindContext) ((ctx instanceof BindContext) ? ctx : null);
    int substituteIndex = 0;
    char[] sqlChars = sql.toCharArray();
    // [#1593] Create a dummy renderer if we're in bind mode
    if (render == null)
        render = new DefaultRenderContext(bind.configuration());
    SQLDialect dialect = render.configuration().dialect();
    SQLDialect family = dialect.family();
    boolean mysql = asList(MARIADB, MYSQL).contains(family);
    String[][] quotes = QUOTES.get(family);
    // [#3630] Depending on this setting, we need to consider backslashes as escape characters within string literals.
    boolean needsBackslashEscaping = needsBackslashEscaping(ctx.configuration());
    characterLoop: for (int i = 0; i < sqlChars.length; i++) {
        // where id = ?
        if (peek(sqlChars, i, "--") || // http://bugs.mysql.com/bug.php?id=76623
        (mysql && peek(sqlChars, i, "#"))) {
            // Consume the complete comment
            for (; i < sqlChars.length && sqlChars[i] != '\r' && sqlChars[i] != '\n'; render.sql(sqlChars[i++])) ;
            // Consume the newline character
            if (i < sqlChars.length)
                render.sql(sqlChars[i]);
        } else // from t_book where id = ?
        if (peek(sqlChars, i, "/*")) {
            // Consume the complete comment
            for (; !peek(sqlChars, i, "*/"); render.sql(sqlChars[i++])) ;
            // Consume the comment delimiter
            render.sql(sqlChars[i++]);
            render.sql(sqlChars[i]);
        } else // insert into x values ('Hello? Anybody out there?');
        if (sqlChars[i] == '\'') {
            // Consume the initial string literal delimiter
            render.sql(sqlChars[i++]);
            // Consume the whole string literal
            for (; ; ) {
                // [#3000] [#3630] Consume backslash-escaped characters if needed
                if (sqlChars[i] == '\\' && needsBackslashEscaping) {
                    render.sql(sqlChars[i++]);
                } else // Consume an escaped apostrophe
                if (peek(sqlChars, i, "''")) {
                    render.sql(sqlChars[i++]);
                } else // Break on the terminal string literal delimiter
                if (peek(sqlChars, i, "'")) {
                    break;
                }
                // Consume string literal content
                render.sql(sqlChars[i++]);
            }
            // Consume the terminal string literal delimiter
            render.sql(sqlChars[i]);
        } else // update x set v = "Column Name with a ? (question mark)"
        if (peekAny(sqlChars, i, quotes[QUOTE_START_DELIMITER])) {
            // Main identifier delimiter or alternative one?
            int delimiter = 0;
            for (int d = 0; d < quotes[QUOTE_START_DELIMITER].length; d++) {
                if (peek(sqlChars, i, quotes[QUOTE_START_DELIMITER][d])) {
                    delimiter = d;
                    break;
                }
            }
            // Consume the initial identifier delimiter
            for (int d = 0; d < quotes[QUOTE_START_DELIMITER][delimiter].length(); d++) render.sql(sqlChars[i++]);
            // Consume the whole identifier
            for (; ; ) {
                // Consume an escaped quote
                if (peek(sqlChars, i, quotes[QUOTE_END_DELIMITER_ESCAPED][delimiter])) {
                    for (int d = 0; d < quotes[QUOTE_END_DELIMITER_ESCAPED][delimiter].length(); d++) render.sql(sqlChars[i++]);
                } else // Break on the terminal identifier delimiter
                if (peek(sqlChars, i, quotes[QUOTE_END_DELIMITER][delimiter])) {
                    break;
                }
                // Consume identifier content
                render.sql(sqlChars[i++]);
            }
            // Consume the terminal identifier delimiter
            for (int d = 0; d < quotes[QUOTE_END_DELIMITER][delimiter].length(); d++) {
                if (d > 0)
                    i++;
                render.sql(sqlChars[i]);
            }
        } else // Inline bind variables only outside of string literals
        if (substituteIndex < substitutes.size() && ((sqlChars[i] == '?') || //         Watch out for the PostgreSQL cast operator ::
        (sqlChars[i] == ':' && i + 1 < sqlChars.length && isJavaIdentifierPart(sqlChars[i + 1]) && (i - 1 < 0 || sqlChars[i - 1] != ':')))) {
            // [#5307] Consume PostgreSQL style operators. These aren't bind variables!
            if (sqlChars[i] == '?' && i + 1 < sqlChars.length) {
                for (String suffix : NON_BIND_VARIABLE_SUFFIXES) {
                    if (peek(sqlChars, i + 1, suffix)) {
                        for (int j = i; i - j <= suffix.length(); i++) render.sql(sqlChars[i]);
                        render.sql(sqlChars[i]);
                        continue characterLoop;
                    }
                }
            }
            // [#4131] Consume the named bind variable
            if (sqlChars[i] == ':')
                while (++i < sqlChars.length && isJavaIdentifierPart(sqlChars[i])) ;
            QueryPart substitute = substitutes.get(substituteIndex++);
            if (render.paramType() == INLINED || render.paramType() == NAMED || render.paramType() == NAMED_OR_INLINED) {
                render.visit(substitute);
            } else {
                CastMode previous = render.castMode();
                render.castMode(CastMode.NEVER).visit(substitute).castMode(previous);
            }
            if (bind != null) {
                bind.visit(substitute);
            }
        } else // [#1432] Inline substitues for {numbered placeholders} outside of string literals
        if (sqlChars[i] == '{') {
            // [#1461] Be careful not to match any JDBC escape syntax
            if (peekAny(sqlChars, i, JDBC_ESCAPE_PREFIXES, true)) {
                render.sql(sqlChars[i]);
            } else // Consume the whole token
            {
                int start = ++i;
                for (; i < sqlChars.length && sqlChars[i] != '}'; i++) ;
                int end = i;
                String token = sql.substring(start, end);
                // Try getting the {numbered placeholder}
                try {
                    QueryPart substitute = substitutes.get(Integer.valueOf(token));
                    render.visit(substitute);
                    if (bind != null) {
                        bind.visit(substitute);
                    }
                }// If the above failed, then we're dealing with a {keyword}
                 catch (NumberFormatException e) {
                    render.keyword(token);
                }
            }
        } else // Any other character
        {
            render.sql(sqlChars[i]);
        }
    }
}
Also used : BindContext(org.jooq.BindContext) RenderContext(org.jooq.RenderContext) SQLDialect(org.jooq.SQLDialect) QueryPart(org.jooq.QueryPart) CastMode(org.jooq.RenderContext.CastMode)

Example 3 with QueryPart

use of org.jooq.QueryPart in project jOOQ by jOOQ.

the class Function method toSQLOverClause.

final void toSQLOverClause(Context<?> ctx) {
    QueryPart window = window(ctx);
    // Render this clause only if needed
    if (window == null)
        return;
    // [#1524] Don't render this clause where it is not supported
    if (term == ROW_NUMBER && ctx.configuration().dialect() == HSQLDB)
        return;
    ctx.sql(' ').keyword("over").sql(' ').visit(window);
}
Also used : QueryPart(org.jooq.QueryPart)

Example 4 with QueryPart

use of org.jooq.QueryPart in project jOOQ by jOOQ.

the class AbstractContext method visit.

// ------------------------------------------------------------------------
// VisitListener API
// ------------------------------------------------------------------------
@Override
public final C visit(QueryPart part) {
    if (part != null) {
        // Issue start clause events
        // -----------------------------------------------------------------
        Clause[] clauses = visitListeners.length > 0 ? clause(part) : null;
        if (clauses != null)
            for (int i = 0; i < clauses.length; i++) start(clauses[i]);
        // Perform the actual visiting, or recurse into the replacement
        // -----------------------------------------------------------------
        QueryPart original = part;
        QueryPart replacement = start(part);
        if (original == replacement)
            visit0(original);
        else
            visit0(replacement);
        end(replacement);
        // -----------------------------------------------------------------
        if (clauses != null)
            for (int i = clauses.length - 1; i >= 0; i--) end(clauses[i]);
    }
    return (C) this;
}
Also used : QueryPart(org.jooq.QueryPart) Clause(org.jooq.Clause)

Aggregations

QueryPart (org.jooq.QueryPart)4 BindContext (org.jooq.BindContext)1 Clause (org.jooq.Clause)1 Field (org.jooq.Field)1 RenderContext (org.jooq.RenderContext)1 CastMode (org.jooq.RenderContext.CastMode)1 SQLDialect (org.jooq.SQLDialect)1 SortField (org.jooq.SortField)1