Extracting order type from sql parser - sql

using global sql parser (gsp) for extracting column and sorting type from order sql query and extract and or from where condition
SELECT employee_id, dept, name, age, salary
FROM employee_info
WHERE dept = 'Sales' and ID=1
ORDER BY salary, age DESC,ID;
I can extracting column name but can extract order type
1- how can extract order type?
2- how can extract and , or from where sql?

If pSqlstmt is gsp_selectStatement * then you can do something like this:
if(pSqlstmt->orderbyClause != nullptr)
{
string sortType;
int colNumOrderBy = pSqlstmt->orderbyClause->items->length;
for(int i = 0; i < colNumOrderBy; i++)
{
gsp_orderByItem *field = reinterpret_cast<gsp_orderByItem *>(gsp_list_celldata(pSqlstmt->orderbyClause->items->head));
//get order by column name
char *sortCol = gsp_node_text(reinterpret_cast<gsp_node*>(field->sortKey));
if(field->sortToken== nullptr)
{
//ERROR
}
else
{
//find out sorting type (ASC/DESC)
sortType = sortType.substr(0,field->sortToken->nStrLen);
}
free(sortCol);
pSqlstmt->orderbyClause->items->head = pSqlstmt->orderbyClause->items->head->nextCell;
}
}

Related

I'm using 3 filters in my lightning component to want to show data all together,i.e. record should be displayed after filtering through all filters

I have created a lightning component with 3 filters- one for searching listview, one from dropdown (picklist) and third by searching the name. I'm able to make it work by individual search but for combining have been asked to use dynamic SQL in apex by passing the string in apex class. So here's code is attached of class .But I don't know how to move forward.
public with sharing class ApexSearchForm {
#AuraEnabled
public static List<Asset__c> fetchAccounts(String status, String v) {
String a= 'Recently Viewed Assets';
String b='All Assets';
String c='Choose One';
List<Asset__c> accList = new List<Asset__c>();
if(String.isNotBlank(status)){
accList = [SELECT Name, Status__c, Description__c, Executive_Sponsor__c, Documentation_Link__c,Video_Link__c,Source_Code_Link__c
FROM Asset__c
WHERE Status__c = :status];
}if(String.isBlank(status)){
accList = [SELECT Name, Status__c, Description__c, Executive_Sponsor__c, Documentation_Link__c, Video_Link__c,Source_Code_Link__c
FROM Asset__c LIMIT 100];
}if(v == a){
accList = [SELECT Id, Name, Description__c, Submitted_Date__c, Documentation_Link__c, Source_Code_Link__c,Video_Link__c,Status__c
FROM Asset__c
WHERE LastViewedDate != NULL
ORDER BY LastViewedDate DESC LIMIT 5];
}else if(v==b){
accList = [SELECT Id, Name, Description__c, Submitted_Date__c, Documentation_Link__c, Source_Code_Link__c,Video_Link__c,Status__c
FROM Asset__c
ORDER BY Name ASC ];
}else if(v==c){
accList = [SELECT Id, Name, Description__c, Submitted_Date__c, Documentation_Link__c, Source_Code_Link__c,Video_Link__c,Status__c
FROM Asset__c ];
}else if(String.isNotBlank(status) && v==a){
accList=[SELECT Id, Name, Description__c, Submitted_Date__c, Documentation_Link__c, Source_Code_Link__c,Video_Link__c,Status__c
FROM Asset__c
WHERE Status__c = :status
ORDER BY LastViewedDate DESC];
}
return accList;
}
#AuraEnabled
public static Map<String, String> getStatusFieldValue(){
Map<String, String> options = new Map<String, String>();
Schema.DescribeFieldResult fieldResult = Asset__c.Status__c.getDescribe();
List<Schema.PicklistEntry> pValues = fieldResult.getPicklistValues();
for (Schema.PicklistEntry p: pValues) {
options.put(p.getValue(), p.getLabel());
}
return options;
}
}
Assuming that you pass correctly the parameters from frontend to the controller, you can do something like:
public static List<Asset__c> fetchAccounts(String status, String v) {
String a= 'Recently Viewed Assets';
String b='All Assets';
String query = 'SELECT Name, Status__c, Description__c, Executive_Sponsor__c, Documentation_Link__c,Video_Link__c,Source_Code_Link__c FROM Asset__c';
if(String.isNotBlank(status) || v != null){
query += ' WHERE';
if(String.isNotBlank(status)){
query += ' Status__c = :status';
}
if(v != null){
query += ' ORDER BY';
if(v == a){
query += ' LastViewedDate DESC';
if(String.isNotBlank(status)){
query += ' LIMIT 5';
}
} else if(v == b){
query += ' Name ASC';
}
}
} else {
query += ' LIMIT 100';
}
List<Asset__c> accList = Database.query(query);
return accList;
}

how to loop over fields of a struct for query filtering

I have a database where each row corresponds to a struct with the following fields
type item struct {
ItemId *string `json:"item_id"`
OwnerId *string `json:"owner_id"`
Status *string `json:"status"`
... // many more
}
Inside the database, all fields are filled for all rows. Now I would like to have a function that takes an item object whose fields may not be filled as input and return a SQL query string. For example
func FindItems(filter item) string
The input item serves as a filter. The logic is as follows (in kind of python style)
query = `select * from item_table`
condition = ""
for field, value in filter:
if value != nil:
condition = " and " if condition else " where "
condition += " field=value"
query += condition
How can I do this in go? Or is there a better way to do filter in go?
You can use reflect package to enumerate your structure fields and values:
package main
import (
"fmt"
"reflect"
)
type item struct {
ItemID *string `json:"item_id"`
OwnerID *string `json:"owner_id"`
Status *string `json:"status"`
}
func FindItemsQuery(filter item) string {
query := `select * from item_table`
condition := ""
val := reflect.ValueOf(filter)
for i := 0; i < val.NumField(); i++ {
valField := val.Field(i)
if !valField.IsNil() {
if condition != "" {
condition += " and "
} else {
condition += " where "
}
condition += fmt.Sprintf("%s=%v", val.Type().Field(i).Tag.Get("json"), valField.Elem())
}
}
return query + condition
}
func main() {
itemID := "123"
item := item{ItemID: &itemID}
fmt.Println(FindItemsQuery(item)) // select * from item_table where item_id=123
}
Keep in mind that using additional json tags like json:"item_id,omitempty" will break your query. You should consider using custom structure tags to define the names of SQL fields.

Matching partial words in two different columns

I am working on trying to weed out a certain customer from our database. I've noticed a trend where people fill out their first name with the same name that is partial to how they fill out their company name. So an example would look like:
business_name first_name
------------- ----------
locksmith taylorsville locksmith
locksmith roy locksmi
locksmith clinton locks
locksmith farmington locksmith
These are people I do not want being pulled in a query. They are bad eggs. I'm trying to put together a query with a WHERE statement (presumably) that isolates anyone who has a first name that contains at least a partial match to their business name, but I'm stumped and could use some help.
You can use LIKE operator:
SELECT * FROM table WHERE business_name NOT LIKE CONCAT(first_name, '%')
% stands for anything.
You can employ similarity based approach
Try code at bottom of answer
It produces result like below
business_name partial_business_name first_name similarity
locksmith taylorsville locksmith locksmith 1.0
locksmith farmington locksmith locksmith 1.0
locksmith roy locksmith locksmi 0.7777777777777778
locksmith clinton locksmith locks 0.5555555555555556
So, you will be able to control what to filter out based on similarity value
** Code **
SELECT business_name, partial_business_name, first_name, similarity FROM
JS( // input table
(
SELECT business_name, REGEXP_EXTRACT(business_name, r'^(\w+)') AS partial_business_name, first_name AS first_name FROM
(SELECT 'locksmith taylorsville' AS business_name, 'locksmith' AS first_name),
(SELECT 'locksmith roy' AS business_name, 'locksmi' AS first_name),
(SELECT 'locksmith clinton' AS business_name, 'locks' AS first_name),
(SELECT 'locksmith farmington' AS business_name, 'locksmith' AS first_name),
) ,
// input columns
business_name, partial_business_name, first_name,
// output schema
"[{name: 'business_name', type:'string'},
{name: 'partial_business_name', type:'string'},
{name: 'first_name', type:'string'},
{name: 'similarity', type:'float'}]
",
// function
"function(r, emit) {
var _extend = function(dst) {
var sources = Array.prototype.slice.call(arguments, 1);
for (var i=0; i<sources.length; ++i) {
var src = sources[i];
for (var p in src) {
if (src.hasOwnProperty(p)) dst[p] = src[p];
}
}
return dst;
};
var Levenshtein = {
/**
* Calculate levenshtein distance of the two strings.
*
* #param str1 String the first string.
* #param str2 String the second string.
* #return Integer the levenshtein distance (0 and above).
*/
get: function(str1, str2) {
// base cases
if (str1 === str2) return 0;
if (str1.length === 0) return str2.length;
if (str2.length === 0) return str1.length;
// two rows
var prevRow = new Array(str2.length + 1),
curCol, nextCol, i, j, tmp;
// initialise previous row
for (i=0; i<prevRow.length; ++i) {
prevRow[i] = i;
}
// calculate current row distance from previous row
for (i=0; i<str1.length; ++i) {
nextCol = i + 1;
for (j=0; j<str2.length; ++j) {
curCol = nextCol;
// substution
nextCol = prevRow[j] + ( (str1.charAt(i) === str2.charAt(j)) ? 0 : 1 );
// insertion
tmp = curCol + 1;
if (nextCol > tmp) {
nextCol = tmp;
}
// deletion
tmp = prevRow[j + 1] + 1;
if (nextCol > tmp) {
nextCol = tmp;
}
// copy current col value into previous (in preparation for next iteration)
prevRow[j] = curCol;
}
// copy last col value into previous (in preparation for next iteration)
prevRow[j] = nextCol;
}
return nextCol;
}
};
var the_partial_business_name;
try {
the_partial_business_name = decodeURI(r.partial_business_name).toLowerCase();
} catch (ex) {
the_partial_business_name = r.partial_business_name.toLowerCase();
}
try {
the_first_name = decodeURI(r.first_name).toLowerCase();
} catch (ex) {
the_first_name = r.first_name.toLowerCase();
}
emit({business_name: r.business_name, partial_business_name: the_partial_business_name, first_name: the_first_name,
similarity: 1 - Levenshtein.get(the_partial_business_name, the_first_name) / the_partial_business_name.length});
}"
)
ORDER BY similarity DESC
Was used in How to perform trigram operations in Google BigQuery? and based on https://storage.googleapis.com/thomaspark-sandbox/udf-examples/pataky.js by #thomaspark where Levenshtein's distance is used to measure similarity
this will do the trick,
select * from TableName where lower(business_name) contains lower(first_name)
use lower() just in case they have upper case letters. Hope it helps.

Searching within subsubdictionaries of an array to return the parent dictionary (Objective C)

I have a structured array like the one below
(
{
id = 0;
name = "A";
tables = (
{
comment = "";
id = 0;
name = "T1";
},
{
comment = "";
id = 1;
name = "T2";
},
{
comment = "";
id = 4;
name = "T3";
}
);
},
{
id = 1;
name = "B";
tables = (
{
comment = "";
id = 5;
name = "T1";
},
{
comment = "";
id = 6;
name = "T2";
}
);
}
)
Given that I know the value of id key of one of the dictionaries (let's take id=6), how can I get its parent dictionary or to be more precise the value of name key (in this case B).
I've tried using predicate strings but the problem is that the parent dictionary has also a key named id, so I get the wrong results.
EDIT: id keys are unique (and it is also not necessary that ids of the elements in the first dictionary have lower intiger values than the ones in the dictionaries with higher indexes)
Try this, where array is your structured array
NSDictionary *parentDict=[[NSDictionary alloc]initWithDictionary:nil];
NSString *name=[[NSString alloc]init];
NSArray *table=[[NSArray alloc]initWithArray:nil];
for (NSDictionary * dict in array) {
table=[dict objectForKey:#"tables"];
for (NSDictionary *childDict in table) {
if ([[childDict objectForKey:#"id"]isEqualToString:#"6"]) {
//if your id value is int then use ==6 to check
parentDict=dict;
name=[dict objectForKey:#"name"];
return;
}
}
}

How to convert an NHibernate.Expression.Order object into a string?

I have a list of NHibernate.Expression.Order objects and want to convert them into a sql string.
i.e. "Name ASC, Id DESC, Amount ASC"
List<string> sqlSortingList = new List<string>();
if (OrderList != null)
{
foreach (Order order in OrderList)
{
sqlSortingList.Add(order.ToString());
}
}
Later I will concatenate the strings into one string.