Skip to content

Features/0.12.0/add oracle procedure based commands #169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions MGR.CommandLineParser.sln
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MGR.CommandLineParser.Hosti
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "docs", "docs\docs.csproj", "{405858FA-1E78-48C7-9915-B558D0F15CAE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MGR.CommandLineParser.Command.OracleProcedure", "src\MGR.CommandLineParser.Command.OracleProcedure\MGR.CommandLineParser.Command.OracleProcedure.csproj", "{738CC3C0-16C1-45FB-B1D0-A21E8FA9D7D9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -79,6 +81,10 @@ Global
{405858FA-1E78-48C7-9915-B558D0F15CAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{405858FA-1E78-48C7-9915-B558D0F15CAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{405858FA-1E78-48C7-9915-B558D0F15CAE}.Release|Any CPU.Build.0 = Release|Any CPU
{738CC3C0-16C1-45FB-B1D0-A21E8FA9D7D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{738CC3C0-16C1-45FB-B1D0-A21E8FA9D7D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{738CC3C0-16C1-45FB-B1D0-A21E8FA9D7D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{738CC3C0-16C1-45FB-B1D0-A21E8FA9D7D9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -92,6 +98,7 @@ Global
{9F5A0142-E0A1-45A2-961E-55611B4440AD} = {FB795A12-C939-492F-9377-4C468D01EF3C}
{40EAA8E2-7AFE-4ED1-A961-35BD7E424985} = {FB795A12-C939-492F-9377-4C468D01EF3C}
{405858FA-1E78-48C7-9915-B558D0F15CAE} = {172E24C2-BF99-4DA9-A7DF-8C0BB44C138D}
{738CC3C0-16C1-45FB-B1D0-A21E8FA9D7D9} = {FB795A12-C939-492F-9377-4C468D01EF3C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {827031C5-AE76-4B4C-9503-E13F15B497E9}
Expand Down
7 changes: 7 additions & 0 deletions docs/procedure/oracle/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Use Oracle procedure commands

You can use stored procedure from Oracle database to represent your commands.

This allow you to call stored procedures via the parser
(to create command-line or web-based tool).

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using MGR.CommandLineParser.Extensibility.Command;

namespace MGR.CommandLineParser.Command.OracleProcedure
{
internal class CommandMetadata : ICommandMetadata
{
public CommandMetadata(string name)
{
Name = name;
Description = name;
Samples = new string[0];
}
public string Name { get; }

public string Description { get; }

public string Usage => string.Empty;

public string[] Samples { get; }

public bool HideFromHelpListing => false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using MGR.CommandLineParser.Extensibility.Command;

namespace MGR.CommandLineParser.Command.OracleProcedure
{
internal class CommandObjectBuilder : ICommandObjectBuilder
{
private IEnumerable<ICommandOptionMetadata> _options;
private IEnumerable<Parameter> _outParameters;
private DbConnection _dbConnection;

public CommandObjectBuilder(IEnumerable<ICommandOptionMetadata> options, IEnumerable<Parameter> outParameters, DbConnection dbConnection)
{
_options = options;
_outParameters = outParameters;
_dbConnection = dbConnection;
}

public void AddArguments(string argument) => throw new NotImplementedException("Oracle procedures does not define unamed arguments");
public ICommandOption FindOption(string optionName)
{
throw new NotImplementedException();
}

public ICommandOption FindOptionByShortName(string optionShortName)
{
throw new NotImplementedException($"Oracle procedures does not define 'short name' for the parameters ('{ optionShortName }')");
}

public ICommandObject GenerateCommandObject()
{
throw new NotImplementedException();
}

public CommandValidationResult Validate(IServiceProvider serviceProvider)
{
throw new NotImplementedException();
}
}
}
14 changes: 14 additions & 0 deletions src/MGR.CommandLineParser.Command.OracleProcedure/CommandOption.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using MGR.CommandLineParser.Extensibility.Command;

namespace MGR.CommandLineParser.Command.OracleProcedure
{
internal class CommandOption : ICommandOption
{
public bool ShouldProvideValue => throw new NotImplementedException();

public ICommandOptionMetadata Metadata => throw new NotImplementedException();

public void AssignValue(string optionValue) => throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using MGR.CommandLineParser.Extensibility.Command;

namespace MGR.CommandLineParser.Command.OracleProcedure
{
internal class CommandOptionMetadata : ICommandOptionMetadata
{
public CommandOptionMetadata(OptionDisplayInfo displayInfo, bool isRequired, string defaultValue)
{
DisplayInfo = displayInfo;
IsRequired = isRequired;
DefaultValue = defaultValue;
}
public bool IsRequired { get; }

public CommandOptionCollectionType CollectionType => CommandOptionCollectionType.None;

public IOptionDisplayInfo DisplayInfo { get; }

public string DefaultValue { get; }
}
}
29 changes: 29 additions & 0 deletions src/MGR.CommandLineParser.Command.OracleProcedure/CommandType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using MGR.CommandLineParser.Extensibility.Command;

namespace MGR.CommandLineParser.Command.OracleProcedure
{
internal class CommandType : ICommandType
{
private readonly IEnumerable<Parameter> _outParameters;
private readonly DbConnection _dbConnection;

public CommandType(CommandMetadata commandMetadata, IEnumerable<CommandOptionMetadata> options, IEnumerable<Parameter> outParameters, DbConnection dbConnection)
{
Metadata = commandMetadata;
Options = options;
_outParameters = outParameters;
_dbConnection = dbConnection;
}
public ICommandMetadata Metadata { get; }

public IEnumerable<ICommandOptionMetadata> Options { get; }

public ICommandObjectBuilder CreateCommandObjectBuilder(IServiceProvider serviceProvider)
{
return new CommandObjectBuilder(Options, _outParameters, _dbConnection);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;
using MGR.CommandLineParser.Extensibility.Command;
using Microsoft.EntityFrameworkCore;

namespace MGR.CommandLineParser.Command.OracleProcedure
{
internal class CommandTypeProvider : ICommandTypeProvider
{
private readonly OracleSystemContext _dbContext;

public CommandTypeProvider(OracleSystemContext dbContext)
{
_dbContext = dbContext;
}
public async Task<IEnumerable<ICommandType>> GetAllCommandTypes()
{
var procedures = await _dbContext.Procedures.Include(procedure => procedure.Parameters).ToListAsync();
return procedures.Select(procedure => MapProcedureToCommandType(procedure, _dbContext.Database.GetDbConnection()));
}
public async Task<ICommandType> GetCommandType(string commandName)
{
var procedure = await _dbContext.Procedures.Include(procedure => procedure.Parameters).Where(procedure => procedure.Name == commandName).SingleOrDefaultAsync();
if (procedure != null)
{
return MapProcedureToCommandType(procedure, _dbContext.Database.GetDbConnection());
}
return null;
}

private static CommandType MapProcedureToCommandType(Procedure procedure, DbConnection dbConnection)
{
return new CommandType(
new CommandMetadata(procedure.Name),
procedure.Parameters
.Where(parameter => parameter.Direction.HasFlag(Direction.In))
.Select(parameter => new CommandOptionMetadata(
new OptionDisplayInfo(parameter.Name),
!parameter.HasDefaultValue,
parameter.DefaultValue
)
),
procedure.Parameters
.Where(parameter => parameter.Direction.HasFlag(Direction.Out)),
dbConnection
);
}
}
}
12 changes: 12 additions & 0 deletions src/MGR.CommandLineParser.Command.OracleProcedure/Direction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace MGR.CommandLineParser.Command.OracleProcedure
{
[Flags]
internal enum Direction
{
In = 1,
Out = 2,
InOut = 3
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Oracle.EntityFrameworkCore" Version="2.19.80" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\MGR.CommandLineParser\MGR.CommandLineParser.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

namespace MGR.CommandLineParser.Command.OracleProcedure.Mapping
{
internal class ParameterMap : IEntityTypeConfiguration<Parameter>
{
public void Configure(EntityTypeBuilder<Parameter> builder)
{
builder.ToTable("USER_ARGUMENTS");

builder.Property(_ => _.Name)
.HasColumnName("OBJECT_NAME");

var defaultValueConverter = new BoolToStringConverter("N", "Y");
builder.Property(_ => _.HasDefaultValue)
.HasColumnName("DEFAULTED")
.HasConversion(defaultValueConverter);

builder.Property(_ => _.DefaultValue)
.HasColumnName("DEFAULT_VALUE");

builder.Property(_ => _.DataType)
.HasColumnName("DATA_TYPE");

var directionConverter = new ValueConverter<Direction, string>(
_ => _.ToString(),
value => ParseDirection(value));
builder.Property(_ => _.Direction)
.HasColumnName("IN_OUT")
.HasConversion(directionConverter);
}
private static Direction ParseDirection(string value) => value
switch
{
"IN" => Direction.In,
"OUT" => Direction.Out,
"IN/OUT" => Direction.InOut,
_ => throw new ArgumentOutOfRangeException(nameof(value))
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace MGR.CommandLineParser.Command.OracleProcedure.Mapping
{
internal class ProcedureMap : IEntityTypeConfiguration<Procedure>
{
public void Configure(EntityTypeBuilder<Procedure> builder)
{
builder.ToTable("ALL_OBJETS");

builder.Property(_ => _.Name)
.HasColumnName("OBJECT_NAME");

builder.HasQueryFilter(_ => EF.Property<string>(_, "OBJECT_TYPE") == "PROCEDURE");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.Linq;
using MGR.CommandLineParser.Extensibility.Command;

namespace MGR.CommandLineParser.Command.OracleProcedure
{
internal class OptionDisplayInfo : IOptionDisplayInfo
{
public OptionDisplayInfo(string name)
{
Name = name;
Description = name;
}
public string Name { get; }

public IEnumerable<string> AlternateNames => Enumerable.Empty<string>();

public string ShortName => string.Empty;

public string Description { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using MGR.CommandLineParser.Command.OracleProcedure.Mapping;
using Microsoft.EntityFrameworkCore;

namespace MGR.CommandLineParser.Command.OracleProcedure
{
internal sealed class OracleSystemContext : DbContext
{
public DbSet<Procedure> Procedures { get; set; }

public OracleSystemContext(DbContextOptions<OracleSystemContext> options)
: base(options)
{ }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.ApplyConfiguration(new ProcedureMap())
.ApplyConfiguration(new ParameterMap());
base.OnModelCreating(modelBuilder);
}
}
}
11 changes: 11 additions & 0 deletions src/MGR.CommandLineParser.Command.OracleProcedure/Parameter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace MGR.CommandLineParser.Command.OracleProcedure
{
internal class Parameter
{
public string Name { get; set; }
public bool HasDefaultValue { get; set; }
public string DefaultValue { get; set; }
public string DataType { get; set; }
public Direction Direction { get; set; }
}
}
10 changes: 10 additions & 0 deletions src/MGR.CommandLineParser.Command.OracleProcedure/Procedure.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Collections.Generic;

namespace MGR.CommandLineParser.Command.OracleProcedure
{
internal class Procedure
{
public string Name { get; set; }
public IEnumerable<Parameter> Parameters { get; set; }
}
}