This message appears when I start a Search Query:

Access denied for user: 'U113017@192.168.4%' to database 'MyDatabase' query: CREATE TEMPORARY TABLE temp_search_sids SELECT i.type, i.sid, SUM(i.score * t.count) AS relevance, COUNT(*) AS matches FROM search_index i INNER JOIN search_total t ON i.word = t.word INNER JOIN node n ON n.nid = i.sid INNER JOIN users u ON n.uid = u.uid WHERE n.status = 1 AND (i.word = 'historie') AND i.type = 'node' GROUP BY i.type, i.sid HAVING COUNT(*) >= 1 in /mnt/am2/08/231/00000012/htdocs/soccer-wikki.info/includes/database.mysql.inc in Zeile 118

I am using 4.7 with:
Id: database.mysql.inc,v 1.50 2006/02/02 01:27:57 unconed Exp

What does it mean?
Any ideas?

Comments

niosop’s picture

It means that your user doesn't have the rights to create a temporary table, which the search module requires. You could check with your hosting provider to see if they will give you rights, but in my experience it's pretty unlikely.

I'm currently in the same situation. It's a new host, so I don't know if they will grant temp table privs (they didn't have a problem granting lock table privs). If not I'll either have to find a new host, or patch the search module to not use a temp table.

niosop’s picture

Hi,

If your host won't give you create temporary table privs, I've changed the code to work w/out temp tables just using table name suffixes based on sid. I haven't throughally tested it, and it's pretty ugly in it's current form, but if you need it I could clean it up and post it.

RaRi’s picture

This sounds good.
My provider really does not allow creating temp tables for the database.
A work around is appreciated and I am looking forward to test it.

niosop’s picture

Hi,

Here's what I have, and it seems to be working fine. It's ugly, I haven't had a chance to clean it up, but I'm pretty busy right now and don't know when I will, so I figure you could use it until I get a chance. This was based off 4.7_rc2 code, so if you're using 4.6 you'll probably have to modify them yourself.

As you can see, instead of making temp tables, it just creates normal tables suffixed with the session ID to avoid collisions. You may want to check the database occasionally and clean up any tables that don't get dropped. Shouldn't happen unless people hit the stop button in the middle of a search.

In modules/search.module, replace the do_search function w/ this:

function do_search($keywords, $type, $join1 = '', $where1 = '1', $arguments1 = array(), $select2 = 'i.relevance AS score', $join2 = '', $arguments2 = array(), $sort_parameters = 'ORDER BY score DESC') {
  $query = search_parse_query($keywords);
  global $user;

  if ($query[2] == '') {
    form_set_error('keys', t('You must include at least one positive keyword with %count characters or more.', array('%count' => variable_get('minimum_word_size', 3))));
  }
  if ($query === NULL || $query[0] == '' || $query[2] == '') {
    return array();
  }

  // First pass: select all possible matching sids, doing a simple index-based OR matching on the keywords.
  // 'matches' is used to reject those items that cannot possibly match the query.
  $conditions = $where1 .' AND ('. $query[2] .") AND i.type = '%s'";
  $arguments = array_merge($arguments1, $query[3], array($type, $query[4]));
  $result = db_query_temporary("SELECT i.type, i.sid, SUM(i.score * t.count) AS relevance, COUNT(*) AS matches FROM {search_index} i INNER JOIN {search_total} t ON i.word = t.word $join1 WHERE $conditions GROUP BY i.type, i.sid HAVING COUNT(*) >= %d", $arguments, 'temp_search_sids');

  // Calculate maximum relevance, to normalize it
  $normalize = db_result(db_query('SELECT MAX(relevance) FROM temp_search_sids'.$user->sid));
  if (!$normalize) {
    return array();
  }
  $select2 = str_replace('i.relevance', '('. (1.0 / $normalize) .' * i.relevance)', $select2);

  // Second pass: only keep items that match the complicated keywords conditions (phrase search, negative keywords, ...)
  $conditions = '('. $query[0] .')';
  $arguments = array_merge($arguments2, $query[1]);
  $result = db_query_temporary("SELECT i.type, i.sid, $select2 FROM temp_search_sids".$user->sid." i INNER JOIN {search_dataset} d ON i.sid = d.sid AND i.type = d.type $join2 WHERE $conditions $sort_parameters", $arguments, 'temp_search_results');
  if (($count = db_result(db_query('SELECT COUNT(*) FROM temp_search_results'.$user->sid))) == 0) {
    db_query('DROP TABLE temp_search_results'.$user->sid);
    db_query('DROP TABLE temp_search_sids'.$user->sid);
    return array();
  }
  $count_query = "SELECT $count";

  // Do actual search query
  $result = pager_query("SELECT * FROM temp_search_results".$user->sid, 10, 0, $count_query);
  $results = array();
  while ($item = db_fetch_object($result)) {
    $results[] = $item;
  }

  db_query('DROP TABLE temp_search_results'.$user->sid);
  db_query('DROP TABLE temp_search_sids'.$user->sid);

  return $results;
}

Then in includes/database.mysql.inc change the function db_query_temporary to the following:

function db_query_temporary($query) {
  $args = func_get_args();
  $tablename = array_pop($args);
  array_shift($args);

  global $user;

  db_query("DROP TABLE IF EXISTS ".$tablename.$user->sid);
  $query = preg_replace('/^SELECT/i', 'CREATE TABLE '.$tablename . $user->sid.' SELECT', db_prefix_tables($query));
  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
    $args = $args[0];
  }
  _db_query_callback($args, TRUE);
  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
  return _db_query($query);
}

This will require that every module that uses db_query_temporary be modified, but of all the ones I have installed, search.module is the only one that uses it.

Let me know if you have any problems with it. And if there's any Drupal/MySQL guru's out there reading this, please feel free to tell me why this is a crappy way to do it :)

Niosop

RaRi’s picture

Thanks a lot .. this is what I was looking and waiting for. Well done.

As many of us Drupal Users do not have an own server running, I am sure this will help lots of people.

I suggest to put this workaround into the drupal core with a little bit more security not to leave unneccessary tables in the database.

Msg to the Drupal Team: Please think about this solution!! Thx

amr’s picture

Thanks very much for the script!

glyphstone’s picture

Thanks. This does the trick.

Breanna Anderson
www.schemalogic.com -- www.glyphstone.com

eva’s picture

hi,

i'm trying to figure what i did wrong.

my search isn't working at all for the connections theme, so i tried changing to bluemarine to see if it was the theme or if there was something not working with the search.

once i switched to bluemarine, i got the error at the top of this thread, so i replaced both sections in the search module and the database.mysql.inc files per the suggestion above - and now i'm not getting any errors, but the search also isn't returning anything for content - though it is returning with responses for users - is there something that i can do to get the search working for content, too?

i'm still not getting anything when i try to submit a search within the connections theme - so i'm guessing that it's just not updated to work within 4.7 just yet.

update: ooops. after upgrading, i hadn't yet run a cron job - as soon as i did it, the content search worked perfectly. now to get the connections theme working...thanks for the script:)

update #2: got search working on connections theme on 4.7 by following this post: http://drupal.org/node/25297#comment-121214.

eva
http://www.selfesteemcommunication.com

divrom’s picture

I've been trying to use this solution, but when I make the changes, I get this error message and the site won't load:

Fatal error: Call to undefined function: search_box() in /home/sites/.../themes/engines/phptemplate/phptemplate.engine on line 198

Is there a way to modify the suggestion above to avoid this?

nick1@neoforts.com’s picture

On my site (neoforts.com) it works well. Our host, does not allow the creation of temporary tables. This worked well for us.

The only two files I had to modify were

search.module

and the

database.mysql.inc

files.

peterthevicar’s picture

Thank you Niosop - those two patches get search working again for me after upgrading from 4.6
LOCK TABLES not allowed by my ISP either.

You are a star! :-D

Note: need to run cron.php after the 4.6->4.7 upgrade as it deletes the search index.

peterthevicar
drupal site: lymingtonchurch.org

Edit: I've put a patch file at http://drupal.org/node/55516#comment-168371 which combines niosop's fix with chx's patch for the removal of LOCK TABLES (only for MySQL).

peterthevicar’s picture

Our hosting company Penguin Internet Ltd now allows LOCK TABLES and CREATE TEMPORARY TABLES so we don't need these patches any more. A superb hosting company and all for £25 a YEAR - what more could you ask!

Thanks to everyone for keeping us going in the mean time.

peterthevicar
drupal site: lymingtonchurch.org

Jofaba’s picture

It's been really bumming me out lacking that very important function on my website, and I just did the code replacements and from first impressions it appears to work perfectly. Thank you very much =)

jhenline’s picture

thank you so much for sharing this. :-)

Antikx’s picture

Thanks! this really helped me with my godaddy site.

dorelxa’s picture

Hello. It seems the work-around you made was working for everyone so maybe I am an idiot...?

I am using 5.1
and
I am not sure if I have cron jobs working. Still haven't figured that out. Maybe it's my problem. I did the poor man's cron fix and don't know how to check on it.

Anyway, this is what I get after doing the fix and trying a search:

* user warning: Access denied for user 'drupaldorelxa'@'%' to database 'drupaldorelxa' query: CREATE TEMPORARY TABLE temp_search_sids SELECT i.type, i.sid, SUM(i.score * t.count) AS relevance, COUNT(*) AS matches FROM search_index i INNER JOIN search_total t ON i.word = t.word INNER JOIN node n ON n.nid = i.sid LEFT JOIN localizernode loc ON loc.nid=n.nid INNER JOIN users u ON n.uid = u.uid WHERE n.status = 1 AND (loc.locale IN ('en','-') OR loc.locale IS NULL) AND (i.word = 'iraq') AND i.type = 'node' GROUP BY i.type, i.sid HAVING COUNT(*) >= 1 in /home/content/d/o/r/dorelxa/html/home/includes/database.mysql.inc on line 172.
* user warning: Table 'drupaldorelxa.temp_search_sids' doesn't exist query: SELECT MAX(relevance) FROM temp_search_sids in /home/content/d/o/r/dorelxa/html/home/includes/database.mysql.inc on line 172.

Any help would be appreciated. I am a total novice in way over my head.
Thanks again,
dorelxa

morrisqueto’s picture

Thanks, you just solved my issue. Seems my hosting company doesn't like temporary tables.

-----------------------------------------------
Morris
My Site

tg20’s picture

I was experiencing this problem when I transfered my drupal site from my testing server to a godaddy hosting server.

After injecting this little piece of code into the proper spots, I have had no problems. (So Far... Knock on wood). It has only been about 5 minutes.

Thanks for this little workaround.

-Tg20

ahaze’s picture

I put this workaround into place as well and it worked perfectly. I just ran a cron, however, and got several "duplicate entry for key 1 query" errors. I'm a total newb with databases... is this something I need to be concerned about or is it to be expected? Is there something I need to do or clean up now? Cheers.

ahaze’s picture

My previous problem hasn't cropped up since that cron, so hopefully that means everything's okay. I have a new problem now:

I just added several backdated entries to my website and cron.php is apparently not indexing them, even though it says the site is completely indexed. Searching for terms I know were included in those backdated posts isn't working. Could this workaround have caused the problem? Is there a solution? Thanks in advance!

ahaze’s picture

For some reason one batch of backdated blog posts was searchable but another batch wasn't. By re-indexing the site (admin-settings-search) and then running cron, it would appear my blog posts are all now searchable. This page was also updated, however: http://www.deandi.com/adventure/galleries - all of the content at the bottom of the page (the ones that don't have thumbnails) were just added in the last couple of days, and none of them appear in searches (I searched "muertos", "chinese new year", etc- nothin'.) Older stuff on that page (the stuff with thumbnails) is searchable. Any input would be appreciated. Thank you!

miau’s picture

Has anybody tried this with Drupal 5.1?

ahaze’s picture

...on the site listed above. Still have the same problem.

miau’s picture

Got my Provider into enabling "create temporary table privs". Luckily. That resolved it. So I have not further tested the workarounds.

zaytouna’s picture

Folks,
I have the same problem with my search and the result are same but i'm using drupal-5.2 and i'm not sure weather this code will work or not. my domain is : http://www.petoskeygyn.com does anyone have any idea? i know you guys a lot better than me :) looking for help.

Thanks.

ManuelMendoza’s picture

Fortunately i worked to achieve my hosting provider to grant temporary tables privs.

Greetings.

Ságitta Consultores Ecuador