How to insert the results of permutation into table in mysql - php

I want to store the results of permutation into a temporary table in mysql so i can use it in the search script.
<?php
function permute($str,$i,$n) {
if ($i == $n) {
echo "$str\n";
echo "<br/>";
$query = mysql_query("CREATE TABLE temp(
id int NOT NULL AUTO_INCREMENT,
number varchar(64) NOT NULL,
PRIMARY KEY(id)
)");
$str = addslashes(trim($_POST['str']));
$query = mysql_query("INSERT INTO temp (number) VALUES ('$str')")
or die(mysql_error());
}
else {
for ($j = $i; $j < $n; $j++) {
swap($str,$i,$j);
permute($str, $i+1, $n);
swap($str,$i,$j); // backtrack.
}
}
}
// function to swap the char at pos $i and $j of $str.
function swap(&$str,$i,$j) {
$temp = $str[$i];
$str[$i] = $str[$j];
$str[$j] = $temp;
}
$str = #$_GET['number'] ;
permute($str,0,strlen($str)); // call the function.
// Get the search variable from URL
?>
Does anyone know how to insert the result of permutation into a temporary table?
I have try to insert into permanent table but the 24sets result of 1234 is not inserted but only the id 1-24 is inserted. I think the problem is because the $str contain 24sets of result but is not separated since it is print out together??
Any solution?

Your real problem is $str = addslashes(trim($_POST['str']));, which is attempting to retrieve the value from the web request in a post form, immediately before putting it into the temp table.
Basically, you're over-writing your variable with something that is (probably not set, thus) blank.
Oh, and I hope in reality you're safely escaping your input parms, or your site is going to be taken over in short order. If number is only ever supposed to contain an actual number (1234), and not some string (ABC), cast it to numeric data (and back to string) to completely sanitize it (exception handling should be included, too).

Related

PHP and MySQL string comparison failing

Okay, so I'm having a pretty annoying little problem with my php code. Basically I pull two variables from two seperate sources. One's a cookie and the other is from a MySQL database.
$data = explode("|", $_COOKIE['login']);
$sql = "SELECT session_id FROM users WHERE username='user1'";
$result = $data->query($sql);
$row = $result->fetch_assoc();
$test1 = $data[0];
$test2 = $row['session_id'];
If($test1 == $test2) {
// Do some stuff
}
else {
// Don't do some stuff
}
The actual string is:
x6vkYu6Ep^lm(1Rdm)5Gj5Hj7ilL6FsDL88JC#n#iTyBUqYgJ48#9Ow%*2ZdGs1rA8bc)JoCD7dywcZgg7soV0D#!DpR^pjQwF#QpBt#HRKe$JEtQ*3LhFXsjmkzWNpt
The string is randomly generated before being stored from the following character set:
1234567890!##$%^&*()abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
for($i = 0; $i < 128; $i++) {
$string .= $char_set[rand(0, strlen($char_set)-1)];
}
$sql = "UPDATE users SET session_id='$string' WHERE user='user1'";
$data->query($sql);
setcookie('login', $string . "|" . $username);
If I just set the two variables equal to the above string and evaluate, it works out just fine. Also, if I echo both $data[0] and $row['session_id'] the entire string will display, and they look indentical.
The if() statement will work if I use basic strings, like a number, or basic word, so I'm guessing it's due to special characters, but I don't know where in the proccess it goes wrong. As I said, if I set two variables to that string value, it evaluates, but when I pull from MySQL and the cookie, despite that both strings look the same, it won't evaluate.
Any thoughts?

Sql Queries in a foreach slows down the page

I have a problem where I get an array of words and I have to insert every one of them in DB via a foreach, but the whole thing is running too slow.
foreach($words as $word) {
// even more checks
if(strlen($word) < 3) continue;
$word = $this->db->escapeString(strtolower($word));
// word not found?
$result = $this->db->querySingle("SELECT id FROM words WHERE word = '{$word}'");
if(!$result) {
$this->db->exec("INSERT INTO words (word) VALUES ('{$word}')");
$this->db->exec("INSERT INTO search (reply, word) VALUES ('{$id}', '{$this->db->lastInsertRowID()}')");
// word found
} else $this->db->exec("INSERT INTO search (reply, word) VALUES ('{$id}', '{$result}')");
}
Basically lets say $words = array('hello', 'kitten');
Within that foreach, it will take my first word (hello) and check if it exists in the words table. If it cannot find the word, it will then insert it there and also insert it into another table with a variable $id that will not change within the foreach. If however it found the word it will insert it directly in the 2nd table. After that it will take the 2nd word (kitten) and do the same thing.
Using php5 with sqlite3
$this->db = new \SQLite3(ROOT . DS . 'db' . DS . 'app.db');
The tables in question are very light
CREATE TABLE words (id INTEGER PRIMARY KEY AUTOINCREMENT, word TEXT);
CREATE TABLE search (reply INTEGER, word INTEGER);
CREATE INDEX search_reply_idx ON search (reply);
CREATE INDEX search_word_idx ON search (word);
This works fine most of the time for 10-15 words, but if i have over 150 words it will be as slow as 8 seconds. Can i combine the queries into just one? Am i missing something?
Thanks.
This method is based on the premise that SQLite support this syntax for insertion (this syntax works in MySQL):
INSERT INTO table (column) VALUES ('value1'), ('value2'), ('value3'), ('valueN');
What you can do is use PHP to build the SQL insert string using logic from the SELECT statement, and then at the end perform two queries; One on the words table and one on the search table:
$sql_words = 'INSERT INTO words (word) VALUES ';
$sql_search = 'INSERT INTO search (reply, word) VALUES ';
$count = count($words);
$i = 0;
$last_insert_id = '';
$delim = '';
foreach ($words as $word)
{
$result = $this->db->querySingle("SELECT id FROM words WHERE word = '{$word}'");
if ($i < $count) {
$delim = ', ';
} else {
$delim = '';
}
if ($result) {
$sql_search .= "('{$result}','{$word}')".$delim;
} else {
$sql_words .= "('{$word}')".$delim;
$sql_search .= "('{$result}','{$last_insert_id}')".$delim;
}
$last_insert_id = $result;
$i++;
}
$this->db-exec($sql_words);
$this->db->exec($sql_search);
As for the validity of this code I am unsure, I was a bit confused where $id came from, and assumed it was the same as $result.
So in order to achieve blazing fast performance some things had to be changed.
Firstly, the use of transactions (sort of like mulquin's answer) and secondly I've added a unique index for the column word in the words table. This will help me skip the sql that checked if a word already existed and just ignore the insert statements from that transaction.
This is the new table which will create my unique index automatically
CREATE TABLE words (id INTEGER PRIMARY KEY AUTOINCREMENT, word TEXT UNIQUE)
And here is the modified foreach
$t1 = $t2 = null;
foreach($words as $word) {
// even more checks
if(strlen($word) < 3) continue;
$word = $this->db->escapeString(strtolower($word));
$t1 .= "INSERT OR IGNORE INTO words (word) VALUES ('{$word}');";
$t2 .= "INSERT INTO search (reply, word) SELECT '{$id}', id FROM words WHERE word = '{$word}';";
}
// run transactions
if(!is_null($t1)) $this->db->exec("BEGIN TRANSACTION;" . $t1 . "COMMIT;");
if(!is_null($t2)) $this->db->exec("BEGIN TRANSACTION;" . $t2 . "COMMIT;");
So, when in doubt, use transactions :)

PHP: Why won't the program compare values as equal when it prints them with equal values

I have this code for a system:
//get new data from text fields
$i = 0;
$data = array();
while ($i < 7){
$data[$i] = $_POST['t'.$i];
$i++;
}
//get the ID to use in the MySQL database query
$id=$data[0];
//get the existing integer from MySQL database
$query="SELECT * FROM tbl WHERE ID='$id';";
$result=mysql_query($query) or die(mysql_error());
$mem=mysql_result($result, 0, 'Member');
//print to see if it's equal
echo 'Does '.$mem.'='.$data[1].'?<br>';
//check equality
if ($mem != $data[1]){
echo "I'm not supposed to exist";
}
The $data[0] is the unique id for that database table and $data[1] is what we're trying to get.
The code prints $mem as 999999. Same with $data[0], 999999. But for some reason, when I pass them through the if statement, They are not equal.
Cast them to int
if ((int)$mem != (int)$data[1]){
echo "I'm not supposed to exist";
}
you write data[0] is equal to $mem and you compare $data[1]

Inserting instances of array into table using a for loop

I am trying to insert rows of data in an array into a table. It's inserting this instead of the actual data:
Here is my code:
for ($i = 0; $i < $arraycount; $i++)
{
$db->query("INSERT INTO contact_tariffs (qid, retail_name, tariff_name, tariff_net, tariff_rental, tariff_inclusive, tariff_length, tariff_data)
Values ('$qid', '$quote->retail_name[$i]', '$quote->tariff_name[$i]', '$quote->tariff_net[$i]', '$quote->tariff_rental[$i]', '$quote->tariff_inclusive[$i]', '$quote->tariff_length[$i]', '$quote->tariff_data[$i]' )");
}
I have had similar problems when using $_POST and $_SESSION variables and the only solution I had for that was to temporarily transport the values into temp variables and use the temp variables to insert into the database.
The variables are too complex to use inside a string. PHP interprets $quote->retail_name as one variable and $i another, because it doesn't know where one variable ends and where the other starts. For example:
$i = 1;
$quote->retail_name[ 1 ] = 'foo';
echo "result: $quote->retail_name[$i]"; // --> result: Array[1]
// the above is the same as
// echo $quote->retail_name; echo "["; echo $i; echo "];
echo "result: ".$quote->retail_name[$i]; // --> result: foo
// The above leaves the variable outside the string so it's parsed correctly.
// You could also use "result: {$quote->retail_name[$i]}"
See also http://www.php.net/manual/en/language.types.string.php#language.types.string.parsing
Try this instead:
for ($i = 0; $i < $arraycount; $i++)
{
$db->query("INSERT INTO contact_tariffs (qid, retail_name, tariff_name, tariff_net, tariff_rental, tariff_inclusive, tariff_length, tariff_data)
Values ('$qid', '".$quote->retail_name[$i]."', '".$quote->tariff_name[$i]."', '".$quote->tariff_net[$i]."', '".$quote->tariff_rental[$i]."', '".$quote->tariff_inclusive[$i]."', '".$quote->tariff_length[$i]."', '".$quote->tariff_data[$i]."' )");
}
Although you should escape the values as well. Something like PDO would be preferable.
You can use curly brackets, to insert array values directly into a double quoted string:
for ($i = 0; $i < $arraycount; $i++)
{
$db->query("INSERT INTO contact_tariffs (qid, retail_name, tariff_name, tariff_net, tariff_rental, tariff_inclusive, tariff_length, tariff_data)
Values ('{$qid}', '{$quote->retail_name[$i]}', '{$quote->tariff_name[$i]}', '{$quote->tariff_net[$i]}', '{$quote->tariff_rental[$i]}', '{$quote->tariff_inclusive[$i]}', '{$quote->tariff_length[$i]}', '{$quote->tariff_data[$i]}' )");
}
...and please be aware of SQL injections.

Check a created string against database, and if found, create new string?

Pretty simple, however, I've yet to find a real straight and appropriate solution;
I've currently got my own function that creates a random string, by running two mt_rand() functions from 1 to maximum integers, then wrapping the results in two dechex() functions, and concatenating them into a single string.
I haven't done the stats on it, but, the chances of two of these strings being the same is pretty low.
However, I'll obviously need a backup solution which is why I want to perform a query against a database, and see if it exists as an entry, and if it does, re-invoke my own function to create a random string, query again, and loop until a non-existent string is found.
I've had a look at a ton of forum threads, and a few SO questions, but have yet to found a concise answer.
Any help would be greatly appreciated, thanks!
$int_affected = 0;
while(!$int_affected) {
/* Set $integer */
mysql_query("INSERT IGNORE INTO table (value) VALUES ({$integer})");
$int_affected = mysql_affected_rows();
}
Is this something you're looking for?
You need a recursive function. Something like:
function makeString() {
// Create our random string
$string = "";
$characters = array('a', 'b', 'c', 'd');
for ($i = 0; $i < 4; $i++) {
$string .= $characters[mt_rand(0, 4)];
}
$query = "SELECT COUNT(*)
FROM myTable
WHERE string = '{$string}'";
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);
if ($row['COUNT(*)'] > 0) { // if it already exists, do it again
$string = makeString();
}
return $string;
}
This isn't the most elegant solution, but it will work:
$result = queryForUnique();
$unique_string = your_described_function();
$how_many_times = 0;
while(in_array($unique_string, $result) !== false){
if($how_many_times > 10){
throw new Exception("Failed to find a unique string! Aborting!");
}
$unique_string = your_described_function();
$how_many_times++;
}
Where queryForUnique($string) is a wrapper for a SELECT statement
Edit:
Took the query out of the loop, it is bad practice to have a SELECT query in a loop.
Might want to review your control structures:
http://php.net/manual/en/language.control-structures.php

Categories