Creating a CLR Table Valued Function - sql-server

Am trying to create a simple table valued CLR function, which takes a comma separated string as a parameter, splits it up and returns it as multiple rows
Following a few online tutorials I ended up at:
[SqlFunction(FillRowMethodName = "FillRow",TableDefinition="val nvarchar(1000)")]
public static IEnumerable SqlFunction1(SqlString val)
{
string[] splitStr = val.Value.Split(',');
return splitStr;
}
private static void FillRow(Object obj, out SqlString str)
{
object[] row = (object[])obj;
str = (string)row[0];
}
However, executing it using
select * from dbo.SqlFunction1('1,2,3,4,5')
Returns the following error
Msg 6260, Level 16, State 1, Line 1
An error occurred while getting new row from user defined Table Valued Function :
System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Object[]'.
System.InvalidCastException:
at UserDefinedFunctions.FillRow(Object obj, SqlString& str)
.

I'm no C# expert, I'm a SQL dev, but this code has worked for me in the past. The method accepts a parameterised delimiter too.
Sorry, I cannot directly answer your question.
I can't even give you a source and credit the original author of the code - suffice to say it wasn't me.
using System;
using System.Data;
using System.Collections;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class UserDefinedFunctions
{
[SqlFunction(Name = "StringParserCLR",
FillRowMethodName = "FillRow",
TableDefinition = "string nvarchar(500)")]
public static IEnumerable StringParserCLR(SqlString str, SqlChars delimiter)
{
if (delimiter.Length == 0)
{
return new string[1] { str.Value };
}
return str.Value.Split(delimiter[0]);
}
public static void FillRow(object row, out SqlString str)
{
str = new SqlString((string)row);
}
};

You are taking a string reference and try to cast it to an object array, which causes the InvalidCastException.
Your SqlFunction1 method returns an array of strings, so the FillRow method will be called with a string reference. Cast the object reference back to string, and then create a SqlString value from it:
private static void FillRow(Object obj, out SqlString str) {
string row = (string)obj;
str = new SqlString(row);
}

Related

Call another method in Spring Aspect

I would like to convert a parameter and then call second method with this parameter.
The convention would be that there is always the same method overloaded with the specific type. The idea is to solve it with Spring AOP.
#Component
public class ExampleAspect {
#Around( "#annotation(Example)" )
public Object test( final ProceedingJoinPoint joinPoint ) throws Throwable {
final MethodSignature signature = (MethodSignature) joinPoint.getSignature();
final Method method = signature.getMethod();
final Example example = method.getAnnotation( Example.class );
final Object[] args = joinPoint.getArgs();
final String test = args[example.value()].toString();
final Bar bar = convertToBar(test)
args[example.value()] = bar;
//ReflectionUtils?
// call getBar(Bar bar)
//return joinPoint.proceed( args );
}
}
Here is the service
#Example(0)
public Object getBar(String test) {}
public Object getBar(Bar test) {}
Are there any better options or ideas?
EDIT:
Cannot inject the target bean, because this AOP should be used by more than specific target bean.
1 possible solution not sure if there is a smarter solution
#Around("#annotation(Example)")
public Object test(final ProceedingJoinPoint joinPoint) throws Throwable {
final MethodSignature signature = (MethodSignature) joinPoint.getSignature();
final Method method = signature.getMethod();
final Example example = method.getAnnotation(Example.class);
final Object[] args = joinPoint.getArgs();
final String bar = args[example.value()].toString();
final Bar aspectModelUrn = convertFromStringToBar(bar);
args[example.value()] = bar;
final Class<?>[] parameterTypes = method.getParameterTypes();
parameterTypes[example.value()] = Bar.class;
final Method newMethod = ReflectionUtils.findMethod(joinPoint.getTarget().getClass(), method.getName(), parameterTypes);
if (newMethod == null) {
throw new IllegalArgumentException("There is no method blubb. Have you forget to create the delegate method");
}
return newMethod.invoke(joinPoint.getTarget(), args);
}
Following code would provide a handle to the annotation and the target bean (for example , here TestComponent)
A call to the TestComponent.getBar() annotated with #Example would be intercepted and advised.
#Aspect
#Component
public class ExampleAspect {
#Around("#annotation(example) && target(bean)")
public Object test(final ProceedingJoinPoint joinPoint,Example example,TestComponent bean) throws Throwable {
String value = String.valueOf(example.value());
Bar bar = convertToBar(value);
bean.getBar(bar);
return joinPoint.proceed();
}
}
Do go through Spring AOP documentation : Passing Parameters to Advice for more details.
Note : For better performance it is a good idea to limit the scope of the expression as follows.
#Around("#annotation(example) && within(com.xyz.service..*) && target(bean)")
where com.xyz.service..* will limit the expression scope only to the beans with in the package com.xyz.service..* and its sub-packages.

Unity JSON creation showing error on array

When I am trying to create a JSON using the below code it is showing a null exception error here.
myObject.test[0]="0";
myObject.test[1]="1";
myObject.test[2]="2";
How to fix this
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class JSON_Manager : MonoBehaviour
{
public string JSON;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Node myObject = new Node();
myObject.BrickName = "test";
myObject.LED=false;
myObject.test[0]="0"; //error
myObject.test[1]="1";
myObject.test[2]="2";
string JSON = JsonUtility.ToJson(myObject);
print(JSON);
}
}
[System.Serializable]
public class Node
{
public string BrickName;
public bool LED;
public string[] test;
}
This error happens since you are not initializing array. The initial capacity is 0, that is why it gives an error.
The easiest way to fix it is to write like that before accessing to the string or maybe create default constructor that will do it for you:
test = new string[size you need]

How take always first parameter when requested array type param in spring mvc using #RequestParam

I wrote this code.
#GetMapping("/test")
public Response search(#RequestParam String value) {
System.out.println(value);
return new Response(value)
}
Some body request like
/test?value=a&value=b&value=c
value binded a,b,c
I want always bind first parmeter. Take a, ignore b, c.
Is there way using #RequestParam?
Or have to use HttpServletRequest and parsing parameter?
In this case you can use #RequestParam List<String> value instead of #RequestParam String value, and get the first value value.get(0) ignore the rest of them
For Example
http://rentacar.com/api/v1/search?make=audi&model=A8&type=6&type=11&type=12&color=RED&color=GREY
Method
public List<Vehicle> search(
#RequestParam(value="make", required=false) String make,
#RequestParam(value="model", required=false) String model,
#RequestParam(value="type", required=false) List<String> types,
#RequestParam(value="color", required=false) List<String> colors)
{
....
}
Great question!
I wrote this code to find out how this works. I included it in the test packages.
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ActiveProfiles("test")
public class ControllerTest {
#LocalServerPort
private int port;
private URL url;
#Autowired
private TestRestTemplate template;
#Before
public void setUp() throws Exception {
this.url = new URL("http://localhost:" + port + "/test?value=a&value=b&value=c");
}
#Test
public void getHello() throws Exception {
ResponseEntity<String> response = template.getForEntity(url.toString(),
String.class);
Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
Assert.assertEquals(response.getBody(), "a");
System.out.println("response = " + response);
}
}
I then modified your code to accept an array of strings, and only pass the first element to your Response Constructor.
Notice the changes in your code in the signature and return statement.
#GetMapping("/test")
public String search(#RequestParam String[] value) {
System.out.println(value);
return new Response(value[0]);
}
With your test, you can now explore using a List type for your request param and quickly see how the behaviour has changed.

Test value of a HashSet in a FitNesse table cell?

Using FitNesse with FitSharp (.Net), I've got a property of an object that is a HashSet of an enum, e.g.
public enum Fubar { Foo, Bar }
public class Test
{
public HashSet<Fubar> SetOfFubar { get; set; }
}
I'd like to test it simply, for example in an array fixture like so:
|MyArrayFixture|
|SetOfFubar|
|Foo|
|Foo,Bar|
|Bar|
||
This simply results in all rows marked missing & red and a set of surplus rows showing something like:
System.Collections.Generic.HashSet`1[MyNamespace.Fubar] surplus
What's the easiest way to get FitNesse with FitSharp (.Net) to understand HashSets?
You can write a parse operator. Here's a little example from http://fitsharp.github.io/Fit/WriteOurOwnCellOperator.html that parses the string"pi" into a numeric value.
using fitSharp.Fit.Operators;
using fitSharp.Machine.Engine;
public class ParsePi: CellOperator, ParseOperator<Cell> {
The CanParse method override determines which cells are processed by
our operator. We check for "pi" in the cell and also that we are
working with a numeric type. This preserves normal behavior if we're
using "pi" as a string input or expected value.
public bool CanParse(Type type, TypedValue instance, Tree<Cell> parameters) {
return type == typeof(double) && parameters.Value.Text == "pi";
}
Overriding the Parse method changes the behavior when the cell is
parsed to create an input or an expected value.
public TypedValue Parse(Type type, TypedValue instance, TreeTree<Cell> parameters) {
return new TypedValue(System.Math.PI);
}
}

How to deserialize several nested Json arrays (more than 2) using DataContractJsonSerializer (Windows Phone 7)

I need to deserialize the next Json string that has several nested Json arrays:
{"d1":[["11791452",[["980",""]]],["11791453",[["1060",""],["1140",""],["1220",""],["1300",""]]],["11791454",[["1070",""]]]]}
I try to do it in several steps, so far I'm able to deserialize three levels of nested arrays. As follow:
{"aOaOa":[[["1060",""],["1140",""],["1220",""],["1300",""]]]}
public class ThreeSimpleNestedArrays
{
public List<List<string[]>> aOaOa; //array of arrays of arrays
public ThreeSimpleNestedArrays()
{
aOaOa = new List<List<string[]>>();
}
}
But the problem arise when I add the extra string in the array structure:
{"TEST": [["11791453",[["1060",""],["1140",""],["1220",""],["1300",""]]],["123456",[["0","1"],["2","3"]]]]}
public class ComplexNestedArray
{
public List<Dictionary<string,List<string[]> >> TEST;
public ComplexNestedArray()
{
TEST = new List<Dictionary<string, List<string[]>>>();
}
}
I'm getting the next error message:
"Unable to cast object of type 'System.String' to type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]'."
What am I missing?
Can anybody suggest a way to deserialize an object like this nested within Json arrays using DataContractJsonSerializer?
The code I use to deserialize is the next:
//Works
DataContractJsonSerializer dcJsonSer = new DataContractJsonSerializer(typeof(ThreeSimpleNestedArrays));
ThreeSimpleNestedArrays root = (ThreeSimpleNestedArrays)dcJsonSer.ReadObject(str);
//Don't work
DataContractJsonSerializer dcJsonSer = new DataContractJsonSerializer(typeof(ComplexNestedArray));
ComplexNestedArray root = (ComplexNestedArray)dcJsonSer.ReadObject(str);
Btw, I'm able to deserilize the object when it is serilized as a Json Object as follow:
{"TEST": [{"s": "11791453","aOa": [["1060",""],["1140",""],["1220",""],["1300",""]]},{"s": "123456","aOa":[["0","1"],["2","3"]]}]}
using a class with two members (a string "s" and a List of string[] "aOa"), but without the names, when the object is serialized as an array, I'm unable to do it.
Any suggestion?
Ok, it looks like the DataContractJsonSerializer is smarter than I though .
It turns out that the way to deserialize that kid of nested objects array is with a class like this:
public class ComplexNestedArray
{
//{"TEST": [["11791453",[["1060",""],["1140",""],["1220",""],["1300",""]]],["123456",[["0","1"],["2","3"]]]]}
public List<List<object>> TEST { get; set; }
}
After that, it is only a mater to do a couple of for cycles and casts to the appropriate class structure.
Btw, This is a MUST in your toolbox in case you have to deal with Json:
json2csharp
Here is my solution. However I'll try to add later a way for your full json:
class Program {
static void Main(string[] args) {
new Program();
}
public Program() {
string full = "{\"d1\":[[\"11791452\",[[\"980\",\"\"]]],[\"11791453\",[[\"1060\",\"\"],[\"1140\",\"\"],[\"1220\",\"\"],[\"1300\",\"\"]]],[\"11791454\",[[\"1070\",\"\"]]]]}";
string simple1 = "{\"aOa\":[[\"1060\",\"\"],[\"1140\",\"\"],[\"1220\",\"\"],[\"1300\",\"\"]]}";
string simple2 = "{\"aOaOa\":[[[\"1060\",\"\"],[\"1140\",\"\"],[\"1220\",\"\"],[\"1300\",\"\"]]]}";
DataContractJsonSerializer d1 = new DataContractJsonSerializer(typeof(S1));
S1 r1 = (S1)d1.ReadObject(new MemoryStream(Encoding.Default.GetBytes(simple1)));
DataContractJsonSerializer d2 = new DataContractJsonSerializer(typeof(S2));
S2 r2 = (S2)d2.ReadObject(new MemoryStream(Encoding.Default.GetBytes(simple2)));
Console.WriteLine("done");
Console.ReadKey();
}
[DataContract]
class S1 {
[DataMember]
List<List<String>> aOa;
}
[DataContract]
class S2 {
[DataMember]
List<List<List<string>>> aOaOa;
}
}

Resources