Repository URL to install this package:
|
Version:
3.2.0 ▾
|
{
This file is part of the Free Pascal run time library.
Copyright (c) 2007 by Michael Van Canneyt, member of the
Free Pascal development team
MS-SQL Server Data Dictionary Engine Implementation.
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
unit FPDDMSSQL;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, sqldb, fpdatadict, fpddsqldb, db;
Type
{ TFPDDMSSQLEngine }
TFPDDMSSQLEngine = Class(TFPDDSQLEngine)
Public
Function CreateDomainSQL(Domain : TDDDomainDef) : String; override;
end;
{ TSQLDBMSSQLDDEngine }
TSQLDBMSSQLDDEngine = Class(TSQLDBDDEngine)
Protected
Function CreateConnection(AConnectString : String) : TSQLConnection; override;
Public
Function ImportIndexes(Table : TDDTableDef) : Integer; override;
Function ImportSequences(Sequences : TDDSequenceDefs; List : TStrings; UpdateExisting : boolean) : Integer; override;
Function ImportDomains(Domains : TDDDomainDefs; List : TStrings; UpdateExisting : boolean) : Integer; override;
Function CreateSQLEngine : TFPDDSQLEngine; override;
Class function EngineCapabilities : TFPDDEngineCapabilities; override;
Class function Description : string; override;
Class function DBType : String; override;
end;
Procedure RegisterMSSQLDDEngine;
Procedure UnRegisterMSSQLDDEngine;
implementation
uses mssqlconn;
Procedure RegisterMSSQLDDEngine;
begin
RegisterDictionaryEngine(TSQLDBMSSQLDDEngine);
end;
Procedure UnRegisterMSSQLDDEngine;
begin
UnRegisterDictionaryEngine(TSQLDBMSSQLDDEngine);
end;
{ TSQLDBMSSQLDDEngine }
function TSQLDBMSSQLDDEngine.CreateConnection(AConnectString: String
): TSQLConnection;
begin
Result:=TMSSQLConnection.Create(Self);
end;
class function TSQLDBMSSQLDDEngine.EngineCapabilities: TFPDDEngineCapabilities;
begin
Result:=[ecImport, ecCreateTable, ecViewTable, ecTableIndexes,
ecRunQuery, ecRowsAffected, ecSequences, ecDomains];
end;
class function TSQLDBMSSQLDDEngine.Description: string;
begin
Result:='Microsoft SQL Server connection using SQLDB';
end;
class function TSQLDBMSSQLDDEngine.DBType: String;
begin
Result:='Microsoft SQL Server';
end;
function TSQLDBMSSQLDDEngine.ImportIndexes(Table: TDDTableDef): Integer;
const
SQL_Indexes = 'SELECT '+
' t.name AS TableName, '+
' ind.name AS IndexName, '+
' ind.index_id AS IndexId, '+
' ic.index_column_id AS ColumnId, '+
' col.name AS ColumnName, '+
' ind.is_unique AS IsUniqueIndex, '+
' ind.is_unique_constraint AS IsConstraint '+
'FROM '+
' sys.indexes ind ' +
' INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id '+
' INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id '+
' INNER JOIN sys.tables t ON ind.object_id = t.object_id '+
'WHERE '+
' t.name=:TableName '+
'ORDER BY '+
' t.name, ind.name, ind.index_id, ic.index_column_id ';
Var
Q : TSQLQuery;
FIndexName, FFieldName, FUnique, FConstraint : TField;
procedure BindIndexFields;
begin
FIndexName := Q.FieldByName ('IndexName');
FFieldName := Q.FieldbyName('ColumnName');
FUnique := Q.FieldByName('IsUniqueIndex');
FConstraint := Q.FieldByName('IsConstraint');
end;
function CreateIndex (AName, indexname: string) : TDDIndexDef;
var n, s : string;
begin
n := trim(AName);
if n = '' then
n := trim(indexname);
if trim (indexName) = '' then
indexname := AName;
result := Table.Indexes.AddIndex(n);
if FUnique.AsInteger<>0 then
result.Options:=[ixUnique];
end;
Var
FN,IndName : String;
IDD : TDDIndexDef;
begin
FN:='';
IndName:='';
IDD:=Nil;
Q:=CreateSQLQuery(Nil);
Q.SQL.text := SQL_Indexes;
Q.Params[0].AsString:=Table.TableName;
Q.Open;
try
BindIndexFields;
while not Q.Eof do
begin
if IndName<>FIndexName.AsString then
begin
if (IDD<>Nil) then
IDD.Fields:=FN;
IndName:=FIndexName.AsString;
IDD:=CreateIndex('',IndName);
FN:='';
end;
if FN<>'' then
FN:=FN+';';
FN:=FN+Trim(FFieldName.AsString);
Q.Next;
end;
if (IDD<>Nil) then
IDD.Fields:=FN;
finally
Q.Free;
end;
end;
function TSQLDBMSSQLDDEngine.ImportSequences(Sequences: TDDSequenceDefs;
List: TStrings; UpdateExisting: boolean): Integer;
const
SQL_Sequences = 'SELECT SEQUENCE_NAME, START_VALUE, INCREMENT FROM INFORMATION_SCHEMA.SEQUENCES';
Var
Q : TSQLQuery;
Seq : TDDSequenceDef;
n : string;
begin
result := 0;
Q:=CreateSQLQuery(Nil);
try
Q.Sql.Text := SQL_Sequences;
Q.Open;
try
while not Q.eof do
begin
n := trim(Q.Fields[0].AsString);
seq := Sequences.FindSequence(n);
if not assigned (Seq) then
Seq := Sequences.AddSequence(n)
else if not UpdateExisting then
Seq := nil;
if assigned (Seq) then
begin
Seq.StartValue := Round(Q.Fields[1].AsFloat);
Seq.Increment := Round(Q.Fields[2].AsFloat);
inc (result);
end;
Q.Next;
end;
finally
Q.CLose;
end;
finally
Q.Free;
end;
end;
function TSQLDBMSSQLDDEngine.ImportDomains(Domains: TDDDomainDefs;
List: TStrings; UpdateExisting: boolean): Integer;
const
SQL_Domains = 'SELECT * FROM INFORMATION_SCHEMA.DOMAINS';
Var
Q : TSQLQuery;
FName, FDomainName, FDomainDefault,
FCharLength, FPrecision, FScale, FDataType : TField;
procedure BindFields;
begin
FName := Q.fieldbyname('DOMAIN_NAME');
FDomainDefault := q.fieldbyname('DOMAIN_DEFAULT');
FCharLength := q.fieldbyname('CHARACTER_MAXIMUM_LENGTH');
FPrecision := q.fieldbyname('NUMERIC_PRECISION');
FScale := q.fieldbyname('NUMERIC_SCALE');
FDataType := q.fieldbyname('DATA_TYPE');
end;
function ImportDomain : boolean;
var Dom : TDDDomainDef;
n : string;
begin
n := trim(FName.AsString);
Dom := Domains.FindDomain(n);
if not assigned (Dom) then
Dom := Domains.AddDomain(n)
else if not UpdateExisting then
Dom := nil;
if assigned (Dom) then
begin
result := true;
Dom.FieldType := SQLDataTypeToFieldType(FDataType.AsString);
Dom.Precision := FPrecision.AsInteger;
if Dom.FieldType in [ftFloat, ftBcd, ftFmtBCD] then
Dom.Size := FScale.AsInteger
else if Dom.FieldType in [ftString, ftFixedChar] then
Dom.Size := FCharLength.AsInteger
else
Dom.Size := 0;
end
else
result := false;
end;
begin
result := 0;
Q:=CreateSQLQuery(Nil);
try
Q.Sql.Text := SQL_Domains;
Q.Open;
BindFields;
try
while not Q.eof do
begin
if ImportDomain then
inc (result);
Q.Next;
end;
finally
Q.CLose;
end;
finally
Q.Free;
end;
end;
function TSQLDBMSSQLDDEngine.CreateSQLEngine: TFPDDSQLEngine;
begin
Result:=TFPDDMSSQLEngine.Create;
end;
{ TFPDDMSSQLEngine }
function TFPDDMSSQLEngine.CreateDomainSQL(Domain: TDDDomainDef): String;
begin
Result:='CREATE TYPE '+Domain.DomainName+' FROM '+FieldTypeString(Domain.FieldType,Domain.Size,Domain.Precision);
if Domain.Required then
Result:=Result+' NOT NULL';
end;
end.