Inital commit with most of the completed code

This commit is contained in:
2026-04-29 12:49:11 -04:00
commit b693a68279
469 changed files with 45970 additions and 0 deletions

91
DataGenerator.pas Normal file
View File

@@ -0,0 +1,91 @@
unit DataGenerator;
interface
uses
System.Math,
System.SysUtils;
type
TDataGenerator = class
private
var FSeed: Integer;
var FEmailDomains: TArray<string>;
function GenerateRandomString(ALength:Integer): string;
public
constructor Create(seed:Integer);
destructor Destroy; override;
function GenerateRandomEmail: string;
function GenerateRandomAge: Integer;
function GenerateRandomSocial: string;
end;
implementation
constructor TDataGenerator.Create(seed: Integer);
begin
FSeed := seed;
RandSeed := FSeed;
FEmailDomains := ['@proton.me',
'@protonmail.com',
'@gmail.com',
'@outlook.com',
'@live.kutztown.edu',
'@kutztown.edu',
'@hotmail.com',
'@yahoo.com',
'@aol.com'];
end;
destructor TDataGenerator.Destroy;
begin
end;
function TDataGenerator.GenerateRandomString(ALength: Integer): string;
begin
const
AllowedChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
var
LIndex: Integer;
SetLength(Result, ALength);
for LIndex := 1 to ALength do
begin
Result[LIndex] := AllowedChars[Random(Length(AllowedChars)) + 1];
end;
end;
function TDataGenerator.GenerateRandomEmail: string;
begin
var LDomain: string;
var LDomainIndex: Integer;
LDomainIndex := RandomRange(0, Length(FEmailDomains));
LDomain := FEmailDomains[LDomainIndex];
Result := GenerateRandomString(32) + LDomain;
end;
function TDataGenerator.GenerateRandomSocial: string;
begin
var LFirstThree: Integer;
var LMiddleTwo: Integer;
var LLastThree: Integer;
LFirstThree := RandomRange(100, 1000);
LMiddleTwo := RandomRange(10, 100);
LLastThree := RandomRange(100, 1000);
Result := '';
Result := LFirstThree.ToString + '-' + LMiddleTwo.ToString + '-' + LLastThree.ToString;
end;
function TDataGenerator.GenerateRandomAge: Integer;
begin
Result := RandomRange(1, 102);
end;
end.

303
DatabaseTestExecutor.pas Normal file
View File

@@ -0,0 +1,303 @@
unit DatabaseTestExecutor;
interface
uses
System.SysUtils,
System.Diagnostics,
ZConnection,
ZDataset,
ZExceptions,
DataGenerator;
type
TDatabaseManager = class
private
FConnection: TZConnection;
FDataGenerator: TDataGenerator;
FSeed: Integer;
FStopwatch: TStopwatch;
FUseEncryptionProxy: Boolean;
FGeneratedEmails: TArray<string>;
FGeneratedSocials: TArray<string>;
FGeneratedAges: TArray<Integer>;
function PerformSingleInsert(APrimaryKey: Integer): Double;
function PerformSingleRead(APrimaryKey: Integer): Double;
function PerformSingleReadByEmail(const AEmail: string): Double;
function PerformSingleReadBySocial(const ASocial: string): Double;
public
constructor Create(AConnection:TZConnection; ASeed:Integer; AUseEncryptionProxy: Boolean);
destructor Destroy; override;
function SetupDatabase: Boolean;
function TestInserts(ACount:Integer): TArray<Double>;
function TestReads(ACount:Integer): TArray<Double>;
function TestReadsByEmail: TArray<Double>;
function TestReadsBySocial: TArray<Double>;
end;
implementation
constructor TDatabaseManager.Create(AConnection:TZConnection; ASeed:Integer; AUseEncryptionProxy: Boolean);
begin
FSeed := ASeed;
FUseEncryptionProxy := AUseEncryptionProxy;
FConnection := AConnection;
FDataGenerator := TDataGenerator.Create(FSeed);
FStopwatch := TStopwatch.Create;
FGeneratedEmails := TArray<string>.Create();
FGeneratedSocials := TArray<string>.Create();
FGeneratedAges := TArray<Integer>.Create();
end;
destructor TDatabaseManager.Destroy;
begin
FreeAndNil(FDataGenerator);
end;
function TDatabaseManager.SetupDatabase: Boolean;
begin
var Query: TZQuery;
Query := TZQuery.Create(nil);
Query.Connection := FConnection;
Query.Sql.Add('DROP TABLE IF EXISTS users');
try
Query.ExecSQL;
except
on E: EZSQLException do
begin
Exit(False);
end;
end;
Query.SQL.Clear;
// We need to create the test table in a specific way if
// we are going to run the command through the proxy
if FUseEncryptionProxy then
begin
Query.SQL.Add('CREATE TABLE IF NOT EXISTS users (id INT PRIMARY KEY, email eql_v2_encrypted, social_security_number eql_v2_encrypted, age eql_v2_encrypted);');
// When using cipher stash we need to do some configuration
// on the table to enable each type of search we want to be able to
// do
Query.SQL.Add('SELECT eql_v2.add_search_config(''users'', ''email'', ''unique'', ''text'');');
Query.SQL.Add('SELECT eql_v2.add_search_config(''users'', ''social_security_number'', ''unique'', ''text'');');
end
else
begin
Query.SQL.Add('CREATE TABLE IF NOT EXISTS users (id INT PRIMARY KEY, email VARCHAR(255), social_security_number VARCHAR(255), age INT);');
end;
try
try
Query.ExecSQL;
except
on E: EZSQLException do
begin
Exit(False);
end
end;
finally
FreeAndNil(Query);
end;
Result := True;
end;
function TDatabaseManager.PerformSingleInsert(APrimaryKey: Integer): Double;
begin
var LEmail: string;
LEmail := FDataGenerator.GenerateRandomEmail;
FGeneratedEmails := FGeneratedEmails + [LEmail];
var LSocial: string;
LSocial := FDataGenerator.GenerateRandomSocial;
FGeneratedSocials := FGeneratedSocials + [LSocial];
var LAge: Integer;
LAge := FDataGenerator.GenerateRandomAge;
FGeneratedAges := FGeneratedAges + [LAge];
var LQuery: TZQuery;
try
LQuery := TZQuery.Create(nil);
LQuery.Connection := FConnection;
LQuery.SQL.Add('INSERT INTO users (id, email, social_security_number, age) ' +
'VALUES (:id, :email, :ssn, :age)');
LQuery.ParamByName('id').AsInteger := APrimaryKey;
LQuery.ParamByName('email').AsString := LEmail;
LQuery.ParamByName('ssn').AsString := LSocial;
LQuery.ParamByName('age').AsInteger := LAge;
FStopwatch := TStopwatch.StartNew;
try
LQuery.ExecSQL;
except
on E: EZSQLException do
begin
Exit(-1.0);
end
end;
finally
FreeAndNil(LQuery);
end;
FStopwatch.Stop;
Result := FStopwatch.Elapsed.TotalMilliseconds;
end;
function TDatabaseManager.PerformSingleRead(APrimaryKey: Integer): Double;
begin
var LQuery: TZQuery;
try
LQuery := TZQuery.Create(nil);
LQuery.Connection := FConnection;
LQuery.SQL.Add('SELECT id, email, social_security_number, age FROM users WHERE id = :id');
LQuery.ParamByName('id').AsInteger := APrimaryKey;
FStopwatch := TStopwatch.StartNew;
try
LQuery.Open;
except
on E: EZSQLException do
begin
Exit(-1.0);
end
end;
finally
FreeAndNil(LQuery);
end;
FStopwatch.Stop;
Result := FStopwatch.Elapsed.TotalMilliseconds;
end;
function TDatabaseManager.TestReads(ACount: Integer):Tarray<Double>;
begin
Result := TArray<Double>.Create();
var LIndex: Integer;
for LIndex := 1 to ACount do
begin
var LRunResult := PerformSingleRead(LIndex);
if LRunResult <> -1.0 then
Result := Result + [LRunResult];
end;
end;
function TDatabaseManager.PerformSingleReadByEmail(const AEmail: string): Double;
begin
var LQuery: TZQuery;
try
LQuery := TZQuery.Create(nil);
LQuery.Connection := FConnection;
LQuery.SQL.Add('SELECT id, email, social_security_number, age FROM users WHERE email = :email');
LQuery.ParamByName('email').AsString := AEmail;
FStopwatch := TStopwatch.StartNew;
try
LQuery.Open;
except
on E: EZSQLException do
begin
Exit(-1.0);
end
end;
finally
FreeAndNil(LQuery);
end;
FStopwatch.Stop;
Result := FStopwatch.Elapsed.TotalMilliseconds;
end;
function TDatabaseManager.PerformSingleReadBySocial(const ASocial: string): Double;
begin
var LQuery: TZQuery;
try
LQuery := TZQuery.Create(nil);
LQuery.Connection := FConnection;
LQuery.SQL.Add('SELECT id, email, social_security_number, age FROM users WHERE social_security_number = :ssn');
LQuery.ParamByName('ssn').AsString := ASocial;
FStopwatch := TStopwatch.StartNew;
try
LQuery.Open;
except
on E: EZSQLException do
begin
Exit(-1.0);
end
end;
finally
FreeAndNil(LQuery);
end;
FStopwatch.Stop;
Result := FStopwatch.Elapsed.TotalMilliseconds;
end;
function TDatabaseManager.TestReadsByEmail: TArray<Double>;
begin
Result := TArray<Double>.Create();
var LEmail: string;
for LEmail in FGeneratedEmails do
begin
var LRunResult := PerformSingleReadByEmail(LEmail);
if LRunResult <> -1.0 then
Result := Result + [LRunResult];
end;
end;
function TDatabaseManager.TestReadsBySocial: TArray<Double>;
begin
Result := TArray<Double>.Create();
var LSocial: string;
for LSocial in FGeneratedSocials do
begin
var LRunResult := PerformSingleReadBySocial(LSocial);
if LRunResult <> -1.0 then
Result := Result + [LRunResult];
end;
end;
function TDatabaseManager.TestInserts(ACount: Integer): TArray<Double>;
begin
SetLength(FGeneratedEmails, 0);
SetLength(FGeneratedSocials, 0);
SetLength(FGeneratedAges, 0);
Result := TArray<Double>.Create();
var Index: Integer;
for Index := 1 to ACount do
begin
var RunResult := PerformSingleInsert(Index);
if RunResult <> -1.0 then
Result := Result + [RunResult];
end;
end;
end.

1116
EncryptedDatabaseTest.dproj Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<BorlandProject>
<Transactions>
<Transaction>2026/04/22 20:29:14.000.105,=C:\Users\Vincent\Documents\Embarcadero\Studio\Projects\555FinalProject\Unit1.pas</Transaction>
<Transaction>2026/04/22 20:29:24.000.377,C:\Users\Vincent\Documents\Embarcadero\Studio\Projects\555FinalProject\DataGenerator.pas=C:\Users\Vincent\Documents\Embarcadero\Studio\Projects\555FinalProject\Unit1.pas</Transaction>
<Transaction>2026/04/23 13:47:05.000.958,C:\Users\Vincent\Documents\Embarcadero\Studio\Projects\555FinalProject\TestDatabaseManager.pas=C:\Users\Vincent\Documents\Embarcadero\Studio\Projects\555FinalProject\DatabaseTestExecutor.pas</Transaction>
</Transactions>
</BorlandProject>

Binary file not shown.

BIN
EncryptedDatabaseTest.res Normal file

Binary file not shown.

View File

@@ -0,0 +1,2 @@
<?xml version="1.0"?>
<TgConfig Version="3" SubLevelDisabled="False" />

210
Main.dpr Normal file
View File

@@ -0,0 +1,210 @@
program Main;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Math,
System.Classes,
ZConnection,
ZDataset,
DatabaseTestExecutor in 'DatabaseTestExecutor.pas',
DataGenerator in 'DataGenerator.pas';
function GetStringArg(const ASwitch, ADefault: string): string;
begin
if not FindCmdLineSwitch(ASwitch, Result, True) then
Result := ADefault;
end;
function GetIntArg(const ASwitch: string; ADefault: Integer): Integer;
begin
var LStrValue: string;
if FindCmdLineSwitch(ASwitch, LStrValue, True) then
Result := StrToIntDef(LStrValue, ADefault)
else
Result := ADefault;
end;
procedure WriteResultsToCSV(const AFileName, AActionType: string; const ATimes: TArray<Double>);
begin
var LFileExists: Boolean;
LFileExists := FileExists(AFileName);
var LWriter: TStreamWriter;
LWriter := TStreamWriter.Create(AFileName, True); // True enables Append mode
try
if not LFileExists then
LWriter.WriteLine('actiontype,value');
var LTime: Double;
for LTime in ATimes do
begin
LWriter.WriteLine(AActionType + ',' + FloatToStr(LTime));
end;
finally
LWriter.Free;
end;
end;
var
LConnection: TZConnection;
begin
var LHost: string;
LHost := GetStringArg('host', 'localhost');
var LPort: Integer;
LPort := GetIntArg('port', 5433);
var LDatabase: string;
LDatabase := GetStringArg('db', 'test_db');
var LUser: string;
LUser := GetStringArg('user', 'postgres');
var LPassword: string;
LPassword := GetStringArg('pass', 'postgres');
var LSeed: Integer;
LSeed := GetIntArg('seed', 1234);
var LNumActions: Integer;
LNumActions := GetIntArg('ops', 10000);
var LUseEncryptionProxy: Boolean;
LUseEncryptionProxy := FindCmdLineSwitch('useproxy', ['-'], True);
var LOutputFileName: string;
LOutputFileName := GetStringArg('out', '');
if LOutputFileName = '' then
begin
LOutputFileName := Format('test_results_%s.csv', [FormatDateTime('yyyymmdd_hhnnss_zzz', Now)]);
end;
Writeln('Test results will be saved to: ', LOutputFileName);
Writeln('-------------------------');
LConnection := TZConnection.Create(nil);
LConnection.LibraryLocation := ExtractFilePath(ParamStr(0)) + 'libpq.dll';
try
LConnection.Protocol := 'postgresql';
LConnection.HostName := LHost;
LConnection.Port := LPort;
LConnection.Database := LDatabase;
LConnection.User := LUser;
LConnection.Password := LPassword;
Writeln('Connecting to PostgreSQL...');
LConnection.Connect;
Writeln('Connected successfully!');
Writeln('-------------------------');
var DatabaseManager: TDatabaseManager;
DatabaseManager := TDatabaseManager.Create(LConnection, LSeed);
try
var SetupSuccess: Boolean;
SetupSuccess := DatabaseManager.SetupDatabase();
if SetupSuccess then
begin
Writeln('Done setting up database!');
end
else
begin
Writeln('Failed to setup database connection!');
end;
Writeln('-------------------------');
WriteLn('Testing Database Inserts');
var LInsertTimes: TArray<Double>;
LInsertTimes := DatabaseManager.TestInserts(LNumActions);
WriteResultsToCSV(LOutputFileName, 'insert', LInsertTimes);
var LMeanInsertTime: Double;
LMeanInsertTime := Mean(LInsertTimes);
if Length(LInsertTimes) <> LNumActions then
begin
WriteLn('All inserts did not complete, got=' + Length(LInsertTimes).ToString + ' expected=' + LNumActions.ToString);
end
else
begin
WriteLn(LNumActions.ToString + ' inserts completed, average time ' + LMeanInsertTime.ToString + 'ms');
end;
Writeln('-------------------------');
WriteLn('Testing reading back each record by primary key');
var LReadTimes: TArray<Double>;
LReadTimes := TArray<Double>.Create();
LReadTimes := DatabaseManager.TestReads(LNumActions);
WriteResultsToCSV(LOutputFileName, 'read_pk', LReadTimes);
var LMeanReadTime: Double;
LMeanReadTime := Mean(LReadTimes);
if Length(LReadTimes) <> LNumActions then
begin
WriteLn('All reads did not complete, got=' + Length(LReadTimes).ToString + ' expected=' + LNumActions.ToString);
end
else
begin
WriteLn(LNumActions.ToString + ' reads completed, average time ' + LMeanReadTime.ToString + 'ms');
end;
Writeln('-------------------------');
WriteLn('Testing reading back each record by email');
var LReadByEmailTimes: TArray<Double>;
LReadByEmailTimes := DatabaseManager.TestReadsByEmail();
WriteResultsToCSV(LOutputFileName, 'read_email', LReadByEmailTimes);
var LMeanReadByEmailTime: Double;
LMeanReadByEmailTime := Mean(LReadByEmailTimes);
if Length(LReadByEmailTimes) <> LNumActions then
begin
WriteLn('All reads by email did not complete, got=' + Length(LReadByEmailTimes).ToString + ' expected=' + LNumActions.ToString);
end
else
begin
WriteLn(LNumActions.ToString + ' reads by email completed, average time ' + LMeanReadByEmailTime.ToString + 'ms');
end;
Writeln('-------------------------');
WriteLn('Testing reading back each record by social security number');
var LReadBySocialTimes: TArray<Double>;
LReadBySocialTimes := DatabaseManager.TestReadsBySocial();
WriteResultsToCSV(LOutputFileName, 'read_social', LReadBySocialTimes);
var LMeanReadBySocialTime: Double;
LMeanReadBySocialTime := Mean(LReadBySocialTimes);
if Length(LReadBySocialTimes) <> LNumActions then
begin
WriteLn('All reads by social did not complete, got=' + Length(LReadBySocialTimes).ToString + ' expected=' + LNumActions.ToString);
end
else
begin
WriteLn(LNumActions.ToString + ' reads by social completed, average time ' + LMeanReadBySocialTime.ToString + 'ms');
end;
finally
DatabaseManager.Free;
end;
finally
FreeAndNil(LConnection);
end;
Writeln('-------------------------');
Writeln('Press Enter to exit...');
Readln;
end.

BIN
Main.res Normal file

Binary file not shown.

8
Scratch.dproj.local Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<BorlandProject>
<Transactions>
<Transaction>2026/04/20 16:47:56.000.053,C:\Users\Vincent\Documents\Embarcadero\Studio\Projects\Project1.dproj=C:\Users\Vincent\Documents\Embarcadero\Studio\Projects\Scratch.dproj</Transaction>
<Transaction>2026/04/22 11:23:56.069,=C:\Users\Vincent\Documents\Embarcadero\Studio\Projects\Unit1.pas</Transaction>
<Transaction>2026/04/22 11:27:12.704,C:\Users\Vincent\Documents\Embarcadero\Studio\Projects\TestDatabaseManager.pas=C:\Users\Vincent\Documents\Embarcadero\Studio\Projects\Unit1.pas</Transaction>
</Transactions>
</BorlandProject>

BIN
Scratch.identcache Normal file

Binary file not shown.

View File

@@ -0,0 +1,2 @@
<?xml version="1.0"?>
<TgConfig Version="3" SubLevelDisabled="False" />

BIN
Win32/Debug/Main.exe Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZAdoToken.dcu Normal file

Binary file not shown.

BIN
Win32/Debug/ZBase64.dcu Normal file

Binary file not shown.

BIN
Win32/Debug/ZClasses.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZConnection.dcu Normal file

Binary file not shown.

BIN
Win32/Debug/ZDataset.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcASA.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcAdo.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcCache.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcDbLib.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcIntfs.dcu Normal file

Binary file not shown.

BIN
Win32/Debug/ZDbcLogging.dcu Normal file

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcMySql.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcODBCCon.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcOleDB.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcOracle.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcPooled.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcProxy.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Win32/Debug/ZDbcSqLite.dcu Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More