I have several Snowflake Stored Procedures and when they are successful, it has the custom message that I created displayed, I would rather be displaying the same message that Snowflake shows in the Query Results window.
For Example, I execute a Stored Proc with the COPY TO statements. I would like the Successful execution of this Stored Proc to show the number of Rows successfully Exported. Can they success information be captured and displayed as easily as the Error messages are?
Yes, you can do this using JavaScript stored procedures. When Snowflake runs a query that returns only a status message, it returns it as a table with a single column "status" and a single row with the status. You can return that value. You may want to consider what happens if there's a SQL error: handle it locally in the SP or throw the error so the calling session knows there was an error. Either way the status return will show an error message if there is one.
Here's a sample using JavaScript SP. It also has some helper functions that I use routinely to execute single value queries and non-query statements just looking for a return value:
create or replace procedure SampleSP()
returns string
language javascript
as
$$
try{
return ExecuteNonQuery("create table MY_NATION_TABLE as select * from SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.NATION;");
}
catch(err){
return err;
}
// ----------------------------------------------------------------------------------
// Main function above; helper functions below
function ExecuteNonQuery(queryString) {
return ExecuteSingleValueQuery("status", queryString)
}
function ExecuteSingleValueQuery(columnName, queryString) {
var out;
cmd1 = {sqlText: queryString};
stmt = snowflake.createStatement(cmd1);
var rs;
try{
rs = stmt.execute();
rs.next();
return rs.getColumnValue(columnName);
}
catch(err) {
if (err.message.substring(0, 18) == "ResultSet is empty"){
throw "ERROR: No rows returned in query.";
} else {
throw "ERROR: " + err.message.replace(/\n/g, " ");
}
}
return out;
}
$$;
-- Run this twice to see the effect of an error. You can remove the try block
-- in the main function of the SP to generate a SQL error instead of just
-- returning a string with the error text
call SampleSP();
Related
I am trying to execute a snowflake stored procedure via python glue job, but when I get any error in the SQL statements in the stored procedure, I want the procedure to exit and that glue job should fail.
I am using this code in my snowflake stored procedure:
create or replace procedure schema.PROC_TEST
(input_sql varchar(16777216))
returns string not null
language javascript
as
$$
snowflake.execute({sqlText:`BEGIN TRANSACTION;`});
try
{
var QueryExec = INPUT_SQL+ ";";
var QueryResult = snowflake.execute({sqlText: QueryExec});
}
catch (err) // Catching any error if occurs in INPUT_SQL
{
result = 'Error: ' + err;
snowflake.execute({sqlText:`ROLLBACK;`});
return result;
throw err.message;
}
$$;
Now if I pass input query as below (here proc_test_final1 is an incorrect table name) :
insert into schema.proc_test_final1
select id, name, sal
from schema.proc_test_src;
Instead of throwing an error 'incorrect table name', the procedure returns a generic error like
Error: 090232 (25000): Stored procedure execution error: Scoped transaction started in stored procedure is incomplete and it was rolled back
I thought it might be because of ROLLBACK command so I tried removing the command but still it failed with the same above error. I also tried removing result variable in catch block but still above error was caught.
I want to catch the exact specific SQL error (syntax error/code error) in my glue job.
Below is my glue job code where I am catching the error:
input_sql = 'insert into schema.proc_test_final1 select id, name, sal from schema.proc_test_src'
try:
f_CallProc = "call TEST_PROC('"+input_sql+"');"
cur.execute(f_CallProc)
print(cur.fetchall())
cur.close()
ctx.close()
except snowflake.connector.errors.ProgrammingError as err:
print('Error: {0} ({1})'.format(err.msg, err.sfqid))
cur.close()
ctx.close()
sys.exit(1)
The error "Scoped transaction started in stored procedure is incomplete and it was rolled back" will happen when you run the SP that has explicit START TRANSACTION, but no explicit "ROLLBACK" or "COMMIT".
In my test, if I do not have below line:
snowflake.execute({sqlText:`ROLLBACK;`});
Your SP will fail with such error.
However, when I have this line, it will fail with below error instead:
Error: SQL compilation error:
Schema 'ERICLIN.SCHEMA' does not exist or not authorized.
Which I think is what you are after.
Can you please double check your SP again? Did you copy and paste the correct one?
By the way, your original SP won't run because there is no variable called "input_sql", it should be "INPUT_SQL", as every variable in Snowflake's SP is in UPPER case.
=========================
UPDATE
Please see below execution output:
create or replace procedure PROC_TEST
(input_sql varchar(16777216))
returns string not null
language javascript
as
$$
snowflake.execute({sqlText:`BEGIN TRANSACTION;`});
try {
var QueryExec = INPUT_SQL + ";";
var QueryResult = snowflake.execute({sqlText: QueryExec});
}
catch (err) {
result = 'Error: ' + err;
snowflake.execute({sqlText:`ROLLBACK;`});
return result;
}
$$;
call PROC_TEST('insert into schema.proc_test_final1 select id, name, sal from schema.proc_test_src');
+-----------------------------------------------------------+
| PROC_TEST |
|-----------------------------------------------------------|
| Error: SQL compilation error: |
| Schema 'ERICLIN.SCHEMA' does not exist or not authorized. |
+-----------------------------------------------------------+
Without the ROLLBACK call, it will produce an error same as yours:
create or replace procedure PROC_TEST
(input_sql varchar(16777216))
returns string not null
language javascript
as
$$
snowflake.execute({sqlText:`BEGIN TRANSACTION;`});
try {
var QueryExec = INPUT_SQL + ";";
var QueryResult = snowflake.execute({sqlText: QueryExec});
}
catch (err) {
result = 'Error: ' + err;
return result;
}
$$;
call PROC_TEST('insert into schema.proc_test_final1 select id, name, sal from schema.proc_test_src');
090232 (25000): Stored procedure execution error: Scoped transaction started in stored procedure is incomplete and it was rolled back.
I had a stored procedure to insert the data from a stage which is called by task. if the load fails(due to on_error= skip_file option) it throws an error which is handled. but the status of the task shows as success. what to do to make the task fail when there is error in stored procedure.
here is the sample code
create or replace procedure sample_procedure()
returns varchar not null
language javascript
execute as caller
as
$$
try
{
try
{
var ct_table_cmd = `create or replace table sample_table_temp like sample_table`;
var ct_table_stmt = snowflake.createStatement({sqlText: ct_table_cmd});
var result_set= ct_table_stmt.execute();
result_set.next();
}
catch(err)
{
var queryId = ct_table_stmt.getQueryId();
var queryText = ct_table_stmt.getSqlText();
var log_insert_into=snowflake.createStatement({sqlText:`insert into error_table
(code, message, queryid, querytext) VALUES (?,?,?,?);`
,binds : [err.code, err.message,queryId,queryText]
});
log_insert_into.execute();
var ct_task_ret_value = snowflake.createStatement({sqlText: `call system$set_return_value('{err.message'});`}).execute();
return err.message;
}
var copy_cmd = `copy into smaple_table_temp from #mystage
file_format=(format_name= 'sample_csv_format')
files=('/file_name')
on_error=skip_file;`;
var copy_cmd_stmt = snowflake.createStatement({sqlText:copy_cmd});
var result_set =copy_cmd_stmt.execute();
result_set.next();
if(result_set.getColumnValue(2)=='LOADED')
{
var swap_cmd = `alter table sample_table_temp swap with sample_table;`;
var swap_stmt = snowflake.createStatement({sqlText: swap_cmd});
swap_stmt.execute();
}
else if (result_set.getColumnValue(2)== 'LOAD_FAILED')
{
var err_message= result_set.getColumnValue(7);
var queryId = copy_cmd_stmt.getQueryId();
var queryText = copy_cmd_stmt.getSqlText();
var log_insert_into=snowflake.createStatement({sqlText:`insert into error_table
(code, message, queryid, querytext) VALUES (?,?,?,?);`
,binds : [err.code, err.message,queryId,queryText]
});
var task_ret_value = snowflake.createStatement({sqlText: `call system$set_return_value('{err_message'});`}).execute();
log_insert_into.execute();
return err_message
}
}
$$
;
The error log table and task to call the procedure is :
create or replace table error_table (ts timestamp_ntz, src varchar(50),code varhcar(100) ,
message varchar, queryid varchar, querytext varhcar);
create or replace task sample task
warehouse = 'my_warehouse'
schedule= '10 minute'
as
call sample_procedure();
when the task call the procedure with no data in the location it throws an error in the task history as "execution error in stored procedure sample procedure:
SQL compilation error:
Syntax error line at position 47 unexpected 'remote'. at statement.execute, line 172 position 111". but the actual error is "remote file is not existed at. there are several potential causes. The file might not exist. The required credentials may be missing or invalid."
and when the table is not existed, the error shown is different in task_history of information schema. It is not showing the error which is shown when the procedure is called independently (i.e call sample_procdure()).
Any suggestions are helpful.
You're setting the return value for the task here:
var ct_task_ret_value = snowflake.createStatement({sqlText: `call system$set_return_value('{err.message'});`}).execute();
You're setting the return for the stored procedure here:
return err.message;
The problem is err.message is a string containing the text of an error message, which is not an error indication. You've caught the error, so as far as Snowflake's concerned it's been handled.
To indicate an error on SP execution, you can either 1) not catch the error or 2) catch the error, handle it, and throw an error.
Option 2 seems to be what you're looking to do. Catch the error as you're already doing, but instead of returning err.message, do this:
//return err.message;
throw err.message;
Snowflake will wrap the error message with its own error text. There is currently no way to avoid that, so you may want to do something in the text to call out attention to your error text like *wrapping in stars* or something like that. Snowflake Stored Procedure Exception & Failure
I am able to do transactions in Hyperledger (fabric implementation). I want to see all the transactions and its payload details initiated by a user by passing the user's key.
for example:
A transfers 10 units to B
A transfers 5 units to C
D transfers 8 units to A
When I pass A's key then fabric must provide me all the transactions of A.
Is there any way? Or which fabric API function call should I use?
/chain/blocks/{Block} endpoint carries ordered list of transactions in a specified block.
Use /chain endpoint to get the height (number of blocks) of your chain, and then retrieve transactions from each block using /chain/blocks/{Block} REST endpoint.
You can develop the proper indexing and query function in your chaincode.
Meaning for each transaction you store its details in the internal key/value store (stub.PutState) with the user as key and return all the transactions associated to a user in your query (stub.GetState).
The best and simplest way is to use the shim package function
GetHistoryForKey(key string)
As the documentation says:
GetHistoryForKey function can be invoked by a chaincode to return a history of key values across time.
GetHistoryForKey is intended to be used for read-only queries.
IF anyone need Java SDk and go chaincode combination. There you go
answered here similar question
Java code
public List<HistoryDao> getUFOHistory(String key) throws Exception {
String[] args = { key };
Logger.getLogger(QueryChaincode.class.getName()).log(Level.INFO, "UFO communication history - " + args[0]);
Collection<ProposalResponse> responses1Query = ucc.getChannelClient().queryByChainCode("skynetchaincode", "getHistoryForUFO", args);
String stringResponse = null;
ArrayList<HistoryDao> newArrayList = new ArrayList<>();
for (ProposalResponse pres : responses1Query) {
stringResponse = new String(pres.getChaincodeActionResponsePayload());
Logger.getLogger(QueryChaincode.class.getName()).log(Level.INFO, stringResponse);
newArrayList = gson.fromJson(stringResponse, new TypeToken<ArrayList<HistoryDao>>() {
}.getType());
}
if (null == stringResponse)
stringResponse = "Not able to find any ufo communication history";
return newArrayList;
}
and you go chancode implemetation is as follows
Go code
func (t *SmartContract) getHistoryForUFO(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
if len(args) < 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
ufoId := args[0]
resultsIterator, err := APIstub.GetHistoryForKey(ufoId)
if err != nil {
return shim.Error(err.Error())
}
defer resultsIterator.Close()
var buffer bytes.Buffer
buffer.WriteString("[")
bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
response, err := resultsIterator.Next()
if err != nil {
return shim.Error(err.Error())
}
// Add a comma before array members, suppress it for the first array member
if bArrayMemberAlreadyWritten == true {
buffer.WriteString(",")
}
buffer.WriteString("{\"TxId\":")
buffer.WriteString("\"")
buffer.WriteString(response.TxId)
buffer.WriteString("\"")
buffer.WriteString(", \"Value\":")
// if it was a delete operation on given key, then we need to set the
//corresponding value null. Else, we will write the response.Value
//as-is (as the Value itself a JSON)
if response.IsDelete {
buffer.WriteString("null")
} else {
buffer.WriteString(string(response.Value))
}
buffer.WriteString(", \"Timestamp\":")
buffer.WriteString("\"")
buffer.WriteString(time.Unix(response.Timestamp.Seconds, int64(response.Timestamp.Nanos)).String())
buffer.WriteString("\"")
buffer.WriteString(", \"IsDelete\":")
buffer.WriteString("\"")
buffer.WriteString(strconv.FormatBool(response.IsDelete))
buffer.WriteString("\"")
buffer.WriteString("}")
bArrayMemberAlreadyWritten = true
}
buffer.WriteString("]")
fmt.Printf("- History returning:\n%s\n", buffer.String())
return shim.Success(buffer.Bytes())
}
Let me know if you question.
If you are using composer-client, you can simply use the Historian command.
var historian = await businessNetworkConnection.getHistorian();
historian.getAll().then(historianRecords => console.log(historianRecords));
The xpages contain SAVE button. The xpages also contain InternetAddres field.
When user click SAVE button, need to check first on names.nsf
- Save success if InternetAddress value NOT found in names.nsf view "($Users)"
- Save fail if InternetAddress value found in names.nsf view "($Users)"
How to write the script to do that?
This is the LotusScript version of script:
Set namesview = namesdb.GetView( "($Users)" )
Set namesdoc = namesview.GetDocumentByKey( Lcase(doc.CurrentInternetAddress( 0 ) ), True )
If ( namesdoc Is Nothing ) Then '-- Create New Doc
How to move on xpages?
The latest release of the OpenNTF Domino API adds a checkUnique() method to the View class. It takes two parameters, the first being a key to check against the view (e.g. a String or List of Strings), the second being the current document. After all, if you're checking for a pre-existing document, you don't want to fail just because it finds this document in the view.
So assuming CurrentInternetAddress is a single value field, the code would be:
function continueWithValidUser(namesDB, doc) {
var success = false;
try {
var view = namesDB.getView("($Users)");
success = view.checkUnique(doc.getItemValue("CurrentInternetAddress"),doc);
} catch (e) {
print(e.message);
}
return success;
}
OpenNTF Domino API recycles all handles to Domino objects, so the recycle() calls aren't needed.
In your datasource is a querySave event. You write JS there. It is almost the same code. Just with { } and ;
Remarks:
your app will break when there is more than one address book, so you you would want to use #NameLookup which is quite fast and checks all addressbooks.
unless you need the document getEntry is faster than getDocument
In SSJS your function would look like this:
function continueWithValidUser(namesDB, addressCandidate) {
var success = false;
try {
var view = namesDB.getView("($Users)");
var doc = view.getDocumentByKey(addressCandidate);
success = (doc != null);
doc.recycle();
view.recycle();
} catch (e) {
print(e.message);
}
return success;
}
That should do the trick
When i launch the php script, sometime works fine, but many other times it retrieve me this errror
Fatal error: Call to a member function children() on a non-object in
/membri/americanhorizon/ytvideo/rilevametadatadaurlyoutube.php on line
21
This is the first part of the code
// set feed URL
$feedURL = 'http://gdata.youtube.com/feeds/api/videos/dZec2Lbr_r8';
// read feed into SimpleXML object
$entry = simplexml_load_file($feedURL);
$video = parseVideoEntry($entry);
function parseVideoEntry($entry) {
$obj= new stdClass;
// get nodes in media: namespace for media information
$media = $entry->children('http://search.yahoo.com/mrss/'); //<----this is the doomed line 21
UPDATE: solution adopted
for ($i=0 ; $i< count($fileArray); $i++)
{
// set feed URL
$feedURL = 'http://gdata.youtube.com/feeds/api/videos/'.$fileArray[$i];
// read feed into SimpleXML object
$entry = simplexml_load_file($feedURL);
if (is_object($entry))
{
$video = parseVideoEntry($entry);
echo ($video->description."|".$video->length);
echo "<br>";
}
else
{
$i--;
}
}
In this mode i force the script to re-check the file that caused the error
You are first of all calling a function:
$entry = simplexml_load_file($feedURL);
That function has a return value. You find it documented on the manual page of that function:
http://php.net/simplexml_load_file
Then you use that return value in form of a variable $entry without verifying that the function call was successful.
Because of that, you run into an error next. However your error/mistake is how you treat the return value of the function.
Not dealing with return values properly is like calling for trouble. Read about the function you use, check the return value(s) and proceed according to success or error conditions.
$entry = simplexml_load_file($feedURL);
if (FALSE === $entry)
{
// youtube not available.
}
else
{
// that's what I love!
}
Sometimes? Really?
Take a look at this:
<?php
$dummy; //IN FACT, this var is NULL now
// Will throw exactly the same error you get
$dummy->children();
Why? Because, we can call method from an object type.
So, if you wanna avoid errors like this one, next time you would call the method ensure that it's "possible".
<?php
if ( is_object($dummy) && method_exists($dummy, 'children') ){
//sure it works
$dummy->children();
}