1 {*********************************************************}
3 { Zeos Database Objects }
4 { Variables classes and interfaces }
6 { Originally written by Sergey Seroukhov }
8 {*********************************************************}
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
13 { License Agreement: }
15 { This library is distributed in the hope that it will be }
16 { useful, but WITHOUT ANY WARRANTY; without even the }
17 { implied warranty of MERCHANTABILITY or FITNESS FOR }
18 { A PARTICULAR PURPOSE. See the GNU Lesser General }
19 { Public License for more details. }
21 { The source code of the ZEOS Libraries and packages are }
22 { distributed under the Library GNU General Public }
23 { License (see the file COPYING / COPYING.ZEOS) }
24 { with the following modification: }
25 { As a special exception, the copyright holders of this }
26 { library give you permission to link this library with }
27 { independent modules to produce an executable, }
28 { regardless of the license terms of these independent }
29 { modules, and to copy and distribute the resulting }
30 { executable under terms of your choice, provided that }
31 { you also meet, for each linked independent module, }
32 { the terms and conditions of the license of that module. }
33 { An independent module is a module which is not derived }
34 { from or based on this library. If you modify this }
35 { library, you may extend this exception to your version }
36 { of the library, but you are not obligated to do so. }
37 { If you do not wish to do so, delete this exception }
38 { statement from your version. }
41 { The project web site is located on: }
42 { http://zeos.firmos.at (FORUM) }
43 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
44 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
46 { http://www.sourceforge.net/projects/zeoslib. }
49 { Zeos Development Group. }
50 {********************************************************@}
52 unit ZFunctionsStrings;
59 SysUtils, ZFunctions, ZExpression, ZVariant;
64 {** Implements a CONCAT function. }
65 TZConcatFunction = class (TZAbstractFunction)
67 function Execute(Stack: TZExecutionStack;
68 VariantManager: IZVariantManager): TZVariant; override;
71 {** Implements a SUBSTR function. }
72 TZSubStrFunction = class (TZAbstractFunction)
74 function Execute(Stack: TZExecutionStack;
75 VariantManager: IZVariantManager): TZVariant; override;
78 {** Implements a LEFT function. }
79 TZLeftFunction = class (TZAbstractFunction)
81 function Execute(Stack: TZExecutionStack;
82 VariantManager: IZVariantManager): TZVariant; override;
85 {** Implements a RIGHT function. }
86 TZRightFunction = class (TZAbstractFunction)
88 function Execute(Stack: TZExecutionStack;
89 VariantManager: IZVariantManager): TZVariant; override;
92 {** Implements a STRPOS function. }
93 TZStrPosFunction = class (TZAbstractFunction)
95 function Execute(Stack: TZExecutionStack;
96 VariantManager: IZVariantManager): TZVariant; override;
99 {** Implements a LENGTH function. }
100 TZLengthFunction = class (TZAbstractFunction)
102 function Execute(Stack: TZExecutionStack;
103 VariantManager: IZVariantManager): TZVariant; override;
106 {** Implements a UPPER function. }
107 TZUpperFunction = class (TZAbstractFunction)
109 function Execute(Stack: TZExecutionStack;
110 VariantManager: IZVariantManager): TZVariant; override;
113 {** Implements a LOWER function. }
114 TZLowerFunction = class (TZAbstractFunction)
116 function Execute(Stack: TZExecutionStack;
117 VariantManager: IZVariantManager): TZVariant; override;
120 {** Implements a CAPITALIZE function. }
121 TZCapitalizeFunction = class (TZAbstractFunction)
123 function Execute(Stack: TZExecutionStack;
124 VariantManager: IZVariantManager): TZVariant; override;
127 {** Implements a TRIM function. }
128 TZTrimFunction = class (TZAbstractFunction)
130 function Execute(Stack: TZExecutionStack;
131 VariantManager: IZVariantManager): TZVariant; override;
134 {** Implements a LTRIM function. }
135 TZLTrimFunction = class (TZAbstractFunction)
137 function Execute(Stack: TZExecutionStack;
138 VariantManager: IZVariantManager): TZVariant; override;
141 {** Implements a RTRIM function. }
142 TZRTrimFunction = class (TZAbstractFunction)
144 function Execute(Stack: TZExecutionStack;
145 VariantManager: IZVariantManager): TZVariant; override;
148 {** Implements a SOUNDEX function. }
149 TZSoundexFunction = class (TZAbstractFunction)
151 function Execute(Stack: TZExecutionStack;
152 VariantManager: IZVariantManager): TZVariant; override;
155 {** Implements a LEVENSHTEINDIST function. }
156 TZLevenshteinDistanceFunction = class (TZAbstractFunction)
158 function Execute(Stack: TZExecutionStack;
159 VariantManager: IZVariantManager): TZVariant; override;
162 Function Capitalize(const s:string; Delims : string = '') : string;
163 Function LevenshteinDistance(const s1, s2: string; const DoUpcase : BOOLEAN = TRUE): Integer;
164 procedure AddStringFunctions(Functions : TZFunctionsList);
172 Math, StrUtils, ZMessages, ZCompatibility;
174 Function Capitalize(const s:string; Delims : string = '') : string;
176 sDelims : set of ansichar;
180 sDelims := StdWordDelims
184 for i:=1 to Length(Delims) do
185 Include(sDelims,AnsiChar(Delims[i]))
187 Result := AnsiProperCase(s, sDelims);
190 Function LevenshteinDistance(const s1, s2: string; const DoUpcase : BOOLEAN = TRUE): Integer;
193 d : array of array of Integer;
226 // trim off the matching items at the beginning
227 while (start <= Len1) and (start <= Len2) and (s[start] = t[start]) do
229 // trim off the matching items at the end
230 while (start <= Len1) and (start <= Len2) and (s[Len1] = t[Len2]) do
252 setlength(d, Len1 + 1, Len2 + 1);
253 for i := 0 to Len1 do
255 for j := 0 to Len2 do
258 // only loop over the items that are different
259 for i := 1 to Len1 do
261 for j := 1 to Len2 do
263 Cost := ABS(ORD(s[i+start] <> t[j+start]));
265 Min(d[i-1,j]+1, // deletion
266 d[i,j-1]+1), // insertion
267 d[i-1,j-1]+Cost); // substitution
270 Result := d[Len1, Len2];
273 {**** This is the original not optimized version
274 Function LevenshteinDistance(const s1, s2: string; const DoUpcase : BOOLEAN = TRUE): Integer;
277 d : array of array of Integer;
306 setlength(d, Len1 + 1, Len2 + 1);
307 for i := 0 to Len1 do
309 for j := 0 to Len2 do
311 for i := 1 to Len1 do
313 for j := 1 to Len2 do
315 Cost := ABS(ORD(s[i] <> t[j]));
322 Result := d[Len1, Len2];
329 Executes this function.
330 @param Stack the stack object.
331 @param VariantManager a reference to variant processor object.
332 @returns a function value.
334 function TZConcatFunction.Execute(Stack: TZExecutionStack;
335 VariantManager: IZVariantManager): TZVariant;
337 I, ParamsCount: Integer;
340 ParamsCount := VariantManager.GetAsInteger(Stack.GetParameter(0));
341 if ParamsCount < 2 then
342 raise TZExpressionError.Create(SExpectedMoreParams);
344 Temp := VariantManager.GetAsString(Stack.GetParameter(ParamsCount));
345 for I := ParamsCount - 1 downto 1 do
346 Temp := Temp + VariantManager.GetAsString(Stack.GetParameter(I));
347 VariantManager.SetAsString(Result, Temp);
353 Executes this function.
354 @param Stack the stack object.
355 @param VariantManager a reference to variant processor object.
356 @returns a function value.
358 function TZSubStrFunction.Execute(Stack: TZExecutionStack;
359 VariantManager: IZVariantManager): TZVariant;
361 CheckParamsCount(Stack, 3);
362 VariantManager.SetAsString(Result, Copy(
363 VariantManager.GetAsString(Stack.GetParameter(3)),
364 VariantManager.GetAsInteger(Stack.GetParameter(2)),
365 VariantManager.GetAsInteger(Stack.GetParameter(1))));
369 function TZLeftFunction.Execute(Stack: TZExecutionStack;
370 VariantManager: IZVariantManager): TZVariant;
372 Value1, Value2: TZVariant;
374 CheckParamsCount(Stack, 2);
375 Value1 := Stack.GetParameter(2);
376 Value2 := Stack.GetParameter(1);
377 VariantManager.SetAsString(Result, LeftStr(Value1.VString, Value2.VInteger));
381 function TZRightFunction.Execute(Stack: TZExecutionStack;
382 VariantManager: IZVariantManager): TZVariant;
384 Value1, Value2: TZVariant;
386 CheckParamsCount(Stack, 2);
387 Value1 := Stack.GetParameter(2);
388 Value2 := Stack.GetParameter(1);
389 VariantManager.SetAsString(Result, RightStr(Value1.VString, Value2.VInteger));
395 Executes this function.
396 @param Stack the stack object.
397 @param VariantManager a reference to variant processor object.
398 @returns a function value.
400 function TZStrPosFunction.Execute(Stack: TZExecutionStack;
401 VariantManager: IZVariantManager): TZVariant;
403 CheckParamsCount(Stack, 2);
404 VariantManager.SetAsInteger(Result, Pos(
405 VariantManager.GetAsString(Stack.GetParameter(2)),
406 VariantManager.GetAsString(Stack.GetParameter(1))));
412 Executes this function.
413 @param Stack the stack object.
414 @param VariantManager a reference to variant processor object.
415 @returns a function value.
417 function TZLengthFunction.Execute(Stack: TZExecutionStack;
418 VariantManager: IZVariantManager): TZVariant;
420 CheckParamsCount(Stack, 1);
421 VariantManager.SetAsInteger(Result, Length(VariantManager.GetAsString(Stack.GetParameter(1))));
427 Executes this function.
428 @param Stack the stack object.
429 @param VariantManager a reference to variant processor object.
430 @returns a function value.
432 function TZLowerFunction.Execute(Stack: TZExecutionStack;
433 VariantManager: IZVariantManager): TZVariant;
435 CheckParamsCount(Stack, 1);
436 VariantManager.SetAsString(Result, AnsiLowerCase(
437 VariantManager.GetAsString(Stack.GetParameter(1))));
443 Executes this function.
444 @param Stack the stack object.
445 @param VariantManager a reference to variant processor object.
446 @returns a function value.
448 function TZUpperFunction.Execute(Stack: TZExecutionStack;
449 VariantManager: IZVariantManager): TZVariant;
451 CheckParamsCount(Stack, 1);
452 VariantManager.SetAsString(Result, AnsiUpperCase(
453 VariantManager.GetAsString(Stack.GetParameter(1))));
456 { TZCapitalizeFunction }
458 function TZCapitalizeFunction.Execute(Stack: TZExecutionStack;
459 VariantManager: IZVariantManager): TZVariant;
461 ParamsCount: Integer;
463 ParamsCount := VariantManager.GetAsInteger(Stack.GetParameter(0));
464 if (ParamsCount < 1) then
465 raise TZExpressionError.Create(SExpectedMoreParams);
466 if (ParamsCount < 2) then
467 VariantManager.SetAsString(Result, Capitalize(
468 VariantManager.GetAsString(Stack.GetParameter(1))))
470 VariantManager.SetAsString(Result, Capitalize(
471 VariantManager.GetAsString(Stack.GetParameter(2)),
472 VariantManager.GetAsString(Stack.GetParameter(1))))
477 function TZTrimFunction.Execute(Stack: TZExecutionStack;
478 VariantManager: IZVariantManager): TZVariant;
482 CheckParamsCount(Stack, 1);
483 Value := Stack.GetParameter(1);
484 VariantManager.SetAsString(Result, Trim(Value.VString));
489 function TZLTrimFunction.Execute(Stack: TZExecutionStack;
490 VariantManager: IZVariantManager): TZVariant;
494 CheckParamsCount(Stack, 1);
495 Value := Stack.GetParameter(1);
496 VariantManager.SetAsString(Result, TrimLeft(Value.VString));
501 function TZRTrimFunction.Execute(Stack: TZExecutionStack;
502 VariantManager: IZVariantManager): TZVariant;
506 CheckParamsCount(Stack, 1);
507 Value := Stack.GetParameter(1);
508 VariantManager.SetAsString(Result, TrimRight(Value.VString));
511 { TZSoundexFunction }
513 function TZSoundexFunction.Execute(Stack: TZExecutionStack;
514 VariantManager: IZVariantManager): TZVariant;
516 ParamsCount: Integer;
518 ParamsCount := VariantManager.GetAsInteger(Stack.GetParameter(0));
519 if (ParamsCount < 1) then
520 raise TZExpressionError.Create(SExpectedMoreParams);
521 if (ParamsCount < 2) then
522 VariantManager.SetAsString(Result, Soundex(
523 VariantManager.GetAsString(Stack.GetParameter(1))))
525 VariantManager.SetAsString(Result, Soundex(
526 VariantManager.GetAsString(Stack.GetParameter(2)),
527 VariantManager.GetAsInteger(Stack.GetParameter(1))))
530 function TZLevenshteinDistanceFunction.Execute(Stack: TZExecutionStack;
531 VariantManager: IZVariantManager): TZVariant;
534 ParamsCount: Integer;
536 ParamsCount := VariantManager.GetAsInteger(Stack.GetParameter(0));
537 if (ParamsCount < 2) then
538 raise TZExpressionError.Create(SExpectedMoreParams);
539 if (ParamsCount < 3) then
540 VariantManager.SetAsInteger(Result,
542 VariantManager.GetAsString(Stack.GetParameter(2)),
543 VariantManager.GetAsString(Stack.GetParameter(1))))
545 VariantManager.SetAsInteger(Result,
547 VariantManager.GetAsString(Stack.GetParameter(3)),
548 VariantManager.GetAsString(Stack.GetParameter(2)),
549 VariantManager.GetAsBoolean(Stack.GetParameter(1))))
552 procedure AddStringFunctions(Functions : TZFunctionsList);
554 Functions.Add(TZConcatFunction.Create('CONCAT'));
555 Functions.Add(TZSubStrFunction.Create('SUBSTR'));
556 Functions.Add(TZLeftFunction.Create('LEFT'));
557 Functions.Add(TZRightFunction.Create('RIGHT'));
558 Functions.Add(TZStrPosFunction.Create('STRPOS'));
559 Functions.Add(TZLengthFunction.Create('LENGTH'));
561 Functions.Add(TZUpperFunction.Create('UPPER'));
562 Functions.Add(TZLowerFunction.Create('LOWER'));
563 Functions.Add(TZCapitalizeFunction.Create('CAP'));
564 Functions.Add(TZCapitalizeFunction.Create('CAPITALIZE'));
566 Functions.Add(TZTrimFunction.Create('TRIM'));
567 Functions.Add(TZLTrimFunction.Create('LTRIM'));
568 Functions.Add(TZRTrimFunction.Create('RTRIM'));
570 Functions.Add(TZSoundexFunction.Create('SOUNDEX'));
571 Functions.Add(TZLevenshteinDistanceFunction.Create('LEVDIST'));
572 Functions.Add(TZLevenshteinDistanceFunction.Create('LEVENSHTEINDISTANCE'));