PDOException: SQLSTATE[42000]: [Microsoft][SQL Server Native Client 11.0][SQL Server]'GROUP_CONCAT' is not a recognized aggregate function.: SELECT TOP(25) pmi.[thread_id] AS [thread_id], MIN(pm.subject) AS subject, MAX(pm.timestamp) AS last_updated, MAX(pm.has_tokens) AS has_tokens, SUM(pmi.is_new) AS is_new, (SELECT GROUP_CONCAT(DISTINCT CONCAT(pmia.type, '_', pmia.recipient)) FROM {pm_index} pmia WHERE pmia.type <> 'hidden' AND pmia.thread_id = pmi.thread_id AND pmia.recipient <> :current) AS participants, pmi.thread_id AS _field_0 FROM {pm_message} pm INNER JOIN {pm_index} pmi ON pm.mid = pmi.mid INNER JOIN {pm_tags_index} pmti ON pmti.thread_id = pmi.thread_id AND pmti.uid = pmi.recipient AND pmi.type IN ('user', 'hidden') WHERE ( ([pmi].[recipient] = :db_condition_placeholder_0) AND ([pmi].[type] IN (:db_condition_placeholder_1, :db_condition_placeholder_2)) AND ([pmi].[deleted] = :db_condition_placeholder_3) AND ([pmti].[tag_id] = :db_condition_placeholder_4) ) GROUP BY pmi.thread_id ORDER BY last_updated DESC; Array ( [:db_condition_placeholder_0] => 3 [:db_condition_placeholder_1] => hidden [:db_condition_placeholder_2] => user [:db_condition_placeholder_3] => 0 [:db_condition_placeholder_4] => 1 [:current] => 3 ) en PagerDefault->execute() (línea 79 de C:\inetpub\wwwroot\drupal_david\public\includes\pager.inc).
From this exception, SQL Server is missing the Group_Concat implementation.
Reference to possible solutions:
- http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/9508abc...
- http://groupconcat.codeplex.com/
Install GROUP_CONCAT functions and modify database.inc accrodingly:
// Add prefixes to Drupal-specific functions.
$functions = array(
'SUBSTRING',
'SUBSTRING_INDEX',
'GREATEST',
'GROUP_CONCAT',
'CONCAT',
'IF',
);
But, once this is fixed, the same module gives an error due to using the CONCAT function with 3 parameters insted of 2 (in the same SQL query that failed previously).
This can be easily fixed by modifying the default function created by the driver to accept 3 parameters, making the last two optionals:
ALTER FUNCTION [dbo].[CONCAT](@op1 sql_variant = 11, @op2 sql_variant = '',@op3 sql_variant = '') RETURNS nvarchar(4000) AS
BEGIN
DECLARE @result nvarchar(4000)
SET @result = CAST(@op1 AS nvarchar(4000)) + CAST(@op2 AS nvarchar(4000)) + CAST(@op3 AS nvarchar(4000))
RETURN @result
END
To convert all of these into a patch....
1. Modifiy the driver installer (install.inc) to include the creation of the procedures provided in GROUP_CONTACT.zip (obtained from http://groupconcat.codeplex.com/). It should also be considered that SQL SERVER 2012 has built-in GROUP_CONTACT.
2. Path "database.inc" to prefix calls to GROUP_CONTACT (->[dbo].[GROUP_CONTACT]), snippet provided.
3. Modify driver installer (install.inc) to include the new version of CONCAT wich is more flexible as to the number of parameters it can receive, and has fully backwards compatibility with old implementation.
If i find the time I will turn all of these into a decent path, in the meanwhile applying these 3 changes can server as a fix!
| Comment | File | Size | Author |
|---|---|---|---|
| #1 | GROUP_CONCAT.zip | 7.99 KB | david_garcia |
Comments
Comment #1
david_garcia commentedComment #2
xenphibian commentedI initially looked at using this as well. However, this requires an access level that allows you to enable the SQLCLR which is going to be frowned upon by shared hosts because of the potential for EXTREMELY unsecure and really, really damaging code. You can have a C# program go in and do almost anything you want to the server if you know how, including calling a C++ or ASM program which inserts bytecode into the server (like possibly replacing an interrupt with some code of your choice and then causing that interrupt) and potentially expose the entire server to hackers. As a result the solution provided is not a solution that is level for all databases. It requires special access to the server which some (many?) hosts do not allow. (None with shared servers who are in their right minds, anyway.) This is directly in conflict with the concept/intent of Drupal as I believe it to be.
I am currently using the XML Path solution and it seems to work well without requiring enabling the SQLCLR.
Comment #3
david_garcia commentedGood observation indeed, I just spent about an hour solving this issue for a project I'm working in without actually giving it a deeper thought.
As per your post, I surmise you might have a T-SQL implementation of GROUP_CONTACT encapsulated inside a User Function, can you provide it? I've been looking around but was able to find nothing but in-query implementations of the functionality.
From http://www.sqlservercentral.com/Forums/Topic984025-391-1.aspx:
"There are quite few ways to do so one is using cross tab queries other is using CLR based agreegate functions
kindly read MSDN Article for CLR based agreegate functions
http://msdn.microsoft.com/en-us/library/ms131056.aspx
or other articles of similar kind with little bit variation here and there
http://www.mssqltips.com/sqlservertip/2022/concat-aggregates-sql-server-...
http://dotnet-enthusiast.blogspot.in/2007/05/user-defined-aggregate-func...
For Cross Tab Based Solution
http://www.stevenmapes.com/stevipedia/recreating+mysql+group_concat+in+m..."
I agree that the CLR implementation is not an option for a definitive patch but a good fix until we have an alternative implementation.
Comment #4
david_garcia commentedupdate!! GROUP_CONCAT IS NATIVELY AVAILABLE IN SQL SERVER 2012 AND AZURE!!
Comment #6
david_garcia commented7.x-1.x and 8.x-1.x version of the driver now include GROUP_CONCAT function prefixing.
Yet, user STILL NEEDS to MANUALLY run the CLR function installation, see comments above.
If anyone has an alternative solution (maybe rewriting the query in the driver to use FOR XML?) feel free to reopen and propose.