zeoslib  UNKNOWN
 All Files
ZFunctionsStrings.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { Variables classes and interfaces }
5 { }
6 { Originally written by Sergey Seroukhov }
7 { }
8 {*********************************************************}
9 
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
12 { }
13 { License Agreement: }
14 { }
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. }
20 { }
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. }
39 { }
40 { }
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) }
45 { }
46 { http://www.sourceforge.net/projects/zeoslib. }
47 { }
48 { }
49 { Zeos Development Group. }
50 {********************************************************@}
51 
52 unit ZFunctionsStrings;
53 
54 interface
55 
56 {$I ZCore.inc}
57 
58 uses
59  SysUtils, ZFunctions, ZExpression, ZVariant;
60 
61 {** String functions}
62 
63 type
64  {** Implements a CONCAT function. }
65  TZConcatFunction = class (TZAbstractFunction)
66  public
67  function Execute(Stack: TZExecutionStack;
68  VariantManager: IZVariantManager): TZVariant; override;
69  end;
70 
71  {** Implements a SUBSTR function. }
72  TZSubStrFunction = class (TZAbstractFunction)
73  public
74  function Execute(Stack: TZExecutionStack;
75  VariantManager: IZVariantManager): TZVariant; override;
76  end;
77 
78  {** Implements a LEFT function. }
79  TZLeftFunction = class (TZAbstractFunction)
80  public
81  function Execute(Stack: TZExecutionStack;
82  VariantManager: IZVariantManager): TZVariant; override;
83  end;
84 
85  {** Implements a RIGHT function. }
86  TZRightFunction = class (TZAbstractFunction)
87  public
88  function Execute(Stack: TZExecutionStack;
89  VariantManager: IZVariantManager): TZVariant; override;
90  end;
91 
92  {** Implements a STRPOS function. }
93  TZStrPosFunction = class (TZAbstractFunction)
94  public
95  function Execute(Stack: TZExecutionStack;
96  VariantManager: IZVariantManager): TZVariant; override;
97  end;
98 
99  {** Implements a LENGTH function. }
100  TZLengthFunction = class (TZAbstractFunction)
101  public
102  function Execute(Stack: TZExecutionStack;
103  VariantManager: IZVariantManager): TZVariant; override;
104  end;
105 
106  {** Implements a UPPER function. }
107  TZUpperFunction = class (TZAbstractFunction)
108  public
109  function Execute(Stack: TZExecutionStack;
110  VariantManager: IZVariantManager): TZVariant; override;
111  end;
112 
113  {** Implements a LOWER function. }
114  TZLowerFunction = class (TZAbstractFunction)
115  public
116  function Execute(Stack: TZExecutionStack;
117  VariantManager: IZVariantManager): TZVariant; override;
118  end;
119 
120  {** Implements a CAPITALIZE function. }
121  TZCapitalizeFunction = class (TZAbstractFunction)
122  public
123  function Execute(Stack: TZExecutionStack;
124  VariantManager: IZVariantManager): TZVariant; override;
125  end;
126 
127  {** Implements a TRIM function. }
128  TZTrimFunction = class (TZAbstractFunction)
129  public
130  function Execute(Stack: TZExecutionStack;
131  VariantManager: IZVariantManager): TZVariant; override;
132  end;
133 
134  {** Implements a LTRIM function. }
135  TZLTrimFunction = class (TZAbstractFunction)
136  public
137  function Execute(Stack: TZExecutionStack;
138  VariantManager: IZVariantManager): TZVariant; override;
139  end;
140 
141  {** Implements a RTRIM function. }
142  TZRTrimFunction = class (TZAbstractFunction)
143  public
144  function Execute(Stack: TZExecutionStack;
145  VariantManager: IZVariantManager): TZVariant; override;
146  end;
147 
148  {** Implements a SOUNDEX function. }
149  TZSoundexFunction = class (TZAbstractFunction)
150  public
151  function Execute(Stack: TZExecutionStack;
152  VariantManager: IZVariantManager): TZVariant; override;
153  end;
154 
155  {** Implements a LEVENSHTEINDIST function. }
156  TZLevenshteinDistanceFunction = class (TZAbstractFunction)
157  public
158  function Execute(Stack: TZExecutionStack;
159  VariantManager: IZVariantManager): TZVariant; override;
160  end;
161 
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);
165 
166 {$IFNDEF FPC}
167 {$ENDIF}
168 
169 implementation
170 
171 uses
172  Math, StrUtils, ZMessages, ZCompatibility;
173 
174 Function Capitalize(const s:string; Delims : string = '') : string;
175 var
176  sDelims : set of ansichar;
177  i : integer;
178 begin
179  if Delims = '' then
180  sDelims := StdWordDelims
181  else
182  begin
183  sDelims := [];
184  for i:=1 to Length(Delims) do
185  Include(sDelims,AnsiChar(Delims[i]))
186  end;
187  Result := AnsiProperCase(s, sDelims);
188 end;
189 
190 Function LevenshteinDistance(const s1, s2: string; const DoUpcase : BOOLEAN = TRUE): Integer;
191 
192 var
193  d : array of array of Integer;
194  s,t : string;
195  Start,
196  Len1,
197  Len2,
198  i, j,
199  Cost : Integer;
200 
201 begin
202  Len1 := Length(s1);
203  Len2 := Length(s2);
204 
205  if Len1 = 0 then
206  begin
207  Result := Len2;
208  Exit;
209  end;
210  if Len2 = 0 then
211  begin
212  Result := Len1;
213  Exit;
214  end;
215  if DoUpcase then
216  begin
217  s := Uppercase(s1);
218  t := Uppercase(s2);
219  end
220  else
221  begin
222  s := s1;
223  t := s2;
224  end;
225  start := 1;
226 // trim off the matching items at the beginning
227  while (start <= Len1) and (start <= Len2) and (s[start] = t[start]) do
228  INC(start);
229 // trim off the matching items at the end
230  while (start <= Len1) and (start <= Len2) and (s[Len1] = t[Len2]) do
231  begin
232  DEC(Len1);
233  DEC(Len2);
234  end;
235 
236  DEC(Start);
237 
238  DEC(Len1, Start);
239  DEC(Len2, Start);
240 
241  if Len1 = 0 then
242  begin
243  Result := Len2;
244  Exit;
245  end;
246  if Len2 = 0 then
247  begin
248  Result := Len1;
249  Exit;
250  end;
251 
252  setlength(d, Len1 + 1, Len2 + 1);
253  for i := 0 to Len1 do
254  d[i, 0] := i;
255  for j := 0 to Len2 do
256  d[0, j] := j;
257 
258 // only loop over the items that are different
259  for i := 1 to Len1 do
260  begin
261  for j := 1 to Len2 do
262  begin
263  Cost := ABS(ORD(s[i+start] <> t[j+start]));
264  d[i, j] := Min(
265  Min(d[i-1,j]+1, // deletion
266  d[i,j-1]+1), // insertion
267  d[i-1,j-1]+Cost); // substitution
268  end;
269  end;
270  Result := d[Len1, Len2];
271 end;
272 
273 {**** This is the original not optimized version
274 Function LevenshteinDistance(const s1, s2: string; const DoUpcase : BOOLEAN = TRUE): Integer;
275 
276 var
277  d : array of array of Integer;
278  s,t : string;
279  Len1,
280  Len2,
281  i, j,
282  Cost : Integer;
283 begin
284  Len1 := Length(s1);
285  Len2 := Length(s2);
286  if Len1 = 0 then
287  begin
288  Result := Len2;
289  Exit;
290  end;
291  if Len2 = 0 then
292  begin
293  Result := Len1;
294  Exit;
295  end;
296  if DoUpcase then
297  begin
298  s := Upcase(s1);
299  t := Upcase(s2);
300  end
301  else
302  begin
303  s := s1;
304  t := s2;
305  end;
306  setlength(d, Len1 + 1, Len2 + 1);
307  for i := 0 to Len1 do
308  d[i, 0] := i;
309  for j := 0 to Len2 do
310  d[0, j] := j;
311  for i := 1 to Len1 do
312  begin
313  for j := 1 to Len2 do
314  begin
315  Cost := ABS(ORD(s[i] <> t[j]));
316  d[i, j] := Min(
317  Min(d[i-1,j]+1,
318  d[i,j-1]+1),
319  d[i-1,j-1]+Cost);
320  end;
321  end;
322  Result := d[Len1, Len2];
323 end;
324 ******}
325 
326 { TZConcatFunction }
327 
328 {**
329  Executes this function.
330  @param Stack the stack object.
331  @param VariantManager a reference to variant processor object.
332  @returns a function value.
333 }
334 function TZConcatFunction.Execute(Stack: TZExecutionStack;
335  VariantManager: IZVariantManager): TZVariant;
336 var
337  I, ParamsCount: Integer;
338  Temp: string;
339 begin
340  ParamsCount := VariantManager.GetAsInteger(Stack.GetParameter(0));
341  if ParamsCount < 2 then
342  raise TZExpressionError.Create(SExpectedMoreParams);
343 
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);
348 end;
349 
350 { TZSubStrFunction }
351 
352 {**
353  Executes this function.
354  @param Stack the stack object.
355  @param VariantManager a reference to variant processor object.
356  @returns a function value.
357 }
358 function TZSubStrFunction.Execute(Stack: TZExecutionStack;
359  VariantManager: IZVariantManager): TZVariant;
360 begin
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))));
366 end;
367 
368 { TZLeftFunction }
369 function TZLeftFunction.Execute(Stack: TZExecutionStack;
370  VariantManager: IZVariantManager): TZVariant;
371 var
372  Value1, Value2: TZVariant;
373 begin
374  CheckParamsCount(Stack, 2);
375  Value1 := Stack.GetParameter(2);
376  Value2 := Stack.GetParameter(1);
377  VariantManager.SetAsString(Result, LeftStr(Value1.VString, Value2.VInteger));
378 end;
379 
380 { TZRightFunction }
381 function TZRightFunction.Execute(Stack: TZExecutionStack;
382  VariantManager: IZVariantManager): TZVariant;
383 var
384  Value1, Value2: TZVariant;
385 begin
386  CheckParamsCount(Stack, 2);
387  Value1 := Stack.GetParameter(2);
388  Value2 := Stack.GetParameter(1);
389  VariantManager.SetAsString(Result, RightStr(Value1.VString, Value2.VInteger));
390 end;
391 
392 { TZStrPosFunction }
393 
394 {**
395  Executes this function.
396  @param Stack the stack object.
397  @param VariantManager a reference to variant processor object.
398  @returns a function value.
399 }
400 function TZStrPosFunction.Execute(Stack: TZExecutionStack;
401  VariantManager: IZVariantManager): TZVariant;
402 begin
403  CheckParamsCount(Stack, 2);
404  VariantManager.SetAsInteger(Result, Pos(
405  VariantManager.GetAsString(Stack.GetParameter(2)),
406  VariantManager.GetAsString(Stack.GetParameter(1))));
407 end;
408 
409 { TZLengthFunction }
410 
411 {**
412  Executes this function.
413  @param Stack the stack object.
414  @param VariantManager a reference to variant processor object.
415  @returns a function value.
416 }
417 function TZLengthFunction.Execute(Stack: TZExecutionStack;
418  VariantManager: IZVariantManager): TZVariant;
419 begin
420  CheckParamsCount(Stack, 1);
421  VariantManager.SetAsInteger(Result, Length(VariantManager.GetAsString(Stack.GetParameter(1))));
422 end;
423 
424 { TZLowerFunction }
425 
426 {**
427  Executes this function.
428  @param Stack the stack object.
429  @param VariantManager a reference to variant processor object.
430  @returns a function value.
431 }
432 function TZLowerFunction.Execute(Stack: TZExecutionStack;
433  VariantManager: IZVariantManager): TZVariant;
434 begin
435  CheckParamsCount(Stack, 1);
436  VariantManager.SetAsString(Result, AnsiLowerCase(
437  VariantManager.GetAsString(Stack.GetParameter(1))));
438 end;
439 
440 { TZUpperFunction }
441 
442 {**
443  Executes this function.
444  @param Stack the stack object.
445  @param VariantManager a reference to variant processor object.
446  @returns a function value.
447 }
448 function TZUpperFunction.Execute(Stack: TZExecutionStack;
449  VariantManager: IZVariantManager): TZVariant;
450 begin
451  CheckParamsCount(Stack, 1);
452  VariantManager.SetAsString(Result, AnsiUpperCase(
453  VariantManager.GetAsString(Stack.GetParameter(1))));
454 end;
455 
456 { TZCapitalizeFunction }
457 
458 function TZCapitalizeFunction.Execute(Stack: TZExecutionStack;
459  VariantManager: IZVariantManager): TZVariant;
460 var
461  ParamsCount: Integer;
462 begin
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))))
469  else
470  VariantManager.SetAsString(Result, Capitalize(
471  VariantManager.GetAsString(Stack.GetParameter(2)),
472  VariantManager.GetAsString(Stack.GetParameter(1))))
473 end;
474 
475 { TZTrimFunction }
476 
477 function TZTrimFunction.Execute(Stack: TZExecutionStack;
478  VariantManager: IZVariantManager): TZVariant;
479 var
480  Value: TZVariant;
481 begin
482  CheckParamsCount(Stack, 1);
483  Value := Stack.GetParameter(1);
484  VariantManager.SetAsString(Result, Trim(Value.VString));
485 end;
486 
487 { TZLTrimFunction }
488 
489 function TZLTrimFunction.Execute(Stack: TZExecutionStack;
490  VariantManager: IZVariantManager): TZVariant;
491 var
492  Value: TZVariant;
493 begin
494  CheckParamsCount(Stack, 1);
495  Value := Stack.GetParameter(1);
496  VariantManager.SetAsString(Result, TrimLeft(Value.VString));
497 end;
498 
499 { TZRTrimFunction }
500 
501 function TZRTrimFunction.Execute(Stack: TZExecutionStack;
502  VariantManager: IZVariantManager): TZVariant;
503 var
504  Value: TZVariant;
505 begin
506  CheckParamsCount(Stack, 1);
507  Value := Stack.GetParameter(1);
508  VariantManager.SetAsString(Result, TrimRight(Value.VString));
509 end;
510 
511 { TZSoundexFunction }
512 
513 function TZSoundexFunction.Execute(Stack: TZExecutionStack;
514  VariantManager: IZVariantManager): TZVariant;
515 var
516  ParamsCount: Integer;
517 begin
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))))
524  else
525  VariantManager.SetAsString(Result, Soundex(
526  VariantManager.GetAsString(Stack.GetParameter(2)),
527  VariantManager.GetAsInteger(Stack.GetParameter(1))))
528 end;
529 
530 function TZLevenshteinDistanceFunction.Execute(Stack: TZExecutionStack;
531  VariantManager: IZVariantManager): TZVariant;
532 
533 var
534  ParamsCount: Integer;
535 begin
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,
541  LevenshteinDistance(
542  VariantManager.GetAsString(Stack.GetParameter(2)),
543  VariantManager.GetAsString(Stack.GetParameter(1))))
544  else
545  VariantManager.SetAsInteger(Result,
546  LevenshteinDistance(
547  VariantManager.GetAsString(Stack.GetParameter(3)),
548  VariantManager.GetAsString(Stack.GetParameter(2)),
549  VariantManager.GetAsBoolean(Stack.GetParameter(1))))
550 end;
551 
552 procedure AddStringFunctions(Functions : TZFunctionsList);
553 begin
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'));
560 
561  Functions.Add(TZUpperFunction.Create('UPPER'));
562  Functions.Add(TZLowerFunction.Create('LOWER'));
563  Functions.Add(TZCapitalizeFunction.Create('CAP'));
564  Functions.Add(TZCapitalizeFunction.Create('CAPITALIZE'));
565 
566  Functions.Add(TZTrimFunction.Create('TRIM'));
567  Functions.Add(TZLTrimFunction.Create('LTRIM'));
568  Functions.Add(TZRTrimFunction.Create('RTRIM'));
569 
570  Functions.Add(TZSoundexFunction.Create('SOUNDEX'));
571  Functions.Add(TZLevenshteinDistanceFunction.Create('LEVDIST'));
572  Functions.Add(TZLevenshteinDistanceFunction.Create('LEVENSHTEINDISTANCE'));
573 end;
574 
575 end.
576