Snowflake Global function and variable - stored-procedures

I have a many (snowflake) javascript stored procedures per data pipeline , in all the procedures I have this function defined.
create or replace procedure procedure1()
returns strint
language javascript
as
'
function returnResult(sql_text){
rs = snowflake.execute({sqlText:sql_text});
rs.next();
return rs.getColumnValue(1);
}
--declare constants
--declare variables
--perform some checks
return returnResult(`call procedure2('param1', 'param2')`);
'
;
I use this to execute sql's multiple times inside the same procedure .like
return returnResult(`call procedure2('param1', 'param2')`);
Note: I don't want to use the function call in 'select statement'
Is there a way I store this function 'returnResult' globally once and use in all the stored procedures ?
Along with this, Can I define any variable globally and use in multiple stored procedures (pipelines) ?
I tried creating UDF's but it does not look to be the right approach.

There is currently no way to define helper functions globally for Snowflake JavaScript stored procedures or UDFs. You need to include the helper functions in every stored procedure or UDF that references them.
Since Snowflake Java stored procedures and UDFs can reference compiled JAR files, you can implement a single helper function (or in fact an entire class) and reuse that code across a number of different stored procedures. Python stored procedures and UDFs can also reference compiled pickle files, so they can reference shared functions and libraries too.
It's also possible to have Snowflake compile Java or Python stored procedures and UDFs if you do not want to deal with external IDEs or a framework like Snowpark. That way a main SP or UDF can include a number of functions that other SPs or UDFs reference.

Related

Why can I export the same function multiple times?

When I export a procedure ha from a library multiple times:
library hahaha;
procedure ha;
begin
Writeln('ha')
end;
exports
ha, ha, ha;
end.
Delphi neatly creates a .dll with three procedures:
I was surprised that the ambiguous call GetProcAddress(LoadLibrary('hahaha.dll'), 'ha') doesn't fail.
That made me wonder: is there a case where this is useful?
One place where this is useful is when you wish to export the function multiple times with different names. For instance, if we were attempting to re-implement user32 in Delphi we might have exports like this:
exports
SetWindowTextA,
SetWindowTextA name 'SetWindowText';
In your case though you are exporting the same function multiple times with the same name and different ordinal values. Why would you want to do that? I can see no good reason for wanting to do that. However, why should the compiler stop you from doing this? It would take effort from the compiler developer to do so, and what would be gained?
My guess therefore, is that the compiler developer did not implement a block on multiple exports with the same name because either:
They did not consider that case, or
They considered it and determined that the effort involved in blocking multiple same-name imports would not provide enough benefit to justify the development cost.
As for what happens when you call GetProcAddress with a function name that has been exported multiple times, the system will return the first exported function whose name matches.

Code sample for freeing advantage database server table

I have a set of tables that were included in an Advantage Database data dictionary. The dictionary is no longer available, and the tables will not open.
I would like to free those tables using code (not the Advantage Data Architect).
The only reference I can find to this is a function listed in the help called ADSDDFreeTable.
The documentation for the function is at this link:
http://devzone.advantagedatabase.com/dz/WebHelp/Advantage11.1/index.html?ace_adsddfreetable.htm
but it does not offer a code sample, and I cannot understand how to use it.
Would anyone be kind enough to show a code sample of how this function is used (with variables, not literals, for file names, etc)
Thanks very much!
Ace.pas defines AdsDDFreeTable as
function AdsDDFreeTable( pucTableName: PAceChar;
pucPassword: PAceChar ):UNSIGNED32; {$IFDEF WIN32}stdcall;{$ENDIF}{$IFDEF LINUX}cdecl;{$ENDIF}
The same Ace.pas defines PAceChar:
type
PAceChar = PAnsiChar;
Therefore, the call to the function should be fairly straightforward:
var
TableName: AnsiString;
begin
TableName := 'C:\Data\MyTable.adt`;
if AdsDDFreeTable(PAnsiChar(TableName), nil) <> ADS_FREETABLEFAILED then
ShowMessage('Table removed from datadictionary')
else
// Call ADSGetLastError to retrieve reason for failure;
end;
In addition to #Ken's solution (+1), there is also a standalone command line utility named freeadt.exe that will free ADT tables from their associated data dictionary. I believe it is installed with Advantage Data Architect.
If you run it from the command line with no parameters, it displays usage information. In general, though, you can give it a folder name (to process all the tables) or a specific file as a parameter.

Can we use RTTI to find functions/procedures by name and run them?

As we can find a Property or an Object using RTTI, can we search for a certain function or procedure (not from an object as a method but from an unit) loaded in memory knowing just it's name?
And if we can, is it possible to execute it sending it's parameters?
Delphi's RTTI system is based around types. However, procedures and functions with unit scope are not associated with types and so cannot be reached using RTTI.

How to create default parameters for DLL procedures (stdcall)?

I have made a DLL which exports several functions (with stdcall).
I want to have some of them accept parameters or not. So a lazy programmer can just call it without any parameters.
I read somewhere on a forum that default parameters don't work in DLL-s. Is my only option is creating 2 functions with different names, like:
procedure DoSomething();
begin
DoSomethingParams(1, 'Hi');
end;
procedure DoSomethingParams(one: Integer; two: PChar);
begin
//
end;
? Or maybe there is a more elegant way to achieve this?
Default parameters can be used with DLLs. But the default parameters must be declared when the function is imported rather than when it is exported. That's because default parameters are implemented at the call site. The caller detects that parameters are missing and generates code to supply the missing parameters.
So you can use default parameters when you import the DLL, provided that the language that consumes the DLL supports that.
In the DLL code, export the function. You can specify default parameters there if you wish, but it won't have any effect for the consumer of the DLL.
In the code that imports the DLL function, declare your default parameters. It is the default values declared at this point that matter.
Since DLLs are typically used to provide language neutral interfaces, and since some languages do not support default parameters, it is rare to use them in DLL interfaces.

How use TDataset and Dll with Delphi

I'd like create a dll to import data from a file (different format, for example csv, txt, xls, ...). My idea is this: the dll load the data with her "engine" then send this data to my application so my application can show them inside a grid.
This is my second DLL so I have some problems/questions.
I think my DLL should send the data to a TDataset on my application but how can I call a DLL with a TDataset as argument?
Any suggestions?
What is the easiest way to accomplish what I have in mind? (if possible)
If you are the creator of those DLL's, then consider to use packages instead of DLL. This will avoid the problems, like dublicate Delphi RTTI, plain DLL API. Then you will need to properly split classes between packages, load packages statically or dynamically, get reference to a class implementing import engine, and call the corresponding method with a dataset reference as a parameter value.
Easier way for you would be to store the data directly into database in DLL. And after import you just refresh your TDataset.
BTW, you don't "call DLL", you call some method that is public in DLL and there you can use arguments as in normal methods.
EDIT: For more generic DLLs that don't require data components just send data in struct
TMyData
{ int ID;
String Value;
};
int MyDataImport(TMyData & data)
{
...
}

Resources