My C++ functions for postgres use a parameter (the path to the config) for static singleton Config class, now it is set from Cmake via definitions. I want to make the path specified like an argv parameter in the main function. However, my functions are just a shared (.so) library. Is there any way to achieve such functionality ?
Now I use this vartiant:
add_compile_definitions(CONFIG_PATH="/some/path/to/config.ini)
Also I have sql script for creating postgres functions:
CREATE OR REPLACE FUNCTION some() RETURNS text
AS 'postgres_Clibrary.so', 'someFunction'
LANGUAGE C;
And load functions as:
psql -f create_functions.sql
And I want to change this to something like:
psql -f create_functions.sql -DPATH_TO_CONFIG="/some/path/to/config.ini"
Is there any variant to get similar functionality as I want ?
How to do it without recompilation ?
I think you could use a default value for a parameter here.
Define your function so that it has an additional parameter config_path. That parameter has to be the last one. Then you can define the function as
CREATE FUNCTION some(
first_param text,
config_path text DEFAULT '/some/path/to/config.ini'
) RETURNS text
AS 'postgres_Clibrary.so', 'someFunction'
LANGUAGE C;
Now you can simply call the function with
SELECT some('first_arg');
and the default value will be substituted for the second argument.
Related
I was looking inside the create_vlabel function and noted that to get the graph_name and label_name it is used graph_name = PG_GETARG_NAME(0) and label_name = PG_GETARG_NAME(1). Since these two variables are also passed as parameters, I was thinking that, if I wanted to add one more parameter to this function, then I would need to use PG_GETARG_NAME(2) to get this parameter and use it in the function's logic. Is my assumption correct or do I need to do more tweaks to do this?
You are correct, but you also need to change the function signature in the "age--1.2.0.sql" file, updating the arguments:
CREATE FUNCTION ag_catalog.create_vlabel(graph_name name, label_name name, type new_argument)
RETURNS void
LANGUAGE c
AS 'MODULE_PATHNAME';
Note that all arguments come as a "Datum" struct, and PG_GETARG_NAME automatically converts it to a "Name" struct. If you need an argument as int32, for example, you should use PG_GETARG_INT32(index_of_the_argument), for strings, PG_GETARG_CSTRING(n), and so on.
Yes, your assumption is correct. If you want to add an additional parameter to the create_vlabel function in PostgreSQL, you can retrieve the value of the third argument using PG_GETARG_NAME(2). Keep in mind that you may need to make additional modifications to the function's logic to handle the new parameter correctly.
The answers given by Fahad Zaheer and Marco Souza are correct, but you can also create a Variadic function, with which you could have n number of arguments but one drawback is that you would have to check the type yourself. You can find more information here. You can also check many Apache Age functions made this way e.g agtype_to_int2.
Consider a codebase with this file structure:
myScript.m (Script)
+modA/
fn.m (Function)
+modB/
fn.m (Function)
myScript.m must choose which of modA.fn or modB.fn to call at runtime using the outcome of a string str_moduleName.
Is there a way to avoid calling feval([str_moduleName,'.fn']) ?
I haven't tried this, but I guess you could build a struct with function handles:
S.modA = #modA.fn
S.modB = #modB.fn
Then you can call the function using the value of str_moduleName as follows:
S.(str_moduleName)()
When I create a custom type summary using a Python script, it is possible to access ivars using value.GetChildMemberByName("<child-name>"). However, this does not work for computed properties or functions.
With the frame variable command, the script that generates the summary can evaluate expressions in the current frame (e.g. value.GetFrame().EvaluateExpression(value.GetName() + ".description"))
However, this will not work when using p <some-expression>/expression -- <some-expression> as there is no frame, so the above statement will fail to produce any results.
Is there a way to call functions or evaluate computed properties in a type summary when using p (expression --)?
You might what to use SBValue.CreateValueFromExpression instead of either the frame or the target EvaluateExpression calls for data formatters.
SBValues remember the context they were defined in, and SBValue.CreateValueFromExpression funnels that context back to the expression evaluator. Since the Variable formatters always receive the SBValue that they are acting on, CreateValueFromExpression allows a simple way to forward that context to the new expression.
The EvaluateExpression function is available on the target as well as on frames. Try value.GetTarget().EvaluateExpression(...).
How do I use Simulink.Bus.createMATLABStruct inside a function? I'm loading some bus definitions in the function's scope but createMATLABStruct doesn't see those. If I load the bus definitions in the global workspace then the function works.
Doesn't work:
function test()
load('someBuses.mat');
s = Simulink.Bus.createMATLABStruct('aBus');
end
Works:
load('someBuses.mat');
% ...
function test()
s = Simulink.Bus.createMATLABStruct('aBus');
end
Any ideas?
Simulink.Bus.createMATLABStruct accepts a 4th (undocumented) input -- open the file in the editor to see the 4th input -- which can either be 'base' (the default) or a Data Dictionary object.
The default is 'base', which is why the version you have that loads from the Base Workspace works.
Have a look at this link to find out about creating Data Dictionaries.
I'd like to use the data that are loaded to my workspace in a Matlab function. This is the beginning of my function.
function [totalProfit] = compute(p,exit)
%% Declaration of variables
entry=0;
T = length(data);
.
.
.
end
I'm getting an error:
Undefined function or variable 'data'.
Where is the error?
The variable data was probably defined outside of the function, so it is out of scope.
Pass data as a parameter to compute and then it will be available inside the function.
You can use evalin to work with variables from another workspace. In your example this could be
T = evalin('caller','length(data)')
But please note that in most cases you get cleaner code if you define the variable as input argument for the function. So for your case this would be
function [totalProfit] = compute(p,exit,data)
T = length(data) ;
end
Ran is correct, but I wanted to mention something else. In general, only variables that are passed as arguments to a function are able to be used inside that function, so if you want to use your existing variables inside the function, pass them as input arguments.
It is possible to create global variables which allow you to use them inside functions without passing them as arguments, but it's usually not the best way of writing code. The times where I have used global variables are where I am calling multiple functions from a single script, and I have some constants that will be used by all the functions (for example gravity is a common one). An alternative to global variables is to use a struct, with the variables you want to pass to the function in it, so you only need one extra input argument, but you still have to be a bit careful.