--- ibx/trunk/runtime/IBSQL.pas 2000/07/31 16:43:00 4 +++ ibx/trunk/runtime/IBSQL.pas 2011/02/18 16:26:16 5 @@ -28,10 +28,18 @@ unit IBSQL; +{$Mode Delphi} + interface uses - Windows, SysUtils, Classes, Forms, Controls, IBHeader, +{$IFDEF LINUX } + baseunix,unix, +{$ELSE} +{$DEFINE HAS_SQLMONITOR} + Windows, +{$ENDIF} + SysUtils, Classes, Forms, Controls, IBHeader, IBErrorCodes, IBExternals, DB, IB, IBDatabase, IBUtils, IBXConst; type @@ -178,7 +186,11 @@ type { TIBOutputDelimitedFile } TIBOutputDelimitedFile = class(TIBBatchOutput) protected + {$IFDEF LINUX} + FHandle: cint; + {$ELSE} FHandle: THandle; + {$ENDIF} FOutputTitles: Boolean; FColDelimiter, FRowDelimiter: string; @@ -217,7 +229,11 @@ type { TIBOutputRawFile } TIBOutputRawFile = class(TIBBatchOutput) protected + {$IFDEF LINUX} + FHandle: cint; + {$ELSE} FHandle: THandle; + {$ENDIF} public destructor Destroy; override; procedure ReadyFile; override; @@ -227,7 +243,11 @@ type { TIBInputRawFile } TIBInputRawFile = class(TIBBatchInput) protected + {$IFDEF LINUX} + FHandle: cint; + {$ELSE} FHandle: THandle; + {$ENDIF} public destructor Destroy; override; function ReadParameters: Boolean; override; @@ -294,6 +314,7 @@ type function Current: TIBXSQLDA; procedure ExecQuery; function FieldByName(FieldName: String): TIBXSQLVAR; + function ParamByName(ParamName: String): TIBXSQLVAR; procedure FreeHandle; function Next: TIBXSQLDA; procedure Prepare; @@ -328,7 +349,7 @@ type implementation uses - IBIntf, IBBlob, IBSQLMonitor; + IBIntf, IBBlob, Variants {$IFDEF HAS_SQLMONITOR}, IBSQLMonitor {$ENDIF}; { TIBXSQLVAR } constructor TIBXSQLVAR.Create(Parent: TIBXSQLDA; Query: TIBSQL); @@ -424,7 +445,8 @@ end; function TIBXSQLVAR.AdjustScale(Value: Int64; Scale: Integer): Double; var - Scaling, i: Integer; + Scaling : Int64; + i: Integer; Val: Double; begin Scaling := 1; Val := Value; @@ -447,7 +469,8 @@ end; function TIBXSQLVAR.AdjustScaleToInt64(Value: Int64; Scale: Integer): Int64; var - Scaling, i: Integer; + Scaling : Int64; + i: Integer; Val: Int64; begin Scaling := 1; Val := Value; @@ -463,10 +486,11 @@ end; function TIBXSQLVAR.AdjustScaleToCurrency(Value: Int64; Scale: Integer): Currency; var - Scaling, i : Integer; + Scaling : Int64; + i : Integer; FractionText, PadText, CurrText: string; begin - result := Value; + Result := 0; Scaling := 1; if Scale > 0 then begin @@ -489,9 +513,12 @@ begin try result := StrToCurr(CurrText); except - on E: Exception do IBError(ibxeInvalidDataConversion, [nil]); + on E: Exception do + IBError(ibxeInvalidDataConversion, [nil]); end; - end; + end + else + result := Value; end; function TIBXSQLVAR.GetAsCurrency: Currency; @@ -1294,19 +1321,23 @@ begin if FParent.FNames[i] = FName then begin xvar := FParent[i]; - xvar.FXSQLVAR^.sqlind^ := -1; - xvar.FModified := True; - end; - end else if ((not Value) and IsNullable) then - begin - for i := 0 to FParent.FCount - 1 do - if FParent.FNames[i] = FName then - begin - xvar := FParent[i]; - xvar.FXSQLVAR^.sqlind^ := 0; + if Assigned(xvar.FXSQLVAR^.sqlind) then + xvar.FXSQLVAR^.sqlind^ := -1; xvar.FModified := True; end; - end; + end + else + if ((not Value) and IsNullable) then + begin + for i := 0 to FParent.FCount - 1 do + if FParent.FNames[i] = FName then + begin + xvar := FParent[i]; + if Assigned(xvar.FXSQLVAR^.sqlind) then + xvar.FXSQLVAR^.sqlind^ := 0; + xvar.FModified := True; + end; + end; end; procedure TIBXSQLVAR.SetIsNullable(Value: Boolean); @@ -1361,7 +1392,7 @@ begin FXSQLDA := nil; FXSQLVARs := nil; end; - inherited; + inherited Destroy; end; procedure TIBXSQLDA.AddName(FieldName: String; Idx: Integer); @@ -1442,31 +1473,40 @@ var begin bUnique := True; NamesWereEmpty := (FNames.Count = 0); - if FXSQLDA <> nil then begin - for i := 0 to FCount - 1 do begin - with FXSQLVARs[i].Data^ do begin - if bUnique and (String(relname) <> '') then + if FXSQLDA <> nil then + begin + for i := 0 to FCount - 1 do + begin + with FXSQLVARs[i].Data^ do + begin + if bUnique and (strpas(relname) <> '') then begin if FUniqueRelationName = '' then - FUniqueRelationName := String(relname) - else if String(relname) <> FUniqueRelationName then - begin - FUniqueRelationName := ''; - bUnique := False; - end; + FUniqueRelationName := strpas(relname) + else + if strpas(relname) <> FUniqueRelationName then + begin + FUniqueRelationName := ''; + bUnique := False; + end; end; - if NamesWereEmpty then begin - st := String(aliasname); - if st = '' then begin + if NamesWereEmpty then + begin + st := strpas(aliasname); + if st = '' then + begin st := 'F_'; {do not localize} aliasname_length := 2; j := 1; j_len := 1; StrPCopy(aliasname, st + IntToStr(j)); - end else begin + end + else + begin StrPCopy(aliasname, st); j := 0; j_len := 0; end; - while GetXSQLVARByName(String(aliasname)) <> nil do begin + while GetXSQLVARByName(strpas(aliasname)) <> nil do + begin Inc(j); j_len := Length(IntToStr(j)); if j_len + aliasname_length > 31 then StrPCopy(aliasname, @@ -1476,7 +1516,7 @@ begin StrPCopy(aliasname, st + IntToStr(j)); end; Inc(aliasname_length, j_len); - AddName(String(aliasname), i); + AddName(strpas(aliasname), i); end; case sqltype and (not 1) of SQL_TEXT, SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TIMESTAMP, @@ -1532,7 +1572,6 @@ begin FXSQLVARs[i] := TIBXSQLVAR.Create(self, FSQL); FXSQLVARs[i].FXSQLVAR := p; p := Pointer(PChar(p) + sizeof(FXSQLDA^.sqlvar)); -// FNames.Add(''); end; FSize := FCount; end; @@ -1548,48 +1587,76 @@ end; destructor TIBOutputDelimitedFile.Destroy; begin +{$IFDEF LINUX} + if FHandle <> -1 then + fpclose(FHandle); +{$ELSE} if FHandle <> 0 then begin FlushFileBuffers(FHandle); CloseHandle(FHandle); end; +{$ENDIF} inherited Destroy; end; procedure TIBOutputDelimitedFile.ReadyFile; var i: Integer; + {$IFDEF LINUX} + BytesWritten: cint; + {$ELSE} BytesWritten: DWORD; + {$ENDIF} st: string; begin if FColDelimiter = '' then FColDelimiter := TAB; if FRowDelimiter = '' then FRowDelimiter := CRLF; + {$IFDEF LINUX} + FHandle := FpOpen(Filename,O_WrOnly or O_Creat); + {$ELSE} FHandle := CreateFile(PChar(Filename), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if FHandle = INVALID_HANDLE_VALUE then FHandle := 0; + {$ENDIF} if FOutputTitles then begin for i := 0 to Columns.Count - 1 do if i = 0 then - st := string(Columns[i].Data^.aliasname) + st := strpas(Columns[i].Data^.aliasname) else - st := st + FColDelimiter + string(Columns[i].Data^.aliasname); + st := st + FColDelimiter + strpas(Columns[i].Data^.aliasname); st := st + FRowDelimiter; - WriteFile(FHandle, st[1], Length(st), BytesWritten, nil); + {$IFDEF LINUX} + if FHandle <> -1 then + BytesWritten := FpWrite(FHandle,st[1],Length(st)); + if BytesWritten = -1 then + raise Exception.Create('File Write Error'); + {$ELSE} + WriteFile(FHandle, PChar(st[1]), Length(st), BytesWritten, nil); + {$ENDIF} end; end; function TIBOutputDelimitedFile.WriteColumns: Boolean; var i: Integer; + {$IFDEF LINUX} + BytesWritten: cint; + {$ELSE} BytesWritten: DWORD; + {$ENDIF} st: string; begin result := False; + {$IFDEF LINUX} + if FHandle <> -1 then + {$ELSE} if FHandle <> 0 then + {$ENDIF} begin st := ''; for i := 0 to Columns.Count - 1 do @@ -1599,7 +1666,11 @@ begin st := st + StripString(Columns[i].AsString, FColDelimiter + FRowDelimiter); end; st := st + FRowDelimiter; + {$IFDEF LINUX} + BytesWritten := FpWrite(FHandle,st[1],Length(st)); + {$ELSE} WriteFile(FHandle, st[1], Length(st), BytesWritten, nil); + {$ENDIF} if BytesWritten = DWORD(Length(st)) then result := True; end @@ -1712,20 +1783,29 @@ end; { TIBOutputRawFile } destructor TIBOutputRawFile.Destroy; begin +{$IFDEF LINUX} + if FHandle <> -1 then + fpclose(FHandle); +{$ELSE} if FHandle <> 0 then begin FlushFileBuffers(FHandle); CloseHandle(FHandle); end; +{$ENDIF} inherited Destroy; end; procedure TIBOutputRawFile.ReadyFile; begin + {$IFDEF LINUX} + FHandle := FpOpen(Filename,O_WrOnly or O_Creat); + {$ELSE} FHandle := CreateFile(PChar(Filename), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if FHandle = INVALID_HANDLE_VALUE then FHandle := 0; + {$ENDIF} end; function TIBOutputRawFile.WriteColumns: Boolean; @@ -1738,8 +1818,12 @@ begin begin for i := 0 to Columns.Count - 1 do begin + {$IFDEF LINUX} + BytesWritten := FpWrite(FHandle,Columns[i].Data^.sqldata^, Columns[i].Data^.sqllen); + {$ELSE} WriteFile(FHandle, Columns[i].Data^.sqldata^, Columns[i].Data^.sqllen, BytesWritten, nil); + {$ENDIF} if BytesWritten <> DWORD(Columns[i].Data^.sqllen) then exit; end; @@ -1750,9 +1834,14 @@ end; { TIBInputRawFile } destructor TIBInputRawFile.Destroy; begin +{$IFDEF LINUX} + if FHandle <> -1 then + fpclose(FHandle); +{$ELSE} if FHandle <> 0 then CloseHandle(FHandle); - inherited; +{$ENDIF} + inherited Destroy; end; function TIBInputRawFile.ReadParameters: Boolean; @@ -1761,12 +1850,20 @@ var BytesRead: DWord; begin result := False; +{$IFDEF LINUX} + if FHandle <> -1 then +{$ELSE} if FHandle <> 0 then +{$ENDIF} begin for i := 0 to Params.Count - 1 do begin - ReadFile(FHandle, Params[i].Data^.sqldata^, Params[i].Data^.sqllen, + {$IFDEF LINUX} + BytesRead := FpRead(FHandle,Params[i].Data^.sqldata^,Params[i].Data^.sqllen); + {$ELSE} + ReadFile(FHandle, Params[i].Data^.sqldata^, Params[i].Data^.sqllen); BytesRead, nil); + {$ENDIF} if BytesRead <> DWORD(Params[i].Data^.sqllen) then exit; end; @@ -1776,12 +1873,20 @@ end; procedure TIBInputRawFile.ReadyFile; begin +{$IFDEF LINUX} + if FHandle <> -1 then + fpclose(FHandle); + FHandle := FpOpen(Filename,O_RdOnly); + if FHandle = -1 then + raise Exception.CreateFmt('Unable to open file %s',[Filename]); +{$ELSE} if FHandle <> 0 then CloseHandle(FHandle); FHandle := CreateFile(PChar(Filename), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); if FHandle = INVALID_HANDLE_VALUE then FHandle := 0; +{$ENDIF} end; { TIBSQL } @@ -1830,7 +1935,7 @@ begin FSQLParams.Free; FSQLRecord.Free; end; - inherited; + inherited Destroy; end; procedure TIBSQL.BatchInput(InputObject: TIBBatchInput); @@ -1982,8 +2087,10 @@ begin Database.SQLDialect, FSQLParams.AsXSQLDA), True) end; + {$IFDEF HAS_SQLMONITOR} if not (csDesigning in ComponentState) then MonitorHook.SQLExecute(Self); + {$ENDIF} end; function TIBSQL.GetEOF: Boolean; @@ -2001,6 +2108,11 @@ begin result := GetFields(i); end; +function TIBSQL.ParamByName(ParamName: String): TIBXSQLVAR; +begin + Result := Params.ByName(ParamName); +end; + function TIBSQL.GetFields(const Idx: Integer): TIBXSQLVAR; begin if (Idx < 0) or (Idx >= FSQLRecord.Count) then @@ -2040,8 +2152,10 @@ begin FBOF := False; result := FSQLRecord; end; + {$IFDEF HAS_SQLMONITOR} if not (csDesigning in ComponentState) then MonitorHook.SQLFetch(Self); + {$ENDIF} end; end; @@ -2372,8 +2486,10 @@ begin end; end; FPrepared := True; + {$IFDEF HAS_SQLMONITOR} if not (csDesigning in ComponentState) then MonitorHook.SQLPrepare(Self); + {$ENDIF} except on E: Exception do begin if (FHandle <> nil) then