00001 {*********************************************************}
00002 { }
00003 { Zeos Database Objects }
00004 { String tokenizing classes for Generic SQL }
00005 { }
00006 { Originally written by Sergey Seroukhov }
00007 { }
00008 {*********************************************************}
00009
00010 {@********************************************************}
00011 { Copyright (c) 1999-2006 Zeos Development Group }
00012 { }
00013 { License Agreement: }
00014 { }
00015 { This library is distributed in the hope that it will be }
00016 { useful, but WITHOUT ANY WARRANTY; without even the }
00017 { implied warranty of MERCHANTABILITY or FITNESS FOR }
00018 { A PARTICULAR PURPOSE. See the GNU Lesser General }
00019 { Public License for more details. }
00020 { }
00021 { The source code of the ZEOS Libraries and packages are }
00022 { distributed under the Library GNU General Public }
00023 { License (see the file COPYING / COPYING.ZEOS) }
00024 { with the following modification: }
00025 { As a special exception, the copyright holders of this }
00026 { library give you permission to link this library with }
00027 { independent modules to produce an executable, }
00028 { regardless of the license terms of these independent }
00029 { modules, and to copy and distribute the resulting }
00030 { executable under terms of your choice, provided that }
00031 { you also meet, for each linked independent module, }
00032 { the terms and conditions of the license of that module. }
00033 { An independent module is a module which is not derived }
00034 { from or based on this library. If you modify this }
00035 { library, you may extend this exception to your version }
00036 { of the library, but you are not obligated to do so. }
00037 { If you do not wish to do so, delete this exception }
00038 { statement from your version. }
00039 { }
00040 { }
00041 { The project web site is located on: }
00042 { http:
00043 { http:
00044 { svn:
00045 { }
00046 { http:
00047 { http:
00048 { }
00049 { }
00050 { }
00051 { Zeos Development Group. }
00052 {********************************************************@}
00053
00054 unit ZGenericSqlToken;
00055
00056 interface
00057
00058 {$I ZParseSql.inc}
00059
00060 uses
00061 Classes, SysUtils, ZTokenizer, ZCompatibility;
00062
00063 type
00064
00065 {** Implements a symbol state object. }
00066 TZGenericSQLSymbolState = class (TZSymbolState)
00067 public
00068 constructor Create;
00069 end;
00070
00071 {** Implements a word state object. }
00072 TZGenericSQLWordState = class (TZWordState)
00073 public
00074 constructor Create;
00075
00076 function NextToken(Stream: TStream; FirstChar: Char;
00077 Tokenizer: TZTokenizer): TZToken; override;
00078 end;
00079
00080 {** Implements a quote string state object. }
00081 TZGenericSQLQuoteState = class (TZQuoteState)
00082 public
00083 function NextToken(Stream: TStream; FirstChar: Char;
00084 Tokenizer: TZTokenizer): TZToken; override;
00085
00086 function EncodeString(const Value: string; QuoteChar: Char): string; override;
00087 function DecodeString(const Value: string; QuoteChar: Char): string; override;
00088 end;
00089
00090 {** Implements a default tokenizer object. }
00091 TZGenericSQLTokenizer = class (TZTokenizer)
00092 public
00093 constructor Create;
00094 end;
00095
00096 implementation
00097
00098 { TZGenericSQLSymbolState }
00099
00100 {**
00101 Creates this SQL-specific symbol state object.
00102 }
00103 constructor TZGenericSQLSymbolState.Create;
00104 begin
00105 inherited Create;
00106 Add('<=');
00107 Add('>=');
00108 Add('<>');
00109 Add('<<');
00110 Add('>>');
00111 end;
00112
00113 { TZGenericSQLWordState }
00114
00115 {**
00116 Constructs this SQL-specific word state object.
00117 }
00118 constructor TZGenericSQLWordState.Create;
00119 begin
00120 SetWordChars(#0, #255, False);
00121 SetWordChars('a', 'z', True);
00122 SetWordChars('A', 'Z', True);
00123 SetWordChars('0', '9', True);
00124 SetWordChars('$', '$', True);
00125 SetWordChars('_', '_', True);
00126 SetWordChars(Char($c0), Char($ff), True);
00127 end;
00128
00129 const
00130 {** List of keywords. }
00131 Keywords: array [0..8] of string = (
00132 'AND','OR','NOT','XOR','LIKE','IS','NULL','TRUE','FALSE'
00133 );
00134
00135 {**
00136 Gets a word tokens or special operators.
00137 @return a processed token.
00138 }
00139 function TZGenericSQLWordState.NextToken(Stream: TStream; FirstChar: Char;
00140 Tokenizer: TZTokenizer): TZToken;
00141 var
00142 I: Integer;
00143 Temp: string;
00144 begin
00145 Result := inherited NextToken(Stream, FirstChar, Tokenizer);
00146 Temp := UpperCase(Result.Value);
00147
00148 for I := Low(Keywords) to High(Keywords) do
00149 begin
00150 if Temp = Keywords[I] then
00151 begin
00152 Result.TokenType := ttKeyword;
00153 Break;
00154 end;
00155 end;
00156 end;
00157
00158
00159 { TZGenericSQLQuoteState }
00160
00161 {**
00162 Return a quoted string token from a reader. This method
00163 will collect characters until it sees a match to the
00164 character that the tokenizer used to switch to this state.
00165
00166 @return a quoted string token from a reader
00167 }
00168 function TZGenericSQLQuoteState.NextToken(Stream: TStream;
00169 FirstChar: Char; Tokenizer: TZTokenizer): TZToken;
00170 var
00171 ReadChar: Char;
00172 LastChar: Char;
00173 begin
00174 Result.Value := FirstChar;
00175 LastChar := #0;
00176 while Stream.Read(ReadChar, 1) > 0 do
00177 begin
00178 if (LastChar = FirstChar) and (ReadChar <> FirstChar) then
00179 begin
00180 Stream.Seek(-1, soFromCurrent);
00181 Break;
00182 end;
00183 Result.Value := Result.Value + ReadChar;
00184 if (LastChar = FirstChar) and (ReadChar = FirstChar) then
00185 LastChar := #0
00186 else LastChar := ReadChar;
00187 end;
00188
00189 if FirstChar = '"' then
00190 Result.TokenType := ttWord
00191 else Result.TokenType := ttQuoted;
00192 end;
00193
00194 {**
00195 Encodes a string value.
00196 @param Value a string value to be encoded.
00197 @param QuoteChar a string quote character.
00198 @returns an encoded string.
00199 }
00200 function TZGenericSQLQuoteState.EncodeString(const Value: string;
00201 QuoteChar: Char): string;
00202 begin
00203 if QuoteChar in [#39, '"', '`'] then
00204 Result := AnsiQuotedStr(Value, QuoteChar)
00205 else Result := Value;
00206 end;
00207
00208 {**
00209 Decodes a string value.
00210 @param Value a string value to be decoded.
00211 @param QuoteChar a string quote character.
00212 @returns an decoded string.
00213 }
00214 function TZGenericSQLQuoteState.DecodeString(const Value: string;
00215 QuoteChar: Char): string;
00216 var
00217 Len: Integer;
00218 begin
00219 Len := Length(Value);
00220 if (Len >= 2) and (QuoteChar in [#39, '"', '`'])
00221 and (Value[1] = QuoteChar) and (Value[Len] = QuoteChar) then
00222 begin
00223 if Len > 2 then
00224 Result := AnsiDequotedStr(Value, QuoteChar)
00225 else Result := '';
00226 end
00227 else Result := Value;
00228 end;
00229
00230 { TZGenericSQLTokenizer }
00231
00232 {**
00233 Constructs a tokenizer with a default state table (as
00234 described in the class comment).
00235 }
00236 constructor TZGenericSQLTokenizer.Create;
00237 begin
00238 NumberState := TZNumberState.Create;
00239 QuoteState := TZGenericSQLQuoteState.Create;
00240 WhitespaceState := TZWhitespaceState.Create;
00241 CommentState := TZCppCommentState.Create;
00242
00243 SymbolState := TZGenericSQLSymbolState.Create;
00244 WordState := TZGenericSQLWordState.Create;
00245
00246 SetCharacterState(#0, #255, SymbolState);
00247 SetCharacterState(#0, ' ', WhitespaceState);
00248
00249 SetCharacterState('a', 'z', WordState);
00250 SetCharacterState('A', 'Z', WordState);
00251 SetCharacterState(Chr($c0), Chr($ff), WordState);
00252 SetCharacterState('_', '_', WordState);
00253 SetCharacterState('$', '$', WordState);
00254
00255 SetCharacterState('0', '9', NumberState);
00256 SetCharacterState('.', '.', NumberState);
00257
00258 SetCharacterState('"', '"', QuoteState);
00259 SetCharacterState(#39, #39, QuoteState);
00260 SetCharacterState('`', '`', QuoteState);
00261
00262 SetCharacterState('/', '/', CommentState);
00263 end;
00264
00265 end.
00266