Page 1 of 1

Unknown function TRIM: firebird 1.5

Posted: 06.12.2014, 11:35
by tkszeos
Hi, I use Delhpi 7, firebird 1.5, zeosdbo 7.1.4, windows 7 64.

I have the following query:

Code: Select all

SELECT DISTINCT
  PREVHDR."Codice Hotel",
  PREVHDR."Oggetto",
  PREVHDR."Arrivo",
  PREVHDR."Partenza",
  LINGUE_PC."Oggetto" AS "OggettoPC",
  LINGUE_PC."Arrivo" AS "ArrivoPC",
  LINGUE_PC."Partenza" AS "PartenzaPC"
FROM
  PREVHDR
  INNER JOIN LINGUE_PC ON (PREVHDR."Lingua" = LINGUE_PC."Codice")
PREVHDR."Codice Hotel" defined as VARCHAR(3)
PREVHDR."Oggetto" defined as VARCHAR(50)
PREVHDR."Arrivo" defined as DATE
PREVHDR."Partenza" defined as DATE
LINGUE_PC."Oggetto" AS "OggettoPC" defined as VARCHAR(20)
LINGUE_PC."Arrivo" AS "ArrivoPC" defined as VARCHAR(20)
LINGUE_PC."Partenza" AS "PartenzaPC" defined as VARCHAR(20)

When in the field editor I add the fields, I have the following message: "...function unknown TRIM...".
The problem is the function TZInterbase6DatabaseMetadata.ConstructNameCondition in the unit ZDbcInterbase6Metadata

Code: Select all

TZInterbase6DatabaseMetadata.ConstructNameCondition function (Pattern: string;
   Column: string): string;
begin
   Result: = Inherited ConstructnameCondition (Pattern, 'trim (' + Column + ')');
end;
in firebird 1.5 TRIM is not defined!

Second problem:
I have eliminated TRIM in the above function. The message no longer appears but the fields "ArrivoPC" and "Partenza PC" are declared TDateField but, having defined them as VARCHAR (20), they should be declared as TStringField. The other fields are defined properly.

In Zeosdbo 6.6.6 all this does not happen.

Help me

Re: Unknown function TRIM: firebird 1.5

Posted: 10.12.2014, 22:52
by EgonHugeist
I'll reply next days again. Have to collect some more informations. The old way was wrong, the "trim" is not supported for FB1 and interbase, same as "TRIMR" which need to be registered first.. Actually no idea. Might become a huge discussion..

Re: Unknown function TRIM: firebird 1.5

Posted: 14.12.2014, 10:06
by EgonHugeist
Me again.

To find a solution i did start a research why this was changed. See:
http://zeoslib.sourceforge.net/viewtopi ... rim#p23838

In addition to your issue there are some more problems:
http://sourceforge.net/p/zeoslib/tickets/105/
http://zeoslib.sourceforge.net/viewtopi ... 18&t=19137
....

So we won't keep it as is.
Note in latest testing/trunk branches i already implementet a FireBird/InterBase check and i have a exact version for FireBird. So we can handle different kind of syntax for the queries.
In addition we did Remove the '_'-charakter from the WildCard-List see: http://sourceforge.net/p/zeoslib/tickets/63/

So this Wild-Card may be the reason for theis workaraound.

@Jan/marsupilami
can you do some resaerches if "old" syntax works with new situation of removed '_'-wildcard char?

Any help would by welcome -> work overload :prog:

Re: Unknown function TRIM: firebird 1.5

Posted: 16.12.2014, 19:25
by marsupilami
Hello Michael,

Puh - I will try to come up with some checks during the weekend. But currently I am under work overload too - that is why I have been absent from the forum for the last months...
Best regards,

Jan

Re: Unknown function TRIM: firebird 1.5

Posted: 24.12.2014, 11:47
by EgonHugeist
Hello Jan,

this issue make me headache. I really would be happy if someone could spend some time to checkout how a "common" solution could work. For FB2up we'll keep it as is but to be honest: we need a solution for the old servers!!

Re: Unknown function TRIM: firebird 1.5

Posted: 31.12.2014, 12:31
by marsupilami
Hello Michael,

after some time of thinking, I think there is no safe way to do a search with wildcards in Firebird 1.0 and 1.5. This is because table names are padded with spaces in the Firebird and Interbase system tables and the like condition does not remove them whereas they are ignored with a simle = operator. Something similar should be true for some Versions of Interbase but I don't have enough knowledge there (yet).

So my suggestion is to either raise an exception if somebody tries to do a search with wildcards or do a "downcast" of the search pattern to a simple table name. Maybe the attached patch can explain this idea better. The patch is for http://svn.code.sf.net/p/zeoslib/code-0 ... ng-7.2/src

A lot of Zeos internal functions seem to simply use table names as input for IZDatabaseMetadata.ConstructNameCondition and IZDatabaseMetadata.GetColumns without escaping them properly. Maybe they should be fixed in a way similar to the way I did it with TZAbstractResultSetMetadata.GetTableColumns in this patch? If you think so, I could try to find the relevant places in the Zeos code base...

Best regards,

Jan

Re: Unknown function TRIM: firebird 1.5

Posted: 31.12.2014, 14:36
by EgonHugeist
Thank you Jan,

i'll check the patch now..

Re: Unknown function TRIM: firebird 1.5

Posted: 06.01.2015, 16:47
by EgonHugeist
Hello Jan,

after looking to the patch..

Hmpf what can i say. Now we've the '_' char again in the WildCard-list which is against: ticket #63.
The change of ZDbcResultSetMetadata.pas: Could this be done in another way? I wouldn't touch this peace of code.
Raising a Exception in this case where users are expecting a automation code sonds not so good for me.

I was thinking about use the "old" code for FB<2.0 and for Interbase i can't judge it. Dali seems to be happy without the TRIM.

Anyway thanks for the first approach but actually i didn't apply the patch because of lack of knowledge and my objection. Jan could you think about it again? The old code did work for a long time and i'm happy about your FB2+ fix...
Actually i did disagree building the RC-Version of 7.2 as long this nasty bug is pending. Soo it would be nice if Dali, and tkszeos would join the discussion to find a "best-practice" way how we can resolve this bug for such old Servers.

Re: Unknown function TRIM: firebird 1.5

Posted: 07.01.2015, 00:18
by tkszeos
Hi,
I was quietly waiting for progress. Given the problems encountered I think the most immediate solution, although not the best, is to use the "old" code for FB <2.0. I currently use the version 6.6.6-stable without any problem.
Thanks for the great work done

Re: Unknown function TRIM: firebird 1.5

Posted: 08.01.2015, 19:45
by marsupilami
Hello Michael,

I know this post is getting lengthy already and I am sorry, if I am talking to much or get to much into details you already know or anything...

There is no easy solution to this as all solutions may break some software. But on the other hand - that would be software that did not follow the specs from the start. Let me start with the Zeos source code embedded documentation for TZAbstractDatabaseMetadata.GetColumns:
ZDbcMetadata.pas wrote: @param catalog a catalog name; "" retrieves those without a
catalog; null means drop catalog name from the selection criteria
@param schemaPattern a schema name pattern; "" retrieves those
without a schema
@param tableNamePattern a table name pattern
@param columnNamePattern a column name pattern
The table name parameter can be a pattern. This way it is possible to retrieve information for more than one table at a time. This problem is mostly about this possibility.
Now we've the '_' char again in the WildCard-list which is against: ticket #63.
Hmmm - I think ticket #63 was fixed in R3149. Back then the result of ConstructNameConditon for a Pattern looked like:

Code: Select all

    Result := Format('%s like %s',
      [Column, EscapeString(WorkPattern+'%')]);
Removing the '_' char from the wildcard list made ConstructNameCondition believe it was a simple comparison and made it construct its result like this:

Code: Select all

Result := Format('%s = %s', [Column, EscapeString(WorkPattern)]);
So - instead of getting something like "where TABELNAME like 'PLU__%' which also returned information for the table PLUSA, Zeos now constructed a statement whith this condition "where TABLENAME = 'PLU__'" that will return only columns for the table PLUU. In my opinion the real fix for this problem would have been to fix the caller to escape the _-chars. Removing _ from the wildchar list is more or less a violation of the specification for the function TZAbstractDatabaseMetadata.GetColumns. I tried to fix this in ZDbcResultSetMetadata.pas by adding the escaping function there.
Please note the % that was appended to the work pattern if it was a pattern at this time. This later on became the culprit for this thread: "0 record(s) updated. Only one record should have been updated". The solution of this thread was to remove the trailing % and add a trim for Firebird.
The change of ZDbcResultSetMetadata.pas: Could this be done in another way? I wouldn't touch this peace of code.
This change adresses the main problem. Whatever the solution to this problem will be, any caller of TZAbstractDatabaseMetadata.GetColumns should escape the wildchars in the table name if it knows that it wants the columns of exactly one table, even if the table name contains a _ or a %.
Raising a Exception in this case where users are expecting a automation code sonds not so good for me.
This change in ZDbcInterbase6Metadata.pas is an examle to notify callers that there is no safe way to use a pattern for the table name with Firebird 1.5 and 1.0. If you don't like the exception you also can do a downcast of the pattern to a table name by adding the necessary escape characters:

Code: Select all

      Result := Inherited ConstructnameCondition(AddEscapeCharToWildcards(Pattern), Column)
This will work under all circumstances but users might wonder why TABLE% doesn't give a result for all columns of TABLEA and TABLEB.
I was thinking about use the "old" code for FB<2.0 and for Interbase i can't judge it. Dali seems to be happy without the TRIM.
The problem with the old code is that there are corner cases for all the old codes that don't work as expected if you use a table name that is a pattern:

Imagine a database with these tables:
ABC
A_C
ABCD

_ enabled as a wildcard and Result := Format('%s like %s', [Column, EscapeString(WorkPattern+'%')]);
This code will fail on the pattern 'A_C' because it returns information about table ABCD where it should only have shown information about ABC and A_C.

_ disabled as a wildcard and Result := Format('%s like %s', [Column, EscapeString(WorkPattern+'%')]);
This code will fail on the pattern 'A%C' because it returns information about ABCD where it should only have shown information about ABC and A_C.

_ disabled as a wildcard and Result := Format('%s like %s', [Column, EscapeString(WorkPattern)]); (% removed from the WorkPattern)
This code will fail on nearly all patterns because it will not return any information at all. Firebird will padd the table names with spaces in its system tables because they use tha char(32) type there. So
"ABC" effectively becomes "ABC" + 29 spaces
"A_C" effectively becomes "A_C" + 29 spaces
"ABCD" effectively becomes "ABCD" + 28 spaces
A comparison with like will not remove these spaces, whereas a comparison with the = operator will. The only solution, I can think of is to remove them by using the trim function. But the trim function is only available for Firebird Versions 2.0 and up. So there is no simple way of doing a pattern search with these servers. Hence I opt to disable it one way or another.

But disabling the possibility to do a search by a pattern for the old Firebird and Interbase servers should not be a big issue, I think. Most users of ConstructNameCondition will most probably only look for one table at a time any way. And if they enter anything wrong the exception would inform them of the problem whereas the downcasting would silently work in a way the user doesn't expect. Usually I am the guy that opts for informing the user that he does something wrong or something is not suported...

I am sorry again for this lengthy post. I hope it will help to make good decisions...

Best regards,

Jan

Re: Unknown function TRIM: firebird 1.5

Posted: 26.01.2015, 20:33
by marsupilami
Just pushing this thread to bring it back to mind. :)

Re: Unknown function TRIM: firebird 1.5

Posted: 17.03.2015, 19:59
by Dali
I'm very sorry for not having said anything before, but I had to be away for a couple of months because of huge changes at my office which required all my attention.
EgonHugeist wrote:(...)
I was thinking about use the "old" code for FB<2.0 and for Interbase i can't judge it. Dali seems to be happy without the TRIM.
(...)
Yes, I'm still happy without the "trim". Let's remember what I did:

Code: Select all

In file ZDbcInterbase6Metadata.pas:

function TZInterbase6DatabaseMetadata.ConstructNameCondition(Pattern: string;
  Column: string): string;
begin
//  Result := Inherited ConstructnameCondition(Pattern,'trim('+Column+')');
  Result := Inherited ConstructnameCondition(Pattern,Column);
end;
It's still working for me, not a single issue with it. I don't know in what conditions it should fail, though.

I was using 7.1 until today and I'm checking 7.2 out at this moment because I want to try the ADO connectivity under FPC/Lazarus out. I'll let you know if anything changes.

Re: Unknown function TRIM: firebird 1.5

Posted: 03.01.2016, 19:50
by marsupilami
Hello Michael,

this is my proposed solution for this issue. I didn't check it in yet, because I want to have your comments. With best regards,

Jan