June 8, 2006 at 8:00 am
I have a stored proc that is using OLE calls to use VB Reg Expr to run some pattern matching on a table of sentences.
The proc has 3 steps
1 create an instance of the VB Reg Expr Component
2 if successful run a select statement to return a recordset of all recs matching that expression by calling a udf passing into it the reference to the component
3 destroy the VB Reg Expr component
If either step 1 or 3 fails then I would like to be able to return to my calling ASP code a return code notifying it of the failure with a custom err message.
I would also like to be able to look at this return code first before deciding whether to display the rst if there are records.
Is there anyway I could retrieve a return value/output parameter first before a recordset?
My bodgy code so far which Im not happy with is this...
CREATE PROCEDURE [usp_asp_cms_find_pattern]
@SitePK int,
@TextType char(1),
@FindText varchar(50),
@SearchType char(1)
AS
declare@RegExp varchar(100),
@hr integer,
@objRegExp integer,
@results bit
begin
--create VB object
exec @hr = sp_OACreate 'VBScript.RegExp', @objRegExp output
if @hr <> 0
begin
set @results = 0
GOTO HANDLE_ERROR
end
SELECT 1 as success, '' as message
if @SearchType = 'e'--email
begin
set @regexp = '[a-z0-9_\.\-\'']+@[a-z0-9\.\-]+\.[a-z]{2,4}' --email reg exp
end
else --'p' phone
begin
set @regexp = '[0-9]+[0-9-\s]{4,}[0-9]+'--phone number reg exp
end
if @TextType = 'T'
begin
SELECT d.SentanceID as ID, d.Sentance as cDefault, c.Sentance as cCustom
FROMtbl_DEFAULT_SENTENCES as d
LEFT JOIN tbl_CUSTOM_SENTENCES as c
ONd.PageFK = c.PageFK AND
d.SentanceID = c.SentanceID AND
c.SiteFK = @SitePk
WHERE dbo.udf_REG_EXP(d.Sentance,@regexp,1)=1 OR
dbo.udf_REG_EXP(c.Sentance,@regexp,1)=1
ORDER BY d.SentanceID;
end
else
begin
SELECT d.MessageID as ID, d.Message as cDefault, c.Message as cCustom
FROM tbl_DEFAULT_MESSAGES as d
LEFT JOIN tbl_CUSTOM_MESSAGES as c
ON d.PageFK = c.PageFK AND
d.MessageID = c.MessageID AND
c.SiteFK = @SitePk
WHERE dbo.udf_REG_EXP(d.Message,@regexp,1)=1 OR
dbo.udf_REG_EXP(c.Message,@regexp,1)=1
ORDER BY d.MessageID;
end
--destroy VB Object
set @objRegExp = @objRegExp
exec @hr = sp_OADestroy @objRegExp
if @hr <> 0
begin
set @results = 0
GOTO HANDLE_ERROR
end
end
return
HANDLE_ERROR:
SELECT 0 as success, dbo.udf_ERROR_MESSAGE(@SitePK, 120,1) as message
GO
At the moment my code is fine unless it fails on the OADestroy part after I have run the select statement. If that happens I return 3 recordsets.
1st one lets me know that the sp_OACreate call worked as success=1
2nd one contains a results recordset which may or not be empty
3rd one contains an error message letting me know that one of the OA calls has failed.
However I want to know if any of the OA calls fails before I display the recordset and the only way I know in VBscript ADO of doing that is using GetRows to hold my results whilst I check other recordsets. Or call the proc twice once with just objCom.Execute so I could access the Return Code parameter and then again set objRS = objCom.Execute to get the recordsets.
Does anyone have any better ways of doing it?
June 8, 2006 at 9:15 am
Return the resultset last. Why does the sp succeed even though one of its OA calls fail?
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
June 8, 2006 at 9:30 am
The sp succeeds if only the OA destroy call fails as the select statement returns records but it cant destroy the OA object.
So if you mangle the sp to break the destroy call manually by doing this
--destroy VB Object
set @objRegExp = @objRegExp + 11 --break code
--set @objRegExp = @objRegExp
exec @hr = sp_OADestroy @objRegExp
if @hr 0
begin
set @results = 0
GOTO HANDLE_ERROR
end
this is what you get if you run in QA
declare @SitePK int,
@TextType char(1),
@FindText varchar(50),
@SearchType char(1)
set @SitePk = 18
set @TextType = 'T'
set @FindText = ''
set @SearchType = 'e'
exec usp_asp_cms_find_pattern @SitePK, @TextType, @FindText, @SearchType
successmessage
1
(1 row(s) affected)
IDcDefaultcCustom
8If you have not yet registered with us, please go to the registration page.If you have not yet registered with us, please email info@xxxxx.org or call 0207 XXX XXXX
(1 row(s) affected)
successmessage
0120: System Error! There was an error with the sp_OACreate object. Contact your system administrator.
(1 row(s) affected)
So I get a recordset of results that match the reg exp looking for email addresses in the second recordset but my error message is in the 3rd recordset which I don't want.
I would like to be able to get a success/fail result value that I can look at first and then decide whether to look at the recordset. With the code I have used I cannot do this as it falls over if the OA Destroy call breaks down.
June 8, 2006 at 10:59 am
What are you using for your front end? I don't see why you cant read all of the tables(recordsets), THEN display what you want.
June 8, 2006 at 11:08 am
Im using ASP. Thats what I said in my message the only way I know of doing it is to put my recordsets into an array then I can move through them get the success value then get the data out of the array.
I would like to know if theres a different way of doing it though as I dont want to have to change the code that displays the recordset to look at the array rather than the current code as its used for several different procs.
June 8, 2006 at 11:10 am
Hmm. Perhaps an output parameter that tells you if there was an error at the end?
June 8, 2006 at 11:17 am
But then I still would have to use a NextRecordset method to get to it as the actual results recordset would always come before the output parameter.
If I use ADO command object and assign the recs to the execute "set objRS = objCom.execute" I would have to move to next recordset to check output parameter then I would loose my results.
If I just did objCom.execute I could check the output parameter eg Result = objCom.parameters("result").value first but then i would have to call the command execute again to get the results.
Pain in the ass as I thought if you used Return values there was a way of accessing them before any result set returned but it seems not.
June 8, 2006 at 11:26 am
Hmmm. Didn't know it worked that way with old ASP and ADO. I am spoiled with .NET and my collections. Don't really know what to say.
One possiblility: Put all of your results into temp tables on SQL, and check them on the server. If your failure is there, decide what to send to the client. Otherwise, simply send it all.
Don't know if that makes sense or not....
June 8, 2006 at 11:27 am
in SQL8+, you could put the results in a varaible and wait until everything else is done before returning it. You could supress the rst at the source, rather than sending it to ASP to suppress. Also, don't bother returning a recordset to record success.
That way, the first(or only?) recordset you get will either be the results of the error or the results of the query. Not sure if that is what you're after...
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
June 8, 2006 at 11:34 am
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
June 8, 2006 at 11:57 am
That was first thing I tried this morning.
My test page ASP code is this:
dim objCom
dim intSitePK: intSitePK= 18
dim strFindText : strFindText= "''"
dim strSearchType : strSearchType = "e"
dim strTextType: strTextType= "T"
Connect()
set objCom = Server.CreateObject("ADODB.Command")
objCom.ActiveConnection = objData.getConnection()
objCom.CommandType = adCmdStoredProc
Response.Write("EXEC @rc = usp_asp_cms_find_pattern " & intSitePK & ", " & strTextType & "," & strFindText & ", " & strSearchType & "
")
objCom.CommandText = "dbo.usp_asp_cms_find_pattern"
objCom.parameters.append objCom.CreateParameter("RETURN_VALUE", adInteger, adParamReturnValue)
objCom.parameters.append objCom.CreateParameter("@SitePK",adInteger,adParamInput,0,intSitePK)
objCom.parameters.append objCom.CreateParameter("@TextType",adChar,adParamInput,1,strTextType)
objCom.parameters.append objCom.CreateParameter("@FindText",adVarchar,adParamInput,50,strFindText)
objCom.parameters.append objCom.CreateParameter("@SearchType",adChar,adParamInput,1,strSearchType)
set objRS = objCom.Execute
'objCom.Execute
intRetVal = objCom.Parameters("RETURN_VALUE")
if cint(intRetVal) = 1 then
do while not objRS.EOF
Response.Write(objRS("ID") & " - " & objRS("cDefault") & "
")
objRS.movenext
loop
objRS.close
else
Response.Write("IT ERRORED - Return Value was 0 No Recs")
end if
DisConnect()
which returns on the ASP page when run
EXEC @rc = usp_asp_cms_find_pattern 18, T,'', e
IT ERRORED - Return Value was 0 No Recs
and if you take that debug statement and run it directly on SQL QA like
declare @rc int
EXEC @rc = usp_asp_cms_find_pattern 18, 'T','', 'e'
if @rc = 1
print 'Return Val 1 Success'
else
print 'Return Val 0 Fail'
you get
successmessage
1
(1 row(s) affected)
IDcDefaultcCustom
8If you have not yet registered with us, please go to the registration page.If you have not yet registered with us, please email info@xxxxxxx.org or call 0207 xxx xxxx
(1 row(s) affected)
Return Val 1 Success
so u see you cant do what you said and I really wish you could but it just won't work like that. If you set a recordset to the objCom.execute you have to move through the recordsets to get the return value.
I changed my ASP to this
set objRS = objCom.Execute
set objRS = objRS.nextRecordset() 'to skip first select 1 as success
'loop through results
do while not objRS.EOF
Response.Write(objRS("ID") & " - " & objRS("cDefault") & "
")
objRS.movenext
loop
objRS.close
'have to close it first b4 getting return value
intRetVal = objCom.Parameters("RETURN_VALUE")
Response.Write("Return Value is " & intRetVal & "
")
set objRS = nothing
which produces
EXEC usp_asp_cms_find_pattern 18, T,'', e
8 - If you have not yet registered with us, please go to the registration page.
Return Value is 1
so you see its a bugger! You cant access return codes b4 recordsets
June 8, 2006 at 12:06 pm
Have you changed the stored proc to actually return a value? (If so, is it set up to be responsive to all errors?) - ah reading your last post again, it appears you have - sorry! But see my previous post.
1. Why not suppress the recordset at the server if an error occurs? Do you have complex logic?
2. Why not return an error rst before (or instead of, see 1) the final select * from @retval
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply