oraservicesuni.pas

来自「CrLab UniDAC 1.0 include sources」· PAS 代码 · 共 1,991 行 · 第 1/5 页

PAS
1,991
字号
            ReadFieldsFromServer := True;
       end;
     end;

(*     if not (ExtendedFieldsInfo or FDataSet.Options.DefaultValues or FDataSet.Options.FieldsOrigin) and
       ReadFieldsFromServer
     then
       Exit; //TODO: Imposible to tune*)

     ReadFieldsFromServer := ReadFieldsFromServer and
       (FExtendedFieldsInfo or FDataSet.Options.DefaultValues or FDataSet.Options.FieldsOrigin);


     if ReadFieldsFromServer or FDataSet.Options.DefaultValues then
       GetTablesFields;

     for i := 0 to FDataSet.FieldCount - 1 do
       if FDataSet.Fields[i].FieldKind = fkData then begin
         FieldDesc := TCRFieldDesc(FDataSet.GetFieldDesc(FDataSet.Fields[i]));
         FieldName := FieldDesc.ActualName;
         for j := 0 to Columns.Count - 1 do begin
           ColumnInfo := TColumnInfo(Columns[j]);
           if (FieldName = ColumnInfo.Alias) and (not ColumnInfo.Used) and
             (not ReadFieldsFromServer or (ColumnInfo.TableIndex <> -1))
           then begin
             if ColumnInfo.Name <> '' then begin
               ColumnInfo.Used := True;
               if ColumnInfo.TableIndex <> - 1 then
                 FieldDesc.TableInfo := TablesInfo[ColumnInfo.TableIndex]
               else
                 // When ExtendedFieldsInfo = False we suggest that field w/o Table
                 // belong to first table in TablesInfo
                 if (ColumnInfo.Table = '') and not ReadFieldsFromServer then
                   FieldDesc.TableInfo := TablesInfo[0];
               Origin := ColumnInfo.Name;
               if ColumnInfo.Alias <> '' then
                 FieldDesc.ActualName := ColumnInfo.Name;
               if ColumnInfo.Expr <> '' then
                 FDataSet.Fields[i].DefaultExpression := ColumnInfo.Expr;
             end;
             break;
           end
           else
             // If we don't find corresponding ColumnInfo,
             // we suggest that field belong to the same table that '*' belong
             if j = Columns.Count - 1 then begin
               if not ReadFieldsFromServer and (DefaultTable <> -1) then
                 FieldDesc.TableInfo := TablesInfo[DefaultTable];
               Origin := FieldName;
             end;
         end;

         if FDataSet.Options.FieldsOrigin then begin
           if FieldDesc.TableInfo <> nil then
             Origin := FieldDesc.TableInfo.TableName + '.' + Origin;
            FDataSet.Fields[i].Origin := Origin;
         end;
       end;
   finally
     for i := 0 to Columns.Count - 1 do
       TObject(Columns[i]).Free;
     Columns.Free;
   end;
  finally
    for i := 0 to ColumnCount - 1 do
      ColumnsInfo[i].Free;
  end;
  FFieldsInfoRequested := True;
end;

function TCustomOraDataSetService.GetRecCount: integer;
var
  St: string;
  UpdateQuery: TCustomDADataSet;
  MonitorClass: TDASQLMonitorClass;
  MessageID: cardinal;
  Parser: TOraParser;
begin
  Result := 0;
  St := FDataSet.FinalSQL;
  St := _SetOrderBy(St, '', TOraParser);
  Parser := TOraParser.Create(PChar(St));
  try
    if Parser.ToLexem(lxFOR) <> lcEnd then begin
      St := copy(St, 1, Parser.CurrPos - 3);
    end;
  finally
    Parser.Free;
  end;
  St := 'SELECT Count(*) FROM (' + LineSeparator + St + ')';

  FUpdater.CheckUpdateQuery(stCustom);
  UpdateQuery := TCustomDADataSet(FUpdater.UpdateQuery);
  UpdateQuery.SQL.Text := St;
  UpdateQuery.Params.Assign(FDataSet.Params);

  UpdateQuery.Prepare;
  if TOCICommand(TDBAccessUtils.GetICommand(UpdateQuery)).GetSQLType = SQL_SELECT then begin
    MonitorClass := TDASQLMonitorClass(TDBAccessUtils.SQLMonitorClass(UsedConnection));
    if MonitorClass.HasMonitor or FDataSet.Debug then
      MonitorClass.SQLExecute(FDataSet, St, UpdateQuery.Params, 'Get RecordCount', MessageID, True);

    UpdateQuery.Open;
    if not UpdateQuery.EOF then
      Result := UpdateQuery.Fields[0].AsInteger;

    if MonitorClass.HasMonitor or FDataSet.Debug then
      MonitorClass.SQLExecute(FDataSet, St, UpdateQuery.Params, 'Get RecordCount', MessageID, False);
  end;
end;

function TCustomOraDataSetService.GetIRecordSet: TCRRecordSet;
begin
  Result := inherited GetIRecordSet;
end;

function TCustomOraDataSetService.UsedConnection: TCustomDAConnection;
begin
  Result := inherited UsedConnection;
end;

function TCustomOraDataSetService.IsFullRefresh: boolean;
begin
  Result := inherited IsFullRefresh;
end;

function TCustomOraDataSetService.IsDMLRefresh: boolean;
begin
  Result := inherited IsDMLRefresh;
end;

function TCustomOraDataSetService.IsInCacheProcessing: boolean;
begin
  Result := inherited IsInCacheProcessing;
end;

function TCustomOraDataSetService.GetKeyFields: string;
begin
  Result := inherited GetKeyFields;
end;

function TCustomOraDataSetService.IsAutoCommit: boolean;
begin
  Result := inherited IsAutoCommit;
end;

function TCustomOraDataSetService.CompatibilityMode: boolean;
begin
  Result := False;
end;

function TCustomOraDataSetService.GetFieldClass(FieldType: TFieldType): TFieldClass;
{$IFDEF VER10P}
var
  Value: variant;
{$ENDIF}
begin
{$IFDEF VER10P}
  if FieldType = ftOraClob then begin
    TDBAccessUtils.GetIConnection(UsedConnection).GetProp(prUseUnicode, Value);
    if Boolean(Value) then
      Result := TWideMemoField
    else
      Result := TMemoField;
  end
  else
{$ENDIF}
    Result := inherited GetFieldClass(FieldType);
end;

{ TOraServerEnumerator }

type
  TTNSParser = class (TParser)
  protected
    function IsInlineComment(Pos: integer): boolean; override;
  end;

function TTNSParser.IsInlineComment(Pos: integer): boolean;
begin
  Result := (TextLength >= Pos + 1) and (Text[Pos] = '#');
end;

procedure TOraServerEnumerator.GetServerList(List: TStrings);
const
  sCannotFind = 'Cannot find ';
  sTnsAdmin = 'TNS_ADMIN';
  sTnsNames = 'tnsnames.ora';
{$IFDEF MSWINDOWS}
  sOraHomeKey = 'SOFTWARE\ORACLE\';
  sNetwork = '\network\admin\';
  sNet80 = '\net80\admin\';
{$ENDIF}
{$IFDEF LINUX}
  sNetwork = '/network/admin/';
{$ENDIF}
var
{$IFDEF MSWINDOWS}
  RegIniFile: TRegIniFile;
{$ENDIF}
  i, j: integer;
  IFile, F: TStrings;
  Parser: TTNSParser;
  Code: integer;
  Text,St,OldSt,Alias: string;
  Bracket: integer;
  HomePath, CurrentDir, FileName: string;
  TNSFound: boolean;

  function AddPath(Path, FileName: string): string;
  begin
    if (Path <> '') and (Path[Length(Path)] <> '\') then
      Result := Path + '\' + FileName
    else
      Result := Path + FileName;
  end;

begin
  inherited;

  if FDirect then
    exit;

  TNSFound := False;

  if FTNSPath <> '' then begin
    FileName := AddPath(FTNSPath, sTnsNames);
    if FileExists(FileName) then
      TNSFound := True;
  end
  else begin
  {$IFDEF MSWINDOWS}
    /// check if TNS_ADMIN environment variable is set
  {$IFNDEF CLR}
    i := GetEnvironmentVariable(sTnsAdmin, nil, 0);
    if i > 0 then begin
      SetLength(FileName, i - 1);
      GetEnvironmentVariable(sTnsAdmin, PChar(FileName), Length(FileName) + 1);
      FileName := AddPath(FileName, sTnsNames);
      if FileExists(FileName) then
        TNSFound := True;
    end;
  {$ENDIF}

    if not TNSFound then begin
      /// look for TNS_ADMIN variable in registry
      if not LoadedOCI then
        DetectOCI;

      RegIniFile := TRegIniFile.Create('');
      try
        RegIniFile.RootKey := HKEY_LOCAL_MACHINE;
        if (FHomeName = '') and (OracleHomeCount > 0) then
          FileName := AddPath(RegIniFile.ReadString(sOraHomeKey +
            OracleHomeKeys[DefaultOracleHome], sTnsAdmin, ''), sTnsNames)
        else
          for i := 0 to OracleHomeCount - 1 do
            if AnsiCompareText(OracleHomeNames[i] , FHomeName) = 0 then begin
              FileName := AddPath(RegIniFile.ReadString(sOraHomeKey +
                OracleHomeKeys[i], sTnsAdmin, ''), sTnsNames);
              break;
            end;
      finally
        RegIniFile.Free;
      end;

      if FileExists(FileName) then
        TNSFound := True;
    end;
  {$ENDIF}

    if not TNSFound then begin
      /// look for tnsnames.ora in Oracle Home
      if FHomeName = '' then
        HomePath := OracleHomePath
      else
        for i := 0 to OracleHomeCount - 1 do
          if AnsiCompareText(OracleHomeNames[i] , FHomeName) = 0 then begin
            HomePath := OracleHomePaths[i];
            break;
          end;

      if HomePath <> '' then begin
        FileName := HomePath + sNetwork + sTnsNames;
        if FileExists(FileName) then
          TNSFound := True
        else begin
        {$IFNDEF LINUX}
          FileName := HomePath + sNet80 + sTnsNames;
          if FileExists(FileName) then
            TNSFound := True
        {$ENDIF}
        end;
      end;
    end;
  end;

  if not TNSFound then
    exit;

  F := TStringList.Create;
  Parser := TTNSParser.Create('');
  try
    Parser.OmitBlank := True;
    Parser.OmitComment := True;
    F.LoadFromFile(FileName);

    IFile := TStringList.Create;
    i := 0;
    CurrentDir := GetCurrentDir;
    SetCurrentDir(ExtractFileDir(FileName));
    try
      while i < F.Count do begin
        if Pos('IFILE', AnsiUpperCase(F[i])) > 0 then begin
          FileName := Trim(Copy(F[i], Pos('=',F[i]) + 1, MaxInt));
          if FileExists(FileName) then begin
            IFile.LoadFromFile(FileName);
            F.Delete(i);
            for j := IFile.Count - 1 downto 0 do
               F.Insert(i, IFile[j]);
            Continue;
          end;
        end;
        Inc(i);
      end;
    finally
      SetCurrentDir(CurrentDir);
      IFile.Free;
    end;

    Text := F.Text;
    Parser.SetText(PChar(Text));
    Code := 0;
    St := '';
    Alias := '';
    Bracket := 0;
    List.Clear;
    repeat
      if (Bracket = 0) and ((Code = lcIdent) or (Code = lcNumber) or (St = '-')) then
        if OldSt = '.' then begin
          if (AnsiUpperCase(St) <> 'WORLD') or (OCIVersion > 8100) then
            Alias := Alias + '.' + St
        end
        else
          Alias := Alias + St;

      OldSt := St;

      Code := Parser.GetNext(St);
      if St = '(' then
        Inc(Bracket)
      else
        if St = ')' then
          Dec(Bracket)
        else
          if (St = '=') and (Bracket = 0) then begin
            List.Add(Alias);
            Alias := '';
          end;
    until Code = lcEnd;
  finally
    Parser.Free;
    F.Free;
  end;
end;

function TOraServerEnumerator.GetProp(Prop: integer; var Value: variant): boolean;
begin
  Result := True;
  case Prop of
    prHomeName:
      Value := FHomeName;
  else
    Result := inherited GetProp(Prop, Value);
  end;
end;

function TOraServerEnumerator.SetProp(Prop: integer; const Value: variant): boolean;
begin
  Result := True;
  case Prop of
    prDirect:
      FDirect := Value;
    prHomeName:
      FHomeName := Value;
    prTNSPath:
      FTNSPath := Value;
  else
    Result := inherited SetProp(Prop, Value);
  end;
end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?