I've successfully installed the newest sqlsrv module update with the help of the david_garcia and the Wincance module's great README.txt file.

However I received this error when trying to update the Wincache extension from 1.3.5.0 to 1.3.7.4 as recommended on the D8 Version and queue gardening post referring to "minimum required environment software to run the SQL Server driver":

Fatal error: Call to undefined function wincache_ucache_get() in includes\database\sqlsrv\database.inc on line 507

These are the steps I took from the recommendations:

  • ODBC 11 *Already installed*
  • Wincache >= 1.3.7.4 *Error when changed from 1.3.5.0; Details above*
  • PDO >= 3.2.0.0 *SUCCESS*
  • PHP >= 5.4 *Already have version 5.5*
  • Recommended SQL Server 2012 or above *Cannot do this right now; Have to stay with SQL Server 2008 R2*

Here are my questions:

  • Are there any issues with me staying with Wincache 1.3.5.0?
  • What could cause that fatal error?
  • Since I don't have the option to upgrade to SQL Server 2012 right now, what issues can/will that cause?

Comments

katannshaw’s picture

Title: Wincache extension update > 1.3.7.4 causes fatal error » Wincache extension 1.3.7.4 + sqlsrv updates cause fatal error

Looking into this further, I noticed that this error gets displayed with drush status no matter what, but only gets displayed in the browser when php_wincache.dll (1.3.7.4) is installed like this:

php_wincache.dll (1.3.5.0)
drush status = error
view site in browser = looks fine

php_wincache.dll (1.3.7.4)
drush status = error
view site in browser = error

This makes me believe that the issue has to do with the sqlsrv module update itself and updating the php_wincache.dll somehow causes the error to get displayed on the site. This is what Drush returned:

Drush command terminated abnormally due to an unrecoverable error. [error]

Error: Call to undefined function wincache_ucache_get() in includes\database\sqlsrv\database.inc, line 507

Line 507 of includes\database\sqlsrv\database.inc using the wincache_ucache_get function:

/**
   * Internal function: massage a query to make it compliant with SQL Server.
   */
  public function preprocessQuery($query) {
    // Generate a cache signature for this query.
    $query_signature = 'query_cache_' . md5($query);

    // Drill through everything...
    $success = FALSE;
    $cache = wincache_ucache_get($query_signature, $success); //<<<<---ERROR ON LINE 507
    if ($success) {
      return $cache;
    }
david_garcia’s picture

StatusFileSize
new361.63 KB
new784.63 KB

You need this in PHP.ini to enable Wincache for CLI:

wincache.enablecli=1

This should solve your issues with Drush.

Yet, that does not explain why you are getting "wincache_ucache_get" as an undefined function.

Things you *can* check:

1) appoolid is NOT SET.
2) ucenabled and ucachesize (former enabled latter big enough)
3) Navigate to /admin/reports/status/wincache and try to spot something wrong

alt

aa

david_garcia’s picture

I forgot to say, wincache_ucache_get undefined means that the WINCACHE extension is not being loaded.

Make sure it is listed in your PHP.info and review your PHP logs to see any possible initilization errors that have prevented the WINCACHE extension from loading.

katannshaw’s picture

Thanks for the prompt reply.

I forgot to say, wincache_ucache_get undefined means that the WINCACHE extension is not being loaded.

Make sure it is listed in your PHP.info and review your PHP logs to see any possible initilization errors that have prevented the WINCACHE extension from loading.

That's the strange thing. The last line of php.ini lists the wincache dll extension as it always has been:

[PHP_WINCACHE]
extension=php_wincache.dll

This is correct?

I'll also check on your other suggestions from post #2. Thank you.

katannshaw’s picture

@david_garcia: Sorry for the delay. Here's where I'm at with this issue:

Make sure it is listed in your PHP.info and review your PHP logs to see any possible initilization errors that have prevented the WINCACHE extension from loading.

The wincache extension is listed on the last line of the php.ini file like this:

[PHP_WINCACHE]
extension=php_wincache.dll
You need this in PHP.ini to enable Wincache for CLI:
wincache.enablecli=1
This should solve your issues with Drush.

I did this however I still continue to receive the same error in Drush with any command (even drush browse as seen in screenshot):

Drush command terminated abnormally due to an unrecoverable error. [error]
Error: Call to undefined function wincache_ucache_get() in includes\database\sqlsrv\database.inc, line 507
Yet, that does not explain why you are getting "wincache_ucache_get" as an undefined function.
Things you *can* check:

1) appoolid is NOT SET.

I set this to match the apppoolid in IIS. There was no change.
wincache.apppoolid = wwwdevelapppool

2) ucenabled and ucachesize (former enabled latter big enough)

It's enabled and set to 24 like this but there was no change.

wincache.ucenabled = 1
wincache.ucachesize = 24
3) Navigate to /admin/reports/status/wincache and try to spot something wrong

I went to that report page and didn't see anything obvious.

I've included screenshots of the /admin/reports/status/wincache page and the Drush error. Please let me know if you see anything amiss or have any other suggestions. Thanks.

david_garcia’s picture

wincache.apppoolid = wwwdevelapppool

This should be completely removed, leave apppoolid unset.

I did this however I still continue to receive the same error in Drush with any command (even drush browse as seen in screenshot):

It is a common mistake to not have clear how and where different php runtimes take part. You might have set wincache.enable_cli for the website, but not for the runtime that your console is using.

Make sure it is listed in your PHP.info

That was my mistake. I meant phpinfo(). If it is showing there, then the extension was properly loaded into the runtime.

katannshaw’s picture

StatusFileSize
new109.28 KB

I re-read "1) appoolid is NOT SET.". Ugh. I've reset it to NOT SET.

This specific site is running on a remote server, not locally. I checked phpinfo() and see that wincache.enablecli is set to On (screenshot - phpinfo-wincache.png). I'm not sure what else to check with Drush. I'll keep digging. Any more suggestions would be great.

david_garcia’s picture

It is a common mistake to not have clear how and where different php runtimes take part. You might have set wincache.enable_cli for the website, but not for the runtime that your console is using.

This means that probably your Drush is not using the same runtime as the web site. Call phpinfo() from the console an see what runtime and ini settings it is using. I bet they are not the same as the website, and that wincache extension is not enabled on it.

katannshaw’s picture

Yes, that was it! Thank you. For some reason the version's not switching over from 1.3.5 > 1.3.7 when I remote into the server, place the new wincache extension (wincache-1.3.7.4-5.6-nts-vc11-x86.exe) into the C:\Windows\Program Files (x86)\PHP\ext folder, and check out the phpinfo() and admin/reports/status/wincache pages. It just continues to say WinCache version 1.3.5.0. But it's progress. Hopefully I'll figure it out tomorrow and update this issue report.

I downloaded the 1.3.7 extension from this location: http://sourceforge.net/projects/wincache/files/wincache-1.3.7/

katannshaw’s picture

Assigned: Unassigned » katannshaw
Status: Active » Closed (fixed)

I was able to solve this issue with a few additional steps:

1. The most-recent wincache download I was using wasn't working for me and was giving me this error:
Fatal error: Call to undefined function wincache_ucache_get() in includes\database\sqlsrv\database.inc on line 507
I switched from using the download at the top of the list (wincache-1.3.7.4-5.6-nts-vc11-x86.exe) to the matching download just below it wincache-1.3.7.4-5.5-nts-vc11-x86.exe, and it then worked for me as it should.

2. There was a misconfiguration in the php.ini file. Once I went into PHP Manager in IIS Manager and checked the php setup, I could see that there were issues with the configuration in php.ini. Once fixed, I now have wincache 1.3.7.4 installed and phpinfo() shows everything as it should.

katannshaw’s picture

Assigned: katannshaw » Unassigned

oops.

mlochd’s picture

StatusFileSize
new56.49 KB

Hello, Hola David,

I have a similar problem in drush... I'm getting:

Error: Call to undefined function wincache_ucache_get() in sites\all\modules\wincachedrupal\drupal_win_cache.inc, line 165

which is ...

// Fetch the data.
$cache = wincache_ucache_get($this->key($cid), $success); <-- Line 165

// Should return FALSE on failure.
if ($success === FALSE) {
return FALSE;
}
My settings are displayed in Capture.PNG

katannshaw’s picture

Title: Wincache extension 1.3.7.4 + sqlsrv updates cause fatal error » Call to undefined function wincache_ucache_get() in includes\database\sqlsrv\database.inc
Version: 7.x-2.0-beta3 » 7.x-2.0
Category: Support request » Bug report
Status: Closed (fixed) » Active

My environment has changed from IIS 7.5 to Apache 2.4 with my new client and I'm still having this issue and need help. Here are the details:

My Environment:
Apache 2.4
Windows 2008 R2
PHP 5.6
SQL Server 2012

Issue:

  • We are trying to update SQL Server from 7.x-1.4 > 7.x-2.0
  • We’re receiving the same error as my OP:

Fatal error: Call to undefined function wincache_ucache_get() in includes\database\sqlsrv\database.inc on line 507

  • When comparing the preprocessQuery function in 7.x-1.4 > 7.x-2.0 we can see that the caching wasn’t called in 7.x-1.4:
  • 7.x-1.4
/**
   * Internal function: massage a query to make it compliant with SQL Server.
   */
  public function preprocessQuery($query) {
    // Force quotes around some SQL Server reserved keywords.
    if (preg_match('/^SELECT/i', $query)) {
      $query = preg_replace_callback(self::RESERVED_REGEXP, array($this, 'replaceReservedCallback'), $query);
    }

    // Last chance to modify some SQL Server-specific syntax.
    $replacements = array(
      // Normalize SAVEPOINT syntax to the SQL Server one.
      '/^SAVEPOINT (.*)$/' => 'SAVE TRANSACTION $1',
      '/^ROLLBACK TO SAVEPOINT (.*)$/' => 'ROLLBACK TRANSACTION $1',
      // SQL Server doesn't need an explicit RELEASE SAVEPOINT.
      // Run a non-operaiton query to avoid a fatal error
      // when no query is runned.
      '/^RELEASE SAVEPOINT (.*)$/' => 'SELECT 1 /* $0 */',
    );
    $query = preg_replace(array_keys($replacements), $replacements, $query);

    // Add prefixes to Drupal-specific functions.
    $functions = $this->schema()->DrupalSpecificFunctions();
    foreach ($functions as $function) {
      $query = preg_replace('/\b(?<![:.])(' . preg_quote($function) . ')\(/i', $this->schema()->defaultSchema . '.$1(', $query);
    }

    $replacements = array(
      'LENGTH' => 'LEN',
      'POW' => 'POWER',
    );
    foreach ($replacements as $function => $replacement) {
      $query = preg_replace('/\b(?<![:.])(' . preg_quote($function) . ')\(/i', $replacement . '(', $query);
    }

    // Replace the ANSI concatenation operator with SQL Server poor one.
    $query = preg_replace('/\|\|/', '+', $query);

    return $query;
  }

7.x-2.0

/**
   * Internal function: massage a query to make it compliant with SQL Server.
   */
  public function preprocessQuery($query) {
    // Generate a cache signature for this query.
    $query_signature = 'query_cache_' . md5($query);

    // Drill through everything...
    $success = FALSE;
    $cache = wincache_ucache_get($query_signature, $success);
    if ($success) {
      return $cache;
    }

    // Force quotes around some SQL Server reserved keywords.
    if (preg_match('/^SELECT/i', $query)) {
      $query = preg_replace_callback(self::RESERVED_REGEXP, array($this, 'replaceReservedCallback'), $query);
    }

    // Last chance to modify some SQL Server-specific syntax.
    $replacements = array();

    // Add prefixes to Drupal-specific functions.
    $defaultSchema = $this->schema()->GetDefaultSchema();
    foreach ($this->schema()->DrupalSpecificFunctions() as $function) {
      $replacements['/\b(?<![:.])(' . preg_quote($function) . ')\(/i'] =  "{$defaultSchema}.$1(";
    }

    // Rename some functions.
    $funcs = array(
      'LENGTH' => 'LEN',
      'POW' => 'POWER',
    );

    foreach ($funcs as $function => $replacement) {
      $replacements['/\b(?<![:.])(' . preg_quote($function) . ')\(/i'] = $replacement . '(';
    }

    // Replace the ANSI concatenation operator with SQL Server poor one.
    $replacements['/\|\|/'] =  '+';

    // Now do all the replacements at once.
    $query = preg_replace(array_keys($replacements), array_values($replacements), $query);

    // Store the processed query, and make sure we expire it some time
    // so that scarcely used queries don't stay in the cache forever.
    wincache_ucache_set($query_signature, $query, rand(600, 3600));

    return $query;
  }
  • The latest version of the SQL Server driver module requires us to use PHP 5.6
  • We’re running the site on Apache 2.4, which requires thread-safe version of PHP
  • PHP 5.6 doesn’t have wincache extension for thread-safe; we must use opcache extension
  • We enabled opcache in php.ini but the error remains
  • We have no option to fix this issue with using the wincache extension because of this requirement from the SQL Server driver module itself, and don’t know how to proceed.

Any and all help would be appreciated.

david_garcia’s picture

Category: Bug report » Feature request

Sorry I'm moving this to feature request....

  • The 7.x-2.x branch of the driver is tightly coupled with Wincache. Not only in the place you are indicating, there are other calls spread over the driver.
  • I don't think you will be able to use Wincache with apache. Besides the thread-safe requirement, I believe that internally the Wincache extension might be dependant on some specific IIS features/settings. You can get more information on this through the Wincache support forum: https://forums.iis.net/1164.aspx

This basically means that SQL Server 7.x-2.x + Apache is a NO GO.

Because the SQL Server team is preparing a Linux ready version of the PDO driver I made the caching backend pluggable in 8.x-2.x. So in Drupal 8 this will not be a problem as you will be able to replace Wincache with APC/APCu.

This basically leaves you with 2 posibilities:

1. Stick to 7.x-1.4 that does not depend on Wincache to run
2. Modify the 7.x-2.x branch to make the caching backend plugable, and implement an APCu version instead of using Wincache.

katannshaw’s picture

Hi @david_garcia: Thanks for the quick reply and thorough explanation. Thanks for changing it back to a feature request; I wasn't sure which to put it under with what I'm dealing with so I appreciate your guidance on that.

Option 1 is a no-go for us because of the security update needed. Option 2 sounds like something we'd need to do. Could you give a hint as to how we'd accomplish that?

david_garcia’s picture

Could you give a hint as to how we'd accomplish that?

I don't even think this is worth being done for 7.x-2.x. I surmise you are running Apache on Windows. If that is the case, APCu is badly broken on windows and segfaults more often than not.

Your best bet is to completely remove from the driver anything that deals with Wincache. That will come at a performance cost, but not something to be worried about.

katannshaw’s picture

Ok thanks for the advise @david_garcia.

katannshaw’s picture

@david_garcia: If we remove the wincache driver we receive this error with the newest version of the SQL Server module:

Fatal error: Call to undefined function wincache_ucache_get() in C:\Apache24\htdocs\includes\database\sqlsrv\database.inc on line 574

In reference to this section of code in includes/database/sqlsrv/database.inc:

/**
   * Internal function: massage a query to make it compliant with SQL Server.
   */
  public function preprocessQuery($query) {
    // Generate a cache signature for this query.
    $query_signature = 'query_cache_' . md5($query);

    // Drill through everything...
    $success = FALSE;
    $cache = wincache_ucache_get($query_signature, $success);
    if ($success) {
      return $cache;
    }

So what do we do if the database.inc file is calling for this caching method if we're *not* using wincache?

$cache = wincache_ucache_get($query_signature, $success);

david_garcia’s picture

Your best bet is to completely remove from the driver anything that deals with Wincache

This means to modify the driver to remove any calls to wincache :(

david_garcia’s picture

Status: Active » Closed (won't fix)

@jayhawkfan75 I am closing this because it's a mixture of too many things, and Im not sure there is anything that can be done from the driver itself.

katannshaw’s picture

That's cool david_garcia. After your advice we're talking with the client about possibly converting the site from Apache to IIS since it's a more future-proof approach with this module and its needed drivers. Thanks again for all of your input, it's always valued.

josephdpurcell’s picture

I ran into this problem when attempting to upgrade the sqlsrv module. I was surprised to find that wincache is a hard dependency. I've created a feature request to make that optional: #2824938: Cannot upgrade to supported PHP version due to wincache dependency.