00001 {*********************************************************}
00002 { }
00003 { Zeos Database Objects }
00004 { String tokenizing classes for PostgreSQL }
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 ZPostgreSqlToken;
00055
00056 interface
00057
00058 {$I ZParseSql.inc}
00059
00060 uses
00061 Classes, ZTokenizer, ZGenericSqlToken, ZMySqlToken;
00062
00063 type
00064
00065 {** Implements a PostgreSQL-specific number state object. }
00066 TZPostgreSQLNumberState = class (TZNumberState)
00067 public
00068 function NextToken(Stream: TStream; FirstChar: Char;
00069 Tokenizer: TZTokenizer): TZToken; override;
00070 end;
00071
00072 {** Implements a PostgreSQL-specific quote string state object. }
00073 TZPostgreSQLQuoteState = class (TZMySQLQuoteState)
00074 public
00075 function NextToken(Stream: TStream; FirstChar: Char;
00076 Tokenizer: TZTokenizer): TZToken; override;
00077 end;
00078
00079 {**
00080 This state will either delegate to a comment-handling
00081 state, or return a token with just a slash in it.
00082 }
00083 TZPostgreSQLCommentState = class (TZCppCommentState)
00084 public
00085 function NextToken(Stream: TStream; FirstChar: Char;
00086 Tokenizer: TZTokenizer): TZToken; override;
00087 end;
00088
00089 {** Implements a symbol state object. }
00090 TZPostgreSQLSymbolState = class (TZSymbolState)
00091 public
00092 constructor Create;
00093 end;
00094
00095 {** Implements a word state object. }
00096 TZPostgreSQLWordState = class (TZGenericSQLWordState)
00097 public
00098 constructor Create;
00099 end;
00100
00101 {** Implements a default tokenizer object. }
00102 TZPostgreSQLTokenizer = class (TZTokenizer)
00103 public
00104 constructor Create;
00105 end;
00106
00107 implementation
00108
00109 { TZPostgreSQLNumberState }
00110
00111 {**
00112 Return a number token from a reader.
00113 @return a number token from a reader
00114 }
00115 function TZPostgreSQLNumberState.NextToken(Stream: TStream; FirstChar: Char;
00116 Tokenizer: TZTokenizer): TZToken;
00117 var
00118 TempChar: Char;
00119 FloatPoint: Boolean;
00120 LastChar: Char;
00121
00122 function ReadDecDigits: string;
00123 begin
00124 Result := '';
00125 LastChar := #0;
00126 while Stream.Read(LastChar, 1) > 0 do
00127 begin
00128 if LastChar in ['0'..'9'] then
00129 begin
00130 Result := Result + LastChar;
00131 LastChar := #0;
00132 end
00133 else
00134 begin
00135 Stream.Seek(-1, soFromCurrent);
00136 Break;
00137 end;
00138 end;
00139 end;
00140
00141 begin
00142 FloatPoint := FirstChar = '.';
00143 Result.Value := FirstChar;
00144 Result.TokenType := ttUnknown;
00145 LastChar := #0;
00146
00147 { Reads the first part of the number before decimal point }
00148 if not FloatPoint then
00149 begin
00150 Result.Value := Result.Value + ReadDecDigits;
00151 FloatPoint := LastChar = '.';
00152 if FloatPoint then
00153 begin
00154 Stream.Read(TempChar, 1);
00155 Result.Value := Result.Value + TempChar;
00156 end;
00157 end;
00158
00159 { Reads the second part of the number after decimal point }
00160 if FloatPoint then
00161 Result.Value := Result.Value + ReadDecDigits;
00162
00163 { Reads a power part of the number }
00164 if LastChar in ['e','E'] then
00165 begin
00166 Stream.Read(TempChar, 1);
00167 Result.Value := Result.Value + TempChar;
00168 FloatPoint := True;
00169
00170 Stream.Read(TempChar, 1);
00171 if TempChar in ['0'..'9','-','+'] then
00172 Result.Value := Result.Value + TempChar + ReadDecDigits
00173 else
00174 begin
00175 Result.Value := Copy(Result.Value, 1, Length(Result.Value) - 1);
00176 Stream.Seek(-2, soFromCurrent);
00177 end;
00178 end;
00179
00180 { Prepare the result }
00181 if Result.Value = '.' then
00182 begin
00183 if Tokenizer.SymbolState <> nil then
00184 Result := Tokenizer.SymbolState.NextToken(Stream, FirstChar, Tokenizer);
00185 end
00186 else
00187 begin
00188 if FloatPoint then
00189 Result.TokenType := ttFloat
00190 else Result.TokenType := ttInteger;
00191 end;
00192 end;
00193
00194 { TZPostgreSQLQuoteState }
00195
00196 {**
00197 Return a quoted string token from a reader. This method
00198 will collect characters until it sees a match to the
00199 character that the tokenizer used to switch to this state.
00200
00201 @return a quoted string token from a reader
00202 }
00203 function TZPostgreSQLQuoteState.NextToken(Stream: TStream;
00204 FirstChar: Char; Tokenizer: TZTokenizer): TZToken;
00205 begin
00206 Result := inherited NextToken(Stream, FirstChar, Tokenizer);
00207 if FirstChar = '"' then
00208 Result.TokenType := ttWord;
00209 end;
00210
00211 { TZPostgreSQLCommentState }
00212
00213 {**
00214 Gets a MySQL specific comments like -- or .
00215 @return either just a slash token, or the results of
00216 delegating to a comment-handling state
00217 }
00218 function TZPostgreSQLCommentState.NextToken(Stream: TStream;
00219 FirstChar: Char; Tokenizer: TZTokenizer): TZToken;
00220 var
00221 ReadChar: Char;
00222 ReadNum: Integer;
00223 begin
00224 Result.TokenType := ttUnknown;
00225 Result.Value := FirstChar;
00226
00227 if FirstChar = '-' then
00228 begin
00229 ReadNum := Stream.Read(ReadChar, 1);
00230 if (ReadNum > 0) and (ReadChar = '-') then
00231 begin
00232 Result.TokenType := ttComment;
00233 Result.Value := '--' + GetSingleLineComment(Stream);
00234 end
00235 else
00236 begin
00237 if ReadNum > 0 then
00238 Stream.Seek(-1, soFromCurrent);
00239 end;
00240 end
00241 else if FirstChar = '/' then
00242 begin
00243 ReadNum := Stream.Read(ReadChar, 1);
00244 if (ReadNum > 0) and (ReadChar = '*') then
00245 begin
00246 Result.TokenType := ttComment;
00247 Result.Value := '
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325