Doctrine 1
  1. Doctrine 1
  2. DC-470

[PATCH] Search : wrong connection used for some queries when multiples connections are defined

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.2.1
    • Fix Version/s: 1.2.3
    • Component/s: Behaviors
    • Labels:
      None
    • Environment:
      Debian Sid + php 5.3, symfony 1.4.1

      Description

      When multiples connections are defined, sometimes the Search behavior use a wrong one.

      This happens because the Query::loadRoot() method calls the Manager::getConnectionForComponent(), which returns the bound connection for the root component (like ModelIndex in this case), but the connection for this component is never bound.
      The following and attached patch solved the issue for me.

      Search / connection patch
      Index: lib/Doctrine/Search.php
      ===================================================================
      --- lib/Doctrine/Search.php	(révision 7080)
      +++ lib/Doctrine/Search.php	(copie de travail)
      @@ -76,7 +76,9 @@
               $result = parent::buildTable();
      
               if ( ! isset($this->_options['connection'])) {
      -            $this->_options['connection'] = $this->_options['table']->getConnection();
      +            $manager = Doctrine_Manager::getInstance();
      +            $this->_options['connection'] = $manager->getConnectionForComponent($this->_options['table']->getComponentName());
      +            $manager->bindComponent($this->_options['className'], $this->_options['connection']->getName());
               }
      
               return $result;
      

      Note : we can't use directly
      $this->_options['connection'] = $this->_options['table']->getConnection();
      because I sometimes found the getConnection() returns the wrong connection (I didn't looked why).

        Activity

        Hide
        Jonathan H. Wage added a comment -

        Can you test this against the latest 1.2 SVN? I applied a fix to Generator.php that might help this issue.

        Show
        Jonathan H. Wage added a comment - Can you test this against the latest 1.2 SVN? I applied a fix to Generator.php that might help this issue.
        Hide
        Colin Darie added a comment -

        No, it doesn't work (with the very last revision, 7323).

        I basically did a $object = Doctrine::getTable('Foo')->search('bar'); and got the following error :

        SQLSTATE[HY000]: General error: 1 no such table: foo_index.
        Failing Query: "SELECT COUNT(keyword) AS relevance, id FROM foo_index WHERE keyword = ?
        GROUP BY id ORDER BY relevance DESC"
        

        (the first defined connection is used).

        Plus if it can help, I just discovered a weird thing with the (odd) code :

        $table = Doctrine::getTable('Foo');
        $object = Doctrine::getTable('Foo')->search('bar');
        

        returns the error :

        Invalid argument type. Expected instance of Doctrine_Table.
        Show
        Colin Darie added a comment - No, it doesn't work (with the very last revision, 7323). I basically did a $object = Doctrine::getTable('Foo')->search('bar'); and got the following error : SQLSTATE[HY000]: General error: 1 no such table: foo_index. Failing Query: "SELECT COUNT(keyword) AS relevance, id FROM foo_index WHERE keyword = ? GROUP BY id ORDER BY relevance DESC" (the first defined connection is used). Plus if it can help, I just discovered a weird thing with the (odd) code : $table = Doctrine::getTable('Foo'); $object = Doctrine::getTable('Foo')->search('bar'); returns the error : Invalid argument type. Expected instance of Doctrine_Table.
        Hide
        Jonathan H. Wage added a comment -

        Hi,

        Please re-open if you can provide some more information. The error you mentioned, please also include the stacktrace and other relevant information. The error message itself is useless

        Thanks, Jon

        Show
        Jonathan H. Wage added a comment - Hi, Please re-open if you can provide some more information. The error you mentioned, please also include the stacktrace and other relevant information. The error message itself is useless Thanks, Jon
        Hide
        Colin Darie added a comment -

        Hi,

        I uploaded 2 stacktraces here (with revision 7326, in a symfony 1.4.4-dev environment) and for the simple code
        $o = Doctrine::getTable('Athlete')->search('hey') :

        The script was called by a "php /path/to/my/test" to have a more readable stacktrace, but of course in a "normal" context, the same error happens.

        The relevant databases.yml :

        test:
          dbsport:
            param:
              dsn: 'mysql:host=localhost;dbname=db_sport'
          dbclient:
            param:
              dsn: 'sqlite:%SF_DATA_DIR%/sqlite/db_client_test.db'
        
        all:
          dbsport:
            param:
              dsn: 'mysql:host=localhost;dbname=db_sport_test'
              username: username
              password: 'password'
          dbclient:
            param:
              dsn: 'sqlite:%SF_DATA_DIR%/sqlite/db_client.db'
        

        A simple switch of the connections order solves the issue, but then it's no possible to search on the dbclient because the last connection defined is used instead (unlike I told in my previous comment, it's not the first one).

        Thanks for your time.

        Show
        Colin Darie added a comment - Hi, I uploaded 2 stacktraces here (with revision 7326, in a symfony 1.4.4-dev environment) and for the simple code $o = Doctrine::getTable('Athlete')->search('hey') : a simplified one (more readable) http://pastebin.org/110117 the full one containing all variables http://pastebin.org/110114 The script was called by a "php /path/to/my/test" to have a more readable stacktrace, but of course in a "normal" context, the same error happens. The relevant databases.yml : test: dbsport: param: dsn: 'mysql:host=localhost;dbname=db_sport' dbclient: param: dsn: 'sqlite:%SF_DATA_DIR%/sqlite/db_client_test.db' all: dbsport: param: dsn: 'mysql:host=localhost;dbname=db_sport_test' username: username password: 'password' dbclient: param: dsn: 'sqlite:%SF_DATA_DIR%/sqlite/db_client.db' A simple switch of the connections order solves the issue, but then it's no possible to search on the dbclient because the last connection defined is used instead (unlike I told in my previous comment, it's not the first one). Thanks for your time.
        Show
        Colin Darie added a comment - Reopen with my previous comment http://www.doctrine-project.org/jira/browse/DC-470?focusedCommentId=12091&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12091
        Hide
        Jonathan H. Wage added a comment -

        Hmm, I am not sure of the problem here. Any way to reproduce this in a Doctrine test case so that i can more clearly see the problem?

        Show
        Jonathan H. Wage added a comment - Hmm, I am not sure of the problem here. Any way to reproduce this in a Doctrine test case so that i can more clearly see the problem?
        Hide
        Colin Darie added a comment -

        I'm unable to write a test case for this, because the problem seems to come only when the base model class has not been loaded before to perform the search.

        Moreover, I found this base class is never loaded by the Doctrine::getTable('foo')->search() method, so the bindComponent() in top of the class is never executed.

        Here is a scenario that fails, if it can help you :

        Doctrine_Core::getTable('Foo')->search('bar');
         -> Doctrine_Manager::getInstance()
         -> getConnectionForComponent('Foo')
              -> Doctrine_Core::modelsAutoload('Foo')
                   At this point, self::$_modelsDirectory is not setted and self::$_loadedModelFiles is empty
                   because no model has been loaded yet, so the BaseFoo class is not loaded and the component is not bound
              -> getCurrentConnection() returns the last defined connection, not the connection for the Foo component
          -> getTable('Foo') .... the following operates on the bad connection,
               so the query tries to select from the foo_index table in the wrong database.
        

        (sorry for my poor english ^^)

        Show
        Colin Darie added a comment - I'm unable to write a test case for this, because the problem seems to come only when the base model class has not been loaded before to perform the search. Moreover, I found this base class is never loaded by the Doctrine::getTable('foo')->search() method, so the bindComponent() in top of the class is never executed. Here is a scenario that fails, if it can help you : Doctrine_Core::getTable('Foo')->search('bar'); -> Doctrine_Manager::getInstance() -> getConnectionForComponent('Foo') -> Doctrine_Core::modelsAutoload('Foo') At this point, self::$_modelsDirectory is not setted and self::$_loadedModelFiles is empty because no model has been loaded yet, so the BaseFoo class is not loaded and the component is not bound -> getCurrentConnection() returns the last defined connection, not the connection for the Foo component -> getTable('Foo') .... the following operates on the bad connection, so the query tries to select from the foo_index table in the wrong database. (sorry for my poor english ^^)
        Hide
        Marcel Berteler added a comment -

        Seems like this could be a duplicate of DC-740 and not an actual Doctrine bug but an sfDoctrinePlugin bug.

        Show
        Marcel Berteler added a comment - Seems like this could be a duplicate of DC-740 and not an actual Doctrine bug but an sfDoctrinePlugin bug.

          People

          • Assignee:
            Jonathan H. Wage
            Reporter:
            Colin Darie
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: