New Sample DataPump

This commit is contained in:
Daniele Teti 2024-05-16 17:59:17 +02:00
parent cb01d14729
commit 7ce308b54f
9 changed files with 1520 additions and 14 deletions

View File

@ -328,8 +328,4 @@ object MainForm: TMainForm
TabOrder = 32 TabOrder = 32
OnClick = btnTransactionClick OnClick = btnTransactionClick
end end
object FDConnection1: TFDConnection
Left = 312
Top = 40
end
end end

View File

@ -42,7 +42,6 @@ type
btnMultiThreading: TButton; btnMultiThreading: TButton;
btnRQL: TButton; btnRQL: TButton;
btnReadOnlyFields: TButton; btnReadOnlyFields: TButton;
FDConnection1: TFDConnection;
btnNullTest: TButton; btnNullTest: TButton;
btnCRUDNoAutoInc: TButton; btnCRUDNoAutoInc: TButton;
btnCRUDWithStringPKs: TButton; btnCRUDWithStringPKs: TButton;
@ -839,13 +838,11 @@ procedure TMainForm.btnMultiThreadingClick(Sender: TObject);
var var
lTasks: TArray<ITask>; lTasks: TArray<ITask>;
lProc: TProc; lProc: TProc;
lConnParams: string;
begin begin
Log('** Multithreading test'); Log('** Multithreading test');
TMVCActiveRecord.DeleteRQL(TCustomer, TMVCActiveRecord.DeleteRQL(TCustomer,
'in(City,["Rome","New York","London","Melbourne","Berlin"])'); 'in(City,["Rome","New York","London","Melbourne","Berlin"])');
lConnParams := FDConnection1.Params.Text;
lProc := procedure lProc := procedure
var var
lCustomer: TCustomer; lCustomer: TCustomer;
@ -2335,7 +2332,7 @@ end;
procedure TMainForm.FormDestroy(Sender: TObject); procedure TMainForm.FormDestroy(Sender: TObject);
begin begin
ActiveRecordConnectionsRegistry.RemoveDefaultConnection(False); ActiveRecordConnectionsRegistry.RemoveDefaultConnection();
end; end;
procedure TMainForm.FormShow(Sender: TObject); procedure TMainForm.FormShow(Sender: TObject);
@ -2380,11 +2377,7 @@ begin
raise Exception.Create('Unknown RDBMS'); raise Exception.Create('Unknown RDBMS');
end; end;
FDConnection1.Params.Clear; ActiveRecordConnectionsRegistry.AddDefaultConnection(FDConnectionConfigU.CON_DEF_NAME);
FDConnection1.ConnectionDefName := FDConnectionConfigU.CON_DEF_NAME;
FDConnection1.Connected := True;
ActiveRecordConnectionsRegistry.AddDefaultConnection(FDConnection1);
Caption := Caption + ' (Curr Backend: ' + ActiveRecordConnectionsRegistry.GetCurrentBackend + ')'; Caption := Caption + ' (Curr Backend: ' + ActiveRecordConnectionsRegistry.GetCurrentBackend + ')';
{$IFDEF USE_SEQUENCES} {$IFDEF USE_SEQUENCES}
Caption := Caption + ' USE_SEQUENCES'; Caption := Caption + ' USE_SEQUENCES';

View File

@ -128,7 +128,8 @@ CREATE TABLE public.customers2 (
description character varying(200), description character varying(200),
city character varying(200), city character varying(200),
note text, note text,
rating integer rating integer,
last_contact_timestamp timestamptz NULL
); );
ALTER TABLE public.customers2 OWNER TO postgres; ALTER TABLE public.customers2 OWNER TO postgres;

View File

@ -0,0 +1,39 @@
unit CustomerEntityU;
interface
uses
MVCFramework.ActiveRecord, MVCFramework.Nullables;
type
[MVCTable('customers')]
TCustomer = class(TMVCActiveRecord)
private
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
fID: NullableInt64;
[MVCTableField('code')]
fCode: NullableString;
[MVCTableField('description')]
fCompanyName: NullableString;
[MVCTableField('city')]
fCity: string;
[MVCTableField('last_contact_timestamp')]
fLastContact: NullableTDateTime;
[MVCTableField('rating')]
fRating: NullableInt32;
[MVCTableField('note')]
fNote: string;
public
property ID: NullableInt64 read fID write fID;
property Code: NullableString read fCode write fCode;
property CompanyName: NullableString read fCompanyName write fCompanyName;
property City: string read fCity write fCity;
property LastContact: NullableTDateTime read fLastContact write fLastContact;
property Rating: NullableInt32 read fRating write fRating;
property Note: string read fNote write fNote;
end;
implementation
end.

View File

@ -0,0 +1,16 @@
program DataPumpSample;
uses
Vcl.Forms,
MainFormU in 'MainFormU.pas' {MainForm},
FDConnectionConfigU in 'FDConnectionConfigU.pas',
CustomerEntityU in 'CustomerEntityU.pas';
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,226 @@
unit FDConnectionConfigU;
interface
const
CON_DEF_NAME = 'MyConnX';
procedure CreateFirebirdPrivateConnDef(AIsPooled: boolean);
procedure CreateInterbasePrivateConnDef(AIsPooled: boolean);
procedure CreateMySQLPrivateConnDef(AIsPooled: boolean);
procedure CreateMSSQLServerPrivateConnDef(AIsPooled: boolean);
procedure CreatePostgresqlPrivateConnDef(AIsPooled: boolean; ConDefName: String = CON_DEF_NAME);
procedure CreateSqlitePrivateConnDef(AIsPooled: boolean; ConDefName: String = CON_DEF_NAME);
implementation
uses
System.Classes,
System.IOUtils,
FireDAC.Comp.Client,
FireDAC.Moni.Base,
FireDAC.Moni.FlatFile,
FireDAC.Stan.Intf
;
var
gFlatFileMonitor: TFDMoniFlatFileClientLink = nil;
procedure CreateMySQLPrivateConnDef(AIsPooled: boolean);
var
LParams: TStringList;
begin
{
docker run --detach --env MARIADB_USER=example-user --env MARIADB_PASSWORD=my_cool_secret --env MARIADB_ROOT_PASSWORD=root -p 3306:3306 mariadb:latest
}
LParams := TStringList.Create;
try
LParams.Add('Database=activerecorddb');
LParams.Add('Protocol=TCPIP');
LParams.Add('Server=localhost');
LParams.Add('User_Name=root');
LParams.Add('Password=root');
LParams.Add('TinyIntFormat=Boolean'); { it's the default }
LParams.Add('CharacterSet=utf8mb4'); // not utf8!!
LParams.Add('MonitorBy=FlatFile');
if AIsPooled then
begin
LParams.Add('Pooled=True');
LParams.Add('POOL_MaximumItems=100');
end
else
begin
LParams.Add('Pooled=False');
end;
FDManager.AddConnectionDef(CON_DEF_NAME, 'MySQL', LParams);
finally
LParams.Free;
end;
end;
procedure CreateMSSQLServerPrivateConnDef(AIsPooled: boolean);
var
LParams: TStringList;
begin
{
docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=!SA_password!" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest
}
// [ACTIVERECORDB_SQLSERVER]
// Database=activerecorddb
// OSAuthent=Yes
// Server=DANIELETETI\SQLEXPRESS
// DriverID=MSSQL
//
LParams := TStringList.Create;
try
LParams.Add('Database=activerecorddb');
LParams.Add('OSAuthent=Yes');
LParams.Add('Server=DANIELETETI\SQLEXPRESS');
if AIsPooled then
begin
LParams.Add('Pooled=True');
LParams.Add('POOL_MaximumItems=100');
end
else
begin
LParams.Add('Pooled=False');
end;
FDManager.AddConnectionDef(CON_DEF_NAME, 'MSSQL', LParams);
finally
LParams.Free;
end;
end;
procedure CreateFirebirdPrivateConnDef(AIsPooled: boolean);
var
LParams: TStringList;
begin
LParams := TStringList.Create;
try
LParams.Add('Database=' + TPath.GetFullPath(TPath.Combine('..\..',
'data\ACTIVERECORDDB.FDB')));
LParams.Add('Protocol=TCPIP');
LParams.Add('Server=localhost');
LParams.Add('User_Name=sysdba');
LParams.Add('Password=masterkey');
LParams.Add('CharacterSet=UTF8');
if AIsPooled then
begin
LParams.Add('Pooled=True');
LParams.Add('POOL_MaximumItems=100');
end
else
begin
LParams.Add('Pooled=False');
end;
FDManager.AddConnectionDef(CON_DEF_NAME, 'FB', LParams);
finally
LParams.Free;
end;
end;
procedure CreateInterbasePrivateConnDef(AIsPooled: boolean);
var
LParams: TStringList;
begin
LParams := TStringList.Create;
try
LParams.Add('Database=' + TPath.GetFullPath(TPath.Combine('..\..',
'data\ACTIVERECORDDB.IB')));
LParams.Add('Protocol=TCPIP');
LParams.Add('Server=localhost');
LParams.Add('User_Name=sysdba');
LParams.Add('Password=masterkey');
LParams.Add('CharacterSet=UTF8');
if AIsPooled then
begin
LParams.Add('Pooled=True');
LParams.Add('POOL_MaximumItems=100');
end
else
begin
LParams.Add('Pooled=False');
end;
FDManager.AddConnectionDef(CON_DEF_NAME, 'IB', LParams);
finally
LParams.Free;
end;
end;
procedure CreatePostgresqlPrivateConnDef(AIsPooled: boolean; ConDefName: String);
var
LParams: TStringList;
begin
LParams := TStringList.Create;
try
LParams.Add('Database=activerecorddb');
LParams.Add('Protocol=TCPIP');
LParams.Add('Server=localhost');
LParams.Add('User_Name=postgres');
LParams.Add('Password=postgres');
LParams.Add('MonitorBy=FlatFile');
// https://quality.embarcadero.com/browse/RSP-19755?jql=text%20~%20%22firedac%20guid%22
LParams.Add('GUIDEndian=Big');
if AIsPooled then
begin
LParams.Add('Pooled=True');
LParams.Add('POOL_MaximumItems=100');
end
else
begin
LParams.Add('Pooled=False');
end;
FDManager.AddConnectionDef(ConDefName, 'PG', LParams);
finally
LParams.Free;
end;
end;
procedure CreateSqlitePrivateConnDef(AIsPooled: Boolean; ConDefName: String);
var
LParams: TStringList;
lFName: string;
begin
LParams := TStringList.Create;
try
lFName := TPath.Combine(TPath.GetDirectoryName(ParamStr(0)),
'..\..\data\activerecorddb.db');
LParams.Add('Database=' + lFName);
LParams.Add('StringFormat=Unicode');
if AIsPooled then
begin
LParams.Add('Pooled=True');
LParams.Add('POOL_MaximumItems=100');
end
else
begin
LParams.Add('Pooled=False');
end;
FDManager.AddConnectionDef(ConDefName, 'SQLite', LParams);
finally
LParams.Free;
end;
end;
initialization
gFlatFileMonitor := TFDMoniFlatFileClientLink.Create(nil);
gFlatFileMonitor.FileColumns := [tiRefNo, tiTime, tiThreadID, tiClassName, tiObjID, tiMsgText];
gFlatFileMonitor.EventKinds := [
ekVendor, ekConnConnect, ekLiveCycle, ekError, ekConnTransact,
ekCmdPrepare, ekCmdExecute, ekCmdDataIn, ekCmdDataOut];
gFlatFileMonitor.ShowTraces := False;
gFlatFileMonitor.FileAppend := False;
gFlatFileMonitor.FileName := TPath.ChangeExtension(ParamStr(0), '.trace.log');
gFlatFileMonitor.Tracing := True;
finalization
gFlatFileMonitor.Free;
end.

View File

@ -0,0 +1,31 @@
object MainForm: TMainForm
Left = 0
Top = 0
Caption = 'Data Pump With MVCActiveRecord Sample'
ClientHeight = 64
ClientWidth = 425
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Segoe UI'
Font.Style = []
OnCreate = FormCreate
TextHeight = 15
object Label1: TLabel
Left = 16
Top = 24
Width = 211
Height = 15
Caption = 'Migrate data from SQLite to PostgreSQL'
end
object btnDataPump: TButton
Left = 336
Top = 20
Width = 81
Height = 25
Caption = 'Data Pump'
TabOrder = 0
OnClick = btnDataPumpClick
end
end

View File

@ -0,0 +1,73 @@
unit MainFormU;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, FireDAC.UI.Intf,
FireDAC.VCLUI.Wait, FireDAC.Stan.Intf, FireDAC.Comp.UI;
type
TMainForm = class(TForm)
btnDataPump: TButton;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
procedure btnDataPumpClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
uses
FDConnectionConfigU, MVCFramework.ActiveRecord, CustomerEntityU,
MVCFramework.SQLGenerators.PostgreSQL, MVCFramework.SQLGenerators.Sqlite;
procedure TMainForm.btnDataPumpClick(Sender: TObject);
begin
// let's prepare connections giving them a name
ActiveRecordConnectionsRegistry.AddConnection('source', 'sqlitecon');
try
ActiveRecordConnectionsRegistry.AddConnection('destination', 'pgcon');
try
// from now on, in this thread, current connection is "source"
ActiveRecordConnectionsRegistry.SetCurrent('source');
var lCustomers := TMVCActiveRecord.All<TCustomer>;
try
// from now on, in this thread, current connection is "destination"
ActiveRecordConnectionsRegistry.SetCurrent('destination');
begin var lTx := TMVCActiveRecord.UseTransactionContext; //use TransactionContext
for var lCustomer in lCustomers do
begin
lCustomer.InvalidateConnection; //set connection to the current one
lCustomer.Insert;
end;
end;
finally
lCustomers.Free;
end;
finally
ActiveRecordConnectionsRegistry.RemoveConnection('destination');
end;
finally
ActiveRecordConnectionsRegistry.RemoveConnection('source');
end;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
CreateSqlitePrivateConnDef(False, 'sqlitecon');
CreatePostgresqlPrivateConnDef(False, 'pgcon');
end;
end.