I have requirement like to call the stored procedures to get the data, here i will get the stored procedure name through post data.
I tried using GString but no use, Can any one help me to solve this issue.
Thanks in advance.
This is a weird one, but possible. Grails/GORM doesn't provide a way to execute stored procedures. It's just not part of ORM functionality. And neither does Hibernate. But, Hibernate does provide access to a JDBC connection. So you can get a connection from Hibernate, then create a Groovy Sql instance with the connection, and finally execute your stored procedure. Here's an example:
import groovy.sql.Sql
SomeDomainClass.withNewSession { session ->
session.doWork { java.sql.Connection connection ->
def sql = new Sql(connection)
sql.call("YOUR STORED PROCEDURE SQL HERE")
}
}
It works like this:
Using any of your domain classes, call withSession(Closure) to get a Hibernate session.
With the session, call doWork(Work) to get access to the session's JDBC connection. Now, doWork(Work) expects an implementation of org.hibernate.jdbc.Work. But, if I recall correctly, Groovy can take a closure with the same parameters and coerce it to implement the interface.
Using the connection, create an instance of Sql. You could skip this and query with Java, but Groovy's Sql class is so nice.
Use one of the available Sql.call() methods to execute your stored procedure.
In postgress SQL, it is posible to call stored procedure. The catch is returning a data table so that you can map it to a model. This is as shown bellow.
create function activate(confirmationcode text)
returns TABLE(resultid integer, resultmessage character varying)
language plpgsql
as $$
BEGIN
....
END
This can be invoked as follows in GORM db connections
type FuncResult struct {
Resultid int
Resultmessage string
}
...
fResult := FuncResult{}
err := s.db.Raw("SELECT * from activate(?)", token).Scan(&fResult).Error
Related
I have created a stored procedure with the behavior execute as OWNER (I need the owner’s rights).
I am looking to get the original role of the user that called it, is there any way to do that?
Unfortunately, as expected the select current_role() statement returns the owner's role ...
If a workaround exists, I would appreciate if you could describe it to me.
Following Mike's advice:there the code I done to test Harsh's solution:
Failed again ^^
There's my code. May be you ll see my mistake.
create or replace procedure do_noting_proc()
returns string
language javascript
execute as OWNER
AS
$$
var retour="Resultat";
try{
rs0=snowflake.createStatement({sqlText:"SELECT $QUERY_TAG;"}).execute();
cR=rs0.getColumnValue(1);
return "QRValue= "+callerRole;
}catch(err){
return "do_noting_proc KO: "+ err.message+";";
}
$$;
create or replace procedure test_proc()
returns string
language javascript
execute as CALLER
AS
$$
var rString="Result -->";
try{
rs0=snowflake.createStatement({sqlText:"SELECT CURRENT_ROLE();"}).execute();
rs0.next();
cr="testQT"+rs0.getColumnValue(1);
snowflake.createStatement({sqlText:"alter session set QUERY_TAG="+cr+";"}).execute();
rs=snowflake.createStatement({sqlText:"call PUBLIC.do_noting_proc();"}).execute();
rs.next();
rString+=rs.getColumnValue(1);
}catch(err){
return "test_proc: "+ err.message+";";
}
return "test_proc : "+rString;
$$;
Thencall share_view_or_table();
==>test_proc : ** Result -->do_noting_proc KO: Use of session variable '$QUERY_TAG' is not allowed in owners rights stored procedure;**
(procedure created by sysadmin and Executed as sysadmin)
Also if I run 'code'
select $QUERY_TAG;
I get the error: SQL compilation error: error line 1 at position 7 Session variable '$QUERY_TAG' does not exist
whereas
SHOW PARAMETERs LIKE 'QUERY_TAG' IN SESSION ;
works fine and print TESTQTSYSADMIN
#Harsh many thanks for your time
When using EXECUTE AS OWNER the rules do not permit reading the caller's session details, including their identity or role:
Owner’s rights stored procedures adhere to the following rules within a session:
[…]
Cannot access most caller-specific information. For example:
Cannot view, set, or unset the caller’s session variables.
Can read only specific session parameters, and cannot set or unset any of the caller’s session parameters.
Cannot query INFORMATION_SCHEMA table functions, such as AUTOMATIC_CLUSTERING_HISTORY, that return results based on the current user.
While inconvenient, you can use logic within the stored procedure to enforce that the role name of the caller should be passed as an argument:
CREATE OR REPLACE PROCEDURE PROC(ROLE_NAME STRING)
[…]
var VALID_ROLES_ARRAY = ["FOO", "BAR"];
var IS_VALID_CALLER_ROLENAME = VALID_ROLES_ARRAY.includes(ROLE_NAME);
[…];
CALL PROC(CURRENT_ROLE());
Does this mean we can not call some thing like this via Java API?
I get error - "Caused by: org.neo4j.graphdb.QueryExecutionException: Cannot perform schema updates in a transaction that has performed data updates."
This happens when I call schema update from a procedure call via neo4j console.
try (Transaction tx = db.beginTx()) {
String query = "CREATE INDEX ON :" + lbl + "(" + name + ")";
db.execute(query);
tx.success();
}
The Cypher query calling the procedure is already executed in a transaction, and there are no nested transactions in Neo4j: when you call db.beginTx(), you're getting the existing transaction, and it's not actually necessary unless you need the Transaction object (e.g. to create locks).
Anyway, even though it's not explicitly documented, it's apparently not possible to manipulate the schema from Neo4j procedures. You could say that it fails the use case of
To provide access to functionality that is not available in Cypher, such as manual indexes and schema introspection.
I created a test procedure similar to yours:
public class IndexProcedure {
#Context
public GraphDatabaseService db;
#Procedure
#PerformsWrites
public void index(#Name("label") String label, #Name("property") String property) {
db.schema().indexFor(Label.label(label)).on(property).create();
}
}
and ran it from the shell in the simplest Cypher query:
CALL my.package.index('Node', 'name');
Without the #PerformsWrite annotation, I get the following (expected) exception:
WARNING: Failed to invoke procedure my.package.index: Caused by: org.neo4j.graphdb.security.AuthorizationViolationException: Schema operations are not allowed for READ transactions.
With the annotation, I get the same exception as you:
WARNING: Failed to invoke procedure my.package.index: Caused by: org.neo4j.graphdb.QueryExecutionException: Cannot perform schema updates in a transaction that has performed data updates.
I guess the rationale is that setting up the schema is mostly a one-time operation that doesn't really need a procedure: if you're going to execute some Cypher query to call the procedure, you might as well run the script which creates the constraints and indices.
There could also be technical constraints: index creation is asynchronous and probably doesn't participate in the transaction (can you rollback the creation of an index?).
Or maybe it's just a bug? We should get someone from Neo to confirm.
Update: it will supposedly be fixed in Neo4j 3.1 when it's released, per a discussion on SlackHQ.
I am new to dropwizard. I am going through different tutorial but I couldnt find good example/tutorial on how to call stored procedure in dropwizard using JDBI.
With JDBI it is possible to specify an object SQL query as a method annotation. This string is treated by the DB as normal SQL. An example DAO to execute a stored procedure might look like:
public interface SomeQueries
{
#SqlQuery("call find_name_procedure(:id)")
String findName(#Bind("id") int id);
}
Where find_name_procedure has been previously defined.
For more information see http://jdbi.org/sql_object_api_queries/
Jooq is an elegant way to call stored procedures from java (See https://dzone.com/articles/using-stored-procedures-with-jpa-jdbc-meh-just-use). You also have a thirdparty module integrating Jooq into Dropwizard
(See http://modules.dropwizard.io/thirdparty/)
So if you're familiar with Maven, you can set up the combination quickly and start validating if it works in your case.
DropWizard JDBI provides two options to make a stored procedure call. Depending on what you want from Stored proc.
If you want resultset from Stored Proc, Andy has answered that already:
public interface DAO
{
#SqlQuery("call sp_name(:id)")
String query(#Bind("id") int id);
}
The other scenario is that your stored proc doesn't return resultset but gives out some output parameters. Here is what you can do:
#SqlCall("{ CALL sp_name(:id, :id2) }")
#OutParameter(name = "out", sqlType = Types.INTEGER)
OutParameters spCal(#Bind("id") long id, #Bind("id2") long id2);
OutParameter annotation may not work in DropWizard as the annotation was introduced in v3, you can use the following for accessing OutParameters:
try (Handle handle = dbi.open()) {
parameters = handle.createCall("CALL sp_name(:IN_Field1,:OUT_field2)")
.bind("IN_Field1", filed1)
.registerOutParameter("OUT_field2", Types.INTEGER)
.invoke();
}
And for some real freaky situations where you will need both Outparameters and resultset - DropWizard currently doesn't provide any direct way (Because the JDBI version with dropwizard is old). So, you can get connection by doing below:
handle = jdbi.open()
handle.getConnection()
And then do what you want to do with the connection.
Also, one more thing - I will not try to use Hibernate for Stored Proc call. Its just more pain.
I used Zalando Sprocwrapper. I like it and was widely used in the Zalando company to call PostgreSQL functions.
https://github.com/zalando-incubator/java-sproc-wrapper
I am using ORM Lite's .SqlList method to call a stored procedure and map the results to my custom object. When I am using only one parameter, and calling the stored procedure as follow it works fine:
var results = conn.SqlList<CustomObject>("EXEC MyStoredProcedure #paramOne"), new { paramOne = "someParam" });
When I want to call a stored procedure with more than one parameter and I call it as shown bellow I get an error stating that "The given key was not present in the dictionary.".
var results = conn.SqlList<CustomObject>("EXEC MyStoredProcedure #paramOne, #paramTwo"), new { paramOne = "someParam", paramTwo = "someOtherParam" });
I had a look at the sql stored procedure test page on the ORM Lite Github repo but it does not show how to call stored procedures with more that one param.
Thanks.
EDIT:
I should add that the second parameter on the sql side is a custom table type, and I am sending in a DataTable type in C#.
I am using VS2010, Entity Framework 4.0, and Advantage v. 10 in my application. I am trying to make a UDF I have defined in my Advantage DB available to my application code. The designer does not show the UDF under stored procs in the "Update Model from Database" wizard as I would expect it to. So I manually added the UDF to the SSDL as follows:
<Function Name="Test" ReturnType="numeric" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion">
<Parameter Name="PartID" Type="integer" Mode="In"/>
</Function>
I also added a CLR method stub:
[EdmFunction("namespace.Store", "Test")]
public static decimal Test(int partID)
{
throw new InvalidOperationException("Call from within an L2E query");
}
I can see the function in my Linq-to-Entities statement; however, the generated SQL is not valid. Using ToTraceString, the UDF call looks something like this:
"namespace.Store"."Test"("Project3"."PartID") AS "C4"
This gives me the following error:
System.Data.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> Advantage.Data.Provider.AdsException: Error 7200: AQE Error: State = 42000; NativeError = 2117; [iAnywhere Solutions][Advantage SQL Engine]Unexpected token: Scalar function name should not be delimited.
It works fine if I run the generated SQL in Advantage Data Architect and correct the function name like so:
Test("Project3"."PartID") AS "C4"
Is there anyway to tell Entity Framework to generate the correct SQL? Am I doing something wrong in the definition of the function in the SSDL?
Thanks in advance.
You need to change your function element to have BuiltIn="true". User Defined Functions are not quoted in the Advantage SQL grammar.
It looks good. Only thing i would recommend is to change the decimal to be nullable but i doubt that would fix the problem because then you would see a different exception. its worth a try. I do covered the function a while back.
http://weblogs.asp.net/zeeshanhirani/archive/2010/04/08/calling-user-defined-database-function-from-linq.aspx