Reputation: 346
I am very new to C# and VFP(Visual fox pro). My first goal is to run and test a simple update query using query builder of MS visual studio. After adding a VFP database successfully(now I can preview data and execute select statements), I executed the following query and I am getting SQL Execution error where error message is: Trigger failed in Inventory.
UPDATE inventory SET location = 'test' WHERE inventoryid = 221
I dont understand what is wrong and Is there any better ways to learn and play with VFP database?
Update
Thanks to everyone. This database came up with a software. Since I was able to connect to the database and export some files after building an external app, I thought I could easily update few information too. Since now I have VFP and I dont have any source code of the whole software,
Is there any possibility that I might not find a way out to find or modify the trigger function and the stored procedure since it is part of a packaged software?
I just have the installed software and the VFP database inside it. The software talks to that VFP database.
Updated 2
I found the stored procedure in a FPT file under a different folder which is a location of an another system database. This is the code:
PROCEDURE InventoryUpdateTrigger(tcAlias,tcSource,tlHis)
IF VARTYPE(glNoTrigger) = "L"
IF glNoTrigger
RETURN .t.
ENDIF
ENDIF
IF VARTYPE(goApp) <> "O"
RETURN .f.
ENDIF
LOCAL laFieldList(1),laDataValues(1,3), laDataFields(1)
LOCAL lcCriticalFields, lnFields, lcField, llRetVal,lnItemid,lnAlias,;
lcPtNo, llBBHasChanged, lnField, lcNewVal, lcOldVal, lcSource, lnInventoryid
lnAlias = SELECT(0)
llRetVal = .t.
lcCriticalFields = "ITEMID,ITEMNUMBER,MFGR,SERIALNUMBER,"+;
"DESCRIPTION,WAREHOUSE,MACHINETYPE,QTY,UNITCOST,STATUS,RECEIVESTATUS,"+;
"FREIGHTIN,CONDITIONCODE,DATERECEIVED,BREAKDOWNINVENTORYID,"+;
"DATEALLOCATED,ALLOCATEDBY,DATEUNBOOKED,UNBOOKEDBY,LOCATION"
llBBHasChanged = .f.
BEGIN TRANSACTION
TRY
lnInventoryid = EVALUATE(tcAlias+".inventoryid")
lnItemid = EVALUATE(tcAlias+".itemid")
SELECT (tcAlias)
lnDataFields = AFIELDS(laDataFields,tcAlias)
DIMENSION laDataValues(lnDataFields,3)
FOR lnField = 1 TO lnDataFields
lcField = ALLTRIM(laDataFields(lnField,1))
lcNewVal = ALLTRIM(TRANSFORM(EVALUATE(tcAlias+"."+lcField)))
lcOldVal = ALLTRIM(TRANSFORM(OLDVAL(lcField,tcAlias)))
laDataValues(lnField,1) = lcField
laDataValues(lnField,2) = lcOldVal
laDataValues(lnField,3) = lcNewVal
IF !llBBHasChanged
IF UPPER(lcField) $ UPPER(lcCriticalFields)
IF GETFLDSTATE(lcField,tcAlias) > 1
llBBHasChanged = .t.
ENDIF
ENDIF
ENDIF
ENDFOR
IF goapp.osystem.audit_inventory
llRetVal = UpdateDatabaseAudit(IIF(tlHis,"INVENTORYHIS","INVENTORY"), lnInventoryid,;
goapp.nUserid, AUDIT_UPDATE, tcSource, @laDataFields,@laDataValues)
ENDIF
IF llRetVal
LOCAL llUpdateBrokerBin
llUpdateBrokerBin = .f.
IF llBBHasChanged
IF !tlHis
** need to update brokerbin
IF GETFLDSTATE("STATUS",tcAlias) > 1 OR GETFLDSTATE("RECEIVESTATUS",tcAlias) > 1
lcOldReceive = OLDVAL("ReceiveStatus",tcAlias)
lcNewReceive = EVALUATE(tcAlias+".ReceiveStatus")
lcOldStatus = OLDVAL("Status",tcalias)
lcNewStatus = EVALUATE(tcAlias+".Status")
lnCase = 0
DO case
CASE lcOldReceive <> STATUS_RECEIVED ;
AND lcNewReceive = STATUS_RECEIVED ;
AND lcNewStatus = STATUS_OPEN
llUpdateBrokerBin = .t.
lnCase = 1
CASE lcOldStatus = STATUS_OPEN ;
AND lcNewStatus = STATUS_ALLOCATED ;
AND lcNewReceive = STATUS_RECEIVED
llUPdateBrokerBin = .t.
lnCase = 2
CASE lcOldReceive = STATUS_RECEIVED ;
AND lcNewReceive <> STATUS_RECEIVED ;
AND lcNewStatus = STATUS_OPEN
llUpdateBrokerBin = .t.
lnCase = 3
CASE lcOldStatus = STATUS_ALLOCATED ;
AND lcNewStatus = STATUS_OPEN ;
AND lcNewReceive = STATUS_RECEIVED
llUPdateBrokerBin = .t.
lnCase = 4
CASE lcOldStatus <> STATUS_BOOKED ;
AND lcNewStatus = STATUS_BOOKED
llUpdateBrokerBin = .t.
lnCase = 5
CASE lcOldStatus = STATUS_BOOKED ;
AND lcNewStatus <> STATUS_BOOKED
llUpdateBrokerBin = .t.
lnCase = 6
ENDCASE
ELSE
lcReceive = EVALUATE(tcAlias+".ReceiveStatus")
lcStatus = EVALUATE(tcAlias+".Status")
IF lcReceive = STATUS_RECEIVED AND lcStatus = STATUS_OPEN
llUpdateBrokerBin = .t.
ENDIF
ENDIF
IF llUpdateBrokerBin
llRetVal = setbrokerbintoprocess(lnItemid,lnInventoryid,0,tcAlias,"INVENTORY","UPDATE")
ENDIF
ENDIF
ENDIF
ENDIF
CATCH TO loException
llRetVal = .f.
RecordError(loException.ErrorNo, loException.LineNo, loException.Message,loException.Procedure)
FINALLY
IF llRetVal
END TRANSACTION
ELSE
ROLLBACK
ENDIF
ENDTRY
SELECT (lnAlias)
RETURN llRetVal
ENDPROC
It leads to many questions which I think that is part of learning VFP first and it is not about simply running a SQL statement.
Upvotes: 0
Views: 1189
Reputation: 23797
@Robi, If you don't have a need to work with existing VFP databases, then it is unlikely you would want to work with them. I suggest you to use one of the many other databases that have ODBC and/or OLEDB drivers (MS SQL Server, PostgreSQL, MariaDb, MySQL, Oracle, SQLite just to name a few). You can work with such databases using C# or VFP. With C# you not only have access to those with ODBC and/or OLEDB drivers but to almost any database (like the relatively newer NoSQL databases). This is just a suggestion. If you would anyway use VFP database from C#, keep in mind that you need to own VFP to do some tasks at database level, and not all commands are supported through VFPOLEDB driver. Also note that VFPOLEDB driver is 32 bits (don't forget to target x86 from C# IOW). Also the VFPOLEDB driver unfortunately doesn't behave the same way when you use it from C# or VFP.
Having said that, assuming you would anyway use a VFP database and want to debug this case, it is easier to do it from within VFP. For a seasoned developer there would be other ways, but I think this one is the easiest for a newcomer. In command window:
use ('inventory')[enter]
modify structure[enter]
(you may need to write fullpath to yourTable if it is not in search path, you don't need to set default to that folder)
This would bring up a tabbed dialog. Choose "Table" tab and check the procedure name next to "Update trigger". So now you know which procedure is called for update trigger. Copy the name from there and close that dialog.
Now type this:
Set Database to[spacebar]
as soon as you press spacebar VFP would show you a database list (likely with one element). Choose the one that this table belongs to and press [enter]. Then type:
Modify Procedure [enter]
Now you should see the code window with "Stored Procedure"s for that database. Locate the procedure that you got from update trigger (hint: in standart toolbar there is an icon with a document and magnifier - "Document View Window". If you bring it up and then click back to code window, you would see all the procedure names in that code file. Clicking the procedure name in doc. window would directly take you to the code location).
Now assuming you are good up to this point, and found the procedure that update trigger calls you need to find out why it is failing. To debug, just after "Procedure ..." line (and also after "lparameters ..." or "parameters ..." line if there is one) insert this line of code:
set step on
Press Ctrl+W to save. Now run your update command from command line:
UPDATE inventory SET location = 'test' WHERE inventoryid = 221
If would hit your "set step on" line and the debugger would pop up. Now you can do all sorts of debugging (after all these years and the glory of VS2013, I still seem to miss VFP's debugging capabilities compared to C# - most of which is discovered in advanced development).
I would bet "location" is coming from a lookup table, which someone created a referential integrity (missing 'test' in the lookup would cause the trigger to fail).
Upvotes: 0
Reputation: 48139
Do you even have VFP to work with?
If you do, run it. In the command window, type
CD "path to where the database is located" [enter]
OPEN DATABASE NameOfYourDatabase [enter]
MODIFY DATABASE [enter]
This will bring up the database and show all the tables and whatever relationships between the tables in question. From there, right-click and popup menu will have "Stored Procedures". The code is embedded in the database container.
Also, for the specific inventory table, you can do a find within the opened database. Then right-click on it and click "Modify...". This will bring up the details about the table... Columns, sizes, indexes, and a "tab" page for the overall table showing what rules to apply and methods to call for insert, update and delete triggers.
This should get you started (provided you HAVE VFP to begin with).
FEEDBACK...
Since you have VFP9, once started, in the command window, type
CD ? [enter]
the "?" will ask you for a folder to change directory to. Pick the directory where your database is located.
Once there, then type
OPEN DATABASE ? [enter]
and it should ask which database to open... pick it.
then
MODIFY DATABASE [enter]
it will open a window showing all the tables and whatever relationships are in the database.
Right-click in the database in any open area and then click "Stored Procedures". This will bring up the code window for the stored procedures.
Now, with respect to the tables that have triggers, back in the modify database window, if you pick a table that you know has triggers (per your example), right-click on the table and modify. it will bring up a tab screen showing the fields, indexes and then table. The "Table" tab has the triggers and any rules for validation and insert/update/delete triggers.
Hopefully this will help you find your issue.
Upvotes: 1