oraservicesuni.pas
来自「CrLab UniDAC 1.0 include sources」· PAS 代码 · 共 1,991 行 · 第 1/5 页
PAS
1,991 行
PropValue: Variant;
begin
GetIRecordSet.GetCommand.GetProp(prTemporaryLobUpdate, PropValue);
Result := PropValue;
end;
procedure TCustomOraDataSetService.InitCursor;
begin
inherited;
end;
procedure TCustomOraDataSetService.InitUpdatingTable(AdjustFields: boolean = True);
begin
FFieldsInfoRequested := False;
inherited;
end;
procedure TCustomOraDataSetService.FillFieldsDefaultValues;
begin
GetFieldsInfo;
end;
procedure TCustomOraDataSetService.FillFieldsOrigin;
begin
GetFieldsInfo;
end;
function TCustomOraDataSetService.DetectIdentityField: TField;
var
i: integer;
FieldDesc: TCRFieldDesc;
RecordSet: TOCIRecordSet;
begin
GetFieldsInfo;
Result := nil;
//Search Identity Field
RecordSet := TOCIRecordSet(GetIRecordSet);
for i := 0 to RecordSet.FieldCount - 1 do begin
FieldDesc := TCRFieldDesc(RecordSet.Fields[i]);
if CompareText(FieldDesc.ActualName, 'ROWID') = 0 then
if TCRFieldDesc(FieldDesc).TableInfo = UpdatingTableInfo then begin
Result := FDataSet.GetField(FieldDesc);
break;
end;
end;
end;
function TCustomOraDataSetService.DetectKeyGeneratorField: TField;
var
FieldName: string;
Pos: integer;
begin
if (Trim(FKeySequence) <> '') and (GetKeyFields <> '') then begin
Pos := 1;
FieldName := ExtractFieldName(GetKeyFields, Pos);
Result := FDataSet.FindField(FieldName);
end
else
Result := nil;
end;
function TCustomOraDataSetService.DetectHiddenFields: TFieldArray;
var
i: integer;
FieldDesc: TCRFieldDesc;
RecordSet: TOCIRecordSet;
Field: TField;
begin
Result := nil;
RecordSet := TOCIRecordSet(GetIRecordSet);
for i := 0 to RecordSet.FieldCount - 1 do begin
FieldDesc := TCRFieldDesc(RecordSet.Fields[i]);
if CompareText(FieldDesc.ActualName, 'ROWID') = 0 then begin
Field := FDataSet.GetField(FieldDesc);
if Field <> nil then begin
SetLength(Result, Length(Result) + 1);
Result[Length(Result) - 1] := Field;
end;
end;
end;
end;
function TCustomOraDataSetService.DetectCanModify: boolean;
begin
Result := (inherited DetectCanModify or
not FDataSet.ReadOnly and
(not CompatibilityMode or
(FDataSet.SQLInsert.Count > 0) or
(FDataSet.SQLUpdate.Count > 0) or
(FDataSet.SQLDelete.Count > 0)) and
FIsAnyFieldCanBeModified) and
not (FScrollableCursor); // can't modify scrollable cursor
end;
function TCustomOraDataSetService.SetProp(Prop: integer; const Value: variant): boolean;
begin
Result := True;
case Prop of
prKeySequence:
FKeySequence := Value;
prSequenceMode:
FSequenceMode := _TSequenceMode(Value);
prExtendedFieldsInfo:
FExtendedFieldsInfo := Value;
prScrollableCursor:
FScrollableCursor := Value;
else
Result := inherited SetProp(Prop, Value);
end;
end;
function TCustomOraDataSetService.OpenNext: boolean;
var
Cursor: TCRCursor;
begin
if not FDataSet.Active then begin
FDataSet.Open;
Result := True;
end
else begin
Cursor := TOCICommand(GetIRecordSet.GetCommand).GetNextCursor;
if Cursor <> nil then begin
FDataSet.Close;
TDBAccessUtils.SetCursor(FDataSet, Cursor);
FDataSet.Open;
Result := True;
end
else
Result := False;
end;
end;
procedure TCustomOraDataSetService.FillDataFieldDescs(out DataFieldDescs: TFieldDescArray;
ForceUseAllKeyFields: boolean);
var
i: integer;
RecordSet: TOCIRecordSet;
Field: TField;
FieldDesc: TCRFieldDesc;
begin
GetFieldsInfo;
for i := 0 to FDataSet.FieldCount - 1 do begin
Field := FDataSet.Fields[i];
if (Field.FieldKind <> fkData) or (Field = FIdentityField) then
Continue;
FieldDesc := TCRFieldDesc(FDataSet.GetFieldDesc(Field));
if (FieldDesc.TableInfo <> UpdatingTableInfo) or (FieldDesc.TableInfo = nil) then
Continue;
if (FieldDesc.ParentField = nil) and not FieldDesc.ReadOnly then begin
SetLength(DataFieldDescs, Length(DataFieldDescs) + 1);
DataFieldDescs[High(DataFieldDescs)] := FieldDesc;
end;
end;
if not FDataSet.ObjectView then begin
RecordSet := TOCIRecordSet(GetIRecordSet);
for i := 0 to RecordSet.Fields.Count - 1 do begin
FieldDesc := TCRFieldDesc(RecordSet.Fields[i]);
if not (((FieldDesc.DataType = dtObject) or (FieldDesc.DataType = dtArray)) and (FieldDesc.ParentField = nil)) then
Continue;
if FieldDesc.TableInfo = nil then
FieldDesc.TableInfo := UpdatingTableInfo;
if not FieldDesc.ReadOnly and (FieldDesc.TableInfo = UpdatingTableInfo) then begin
SetLength(DataFieldDescs, Length(DataFieldDescs) + 1);
DataFieldDescs[High(DataFieldDescs)] := FieldDesc;
end;
end;
end;
end;
type
TColumnInfo = class
Name: string;
Table: string;
TableIndex: Integer; //TODO: ref on TCRTableInfo
Expr: string; // expression
Alias: string;
Used: boolean; // is ColumnInfo used by another Field
Described: boolean;
end;
TColumnsInfo = array of TColumnInfo;
function GetColumnsInfo(SQL: string; var ColumnsInfo: TColumnsInfo): integer;
var
Parser: TOraParser;
St, PrevSt, Name, Table, Expr, Alias: string;
Code, PrevCode: integer;
BracketCount: integer;
IsExpr: boolean;
begin
Result := 0;
Parser := TOraParser.Create(PChar(SQL));
try
Parser.OmitComment := True;
if Parser.ToLexem(lxSELECT) = lxSELECT then begin
Name := '';
Table := '';
Alias := '';
Expr := '';
IsExpr := False;
BracketCount := 0;
Code := 0;
repeat
PrevCode := Code;
PrevSt := St;
Code := Parser.GetNext(St);
/// keywords after SELECT
if (St = 'ALL') or (St = 'DISTINCT') or (St = 'UNIQUE') then
Continue;
if ((Code = lcIdent) or (St = '*')) and not IsExpr then begin
Name := St;
Code := Parser.GetNext(St);
if St = '.' then begin
Code := Parser.GetNext(St);
if (Code = lcIdent) or (St = '*') then begin
Table := Name;
Name := St;
Code := Parser.GetNext(St);
if St = '.' then begin
Code := Parser.GetNext(St);
if (Code = lcIdent) or (St = '*') then begin
Table := Table + '.' + Name;
Name := St;
Code := Parser.GetNext(St);
end;
end;
end;
end;
if Code = lxAS then
Code := Parser.GetNext(St);
if Code = lcIdent then begin
Alias := St;
Code := Parser.GetNext(St);
end;
end;
if ((St = ',') or (Code = lxFROM)) and (BracketCount = 0) or (Code = lcEnd) then begin
if not isExpr and ((Name = 'NULL') or (Name = 'SYSDATE')
or (Name = 'USER') or (Name = 'UID'))
then begin
IsExpr := True;
Expr := name;
end;
// add column
if Result >= Length(ColumnsInfo) then
SetLength(ColumnsInfo, Length(ColumnsInfo) + 200);
ColumnsInfo[Result] := TColumnInfo.Create;
if not IsExpr then begin
ColumnsInfo[Result].Name := TOCITableInfo.NormalizeName(Name, False, True);
ColumnsInfo[Result].Table := TOCITableInfo.NormalizeName(Table, False, True);
end
else
ColumnsInfo[Result].Expr := Expr;
ColumnsInfo[Result].Alias := TOCITableInfo.NormalizeName(Alias, False, True);
Inc(Result);
if St = ',' then begin
Name := '';
Table := '';
Alias := '';
Expr := '';
IsExpr := False;
end
else
break;
end
else begin
if not IsExpr then begin
Expr := Name;
if Table = '' then
Expr := Name
else
Expr := Table + '.' + Name;
Alias := '';
IsExpr := True;
end
else
if Alias <> '' then
Expr := Expr + Alias;
if St = '(' then
Inc(BracketCount)
else
if St = ')'then
Dec(BracketCount);
if Code = lxAS then
Continue;
if (BracketCount = 0) and (Code = lcIdent) and
((PrevCode = lcIdent) or (PrevCode = lcNumber) or (PrevCode = lcString)
or (PrevCode = lxAS) or (PrevSt = ')'))
then
Alias := St
else
Expr := Expr + St;
end;
if (Code = lcEnd) or (Code = lxFROM) and (BracketCount = 0) then
break;
until False;
end;
finally
Parser.Free;
end;
end;
type
TLocalTableInfo = record
TableName: string;
Synonym: string;
DBLink: string;
Schema: string;
Flag: byte;
end;
TLocalTablesInfo = array of TLocalTableInfo;
procedure TCustomOraDataSetService.GetFieldsInfo;
var
Columns: TList;
UserName: string;
Query: TCustomDADataSet;
Tables: TLocalTablesInfo;
function AddDBLink(DBLink: string): string;
begin
if DBLink <> '' then
Result := '@' + DBLink;
end;
function GetDefExpr(Value: string; DataType: string): string;
var
P: integer;
DeqValue: string;
begin
if DefaultExpressionOldBehavior then begin
Result := TrimRight(Value);
DeqValue := AnsiDequotedStr(Result, '''');
if (Result <> DeqValue) and (AnsiQuotedStr(DeqValue, '''') = Result) then // '1' + '2' should not be dequoted
Result := DeqValue;
if (DataType = 'NUMBER') and (DecimalSeparator{$IFDEF CLR}[1]{$ENDIF} <> '.') then begin
P := Pos('.', Result);
if P > 0 then
Result[P] := DecimalSeparator{$IFDEF CLR}[1]{$ENDIF};
end;
end
else
Result := Value;
end;
function GetOwner: string;
begin
Result := TOCIConnection(TDBAccessUtils.GetIConnection(UsedConnection)).GetCachedSchema;
end;
procedure GetFieldsInfoServer(var NeedDescribeSynonyms: boolean);
var
SQL, Filter: string;
CurTableName, FieldTableName, CurOwner, FieldOwner, DBLink: string;
j, p: integer;
ColumnInfo, NewColumnInfo: TColumnInfo;
Located, MoreDBLinks: boolean;
begin
NeedDescribeSynonyms := False;
for j := 0 to High(Tables) do
Tables[j].Flag := Tables[j].Flag and not 2; // 2 - info is queried
repeat
Filter := '';
MoreDBLinks := False;
for j := 0 to High(Tables) do
if (Tables[j].Flag and 1 <> 0) and (Tables[j].Flag and 2 = 0) then begin
if Filter = '' then
DBLink := Tables[j].DBLink
else begin
if Tables[j].DBLink <> DBLink then begin
MoreDBLinks := True;
continue;
end;
Tables[j].Flag := Tables[j].Flag or 2;
Filter := Filter + ' OR';
end;
Filter := Filter + ' (table_name = ''' + Tables[j].TableName + '''' +
' and owner = ''' + Tables[j].Schema + ''')';
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?