string replacement, better exception names
This commit is contained in:
parent
7b039b4fa4
commit
0f4c509b13
57
DbService.cs
57
DbService.cs
@ -71,13 +71,29 @@ namespace com.krohne.genericdatabaseapiservice.Services {
|
|||||||
|
|
||||||
|
|
||||||
public interface IDbService {
|
public interface IDbService {
|
||||||
Task<List<TOUT>> ReadBySelect<TIN, TOUT>(string databaseTag, string selectStatement, bool justOne, TIN input);
|
Task<List<TOUT>> ReadBySelect<TIN, TOUT>(string databaseTag, string selectStatement, bool justOne, TIN input, bool bindingByStringReplacement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DbServiceException : Exception {}
|
public class DbServiceException : Exception {
|
||||||
public class NoDataFoundException : DbServiceException {}
|
public DbServiceException(string msg): base(msg) { }
|
||||||
public class TooMuchDataFoundException : DbServiceException {}
|
public DbServiceException(): base() { }
|
||||||
public class UnsupportedDataTypeException: DbServiceException {}
|
}
|
||||||
|
public class NoDataFoundException : DbServiceException {
|
||||||
|
public NoDataFoundException(string msg): base(msg) { }
|
||||||
|
public NoDataFoundException(): base() { }
|
||||||
|
}
|
||||||
|
public class TooMuchDataFoundException : DbServiceException {
|
||||||
|
public TooMuchDataFoundException(string msg): base(msg) { }
|
||||||
|
public TooMuchDataFoundException(): base() { }
|
||||||
|
}
|
||||||
|
public class UnsupportedDataTypeException: DbServiceException {
|
||||||
|
public UnsupportedDataTypeException(string msg): base(msg) { }
|
||||||
|
public UnsupportedDataTypeException(): base() { }
|
||||||
|
}
|
||||||
|
public class StringReplacementNotAllowedException: DbServiceException {
|
||||||
|
public StringReplacementNotAllowedException(string msg): base(msg) { }
|
||||||
|
public StringReplacementNotAllowedException(): base() { }
|
||||||
|
}
|
||||||
|
|
||||||
public class DbService : IDbService {
|
public class DbService : IDbService {
|
||||||
private readonly IConfiguration Configuration;
|
private readonly IConfiguration Configuration;
|
||||||
@ -90,7 +106,7 @@ namespace com.krohne.genericdatabaseapiservice.Services {
|
|||||||
DbInfoService = dbInfoService;
|
DbInfoService = dbInfoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
async public Task<List<TOUT>> ReadBySelect<TIN, TOUT>(string databaseTag, string selectStatement, bool justOne, TIN input) {
|
async public Task<List<TOUT>> ReadBySelect<TIN, TOUT>(string databaseTag, string selectStatement, bool justOne, TIN input, bool bindingByStringReplacement) {
|
||||||
var itemList = new List<TOUT>();
|
var itemList = new List<TOUT>();
|
||||||
|
|
||||||
var databaseConnInfo = DbInfoService.GetInfoStringByTag(databaseTag);
|
var databaseConnInfo = DbInfoService.GetInfoStringByTag(databaseTag);
|
||||||
@ -101,8 +117,12 @@ namespace com.krohne.genericdatabaseapiservice.Services {
|
|||||||
using (var conn = new MySqlConnection(databaseConnInfo)) {
|
using (var conn = new MySqlConnection(databaseConnInfo)) {
|
||||||
await conn.OpenAsync();
|
await conn.OpenAsync();
|
||||||
|
|
||||||
|
bool commandTextSet = false;
|
||||||
using (var cmd = conn.CreateCommand()) {
|
using (var cmd = conn.CreateCommand()) {
|
||||||
|
if (! bindingByStringReplacement) {
|
||||||
cmd.CommandText = selectStatement;
|
cmd.CommandText = selectStatement;
|
||||||
|
commandTextSet = true;
|
||||||
|
}
|
||||||
if (input != null){
|
if (input != null){
|
||||||
foreach (var propertyInfo in typeof(TIN).GetProperties()) {
|
foreach (var propertyInfo in typeof(TIN).GetProperties()) {
|
||||||
Logger.LogInformation("Input Property name: {0} {1} ", propertyInfo.Name, propertyInfo.PropertyType);
|
Logger.LogInformation("Input Property name: {0} {1} ", propertyInfo.Name, propertyInfo.PropertyType);
|
||||||
@ -117,6 +137,9 @@ namespace com.krohne.genericdatabaseapiservice.Services {
|
|||||||
var p2 = new StringBuilder();
|
var p2 = new StringBuilder();
|
||||||
var sep = "";
|
var sep = "";
|
||||||
foreach (var x in p1) {
|
foreach (var x in p1) {
|
||||||
|
if (! (x is int || x is long)) {
|
||||||
|
throw new StringReplacementNotAllowedException();
|
||||||
|
}
|
||||||
Logger.LogInformation("x: {0}", x);
|
Logger.LogInformation("x: {0}", x);
|
||||||
p2.Append(sep);
|
p2.Append(sep);
|
||||||
p2.Append(x);
|
p2.Append(x);
|
||||||
@ -124,8 +147,21 @@ namespace com.krohne.genericdatabaseapiservice.Services {
|
|||||||
}
|
}
|
||||||
var p3 = p2.ToString();
|
var p3 = p2.ToString();
|
||||||
Logger.LogInformation("Input Value: p3:{0} typ:{1} isList:{2}", p3, typ, isList);
|
Logger.LogInformation("Input Value: p3:{0} typ:{1} isList:{2}", p3, typ, isList);
|
||||||
cmd.Parameters.AddWithValue(dma.Name, p3);
|
if (bindingByStringReplacement) {
|
||||||
|
if (commandTextSet) {
|
||||||
|
throw new StringReplacementNotAllowedException("string replacement only allowed for numeric parameters");
|
||||||
|
}
|
||||||
|
var processedStatement = selectStatement.Replace(String.Format("@{0}", dma.Name), p3);
|
||||||
|
cmd.CommandText = processedStatement;
|
||||||
|
commandTextSet = true;
|
||||||
|
Logger.LogInformation("Statement after replacement is {0}", processedStatement);
|
||||||
} else {
|
} else {
|
||||||
|
cmd.Parameters.AddWithValue(dma.Name, p3);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (bindingByStringReplacement) {
|
||||||
|
throw new StringReplacementNotAllowedException("string replacement only allowed to handle lists of parameters");
|
||||||
|
}
|
||||||
Logger.LogInformation("Input Value: {0} {1} {2}", value, typ, isList);
|
Logger.LogInformation("Input Value: {0} {1} {2}", value, typ, isList);
|
||||||
cmd.Parameters.AddWithValue(dma.Name, value);
|
cmd.Parameters.AddWithValue(dma.Name, value);
|
||||||
}
|
}
|
||||||
@ -154,6 +190,11 @@ namespace com.krohne.genericdatabaseapiservice.Services {
|
|||||||
var value = reader.GetInt32(ordinal);
|
var value = reader.GetInt32(ordinal);
|
||||||
propertyInfo.SetValue(item, value);
|
propertyInfo.SetValue(item, value);
|
||||||
Logger.LogInformation("Output Value:{0}", (System.Int32)value);
|
Logger.LogInformation("Output Value:{0}", (System.Int32)value);
|
||||||
|
} else if (propertyInfo.PropertyType == typeof(System.Int64) ||
|
||||||
|
propertyInfo.PropertyType == typeof(System.Nullable<System.Int64>)) {
|
||||||
|
var value = reader.GetInt64(ordinal);
|
||||||
|
propertyInfo.SetValue(item, value);
|
||||||
|
Logger.LogInformation("Output Value:{0}", (System.Int64)value);
|
||||||
} else if (propertyInfo.PropertyType == typeof(System.DateTime)) {
|
} else if (propertyInfo.PropertyType == typeof(System.DateTime)) {
|
||||||
var value = reader.GetDateTime(ordinal);
|
var value = reader.GetDateTime(ordinal);
|
||||||
propertyInfo.SetValue(item, value);
|
propertyInfo.SetValue(item, value);
|
||||||
@ -164,7 +205,7 @@ namespace com.krohne.genericdatabaseapiservice.Services {
|
|||||||
propertyInfo.SetValue(item, value);
|
propertyInfo.SetValue(item, value);
|
||||||
Logger.LogInformation("Output Value:{0}", value);
|
Logger.LogInformation("Output Value:{0}", value);
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedDataTypeException();
|
throw new UnsupportedDataTypeException(String.Format("{0}", propertyInfo.PropertyType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
itemList.Add(item);
|
itemList.Add(item);
|
||||||
|
11
generate.py
11
generate.py
@ -77,6 +77,7 @@ statementChecker = {
|
|||||||
'post': re.compile('^insert', re.IGNORECASE)
|
'post': re.compile('^insert', re.IGNORECASE)
|
||||||
}
|
}
|
||||||
databaseTagFinder = re.compile('DATABASETAGBEGIN(\s+)(\S+)(\s+)DATABASETAGEND', flags=re.DOTALL)
|
databaseTagFinder = re.compile('DATABASETAGBEGIN(\s+)(\S+)(\s+)DATABASETAGEND', flags=re.DOTALL)
|
||||||
|
bindingHintFinder = re.compile('BINDINGHINTBEGIN(\s+)(\S+)(\s+)BINDINGHINTEND', flags=re.DOTALL)
|
||||||
|
|
||||||
operations = []
|
operations = []
|
||||||
for path in apiDefinition['paths'].values():
|
for path in apiDefinition['paths'].values():
|
||||||
@ -95,6 +96,7 @@ for path in apiDefinition['paths'].values():
|
|||||||
print(f"{resultType=}")
|
print(f"{resultType=}")
|
||||||
description = None
|
description = None
|
||||||
statement = None
|
statement = None
|
||||||
|
bindingByStringReplacement = False
|
||||||
if 'description' in operation:
|
if 'description' in operation:
|
||||||
description = operation['description']
|
description = operation['description']
|
||||||
print(f"{description=}")
|
print(f"{description=}")
|
||||||
@ -112,6 +114,12 @@ for path in apiDefinition['paths'].values():
|
|||||||
print(f"{databaseTag=}")
|
print(f"{databaseTag=}")
|
||||||
else:
|
else:
|
||||||
print("no databasetag")
|
print("no databasetag")
|
||||||
|
bindingHintFinderResult = bindingHintFinder.search(description)
|
||||||
|
if bindingHintFinderResult:
|
||||||
|
bindingHint = bindingHintFinderResult.group(2)
|
||||||
|
print(f"{bindingHint=}")
|
||||||
|
bindingByStringReplacement = bindingHint == 'stringreplacement'
|
||||||
|
print(f"{bindingByStringReplacement=}")
|
||||||
|
|
||||||
bodyInputType = {}
|
bodyInputType = {}
|
||||||
if 'requestBody' in operation:
|
if 'requestBody' in operation:
|
||||||
@ -143,7 +151,8 @@ for path in apiDefinition['paths'].values():
|
|||||||
'statement': statement,
|
'statement': statement,
|
||||||
'databaseTag': databaseTag,
|
'databaseTag': databaseTag,
|
||||||
'bodyInputType': bodyInputType,
|
'bodyInputType': bodyInputType,
|
||||||
'paramInputTypes': paramInputTypes
|
'paramInputTypes': paramInputTypes,
|
||||||
|
'bindingByStringReplacement': bindingByStringReplacement
|
||||||
})
|
})
|
||||||
print(f"{operations=}")
|
print(f"{operations=}")
|
||||||
apiDefinition["operations"] = operations
|
apiDefinition["operations"] = operations
|
||||||
|
16
openapi.yaml
16
openapi.yaml
@ -168,6 +168,9 @@ paths:
|
|||||||
DATABASETAGBEGIN
|
DATABASETAGBEGIN
|
||||||
pdb_el_reader1
|
pdb_el_reader1
|
||||||
DATABASETAGEND
|
DATABASETAGEND
|
||||||
|
BINDINGHINTBEGIN
|
||||||
|
stringreplacement
|
||||||
|
BINDINGHINTEND
|
||||||
STATEMENTBEGIN
|
STATEMENTBEGIN
|
||||||
SELECT
|
SELECT
|
||||||
sn.seriennummer AS serialNumber
|
sn.seriennummer AS serialNumber
|
||||||
@ -184,7 +187,7 @@ paths:
|
|||||||
LEFT JOIN ems ON sn.seriennummer = ems.Seriennummer
|
LEFT JOIN ems ON sn.seriennummer = ems.Seriennummer
|
||||||
LEFT JOIN modulindex ON sn.seriennummer = modulindex.sn_lp
|
LEFT JOIN modulindex ON sn.seriennummer = modulindex.sn_lp
|
||||||
WHERE
|
WHERE
|
||||||
FIND_IN_SET(sn.seriennummer, @serialNumbers) != 0
|
sn.seriennummer in (@serialNumbers)
|
||||||
STATEMENTEND
|
STATEMENTEND
|
||||||
```
|
```
|
||||||
parameters:
|
parameters:
|
||||||
@ -194,7 +197,7 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: integer
|
type: string
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: Here are your pcbItem items
|
description: Here are your pcbItem items
|
||||||
@ -242,6 +245,12 @@ components:
|
|||||||
offensiveData:
|
offensiveData:
|
||||||
description: Input data which causes this error
|
description: Input data which causes this error
|
||||||
type: string
|
type: string
|
||||||
|
caughtException:
|
||||||
|
description: caught exception as a string
|
||||||
|
type: string
|
||||||
|
caughtExceptionMessage:
|
||||||
|
description: message of caught exception
|
||||||
|
type: string
|
||||||
# --------------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------------
|
||||||
baseItem:
|
baseItem:
|
||||||
description: Selected columns of the stammdaten table from pdb_el
|
description: Selected columns of the stammdaten table from pdb_el
|
||||||
@ -389,9 +398,10 @@ components:
|
|||||||
nullable: true
|
nullable: true
|
||||||
articleCode:
|
articleCode:
|
||||||
type: integer
|
type: integer
|
||||||
|
format: int64
|
||||||
nullable: true
|
nullable: true
|
||||||
bomIndex:
|
bomIndex:
|
||||||
type: integer
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
hasEmsUpdate:
|
hasEmsUpdate:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
@ -126,6 +126,12 @@ paramInput#slurp
|
|||||||
#else
|
#else
|
||||||
null#slurp
|
null#slurp
|
||||||
#end if
|
#end if
|
||||||
|
, #slurp
|
||||||
|
#if $operation['bindingByStringReplacement']
|
||||||
|
true#slurp
|
||||||
|
#else
|
||||||
|
false#slurp
|
||||||
|
#end if
|
||||||
);
|
);
|
||||||
return new ObjectResult(res#slurp
|
return new ObjectResult(res#slurp
|
||||||
#if not $operation['isList']
|
#if not $operation['isList']
|
||||||
@ -138,13 +144,10 @@ null#slurp
|
|||||||
var err = new ErrorResultObject();
|
var err = new ErrorResultObject();
|
||||||
err.ErrorCode = $errDef['ErrorCode'];
|
err.ErrorCode = $errDef['ErrorCode'];
|
||||||
err.ServiceErrorCode = $errDef['ServiceErrorCode'];
|
err.ServiceErrorCode = $errDef['ServiceErrorCode'];
|
||||||
err.ErrorMessage = #slurp
|
err.ErrorMessage = "$errDef['ErrorMessage']";
|
||||||
#if $errDef['ErrorMessage'] == 'INSERT_EXCEPTION_MESSAGE'
|
|
||||||
ex.ToString();
|
|
||||||
#else
|
|
||||||
"$errDef['ErrorMessage']";
|
|
||||||
#end if
|
|
||||||
err.ErrorInfoURL = "$errDef['ErrorInfoURL']";
|
err.ErrorInfoURL = "$errDef['ErrorInfoURL']";
|
||||||
|
err.CaughtException = ex.ToString();
|
||||||
|
err.CaughtExceptionMessage = ex.Message;
|
||||||
err.OffensiveData = #slurp
|
err.OffensiveData = #slurp
|
||||||
#if $operation['bodyInputType']
|
#if $operation['bodyInputType']
|
||||||
Newtonsoft.Json.JsonConvert.SerializeObject($operation['bodyInputType']['apiName'], Newtonsoft.Json.Formatting.Indented);
|
Newtonsoft.Json.JsonConvert.SerializeObject($operation['bodyInputType']['apiName'], Newtonsoft.Json.Formatting.Indented);
|
||||||
|
@ -20,9 +20,14 @@ Exceptions:
|
|||||||
ServiceErrorCode: 10004
|
ServiceErrorCode: 10004
|
||||||
ErrorMessage: the database tag mentioned in the API spec is not configured on the server, review the server configuration
|
ErrorMessage: the database tag mentioned in the API spec is not configured on the server, review the server configuration
|
||||||
ErrorInfoURL: https://google.com
|
ErrorInfoURL: https://google.com
|
||||||
|
- Exception: StringReplacementNotAllowedException
|
||||||
|
ErrorCode: 500
|
||||||
|
ServiceErrorCode: 10005
|
||||||
|
ErrorMessage: parameter binding by string replacement is not allowed for this select, review the openapi specifiction
|
||||||
|
ErrorInfoURL: https://google.com
|
||||||
# Make sure "Exception: Exception" is the last entry in the list
|
# Make sure "Exception: Exception" is the last entry in the list
|
||||||
- Exception: Exception
|
- Exception: Exception
|
||||||
ErrorCode: 500
|
ErrorCode: 500
|
||||||
ServiceErrorCode: 10000
|
ServiceErrorCode: 10000
|
||||||
ErrorMessage: INSERT_EXCEPTION_MESSAGE
|
ErrorMessage: catch-all message
|
||||||
ErrorInfoURL: https://google.com
|
ErrorInfoURL: https://google.com
|
||||||
|
Loading…
x
Reference in New Issue
Block a user