On 09-Nov-2011 18:19 , Hal wrote:
>> Hmmm, no info about the CREATE PROCEDURE; nor the QMQRY source,
>> nor the CLP source statement doing the STRQMQRY SETVAR(()). No
>> matter probably, since...
>>
>
> I apologize. I should have included all of the source code.
> Let me preface the code briefly...because I'm thinking you'll
> shudder when you see it. I have never had any as/400 programming
> training so what you see is the result of self-taught fumbling.
> With that..here it is.
>
> PGM PARM(&USER)
> DCL VAR(&BADUSR) TYPE(*LGL) VALUE('0')
> DCL VAR(&USER) TYPE(*CHAR) LEN(10) /* DECLARE +
> THE PARM THAT IS PASSED IN */
> DCL VAR(&USR2) TYPE(*CHAR) LEN(12) /* USERNAME +
> W/ QUOTES FOR STRQMQRY USE */
> DCL VAR(&DLM) TYPE(*CHAR) LEN(1) VALUE('''')
> CHGVAR VAR(&USR2) VALUE(&DLM *TCAT &USER *TCAT &DLM) +
> /* ADD QUOTES TO EITHER SIDE OF THE +
> USER VARIABLE SO IT CAN BE USED IN THE +
> QUERY MANAGER QUERY */
> STRQMQRY QMQRY(QGPL/DLTUSRP) RDBCNNMTH(*DUW) +
> NAMING(*SQL) SETVAR((USR &USR2))
> STRQMQRY QMQRY(QGPL/DLTUSPP) RDBCNNMTH(*DUW) +
> NAMING(*SQL) SETVAR((USR &USR2))
> STRQMQRY QMQRY(QGPL/DLTUSAP) RDBCNNMTH(*DUW) +
> NAMING(*SQL) SETVAR((USR &USR2))
> IF COND(&USER *EQ '***********') +
> THEN( CHGVAR VAR(&BADUSR) VALUE('1'))
> IF COND(&USER *EQ '*********') +
> THEN( CHGVAR VAR(&BADUSR) VALUE('1'))
> IF COND(&BADUSR *EQ '0')
> THEN(DO)
> DLTUSRPRF USRPRF(&USER) OWNOBJOPT(*DLT)
> MONMSG MSGID(CPF2204)
> ENDDO
> IF COND(&BADUSR *EQ '1') +
> THEN( SNDUSRMSG MSG('Not allowed to delete this user') +
> MSGTYPE(*INFO) )
> ENDPGM
>
> The QM queries are all the same as far as the bottom variable goes,
> so I will post the first one:
>
> SQL Statement:
> ********* Begin of Data *********
> DELETE FROM CPDATA.AUSAP
> WHERE USAKUSR = &USR
> ********** End of Data **********
>
> This is where I had to pad the variable with the single quotes
> because USAKUSR is a character field. I couldn't figure out how
> to do that in the query, so I did it in the CL.
FWiW: Since the "Variable value" on the SETVAR parameter allows an
expression, the concatenation can be done as an expression on the SETVAR
rather than in a [temporary] variable.
strqmqry dlmusrqm setvar((USR (&dlm *cat &usr *cat &dlm)))
> Now, I get a different error than the one you posted below when I
> execute the call via DbVisualizer(JDBC app, using the JT400.JAR
> driver).
>
> Job: QZDASSINIT User: QUSER Number: 029182
> Job 029182/QUSER/QZDASSINIT started
> on 11/08/11 at 09:12:49 in subsystem QUSRWRK in QSYS.
> Job entered system on 11/08/11 at 09:12:49.
> User BLAW from client 1.2.3.4 connected to server.
> Token CHRIS was not valid. Valid tokens:<END-OF-STATEMENT>.
> RUN QUERY command failed with SQLCODE -104.
> RUN QUERY command ended due to error.
> STRQMQRY command failed.
> Function check. QWM2701 unmonitored by DLTUSR at statement
> 1200, instruction X'001A'.
> QWM2701 received by DLTUSR at 1200. (C D I R)
>
> What puzzles me is the line I put the asterisks on. "Token CHRIS was
> not valid". I made the call in interactive SQL like this:
>
> call qgpl.dltusr('DUMMY')
>
> I'm not sure where the CHRIS value comes from.
I infer the same invocation was made via JDBC.? On the old release I
have to test, the STRQMQRY has an obvious problem with NAMING(*SQL). I
get msgQWM2707 suggesting that "*LIBL not allowed when SQL naming
applied" even though I had no unqualified references in the query. I
presume a variation of the same problem may exist on the release where
the above JDBC was attempted, but now manifest with the "authorization
identifier", the user name CHRIS, being added to the statement text
similar to how the *LIBL seems to have impacted my similar invocation.
When I used NAMING(*SYS), the CLP as stored procedure [i.e. the
STRQMQRY request(s)] functioned well from DB2 command line in QShell and
from a REXX SQL CALL.
> I get a different error, and it is indeed exactly the one you
> posted, if I try that same call as above inside a STRSQL
> green-screen interactive SQL session.
>
> Anyway, the program works fine from an os/400 command line. Any
> suggestions on what I can do to improve the code?
Without knowing more about requirements, who\when called and why, I
have little to suggest; I would remove or resend the error(s), but that
is overkill for most operator-like utilities. I have a preference for
different formatting than what SEU provides, but what I prefer is
unlikely helpful to anyone.
> I did write a "Hello world" REXX program today after I found some
> docs on your mention of that being another method to do this type
> of thing. Maybe that would be a better way to tackle this.
>
Avoiding the restriction from STRSQL, and using system naming instead
of SQL naming, perhaps what exists already, could be made to function as
expected. I would probably use REXX instead though, just because of the
flexibility to use both CL and SQL; being new to REXX and SQL in REXX
might be a burden. Note: a CMD can invoke a REXX procedure instead of a
*PGM as CPP, and LANGUAGE REXX can be defined for an external stored
procedure. Also FWiW, for "destructive" work, I tend to generate a
script for running later or force prompting for running now; i.e.
DLTxxxyyy often might better be reviewed versus performed directly in
the program with little visibility to the invoker, beyond logged
[completion] messages.
Regards, Chuck