Procedure works well or return "error 500" depends of SOAP user

Version: 07.20.3239
Build: Feb 13 2024 (d698f21712)

One procedure works well with “SOAP” or “dba” user permissions:
Another procedure works well or returns “error 500” depends of SOAP user.
Problematic line in the procedure: foreach (any row in data) DO {

1
This 2 procedures will works well no matter if published with “SOAP” or “dba” user permissions:


1.1

create procedure XYZ.DBA.xyz_download (
out ret varchar
) {
for (sparql SELECT distinct * WHERE { ?s ?p ?o . } limit 5 ) DO {
ret := 'test';
}
}

1.2

create procedure XYZ.DBA.xyz_download (
out ret varchar
) {
declare qr, data, meta, message, state, env, ses any;
env := vector (dict_new (16000), 0, '', '', '', 0, 0, 0, 0, 0);
qr := 'sparql SELECT distinct * WHERE { ?s ?p ?o . } limit 5 ';
exec (qr, state, message, vector (), vector('use_cache', 1, 'max_rows', 0), meta, data);
ret := 'test';
}

2
This procedure works well published with “DBA” user permissions only:

create procedure XYZ.DBA.xyz_download (
out ret varchar
) {
declare qr, data, meta, message, state, env, ses any;
env := vector (dict_new (16000), 0, '', '', '', 0, 0, 0, 0, 0);
qr := 'sparql SELECT distinct * WHERE { ?s ?p ?o . } limit 5 ';
exec (qr, state, message, vector (), vector('use_cache', 1, 'max_rows', 0), meta, data);
foreach (any row in data) DO {
ret := 'test';
}
}

Or will return error then published with “SOAP” user permissions:
<faultstring>[Virtuoso SOAP server] SR016: Function length needs a string or array as its argument, not an argument of type 189 (= INTEGER)</faultstring>

The only difference between last two procedures:

foreach (any row in data) DO { 
...
}

3 Question

Why “foreach” works for “dba” user only ?
Is it a bug or feature ?

@MakeItWork

You should test state after exec(), see example. Also note exec() is a dynamic statement execution thus it compiles and executes on behalf of SQL user account in effect, where inline cursor is compiled and executed on behalf of SQL account which is used to create the stored procedure/service call.

HTH

Hello Mitko,

yes, you are right.

create procedure XYZ.DBA.xyz_download (
out ret varchar
) {
declare qr, data, meta, message, state, env, ses any;
state := '00000';
env := vector (dict_new (16000), 0, '', '', '', 0, 0, 0, 0, 0);
qr := 'sparql SELECT distinct * WHERE { ?s ?p ?o . } limit 5 ';
exec (qr, state, message, vector (), vector('use_cache', 1, 'max_rows', 0), meta, data);
if (state = '00000' and length (data) > 0) {
foreach (any row in data) DO {
ret := 'no errors';
}
}else{
ret := concat('error state: ', state);
}
}

Shows error state: 42000 for “SOAP” user.
However, no error occurs for “dba” user.

Same procedure named as
create procedure XYZ.SOAP.xyz_download
will do the same: return “no error” for “dba” user and error state: 42000 for “SOAP”.

Should Virtuoso work this way ?

@MakeItWork
If you look at “message” most probably will see permission error. This is because the user “SOAP” can’t compile SPARQL by default unless you do not grant permission to do so.

1 Like