I need to search for string or list of strings Snowflake table using Java API and fetch all the matching rows and display in Angular UI. I am using dynamic SQL (like operator) to generate the query using information schema. I have created this stored procedure and its working. Do we have any better approach or any architectural patterns for this particular usecase.
Based on the search option (starts/ends with) decide the start and end character to be used with Like operator
Get all the varchar,char columns from the table by joining with information schema.
Build dynamic sql with these columns.
Build the json array based on the query result.
CREATE OR REPLACE PROCEDURE SEARCH_DATA(SCHEMA_NAME VARCHAR, TABLE_NAME VARCHAR, SEARCH_OPTION VARCHAR, KEYWORDS ARRAY)
RETURNS VARIANT
LANGUAGE JAVASCRIPT
EXECUTE AS OWNER
AS '
var searchStart = "";
var searchEnd = "";
if (SEARCH_OPTION == "Starts with")
{
searchEnd = "%";
}
else if (SEARCH_OPTION == "Ends with")
{
searchStart = "%";
}
else if (SEARCH_OPTION == "Contains")
{
searchStart = "%";
searchEnd = "%";
}
// Dynamically compose the SQL statement to execute.
var sqlCommand = "select c.column_name from information_schema.COLUMNS c JOIN information_schema.TABLES T ON T.table_name = c.table_name AND T.table_schema = c.table_schema WHERE T.table_schema = ''";
sqlCommand+= SCHEMA_NAME;
sqlCommand+= "'' AND T.table_name= ''";
sqlCommand+= TABLE_NAME;
sqlCommand+= "'' AND c.data_type NOT IN (''TIMESTAMP_TZ'',''BOOLEAN'',''NUMBER'') ORDER BY ordinal_position";
// Prepare statement.
var stmt = snowflake.createStatement({ sqlText: sqlCommand });
// Execute Statement
var rs = stmt.execute();
var columnArray = [];
var columnName = "";
while (rs.next())
{
columnName = rs.getColumnValue(''COLUMN_NAME'');
columnArray.push(columnName);
}
var queryPrefix = "SELECT ''dummy''"
for(var i=0; i< columnArray.length; i++)
{
queryPrefix += "," + columnArray[i];
}
queryPrefix+= " FROM " + SCHEMA_NAME + "." + TABLE_NAME;
var query = "";
for(var j=0; j< KEYWORDS.length; j++)
{
query += queryPrefix;
query += " WHERE (1=0";
for(var i=0; i< columnArray.length; i++)
{
query += " OR "+ columnArray[i] + " LIKE ''" + searchStart + KEYWORDS[j] + searchEnd + "''";
}
query += ")";
if(j < KEYWORDS.length - 1)
query += " UNION ";
}
// Prepare statement.
stmt = snowflake.createStatement({ sqlText: query });
// Execute Statement
rs = stmt.execute();
var resultArray = [];
var row_as_json = {};
while (rs.next())
{
// Put each row in a variable of type JSON.
row_as_json = {};
// For each column in the row...
for (var i=0; i< columnArray.length; i++)
{
row_as_json[columnArray[i]] = rs.getColumnValue(columnArray[i]);
}
// Add the row to the array of rows.
resultArray.push(row_as_json);
}
return resultArray;
';
I adjust tickscript(kapacitor) for my calculation.
However, no alerts work after few changes.
Before adjustment, it worked without problem.
I wonder why it does not work after adjustment.
To be more specific, I need to get "MACD" of my stock price.
Measurements contain the price of each items.
Anyone knows why?
before it was:
var db = 'telegraf'
var rp = 'autogen'
var measurement = 'exec'
var groupBy = ['symbol']
var whereFilter = lambda: TRUE
var name = 'coin'
var idVar = name + '-{{.Group}}'
var message = ' {{.ID}} {{.Level}} {{.Time}}'
var idTag = 'alertID'
var levelTag = 'level'
var messageField = 'message'
var durationField = 'duration'
var outputDB = 'chronograf'
var outputRP = 'autogen'
var outputMeasurement = 'alerts'
var triggerType = 'threshold'
var crit = 50000000000
var data = stream
|from()
.database(db)
.retentionPolicy(rp)
.measurement(measurement)
.groupBy(groupBy)
.where(whereFilter)
|eval(lambda: "lastPrice")
.as('value')
var trigger = data
|alert()
.crit(lambda: "value" > crit)
.message(message)
.id(idVar)
.idTag(idTag)
.levelTag(levelTag)
.messageField(messageField)
.durationField(durationField)
.stateChangesOnly()
.telegram()
.chatId('####')
.parseMode('Markdown')
trigger
|eval(lambda: float("value"))
.as('value')
.keep()
|influxDBOut()
.create()
.database(outputDB)
.retentionPolicy(outputRP)
.measurement(outputMeasurement)
.tag('alertName', name)
.tag('triggerType', triggerType)
trigger
|httpOut('output')
Now it became:
var db = 'telegraf'
var rp = 'autogen'
var measurement = 'exec'
var groupBy = ['symbol']
var whereFilter = lambda: TRUE
var name = 'coin'
var idVar = name + '-{{.Group}}'
var message = ' {{.ID}} {{.Level}} {{.Time}}'
var idTag = 'alertID'
var levelTag = 'level'
var messageField = 'message'
var durationField = 'duration'
var outputDB = 'chronograf'
var outputRP = 'autogen'
var outputMeasurement = 'alerts'
var triggerType = 'threshold'
var crit = 0
var data = stream
|from()
.database(db)
.retentionPolicy(rp)
.measurement(measurement)
.groupBy(groupBy)
.where(whereFilter)
|eval(lambda: "lastPrice")
.as('v')
var avg12 = data
|window()
.period(3m)
.every(1m)
|mean('x1')
.as('x1a')
var avg26 = data
|window()
.period(5m)
.every(1m)
|mean('x2')
.as('x2a')
var macd = avg12
|join(avg26)
.as('x1a', 'x2a')
|eval(lambda: float('x1a.value' - 'x2a.value'))
.keep()
.as('value')
var trigger = macd
|alert()
.crit(lambda: "value" > crit)
.message(message)
.id(idVar)
.idTag(idTag)
.levelTag(levelTag)
.messageField(messageField)
.durationField(durationField)
.stateChangesOnly()
.telegram()
.chatId('###')
.parseMode('Markdown')
trigger
|eval(lambda: float("value"))
.as('value')
.keep()
|influxDBOut()
.create()
.database(outputDB)
.retentionPolicy(outputRP)
.measurement(outputMeasurement)
.tag('alertName', name)
.tag('triggerType', triggerType)
trigger
|httpOut('output')
I have a table with 2 columns - one where user can input a value to return and other column is a checkbox. If a user enters a value in the item row, I make the checkbox checked. If value is greater than 0 then only the checkbox is selected. My issue is with the below code, if I input a value on the 3 rd row, that checkbox is selected but alongside even the first row's checkbox is selected. I think the issue is in the stmt: tableModel.setProperty("/ItemSet/results/0/ReturnItemFlag", "X"); Because I am giving "0" the first row is also getting the value. How to I point to the correct result number.
Controller.js
qtyChange: function(oEvent) {
var a = oEvent.getSource();
var input = a.getValue()
var row = oEvent.getSource().getParent().getParent();
var index = row.getIndex();
var oTable = vc.getView().byId("takeStockHistoryDetailTable");
var selectedRowPath = oTable.getContextByIndex(index).getPath();
var tableModel = vc.getView().getModel(TAKE_STOCK_ORDER_DETAIL);
var selectedPart = tableModel.getObject(selectedRowPath);
var QtyOnHand = selectedPart.QtyOnHand;
var UnitP = selectedPart.UnitPrice;
var f = parseInt(input);
var g = parseInt(QtyOnHand);
var h = parseFloat(UnitP);
if (f > g) {
sap.m.MessageToast.show("Return quantity is more than available quantity");
a.setValue("");
} else if (f === 0 || input === "") {
selectedPart.ReturnItemFlag = 'Y';
tableModel.setProperty("/ItemSet/results/0/ReturnItemFlag", "Y");
} else {
selectedPart.ReturnItemFlag = 'X';
selectedPart.QtyToReturn = input;
var sub = input * h;
// debugger;
var sub1 = sub.toString();
selectedPart.Subtotal = sub1;
tableModel.setProperty("/ItemSet/results/0/ReturnItemFlag", "X");
tableModel.setProperty("/ItemSet/results/0/Subtotal", sub1);
}
},
This is possibly a very complicated way of working with table items.
Here is how you should work with bindingContexts.
on listItemPress Event of the table(list)
qtyChange: function(oEvent){
var oColumnListItem = oEvent.getSource().getParent();
var sPath = oColumnListItem.getBindingContextPath("yourModelName");
OR
var sPath = oColumnListItem.getBindingContext("yourModelName").getPath();
var sReturnItemFlagPath = sPath + "/ReturnItemFlag";
tableModel.setProperty(sReturnItemFlagPath,"newValue");
}
Let me know if this helps!
I created this script to apply to only the worksheet with the name "jan" -- however it runs on all the worksheets no matter how I try. Who can help me check what I am doing wrong?
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("jan");
var r = sheet.getActiveCell();
if( r.getColumn() == 3 ) {
var nextCell = r.offset(0, 1);
if( nextCell.getValue() === '' )
var time = new Date();
time = Utilities.formatDate(time, "GMT", "dd/MM");
nextCell.setValue(time);
};
};
Try:
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
if (sheet.getName() == "jan") {
// DO SOMETHING TO "jan"
Logger.log("working on sheet jan...");
}
}
To put the above with what you are doing:
function onEdit(e) {
var activeSheet = e.source.getActiveSheet();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("jan");
var r = sheet.getActiveCell();
if( r.getColumn() == 3 && activeSheet.getName()=="jan") {
var nextCell = r.offset(0, 1);
if( nextCell.getValue() === '' )
var time = new Date();
time = Utilities.formatDate(time, "GMT", "dd/MM");
nextCell.setValue(time);
};
};
I'm using Entity Framework in an ASP.NET MVC3 application and I'm trying to use the following code:
var token = "";
this.Database.ExecuteSqlCommand("exec dbo.MyUsp", new SqlParameter("token", token));
My stored proc signature is:
CREATE PROCEDURE MyUSP(#token varchar(10) OUT)
(...)
When I use this code I get an error saying that parameter "#token" was expected but not supplied.
How do I tell EF that the token parameter is for output?
I ended up using this to get it working, but I'm sure there's a more optimal way:
var p = new SqlParameter
{
ParameterName = "token",
DbType = System.Data.DbType.String,
Size = 100,
Direction = System.Data.ParameterDirection.Output
};
var resp = this.Database.SqlQuery<String>("exec dbo.usp_GetRequestToken #token", p);
return resp.First();
var outParam = new SqlParameter();
outParam.ParameterName = "OutPutParametname";
outParam.SqlDbType = SqlDbType.Bit;//DataType Of OutPut Parameter
outParam.Direction = ParameterDirection.Output;
db.Database.ExecuteSqlCommand("EXEC ProcedureName #Param1,#Param2 OUTPUT", new SqlParameter("Param1", value), outParam);
object outParamValue = Convert.ToBoolean(outParam.Value);
You need to indicate the direction in the parameter. For example, try something like this:
var p = new SqlParameter("token", token);
p.Direction = ParameterDirection.InputOutput;
this.Database.ExecuteSqlCommand("exec dbo.MyUsp", p);
I solved this issue with following SQL and Entity Framework code
SP :
ALTER PROCEDURE [dbo].[SaveSingleColumnValueFromGrid]
(
#TableName VARCHAR(200),
#ColumnName VARCHAR (200),
#CompareField VARCHAR(200),
#CompareValue VARCHAR(200),
#NewValue VARCHAR(200),
#Result INT OUTPUT
)
AS
BEGIN
DECLARE #SqlString NVARCHAR(2000),
#id INTEGER = 0;
IF #CompareValue = ''
BEGIN
SET #SqlString = 'INSERT INTO ' + #TableName + ' ( ' + #ColumnName + ' ) VALUES ( ''' + #NewValue + ''' ) ; SELECT #id = SCOPE_IDENTITY()';
EXECUTE sp_executesql #SqlString, N'#id INTEGER OUTPUT', #id OUTPUT
END
ELSE
BEGIN
SET #SqlString = 'UPDATE ' + #TableName + ' SET ' + #ColumnName + ' = ''' + #NewValue + ''' WHERE ' + #CompareField + ' = ''' + #CompareValue + '''';
EXECUTE sp_executesql #SqlString
set #id = ##ROWCOUNT
END
SELECT #Result = #id
END
Entity Framework Code :
public FieldUpdateResult SaveSingleColumnValueFromGrid(string tableName, string tableSetFieldName, string updatedValue, string tableCompareFieldName, string uniqueFieldValue)
{
var fieldUpdateResult = new FieldUpdateResult() ;
var isNewRecord = false;
if (string.IsNullOrWhiteSpace(uniqueFieldValue))
{
uniqueFieldValue = string.Empty;
isNewRecord = true;
}
using (var dbContext = new DBEntities())
{
var resultParameter = new SqlParameter("#Result", SqlDbType.Int)
{
Direction = ParameterDirection.Output
};
var recordsAffected = dbContext.Database.ExecuteSqlCommand("SaveSingleColumnValueFromGrid #TableName,#ColumnName,#CompareField,#CompareValue,#NewValue,#Result out",
new SqlParameter("#TableName", tableName),
new SqlParameter("#ColumnName", tableSetFieldName),
new SqlParameter("#CompareField", tableCompareFieldName),
new SqlParameter("#CompareValue", uniqueFieldValue),
new SqlParameter("#NewValue", updatedValue),
resultParameter);
fieldUpdateResult.Success = recordsAffected > 0;
if (isNewRecord)
{
fieldUpdateResult.NewId = (int)resultParameter.Value;
}
else
{
fieldUpdateResult.AffectedRows = (int)resultParameter.Value;
}
}
return fieldUpdateResult;
}
var db = new DBContext();
var outParam = new SqlParameter
{
ParameterName = "#Param",
DbType = System.Data.DbType.String,
Size = 20,
Direction = System.Data.ParameterDirection.Output
};
var r = db.Database.ExecuteSqlCommand("EXEC MyStoredProd #Param OUT",outParam );
Console.WriteLine(outParam.Value);
The main part i see everyone is missing, is the OUT keyword needed after #Param.
Below is what I do for Oracle using the DevArt driver. I have a package.proc called P_SID.SID_PGet that returns a single string value. The proc is:
PROCEDURE SID_PGet(io_SID OUT varchar2) is
Begin
io_SID:=GetSID; -- GetSID just goes off and gets the actual value
End;
Below is how I call it and retrieve the SID value (I'm using this with EF 4.1 code first and this method is in the DbContext):
/// <summary>
/// Get the next SID value from the database
/// </summary>
/// <returns>String in X12345 format</returns>
public string GetNextSId()
{
var parameter = new Devart.Data.Oracle.OracleParameter("io_SID", Devart.Data.Oracle.OracleDbType.VarChar, ParameterDirection.Output);
this.Database.ExecuteSqlCommand("BEGIN P_SID.SID_PGet(:io_SID); END;", parameter);
var sid = parameter.Value as string;
return sid;
}