Also earlier, write another section. I am going to travel with a girl with a girl to travel with the identity of my quasi-boyfriend. By the way, I will give it a quasi-word. I have been waiting for two years ...
Third, solve the first problem with expansion stored procedures
Although there are some suspects who use the Wark to destroy the mice, but it is not a way to get a way. It is more important that I can take the idea to finish the idea. Although tomato is a good thing, I will eat more, too fat. Friends don't want ................ You are 俺, haha, it's it ~~
Create an extended stored procedure project in VS.NET, named XstrainQuery, and then set the extended stored procedure in the pop-up window name XS_TRAINQUERY, complete.
Now, VS.NET automatically generates several files. If you are my newcomer, read Readme.txt, the method of the role and join, run, delete the extension stored procedure XS_TRAINQUERY, the role of each file is explained in detail .
Let us focus on proc.cpp, the role of this file is to implement the interface defined in XstrainQuery.cpp, and its contents are as follows:
#include
// Some global constant statements
#ifdef __cplusplus
Extern "C" {
#ENDIFRETCODE __DECLSPEC (DLLEXPORT) XS_TRAINQUERY (SRV_PROC * SRVPROC);
//statement
#ifdef __cplusplus
}
RETCODE __DECLSPEC (DLLEXPORT) XS_TRAINQUERY (SRV_PROC * SRVPROC)
//achieve{
??????????
// ......}
Among them, Retcode XS_TrainQuery (srv_proc *) is exactly the method of running the extended stored procedure XS_TRAINQUERY in the database, so it is only necessary to add an appropriate code in this section, and make an extended stored procedure.
SRV_PROC is a structure that defines the handle of a database client, almost all methods in srv.h are used to use this handle, but there is any data behind this handle, we don't have to care at all. (Suddenly I think that the CBITMAP class is not easy to use when writing a master's graduation thesis, so when you are stupid, you are super depressed ......)
The format of this expansion stored procedure call should be the XS_TRAINQUERY [starting station name, end site name, result output], then solving the first problem will be divided into the following steps:
1. Pass the value of the two station names; 2. Read all train routes including this second station; 3. Find the shortest route; 4, generate results and pass.
The first step is let us solve the value problem.
The values in the extended stored procedure include three steps: first get the type, length and other information of the parameter, then set the type and length of the local variable corresponding to this parameter, and finally read this parameter, then call SRV_PARAMINFO, and then ALLOC is a suitable memory space, and finally calls SRV_PARAMINFO to store the entry to this memory space.
The format of SRV_PARAMINFO is: int SRV_PARAMINFO (SRV_PROC * SRVPROC, INT N, BYTE * PBTYPE, ULONG * PCBMAXLEN, ULONG * PCBACTUALLEN, BYTE * PBDATA, BOOL * PFNULL)
Where: N represents the second parameter, such as XS_TRAINQUERY 'Beijing', 'Chengdu', '', 'Chengdu''s N value is 2, PBTYPE, PCBMAXLEN, PCBACTYPEEN, PCACTUALLEN, represents the type, maximum length and actuality of this parameter, respectively. The pointer of the incoming length, the PBDATA represents the pointer to this parameter value, and PFNULL represents whether this parameter is null. If so, after running srv_paraminfo, * PFNULL will be set to true. When this parameter is present, SRV_PARAMINFO returns succeed, Otherwise, returns Fail. We need to read the starting point and the end of the station, you need the following code:
{????????? Bool bfnull; ?????????????????????? // is recorded Empty (null) ????????? pbyte pbtype; ?????????????????? // into the type ?? ??????? ulong ulmaxlen = 20; ????????????? // The maximum length of the inclination is 20 bytes ????????? ulong uLActuallen ;? ????????????????? 入 入 实际 ????????? pbyte pbstart; ??????????????? ??????????? // starting site name ????????? pbyte pbend; ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ??? // terminal name ????????? // obtain the first parameter, the type of starting point name, length and other information ????????? IF (SRV_PARAMINFO (SRVPROC, 1, PBTYPE, & ULMAXLEN, & ULACTUALLEN, NULL, & BFNULL)! =? Succeed) ????????????????????? // Some abnormalities Processing code ?????????} ?????????} ?????????} ???????? PBSTART = (PBYTE) :: Malloc (uLActuallen) ; ????????? IF (PBSTART == NULL) ????????????????????? // some abnormalities Processing code ?????????} ????????? // obtain the value of the first parameter ????????? IF (SRV_PARAMINFO (SRVPROC, 1, PBTYPE, & ULMAXLEN , & uLACTUALLEN, PBSTART, & BFNULL?! = succeed) ????????????????????? // some exception processing code??? ??????} ????????? // repeat the three steps above, but N becomes 2, PBSTART changes to PBEND, read in the terminal name}
In the second step, all routes from the secondary station name from the database
There are two ways to connect the database during the extended stored procedure. For the first to see XP_DBLIB in the MS SQL Server ODS example, here only the second method is introduced, and a series of ODBC APIs starting with SQL.
In order to use these APIs, first join in proc.cpp or stdafx.h to add #include
.
The process of primary database connection includes the following steps: 1, initialize the ODBC connection, and assign environment handles; 2, set the environment; Assign and use statements; 6, call SQLDisConnect disconnection; 7, sequentially release the assigned handle. Direct use examples, now we have to read all the routes with this second-vehicle station name from the database, you can use the following code: {??? sqlhenv henv = SQL_NULL_ENV; ??????????? / / Environment handle ??? SQLHDBC HDBC = SQL_NULL_HDBC; ??????? // Connection Handle ??? SQLHSTMT HSTMT = SQL_NULL_HSTMT; ?? // Statement Handle ???? Sqlchar Connstr [255] = "driver = { SQL Server}; server = localhost; uid = your username; PWD = your password; Database = railway; "; ??? // Assign environment handle ??? sqlallochandle (SQL_HANDE_ENV, NULL, & HENV); ??? / / Set the connection environment, the ODBC version is set to 3.x ??? sqlsetenvattr (henv, sql_attr_odbc_vebc3, sql_is_integer); ??? // Depending on the environment to the connection handle ??? SQLALLOCHANDLE (SQL_HANDLE_DBC, HENV, & HDBC ); ??? // Establish a database connection ??? SQLDRIVERCONNECT (HDBC, NULL, CNSTR, SQL_NTS, NULL, 255, NULL, SQL_DRIVER_NOPROMPT); ??? // According to the connection clause handle ??? sqlallochandle (SQL_HANDLE_STMT, HDBC , & hstmt); ??? // Define query statement query, don't forget #include
??? tchar query [255] = "SELECT Routes.Trainid, Allstations from routes, trains where routes.trainid = trains.trainid and allstations like '%"; ??? _tcscat (query, (tchar *) pbstart;? ?? _tcscat (query, "%"); ??? _tcscat (query, (tchar *) pbend); ??? _tcscat (query, "% '"); ??? // Now query = "SELECT ROUTES ...... Like '% starting point% endpoint%' ", we run this query ??? SQLEXECDirect (hstmt, (sqlchar *) query, sql_nts); ??? // Get the number of rows obtained from the query? ; ??????????????????? The number of rows in the result is the number of rows in SQLSETSTMTATTR (HSTMT, SQL_ATTR_ROWS_FETCHED_PTR), (void *) & uirowscount, sizeof (sqlinteger); ??? // Initialization result set group, including two: trainid and allstations ??? int * pitrainid = (int *) :: malloc (uirowscount * sizeof (int)); ??? pchar * ppcStations = (pchar *) :: Malloc (UirowsCount * SizeOf (Pchar);
??? // Because the result is the first column, that is, TrainId is integer, the length is constant, so it can be binded directly? SQLBINDCOL (HSTMT, 1, SQL_INTEGER, (SQLPointer) Pitrainid, Sizeof (int), null) ??? // Remove the data of the second column, because the length is uncertain, so the length must first be previously ??? SQLINTEGER LCOLLEN; ??? // String column, ie allstations length ??? uint nRow = 0; ?? // Market ??? While (SQLFETCH (HSTMT) == SQL_SUCCESS_WITH_INFO)? // Take out a line ??? {????????? // Get the length ??????? Sqlgetdata (HSTMT, 2, SQL_CHAR, NULL, 0, & LCOLLEN); ???????? // According to the length of the second column ???????? ppcStation [nROW] = :: malloc (LCOLLEN); ????????? // Get data ???????? sqlgetdata (HSTMT, 2, SQL_CHAR, PPCStation [nrow], LCOLLLEN, & LCOLLEN); ??????? ?? // Fetch increment in the labeling ????????? nrow; ???} ??? // Now we take out all trainid and allstations ??? // Turns the database connection , Release resources ??? SQLFreeHandle (SQL_HANDLE_STMT, HSTMT); ??? SQLDisconnect (HDBC); ??? SQLFreeHandle (SQL_HANDLE_DBC, HDBC); ??? SQLFreeHandle (SQL_HANDLE_ENV, HENV);} By the way, to the current The two-segment code is all in the method Retcode XS_TRAINQUERY (SRV_PROC *), and the code automatically generated automatically before joining these two pieces of code. Call, it seems that this problem is divided into two, really long. If you are tired, you are now sitting in front of the computer, he is giving a girlfriend ............ Although he will not care, he is still intended ...