justdiy Posted September 13, 2007 Share Posted September 13, 2007 hello all! I'm having a heck of time understanding the way a few things work, or at least, the proper way to do them. To start off, I have a mysql 5 database that's loaded up with lots of stored procedures I've written for handling a firewall log table. When I started on my project, I didn't worry about things like multiuser ability, or pagination. Now that I've got a lot of the backend work done, I'm trying to improve the front end. My stored procs return their results in the form of a temporary table (engine=memory); as I understand the mysql documentation, a temporary table stored in memory exists only while the database connection is open, and is discarded once the connection closes. So that started me on a quest to maintain my connection to the database persistently across multiple page loads. This is were I start pulling my hair out. First I find that some group of developers in their infinite wisdom have decided to not support persistent connections in the mysqli (mysql improved) functions, to that end, there is no mysqli_pconnect function. I've tried mysql_pconnect, but the (old fashioned) mysql functions don't understand stored procedures, and I get an error back from mysql that the result cannot be represented (or something like that). So I started searching for alternatives. At first, I considered switching to postgres instead of mysql; pg offers sprocs and the php functions for it offer persistent connections. Rather than go the route of reconfiguring everything, I kept searching. I then came across the php odbc functions. They seemed pretty straight forward, and functionally similar to the mysqli functions. So, I installed an odbc connector on my server, and changed my code to use odbc instead of mysqli. Now I have odbc working correctly, the same way mysqli did previously. So now, I want to try to maintain a persistent connection. According to the php docs, I need to call odbc_pconnect first to setup the connection, and then when I want to re-use that connection, I can call it again with the same dsn, username and password. So lets say I visit index.php, which asks for a username and password, and then opens a connection to the database via odbc. I store the username and password in a session variable, which is subsequently checked by an include in all my other pages. The include grabs the u/p from the session array, and fires off another odbc_pconnect, presumably to reopen the db connection. So far so good; its all working. Now I decide to test if my db connection is actually being maintained, or just recreated. I fire off a stored proc using odbc_exec($link_id,"CALL mydb.myproc()") , followed by a query to grab results from the temporary table using odbc_exec again. This works as expected. However, in my code, I also set a session variable to indicate the sp has been run, so when I refresh the page, the sp will not be called, just the query on the temp table. This is where it breaks down. Warning: odbc_exec() [function.odbc-exec]: SQL error: [unixODBC][MySQL][ODBC 5.1 Driver][mysqld-5.0.22]Table 'ulogdb.summary_results' doesn't exist, SQL state S0002 in SQLExecDirect in /var/www/html/db/new_summary2.php on line 29 The table summary_results should still be there if my db connection had been preserved, however, it seems the db connection was closed somewhere along the way, and mysql destroyed the table. On a side note, odbc_pconnect causes apache to segfault if it passes an incorrect username or password to the odbc connector. Here's my scripts: <?php session_start(); ?> <html><head><title>Connections Summary</title> <?php include 'styleref.php'; // Report all PHP errors (bitwise 63 may be used in PHP 3) error_reporting(E_ALL ^ E_NOTICE); $limit = 100; include("opendb.php"); include("getdefs.php"); // run SP to generate table of in/out traffic over the last n hours $starttime = microtime(true); if($_SESSION['summary'] != "yes" || $_GET['refresh'] == "yes"){ $result = odbc_exec($link_id, "CALL new_summary($my_hours,'$my_trafdir')"); if (!$result) { echo odbc_error($link_id) ." : ". odbc_errormsg($link_id); die; } $_SESSION['summary'] = "yes"; } $endtime = microtime(true); $sproctime = $endtime - $starttime; $starttime = microtime(true); $result = odbc_exec($link_id, "SELECT * FROM summary_results ORDER BY 'time' DESC"); if (!$result) { echo odbc_error($link_id) ." : ". odbc_errormsg($link_id); $_SESSION['summary'] = "no"; die; } $endtime = microtime(true); $querytime = $endtime - $starttime; $totalrows = odbc_num_rows($result); $fields_num = odbc_num_fields($result); $starttime = microtime(true); if($my_trafdir == "out"){$direction = "Outbound to";}else{$direction = "Inbound from";} echo "<h1>Packets $direction Internet</h1>\n"; echo "<h3>click on anything for detailed accounting</h3>\n"; echo "<h3>data returned from the past "; if($my_hours > 1){echo "$my_hours hours</h3>\n";} else{echo "hour</h3>\n";} // generate table header based on field names from query include("printtable.php"); // fetch row as an array which accepts a name based index // index is case sensitive! while($row = odbc_fetch_array($result)) { // this variable contains the rule action obtained from the database // it must be defined to something, even it it's not being used $ruleaction = $row['rule']; // this include applies a CSS class to each TR element in the table // based on the action of the rule - current accept, deny and reject include("row_colorizer.php"); // these variables are used by inter-links to build the various report // links (hrefs) // these varible must be defined to something, even if not used $srcip = $row['srcip']; $destip = $row['destip']; $tcpport = $row['tcp']; $udpport = $row['udp']; $timestamp = $row['time']; // this include builds hrefs based on the info above include("inter-links.php"); ?> <TD><?=$timedetail?></TD> <TD><?=$srcdetail?></TD> <TD><?=$row['proto']?></TD> <TD><?=$destdetail?></TD> <TD><?=$tcpdetail?></TD> <TD><?=$udpdetail?></TD> <TD><?=$ruledetail?></TD> <TD><?=$row['cnt']?></TD> </TR> <? } echo "</TABLE>"; $endtime = microtime(true); $disptime = $endtime - $starttime; odbc_free_result($result); ?> <P> <h3><a class="hdr" href="new_summary2.php?trafdir=in&hours=<?=$my_hours?>">Inbound Summary</a> - <a class="hdr" href="new_summary2.php?trafdir=out&hours=<?=$my_hours?>">Outbound Summary</a></h3> <h4>sproc: <?=round($sproctime,3)?> query: <?=round($querytime,3)?> display: <?=round($disptime,3)?></h4> </body></html> and opendb.php: <? $db_dsn = 'Default'; $form = ' <center> <form action="'.$_SERVER['PHP_SELF'].'" method="post"> <input type="text" name="username"> <input type="password" name="password"><br> <input type="submit" name="submit" value="submit this"> </form></center> '; if(isset($_SESSION['username'])) // is the username session variable set? { // the username variable is set, we're good // force odbc connection to be a specific username and password for now // thanks to the odbc_pconnect bug $link_id = odbc_pconnect('Default','work','damnit'); if(!$link_id){die("db=gone");} else{$hm = "connected";} echo "<h4>(welcome back ".$_SESSION['username'].")</h4>\n"; }else{ // nope? if(isset($_POST['submit'])) // has the user submitted the form? { // yes, they have! $user = $_POST['username']; $pass = $_POST['password']; $user = str_replace(" ", "", $user); //remove spaces $pass = str_replace(" ", "", $pass); //remove spaces $user = str_replace("%20", "", $user); //remove escaped spaces $pass = str_replace("%20", "", $pass); //remove escaped spaces // add slashes to escape things like quotes and apostrophes // because they can be used to hijack SQL statements! $user = addslashes($user); $pass = addslashes($pass); // trial by fire, see if we can link up with the db server // force odbc connection to be a specific username and password for now // thanks to the odbc_pconnect bug $link_id = odbc_pconnect('Default','work','damnit'); if(!$link_id){$hm = "nope";} else{$hm = "connected";} if($hm == "connected"){ // auth successful $_SESSION['username'] = $_POST['username']; echo "<h4>(welcome aboard ".$_SESSION['username'].")</h4>\n"; }else{ // auth failed echo "<h4>(username / password not valid)</h4>\n"; echo $form; die; } }else{ // default page load, display form echo "<h4>(please log in)</h4>\n"; echo $form; die; } } ?> Link to comment https://forums.phpfreaks.com/topic/69200-persistent-connections-and-temporary-tables/ Share on other sites More sharing options...
justdiy Posted September 13, 2007 Author Share Posted September 13, 2007 I didn't want the first post getting too long. Here is the sproc in case it is relevant somehow. BEGIN DECLARE my_query1 TEXT; DECLARE my_query2 TEXT; DECLARE my_netdir TEXT; /* first part of SQL statement */ SET my_query1 = " CREATE TEMPORARY TABLE summary_results ENGINE = MEMORY SELECT max(ulog.`timestamp`) AS 'time', inet_ntoa(ip_saddr) AS 'srcip', proto.protocol AS 'proto', inet_ntoa(ip_daddr) AS 'destip', ulogdb.ulog.tcp_dport AS 'tcp', ulogdb.ulog.udp_dport AS 'udp', ulogdb.ulog.oob_prefix AS 'rule', count(*) AS 'cnt' FROM ulogdb.ulog Left Join ulogdb.ip_protocols AS proto ON proto.ip_protocol = ulog.ip_protocol WHERE "; /* second part of SQL statement */ SET my_query2 = " GROUP BY ulog.ip_saddr, ulog.tcp_dport, ulog.udp_dport, ulog.ip_daddr, ulog.oob_prefix ORDER BY 'time' DESC"; /* setup traffic direction */ IF trafdir = 'out' THEN /* display outgoing traffic */ SET my_netdir = "ulogdb.ulog.oob_out LIKE 'eth0' "; ELSE /* display incoming traffic */ SET my_netdir = "ulogdb.ulog.oob_in LIKE 'eth0' "; END IF; SET @s = CONCAT(my_query1, 'ulogdb.ulog.`timestamp` >= SUBDATE(Now(), INTERVAL ', hourcount, ' HOUR) AND ', my_netdir, my_query2); PREPARE stmt1 FROM @s; DROP TEMPORARY TABLE IF EXISTS summary_results ; EXECUTE stmt1; DEALLOCATE PREPARE stmt1; END Link to comment https://forums.phpfreaks.com/topic/69200-persistent-connections-and-temporary-tables/#findComment-347794 Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.