浏览代码

* Change to use new charset and charwidth

git-svn-id: trunk@34102 -
michael 9 年之前
父节点
当前提交
d40bf3684b

+ 60 - 70
packages/fcl-db/src/sqldb/interbase/ibconnection.pp

@@ -75,7 +75,7 @@ type
 
     // conversion methods
     procedure TranslateFldType(SQLType, SQLSubType, SQLLen, SQLScale : integer;
-      var TrType : TFieldType; var TrLen : word);
+      out TrType : TFieldType; out TrLen, TrPrec : word);
     procedure GetDateTime(CurrBuff, Buffer : pointer; AType : integer);
     procedure SetDateTime(CurrBuff: pointer; PTime : TDateTime; AType : integer);
     procedure GetFloat(CurrBuff, Buffer : pointer; Size : Byte);
@@ -99,7 +99,7 @@ type
     procedure UnPrepareStatement(cursor : TSQLCursor); override;
     procedure FreeFldBuffers(cursor : TSQLCursor); override;
     procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction; AParams : TParams); override;
-    procedure AddFieldDefs(cursor: TSQLCursor;FieldDefs : TfieldDefs); override;
+    procedure AddFieldDefs(cursor: TSQLCursor;FieldDefs : TFieldDefs); override;
     function Fetch(cursor : TSQLCursor) : boolean; override;
     function LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; override;
     function GetTransactionHandle(trans : TSQLHandle): pointer; override;
@@ -266,7 +266,7 @@ function TIBConnection.StartDBTransaction(trans: TSQLHandle; AParams: string
 
 Var
   DBHandle:pointer;
-  I,T :integer;
+  I : integer;
   S :string;
   tpbv,version : ansichar;
   prVal :String;
@@ -662,17 +662,25 @@ begin
 end;
 
 procedure TIBConnection.TranslateFldType(SQLType, SQLSubType, SQLLen, SQLScale : integer;
-           var TrType : TFieldType; var TrLen : word);
+           out TrType : TFieldType; out TrLen, TrPrec : word);
 begin
   TrLen := 0;
+  TrPrec := 0;
   if SQLScale < 0 then
-    begin
+  begin
     TrLen := abs(SQLScale);
     if (TrLen <= MaxBCDScale) then //Note: NUMERIC(18,3) or (17,2) must be mapped to ftFmtBCD, but we do not know Precision
       TrType := ftBCD
     else
       TrType := ftFMTBcd;
-    end
+    case (SQLType and not 1) of
+      SQL_SHORT : TrPrec := 4;
+      SQL_LONG  : TrPrec := 9;
+      SQL_DOUBLE,
+      SQL_INT64 : TrPrec := 18;
+      else        TrPrec := SQLLen;
+    end;
+  end
   else case (SQLType and not 1) of
     SQL_VARYING :
       begin
@@ -930,12 +938,12 @@ begin
 end;
 
 
-procedure TIBConnection.AddFieldDefs(cursor: TSQLCursor;FieldDefs : TfieldDefs);
+procedure TIBConnection.AddFieldDefs(cursor: TSQLCursor;FieldDefs : TFieldDefs);
 var
   x         : integer;
-  TransLen  : word;
+  TransLen,
+  TransPrec : word;
   TransType : TFieldType;
-  FD        : TFieldDef;
 
 begin
   {$push}
@@ -946,20 +954,11 @@ begin
     for x := 0 to SQLDA^.SQLD - 1 do
       begin
       TranslateFldType(SQLDA^.SQLVar[x].SQLType, SQLDA^.SQLVar[x].sqlsubtype, SQLDA^.SQLVar[x].SQLLen, SQLDA^.SQLVar[x].SQLScale,
-        TransType, TransLen);
-
-      FD := FieldDefs.Add(FieldDefs.MakeNameUnique(SQLDA^.SQLVar[x].AliasName), TransType,
-         TransLen, (SQLDA^.SQLVar[x].sqltype and 1)=0, (x + 1));
-      if TransType in [ftBCD, ftFmtBCD] then
-        case (SQLDA^.SQLVar[x].sqltype and not 1) of
-          SQL_SHORT : FD.precision := 4;
-          SQL_LONG  : FD.precision := 9;
-          SQL_DOUBLE,
-          SQL_INT64 : FD.precision := 18;
-          else FD.precision := SQLDA^.SQLVar[x].SQLLen;
-        end;
-//      FD.DisplayName := SQLDA^.SQLVar[x].AliasName;
-      FieldBinding[FD.FieldNo-1] := x;
+        TransType, TransLen, TransPrec);
+
+      AddFieldDef(FieldDefs, x+1, SQLDA^.SQLVar[x].AliasName, TransType, TransLen, TransPrec, True, (SQLDA^.SQLVar[x].sqltype and 1)=0, False);
+
+      FieldBinding[x] := x;
       end;
     end;
   {$pop}
@@ -1009,13 +1008,10 @@ end;
 
 procedure TIBConnection.SetParameters(cursor : TSQLCursor; aTransation : TSQLTransaction; AParams : TParams);
 
-var ParNr,SQLVarNr : integer;
-    s               : string;
-    i               : integer;
-    si              : smallint;
-    li              : LargeInt;
-    currbuff        : pchar;
-    w               : word;
+var SQLVarNr : integer;
+    AParam   : TParam;
+    s        : rawbytestring;
+    i        : integer;
 
     TransactionHandle : pointer;
     blobId            : ISC_QUAD;
@@ -1035,7 +1031,7 @@ var ParNr,SQLVarNr : integer;
       if isc_create_blob(@FStatus[0], @FSQLDatabaseHandle, @TransactionHandle, @blobHandle, @blobId) <> 0 then
        CheckError('TIBConnection.CreateBlobStream', FStatus);
 
-      s := AParams[ParNr].AsString;
+      s := GetAsString(AParam);
       BlobSize := length(s);
 
       BlobBytesWritten := 0;
@@ -1059,25 +1055,22 @@ var ParNr,SQLVarNr : integer;
       {$pop}
   end;
 
-Const
-  DateF = 'yyyy-mm-dd';
-  TimeF = 'hh:nn:ss';
-  DateTimeF = DateF+' '+TimeF;
-
 var
-  // This should be a pointer, because the ORIGINAL variables must
-  // be modified.
-  VSQLVar: ^XSQLVAR;
-  P: TParam;
-  ft : TFieldType;
+  // This should be a pointer, because the ORIGINAL variables must be modified.
+  VSQLVar  : ^XSQLVAR;
+  si       : smallint;
+  li       : LargeInt;
+  CurrBuff : pchar;
+  w        : word;
+
 begin
   {$push}
   {$R-}
   with cursor as TIBCursor do for SQLVarNr := 0 to High(ParamBinding){AParams.count-1} do
     begin
-    ParNr := ParamBinding[SQLVarNr];
+    AParam := AParams[ParamBinding[SQLVarNr]];
     VSQLVar := @in_sqlda^.SQLvar[SQLVarNr];
-    if AParams[ParNr].IsNull then
+    if AParam.IsNull then
       VSQLVar^.SQLInd^ := -1
     else
       begin
@@ -1087,50 +1080,47 @@ begin
         SQL_SHORT, SQL_BOOLEAN_INTERBASE :
           begin
             if VSQLVar^.sqlscale = 0 then
-              si := AParams[ParNr].AsSmallint
+              si := AParam.AsSmallint
             else
-              si := Round(AParams[ParNr].AsCurrency * IntPower10(-VSQLVar^.sqlscale));
+              si := Round(AParam.AsCurrency * IntPower10(-VSQLVar^.sqlscale));
             i := si;
             Move(i, VSQLVar^.SQLData^, VSQLVar^.SQLLen);
           end;
         SQL_LONG :
           begin
             if VSQLVar^.sqlscale = 0 then
-              i := AParams[ParNr].AsInteger
+              i := AParam.AsInteger
             else
-              i := Round(AParams[ParNr].AsFloat * IntPower10(-VSQLVar^.sqlscale)); //*any number of digits
+              i := Round(AParam.AsFloat * IntPower10(-VSQLVar^.sqlscale)); //*any number of digits
             Move(i, VSQLVar^.SQLData^, VSQLVar^.SQLLen);
           end;
         SQL_INT64:
           begin
             if VSQLVar^.sqlscale = 0 then
-              li := AParams[ParNr].AsLargeInt
-            else if AParams[ParNr].DataType = ftFMTBcd then
-              li := AParams[ParNr].AsFMTBCD * IntPower10(-VSQLVar^.sqlscale)
+              li := AParam.AsLargeInt
+            else if AParam.DataType = ftFMTBcd then
+              li := AParam.AsFMTBCD * IntPower10(-VSQLVar^.sqlscale)
             else
-              li := Round(AParams[ParNr].AsCurrency * IntPower10(-VSQLVar^.sqlscale));
+              li := Round(AParam.AsCurrency * IntPower10(-VSQLVar^.sqlscale));
             Move(li, VSQLVar^.SQLData^, VSQLVar^.SQLLen);
           end;
         SQL_DOUBLE, SQL_FLOAT:
-          SetFloat(VSQLVar^.SQLData, AParams[ParNr].AsFloat, VSQLVar^.SQLLen);
+          SetFloat(VSQLVar^.SQLData, AParam.AsFloat, VSQLVar^.SQLLen);
         SQL_BLOB :
           SetBlobParam;
         SQL_VARYING, SQL_TEXT :
           begin
-          P:=AParams[ParNr];
-          ft:=P.DataType;
-          if Not (ft in [ftDate,ftTime,ftDateTime,ftTimeStamp]) then
-            S:=P.AsString
-          else
-            begin
-            Case ft of
-              ftDate : S:=DateF;
-              ftTime : S:=TimeF;
-              ftDateTime,
-              ftTimeStamp : S:=DateTimeF;
-            end;
-            S:=FormatDateTime(S,P.AsDateTime);
-            end;
+          Case AParam.DataType of
+            ftDate :
+              s := FormatDateTime('yyyy-mm-dd', AParam.AsDateTime);
+            ftTime :
+              s := FormatDateTime('hh":"nn":"ss', AParam.AsDateTime);
+            ftDateTime,
+            ftTimeStamp :
+              s := FormatDateTime('yyyy-mm-dd hh":"nn":"ss', AParam.AsDateTime);
+            else
+              s := GetAsString(AParam);
+          end;
           w := length(s); // a word is enough, since the max-length of a string in interbase is 32k
           if ((VSQLVar^.SQLType and not 1) = SQL_VARYING) then
             begin
@@ -1138,7 +1128,7 @@ begin
             ReAllocMem(VSQLVar^.SQLData, VSQLVar^.SQLLen+2);
             CurrBuff := VSQLVar^.SQLData;
             move(w,CurrBuff^,sizeof(w));
-            inc(CurrBuff,2);
+            inc(CurrBuff,sizeof(w));
             end
           else
             begin
@@ -1152,11 +1142,11 @@ begin
           Move(s[1], CurrBuff^, w);
           end;
         SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TIMESTAMP :
-          SetDateTime(VSQLVar^.SQLData, AParams[ParNr].AsDateTime, VSQLVar^.SQLType);
+          SetDateTime(VSQLVar^.SQLData, AParam.AsDateTime, VSQLVar^.SQLType);
         SQL_BOOLEAN_FIREBIRD:
-          PByte(VSQLVar^.SQLData)^ := Byte(AParams[ParNr].AsBoolean);
+          PByte(VSQLVar^.SQLData)^ := Byte(AParam.AsBoolean);
       else
-        DatabaseErrorFmt(SUnsupportedParameter,[Fieldtypenames[AParams[ParNr].DataType]],self);
+        DatabaseErrorFmt(SUnsupportedParameter,[FieldTypeNames[AParam.DataType]],self);
       end {case}
       end;
     end;

+ 26 - 22
packages/fcl-db/src/sqldb/mysql/mysqlconn.inc

@@ -110,6 +110,9 @@ Type
     FHostInfo: String;
     FServerInfo: String;
     FMySQL : PMySQL;
+{$IFDEF MYSQL50_UP}
+    FConnectionCharsetInfo: MY_CHARSET_INFO;
+{$ENDIF}
     function GetClientInfo: string;
     function GetServerStatus: String;
     procedure ConnectMySQL(var HMySQL: PMySQL);
@@ -125,8 +128,8 @@ Type
     procedure DoInternalConnect; override;
     procedure DoInternalDisconnect; override;
     function GetHandle : pointer; override;
+    function GetConnectionCharSet: string; override;
 
-    function GetAsSQLText(Field : TField) : string; overload; override;
     function GetAsSQLText(Param : TParam) : string; overload; override;
 
     Function AllocateCursorHandle : TSQLCursor; override;
@@ -412,26 +415,17 @@ begin
         MySQLError(HMySQL,SErrExecuting,Self);
 end;
 
-function TConnectionName.GetAsSQLText(Field : TField) : string;
-
-begin
-  if (not assigned(Field)) or Field.IsNull then
-    Result := 'Null'
-  else if Field.DataType = ftString then
-    Result := '''' + EscapeString(Field.AsString) + ''''
-  else
-    Result := inherited GetAsSqlText(Field);
-end;
-
 function TConnectionName.GetAsSQLText(Param: TParam) : string;
 
 begin
   if (not assigned(Param)) or Param.IsNull then
     Result := 'Null'
-  else if Param.DataType in [ftString,ftFixedChar,ftBlob,ftMemo,ftBytes,ftVarBytes] then
+  else if Param.DataType in [ftString,ftFixedChar,ftMemo] then
+    Result := '''' + EscapeString(GetAsString(Param)) + ''''
+  else if Param.DataType in [ftBlob,ftBytes,ftVarBytes] then
     Result := '''' + EscapeString(Param.AsString) + ''''
   else
-    Result := inherited GetAsSqlText(Param);
+    Result := inherited GetAsSQLText(Param);
 end;
 
 
@@ -440,8 +434,12 @@ begin
   ConnectMySQL(FMySQL);
   FServerInfo := strpas(mysql_get_server_info(FMYSQL));
   FHostInfo := strpas(mysql_get_host_info(FMYSQL));
+{$IFDEF MYSQL50_UP}
+  mysql_get_character_set_info(FMYSQL, @FConnectionCharsetInfo);
+{$ENDIF}
 end;
 
+
 Procedure TConnectionName.SelectDatabase;
 begin
   if mysql_select_db(FMySQL,pchar(DatabaseName))<>0 then
@@ -527,6 +525,11 @@ begin
   Result:=FMySQL;
 end;
 
+function TConnectionName.GetConnectionCharSet: string;
+begin
+  Result:=StrPas(mysql_character_set_name(FMySQL));
+end;
+
 Function TConnectionName.AllocateCursorHandle: TSQLCursor;
 begin
   {$IFDEF mysql57}
@@ -753,8 +756,10 @@ begin
           NewType := ftBytes
         else
           NewType := ftVarBytes;
-{$ENDIF}
+      NewSize := ASize div FConnectionCharsetInfo.mbmaxlen;
+{$ELSE}
       NewSize := ASize;
+{$ENDIF}
       end;
     FIELD_TYPE_TINY_BLOB..FIELD_TYPE_BLOB:
       begin
@@ -781,7 +786,7 @@ procedure TConnectionName.AddFieldDefs(cursor: TSQLCursor;
 
 var
   C : TCursorName;
-  I, TF, FC: Integer;
+  I, FC: Integer;
   field: PMYSQL_FIELD;
   DFT: TFieldType;
   DFS: Integer;
@@ -798,19 +803,18 @@ begin
   FC:=mysql_num_fields(C.FRes);
   SetLength(c.MapDSRowToMSQLRow,FC);
 
-  TF := 1;
-  For I:= 0 to FC-1 do
+  For I := 0 to FC-1 do
     begin
     field := mysql_fetch_field_direct(C.FRES, I);
 //    Writeln('MySQL: creating fielddef ',I+1);
 
     if MySQLDataType(field, DFT, DFS) then
       begin
-      FieldDefs.Add(FieldDefs.MakeNameUnique(field^.name), DFT, DFS,
+      AddFieldDef(FieldDefs, I+1, field^.name, DFT, DFS, -1,
+                    False,
                     (field^.flags and (AUTO_INCREMENT_FLAG or NOT_NULL_FLAG {$IFDEF MYSQL50_UP}or NO_DEFAULT_VALUE_FLAG{$ENDIF})) = (NOT_NULL_FLAG {$IFDEF MYSQL50_UP}or NO_DEFAULT_VALUE_FLAG{$ENDIF}),
-                    TF);
-      c.MapDSRowToMSQLRow[TF-1] := I;
-      inc(TF);
+                    False);
+      c.MapDSRowToMSQLRow[I] := I;
       end
     end;
 //  Writeln('MySQL: Finished adding fielddefs');

+ 10 - 10
packages/fcl-db/src/sqldb/postgres/pqconnection.pp

@@ -742,7 +742,7 @@ begin
   case AOID of
     Oid_varchar,Oid_bpchar,
     Oid_name               : begin
-                             Result := ftstring;
+                             Result := ftString;
                              size := PQfsize(Res, Tuple);
                              if (size = -1) then
                                begin
@@ -754,7 +754,7 @@ begin
                                end;
                              if size > MaxSmallint then size := MaxSmallint;
                              end;
-//    Oid_text               : Result := ftstring;
+//    Oid_text               : Result := ftString;
     Oid_text,Oid_JSON      : Result := ftMemo;
     Oid_Bytea              : Result := ftBlob;
     Oid_oid                : Result := ftInteger;
@@ -973,9 +973,9 @@ end;
 
 procedure TPQConnection.Execute(cursor: TSQLCursor;atransaction:tSQLtransaction;AParams : TParams);
 
-var ar  : array of pchar;
+var ar  : array of PAnsiChar;
     l,i : integer;
-    s   : string;
+    s   : RawByteString;
     lengths,formats : array of integer;
     ParamNames,
     ParamValues : array of string;
@@ -1022,10 +1022,10 @@ begin
             ftFmtBCD:
               s := BCDToStr(AParams[i].AsFMTBCD, FSQLFormatSettings);
             else
-              s := AParams[i].AsString;
+              s := GetAsString(AParams[i]);
           end; {case}
           GetMem(ar[i],length(s)+1);
-          StrMove(PChar(ar[i]),PChar(s),Length(S)+1);
+          StrMove(PAnsiChar(ar[i]), PAnsiChar(s), Length(S)+1);
           lengths[i]:=Length(s);
           if (AParams[i].DataType in [ftBlob,ftMemo,ftGraphic,ftCurrency]) then
             Formats[i]:=1
@@ -1083,8 +1083,8 @@ end;
 procedure TPQConnection.AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs);
 var
   i         : integer;
-  size      : integer;
-  aoid       : oid;
+  asize     : integer;
+  aoid      : oid;
   fieldtype : tfieldtype;
   nFields   : integer;
   b : Boolean;
@@ -1101,8 +1101,8 @@ begin
     setlength(FieldBinding,nFields);
     for i := 0 to nFields-1 do
       begin
-      fieldtype := TranslateFldType(Res, i,size, aoid );
-      FD:=FieldDefs.Add(FieldDefs.MakeNameUnique(PQfname(Res, i)),fieldtype,Size,False,I+1) as TSQLDBFieldDef;
+      fieldtype := TranslateFldType(Res, i, asize, aoid );
+      FD := AddFieldDef(FieldDefs, i+1, PQfname(Res, i), fieldtype, asize, -1, False, False, False) as TSQLDBFieldDef;
       With FD do
         begin
         SQLDBData:=@FieldBinding[i];