Parse a string value using mysql - mysql

I have a value in a column in this manner
"id=Clarizen,ou=GROUP,dc=opensso,dc=java,dc=net|id=devendrat,ou=USER,dc=opensso,dc=java,dc=net"
I want to extract group name and user name from this string and will store it into separate columns of another table.
Desired result:
Clarizen as Groupname
devendrat as Username
Please help

You are looking for CharIndex and Substring option.
The following works for T-SQL. I am not sure about the Syntax in My SQL
SELECT REPLACE(SUBSTRING(ColumnName,1,CHARINDEX(',',ColumnName) - 1),'ID=','')
AS Groupname,
REPLACE(SUBSTRING(SUBSTRING(ColumnName,CHARINDEX('|',ColumnName),
LEN(ColumnName)),1,
CHARINDEX(',',ColumnName) - 1),'|ID=','') AS Username

(sorry this is C# I overlooked that you are using mysql, so the answer is useless to you but I'll leave it here unless someone is to remove it)
Using string split can get the job done, here is something that I whipped together, it won't be optimal but it definately works!
string parse_me = "id=Clarizen,ou=GROUP,dc=opensso,dc=java,dc=net|id=devendrat,ou=USER,dc=opensso,dc=java,dc=net";
string[] lines = parse_me.Split(',');
List<string> variables = new List<string>();
List<string> values = new List<string>();
foreach (string line in lines)
{
string[] pair = line.Split('=');
//Console.WriteLine(line);
variables.Add(pair[0]);
values.Add(pair[1]);
}
string group = "";
string user = "";
if (variables.Count == values.Count)
{
for (int i = 0; i < variables.Count; ++i )
{
Console.Write(variables[i]);
Console.Write(" : ");
Console.WriteLine(values[i]);
if (variables[i] == "ou")
{
if (group == "")
{
group = values[i];
}
else if (user == "")
{
user = values[i];
}
}
}
}
Console.WriteLine("Group is: " + group);
Console.WriteLine("User is: " + user);
Console.ReadLine();

Related

How to properly query Postgres JSONB field in Vapor/Fluent

I have a table with some jsonb columns created by a migration like this:
public func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.schema(MyTable.schema)
.id()
.field(.metadata, .custom("JSONB"), .required)
.create()
}
I am trying to filter query on jsonb field. The following is a simple string interpolation that works.
//jsonFilters is a dictionary of key value pair for which we want to filter in jsonb field
var query = MyTable.query(on: db)
var filterString = ""
var cycleCount = 0;
jsonFilters.forEach({
(key, value) in
filterString +=
"metadata->>'\(key)' = '\(value)' "
cycleCount+=1
if(cycleCount < filter.metadata!.count) {
filterString += " AND "
}
})
query = query.filter(.custom(metadataString))
// Also filter on something else.
query = query.filter(....)
However this is not secure and is sql injection vulnerable. Is there a way to bind the filter arguments in for example using SQLQueryString? It should work in conjunction with the rest of the regular filter. ( Last line in the code)
Just in case someone runs into the same here is what works with SQLQueryString so you can pass the parameters instead of string interpolation:
var queryString = SQLQueryString("")
var cycleCount = 0;
filter.metadata!.forEach({
(key, value) in
queryString.appendLiteral("metadata->>")
queryString.appendInterpolation(bind: key)
queryString.appendLiteral(" = ")
queryString.appendInterpolation(bind: value)
cycleCount+=1
if(cycleCount < filter.metadata!.count) {
queryString.appendLiteral(" AND ")
}
})

How do I consume a JSon object that has no headers?

My C# MVC5 Razor page returns a Newtonsoft json link object to my controller (the "1" before \nEdit |" indicates that the checkbox is checked:
"{\"0\": [\"6146\",\"Kimball\",\"Jimmy\",\"General Funny Guy\",\"277\",\"Unite\",\"Jun 2019\",\"\",\"\",\"1\",\"\nEdit |\nDetails\n\n \n\"],\"1\": [\"6147\",\"Hawk\",\"Jack\",\"\",\"547\",\"Painters\",\"Jun 2019\",\"\",\"\",\"on\",\"\nEdit |\nDetails\n\n \n\"]}"
How do I parse this?
I am using a WebGrid to view and I want to allow the users to update only the lines they want (by checking the checkbox for that row), but it doesn't include an id for the 's in the dom. I figured out how to pull the values, but not the fieldname: "Last Name" , value: "Smith"... I only have the value and can't seem to parse it... one of my many failed attempts:
public ActoinResult AttMods(string gridData)
{
dynamic parsedArray = JsonConvert.DeserializeObject(gridData);
foreach (var item in parsedArray)
{
string[] itemvalue = item.Split(delimiterChars);
{
var id = itemvalue[0];
}
}
I finally sorted this one out..If there is a more dynamic answer, please share... I'll give it a few days before I accept my own (admittedly clugy) answer.
if(ModelState.IsValid)
{
try
{
Dictionary <string,string[]> log = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string[]>>(gridData);
foreach (KeyValuePair<string,string[]> keyValue in log)
{
if (keyValue.Value[9] == "1")//Update this row based on the checkbox being checked
{
var AttendeeID = keyValue.Value[0];
int intAttendeeID = 0;
if (int.TryParse(AttendeeID, out intAttendeeID))//Make sure the AttendeeID is valid
{
var LName = keyValue.Value[1];
var FName = keyValue.Value[2];
var Title = keyValue.Value[3];
var kOrgID = keyValue.Value[4];
var Org = keyValue.Value[5];
var City = keyValue.Value[7];
var State = keyValue.Value[8];
var LegalApproval = keyValue.Value[9];
tblAttendee att = db.tblAttendees.Find(Convert.ToInt32(AttendeeID));
att.FName = FName;
att.LName = LName;
att.Title = Title;
att.kOrgID = Convert.ToInt32(kOrgID);
att.Organization = Org;
att.City = City;
att.State = State;
att.LegalApprovedAtt = Convert.ToBoolean(LegalApproval);
}
}
}
db.SaveChanges();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
You can avoid assigning the var's and just populate the att object with the KeyValue.Value[n] value, but you get the idea.

Mule - how to pad rows in a CSV file with extra delimiters

I have a CSV file coming into my Mule application that looks as follows:
1,Item,Item,Item
2,Field,Field,Field,Field
2,Field,Field,Field,Field
3,Text
Is there a way I can transform this file in Mule to something like the below:
1,Item,Item,Item,,,,,,
2,Field,Field,Field,Field,,,,,
2,Field,Field,Field,Field,,,,,
3,Text,,,,,,,,
Essentially, what I need to do here is append a string (containing x occurrences of a delimiter) to the end of each row. The number of delimiters I need to append to each row can be determined by the first character of that row e.g. if row[0]='1' then (append ",,,,,,") else if row[0]='2' then (append ",,,,,"etc.
The reason I have this rather annoying problem is because the system providing the input to my Mule application produces a file where the number of columns in each row may vary. I'm trying to pad this file so that the number of columns in each row is equal, so that I can pass it on to a Java transformer like the one explained here that is using FlatPack (which expects x columns, it won't accept a file that has a varying number of columns in each row).
Does anyone have any ideas on how I could approach this? Thanks in advance.
UPDATE
Based on #Learner's recommendation and #EdC's answer - I've achieved this in Mule using the below:
<flow name="testFlow1" doc:name="testFlow1">
<file:inbound-endpoint .../>
<file:file-to-string-transformer doc:name="File to String"/>
<component doc:name="Java" class="package.etc.etc.MalformData"/>
</flow>
Try this based on #Learner 's answer.
import org.mule.api.MuleEventContext;
import org.mule.api.MuleMessage;
public class MalformData implements org.mule.api.lifecycle.Callable {
private String[] strTempArray;
public String findMalformRow(String strInput) {
String strOutput = "";
String strFix = "";
int intArrayLength = 0;
char charFirst = ' ';
String strControl = "";
strTempArray = strInput.split("\\n");
intArrayLength = strTempArray.length;
for (int i = 0; i < intArrayLength; i++) {
charFirst = strTempArray[i].charAt(0);
strFix = strTempArray[i];
String missingDelimiter = "";
if (charFirst == '1') {
missingDelimiter = ",,,,,,";
strFix += missingDelimiter;
} else if (charFirst == '2') {
missingDelimiter = ",,,,,";
strFix += missingDelimiter;
} else if (charFirst == '3') {
missingDelimiter = ",,,,,,,,";
strFix += missingDelimiter;
} else {
strFix = "Good";
}
if (strControl != "Good") {
strTempArray[i] = strFix;
} else {
charFirst = ' ';
strFix = "";
}
}
for(int i=0; i < intArrayLength; i++){
strOutput += strTempArray[i] + "\n";
}
return strOutput;
}
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
MuleMessage message = eventContext.getMessage();
String newPayload = this.findMalformRow(message.getPayloadAsString());
message.setPayload(newPayload);
return message;
}
}
You could write a custom java component that reads your CSV file line by line, write to another file and add , based on your logic at the end of each line

Local sequence cannot be used in LINQ to SQL implementation

I'm getting an error, see below, when I try to generate a list of the class MappedItem. In short the code example below tries to find products by category, date range and SKU. The requirement I have is that the user should be able to enter a comma separated list of SKUs and the search is to find any product whos SKU starts with one of the SKUs entered by the user. When I run the code, I get.
Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator.
The abbreviated sequence is this:
Convert the comma separated string of SKUs into a list of strings.
string sku = TextSKU.Text;
List<string> skuList = sku.Split(new char[] { ',' }).ToList();
Define elsewhere in the code the class that will accept the search results.
public class MappedItem
{
public string ItemDescription { get; set; }
public int ItemCount { get; set; }
public MappedItem()
{
}
public MappedItem(string itemDescription, int itemCount)
{
ItemDescription = itemDescription;
ItemCount = itemCount;
}
}
Here's the query that I generate my results from
List<MappedItem> widgetItems = (from c1 in db.CCRCodes
join pac in db.widgetAssignedCodes on c1.code_id equals pac.code_id
join ph in db.widgetHistories on pac.history_id equals ph.history_id
where ph.contact_dt.Value.Date >= startDate && ph.contact_dt.Value.Date <= endDate &&
(string.IsNullOrEmpty(baanCatFam) || ph.baan_cat_family_code == baanCatFam) &&
(string.IsNullOrEmpty(baanCat) || ph.baan_cat_code == baanCat) &&
(string.IsNullOrEmpty(baanSubCat) || (ph.baan_sub_cat_code == baanSubCat)) &&
(string.IsNullOrEmpty(sku) || skuList.All(sl => ph.product_mod.StartsWith(sl)))
group c1 by c1.code_desc into ct
select new MappedItem
{
ItemDescription = ct.Key.ToUpper(),
ItemCount = ct.Count()
}).OrderByDescending(m => m.ItemCount)
.ToList();
I believe that the culprit is the line of code that I've extracted and displayed below.
skuList.All(sl => ph.product_mod.StartsWith(sl))
This identifies all skus that start with an element from the skuList which is derived from a comma delimited lists of skus entered by the user. My question is, what causes this error, and given the code examples, what do I do to get around them.
First - logically you want Any, not All.
Second, this is a poor way to build up a query filter. All of those operations are sent into the database, while the information to determine which filters should be applied is already local. The explicit joins are also bad (association properties could be used instead).
IQueryable<WidgetHistory> query = db.widgetHistories
.Where(ph => ph.contact_dt.Value.Date >= startDate
&& ph.contact_dt.Value.Date <= endDate);
if (!string.IsNullOrEmpty(baanCatFam))
{
query = query.Where(ph => ph.baan_cat_family_code == baanCatFam);
}
if (!string.IsNullOrEmpty(baanCat))
{
query = query.Where(ph => ph.baan_cat_code == baanCat);
}
if (!string.IsNullOrEmpty(baanSubCat))
{
query = query.Where(ph => ph.baan_sub_cat_code == baanSubCat);
}
//TODO sku filtering here.
List<MappedItem> widgetItems =
from ph in query
let c1 = ph.widgetAssignedCode.CCRCode
group c1 by c1.code_desc into g
select new MappedItem
{
ItemDescription = g.Key.ToUpper(),
ItemCount = g.Count()
}).OrderByDescending(m => m.ItemCount)
.ToList();
Third: the answer to your question.
what causes this error
LinqToSql's query provider cannot translate your local collection into sql. There's only a limitted set of scenarios where it can translate... .Where(ph => idList.Contains(ph.Id)) is translated into an IN clause with 1 parameter per int in idList.
To get around this limitation, you need to convert the local collection into an expression. Start by tranforming each item in the collection into a filtering expression:
List<Expression<Func<WidgetHistory, bool>>> skuFilters =
skuList.Select<string, Expression<Func<WidgetHistory, bool>>>(skuItem =>
ph => ph.ProductMod.StartsWith(skuItem)
).ToList();
Next, a helper method:
public static Expression<Func<T, bool>> OrTheseFiltersTogether<T>(
this IEnumerable<Expression<Func<T, bool>>> filters)
{
Expression<Func<T, bool>> firstFilter = filters.FirstOrDefault();
if (firstFilter == null)
{
Expression<Func<T, bool>> alwaysTrue = x => true;
return alwaysTrue;
}
var body = firstFilter.Body;
var param = firstFilter.Parameters.ToArray();
foreach (var nextFilter in filters.Skip(1))
{
var nextBody = Expression.Invoke(nextFilter, param);
body = Expression.OrElse(body, nextBody);
}
Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>(body, param);
return result;
}
And now putting it all together:
if (skuFilters.Any()) //this part goes into where it says "TODO"
{
Expression<Func<WidgetHistory, bool>> theSkuFilter = skuFilters.OrTheseFiltersTogether()
query = query.Where(theSkuFilter);
}

performing more than one Where in query return null!!! why? how to fix this?

i have wrote a method that filters output with provided query and return it. when one Where excuted; it return correct output but when more than one Where excuted; output is null and Exception occured with message "Enumeration yielded no results". why? how i can fix it?
public IQueryable<SearchResult> PerformSearch(string query, int skip = 0, int take = 5)
{
if (!string.IsNullOrEmpty(query))
{
var queryList = query.Split('+').ToList();
var results = GENERATERESULTS();
string key;
foreach (string _q in queryList)
{
if (_q.StartsWith("(") && _q.EndsWith(")"))
{
key = _q.Replace("(", "").Replace(")", "");
results = results.Where(q => q.Title.Contains(key, StringComparison.CurrentCultureIgnoreCase));
}
else if (_q.StartsWith("\"") && _q.EndsWith("\""))
{
key = _q.Replace("\"", "").Replace("\"", "");
results = results.Where(q => q.Title.Contains(key, StringComparison.CurrentCulture));
}
else if (_q.StartsWith("-(") && _q.EndsWith(")"))
{
key = _q.Replace("-(", "").Replace(")", "");
results = results.Where(q=> !q.Title.Contains(key, StringComparison.CurrentCultureIgnoreCase));
}
else
{
key = _q;
results = results.Where(q => q.Title.Contains(key, StringComparison.CurrentCulture));
}
}
this._Count = results.Count();
results = results.Skip(skip).Take(take);
this._EndOn = DateTime.Now;
this.ExecutionTime();
return results;
}
else return null;
}
thanks in advance ;)
string key;
foreach (string _q in queryList)
{
Ah, the expression binds to the key variable. You need a new key variable for each execution of the loop.
foreach (string _q in queryList)
{
string key;