Skip to content

Superfluous SQL casts generated in FirebirdClientDriver #1886

Closed
@catcrab

Description

@catcrab

I've discovered two problems:

  1. In select statements, every parameter is 'casted'.
    When single entity selected by ID (Session.Get), SQL is good, but when selecting multiple entities using Restrictions.InG, every ID is casted. Searching internet, i've found one forum thread about this problem.
    SQL example:
SELECT this_.ID as ID19_0_,
        this_.NAME as NAME19_0_,
        this_.SHORT_NAME as SHORT3_19_0_,
        this_.CREATE_DATETIME as CREATE4_19_0_,
        this_.PARENT_ID as PARENT5_19_0_,
        this_.TYPE_ID as TYPE6_19_0_,
        this_.STATE_ID as STATE7_19_0_,
        this_.TYPE_ID as clazz_0_
    FROM L_TREE this_
    WHERE this_.ID in (cast(@p0 as VARCHAR(255)))

Parameters:
Name:@p0 Type:VarChar Used Value:c034e889-3b80-42d3-bdad-5f4e729a905b

More details here (Russian).

The problem is Firebird SQL server stops using primary key when parameter list is too long and every parameter is casted (it uses index, if I remove casts). For short parameter lists, casts does not affect query plan.

  1. In insert statements, I can't insert long string (more than 255 chars) into some tables, because string parameter is casted to varchar(255):
INSERT INTO My_Table (Fio, SELECTED_MODE, STATE)
    VALUES (cast(@p0 as VARCHAR(255)), cast(@p1 as INTEGER), cast(@p2 as INTEGER))

After reading debug logs and source code, i've got explanation of this.
Looks like FirebirdClientDriver expected to cast parameters for 'first', 'between' and 'like' operators in select statements, but there are two mistakes in regexes.

The regex
string SELECT_CLAUSE_EXP = @"(?<=\bselect|\bwhere).*";
should match 'select' statements with 'where', but it matches any statement, containing word, starting with 'select' or 'where' (like INSERT INTO My_Table (Fio, SELECTED_MODE...) given above)

The regex
CAST_PARAMS_EXP = @"(?<![=<>]\s?|first\s?|skip\s?|between\s|between\s@\bp\w+\b\sand\s)@\bp\w+\b(?!\s?[=<>])";
should match parameters of first, between, like, etc. But matches every parameter that is not prepended with = < > characters.

Not a regex guru, so I have no idea, how to fix them right.
But completely removing parameter casting (GetStatementsWithCastCandidates, GetCastCandidates) have no issues with current versions of firebird (2.x, 3.0). I suspect that 'cast' was workaround for very old firebird versions, and are not actual today.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions