Description
I've discovered two problems:
- 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.
- 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.