1 {*********************************************************}
3 { Zeos Database Objects }
4 { MySQL Database Connectivity Classes }
6 { Originally written by Sergey Seroukhov }
7 { and Sergey Merkuriev }
9 {*********************************************************}
11 {@********************************************************}
12 { Copyright (c) 1999-2012 Zeos Development Group }
14 { License Agreement: }
16 { This library is distributed in the hope that it will be }
17 { useful, but WITHOUT ANY WARRANTY; without even the }
18 { implied warranty of MERCHANTABILITY or FITNESS FOR }
19 { A PARTICULAR PURPOSE. See the GNU Lesser General }
20 { Public License for more details. }
22 { The source code of the ZEOS Libraries and packages are }
23 { distributed under the Library GNU General Public }
24 { License (see the file COPYING / COPYING.ZEOS) }
25 { with the following modification: }
26 { As a special exception, the copyright holders of this }
27 { library give you permission to link this library with }
28 { independent modules to produce an executable, }
29 { regardless of the license terms of these independent }
30 { modules, and to copy and distribute the resulting }
31 { executable under terms of your choice, provided that }
32 { you also meet, for each linked independent module, }
33 { the terms and conditions of the license of that module. }
34 { An independent module is a module which is not derived }
35 { from or based on this library. If you modify this }
36 { library, you may extend this exception to your version }
37 { of the library, but you are not obligated to do so. }
38 { If you do not wish to do so, delete this exception }
39 { statement from your version. }
42 { The project web site is located on: }
43 { http://zeos.firmos.at (FORUM) }
44 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
45 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
47 { http://www.sourceforge.net/projects/zeoslib. }
50 { Zeos Development Group. }
51 {********************************************************@}
60 Classes, {$IFDEF MSEgui}mclasses,{$ENDIF} SysUtils, StrUtils,
61 ZSysUtils, ZDbcIntfs, ZPlainMySqlDriver, ZPlainMySqlConstants, ZDbcLogging,
62 ZCompatibility, ZDbcResultSetMetadata;
68 {** Silent exception }
69 EZMySQLSilentException = class(EAbort);
72 Converts a MySQL native types into ZDBC SQL types.
73 @param PlainDriver a native MySQL plain driver.
74 @param FieldHandle a handler to field description structure.
75 @param FieldFlags field flags.
76 @return a SQL undepended type.
78 function ConvertMySQLHandleToSQLType(FieldHandle: PZMySQLField;
79 CtrlsCPType: TZControlsCodePage): TZSQLType;
82 Convert string mysql field type to SQLType
83 @param string field type value
84 @result the SQLType field type value
86 function ConvertMySQLTypeToSQLType(TypeName, TypeNameFull: string;
87 const CtrlsCPType: TZControlsCodePage): TZSQLType;
90 Checks for possible sql errors.
91 @param PlainDriver a MySQL plain driver.
92 @param Handle a MySQL connection handle.
93 @param LogCategory a logging category.
94 @param LogMessage a logging message.
96 procedure CheckMySQLError(PlainDriver: IZMySQLPlainDriver;
97 Handle: PZMySQLConnect; LogCategory: TZLoggingCategory; const LogMessage: string);
98 procedure CheckMySQLPrepStmtError(PlainDriver: IZMySQLPlainDriver;
99 Handle: PZMySQLConnect; LogCategory: TZLoggingCategory; const LogMessage: string);
100 procedure EnterSilentMySQLError;
101 procedure LeaveSilentMySQLError;
104 Decodes a MySQL Version Value encoded with format:
105 (major_version * 10,000) + (minor_version * 100) + sub_version
106 into separated major, minor and subversion values
107 @param MySQLVersion an integer containing the MySQL Full Version to decode.
108 @param MajorVersion an integer containing the Major Version decoded.
109 @param MinorVersion an integer containing the Minor Version decoded.
110 @param SubVersion an integer contaning the Sub Version (revision) decoded.
112 procedure DecodeMySQLVersioning(const MySQLVersion: Integer;
113 out MajorVersion: Integer; out MinorVersion: Integer;
114 out SubVersion: Integer);
117 Encodes major, minor and subversion (revision) values in MySQL format:
118 (major_version * 10,000) + (minor_version * 100) + sub_version
119 For example, 4.1.12 is returned as 40112.
120 @param MajorVersion an integer containing the Major Version.
121 @param MinorVersion an integer containing the Minor Version.
122 @param SubVersion an integer containing the Sub Version (revision).
123 @return an integer containing the full version.
125 function EncodeMySQLVersioning(const MajorVersion: Integer;
126 const MinorVersion: Integer; const SubVersion: Integer): Integer;
129 Decodes a MySQL Version Value and Encodes it to a Zeos SQL Version format:
130 (major_version * 1,000,000) + (minor_version * 1,000) + sub_version
131 into separated major, minor and subversion values
132 @param MySQLVersion an integer containing the Full Version to decode.
133 @return Encoded Zeos SQL Version Value.
135 function ConvertMySQLVersionToSQLVersion( const MySQLVersion: Integer ): Integer;
137 function getMySQLFieldSize (field_type: TMysqlFieldTypes; field_size: LongWord): LongWord;
140 Returns a valid TZColumnInfo from a FieldHandle
141 @param PlainDriver the MySQL PlainDriver interface
142 @param FieldHandle the handle of the fetched field
143 @returns a new TZColumnInfo
145 function GetMySQLColumnInfoFromFieldHandle(PlainDriver: IZMySQLPlainDriver;
146 FieldHandle: PZMySQLField; ConSettings: PZConSettings;
147 bUseResult:boolean): TZColumnInfo;
149 procedure ConvertMySQLColumnInfoFromString(const TypeInfo: String;
150 ConSettings: PZConSettings; out TypeName, TypeInfoSecond: String;
151 out FieldType: TZSQLType; out ColumnSize: Integer; out Precision: Integer);
153 function ReverseWordBytes(Src: Pointer): Word;
154 function ReverseLongWordBytes(Src: Pointer; Len: Byte): LongWord;
155 function ReverseQuadWordBytes(Src: Pointer; Len: Byte): UInt64;
159 uses ZMessages, Math, ZDbcUtils;
162 SilentMySQLError: Integer;
164 procedure EnterSilentMySQLError;
166 Inc(SilentMySQLError);
169 procedure LeaveSilentMySQLError;
171 Dec(SilentMySQLError);
175 Converts a MySQL native types into ZDBC SQL types.
176 @param PlainDriver a native MySQL plain driver.
177 @param FieldHandle a handler to field description structure.
178 @param FieldFlags a field flags.
179 @return a SQL undepended type.
181 function ConvertMySQLHandleToSQLType(FieldHandle: PZMySQLField;
182 CtrlsCPType: TZControlsCodePage): TZSQLType;
184 case PMYSQL_FIELD(FieldHandle)^._type of
186 if PMYSQL_FIELD(FieldHandle)^.flags and UNSIGNED_FLAG = 0 then
190 FIELD_TYPE_YEAR: //word value
193 if PMYSQL_FIELD(FieldHandle)^.flags and UNSIGNED_FLAG = 0 then
197 FIELD_TYPE_INT24, FIELD_TYPE_LONG:
198 if PMYSQL_FIELD(FieldHandle)^.flags and UNSIGNED_FLAG = 0 then
203 if PMYSQL_FIELD(FieldHandle)^.flags and UNSIGNED_FLAG = 0 then
206 Result := stBigDecimal;
209 FIELD_TYPE_DECIMAL, FIELD_TYPE_NEWDECIMAL: {ADDED FIELD_TYPE_NEWDECIMAL by fduenas 20-06-2006}
210 if PMYSQL_FIELD(FieldHandle)^.decimals = 0 then
211 if PMYSQL_FIELD(FieldHandle)^.length < 11 then
219 FIELD_TYPE_DATE, FIELD_TYPE_NEWDATE:
223 FIELD_TYPE_DATETIME, FIELD_TYPE_TIMESTAMP:
224 Result := stTimestamp;
225 FIELD_TYPE_TINY_BLOB, FIELD_TYPE_MEDIUM_BLOB,
226 FIELD_TYPE_LONG_BLOB, FIELD_TYPE_BLOB:
227 if (PMYSQL_FIELD(FieldHandle)^.flags and BINARY_FLAG) = 0 then
228 If ( CtrlsCPType = cCP_UTF16) then
229 Result := stUnicodeStream
231 Result := stAsciiStream
233 Result := stBinaryStream;
234 FIELD_TYPE_BIT: //http://dev.mysql.com/doc/refman/5.1/en/bit-type.html
235 case PMYSQL_FIELD(FieldHandle)^.length of
236 1..8: Result := stByte;
237 9..16: Result := stShort;
238 17..32: Result := stInteger;
239 else Result := stLong;
242 FIELD_TYPE_VAR_STRING,
244 if (PMYSQL_FIELD(FieldHandle)^.flags and BINARY_FLAG) = 0 then
245 if ( CtrlsCPType = cCP_UTF16) then
246 Result := stUnicodeString
256 // Example: SELECT NULL FROM DUAL
259 // Todo: Would be nice to show as WKT.
260 Result := stBinaryStream;
262 raise Exception.Create('Unknown MySQL data type!');
267 Convert string mysql field type to SQLType
268 @param string field type value
269 @result the SQLType field type value
271 function ConvertMySQLTypeToSQLType(TypeName, TypeNameFull: string;
272 const CtrlsCPType: TZControlsCodePage): TZSQLType;
274 GeoTypes: array[0..7] of string = (
275 'POINT','LINESTRING','POLYGON','GEOMETRY',
276 'MULTIPOINT','MULTILINESTRING','MULTIPOLYGON','GEOMETRYCOLLECTION'
280 Posi, Len, i: Integer;
283 TypeName := UpperCase(TypeName);
284 TypeNameFull := UpperCase(TypeNameFull);
287 Posi := FirstDelimiter(' ', TypeName);
289 TypeName := Copy(TypeName, 1, Posi - 1);
292 Posi := FirstDelimiter(' ', TypeNameFull);
294 Spec := Copy(TypeNameFull, Posi + 1, Length(TypeNameFull)-Posi);
296 IsUnsigned := Pos('UNSIGNED', Spec) > 0;
298 if TypeName = 'TINYINT' then
300 if not IsUnsigned then
305 else if TypeName = 'YEAR' then
307 else if TypeName = 'SMALLINT' then
314 else if TypeName = 'MEDIUMINT' then
316 else if (TypeName = 'INT') or (TypeName = 'INTEGER') then
323 else if TypeName = 'BIGINT' then
325 else if TypeName = 'INT24' then
327 else if TypeName = 'REAL' then
334 else if TypeName = 'FLOAT' then
336 // if IsUnsigned then
338 // else Result := stFloat;
340 else if TypeName = 'DECIMAL' then
342 if EndsWith(TypeNameFull, ',0)') then
344 Len := StrToInt(Copy(TypeNameFull, 9, Length(TypeNameFull) - 11));
353 else if TypeName = 'DOUBLE' then
355 else if TypeName = 'CHAR' then
357 else if TypeName = 'VARCHAR' then
359 else if TypeName = 'VARBINARY' then
361 else if TypeName = 'BINARY' then
363 else if TypeName = 'DATE' then
365 else if TypeName = 'TIME' then
367 else if TypeName = 'TIMESTAMP' then
368 Result := stTimestamp
369 else if TypeName = 'DATETIME' then
370 Result := stTimestamp
371 else if TypeName = 'TINYBLOB' then
372 Result := stBinaryStream
373 else if TypeName = 'BLOB' then
374 Result := stBinaryStream
375 else if TypeName = 'MEDIUMBLOB' then
376 Result := stBinaryStream
377 else if TypeName = 'LONGBLOB' then
378 Result := stBinaryStream
379 else if TypeName = 'TINYTEXT' then
380 Result := stAsciiStream
381 else if TypeName = 'TEXT' then
382 Result := stAsciiStream
383 else if TypeName = 'MEDIUMTEXT' then
384 Result := stAsciiStream
385 else if TypeName = 'LONGTEXT' then
386 Result := stAsciiStream
387 else if TypeName = 'ENUM' then
389 if (TypeNameFull = 'ENUM(''Y'',''N'')')
390 or (TypeNameFull = 'ENUM(''N'',''Y'')') then
395 else if TypeName = 'SET' then
397 else if TypeName = 'BIT' then //see: http://dev.mysql.com/doc/refman/5.1/en/bit-type.html
399 Posi := Pos('(', TypeNameFull);
400 if (Posi > 0) and EndsWith(TypeNameFull, ')') then
402 Len := StrToIntDef(Copy(TypeNameFull, Posi+1, Length(TypeNameFull)-Posi-1), 1);
404 1..8: Result := stByte;
405 9..16: Result := stShort;
406 17..32: Result := stInteger;
407 else Result := stLong;
413 for i := 0 to Length(GeoTypes) - 1 do
414 if GeoTypes[i] = TypeName then
415 Result := stBinaryStream;
417 if ( CtrlsCPType = cCP_UTF16) then
419 stString: Result := stUnicodeString;
420 stAsciiStream: Result := stUnicodeStream;
423 if Result = stUnknown then
424 raise Exception.Create('Unknown MySQL data type!');
428 Checks for possible sql errors.
429 @param PlainDriver a MySQL plain driver.
430 @param Handle a MySQL connection handle.
431 @param LogCategory a logging category.
432 @param LogMessage a logging message.
434 procedure CheckMySQLError(PlainDriver: IZMySQLPlainDriver;
435 Handle: PZMySQLConnect; LogCategory: TZLoggingCategory; const LogMessage: string);
437 ErrorMessage: string;
440 ErrorMessage := Trim(String(PlainDriver.GetLastError(Handle)));
441 ErrorCode := PlainDriver.GetLastErrorCode(Handle);
442 if (ErrorCode <> 0) and (ErrorMessage <> '') then
444 if SilentMySQLError > 0 then
445 raise EZMySQLSilentException.CreateFmt(SSQLError1, [ErrorMessage]);
447 DriverManager.LogError(LogCategory, PlainDriver.GetProtocol, LogMessage,
448 ErrorCode, ErrorMessage);
449 raise EZSQLException.CreateWithCode(ErrorCode,
450 Format(SSQLError1, [ErrorMessage]));
454 procedure CheckMySQLPrepStmtError(PlainDriver: IZMySQLPlainDriver;
455 Handle: PZMySQLConnect; LogCategory: TZLoggingCategory; const LogMessage: string);
457 ErrorMessage: string;
460 ErrorMessage := Trim(String(PlainDriver.GetLastPreparedError(Handle)));
461 ErrorCode := PlainDriver.GetLastPreparedErrorCode(Handle);
462 if (ErrorCode <> 0) and (ErrorMessage <> '') then
464 if SilentMySQLError > 0 then
465 raise EZMySQLSilentException.CreateFmt(SSQLError1, [ErrorMessage]);
467 DriverManager.LogError(LogCategory,PlainDriver.GetProtocol,LogMessage,ErrorCode, ErrorMessage);
468 raise EZSQLException.CreateWithCode(ErrorCode,
469 Format(SSQLError1, [ErrorMessage]));
474 Decodes a MySQL Version Value encoded with format:
475 (major_version * 10,000) + (minor_version * 100) + sub_version
476 into separated major, minor and subversion values
477 @param MySQLVersion an integer containing the MySQL Full Version to decode.
478 @param MajorVersion an integer containing the Major Version decoded.
479 @param MinorVersion an integer containing the Minor Version decoded.
480 @param SubVersion an integer contaning the Sub Version (revision) decoded.
482 procedure DecodeMySQLVersioning(const MySQLVersion: Integer;
483 out MajorVersion: Integer; out MinorVersion: Integer;
484 out SubVersion: Integer);
486 MajorVersion := MySQLVersion div 10000;
487 MinorVersion := (MySQLVersion - (MajorVersion * 10000)) div 100;
488 SubVersion := MySQLVersion-(MajorVersion*10000)-(MinorVersion*100);
492 Encodes major, minor and subversion (revision) values in MySQL format:
493 (major_version * 10,000) + (minor_version * 100) + sub_version
494 For example, 4.1.12 is returned as 40112.
495 @param MajorVersion an integer containing the Major Version.
496 @param MinorVersion an integer containing the Minor Version.
497 @param SubVersion an integer containing the Sub Version (revision).
498 @return an integer containing the full version.
500 function EncodeMySQLVersioning(const MajorVersion: Integer;
501 const MinorVersion: Integer; const SubVersion: Integer): Integer;
503 Result := (MajorVersion * 10000) + (MinorVersion * 100) + SubVersion;
507 Decodes a MySQL Version Value and Encodes it to a Zeos SQL Version format:
508 (major_version * 1,000,000) + (minor_version * 1,000) + sub_version
509 into separated major, minor and subversion values
510 So it transforms a version in format XYYZZ to XYYYZZZ where:
514 @param MySQLVersion an integer containing the Full MySQL Version to decode.
515 @return Encoded Zeos SQL Version Value.
517 function ConvertMySQLVersionToSQLVersion( const MySQLVersion: Integer ): integer;
519 MajorVersion, MinorVersion, SubVersion: Integer;
521 DecodeMySQLVersioning(MySQLVersion,MajorVersion,MinorVersion,SubVersion);
522 Result := EncodeSQLVersioning(MajorVersion,MinorVersion,SubVersion);
525 function getMySQLFieldSize (field_type: TMysqlFieldTypes; field_size: LongWord): LongWord;
529 FieldSize := field_size;
532 FIELD_TYPE_TINY: Result := 1;
533 FIELD_TYPE_SHORT: Result := 2;
534 FIELD_TYPE_LONG: Result := 4;
535 FIELD_TYPE_LONGLONG: Result := 8;
536 FIELD_TYPE_FLOAT: Result := 4;
537 FIELD_TYPE_DOUBLE: Result := 8;
538 FIELD_TYPE_DATE: Result := sizeOf(MYSQL_TIME);
539 FIELD_TYPE_TIME: Result := sizeOf(MYSQL_TIME);
540 FIELD_TYPE_DATETIME: Result := sizeOf(MYSQL_TIME);
541 FIELD_TYPE_TINY_BLOB: Result := FieldSize; //stBytes
542 FIELD_TYPE_BLOB: Result := FieldSize;
543 FIELD_TYPE_STRING: Result := FieldSize;
545 Result := 255; {unknown ??}
550 Returns a valid TZColumnInfo from a FieldHandle
551 @param PlainDriver the MySQL PlainDriver interface
552 @param FieldHandle the handle of the fetched field
553 @returns a new TZColumnInfo
555 function GetMySQLColumnInfoFromFieldHandle(PlainDriver: IZMySQLPlainDriver;
556 FieldHandle: PZMySQLField;ConSettings: PZConSettings; bUseResult:boolean): TZColumnInfo;
561 if Assigned(FieldHandle) then
563 Result := TZColumnInfo.Create;
564 FieldFlags := PlainDriver.GetFieldFlags(FieldHandle);
566 Result.ColumnLabel := PlainDriver.ZDbcString(PlainDriver.GetFieldName(FieldHandle), ConSettings);
567 Result.ColumnName := PlainDriver.ZDbcString(PlainDriver.GetFieldOrigName(FieldHandle), ConSettings);
568 Result.TableName := PlainDriver.ZDbcString(PlainDriver.GetFieldTable(FieldHandle), ConSettings);
569 Result.ReadOnly := (PlainDriver.GetFieldTable(FieldHandle) = '');
570 Result.Writable := not Result.ReadOnly;
571 Result.ColumnType := ConvertMySQLHandleToSQLType(FieldHandle, ConSettings.CPType);
572 FieldLength := PMYSQL_FIELD(FieldHandle)^.length;
573 //EgonHugeist: arrange the MBCS field DisplayWidth to a proper count of Chars
574 if Result.ColumnType in [stString, stUnicodeString] then
575 case PMYSQL_FIELD(FieldHandle)^.charsetnr of
577 95, 96, {cp932 japanese}
582 35, 90, 128..151: {ucs2}
584 Result.ColumnDisplaySize := (FieldLength div 4);
585 Result.Precision := GetFieldSize(Result.ColumnType, ConSettings,
586 Result.ColumnDisplaySize, 2, nil);
588 33, 83, 192..215, { utf8 }
592 Result.ColumnDisplaySize := (FieldLength div 3);
593 Result.Precision := GetFieldSize(Result.ColumnType,
594 ConSettings, Result.ColumnDisplaySize, 3, nil);
596 54, 55, 101..124, {utf16}
598 60, 61, 160..183, {utf32}
599 45, 46, 224..247: {utf8mb4}
601 Result.ColumnDisplaySize := (FieldLength div 4);
602 Result.Precision := GetFieldSize(Result.ColumnType,
603 ConSettings, Result.ColumnDisplaySize, 4, nil);
605 else //1-Byte charsets
607 Result.ColumnDisplaySize := FieldLength;
608 Result.Precision := GetFieldSize(Result.ColumnType,
609 ConSettings, Result.ColumnDisplaySize, 1, nil);
613 Result.Precision := min(MaxBlobSize,FieldLength);
615 if PMYSQL_FIELD(FieldHandle)^._type in [FIELD_TYPE_BLOB, FIELD_TYPE_MEDIUM_BLOB,
616 FIELD_TYPE_LONG_BLOB,FIELD_TYPE_STRING, FIELD_TYPE_VAR_STRING] then
618 if bUseResult then //PMYSQL_FIELD(Field)^.max_length not valid
619 Result.MaxLenghtBytes:=Result.Precision
621 Result.MaxLenghtBytes:=PlainDriver.GetFieldMaxLength(FieldHandle);
624 Result.MaxLenghtBytes:=FieldLength;
625 Result.Scale := PlainDriver.GetFieldDecimals(FieldHandle);
626 if (AUTO_INCREMENT_FLAG and FieldFlags <> 0)
627 or (TIMESTAMP_FLAG and FieldFlags <> 0) then
628 Result.AutoIncrement := True;
629 if UNSIGNED_FLAG and FieldFlags <> 0 then
630 Result.Signed := False
632 Result.Signed := True;
633 if NOT_NULL_FLAG and FieldFlags <> 0 then
634 Result.Nullable := ntNoNulls
636 Result.Nullable := ntNullable;
637 // Properties not set via query results here will be fetched from table metadata.
643 procedure ConvertMySQLColumnInfoFromString(const TypeInfo: String;
644 ConSettings: PZConSettings; out TypeName, TypeInfoSecond:
645 String; out FieldType: TZSQLType; out ColumnSize: Integer; out Precision: Integer);
647 TypeInfoList: TStrings;
648 TypeInfoFirst: String;
651 TypeInfoList := TStringList.Create;
653 TypeInfoSecond := '';
657 if StrPos(PChar(TypeInfo), '(') <> nil then
659 PutSplitString(TypeInfoList, TypeInfo, '()');
660 TypeInfoFirst := TypeInfoList.Strings[0];
661 TypeInfoSecond := TypeInfoList.Strings[1];
664 TypeInfoFirst := TypeInfo;
666 TypeInfoFirst := LowerCase(TypeInfoFirst);
667 TypeName := TypeInfoFirst;
669 FieldType := ConvertMySQLTypeToSQLType(TypeInfoFirst, TypeInfo, Consettings.CPType);
670 { the column type is ENUM}
671 if TypeInfoFirst = 'enum' then
673 PutSplitString(TypeInfoList, TypeInfoSecond, ',');
674 for J := 0 to TypeInfoList.Count-1 do
675 ColumnSize := Max(ColumnSize, Length(TypeInfoList.Strings[J]));
678 { the column type is decimal }
679 if ( Pos(',', TypeInfoSecond) > 0 ) and not ( TypeInfoFirst = 'set' ) then
681 TempPos := FirstDelimiter(',', TypeInfoSecond);
682 ColumnSize := StrToIntDef(Copy(TypeInfoSecond, 1, TempPos - 1), 0);
683 Precision := StrToIntDef(Copy(TypeInfoSecond, TempPos + 1,
684 Length(TypeInfoSecond) - TempPos), 0);
688 { the column type is other }
689 if (TypeInfoSecond <> '') and not (TypeInfoFirst = 'set') then
690 ColumnSize := StrToIntDef(TypeInfoSecond, 0)
691 else if TypeInfoFirst = 'tinyint' then
693 else if TypeInfoFirst = 'smallint' then
695 else if TypeInfoFirst = 'mediumint' then
697 else if TypeInfoFirst = 'int' then
699 else if TypeInfoFirst = 'integer' then
701 else if TypeInfoFirst = 'bigint' then
703 else if TypeInfoFirst = 'int24' then
705 else if TypeInfoFirst = 'real' then
707 else if TypeInfoFirst = 'float' then
709 else if TypeInfoFirst = 'decimal' then
711 else if TypeInfoFirst = 'numeric' then
713 else if TypeInfoFirst = 'double' then
715 else if TypeInfoFirst = 'char' then
717 else if TypeInfoFirst = 'varchar' then
719 else if TypeInfoFirst = 'date' then
721 else if TypeInfoFirst = 'time' then
723 else if TypeInfoFirst = 'timestamp' then
725 else if TypeInfoFirst = 'datetime' then
727 else if TypeInfoFirst = 'tinyblob' then
729 else if TypeInfoFirst = 'blob' then
731 else if TypeInfoFirst = 'mediumblob' then
732 ColumnSize := 16277215//may be 65535
733 else if TypeInfoFirst = 'longblob' then
734 ColumnSize := High(Integer)//2147483657//may be 65535
735 else if TypeInfoFirst = 'tinytext' then
737 else if TypeInfoFirst = 'text' then
739 else if TypeInfoFirst = 'mediumtext' then
740 ColumnSize := 16277215 //may be 65535
741 else if TypeInfoFirst = 'enum' then
743 else if TypeInfoFirst = 'set' then
746 if FieldType in [stString, stUnicodeString] then
747 ColumnSize := GetFieldSize(FieldType, consettings, ColumnSize,
748 ConSettings.ClientCodePage.CharWidth, nil);
750 FreeAndNil(TypeInfoList);
753 procedure ReverseBytes(const Src, Dest: Pointer; Len: Byte);
758 P := PAnsiChar(Src)+Len;
759 for b := Len downto 0 do
760 (PAnsiChar(Dest)+B)^ := (P-B)^;
763 function ReverseWordBytes(Src: Pointer): Word;
765 (PAnsiChar(@Result)+1)^ := PAnsiChar(Src)^;
766 PAnsiChar(@Result)^ := (PAnsiChar(Src)+1)^;
769 function ReverseLongWordBytes(Src: Pointer; Len: Byte): LongWord;
772 ReverseBytes(Src, @Result, Len);
775 function ReverseQuadWordBytes(Src: Pointer; Len: Byte): UInt64;
778 ReverseBytes(Src, @Result, Len);