Browse Source

Make chado_db_select match db_select in functionality

863 fix chado_db_select function
Lacey-Anne Sanderson 5 years ago
parent
commit
81fe06c0c8

+ 221 - 48
composer.lock

@@ -229,32 +229,33 @@
         },
         {
             "name": "guzzlehttp/psr7",
-            "version": "1.4.2",
+            "version": "1.5.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/psr7.git",
-                "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
+                "reference": "9f83dded91781a01c63574e387eaa769be769115"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
-                "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
+                "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115",
+                "reference": "9f83dded91781a01c63574e387eaa769be769115",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.4.0",
-                "psr/http-message": "~1.0"
+                "psr/http-message": "~1.0",
+                "ralouphie/getallheaders": "^2.0.5"
             },
             "provide": {
                 "psr/http-message-implementation": "1.0"
             },
             "require-dev": {
-                "phpunit/phpunit": "~4.0"
+                "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.4-dev"
+                    "dev-master": "1.5-dev"
                 }
             },
             "autoload": {
@@ -284,13 +285,14 @@
             "keywords": [
                 "http",
                 "message",
+                "psr-7",
                 "request",
                 "response",
                 "stream",
                 "uri",
                 "url"
             ],
-            "time": "2017-03-20T17:10:46+00:00"
+            "time": "2018-12-04T20:46:45+00:00"
         },
         {
             "name": "myclabs/deep-copy",
@@ -810,16 +812,16 @@
         },
         {
             "name": "phpunit/php-timer",
-            "version": "2.0.0",
+            "version": "2.1.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-timer.git",
-                "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f"
+                "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f",
-                "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b389aebe1b8b0578430bda0c7c95a829608e059",
+                "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059",
                 "shasum": ""
             },
             "require": {
@@ -831,7 +833,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.0-dev"
+                    "dev-master": "2.1-dev"
                 }
             },
             "autoload": {
@@ -855,20 +857,20 @@
             "keywords": [
                 "timer"
             ],
-            "time": "2018-02-01T13:07:23+00:00"
+            "time": "2019-02-20T10:12:59+00:00"
         },
         {
             "name": "phpunit/php-token-stream",
-            "version": "3.0.0",
+            "version": "3.0.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-token-stream.git",
-                "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace"
+                "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace",
-                "reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18",
+                "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18",
                 "shasum": ""
             },
             "require": {
@@ -904,7 +906,7 @@
             "keywords": [
                 "tokenizer"
             ],
-            "time": "2018-02-01T13:16:43+00:00"
+            "time": "2018-10-30T05:52:18+00:00"
         },
         {
             "name": "phpunit/phpunit",
@@ -1092,6 +1094,46 @@
             ],
             "time": "2016-08-06T14:39:51+00:00"
         },
+        {
+            "name": "ralouphie/getallheaders",
+            "version": "2.0.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ralouphie/getallheaders.git",
+                "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
+                "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~3.7.0",
+                "satooshi/php-coveralls": ">=1.0"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "src/getallheaders.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Ralph Khattar",
+                    "email": "ralph.khattar@gmail.com"
+                }
+            ],
+            "description": "A polyfill for getallheaders.",
+            "time": "2016-02-11T07:05:27+00:00"
+        },
         {
             "name": "sebastian/code-unit-reverse-lookup",
             "version": "1.0.1",
@@ -1203,23 +1245,23 @@
         },
         {
             "name": "sebastian/diff",
-            "version": "3.0.1",
+            "version": "3.0.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/diff.git",
-                "reference": "366541b989927187c4ca70490a35615d3fef2dce"
+                "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/366541b989927187c4ca70490a35615d3fef2dce",
-                "reference": "366541b989927187c4ca70490a35615d3fef2dce",
+                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
+                "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
                 "shasum": ""
             },
             "require": {
                 "php": "^7.1"
             },
             "require-dev": {
-                "phpunit/phpunit": "^7.0",
+                "phpunit/phpunit": "^7.5 || ^8.0",
                 "symfony/process": "^2 || ^3.3 || ^4"
             },
             "type": "library",
@@ -1255,7 +1297,7 @@
                 "unidiff",
                 "unified diff"
             ],
-            "time": "2018-06-10T07:54:39+00:00"
+            "time": "2019-02-04T06:01:07+00:00"
         },
         {
             "name": "sebastian/environment",
@@ -1657,16 +1699,16 @@
         },
         {
             "name": "statonlab/tripal-test-suite",
-            "version": "1.5.1",
+            "version": "1.5.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/tripal/TripalTestSuite.git",
-                "reference": "c652f62c0e8302e00cf25a39c95a605b0266656f"
+                "reference": "2c89b5919e3a48c8ecd63744e5879b00fac03bd7"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/tripal/TripalTestSuite/zipball/c652f62c0e8302e00cf25a39c95a605b0266656f",
-                "reference": "c652f62c0e8302e00cf25a39c95a605b0266656f",
+                "url": "https://api.github.com/repos/tripal/TripalTestSuite/zipball/2c89b5919e3a48c8ecd63744e5879b00fac03bd7",
+                "reference": "2c89b5919e3a48c8ecd63744e5879b00fac03bd7",
                 "shasum": ""
             },
             "require": {
@@ -1701,30 +1743,34 @@
                     "email": "bcondon@utk.edu"
                 }
             ],
-            "time": "2018-09-25T19:08:14+00:00"
+            "time": "2019-01-10T13:18:54+00:00"
         },
         {
             "name": "symfony/console",
-            "version": "v4.1.4",
+            "version": "v4.2.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "ca80b8ced97cf07390078b29773dc384c39eee1f"
+                "reference": "9dc2299a016497f9ee620be94524e6c0af0280a9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/ca80b8ced97cf07390078b29773dc384c39eee1f",
-                "reference": "ca80b8ced97cf07390078b29773dc384c39eee1f",
+                "url": "https://api.github.com/repos/symfony/console/zipball/9dc2299a016497f9ee620be94524e6c0af0280a9",
+                "reference": "9dc2299a016497f9ee620be94524e6c0af0280a9",
                 "shasum": ""
             },
             "require": {
                 "php": "^7.1.3",
+                "symfony/contracts": "^1.0",
                 "symfony/polyfill-mbstring": "~1.0"
             },
             "conflict": {
                 "symfony/dependency-injection": "<3.4",
                 "symfony/process": "<3.3"
             },
+            "provide": {
+                "psr/log-implementation": "1.0"
+            },
             "require-dev": {
                 "psr/log": "~1.0",
                 "symfony/config": "~3.4|~4.0",
@@ -1734,7 +1780,7 @@
                 "symfony/process": "~3.4|~4.0"
             },
             "suggest": {
-                "psr/log-implementation": "For using the console logger",
+                "psr/log": "For using the console logger",
                 "symfony/event-dispatcher": "",
                 "symfony/lock": "",
                 "symfony/process": ""
@@ -1742,7 +1788,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "4.1-dev"
+                    "dev-master": "4.2-dev"
                 }
             },
             "autoload": {
@@ -1769,20 +1815,146 @@
             ],
             "description": "Symfony Console Component",
             "homepage": "https://symfony.com",
-            "time": "2018-07-26T11:24:31+00:00"
+            "time": "2019-02-23T15:17:42+00:00"
+        },
+        {
+            "name": "symfony/contracts",
+            "version": "v1.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/contracts.git",
+                "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf",
+                "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1.3"
+            },
+            "require-dev": {
+                "psr/cache": "^1.0",
+                "psr/container": "^1.0"
+            },
+            "suggest": {
+                "psr/cache": "When using the Cache contracts",
+                "psr/container": "When using the Service contracts",
+                "symfony/cache-contracts-implementation": "",
+                "symfony/service-contracts-implementation": "",
+                "symfony/translation-contracts-implementation": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Contracts\\": ""
+                },
+                "exclude-from-classmap": [
+                    "**/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "A set of abstractions extracted out of the Symfony components",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "abstractions",
+                "contracts",
+                "decoupling",
+                "interfaces",
+                "interoperability",
+                "standards"
+            ],
+            "time": "2018-12-05T08:06:11+00:00"
+        },
+        {
+            "name": "symfony/polyfill-ctype",
+            "version": "v1.10.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-ctype.git",
+                "reference": "e3d826245268269cd66f8326bd8bc066687b4a19"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
+                "reference": "e3d826245268269cd66f8326bd8bc066687b4a19",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "suggest": {
+                "ext-ctype": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.9-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Ctype\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                },
+                {
+                    "name": "Gert de Pagter",
+                    "email": "backendtea@gmail.com"
+                }
+            ],
+            "description": "Symfony polyfill for ctype functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "ctype",
+                "polyfill",
+                "portable"
+            ],
+            "time": "2018-08-06T14:22:27+00:00"
         },
         {
             "name": "symfony/polyfill-mbstring",
-            "version": "v1.9.0",
+            "version": "v1.10.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-mbstring.git",
-                "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8"
+                "reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8",
-                "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
+                "reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
                 "shasum": ""
             },
             "require": {
@@ -1828,7 +2000,7 @@
                 "portable",
                 "shim"
             ],
-            "time": "2018-08-06T14:22:27+00:00"
+            "time": "2018-09-21T13:07:52+00:00"
         },
         {
             "name": "theseer/tokenizer",
@@ -1872,20 +2044,21 @@
         },
         {
             "name": "webmozart/assert",
-            "version": "1.3.0",
+            "version": "1.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/webmozart/assert.git",
-                "reference": "0df1908962e7a3071564e857d86874dad1ef204a"
+                "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a",
-                "reference": "0df1908962e7a3071564e857d86874dad1ef204a",
+                "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9",
+                "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9",
                 "shasum": ""
             },
             "require": {
-                "php": "^5.3.3 || ^7.0"
+                "php": "^5.3.3 || ^7.0",
+                "symfony/polyfill-ctype": "^1.8"
             },
             "require-dev": {
                 "phpunit/phpunit": "^4.6",
@@ -1918,7 +2091,7 @@
                 "check",
                 "validate"
             ],
-            "time": "2018-01-29T19:49:41+00:00"
+            "time": "2018-12-25T11:19:39+00:00"
         }
     ],
     "aliases": [],

+ 18 - 10
tests/DataFactory.php

@@ -11,7 +11,7 @@ use StatonLab\TripalTestSuite\Database\Factory;
  * @docs https://github.com/statonlab/TripalTestSuite
  */
 
-/** @see  StatonLab\TripalTestSuite\Database\Factory::define() */
+/** @see StatonLab\TripalTestSuite\Database\Factory::define() */
 Factory::define('chado.cv', function (Faker\Generator $faker) {
   return [
     'name' => $faker->name,
@@ -19,7 +19,7 @@ Factory::define('chado.cv', function (Faker\Generator $faker) {
   ];
 });
 
-/** @see  StatonLab\TripalTestSuite\Database\Factory::define() */
+/** @see StatonLab\TripalTestSuite\Database\Factory::define() */
 Factory::define('chado.db', function (Faker\Generator $faker) {
   return [
     'name' => $faker->name,
@@ -29,7 +29,7 @@ Factory::define('chado.db', function (Faker\Generator $faker) {
   ];
 });
 
-/** @see  StatonLab\TripalTestSuite\Database\Factory::define() */
+/** @see StatonLab\TripalTestSuite\Database\Factory::define() */
 Factory::define('chado.dbxref', function (Faker\Generator $faker) {
   return [
     'db_id' => factory('chado.db')->create()->db_id,
@@ -39,7 +39,7 @@ Factory::define('chado.dbxref', function (Faker\Generator $faker) {
   ];
 });
 
-/** @see  StatonLab\TripalTestSuite\Database\Factory::define() */
+/** @see StatonLab\TripalTestSuite\Database\Factory::define() */
 Factory::define('chado.cvterm', function (Faker\Generator $faker) {
   return [
     'cv_id' => factory('chado.cv')->create()->cv_id,
@@ -51,7 +51,7 @@ Factory::define('chado.cvterm', function (Faker\Generator $faker) {
   ];
 });
 
-/** @see  StatonLab\TripalTestSuite\Database\Factory::define() */
+/** @see StatonLab\TripalTestSuite\Database\Factory::define() */
 Factory::define('chado.organism', function (Faker\Generator $faker) {
   return [
     'abbreviation' => $faker->name,
@@ -62,7 +62,7 @@ Factory::define('chado.organism', function (Faker\Generator $faker) {
   ];
 });
 
-/** @see  StatonLab\TripalTestSuite\Database\Factory::define() */
+/** @see StatonLab\TripalTestSuite\Database\Factory::define() */
 Factory::define('chado.feature', function (Faker\Generator $faker) {
   return [
     'name' => $faker->name,
@@ -73,7 +73,7 @@ Factory::define('chado.feature', function (Faker\Generator $faker) {
 });
 
 
-/** @see  StatonLab\TripalTestSuite\Database\Factory::define() */
+/** @see StatonLab\TripalTestSuite\Database\Factory::define() */
 Factory::define('chado.stock', function (Faker\Generator $faker) {
   return [
     'name' => $faker->name,
@@ -83,14 +83,13 @@ Factory::define('chado.stock', function (Faker\Generator $faker) {
   ];
 });
 
-/** @see  StatonLab\TripalTestSuite\Database\Factory::define() */
+/** @see StatonLab\TripalTestSuite\Database\Factory::define() */
 Factory::define('chado.project', function (Faker\Generator $faker) {
   return [
     'name' => $faker->name,
   ];
 });
 
-
 Factory::define('chado.analysis', function (Faker\Generator $faker) {
   return [
     'name' => $faker->name,
@@ -104,7 +103,8 @@ Factory::define('chado.analysis', function (Faker\Generator $faker) {
     'sourceuri' => $faker->name,
   ];
 });
-/** @see  StatonLab\TripalTestSuite\Database\Factory::define() */
+
+/** @see StatonLab\TripalTestSuite\Database\Factory::define() */
 Factory::define('tripal_jobs', function (Faker\Generator $faker) {
   return [
     'uid' => 1,
@@ -127,3 +127,11 @@ Factory::define('tripal_jobs', function (Faker\Generator $faker) {
     'priority' => $faker->numberBetween(1, 10),
   ];
 }, 'job_id');
+
+/** @see StatonLab\TripalTestSuite\Database\Factory::define() */
+Factory::define('chado.pub', function (Faker\Generator $faker) {
+  return [
+    'uniquename' => $faker->word,
+    'type_id' => factory('chado.cvterm')->create()->cvterm_id,
+  ];
+});

+ 194 - 0
tests/tripal_chado/api/ChadoQueryTest.php

@@ -66,7 +66,201 @@ class ChadoQueryTest extends TripalTestCase {
     $object = chado_generate_var('stock', $selector);
     $this->assertNotNull($object->stock_id);
     $this->assertEquals($stock->stock_id, $object->stock_id);
+  }
+
+  /**
+   * @group api
+   * @group chado
+   * @group chado_db_select
+   */
+  public function test_chado_db_select_works_for_chado_tables() {
+    $analysis_record = factory('chado.analysis')->create();
+
+    $id = $analysis_record->analysis_id;
+
+
+    // Test passing a table name without brackets or braces.
+    $query = chado_db_select('analysis', 't');
+
+    $analysis = $query
+      ->condition('analysis_id', $id)
+      ->fields('t')
+      ->execute()
+      ->fetchObject();
+
+    $this->assertNotFalse($analysis);
+    $this->assertNotEmpty($analysis);
+    $this->assertEquals($id, $analysis->analysis_id);
+  }
+
+  /**
+   * @group api
+   * @group chado
+   * @group chado_db_select
+   */
+  public function test_chado_db_select_should_throw_an_exception_if_table_is_undefined() {
+    $this->expectException(\Exception::class);
+    chado_db_select('some_nonexistent_table', 'd')->execute();
+  }
+
+  /**
+   * @group api
+   * @group chado
+   * @group chado_db_select
+   */
+  public function test_chado_db_select_recognizes_non_chado_tables() {
+    $query = chado_db_select('users', 'u');
+    $query->fields('u');
+    $query->range(0, 1);
+    $results = $query->execute()->fetchAll();
+
+    $this->assertNotEmpty($results);
+  }
+
+  /**
+   * @group api
+   * @group chado
+   * @group chado_db_select
+   */
+  public function test_chado_db_select_handles_aliases_correctly() {
+    $query = chado_db_select('public.users');
+    $query->fields('public_users');
+    $query->range(0, 1);
+    $results = $query->execute()->fetchAll();
+
+    $this->assertNotEmpty($results);
+  }
+
+  /**
+   * @group api
+   * @group chado
+   * @group chado_db_select
+   */
+  public function test_joining_chado_tables_in_chado_db_select() {
+    $feature = factory('chado.feature')->create();
+    $cvterm = factory('chado.cvterm')->create();
+    $pub = factory('chado.pub')->create();
+
+    $feature_cvterm = chado_insert_record('feature_cvterm', [
+      'feature_id' => $feature->feature_id,
+      'cvterm_id' => $cvterm->cvterm_id,
+      'pub_id' => $pub->pub_id,
+    ]);
+
+    $query = chado_db_select('feature', 'f');
+    $query->join('feature_cvterm', 'fcvt', 'f.feature_id = fcvt.feature_id');
+    $query->fields('f', ['name']);
+    $query->fields('fcvt', ['cvterm_id']);
+    $query->condition('f.feature_id', $feature->feature_id);
+    $found = $query->execute()->fetchObject();
 
+    $this->assertNotEmpty($found);
+    $this->assertEquals($feature_cvterm['cvterm_id'], $found->cvterm_id);
   }
 
+  /**
+   * @group api
+   * @group chado
+   * @group chado_db_select
+   */
+  public function test_left_joining_chado_tables_in_chado_db_select() {
+    $feature = factory('chado.feature')->create();
+    $cvterm = factory('chado.cvterm')->create();
+    $pub = factory('chado.pub')->create();
+
+    $feature_cvterm = chado_insert_record('feature_cvterm', [
+      'feature_id' => $feature->feature_id,
+      'cvterm_id' => $cvterm->cvterm_id,
+      'pub_id' => $pub->pub_id,
+    ]);
+
+    $query = chado_db_select('feature', 'f');
+    $query->leftJoin('feature_cvterm', 'fcvt', 'f.feature_id = fcvt.feature_id');
+    $query->fields('f', ['name']);
+    $query->fields('fcvt', ['cvterm_id']);
+    $query->condition('f.feature_id', $feature->feature_id);
+    $found = $query->execute()->fetchObject();
+
+    $this->assertNotEmpty($found);
+    $this->assertEquals($feature_cvterm['cvterm_id'], $found->cvterm_id);
+  }
+
+  /**
+   * @group api
+   * @group chado
+   * @group chado_db_select
+   */
+  public function test_right_joining_chado_tables_in_chado_db_select() {
+    $feature = factory('chado.feature')->create();
+    $cvterm = factory('chado.cvterm')->create();
+    $pub = factory('chado.pub')->create();
+
+    $feature_cvterm = chado_insert_record('feature_cvterm', [
+      'feature_id' => $feature->feature_id,
+      'cvterm_id' => $cvterm->cvterm_id,
+      'pub_id' => $pub->pub_id,
+    ]);
+
+    $query = chado_db_select('feature', 'f');
+    $query->rightJoin('feature_cvterm', 'fcvt', 'f.feature_id = fcvt.feature_id');
+    $query->fields('f', ['name']);
+    $query->fields('fcvt', ['cvterm_id']);
+    $query->condition('f.feature_id', $feature->feature_id);
+    $found = $query->execute()->fetchObject();
+
+    $this->assertNotEmpty($found);
+    $this->assertEquals($feature_cvterm['cvterm_id'], $found->cvterm_id);
+  }
+
+  /**
+   * @group api
+   * @group chado
+   * @group chado_db_select
+   */
+  public function test_inner_joining_chado_tables_in_chado_db_select() {
+    $feature = factory('chado.feature')->create();
+    $cvterm = factory('chado.cvterm')->create();
+    $pub = factory('chado.pub')->create();
+
+    $feature_cvterm = chado_insert_record('feature_cvterm', [
+      'feature_id' => $feature->feature_id,
+      'cvterm_id' => $cvterm->cvterm_id,
+      'pub_id' => $pub->pub_id,
+    ]);
+
+    $query = chado_db_select('feature', 'f');
+    $query->innerJoin('feature_cvterm', 'fcvt', 'f.feature_id = fcvt.feature_id');
+    $query->fields('f', ['name']);
+    $query->fields('fcvt', ['cvterm_id']);
+    $query->condition('f.feature_id', $feature->feature_id);
+    $found = $query->execute()->fetchObject();
+
+    $this->assertNotEmpty($found);
+    $this->assertEquals($feature_cvterm['cvterm_id'], $found->cvterm_id);
+  }
+
+  /**
+   * @group api
+   * @group chado
+   * @group chado_db_select
+   */
+  public function test_is_chado_table_returns_correct_results() {
+    $this->assertTrue(\ChadoPrefixExtender::isChadoTable('analysis'));
+    $this->assertTrue(\ChadoPrefixExtender::isChadoTable('feature_cvtermprop'));
+    $this->assertFalse(\ChadoPrefixExtender::isChadoTable('users'));
+  }
+
+  /**
+   * @group api
+   * @group chado
+   * @group chado_db_select
+   */
+  public function test_get_real_schema_returns_correct_results() {
+    $chado = chado_get_schema_name('chado');
+    $public = chado_get_schema_name('drupal');
+
+    $this->assertEquals($chado . '.analysis', \ChadoPrefixExtender::getRealSchema('chado.analysis'));
+    $this->assertEquals($public . '.users', \ChadoPrefixExtender::getRealSchema('public.users'));
+    $this->assertEquals('users', \ChadoPrefixExtender::getRealSchema('users'));
+  }
 }

+ 3 - 19
tripal_chado/api/tripal_chado.query.api.inc

@@ -2126,7 +2126,7 @@ function hook_chado_get_schema_name_alter($schema_name, $context) {
 }
 
 /**
- * A replacment for db_select when querying Chado.
+ * A replacement for db_select when querying Chado.
  *
  * Use this function instead of db_select when querying Chado tables.
  *
@@ -2142,24 +2142,8 @@ function hook_chado_get_schema_name_alter($schema_name, $context) {
  *   A new SelectQuery object for this connection.
  *
  * @ingroup tripal_chado_query_api
+ * @see \ChadoPrefixExtender::select()
  */
 function chado_db_select($table, $alias = NULL, array $options = []) {
-  if (empty($options['target'])) {
-    $options['target'] = 'default';
-  }
-
-  // We only want one connection for chado_db_select, so the first time we
-  // create it, we'll save it in the $GLOBALS array for use next time this
-  // function is called. If we don't do this, then the function will
-  // open too many connections and cause the database server to block.
-  $conn = NULL;
-  if (!array_key_exists('chado_db_select_connnection', $GLOBALS)) {
-    $conninfo = Database::getConnectionInfo();
-    $conn = new ChadoDatabaseConnection($conninfo['default']);
-    $GLOBALS['chado_db_select_connnection'] = $conn;
-  }
-  else {
-    $conn = $GLOBALS['chado_db_select_connnection'];
-  }
-  return $conn->select($table, $alias, $options);
+  return ChadoPrefixExtender::select($table, $alias, $options);
 }

+ 0 - 55
tripal_chado/includes/ChadoDatabaseConnection.inc

@@ -1,55 +0,0 @@
-<?php
-
-/**
- * Overrides the DatabaseConnection_pgsql.
- *
- * The primary purpose of this class is to allow for prefixing of Chado tables.
- * By default the only way to support this is to add an array to the 'prefix'
- * key of the settings.php file.  But this is problematic. For example, what
- * if there is a contact table in the Drupal database as well as one in Chado.
- * The default prefix replacement would always rewrite it to be the one in
- * Chado.  This class is intended to be used when the Chado tables
- * are needed.
- *
- */
-class ChadoDatabaseConnection extends DatabaseConnection_pgsql {
-
-  /**
-   * A replacement constructor for DatabaseConnection_pgsql::__construct.
-   *
-   * The primary purpose for overiding the constructor is to dynamically add
-   * a set of prefixes for replacing. This will allow Chado tables to be
-   * prefixed with the 'chado.' schema prefix.  The alternative to overridding
-   * the DatabaseConnection_pgsql is to ask the end-user to add a prefix
-   * entry for every Chado table and custom table they create.  That's not
-   * very manageable.
-   */
-  function __construct(array $connection_options = []) {
-    parent::__construct($connection_options);
-
-
-    // Get the list of prefix search and replace that are set in the
-    // settings.php file. We'll need those later.
-    $psearch = $this->prefixSearch;
-    $preplace = $this->prefixReplace;
-
-    // Reset the prefix serach and replace
-    $this->prefixSearch = [];
-    $this->prefixReplace = [];
-
-    $tables = chado_get_table_names(TRUE);
-    foreach ($tables as $table) {
-      $this->prefixSearch[] = '{' . $table . '}';
-      $this->prefixReplace[] = 'chado.' . $table;
-    }
-    $this->prefixSearch = array_merge($this->prefixSearch, $psearch);
-    $this->prefixReplace = array_merge($this->prefixReplace, $preplace);
-  }
-
-  public function prefixTables($sql) {
-    $sql = str_replace($this->prefixSearch, $this->prefixReplace, $sql);
-    return $sql;
-  }
-
-
-}

+ 265 - 0
tripal_chado/includes/ChadoPrefixExtender.inc

@@ -0,0 +1,265 @@
+<?php
+
+/**
+ * ChadoPrefixExtender
+ *
+ * A query extender that for select queries. By extending the
+ * SelectQueryExtender class, we can make sure that chado tables
+ *
+ * @see https://www.drupal.org/docs/7/api/database-api/dynamic-queries/extenders
+ */
+class ChadoPrefixExtender extends SelectQueryExtender {
+
+  /**
+   * A static cache for Chado tables.
+   *
+   * @var array
+   */
+  protected static $chado_tables = [];
+
+  /**
+   * A replacement for db_select when querying Chado.
+   *
+   * Use this function instead of db_select when querying Chado tables.
+   *
+   * @param string|\SelectQuery $table
+   *   The base table for this query. May be a
+   *   string or another SelectQuery object. If a query object is passed, it
+   *   will be used as a subselect.
+   * @param string $alias
+   *   The alias for the base table of this query.
+   * @param array $options
+   *   An array of options to control how the query
+   *   operates.
+   *
+   * @return \SelectQuery
+   *   A new SelectQuery object for this connection.
+   *
+   * @ingroup tripal_chado_query_api
+   */
+  public static function select($table, $alias = NULL, array $options = []) {
+    // Since the table could also be a SelectQuery object, we should verify that
+    // it is a string first.
+    if (is_string($table)) {
+      $table = static::getTable($table);
+    }
+
+    // If the alias is null, determine a safe alias. db_select fails to generate
+    // a safe alias when the table name is prefixed with "public.".
+    if (is_null($alias)) {
+      $alias = static::makeAlias($table);
+    }
+
+    // Create a select query
+    $query = db_select($table, $alias, $options);
+    return $query->extend('ChadoPrefixExtender');
+  }
+
+  /**
+   * @param $type
+   * @param $table
+   * @param null $alias
+   * @param null $condition
+   * @param array $arguments
+   *
+   * @return $this
+   *
+   * @see SelectQueryInterface::addJoin()
+   */
+  public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = []) {
+    $table = static::getTable($table);
+
+    if (is_null($alias)) {
+      $alias = static::makeAlias($table);
+    }
+
+    $this->query->addJoin($type, $table, $alias, $condition, $arguments);
+
+    return $this;
+  }
+
+  /**
+   * Overwrites the join to prefix table names.
+   *
+   * @param string $table
+   *   Table to join.
+   * @param string $alias
+   *   Alias for joined table.
+   * @param string $condition
+   *   Operation for joining.
+   * @param array $arguments
+   *   Additional arguments.
+   *
+   * @return $this
+   *   The current object.
+   *
+   * @ingroup tripal_chado_query_api
+   */
+  public function join($table, $alias = NULL, $condition = NULL, $arguments = []) {
+    $table = static::getTable($table);
+
+    if (is_null($alias)) {
+      $alias = static::makeAlias($table);
+    }
+
+    $this->query->join($table, $alias, $condition, $arguments);
+
+    return $this;
+  }
+
+  /**
+   * Overwrites the innerJoin to prefix table names.
+   *
+   * @param string $table
+   *   Table to join.
+   * @param string $alias
+   *   Alias for joined table.
+   * @param string $condition
+   *   Operation for joining.
+   * @param array $arguments
+   *   Additional arguments.
+   *
+   * @return $this
+   *   The current object.
+   *
+   * @ingroup tripal_chado_query_api
+   */
+  public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
+    $table = static::getTable($table);
+
+    if (is_null($alias)) {
+      $alias = static::makeAlias($table);
+    }
+
+    $this->query->innerJoin($table, $alias, $condition, $arguments);
+
+    return $this;
+  }
+
+  public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
+    $table = static::getTable($table);
+
+    if (is_null($alias)) {
+      $alias = static::makeAlias($table);
+    }
+
+    $this->query->leftJoin($table, $alias, $condition, $arguments);
+
+    return $this;
+  }
+
+  /**
+   * Overwrites the rightJoin to prefix table names.
+   *
+   * @param string $table
+   *   Table to join.
+   * @param string $alias
+   *   Alias for joined table.
+   * @param string $condition
+   *   Operation for joining.
+   * @param array $arguments
+   *   Additional arguments.
+   *
+   * @return $this
+   *   The current object.
+   *
+   * @ingroup tripal_chado_query_api
+   */
+  public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
+    $table = static::getTable($table);
+
+    if (is_null($alias)) {
+      $alias = static::makeAlias($table);
+    }
+
+    $this->query->rightJoin($table, $alias, $condition, $arguments);
+
+    return $this;
+  }
+
+  /**
+   * Checks if a table is a chado table.
+   *
+   * @param string $table The table name.
+   *
+   * @return bool
+   */
+  public static function isChadoTable($table) {
+    if (empty(static::$chado_tables)) {
+      static::$chado_tables = chado_get_table_names(TRUE);
+    }
+
+    return in_array($table, static::$chado_tables);
+  }
+
+  /**
+   * If the table name has a schema name as a prefix, replace it with the
+   * correct schema name.
+   *
+   * @param string $table
+   *   The table name.
+   *
+   * @return string
+   *   The table with the correct prefix.
+   *
+   */
+  public static function getTable($table) {
+    $chado_schema_name = chado_get_schema_name('chado');
+    $drupal_schema_name = chado_get_schema_name('drupal');
+
+    // No schema was provided.
+    if (strpos($table, '.') === FALSE) {
+      // If this is a chado table, add the chado prefix. Otherwise, add the
+      // public prefix.
+      if (static::isChadoTable($table)) {
+        $table = $chado_schema_name . ".{$table}";
+      }
+      else {
+        $table = $drupal_schema_name . ".{$table}";
+      }
+    }
+
+    // Now that the schema has been set, we can replace it with the correct
+    // name. Note that schema names can be altered by developers so we need to
+    // to run the following function to obtain the final name.
+    $table = static::getRealSchema($table);
+
+    return $table;
+  }
+
+  /**
+   * Allows altered schema names to be replaces correctly.
+   *
+   * @param string $table
+   *     The table name with a prefix such as "chado." or "public."
+   *
+   * @return mixed
+   *    The table name with the correct prefix.
+   */
+  public static function getRealSchema($table) {
+
+    if (strpos($table, 'public.') === 0) {
+      $replace = chado_get_schema_name('drupal') . '.';
+      return str_replace('public.', $replace, $table);
+    }
+
+    if (strpos($table, 'chado.') === 0) {
+      $replace = chado_get_schema_name('chado') . '.';
+      return str_replace('chado.', $replace, $table);
+    }
+
+    return $table;
+  }
+
+  /**
+   * Create a safe alias.
+   *
+   * @param string $table Table name.
+   *
+   * @return string
+   *    The safe alias.
+   */
+  public static function makeAlias($table) {
+    return str_replace('.', '_', $table);
+  }
+}

+ 1 - 1
tripal_chado/tripal_chado.module

@@ -68,7 +68,7 @@ require_once "includes/TripalFields/ChadoField.inc";
 require_once "includes/TripalFields/ChadoFieldWidget.inc";
 require_once "includes/TripalFields/ChadoFieldFormatter.inc";
 
-require_once "includes/ChadoDatabaseConnection.inc";
+require_once "includes/ChadoPrefixExtender.inc";
 
 tripal_chado_set_globals();