Componentes.Terceros.RemObj.../official/5.0.24.615/Data Abstract for Delphi/Source/Drivers/Unsupported/uDADOADriver.pas

1175 lines
33 KiB
ObjectPascal
Raw Blame History

unit uDADOADriver;
interface
uses
DB,
Classes,
uROClasses,
uDAEngine,
uDAInterfaces,
uDAOracleInterfaces,
uDAUtils,
Oracle,
OracleData;
type
TDADOADriver = class(TDADriverReference)
end;
TDAEDOADriver = class(TDAEDriver)
private
fTraceCallBack: TDALogTraceEvent; // UKO 26.09.2003
protected
procedure DoSetTraceOptions(TraceActive: Boolean; TraceOptions:
TDATraceOptions; Callback: TDALogTraceEvent); override;
function GetAvailableDriverOptions: TDAAvailableDriverOptions; override;
function GetConnectionClass: TDAEConnectionClass; override;
function GetDefaultCustomParameters: string; override;
function GetDescription: string; override;
function GetDriverID: string; override;
function GetMajVersion: byte; override;
function GetMinVersion: byte; override;
procedure GetAuxParams(const AuxDriver: string; out List: IROStrings); override;
end;
TDAEDOAConnection = class(TDAECOnnection, IOracleConnection)
private
fSysObjects: Boolean;
fSchema: string;
fUsername: string;
function GetObjects(Schema, WhereClause: string): IROStrings;
function GetEncodedObjects(WhereClause: string): IROStrings;
function GetOracleSession: TOracleSession;
function GetStoredProcsInPackages(Schema: string): IROStrings;
function EncodeSchema(const Username, Schema: string; Contents: IROStrings): IROStrings;
function GetPrimaryKeys(const Schema, TableName: string): IROStrings;
function GetConstraintColumnsAsString(const AOwner, AConstraintName: string; out AColumns: string): string;
protected
function CreateCustomConnection: TCustomConnection; override;
function CreateMacroProcessor: TDASQLMacroProcessor; override;
procedure DoApplyConnectionString(aConnStrParser: TDAConnectionStringParser; aConnectionObject: TCustomConnection); override;
function DoBeginTransaction: Integer; override;
procedure DoCommitTransaction; override;
procedure DoGetStoredProcedureNames(out List: IROStrings); override;
procedure DoGetStoredProcedureParams(const aStoredProcedureName: string;
out Params: TDAParamCollection); override;
procedure DoGetTableFields(const aTableName: string; out Fields:
TDAFieldCollection); override;
procedure DoGetTableNames(out List: IROStrings); override;
procedure DoGetViewFields(const aViewName: string; out Fields:
TDAFieldCollection); override;
procedure DoGetViewNames(out List: IROStrings); override;
procedure DoGetForeignKeys(out ForeignKeys: TDADriverForeignKeyCollection); override;
procedure DoRollbackTransaction; override;
function GetDataSetClass: TDAEDatasetClass; override;
function GetStoredProcedureClass: TDAEStoredProcedureClass; override;
property OracleSession: TOracleSession read GetOracleSession;
function IdentifierNeedsQuoting(const iIdentifier: string): boolean; override;
end;
TDAEDOAQuery = class(TDAEDataSet, IDAMustSetParams, IOracleDataSet)
private
function LockModeDaToDoa(LockMode: TOracleLockMode): TLockingModeOptions;
function LockModeDoaToDa(LockMode: TLockingModeOptions): TOracleLockMode;
protected
function CreateDataset(aConnection: TDAEConnection): TDataset; override;
function DoExecute: Integer; override;
function DoGetSQL: string; override;
procedure DoPrepare(Value: Boolean); override;
procedure DoSetSQL(const Value: string); override;
function GetLockMode: TOracleLockMode;
function GetOptions: TOracleOptions;
procedure SetLockMode(Value: TOracleLockMode);
procedure SetOptions(Value: TOracleOptions);
procedure SetParamValues(Params: TDAParamCollection); safecall;
procedure GetParamValues(Params: TDAParamCollection); safecall;
end;
TDAEDOAStoredProcedure = class(TDAEStoredProcedure, IDAMustSetParams)
private
fProcedureName: string;
procedure DoGetParams;
function DoGetParamsResult: TDAParam;
procedure DoSetSource;
protected
function CreateDataset(aConnection: TDAEConnection): TDataset; override;
function Execute: Integer; override;
function GetStoredProcedureName: string; override;
procedure RefreshParams; override;
procedure SetParamValues(Params: TDAParamCollection); safecall;
procedure SetStoredProcedureName(const Name: string); override;
end;
procedure Register;
function GetDriverObject: IDADriver; stdcall;
implementation
{$INCLUDE DOA.INC}
uses
SysUtils,
uDADriverManager,
uDARes,
{$IFDEF DOA4}
OracleMonitor,
{$ENDIF}
uDAMacroProcessors;
const
NL = #13#10;
type
TDADOAInternalConnection = class(TCustomConnection)
private
fOracleSession: TOracleSession;
protected
procedure DoConnect; override;
procedure DoDisconnect; override;
function GetConnected: Boolean; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Session: TOracleSession read fOracleSession;
end;
TOraPath = record
aScheme: string;
aPackage: string;
aObject: string;
end;
var
_Driver: TDAEDriver = nil;
procedure Register;
begin
RegisterComponents(DAPalettePageName, [TDADOADriver]);
end;
function GetDriverObject: IDADriver;
begin
if (_Driver = nil) then
_Driver := TDAEDOADriver.Create(nil);
Result := _Driver;
end;
{ HELPERS ******************************************************************** }
function CaseStringOf(const Value: string; const Args: array of string):
Integer;
begin
for Result := High(Args) downto 0 do
if AnsiSameStr(Value, Args[Result]) then
Break;
end;
function ParamTypeOraToDa(const AName, AType: string): TDAParamType;
begin
Result := daptUnknown;
if AnsiSameStr(AType, 'IN') then
Result := daptInput;
if AnsiSameStr(AType, 'OUT') then
begin
if Length(AName) = 0 then
Result := daptResult
else
Result := daptOutput;
end;
if AnsiSameStr(AType, 'IN/OUT') then
Result := daptInputOutput;
end;
function DataTypeOraToVcl(const AName: string; AScale: Integer): TFieldType;
begin
Result := ftUnknown;
case CaseStringOf(AName, ['BINARY_INTEGER', 'NUMBER', 'CHAR', 'NCHAR',
'VARCHAR2', 'NVARCHAR2', 'DATE', 'BLOB', 'CLOB', 'NCLOB', 'PL/SQL BOOLEAN',
'FLOAT']) of
0, 1:
if AScale = 0 then
Result := ftInteger
else
Result := ftFloat;
2, 3, 4, 5: Result := ftString;
6: Result := ftDate;
7: Result := ftBlob;
8, 9: Result := ftMemo;
10: Result := ftBoolean;
11: Result := ftFloat;
end;
end;
// 1) extended with DefaultScheme
// 2) if Scheme is not the Default and not SYS or SYSTEM then handle it as Packagename
// UKO 25.09.2003
function ExtractOraPath(AOraPath: string; ADefaultScheme: string): TOraPath;
var
PathList: TStringList;
Count: Integer;
begin
Result.aScheme := '';
Result.aPackage := '';
Result.aObject := '';
PathList := TStringList.Create;
try
Count := ExtractStrings(['.'], [' '], PAnsiChar(AOraPath), PathList);
case Count of
0: ;
1:
begin
Result.aObject := AOraPath;
Result.aScheme := ADefaultScheme;
end;
2:
begin
Result.aObject := PathList[1];
Result.aScheme := PathList[0];
// The case of packages must be handled seperatly :
// UKO 25.09.2003
if (AnsiCompareText(Result.aScheme, ADefaultScheme) <> 0) and
(AnsiCompareText(Result.aScheme, 'SYS') <> 0) and
(AnsiCompareText(Result.aScheme, 'SYSTEM') <> 0) then
begin
Result.aScheme := ADefaultScheme;
Result.aPackage := PathList[0];
Result.aObject := PathList[1];
end;
end;
else
begin
Result.aObject := PathList[PathList.Count - 1];
Result.aPackage := PathList[PathList.Count - 2];
Result.aScheme := PathList[PathList.Count - 3];
end;
end;
UpperCase(Result.aScheme);
UpperCase(Result.aPackage);
UpperCase(Result.aObject);
finally
PathList.Free;
end;
end;
function ProcessWhereExp(AName, AValue: string): string;
begin
Result := Format('%s =''%s''', [AName, AValue]);
if AValue = '' then
Result := Format('%s is null', [AName]);
end;
function HandleSqlName(AParamName: string; AParamType: TDAParamType): string;
begin
Result := AParamName;
if AParamType = daptResult then
Result := 'result';
end;
function DataTypeDaToOra(AType: TDADataType): Integer;
const
Error = 'INTERNAL: not supported by DOA';
begin
Result := otString;
case AType of
datUnknown: raise Exception.Create(Error);
datString: Result := otString;
datDateTime: Result := otDate;
datFloat: Result := otFloat;
datCurrency: Result := otFloat;
datAutoInc: raise Exception.Create(Error);
datInteger: Result := otInteger;
datLargeInt: Result := otInteger;
datBoolean: Result := otInteger; // needs a special handling
datMemo: Result := otClob;
datBlob: Result := otBlob;
end;
end;
procedure SetDataSetParams(Params: TDAParamCollection; DataSet: TDataSet);
var
I: Integer;
Ds: TOracleDataSet;
ParamIndex, OraType: Integer;
Name: string;
begin
Ds := TOracleDataSet(DataSet);
if Ds.Variables.Count > Params.Count then
for I := Ds.VariableCount - 1 downto 0 do
if Params.ParamByName(Ds.VariableName(I)) = nil then
Ds.DeleteVariable(Ds.VariableName(I));
for I := 0 to Params.Count - 1 do
begin
ParamIndex := Ds.VariableIndex(Params[I].Name);
Name := HandleSqlName(Params[I].Name, Params[I].ParamType);
OraType := DataTypeDaToOra(Params[I].DataType);
// New Param
if ParamIndex = -1 then
Ds.DeclareVariable(Name, OraType);
// Changed Param
if (ParamIndex > -1) and (Ds.VariableType(ParamIndex) <> DataTypeDaToOra(
Params[I].DataType)) then
begin
Ds.DeleteVariable(Params[I].Name);
Ds.DeclareVariable(Name, OraType);
end;
// Set value
if Params[I].DataType = datBoolean then
Ds.SetVariable(Name, Integer(Params[I].Value))
else
Ds.SetVariable(Name, Params[I].Value);
end;
end;
procedure GetStoredProcParams(
OracleSession: TOracleSession;
const aStoredProcedureName: string;
out Params: TDAParamCollection);
var
Query: TOracleQuery;
OraPath: TOraPath;
const
SQL = 'select ' + NL +
' argument_name, data_type, in_out, data_length, data_precision, data_scale ' + NL +
'from all_arguments' + NL +
'where' + NL +
' ((in_out = ''IN'' and argument_name IS NOT NULL) or in_out = ''OUT'' or in_out = ''IN/OUT'') ' + NL +
' and %s' + NL +
' and %s' + NL +
' and %s';
begin
Params := TDAParamCollection.Create(nil);
Query := TOracleQuery.Create(nil);
try
OraPath := ExtractOraPath(aStoredProcedureName, OracleSession.LogonUsername);
Query.Session := OracleSession;
Query.SQL.Text := Format(SQL, [ProcessWhereExp('owner', OraPath.aScheme),
ProcessWhereExp('package_name', OraPath.aPackage),
ProcessWhereExp('object_name', OraPath.aObject)]);
Query.Execute;
while not (Query.Eof) do
begin
with Params.Add() do
begin
ParamType := ParamTypeOraToDa(Query.Field(0), Query.Field(2));
Name := HandleSqlName(Query.Field(0), ParamType);
DataType := VCLTypeToDAType(DataTypeOraToVcl(Query.Field(1),
Query.Field(5)));
Size := Query.Field(4);
end;
Query.Next;
end;
finally
Query.Close;
Query.Free;
end;
end;
procedure AddStrings(Base, Addition: IROStrings);
var
I: Integer;
begin
for I := 0 to Addition.Count - 1 do
Base.Add(Addition[I]);
end;
{ INTERNAL CLASSES *********************************************************** }
{
*************************** TDADOAInternalConnection ***************************
}
constructor TDADOAInternalConnection.Create(AOwner: TComponent);
begin
inherited;
fOracleSession := TOracleSession.Create(nil);
end;
destructor TDADOAInternalConnection.Destroy;
begin
fOracleSession.Free;
inherited;
end;
procedure TDADOAInternalConnection.DoConnect;
begin
fOracleSession.LogOn;
end;
procedure TDADOAInternalConnection.DoDisconnect;
begin
fOracleSession.LogOff;
end;
function TDADOAInternalConnection.GetConnected: Boolean;
begin
Result := fOracleSession.Connected;
end;
{ PUBLIC CLASSES ************************************************************* }
{
******************************** TDAEDOADriver *********************************
}
// -----------------------------------------------------------------------------
// TDAEDOADriver.DoSetTraceOptions
//
// Tracing can only be enabled when DOA Version 4.0 or higher is used.
// UKO 26.09.2003 21:14:47
//
procedure TDAEDOADriver.DoSetTraceOptions(TraceActive: Boolean; TraceOptions:
TDATraceOptions; Callback: TDALogTraceEvent);
begin
inherited;
if TraceActive then
begin
fTraceCallBack := Callback;
{$IFDEF DOA4}
EnableMonitor;
{$ENDIF}
end
else
begin
fTraceCallBack := nil;
{$IFDEF DOA4}
DisableMonitor;
{$ENDIF}
end;
end;
procedure TDAEDOADriver.GetAuxParams(const AuxDriver: string;
out List: IROStrings);
begin
inherited;
List.Add('SysObjects=0,1');
end;
// -----------------------------------------------------------------------------
// TDAEDOADriver.GetAvailableDriverOptions
//
// Only Database, Login and Custom needed. doServerName is not needed !
//
// UKO 25.09.2003 17:51:31
//
function TDAEDOADriver.GetAvailableDriverOptions: TDAAvailableDriverOptions;
begin
Result := [doDatabaseName, doLogin, doCustom];
end;
function TDAEDOADriver.GetConnectionClass: TDAEConnectionClass;
begin
Result := TDAEDOAConnection;
end;
function TDAEDOADriver.GetDefaultCustomParameters: string;
begin
Result := 'SysObjects=0';
end;
function TDAEDOADriver.GetDescription: string;
begin
Result := 'Direct Oracle Access Driver';
end;
function TDAEDOADriver.GetDriverID: string;
begin
Result := 'DOA';
end;
// -----------------------------------------------------------------------------
// TDAEDOADriver.GetMajVersion
//
// UKO 25.09.2003 17:45:47
//
function TDAEDOADriver.GetMajVersion: byte;
begin
Result := 1;
end;
// -----------------------------------------------------------------------------
// TDAEDOADriver.GetMinVersion
//
// UKO 25.09.2003 17:45:49
//
function TDAEDOADriver.GetMinVersion: byte;
begin
Result := 1;
end;
{
****************************** TDAEDOAConnection *******************************
}
function TDAEDOAConnection.CreateCustomConnection: TCustomConnection;
begin
Result := TDADOAInternalConnection.Create(nil);
end;
// -----------------------------------------------------------------------------
// TDAEDOAConnection.CreateMacroProcessor
//
// UKO 25.09.2003 18:43:06
//
function TDAEDOAConnection.CreateMacroProcessor: TDASQLMacroProcessor;
begin
result := TOracleMacroProcessor.Create;
end;
// -----------------------------------------------------------------------------
// TDAEDOAConnection.DoApplyConnectionString
//
// Use Database instead of Server. Server has no meaning in Oracle
// UKO 25.09.2003 17:54:25
//
procedure TDAEDOAConnection.DoApplyConnectionString(aConnStrParser: TDAConnectionStringParser; aConnectionObject: TCustomConnection);
begin
inherited;
with aConnStrParser do begin
fUserName := UpperCase(UserID);
OracleSession.LogonDatabase := Database;
OracleSession.LogonUsername := fUserName;
OracleSession.LogonPassword := Password;
fSchema := fUserName;
fSysObjects := AuxParams['SysObjects'] = '1';
end;
end;
function TDAEDOAConnection.DoBeginTransaction: Integer;
begin
// DOA doesn't have any special transaction starting routines
Result := 0;
end;
procedure TDAEDOAConnection.DoCommitTransaction;
begin
OracleSession.Commit;
end;
procedure TDAEDOAConnection.DoGetForeignKeys(
out ForeignKeys: TDADriverForeignKeyCollection);
type
TFKRec =
record
TableName: string;
ConstraintName: string;
ReferenzContraintName: string;
ReferenzOwner: string;
end;
var
lReferenzTable: string;
lQuery: TOracleQuery;
lColumns: string;
lFKArray: array of TFKRec;
lIndex: integer;
lfv: integer;
const
SQL =
'SELECT constraint_name, table_name, r_owner, r_constraint_name FROM all_constraints' + #13#10 +
'WHERE owner = ''%s''' + #13#10 +
'AND constraint_type = ''R''';
begin
inherited; // creates an empty collection
OracleSession.LogOn;
lQuery := TOracleQuery.Create(nil);
try
lQuery.Session := OracleSession;
lQuery.SQL.Text := Format(SQL, [Uppercase(OracleSession.LogonUsername)]);
lQuery.Execute;
lIndex := 0;
while not (lQuery.Eof) do
begin
SetLength(lFKArray, lIndex+1);
lFKArray[lIndex].ConstraintName := lQuery.FieldAsString('CONSTRAINT_NAME');
lFKArray[lIndex].TableName := lQuery.FieldAsString('TABLE_NAME');
lFKArray[lIndex].ReferenzOwner := lQuery.FieldAsString('R_OWNER');
lFKArray[lIndex].ReferenzContraintName := lQuery.FieldAsString('R_CONSTRAINT_NAME');
inc(lIndex);
lQuery.Next;
end;
finally
lQuery.Free;
end;
if lIndex > 0 then
begin
for lfv := 0 to Length(lFKArray)-1 do
begin
with ForeignKeys.Add() do
begin
GetConstraintColumnsAsString(Uppercase(OracleSession.LogonUsername), lFKArray[lfv].ConstraintName, lColumns);
FKTable := lFKArray[lfv].TableName;
FKField := lColumns;
lReferenzTable := GetConstraintColumnsAsString(lFKArray[lfv].ReferenzOwner, lFKArray[lfv].ReferenzContraintName, lColumns);
PKTable := lReferenzTable;
PKField := lColumns;
end;
end;
end;
end;
procedure TDAEDOAConnection.DoGetStoredProcedureNames(out List: IROStrings);
begin
List := EncodeSchema(fUserName, fSchema, GetStoredProcsInPackages(fSchema));
if fSysObjects then
begin
AddStrings(List, EncodeSchema(fUserName, 'SYS', GetStoredProcsInPackages('SYS')));
AddStrings(List, EncodeSchema(fUserName, 'SYSTEM', GetStoredProcsInPackages('SYSTEM')));
end;
AddStrings(List, GetEncodedObjects(' (object_type = ''FUNCTION'' or object_type = ''PROCEDURE'')'));
end;
procedure TDAEDOAConnection.DoGetStoredProcedureParams(const
aStoredProcedureName: string; out Params: TDAParamCollection);
begin
OracleSession.LogOn;
GetStoredProcParams(OracleSession, aStoredProcedureName, Params);
end;
procedure TDAEDOAConnection.DoGetTableFields(const aTableName: string; out
Fields: TDAFieldCollection);
var
Query: TOracleQuery;
OraPath: TOraPath;
PrimaryKey: IROStrings;
const
SQL = 'SELECT atc.column_name, atc.data_type, atc.data_length, atc.data_scale, atc.nullable, acc.comments' + #13#10 +
'FROM all_tab_columns atc, all_col_comments acc' + #13#10 +
'WHERE atc.owner = ''%s''' + #13#10 +
'AND atc.table_name = ''%s''' + #13#10 +
'AND acc.owner= atc.OWNER' + #13#10 +
'AND acc.table_name=atc.TABLE_NAME' + #13#10 +
'AND acc.column_name=atc.COLUMN_NAME';
begin
OracleSession.LogOn;
Fields := TDAFieldCollection.Create(nil);
Query := TOracleQuery.Create(nil);
try
OraPath := ExtractOraPath(aTableName, OracleSession.LogonUsername);
PrimaryKey := GetPrimaryKeys(OraPath.aScheme, OraPath.aObject);
Query.Session := OracleSession;
Query.SQL.Text := Format(SQL, [OraPath.aScheme, OraPath.aObject]);
Query.Execute;
// if Query.Eof then ????? UKO 10.09.2003
while not Query.Eof do
begin
with Fields.Add() do
begin
Name := Query.Field(0);
InPrimaryKey := (PrimaryKey.IndexOf(Name) > -1);
DataType := VCLTypeToDAType(DataTypeOraToVcl(Query.Field(1),
Query.Field(3)));
Size := Query.Field(2);
// UKO 17.09.2004 get additional information
Required := (Query.FieldAsString(4) = 'N');
Description := Query.FieldAsString(5);
// TODO: Defaultvalue
end;
Query.Next;
end;
Query.Close;
finally
Query.Free;
end;
end;
procedure TDAEDOAConnection.DoGetTableNames(out List: IROStrings);
begin
List := GetEncodedObjects(' (object_type = ''TABLE'')');
end;
procedure TDAEDOAConnection.DoGetViewFields(const aViewName: string; out
Fields: TDAFieldCollection);
begin
DoGetTableFields(aViewName, Fields);
end;
procedure TDAEDOAConnection.DoGetViewNames(out List: IROStrings);
begin
List := GetEncodedObjects(' (object_type = ''VIEW'')');
end;
procedure TDAEDOAConnection.DoRollbackTransaction;
begin
TOracleSession(inherited ConnectionObject).Rollback;
end;
function TDAEDOAConnection.EncodeSchema(const Username, Schema: string;
Contents: IROStrings): IROStrings;
var
I: Integer;
begin
Result := Contents;
if Username <> Schema then // scheme only when different then user UKO 25.09.2003
for I := 0 to Result.Count - 1 do
Result[I] := Schema + '.' + Result[I];
end;
function TDAEDOAConnection.GetConstraintColumnsAsString(const AOwner,
AConstraintName: string; out AColumns: string): string;
var
Query: TOracleQuery;
const
SQL =
'SELECT Table_name, Column_Name FROM All_Cons_Columns' + #13#10 +
'WHERE owner = ''%s''' + #13#10 +
'AND constraint_name = ''%s''' + #13#10 +
'ORDER BY position';
begin
Result := '';
AColumns := '';
OracleSession.LogOn;
Query := TOracleQuery.Create(nil);
try
Query.Session := OracleSession;
Query.SQL.Text := Format(SQL, [AOwner, AConstraintName]);
Query.Execute;
while not (Query.Eof) do
begin
Result := Query.FieldAsString('TABLE_NAME');
AColumns := AColumns + Query.FieldAsString('COLUMN_NAME');
Query.Next;
if not Query.Eof then
AColumns := AColumns + ',';
end;
Query.Close;
finally
Query.Free;
end;
end;
function TDAEDOAConnection.GetDataSetClass: TDAEDatasetClass;
begin
Result := TDAEDOAQuery;
end;
function TDAEDOAConnection.GetEncodedObjects(
WhereClause: string): IROStrings;
begin
Result := TROStrings.Create;
AddStrings(Result, EncodeSchema(fUserName, fSchema, GetObjects(fSchema, WhereClause)));
if fSysObjects then
begin
AddStrings(Result, EncodeSchema(fUserName, 'SYS', GetObjects('SYS', WhereClause)));
AddStrings(Result, EncodeSchema(fUserName, 'SYSTEM', GetObjects('SYSTEM', WhereClause)));
end;
end;
function TDAEDOAConnection.GetObjects(Schema, WhereClause: string): IROStrings;
var
Query: TOracleQuery;
const
SQL = 'select object_name as object' + NL +
'from all_objects where owner = ''%s'' and %s';
begin
Result := TROStrings.Create;
OracleSession.LogOn;
Query := TOracleQuery.Create(nil);
try
Query.Session := OracleSession;
Query.SQL.Text := Format(SQL, [Schema, WhereClause]);
Query.Execute;
while not (Query.Eof) do
begin
Result.Add(Query.Field(0));
Query.Next;
end;
Query.Close;
finally
Query.Free;
end;
end;
function TDAEDOAConnection.GetOracleSession: TOracleSession;
begin
Result := TDADOAInternalConnection(inherited ConnectionObject).Session;
end;
function TDAEDOAConnection.GetPrimaryKeys(const Schema,
TableName: string): IROStrings;
var
Query: TOracleQuery;
const
// this statement doesn<73>t work properly if the table is in more then one
// database users available (e.g. two different versions of the database user)
// In this case duplicated results are generated and performance decreases cause
// of a full table scan on obj$
// Solution: link also owner and tablename !
// UKO 23.09.2003
//
// SQL = 'select' + NL +
// ' a.column_name' + NL +
// 'from' + NL +
// ' all_cons_columns a, all_constraints b' + NL +
// 'where a.constraint_name = b.constraint_name' + NL +
// ' and b.constraint_type = ''P''' + NL +
// ' and b.owner = ''%s''' + NL +
// ' and b.table_name = ''%s''';
SQL = 'select' + NL +
' a.column_name' + NL +
'from' + NL +
' all_cons_columns a, all_constraints b' + NL +
'where a.owner = b.owner' + NL +
' and a.table_name = b.table_name' + NL +
' and a.constraint_name = b.constraint_name' + NL +
' and b.constraint_type = ''P''' + NL +
' and b.owner = ''%s''' + NL +
' and b.table_name = ''%s''';
begin
Result := TROStrings.Create;
Query := TOracleQuery.Create(nil);
try
Query.Session := OracleSession;
Query.SQL.Text := Format(SQL, [UpperCase(Schema), UpperCase(TableName)]);
Query.Execute;
while not (Query.Eof) do
begin
Result.Add(Query.Field(0));
Query.Next;
end;
finally
Query.Free;
end;
end;
function TDAEDOAConnection.GetStoredProcedureClass: TDAEStoredProcedureClass;
begin
Result := TDAEDOAStoredProcedure;
end;
// -----------------------------------------------------------------------------
// TDAEDOAConnection.GetStoredProcsInPackages
//
// UKO 25.09.2003 11:48:08
//
function TDAEDOAConnection.GetStoredProcsInPackages(Schema: string): IROStrings;
var
Query: TOracleQuery;
const
SQL = 'select distinct package_name || ''.'' || object_name as proc ' + NL +
'from all_arguments' + NL +
'where package_name is not null and owner = ''%s''';
begin
Result := TROStrings.Create;
OracleSession.LogOn;
Query := TOracleQuery.Create(nil);
try
Query.Session := OracleSession;
Query.SQL.Text := Format(SQL, [Schema]);
Query.Execute;
while not (Query.Eof) do
begin
Result.Add(Query.Field(0));
Query.Next;
end;
finally
Query.Close;
Query.Free;
end;
end;
// -----------------------------------------------------------------------------
// TDAEDOAConnection.IdentifierNeedsQuoting
//
// Default behavior not enough, as '$' and '.' are also a valid character which doesn<73>t need quoting
//
// UKO 25.09.2003 11:48:13
//
function TDAEDOAConnection.IdentifierNeedsQuoting(const iIdentifier: string): boolean;
var
i: integer;
begin
result := false;
if IdentifierIsQuoted(iIdentifier) then
exit;
for i := 1 to Length(iIdentifier) do
begin
if not (iIdentifier[i] in ['a'..'z', 'A'..'Z', '0'..'9', '_', '$', '.']) then
begin
result := true;
exit;
end;
end;
end;
{
********************************* TDAEDOAQuery *********************************
}
function TDAEDOAQuery.CreateDataset(aConnection: TDAEConnection): TDataset;
begin
Result := TOracleDataSet.Create(nil);
TOracleDataSet(Result).ReadOnly := True;
TOracleDataSet(Result).Session := TDAEDOAConnection(
aConnection).OracleSession;
end;
function TDAEDOAQuery.DoExecute: Integer;
begin
TOracleDataSet(DataSet).ExecSQL;
Result := -1;
end;
function TDAEDOAQuery.DoGetSQL: string;
begin
Result := TOracleDataSet(Dataset).SQL.Text;
end;
procedure TDAEDOAQuery.DoPrepare(Value: Boolean);
begin
TOracleDataSet(DataSet).Optimize := Value;
end;
procedure TDAEDOAQuery.DoSetSQL(const Value: string);
begin
TOracleDataSet(Dataset).SQL.Text := Value;
end;
function TDAEDOAQuery.GetLockMode: TOracleLockMode;
begin
Result := LockModeDoaToDa(TOracleDataSet(Dataset).LockingMode)
end;
function TDAEDOAQuery.GetOptions: TOracleOptions;
begin
// Can't be implemented
end;
procedure TDAEDOAQuery.GetParamValues(Params: TDAParamCollection);
begin
//
end;
function TDAEDOAQuery.LockModeDaToDoa(LockMode: TOracleLockMode):
TLockingModeOptions;
begin
Result := lmNone;
case LockMode of
olmLockImmediate: Result := lmLockImmediate;
olmLockDelayed: Result := lmLockDelayed;
end;
end;
function TDAEDOAQuery.LockModeDoaToDa(LockMode: TLockingModeOptions):
TOracleLockMode;
begin
Result := olmNone;
case LockMode of
lmLockImmediate: Result := olmLockImmediate;
lmLockDelayed: Result := olmLockDelayed;
end;
end;
procedure TDAEDOAQuery.SetLockMode(Value: TOracleLockMode);
begin
TOracleDataSet(Dataset).LockingMode := LockModeDaToDoa(Value);
end;
procedure TDAEDOAQuery.SetOptions(Value: TOracleOptions);
begin
// Can't be implemented
end;
procedure TDAEDOAQuery.SetParamValues(Params: TDAParamCollection);
begin
SetDataSetParams(Params, DataSet);
end;
{
**************************** TDAEDOAStoredProcedure ****************************
}
function TDAEDOAStoredProcedure.CreateDataset(aConnection: TDAEConnection):
TDataset;
begin
Result := TOracleDataSet.Create(nil);
TOracleDataSet(Result).Session := TDAEDOAConnection(
aConnection).OracleSession;
end;
procedure TDAEDOAStoredProcedure.DoGetParams;
var
Ds: TOracleDataSet;
I: Integer;
Params: TDAParamCollection;
begin
Params := GetParams;
Ds := TOracleDataSet(DataSet);
for I := 0 to Params.Count - 1 do
if Params[I].ParamType in [daptOutput, daptInputOutput, daptResult] then
Params[I].Value := Ds.GetVariable(HandleSqlName(Params[I].Name,
Params[I].ParamType));
end;
function TDAEDOAStoredProcedure.DoGetParamsResult: TDAParam;
var
I: Integer;
Params: TDAParamCollection;
begin
Result := nil;
Params := GetParams;
for I := 0 to Params.Count - 1 do
if Params[I].ParamType = daptResult then
begin
Result := Params[I];
Exit;
end;
end;
procedure TDAEDOAStoredProcedure.DoSetSource;
var
Ds: TOracleDataSet;
I: Integer;
Params: TDaParamCollection;
ParamResult: TDAParam;
ParamsExist: Boolean;
const
SQLHeader = 'declare' + NL +
' result boolean;' + NL +
'begin' + NL;
SQLHandleBoolean = ':result := sys.diutil.bool_to_int(function_result);';
SQLFooter = 'end;';
function CaseOfParam(const AParamResult: TDAParam): Integer;
begin
Result := 0;
if AParamResult <> nil then
if AParamResult.DataType = datBoolean then
Result := 1
else
Result := 2;
end;
function ConvertParam(const AName: string; const ADataType: TDADataType):
string;
begin
if ADataType = datBoolean then
begin
Result := Format('%s => sys.diutil.int_to_bool(:%s), ', [AName, AName]);
Exit;
end;
Result := Format('%s => :%s, ', [AName, AName]);
end;
function TrimSqlParams(const SQL: string): string;
var
S: string;
begin
S := SQL;
Delete(S, Length(S) - 3, 4);
Result := S;
end;
begin
Ds := TOracleDataSet(DataSet);
Params := GetParams;
ParamResult := DoGetParamsResult;
// PL/SQL Block - header + stored proc name
Ds.SQL.Text := SQLHeader;
case CaseOfParam(ParamResult) of // 0 = no result, 1 = boolean, 2 = misc
0: Ds.SQL.Add(Format(' %s(', [fProcedureName]));
1: Ds.SQL.Add(Format(' result := %s(', [fProcedureName]));
2: Ds.SQL.Add(Format(' :result := %s(', [fProcedureName]));
end;
// PL/SQL Block - params if any;
ParamsExist := False;
for I := 0 to Params.Count - 1 do
if (Params.Items[I] <> ParamResult) then
begin
ParamsExist := True;
Ds.SQL.Add(ConvertParam(Params[I].Name, Params[I].DataType));
end;
// PL/SQL Block - params - remove the last half-stop
if ParamsExist then
Ds.SQL.Text := TrimSQLParams(Ds.SQL.Text);
Ds.SQL.Add(');');
// PL/SQL Block - special treatment for functions with boolean results
if ParamResult.DataType = datBoolean then
Ds.SQL.Add(SQLHandleBoolean);
Ds.SQL.Add(SQLFooter);
end;
function TDAEDOAStoredProcedure.Execute: Integer;
var
Params: TDAParamCollection;
begin
Params := GetParams;
SetDataSetParams(Params, DataSet);
DoSetSource;
TOracleDataSet(DataSet).ExecSQL;
DoGetParams;
Result := -1;
end;
function TDAEDOAStoredProcedure.GetStoredProcedureName: string;
begin
Result := fProcedureName;
end;
procedure TDAEDOAStoredProcedure.RefreshParams;
var
OraParams, DaParams: TDAParamCollection;
begin
GetStoredProcParams(TOracleDataSet(DataSet).Session, fProcedureName,
OraParams);
DaParams := GetParams;
DaParams.AssignParamCollection(OraParams);
end;
procedure TDAEDOAStoredProcedure.SetParamValues(Params: TDAParamCollection);
begin
SetDataSetParams(Params, DataSet);
end;
procedure TDAEDOAStoredProcedure.SetStoredProcedureName(const Name: string);
begin
fProcedureName := Name;
end;
exports
GetDriverObject name func_GetDriverObject;
initialization
_Driver := nil;
RegisterDriverProc(GetDriverObject);
finalization
UnregisterDriverProc(GetDriverObject);
FreeAndNil(_Driver);
end.