/* 
   Postgres95SQLExpression.m

   Copyright (C) 1996 Free Software Foundation, Inc.

   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
	      based on the Sybase Adaptor written by 
	   Ovidiu Predescu <ovidiu@bx.logicnet.ro>
   Date: December 1996

   This file is part of the GNUstep Database Library.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; see the file COPYING.LIB.
   If not, write to the Free Software Foundation,
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include <Foundation/NSUtilities.h>

#include <extensions/NSException.h>

#include <eoaccess/EOEntity.h>
#include <eoaccess/EORelationship.h>
#include <eoaccess/EOAttribute.h>
#include <eoaccess/EOAttributeOrdering.h>

#include <eoadaptors/Postgres95/Postgres95Exceptions.h>
#include <eoadaptors/Postgres95/Postgres95SQLExpression.h>
#include <eoaccess/EOAdaptor.h>

@implementation Postgres95SQLExpression

//Serveur does not accept where clause like field = null
//we replace this by field is null
+(NSString*)convertWhereClause:(NSString*)whereClause
{
  if (whereClause)
	{
	  NSString* _replace=@"= NULL";
	  NSRange range=[whereClause rangeOfString:_replace];
	  if (range.length>0)
        {
		  NSString* _by=@"is null";
          int byLen=[_by length];
		  whereClause=[whereClause mutableCopy];
          do
			{
			  [(NSMutableString*)whereClause replaceCharactersInRange:range
								 withString: _by];
			  range.location+=byLen;
			  range.length=[whereClause length]-range.location;
			  range=[whereClause rangeOfString: _replace
								 options: 0
								 range: range];
			}
          while (range.length>0);
        };
	};
  return whereClause;
}


+ (Class)selectExpressionClass
{
    return [Postgres95SelectSQLExpression class];
}

+ (Class)deleteExpressionClass 
{
    return [Postgres95DeleteSQLExpression class];
}

+ (Class)updateExpressionClass
{
    return [Postgres95UpdateSQLExpression class];
}

@end /* Postgres95SQLExpression */


@implementation Postgres95SelectSQLExpression

- selectExpressionForAttributes:(NSArray*)attributes
  lock:(BOOL)flag
  qualifier:(EOQualifier*)qualifier
  fetchOrder:(NSArray*)fetchOrder
  channel:(EOAdaptorChannel*)channel
{
    lock = flag;
    [super selectExpressionForAttributes:attributes
	   lock:flag
	   qualifier:qualifier
	   fetchOrder:fetchOrder
	   channel:channel];
    return self;
}

- (NSString*)fromClause
{
    NSMutableString* fromClause
	    = [NSMutableString stringWithCString:"\nFROM "];
    NSEnumerator* enumerator = [fromListEntities objectEnumerator];
    BOOL first = YES;
    id key;

    /* Compute the FROM list from all the aliases found in
       entitiesAndPropertiesAliases dictionary. Note that this dictionary
       contains entities and relationships. The last ones are there for
       flattened attributes over reflexive relationships. */
    while((key = [enumerator nextObject])) {
	if(first)
	    first = NO;
	else
	    [fromClause appendString:@", "];

	if([key isKindOfClass:[EORelationship class]]) {
	    /* This key corresponds to a flattened attribute. */
	    [fromClause appendFormat:@"%@ %@",
			    [[key destinationEntity] externalName],
			    [entitiesAndPropertiesAliases objectForKey:key]];
	    /* xxx HOLDLOCK doesn't work! */
#if 0
	    if (lock)
		[fromClause appendString:@" HOLDLOCK"];
#endif
	}
	else {
	    /* This is an EOEntity. */
	    [fromClause appendFormat:@"%@ %@",
			    [key externalName],
			    [entitiesAndPropertiesAliases objectForKey:key]];
	    /* xxx HOLDLOCK doesn't work! */
#if 0
	    if (lock)
		[fromClause appendString:@" HOLDLOCK"];
#endif
	}
    }

    return fromClause;
}

/*
 *  Version < 6.0 does not accept table aliases and ASC/DESC in ORDER BY
 *  only ascending seems to be supported.
 */

- (NSString*)orderByClauseForFetchOrder:(NSArray*)fetchOrder
{
    int i, count = [fetchOrder count];
    NSMutableString* orderBy;
    BOOL first = YES;
	NSDictionary* connectionDictionary=[[self adaptor] connectionDictionary];
	float databaseVersion=[[connectionDictionary objectForKey:@"databaseVersion"] floatValue];
	BOOL isSupportingDescendingOrderBy=(databaseVersion>=6.0); //May be previous versions support it too but I don't know

    if(!count)
	  return @"";

    orderBy = (id)[NSMutableString stringWithCString:"\nORDER BY "];
    for(i = 0; i < count; i++) {
	EOAttributeOrdering* order = [fetchOrder objectAtIndex:i];
	EOOrdering ordering = [order ordering];

	if (!isSupportingDescendingOrderBy)
	  {
		if (ordering == EODescendingOrder)
		  THROW([[Postgres95Exception alloc] initWithFormat:
											   @"Postgres95 does not support DESC[ENDING] in ORDER BY"]);
		if (ordering == EODescendingOrder)
		  continue;
	  };
	
	if (first)
	    first = NO;
	else
	    [orderBy appendString:@", "];
	
	[orderBy appendFormat:@"%@", [self expressionValueForAttribute:[order attribute]]];

	if (!isSupportingDescendingOrderBy)
	  {
		if (ordering == EODescendingOrder)
		  [orderBy appendString:@" DESC"];
		else
		  [orderBy appendString:@" ASC"];
	  };
    }

    return orderBy;
}

//Serveur does not accept where clause like field = null
//we replace this by field is null
- (NSString*)whereClauseForQualifier:(EOQualifier*)qualifier
  joinExpresssion:(NSString*)joinExpression
{
  NSString* whereClause=[super whereClauseForQualifier:qualifier
							   joinExpresssion:joinExpression];
  whereClause=[Postgres95SQLExpression convertWhereClause:whereClause];
  return whereClause;
}


@end /* Postgres95SelectSQLExpression */

@implementation Postgres95DeleteSQLExpression : EODeleteSQLExpression
//Serveur does not accept where clause like field = null
//we replace this by field is null
- (NSString*)whereClauseForQualifier:(EOQualifier*)qualifier
  joinExpresssion:(NSString*)joinExpression
{
  NSString* whereClause=[super whereClauseForQualifier:qualifier
							   joinExpresssion:joinExpression];
  whereClause=[Postgres95SQLExpression convertWhereClause:whereClause];
  return whereClause;
}
@end

@implementation Postgres95UpdateSQLExpression : EOUpdateSQLExpression
//Serveur does not accept where clause like field = null
//we replace this by field is null
- (NSString*)whereClauseForQualifier:(EOQualifier*)qualifier
  joinExpresssion:(NSString*)joinExpression
{
  NSString* whereClause=[super whereClauseForQualifier:qualifier
							   joinExpresssion:joinExpression];
  whereClause=[Postgres95SQLExpression convertWhereClause:whereClause];
  return whereClause;
}
@end

