diff --git a/Packages/d103/sqlcmdcli.dproj b/Packages/d103/sqlcmdcli.dproj index a9351ba..89e257e 100644 --- a/Packages/d103/sqlcmdcli.dproj +++ b/Packages/d103/sqlcmdcli.dproj @@ -112,8 +112,8 @@ 1033 true true - CompanyName=;FileDescription=Command-line utility for ad hoc, interactive execution of commands on SQL Server;FileVersion=1.0.0.67;InternalName=sqlcmdcli;LegalCopyright=;LegalTrademarks=;OriginalFilename=sqlcmdcli.exe;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0;Comments=https://github.com/segovoni/sqlcmdcli - 67 + CompanyName=;FileDescription=Command-line utility for ad hoc, interactive execution of commands on SQL Server;FileVersion=1.0.0.77;InternalName=sqlcmdcli;LegalCopyright=;LegalTrademarks=;OriginalFilename=sqlcmdcli.exe;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0;Comments=https://github.com/segovoni/sqlcmdcli + 77 diff --git a/Packages/d103/sqlcmdcli.dres b/Packages/d103/sqlcmdcli.dres index 15a9587..a47b618 100644 Binary files a/Packages/d103/sqlcmdcli.dres and b/Packages/d103/sqlcmdcli.dres differ diff --git a/Sources/sqlcmdcli.AnonymizeDB.pas b/Sources/sqlcmdcli.AnonymizeDB.pas index dc822af..5fa210b 100644 --- a/Sources/sqlcmdcli.AnonymizeDB.pas +++ b/Sources/sqlcmdcli.AnonymizeDB.pas @@ -22,8 +22,8 @@ TAnonymizeDB = class(TObject) class procedure DisableTriggers(const AConnection: TADOConnection; const ATriggers: TDictionary); public - class procedure Run(const AServerName, ADatabaseName, AUserName, APassword: string; - const AVerbose: Boolean); + class procedure Run(const AServerName, ADatabaseName, AUserName, APassword, + ASchemaName, ATableName, AColumnName: string; const AVerbose: Boolean); end; implementation @@ -174,7 +174,7 @@ class procedure TAnonymizeDB.EnableTriggers(const AConnection: TADOConnection; end; class procedure TAnonymizeDB.Run(const AServerName, ADatabaseName, AUserName, - APassword: string; const AVerbose: Boolean); + APassword, ASchemaName, ATableName, AColumnName: string; const AVerbose: Boolean); var LConnection: TADOConnection; LDBSchema: TDBSchema; @@ -224,7 +224,24 @@ class procedure TAnonymizeDB.Run(const AServerName, ADatabaseName, AUserName, if (AVerbose) then TConsole.Log(Format('Extract schema for %s ...', [ADatabaseName]), Success, False); - LDBSchemaExtractor.ExtractSchema(stText); + if (Trim(ASchemaName) = '') and + (Trim(ATableName) = '') and + (Trim(AColumnName) = '') then + begin + LDBSchemaExtractor.ExtractSchema(stText); + end + else if (Trim(ASchemaName) <> '') and + (Trim(ATableName) <> '') and + (Trim(AColumnName) <> '') then + begin + LDBSchemaExtractor.ExtractSchema(ASchemaName, ATableName, AColumnName); + end + else begin + if (AVerbose) then + TConsole.Log('Invalid parametes', Error, True); + raise Exception.Create('Invalid parametes'); + end; + LDBSchema := LDBSchemaExtractor.DBSchema; //LDBSchemaIndex := LDBSchemaExtractor.DBSchemaIndex; finally diff --git a/Sources/sqlcmdcli.Boot.pas b/Sources/sqlcmdcli.Boot.pas index feaf13b..2eaa6a7 100644 --- a/Sources/sqlcmdcli.Boot.pas +++ b/Sources/sqlcmdcli.Boot.pas @@ -157,11 +157,40 @@ class procedure TBootCLI.Boot; // Command: anonymizedb LCommand := TOptionsRegistry.RegisterCommand('anonymizedb', 'anondb', RS_CMD_ANONYMIZEDB_DESCRIPTION, RS_CMD_ANONYMIZEDB_INFO, - 'anonymizedb -servername: -databasename: -username: -password:'); + 'anonymizedb -servername: -databasename: -username: ' + + '-password: -schemaname: -tablename: ' + + '-columnname:'); LCommand.Examples.Add('anonymizedb -servername:MARCONI -databasename:AdventureWorks -username:sgovoni -password:royalbreeze489'); LCommand.Examples.Add('anonymizedb -s:MARCONI -d:AdventureWorks -u:sgovoni -p:royalbreeze489'); LCommand.Examples.Add('anondb -s:MARCONI -d:AdventureWorks -u:sgovoni -p:royalbreeze489'); + // Option: "schemaname" + LOption := LCommand.RegisterOption('schemaname', 'schema', + RS_CMD_ANONYMIZEDB_SCHEMANAMEINFO, + procedure(const AValue: string) + begin + TAnonymizeDBOptions.SchemaName := AValue + end); + LOption.Required := False; + + // Option: "tablename" + LOption := LCommand.RegisterOption('tablename', 'table', + RS_CMD_ANONYMIZEDB_TABLENAMEINFO, + procedure(const AValue: string) + begin + TAnonymizeDBOptions.TableName := AValue + end); + LOption.Required := False; + + // Option: "columnname" + LOption := LCommand.RegisterOption('columnname', 'column', + RS_CMD_ANONYMIZEDB_COLUMNNAMEINFO, + procedure(const AValue: string) + begin + TAnonymizeDBOptions.ColumnName := AValue + end); + LOption.Required := False; + TCommandHandler.RegisterCommand('anonymizedb', procedure() begin @@ -170,6 +199,9 @@ class procedure TBootCLI.Boot; TGlobalOptions.DatabaseName, TGlobalOptions.UserName, TGlobalOptions.Password, + TAnonymizeDBOptions.SchemaName, + TAnonymizeDBOptions.TableName, + TAnonymizeDBOptions.ColumnName, TGlobalOptions.Verbose); end); diff --git a/Sources/sqlcmdcli.CommandOptions.pas b/Sources/sqlcmdcli.CommandOptions.pas index 2eefa9c..002e375 100644 --- a/Sources/sqlcmdcli.CommandOptions.pas +++ b/Sources/sqlcmdcli.CommandOptions.pas @@ -27,6 +27,13 @@ TAlterColumnOptions = class class var DataType: string; end; + TAnonymizeDBOptions = class + public + class var SchemaName: string; + class var TableName: string; + class var ColumnName: string; + end; + TGlobalOptions = class public class var ServerName: string; diff --git a/Sources/sqlcmdcli.ResourceStrings.pas b/Sources/sqlcmdcli.ResourceStrings.pas index e841684..46831f9 100644 --- a/Sources/sqlcmdcli.ResourceStrings.pas +++ b/Sources/sqlcmdcli.ResourceStrings.pas @@ -40,6 +40,9 @@ interface 'removing personally identifiable information from data sets, so that the ' + 'people whom the data describe remain anonymous (source ' + 'https://en.wikipedia.org/wiki/Data_anonymization)'; + RS_CMD_ANONYMIZEDB_SCHEMANAMEINFO = 'The name of the table schema'; + RS_CMD_ANONYMIZEDB_TABLENAMEINFO = 'The name of the table'; + RS_CMD_ANONYMIZEDB_COLUMNNAMEINFO = 'The name of the column you want to modify'; RS_CMD_ANONYMIZEDB_DISABLE_FK_START = 'Disable foreign key constraints on %s ...'; RS_CMD_ANONYMIZEDB_DISABLE_FK_END = 'Foreign key constraints disabled successfully!'; diff --git a/Sources/sqlcmdcli.SchemaExtractor.pas b/Sources/sqlcmdcli.SchemaExtractor.pas index e652e2d..ac2849b 100644 --- a/Sources/sqlcmdcli.SchemaExtractor.pas +++ b/Sources/sqlcmdcli.SchemaExtractor.pas @@ -41,6 +41,7 @@ TSQLDBSchemaExtractor = class(TObject) function GetDBSchema: TDBSchema; //function GetDBSchemaIndex: TDBSchemaIndex; function GetSQLbySchemaType(ASchemaType: TSchemaType): string; + function GetSQLbySchema(const ASchemaName, ATableName, AColumnName: string): string; protected FConnection: TADOConnection; FDBSchema: TDBSchema; @@ -48,7 +49,8 @@ TSQLDBSchemaExtractor = class(TObject) public constructor Create(AConnection: TADOConnection); destructor Destroy; override; - procedure ExtractSchema(ASchemaType: TSchemaType); + procedure ExtractSchema(ASchemaType: TSchemaType); overload; + procedure ExtractSchema(const ASchemaName, ATableName, AColumnName: string); overload; property DBSchema: TDBSchema read GetDBSchema; //property DBSchemaIndex: TDBSchemaIndex read GetDBSchemaIndex; end; @@ -78,6 +80,75 @@ destructor TSQLDBSchemaExtractor.Destroy; inherited; end; +procedure TSQLDBSchemaExtractor.ExtractSchema(const ASchemaName, ATableName, + AColumnName: string); +var + LQry: TADOQuery; + LCurrentTable: string; + LList: TObjectList; +begin + // Database schema extractor logic + + LQry := TADOQuery.Create(nil); + LList := TObjectList.Create(); + try + LQry.Connection := FConnection; + LQry.SQL.Text := GetSQLbySchema(ASchemaName, ATableName, AColumnName); + LQry.Open; + + // + if not (LQry.Eof) then + LCurrentTable := + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_SCHEMA').AsString) + + '.' + + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_NAME').AsString); + + while (not LQry.Eof) do + begin + if CompareText(LCurrentTable, + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_SCHEMA').AsString) + '.' + + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_NAME').AsString)) = 0 then + begin + LList.Add(TSQLDBTableInfo.Create( + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_SCHEMA').AsString), + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_NAME').AsString), + TSQLObjectNameFormatter.Format(LQry.FieldByName('COLUMN_NAME').AsString), + TSQLObjectNameFormatter.Format(LQry.FieldByName('DATA_TYPE').AsString), + LQry.FieldByName('MAX_LENGHT').AsInteger, + LQry.FieldByName('COLUMN_IDENTITY').AsBoolean + ) + ) + end + else begin + FDBSchema.Add(LCurrentTable, LList); + LList := TObjectList.Create(); + LList.Add(TSQLDBTableInfo.Create( + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_SCHEMA').AsString), + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_NAME').AsString), + TSQLObjectNameFormatter.Format(LQry.FieldByName('COLUMN_NAME').AsString), + TSQLObjectNameFormatter.Format(LQry.FieldByName('DATA_TYPE').AsString), + LQry.FieldByName('MAX_LENGHT').AsInteger, + LQry.FieldByName('COLUMN_IDENTITY').AsBoolean + ) + ); + LCurrentTable := + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_SCHEMA').AsString) + + '.' + + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_NAME').AsString); + end; + + LQry.Next; + end; + + FDBSchema.Add(TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_SCHEMA').AsString) + + '.' + + TSQLObjectNameFormatter.Format(LQry.FieldByName('TABLE_NAME').AsString), LList); + + finally + FreeAndNil(LQry); + end; +end; + procedure TSQLDBSchemaExtractor.ExtractSchema(ASchemaType: TSchemaType); var LQry: TADOQuery; @@ -169,6 +240,42 @@ function TSQLDBSchemaExtractor.GetDBSchema: TDictionary