2002-11-15 22:57:05 +00:00
|
|
|
/**
|
2006-09-15 13:01:07 +00:00
|
|
|
PostgreSQLChannel.m <title>PostgreSQLChannel</title>
|
2002-11-15 22:57:05 +00:00
|
|
|
|
2005-08-17 08:07:57 +00:00
|
|
|
Copyright (C) 2000-2002,2003,2004,2005 Free Software Foundation, Inc.
|
2002-11-15 22:57:05 +00:00
|
|
|
|
2006-09-14 16:06:21 +00:00
|
|
|
Author: Mirko Viviani <mirko.viviani@gmail.com>
|
2002-11-15 22:57:05 +00:00
|
|
|
Date: February 2000
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
based on the PostgreSQL adaptor written by
|
2002-11-15 22:57:05 +00:00
|
|
|
Mircea Oancea <mircea@jupiter.elcom.pub.ro>
|
|
|
|
|
|
|
|
Author: Manuel Guesdon <mguesdon@orange-concept.com>
|
|
|
|
Date: October 2000
|
|
|
|
|
|
|
|
$Revision$
|
|
|
|
$Date$
|
|
|
|
|
|
|
|
<abstract></abstract>
|
|
|
|
|
|
|
|
This file is part of the GNUstep Database Library.
|
|
|
|
|
|
|
|
<license>
|
|
|
|
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,
|
2005-08-17 08:07:57 +00:00
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2002-11-15 22:57:05 +00:00
|
|
|
</license>
|
|
|
|
**/
|
|
|
|
|
2002-12-31 16:25:21 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
RCS_ID("$Id$")
|
2002-11-15 22:57:05 +00:00
|
|
|
|
2003-03-31 00:24:15 +00:00
|
|
|
|
2004-03-19 16:41:21 +00:00
|
|
|
#ifdef GNUSTEP
|
2003-03-31 00:24:15 +00:00
|
|
|
#include <Foundation/NSArray.h>
|
|
|
|
#include <Foundation/NSDictionary.h>
|
|
|
|
#include <Foundation/NSString.h>
|
2004-02-25 12:27:43 +00:00
|
|
|
#include <Foundation/NSSet.h>
|
2003-03-31 00:24:15 +00:00
|
|
|
#include <Foundation/NSObjCRuntime.h>
|
|
|
|
#include <Foundation/NSUtilities.h>
|
|
|
|
#include <Foundation/NSException.h>
|
2004-02-26 10:33:10 +00:00
|
|
|
#include <Foundation/NSAutoreleasePool.h>
|
2003-03-31 00:24:15 +00:00
|
|
|
#include <Foundation/NSDebug.h>
|
|
|
|
#else
|
|
|
|
#include <Foundation/Foundation.h>
|
2004-02-14 02:02:15 +00:00
|
|
|
#include <GNUstepBase/GSCategories.h>
|
2003-03-31 00:24:15 +00:00
|
|
|
#endif
|
|
|
|
|
2003-07-11 19:04:05 +00:00
|
|
|
#ifndef GNUSTEP
|
2003-08-25 20:01:59 +00:00
|
|
|
#include <GNUstepBase/GNUstep.h>
|
2004-01-31 13:57:38 +00:00
|
|
|
#include <GNUstepBase/GSCategories.h>
|
2003-07-11 19:04:05 +00:00
|
|
|
#endif
|
|
|
|
|
2003-03-31 00:24:15 +00:00
|
|
|
#include <EOControl/EONull.h>
|
|
|
|
#include <EOControl/EOQualifier.h>
|
|
|
|
#include <EOControl/EOFetchSpecification.h>
|
2003-06-24 16:27:01 +00:00
|
|
|
#include <EOControl/EONSAddOns.h>
|
2003-03-31 00:24:15 +00:00
|
|
|
#include <EOControl/EODebug.h>
|
|
|
|
|
|
|
|
#include <EOAccess/EOAttribute.h>
|
|
|
|
#include <EOAccess/EOEntity.h>
|
|
|
|
#include <EOAccess/EOModel.h>
|
|
|
|
#include <EOAccess/EOSQLExpression.h>
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
#include <PostgreSQLEOAdaptor/PostgreSQLChannel.h>
|
|
|
|
#include <PostgreSQLEOAdaptor/PostgreSQLContext.h>
|
|
|
|
#include <PostgreSQLEOAdaptor/PostgreSQLValues.h>
|
2002-11-15 22:57:05 +00:00
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
#include "PostgreSQLPrivate.h"
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
static void __dummy_function_used_for_linking(void)
|
|
|
|
{
|
2006-09-15 12:05:56 +00:00
|
|
|
extern void __postgres_values_linking_function(void);
|
2002-11-15 22:57:05 +00:00
|
|
|
|
2006-09-15 12:05:56 +00:00
|
|
|
__postgres_values_linking_function();
|
2002-11-15 22:57:05 +00:00
|
|
|
__dummy_function_used_for_linking();
|
|
|
|
}
|
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
#define EOAdaptorDebugLog(format, args...) \
|
|
|
|
do { if ([self isDebugEnabled]) { NSLog(format , ## args); } } while (0)
|
2003-06-24 16:27:01 +00:00
|
|
|
#define NSS_SWF NSString stringWithFormat
|
2004-02-25 12:27:43 +00:00
|
|
|
|
2003-06-24 16:27:01 +00:00
|
|
|
static NSDictionary *
|
|
|
|
pgResultDictionary(PGresult *pgResult)
|
|
|
|
{
|
|
|
|
int nfields, ntuples;
|
|
|
|
int i, j;
|
|
|
|
NSMutableArray *fields;
|
|
|
|
NSMutableArray *tuples;
|
|
|
|
ExecStatusType statusType;
|
|
|
|
|
|
|
|
nfields = PQnfields(pgResult);
|
|
|
|
ntuples = PQntuples(pgResult);
|
|
|
|
|
2005-02-19 12:13:22 +00:00
|
|
|
fields = [NSMutableArray arrayWithCapacity: nfields];
|
|
|
|
tuples = [NSMutableArray arrayWithCapacity: ntuples];
|
2003-06-24 16:27:01 +00:00
|
|
|
|
|
|
|
for (i = 1; i <= nfields; i++)
|
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
NSString *fname;
|
|
|
|
NSNumber *fnumber;
|
|
|
|
NSNumber *ftype;
|
|
|
|
NSNumber *fsize;
|
|
|
|
NSNumber *fmod;
|
|
|
|
NSDictionary *dict;
|
|
|
|
char *cfname;
|
|
|
|
|
|
|
|
cfname = PQfname(pgResult, i);
|
|
|
|
|
|
|
|
fname = [NSString stringWithCString: cfname];
|
|
|
|
fnumber = [NSNumber numberWithInt: PQfnumber(pgResult, cfname)];
|
|
|
|
ftype = [NSNumber numberWithUnsignedInt: PQftype(pgResult, i)];
|
|
|
|
fsize = [NSNumber numberWithInt: PQfsize(pgResult, i)];
|
|
|
|
fmod = [NSNumber numberWithInt: PQfmod(pgResult, i)];
|
|
|
|
|
|
|
|
dict = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
fname, @"PQfname",
|
|
|
|
fnumber, @"PQfnumber",
|
|
|
|
ftype, @"PQftype",
|
|
|
|
fsize, @"PQfsize",
|
|
|
|
fmod, @"PQfmod",
|
|
|
|
nil];
|
|
|
|
|
|
|
|
[fields addObject: dict];
|
2003-06-24 16:27:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 1; i <= ntuples; i++)
|
|
|
|
{
|
|
|
|
NSMutableDictionary *tuple;
|
2005-02-19 12:13:22 +00:00
|
|
|
tuple = [NSMutableDictionary dictionaryWithCapacity: nfields];
|
2003-06-24 16:27:01 +00:00
|
|
|
for (j = 1; j <= nfields; j++)
|
|
|
|
{
|
|
|
|
NSString *tupleInfo;
|
|
|
|
NSString *tupleKey;
|
2005-02-19 12:13:22 +00:00
|
|
|
|
|
|
|
tupleKey = [NSString stringWithCString: PQfname(pgResult, j)];
|
|
|
|
|
2003-06-24 16:27:01 +00:00
|
|
|
if (PQgetisnull(pgResult, i, j))
|
|
|
|
{
|
|
|
|
tupleInfo = @"NULL";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSString *fmt;
|
|
|
|
fmt = [NSS_SWF: @"%%%ds", PQgetlength(pgResult, i, j)];
|
|
|
|
tupleInfo = [NSS_SWF: fmt, PQgetvalue(pgResult, i, j)];
|
|
|
|
}
|
2005-02-19 12:13:22 +00:00
|
|
|
[tuple setObject: tupleInfo forKey: tupleKey];
|
2003-06-24 16:27:01 +00:00
|
|
|
}
|
2005-02-19 12:13:22 +00:00
|
|
|
[tuples addObject: tuple];
|
2003-06-24 16:27:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
statusType = PQresultStatus(pgResult);
|
|
|
|
|
|
|
|
return [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
[NSS_SWF:@"%d", statusType], @"PQresultStatus",
|
|
|
|
[NSS_SWF:@"%s", PQresStatus(statusType)], @"PQresStatus",
|
|
|
|
[NSS_SWF:@"%s", PQresultErrorMessage(pgResult)], @"PQresultErrorMessage",
|
|
|
|
[NSS_SWF:@"%d", ntuples], @"PQntuples",
|
|
|
|
[NSS_SWF:@"%d", nfields], @"PQnfields",
|
|
|
|
[NSS_SWF:@"%d", PQbinaryTuples(pgResult)], @"PQbinaryTuples",
|
|
|
|
[NSS_SWF:@"%s", PQcmdStatus(pgResult)], @"PQcmdStatus",
|
|
|
|
[NSS_SWF:@"%s", PQoidStatus(pgResult)], @"PQoidStatus",
|
|
|
|
[NSS_SWF:@"%d", PQoidValue(pgResult)], @"PQoidValue",
|
|
|
|
[NSS_SWF:@"%s", PQcmdTuples(pgResult)], @"PQcmdTuples",
|
|
|
|
tuples, @"tuples",
|
|
|
|
fields, @"fields",
|
|
|
|
nil];
|
|
|
|
}
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
@implementation PostgreSQLChannel
|
2002-11-15 22:57:05 +00:00
|
|
|
|
COmmit Part 2
* EOAccess/EOAdaptor.m:
o optimization in 'for' loops
* EOAccess/EODatabase.m:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAccess/EODatabaseContext.h:
o added _snapshotForGlobalIDIMP
* EOAccess/EODatabaseContext.m:
o commented NSEmitTODO in
-objectsForSourceGlobalID:relationshipName:editingContext:
o added beter exception format in
qualifierForLockingAttributes:primaryKeyAttributes:entity:snapshot:
o fix compiler warning in -relayPrimaryKey:object:entity:
o logs
o optimizations in -objectsWithFetchSpecification:editingContext:
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o use _snapshotForGlobalIDIMP
o IMP usage optimization
* EOAccess/EOAttribute.[hm]:
o added EOAdaptorUnknownType
o added _adaptorValueType and avoid recomputing it each time
o added _valueTypeChar to avoid string comparaisons
o use EOPriv classes declarations
o Temporary reverted David changes in
-adaptorValueByConvertingAttributeValue
* EOAccess/EOAttributePriv.h:
o added _valueTypeChar to avoid string comparaisons
* EOAccess/EOEntityPriv.h:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.h:
o moved private -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.m:
o better exception in classProperties
o fix compiler warning in -setClassProperties:,
-setPrimaryKeyAttributes:,
-setAttributesUsedForLocking:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLExpression.m:
o optimization in -tableListWithRootEntity:
o optimization in -formatSQLString:format:
o optimization in +sqlPatternFromShellPattern:
o optimization in +sqlPatternFromShellPattern:withEscapeCharacter:
o fix in -sqlStringForKeyValueQualifier:
o added log in -sqlStringForKeyValueQualifier: for not handled
readFormat
o added log -addInsertListAttribute:value: for not handled
writeFormat
o added log -addUpdateListAttribute:value: for not handled
writeFormat
o changed EOFLOGObjectFnStart to EOFLOGObjectFnStartCond
o changed EOFLOGObjectFnStop to EOFLOGObjectFnStopCond
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLQualifier.m:
o implemented EOKeyComparisonQualifier
-schemaBasedQualifierWithRootEntity
* EOAccess/EOUtilities.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOControl/EOPriv.[hm]:
o added. Contains various classes/selectors/IMPs
* EOControl/EOClassDescription.m:
o handle EONull case in -propagateDeleteForObject:editingContext:,
-addObject:toPropertyWithKey:, -snapshot,
-removeObject:fromPropertyWithKey:,
_setObject:forBothSidesOfRelationshipWithKey:,
addObject:toBothSidesOfRelationshipWithKey:,
-removeObject:fromBothSidesOfRelationshipWithKey:
o fix compiler warning in
-dictionaryForInstanceProperties, -shallowCopy,
-updateFromSnapshot:, -snapshot
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o replaced isNilOrEONull() by _isNilOrEONull()
o fix in -validateForSave
o rewritten -validateValue:forKey: selector build
* EOControl/EOEditingContext.h:
o added -hasUnprocessedChanges
* EOControl/EOEditingContext.m:
o added -hasUnprocessedChanges
o added NS_DURING,... to catch exceptions
o replace [EOFault isFault:] by _isFault()
o IMP usage optimization
* EOControl/EOKeyGlobalID.m:
o replaced isNilOrEONull() by _isNilOrEONull()
o include <EOCOntrol/EOPriv.h>
* EOControl/EOGenericRecord.m:
o partially rewritten -description
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o changed variable name type of
_infoForInstanceVariableNamed:retType:retSize:retOffset:
o rewritten valueForKey:,... to use cString NSKeyValueCoding
* EOControl/EOKeyValueCoding.m:
o changed NSAssert in NSArray -valueForKey:
o optimization in NSDictionary -takeValue:forKeyPath:isSmart:
o optimization in NSDictionary -takeStoredValue:forKeyPath:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOKeyValueQualifier.m:
o fixes for EONull/nil in -evaluateWithObject:
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOSortOrdering.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAdaptors/Postgres95SQLExpression.m:
o float formatting in +formatValue:forAttribute:
o added -externalNameQuoteCharacter
o added +sqlPatternFromShellPattern:
o added +sqlPatternFromShellPattern:withEscapeCharacter:
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAdaptors/Postgres95Channel.m:
o logs
* EOAdaptors/Postgres95Values.m:
o logs
o fix in +setPostgres95Format:
o fix calendard format to handle timezone (%z)
o optimizations
* EOControl/EOMutableKnownKeyDictionary.m
o removed EOMKKDArrayMapping
+dictionaryFromDictionary:subsetMapping:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOControl/EONSAddOns.[hm]:
o added NSString(ShellPattern)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@20688 72102866-910b-0410-8b05-ffd578937521
2005-02-11 17:37:23 +00:00
|
|
|
+ (void) initialize
|
|
|
|
{
|
|
|
|
static BOOL initialized=NO;
|
|
|
|
if (!initialized)
|
|
|
|
{
|
2005-02-13 13:04:19 +00:00
|
|
|
Class aClass=Nil;
|
2005-02-19 12:13:22 +00:00
|
|
|
PSQLA_PrivInit();
|
2005-02-13 13:04:19 +00:00
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
aClass=[PostgreSQLValues class]; // Force Initialize;
|
COmmit Part 2
* EOAccess/EOAdaptor.m:
o optimization in 'for' loops
* EOAccess/EODatabase.m:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAccess/EODatabaseContext.h:
o added _snapshotForGlobalIDIMP
* EOAccess/EODatabaseContext.m:
o commented NSEmitTODO in
-objectsForSourceGlobalID:relationshipName:editingContext:
o added beter exception format in
qualifierForLockingAttributes:primaryKeyAttributes:entity:snapshot:
o fix compiler warning in -relayPrimaryKey:object:entity:
o logs
o optimizations in -objectsWithFetchSpecification:editingContext:
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o use _snapshotForGlobalIDIMP
o IMP usage optimization
* EOAccess/EOAttribute.[hm]:
o added EOAdaptorUnknownType
o added _adaptorValueType and avoid recomputing it each time
o added _valueTypeChar to avoid string comparaisons
o use EOPriv classes declarations
o Temporary reverted David changes in
-adaptorValueByConvertingAttributeValue
* EOAccess/EOAttributePriv.h:
o added _valueTypeChar to avoid string comparaisons
* EOAccess/EOEntityPriv.h:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.h:
o moved private -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.m:
o better exception in classProperties
o fix compiler warning in -setClassProperties:,
-setPrimaryKeyAttributes:,
-setAttributesUsedForLocking:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLExpression.m:
o optimization in -tableListWithRootEntity:
o optimization in -formatSQLString:format:
o optimization in +sqlPatternFromShellPattern:
o optimization in +sqlPatternFromShellPattern:withEscapeCharacter:
o fix in -sqlStringForKeyValueQualifier:
o added log in -sqlStringForKeyValueQualifier: for not handled
readFormat
o added log -addInsertListAttribute:value: for not handled
writeFormat
o added log -addUpdateListAttribute:value: for not handled
writeFormat
o changed EOFLOGObjectFnStart to EOFLOGObjectFnStartCond
o changed EOFLOGObjectFnStop to EOFLOGObjectFnStopCond
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLQualifier.m:
o implemented EOKeyComparisonQualifier
-schemaBasedQualifierWithRootEntity
* EOAccess/EOUtilities.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOControl/EOPriv.[hm]:
o added. Contains various classes/selectors/IMPs
* EOControl/EOClassDescription.m:
o handle EONull case in -propagateDeleteForObject:editingContext:,
-addObject:toPropertyWithKey:, -snapshot,
-removeObject:fromPropertyWithKey:,
_setObject:forBothSidesOfRelationshipWithKey:,
addObject:toBothSidesOfRelationshipWithKey:,
-removeObject:fromBothSidesOfRelationshipWithKey:
o fix compiler warning in
-dictionaryForInstanceProperties, -shallowCopy,
-updateFromSnapshot:, -snapshot
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o replaced isNilOrEONull() by _isNilOrEONull()
o fix in -validateForSave
o rewritten -validateValue:forKey: selector build
* EOControl/EOEditingContext.h:
o added -hasUnprocessedChanges
* EOControl/EOEditingContext.m:
o added -hasUnprocessedChanges
o added NS_DURING,... to catch exceptions
o replace [EOFault isFault:] by _isFault()
o IMP usage optimization
* EOControl/EOKeyGlobalID.m:
o replaced isNilOrEONull() by _isNilOrEONull()
o include <EOCOntrol/EOPriv.h>
* EOControl/EOGenericRecord.m:
o partially rewritten -description
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o changed variable name type of
_infoForInstanceVariableNamed:retType:retSize:retOffset:
o rewritten valueForKey:,... to use cString NSKeyValueCoding
* EOControl/EOKeyValueCoding.m:
o changed NSAssert in NSArray -valueForKey:
o optimization in NSDictionary -takeValue:forKeyPath:isSmart:
o optimization in NSDictionary -takeStoredValue:forKeyPath:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOKeyValueQualifier.m:
o fixes for EONull/nil in -evaluateWithObject:
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOSortOrdering.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAdaptors/Postgres95SQLExpression.m:
o float formatting in +formatValue:forAttribute:
o added -externalNameQuoteCharacter
o added +sqlPatternFromShellPattern:
o added +sqlPatternFromShellPattern:withEscapeCharacter:
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAdaptors/Postgres95Channel.m:
o logs
* EOAdaptors/Postgres95Values.m:
o logs
o fix in +setPostgres95Format:
o fix calendard format to handle timezone (%z)
o optimizations
* EOControl/EOMutableKnownKeyDictionary.m
o removed EOMKKDArrayMapping
+dictionaryFromDictionary:subsetMapping:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOControl/EONSAddOns.[hm]:
o added NSString(ShellPattern)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@20688 72102866-910b-0410-8b05-ffd578937521
2005-02-11 17:37:23 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2004-05-15 21:46:38 +00:00
|
|
|
/* Set DateStyle to use ISO format. */
|
|
|
|
- (void)_setDateStyle
|
|
|
|
{
|
|
|
|
_pgResult = PQexec(_pgConn,
|
|
|
|
"SET DATESTYLE TO ISO");
|
|
|
|
|
|
|
|
if (_pgResult == NULL || PQresultStatus(_pgResult) != PGRES_COMMAND_OK)
|
|
|
|
{
|
|
|
|
_pgResult = NULL;
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2004-05-15 21:46:38 +00:00
|
|
|
format: @"cannot set date style to ISO."];
|
|
|
|
}
|
|
|
|
|
|
|
|
PQclear(_pgResult);
|
|
|
|
_pgResult = NULL;
|
|
|
|
}
|
|
|
|
|
2002-11-15 22:57:05 +00:00
|
|
|
- (id) initWithAdaptorContext: (EOAdaptorContext *)adaptorContext
|
|
|
|
{
|
|
|
|
if ((self = [super initWithAdaptorContext: adaptorContext]))
|
|
|
|
{
|
|
|
|
EOAttribute *attr = nil;
|
|
|
|
|
|
|
|
ASSIGN(_adaptorContext, adaptorContext);//TODO NO
|
|
|
|
|
|
|
|
//verify
|
|
|
|
_oidToTypeName = [[NSMutableDictionary alloc] initWithCapacity: 101];
|
|
|
|
|
2003-02-03 14:53:03 +00:00
|
|
|
attr = [[EOAttribute alloc] init];
|
2002-11-15 22:57:05 +00:00
|
|
|
[attr setName: @"nextval"];
|
|
|
|
[attr setColumnName: @"nextval"];
|
|
|
|
[attr setValueType: @"i"];
|
|
|
|
[attr setValueClassName: @"NSNumber"];
|
|
|
|
|
|
|
|
ASSIGN(_pkAttributeArray, [NSArray arrayWithObject: attr]);
|
2003-02-03 14:53:03 +00:00
|
|
|
RELEASE(attr);
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc
|
|
|
|
{
|
|
|
|
if ([self isOpen])
|
|
|
|
[self closeChannel];
|
|
|
|
|
|
|
|
DESTROY(_adaptorContext);
|
|
|
|
DESTROY(_sqlExpression);
|
|
|
|
DESTROY(_oidToTypeName);
|
|
|
|
DESTROY(_pkAttributeArray);
|
|
|
|
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)isOpen
|
|
|
|
{
|
|
|
|
return (_pgConn ? YES : NO);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)openChannel
|
|
|
|
{
|
|
|
|
//OK
|
|
|
|
NSAssert(!_pgConn, @"Channel already opened");
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
_pgConn = [(PostgreSQLAdaptor *)[[self adaptorContext] adaptor] newPGconn];
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
if (_pgConn)
|
2003-06-24 16:27:01 +00:00
|
|
|
{
|
2004-05-15 21:46:38 +00:00
|
|
|
[self _setDateStyle];
|
2003-06-24 16:27:01 +00:00
|
|
|
[self _readServerVersion];
|
|
|
|
[self _describeDatabaseTypes];
|
|
|
|
}
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)closeChannel
|
|
|
|
{
|
|
|
|
NSAssert(_pgConn, @"Channel not opened");
|
|
|
|
|
|
|
|
[self _cancelResults];
|
2006-09-15 13:01:07 +00:00
|
|
|
[(PostgreSQLAdaptor *)[[self adaptorContext] adaptor] releasePGconn: _pgConn
|
2002-11-15 22:57:05 +00:00
|
|
|
force: NO];
|
|
|
|
_pgConn = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)isFetchInProgress
|
|
|
|
{
|
|
|
|
return _isFetchInProgress;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (PGconn *)pgConn
|
|
|
|
{
|
|
|
|
return _pgConn;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (PGresult *)pgResult
|
|
|
|
{
|
|
|
|
return _pgResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)cancelFetch
|
|
|
|
{
|
|
|
|
EOAdaptorContext *adaptorContext = nil;
|
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
adaptorContext = [self adaptorContext];
|
|
|
|
[self cleanupFetch];
|
|
|
|
|
|
|
|
//NO ?? [self _cancelResults];//Done in cleanup fetch
|
|
|
|
// [_adaptorContext autoCommitTransaction];//Done in cleanup fetch
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)_cancelResults
|
|
|
|
{
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
_fetchBlobsOid = NO;
|
|
|
|
|
|
|
|
DESTROY(_attributes);
|
|
|
|
DESTROY(_origAttributes);
|
|
|
|
|
|
|
|
if (_pgResult)
|
|
|
|
{
|
|
|
|
PQclear(_pgResult);
|
|
|
|
_pgResult = NULL;
|
|
|
|
_currentResultRow = -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
_isFetchInProgress = NO;
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)advanceRow
|
|
|
|
{
|
|
|
|
BOOL advanceRow = NO;
|
|
|
|
|
|
|
|
// fetch results where read then freed
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
if (_pgResult)
|
|
|
|
{
|
|
|
|
// next row
|
|
|
|
_currentResultRow++;
|
|
|
|
|
|
|
|
// check if result set is finished
|
|
|
|
if (_currentResultRow >= PQntuples(_pgResult))
|
|
|
|
{
|
|
|
|
[self _cancelResults];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
advanceRow = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
|
|
|
|
return advanceRow;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray*)lowLevelResultFieldNames: (PGresult*)res
|
|
|
|
{
|
|
|
|
int nb = PQnfields(res);
|
2005-02-19 12:13:22 +00:00
|
|
|
NSMutableArray *names
|
|
|
|
= AUTORELEASE([PSQLA_alloc(NSMutableArray) initWithCapacity: nb]);
|
2002-11-15 22:57:05 +00:00
|
|
|
int i;
|
2005-02-13 13:04:19 +00:00
|
|
|
IMP namesAO=NULL; //addObject:
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
for (i = 0; i < nb; i++)
|
|
|
|
{
|
|
|
|
char *szName = PQfname(res,i);
|
2005-02-19 12:13:22 +00:00
|
|
|
unsigned length = szName ? strlen(szName) : 0;
|
|
|
|
NSString *name = [(PSQLA_alloc(NSString)) initWithCString: szName
|
|
|
|
length: length];
|
|
|
|
PSQLA_AddObjectWithImpPtr(names,&namesAO,name);
|
|
|
|
RELEASE(name);
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return names;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSMutableDictionary *)fetchRowWithZone: (NSZone *)zone
|
|
|
|
{
|
|
|
|
//TODO
|
|
|
|
/*
|
|
|
|
//self cleanupFetch quand plus de row !!
|
|
|
|
valueClassName...externaltype on each attr
|
|
|
|
self adaptorContext
|
|
|
|
context adaptor
|
|
|
|
adaptor databaseEncoding//2
|
|
|
|
|
|
|
|
|
|
|
|
self dictionaryWithObjects:???
|
|
|
|
forAttributes:_attributes
|
|
|
|
zone:zone
|
|
|
|
//end
|
|
|
|
*/
|
|
|
|
NSMutableDictionary *dict = nil;
|
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
if (_delegateRespondsTo.willFetchRow)
|
|
|
|
[_delegate adaptorChannelWillFetchRow: self];
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb",@"[self isFetchInProgress]: %s",
|
|
|
|
([self isFetchInProgress] ? "YES" : "NO"));
|
|
|
|
|
|
|
|
if ([self isFetchInProgress])
|
|
|
|
{
|
|
|
|
NSDebugMLLog(@"gsdb", @"ATTRIBUTES=%@", _attributes);
|
|
|
|
|
|
|
|
if (!_attributes)
|
|
|
|
[self _describeResults];
|
|
|
|
|
|
|
|
if ([self advanceRow] == NO)
|
|
|
|
{
|
2003-02-03 14:53:03 +00:00
|
|
|
NSDebugMLLog(@"gsdb", @"No Advance Row", "");
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
// Return nil to indicate that the fetch operation was finished
|
|
|
|
if (_delegateRespondsTo.didFinishFetching)
|
|
|
|
[_delegate adaptorChannelDidFinishFetching: self];
|
|
|
|
|
|
|
|
[self _cancelResults];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int count = [_attributes count];
|
|
|
|
id valueBuffer[100];
|
|
|
|
id *values = NULL;
|
2005-02-13 13:04:19 +00:00
|
|
|
IMP attributesOAI=NULL; // objectAtIndex:
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"count=%d", count);
|
|
|
|
|
|
|
|
if (count > PQnfields(_pgResult))
|
|
|
|
{
|
|
|
|
NSDebugMLog(@"attempt to read %d attributes when the result set has only %d columns",
|
|
|
|
count, PQnfields(_pgResult));
|
|
|
|
NSDebugMLog(@"_attributes=%@", _attributes);
|
|
|
|
NSDebugMLog(@"result=%@", [self lowLevelResultFieldNames:
|
|
|
|
_pgResult]);
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"attempt to read %d attributes "
|
|
|
|
@"when the result set has only %d columns",
|
|
|
|
count, PQnfields(_pgResult)];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count > 100)
|
|
|
|
values = (id *)NSZoneMalloc(zone, count * sizeof(id));
|
|
|
|
else
|
|
|
|
values = valueBuffer;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
EOAttribute *attr = PSQLA_ObjectAtIndexWithImpPtr(_attributes,&attributesOAI,i);
|
2002-11-15 22:57:05 +00:00
|
|
|
int length = 0;
|
|
|
|
const char *string = NULL;
|
|
|
|
|
|
|
|
// If the column has the NULL value insert EONull in row
|
|
|
|
|
|
|
|
if (PQgetisnull(_pgResult, _currentResultRow, i))
|
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
values[i] = RETAIN(PSQLA_EONull); //to be compatible with others returned values
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
string = PQgetvalue(_pgResult, _currentResultRow, i);
|
|
|
|
length = PQgetlength(_pgResult, _currentResultRow, i);
|
|
|
|
|
|
|
|
// if external type for this attribute is "inversion" then this
|
|
|
|
// column represents an Oid of a large object
|
|
|
|
|
|
|
|
if ([[attr externalType] isEqual: @"inversion"])
|
|
|
|
{
|
|
|
|
if (!_fetchBlobsOid)
|
|
|
|
{
|
|
|
|
string = [self _readBinaryDataRow: (Oid)atol(string)
|
|
|
|
length:&length zone: zone];
|
|
|
|
//For efficiency reasons, the returned value is NOT autoreleased !
|
2006-09-15 13:01:07 +00:00
|
|
|
values[i] = PSQLA_PostgreSQLValues_newValueForBytesLengthAttribute(string,length,attr);
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
// The documentatin states that for efficiency
|
|
|
|
// reasons, the returned value is NOT autoreleased
|
|
|
|
// yet in the case of GNUstep-base it would be more
|
|
|
|
// efficient if the numberWithLong: method would be
|
|
|
|
// used as we could often skip alloc / dealloc
|
|
|
|
// and get a cached value. We could use it and
|
|
|
|
// send retain, or we could start maintaing our
|
|
|
|
// own cache.
|
|
|
|
values[i] = [PSQLA_alloc(NSNumber) initWithLong: atol(string)];
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//For efficiency reasons, the returned value is NOT autoreleased !
|
2006-09-15 13:01:07 +00:00
|
|
|
values[i] = PSQLA_PostgreSQLValues_newValueForBytesLengthAttribute(string,length,attr);
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
COmmit Part 2
* EOAccess/EOAdaptor.m:
o optimization in 'for' loops
* EOAccess/EODatabase.m:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAccess/EODatabaseContext.h:
o added _snapshotForGlobalIDIMP
* EOAccess/EODatabaseContext.m:
o commented NSEmitTODO in
-objectsForSourceGlobalID:relationshipName:editingContext:
o added beter exception format in
qualifierForLockingAttributes:primaryKeyAttributes:entity:snapshot:
o fix compiler warning in -relayPrimaryKey:object:entity:
o logs
o optimizations in -objectsWithFetchSpecification:editingContext:
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o use _snapshotForGlobalIDIMP
o IMP usage optimization
* EOAccess/EOAttribute.[hm]:
o added EOAdaptorUnknownType
o added _adaptorValueType and avoid recomputing it each time
o added _valueTypeChar to avoid string comparaisons
o use EOPriv classes declarations
o Temporary reverted David changes in
-adaptorValueByConvertingAttributeValue
* EOAccess/EOAttributePriv.h:
o added _valueTypeChar to avoid string comparaisons
* EOAccess/EOEntityPriv.h:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.h:
o moved private -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.m:
o better exception in classProperties
o fix compiler warning in -setClassProperties:,
-setPrimaryKeyAttributes:,
-setAttributesUsedForLocking:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLExpression.m:
o optimization in -tableListWithRootEntity:
o optimization in -formatSQLString:format:
o optimization in +sqlPatternFromShellPattern:
o optimization in +sqlPatternFromShellPattern:withEscapeCharacter:
o fix in -sqlStringForKeyValueQualifier:
o added log in -sqlStringForKeyValueQualifier: for not handled
readFormat
o added log -addInsertListAttribute:value: for not handled
writeFormat
o added log -addUpdateListAttribute:value: for not handled
writeFormat
o changed EOFLOGObjectFnStart to EOFLOGObjectFnStartCond
o changed EOFLOGObjectFnStop to EOFLOGObjectFnStopCond
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLQualifier.m:
o implemented EOKeyComparisonQualifier
-schemaBasedQualifierWithRootEntity
* EOAccess/EOUtilities.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOControl/EOPriv.[hm]:
o added. Contains various classes/selectors/IMPs
* EOControl/EOClassDescription.m:
o handle EONull case in -propagateDeleteForObject:editingContext:,
-addObject:toPropertyWithKey:, -snapshot,
-removeObject:fromPropertyWithKey:,
_setObject:forBothSidesOfRelationshipWithKey:,
addObject:toBothSidesOfRelationshipWithKey:,
-removeObject:fromBothSidesOfRelationshipWithKey:
o fix compiler warning in
-dictionaryForInstanceProperties, -shallowCopy,
-updateFromSnapshot:, -snapshot
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o replaced isNilOrEONull() by _isNilOrEONull()
o fix in -validateForSave
o rewritten -validateValue:forKey: selector build
* EOControl/EOEditingContext.h:
o added -hasUnprocessedChanges
* EOControl/EOEditingContext.m:
o added -hasUnprocessedChanges
o added NS_DURING,... to catch exceptions
o replace [EOFault isFault:] by _isFault()
o IMP usage optimization
* EOControl/EOKeyGlobalID.m:
o replaced isNilOrEONull() by _isNilOrEONull()
o include <EOCOntrol/EOPriv.h>
* EOControl/EOGenericRecord.m:
o partially rewritten -description
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o changed variable name type of
_infoForInstanceVariableNamed:retType:retSize:retOffset:
o rewritten valueForKey:,... to use cString NSKeyValueCoding
* EOControl/EOKeyValueCoding.m:
o changed NSAssert in NSArray -valueForKey:
o optimization in NSDictionary -takeValue:forKeyPath:isSmart:
o optimization in NSDictionary -takeStoredValue:forKeyPath:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOKeyValueQualifier.m:
o fixes for EONull/nil in -evaluateWithObject:
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOSortOrdering.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAdaptors/Postgres95SQLExpression.m:
o float formatting in +formatValue:forAttribute:
o added -externalNameQuoteCharacter
o added +sqlPatternFromShellPattern:
o added +sqlPatternFromShellPattern:withEscapeCharacter:
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAdaptors/Postgres95Channel.m:
o logs
* EOAdaptors/Postgres95Values.m:
o logs
o fix in +setPostgres95Format:
o fix calendard format to handle timezone (%z)
o optimizations
* EOControl/EOMutableKnownKeyDictionary.m
o removed EOMKKDArrayMapping
+dictionaryFromDictionary:subsetMapping:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOControl/EONSAddOns.[hm]:
o added NSString(ShellPattern)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@20688 72102866-910b-0410-8b05-ffd578937521
2005-02-11 17:37:23 +00:00
|
|
|
NSDebugMLLog(@"gsdb", @"value[%d] (%p)=%@ of class: %@",
|
|
|
|
i, values[i], values[i], [values[i] class]);
|
|
|
|
|
|
|
|
// We don't want to add nil value to dictionary !
|
|
|
|
NSAssert1(values[i],@"No value for attribute: %@",attr);
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"values count=%d values=%p", count, values);
|
|
|
|
NSDebugMLLog(@"gsdb", @"_attributes=%@", _attributes);
|
|
|
|
|
|
|
|
dict = [self dictionaryWithObjects: values
|
|
|
|
forAttributes: _attributes
|
|
|
|
zone: zone];
|
|
|
|
|
|
|
|
/* NO: For efficiency reasons, the returned value is NOT autoreleased !
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
[values[i] release];
|
|
|
|
*/
|
|
|
|
if (values != valueBuffer)
|
|
|
|
NSZoneFree(zone, values);
|
|
|
|
|
|
|
|
if (_delegateRespondsTo.didFetchRow)
|
|
|
|
[_delegate adaptorChannel: self didFetchRow: dict];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"row: %@", dict);
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
|
|
|
|
return dict; //an EOMutableKnownKeyDictionary
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)_evaluateCommandsUntilAFetch
|
|
|
|
{
|
|
|
|
BOOL ret = NO;
|
|
|
|
ExecStatusType status;
|
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
// Check results
|
|
|
|
status = PQresultStatus(_pgResult);
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb",@"status=%d (%s)",
|
|
|
|
(int)status,
|
|
|
|
PQresStatus(status));
|
|
|
|
|
|
|
|
switch (status)
|
|
|
|
{
|
|
|
|
case PGRES_EMPTY_QUERY:
|
|
|
|
_isFetchInProgress = NO;
|
|
|
|
ret = YES;
|
|
|
|
break;
|
|
|
|
case PGRES_COMMAND_OK:
|
|
|
|
_isFetchInProgress = NO;
|
|
|
|
ret = YES;
|
|
|
|
break;
|
|
|
|
case PGRES_TUPLES_OK:
|
|
|
|
_isFetchInProgress = YES;
|
|
|
|
_currentResultRow = -1;
|
|
|
|
ret = YES;
|
|
|
|
break;
|
|
|
|
case PGRES_COPY_OUT:
|
|
|
|
_isFetchInProgress = NO;
|
|
|
|
ret = YES;
|
|
|
|
break;
|
|
|
|
case PGRES_COPY_IN:
|
|
|
|
_isFetchInProgress = NO;
|
|
|
|
ret = YES;
|
|
|
|
break;
|
|
|
|
case PGRES_BAD_RESPONSE:
|
|
|
|
case PGRES_NONFATAL_ERROR:
|
|
|
|
case PGRES_FATAL_ERROR:
|
|
|
|
{
|
2003-06-26 08:20:30 +00:00
|
|
|
NSString* errorString=[NSString stringWithCString:PQerrorMessage(_pgConn)];
|
2002-11-15 22:57:05 +00:00
|
|
|
if ([self isDebugEnabled])
|
2003-06-26 08:20:30 +00:00
|
|
|
NSLog(@"SQL expression '%@' caused %@",
|
|
|
|
[_sqlExpression statement], errorString);
|
|
|
|
NSDebugMLLog(@"SQL expression '%@' caused %@",
|
|
|
|
[_sqlExpression statement], errorString);
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2003-06-26 08:20:30 +00:00
|
|
|
format: @"unexpected result returned by PQresultStatus(): %@",errorString];
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
2003-06-26 08:20:30 +00:00
|
|
|
NSString* errorString=[NSString stringWithCString:PQerrorMessage(_pgConn)];
|
|
|
|
if ([self isDebugEnabled])
|
|
|
|
NSLog(@"SQL expression '%@' returned status %d: %@",
|
|
|
|
[_sqlExpression statement], status, errorString);
|
|
|
|
NSDebugMLLog(@"SQL expression '%@' returned status %d: %@",
|
|
|
|
[_sqlExpression statement], status, errorString);
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2003-06-26 08:20:30 +00:00
|
|
|
format: @"unexpected result returned by PQresultStatus(): status %d: %@",
|
|
|
|
status,errorString];
|
|
|
|
|
2002-11-15 22:57:05 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"ret=%s", (ret ? "YES" : "NO"));
|
|
|
|
NSDebugMLLog(@"gsdb", @"_isFetchInProgress=%s", (_isFetchInProgress ? "YES" : "NO"));
|
|
|
|
|
|
|
|
if (ret == YES)
|
|
|
|
{
|
|
|
|
PGnotify *notify = PQnotifies(_pgConn);
|
|
|
|
const char *insoid = NULL;
|
|
|
|
|
|
|
|
if (notify)
|
|
|
|
{
|
2006-09-15 12:05:56 +00:00
|
|
|
if (_postgresDelegateRespondsTo.postgresNotification)
|
|
|
|
[_delegate postgresChannel: self
|
2002-11-15 22:57:05 +00:00
|
|
|
receivedNotification:
|
|
|
|
[NSString stringWithCString: notify->relname]];
|
|
|
|
|
|
|
|
free(notify);
|
|
|
|
}
|
|
|
|
|
|
|
|
insoid = PQoidStatus(_pgResult);
|
|
|
|
|
2006-09-15 12:05:56 +00:00
|
|
|
if (*insoid && _postgresDelegateRespondsTo.postgresInsertedRowOid)
|
2002-11-15 22:57:05 +00:00
|
|
|
{
|
|
|
|
Oid oid = atol(insoid);
|
|
|
|
|
2006-09-15 12:05:56 +00:00
|
|
|
[_delegate postgresChannel: self insertedRowWithOid: oid];
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb",@"_isFetchInProgress=%s",
|
|
|
|
(_isFetchInProgress ? "YES" : "NO"));
|
|
|
|
|
|
|
|
if ([self isFetchInProgress])// Mirko: TODO remove this !
|
|
|
|
[self _describeResults];
|
|
|
|
|
|
|
|
if ([self isDebugEnabled])
|
|
|
|
{
|
|
|
|
NSString *message = [NSString stringWithCString: PQcmdStatus(_pgResult)];
|
|
|
|
|
|
|
|
if (status == PGRES_TUPLES_OK)
|
|
|
|
message = [NSString stringWithFormat:
|
|
|
|
@"Command status %@. Returned %d rows with %d columns ",
|
|
|
|
message, PQntuples(_pgResult), PQnfields(_pgResult)];
|
2006-09-15 13:01:07 +00:00
|
|
|
NSLog (@"PostgreSQLAdaptor: %@", message);
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"ret=%s", (ret ? "YES" : "NO"));
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)_evaluateExpression: (EOSQLExpression *)expression
|
|
|
|
withAttributes: (NSArray*)attributes
|
|
|
|
{
|
|
|
|
BOOL result = NO;
|
|
|
|
EOAdaptorContext *adaptorContext = nil;
|
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"expression=%@", expression);
|
|
|
|
|
|
|
|
ASSIGN(_sqlExpression, expression);
|
|
|
|
ASSIGN(_origAttributes, attributes);
|
|
|
|
|
|
|
|
// NSDebugMLLog(@"gsdb",@"EE _origAttributes=%@",_origAttributes);
|
|
|
|
// NSDebugMLLog(@"gsdb",@"EE _attributes=%@",_attributes);
|
2006-09-15 13:01:07 +00:00
|
|
|
NSDebugMLLog(@"gsdb", @"PostgreSQLAdaptor: execute command:\n%@\n",
|
2002-11-15 22:57:05 +00:00
|
|
|
[expression statement]);
|
|
|
|
|
|
|
|
if ([self isDebugEnabled] == YES)
|
2006-09-15 13:01:07 +00:00
|
|
|
NSLog(@"PostgreSQLAdaptor: execute command:\n%@\n",
|
2002-11-15 22:57:05 +00:00
|
|
|
[expression statement]);
|
|
|
|
//call PostgreSQLChannel numberOfAffectedRows
|
|
|
|
/* Send the expression to the SQL server */
|
|
|
|
|
2003-02-03 14:53:03 +00:00
|
|
|
_pgResult = PQexec(_pgConn, (char *)[[[expression statement] stringByAppendingString:@";"] cString]); // stephane@sente.ch: We need to add ; for INSERT, at least
|
2002-11-15 22:57:05 +00:00
|
|
|
NSDebugMLLog(@"gsdb", @"_pgResult=%p", (void*)_pgResult);
|
|
|
|
|
|
|
|
if (_pgResult == NULL)
|
|
|
|
{
|
|
|
|
if ([self isDebugEnabled])
|
|
|
|
{
|
|
|
|
adaptorContext = [self adaptorContext];
|
2006-09-15 13:01:07 +00:00
|
|
|
[(PostgreSQLAdaptor *)[adaptorContext adaptor]
|
2002-11-15 22:57:05 +00:00
|
|
|
privateReportError: _pgConn];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Check command results */
|
|
|
|
if ([self _evaluateCommandsUntilAFetch] != NO)
|
|
|
|
result = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
//self numberOfAffectedRows
|
|
|
|
NSDebugMLLog(@"gsdb", @"result: %s", (result ? "YES" : "NO"));
|
|
|
|
// NSDebugMLLog(@"gsdb",@"FF attributes=%@",_attributes);
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)evaluateExpression: (EOSQLExpression *)expression // OK quasi
|
|
|
|
{
|
2006-09-15 13:01:07 +00:00
|
|
|
PostgreSQLContext *adaptorContext = nil;
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
//_evaluationIsDirectCalled=1
|
2006-09-15 13:01:07 +00:00
|
|
|
adaptorContext = (PostgreSQLContext *)[self adaptorContext];
|
2002-11-15 22:57:05 +00:00
|
|
|
//call expression statement
|
|
|
|
//call adaptorContext adaptor
|
|
|
|
//call adaptor databaseEncoding
|
|
|
|
//call self setErrorMessage
|
|
|
|
//call expre statement
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"expression=%@", expression);
|
|
|
|
|
|
|
|
if (_delegateRespondsTo.shouldEvaluateExpression)
|
|
|
|
{
|
|
|
|
BOOL response
|
|
|
|
= [_delegate adaptorChannel: self
|
|
|
|
shouldEvaluateExpression: expression];
|
|
|
|
|
|
|
|
if (response == NO)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([self isOpen] == NO)
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"cannot execute SQL expression. Channel is not opened."];
|
|
|
|
|
|
|
|
[self _cancelResults];
|
|
|
|
[adaptorContext autoBeginTransaction: NO/*YES*/]; //TODO: shouldbe yes ??
|
|
|
|
|
|
|
|
if (![self _evaluateExpression: expression
|
|
|
|
withAttributes: nil])
|
|
|
|
{
|
2003-02-03 14:53:03 +00:00
|
|
|
NSDebugMLLog(@"gsdb", @"_evaluateExpression:withAttributes: return NO", "");
|
2002-11-15 22:57:05 +00:00
|
|
|
[self _cancelResults];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSDebugMLLog(@"gsdb", @"expression=%@ [self isFetchInProgress]=%d",
|
|
|
|
expression,
|
|
|
|
[self isFetchInProgress]);
|
|
|
|
if (![self isFetchInProgress])//If a fetch is in progress, we don't want to commit because
|
|
|
|
//it will cancel fetch. I'm not sure it the 'good' way to do
|
|
|
|
[adaptorContext autoCommitTransaction];
|
|
|
|
|
|
|
|
if (_delegateRespondsTo.didEvaluateExpression)
|
|
|
|
[_delegate adaptorChannel: self didEvaluateExpression: expression];
|
|
|
|
}
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)insertRow: (NSDictionary *)row
|
|
|
|
forEntity: (EOEntity *)entity
|
|
|
|
{
|
|
|
|
EOSQLExpression *sqlexpr = nil;
|
|
|
|
NSMutableDictionary *nrow = nil;
|
|
|
|
NSEnumerator *enumerator = nil;
|
|
|
|
NSString *attrName = nil;
|
2006-09-15 13:01:07 +00:00
|
|
|
PostgreSQLContext *adaptorContext = nil;
|
2005-02-13 13:04:19 +00:00
|
|
|
IMP attrEnumNO=NULL; // nextObject
|
|
|
|
IMP rowOFK=NULL; // objectForKey:
|
|
|
|
IMP nrowSOFK=NULL; // setObject:forKey:
|
|
|
|
IMP nrowOFK=NULL; // objectForKey:
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"row=%@", row);
|
|
|
|
|
|
|
|
if (![self isOpen])
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"%@ -- %@ 0x%x: attempt to insert rows with no open channel",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self];
|
|
|
|
|
|
|
|
if (!row || !entity)
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"row and entity arguments for insertRow:forEntity:"
|
|
|
|
@" must not be nil objects"];
|
|
|
|
|
|
|
|
if ([self isFetchInProgress])
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"%@ -- %@ 0x%x: attempt to insert rows with fetch in progress",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self];
|
|
|
|
|
|
|
|
/* Before creating the SQL INSERT expression we have to replace in the
|
|
|
|
row the large objects as Oids and to insert them with the large
|
|
|
|
object file-like interface */
|
|
|
|
|
2003-02-03 14:53:03 +00:00
|
|
|
nrow = AUTORELEASE([row mutableCopy]);
|
2002-11-15 22:57:05 +00:00
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
adaptorContext = (PostgreSQLContext *)[self adaptorContext];
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
[self _cancelResults]; //No done by WO
|
|
|
|
|
2003-02-03 14:53:03 +00:00
|
|
|
NSDebugMLLog(@"gsdb", @"autoBeginTransaction", "");
|
2002-11-15 22:57:05 +00:00
|
|
|
[adaptorContext autoBeginTransaction: YES];
|
|
|
|
/*:
|
|
|
|
row allKeys
|
|
|
|
allkey sortedArrayUsingSelector:compare:
|
|
|
|
each key
|
|
|
|
*/
|
|
|
|
|
|
|
|
enumerator = [row keyEnumerator];
|
2005-02-19 12:13:22 +00:00
|
|
|
while ((attrName = PSQLA_NextObjectWithImpPtr(enumerator,&attrEnumNO)))
|
2002-11-15 22:57:05 +00:00
|
|
|
{
|
|
|
|
EOAttribute *attribute = nil;
|
|
|
|
NSString *externalType = nil;
|
|
|
|
id value = nil;
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"attrName=%@", attrName);
|
|
|
|
|
|
|
|
attribute=[entity attributeNamed: attrName];
|
|
|
|
NSDebugMLLog(@"gsdb", @"attribute=%@", attribute);
|
|
|
|
|
|
|
|
if (!attribute)
|
|
|
|
return; //???????????
|
|
|
|
|
2005-02-19 12:13:22 +00:00
|
|
|
value = PSQLA_ObjectForKeyWithImpPtr(row,&rowOFK,attrName);
|
2002-11-15 22:57:05 +00:00
|
|
|
NSDebugMLLog(@"gsdb", @"value=%@", value);
|
|
|
|
|
|
|
|
externalType = [attribute externalType];
|
|
|
|
NSDebugMLLog(@"gsdb", @"externalType=%@", externalType);
|
|
|
|
|
|
|
|
/* Insert the binary value into the binaryDataRow dictionary */
|
|
|
|
if ([externalType isEqual: @"inversion"])
|
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
id binValue = PSQLA_ObjectForKeyWithImpPtr(nrow,&nrowOFK,attrName);
|
2002-11-15 22:57:05 +00:00
|
|
|
Oid binOid = [self _insertBinaryData: binValue
|
|
|
|
forAttribute: attribute];
|
|
|
|
value = [NSNumber numberWithLong: binOid];
|
|
|
|
}
|
|
|
|
else if ([externalType isEqual: @"NSString"]) //??
|
|
|
|
{
|
|
|
|
//TODO: database encoding
|
|
|
|
// [[adaptorContext adaptor] databaseEncoding]
|
|
|
|
}
|
|
|
|
|
2005-02-19 12:13:22 +00:00
|
|
|
PSQLA_SetObjectForKeyWithImpPtr(nrow,&nrowSOFK,value,attrName);
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"nrow=%@", nrow);
|
|
|
|
|
|
|
|
if ([nrow count] > 0)
|
|
|
|
{
|
|
|
|
sqlexpr = [[[_adaptorContext adaptor] expressionClass]
|
|
|
|
insertStatementForRow: nrow
|
|
|
|
entity: entity];
|
|
|
|
NSDebugMLLog(@"gsdb", @"sqlexpr=%@", sqlexpr);
|
|
|
|
|
|
|
|
if ([self _evaluateExpression: sqlexpr withAttributes: nil] == NO) //call evaluateExpression:
|
|
|
|
[NSException raise: EOGeneralAdaptorException
|
|
|
|
format: @"%@ -- %@ 0x%x: cannot insert row for entity '%@'",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self,
|
|
|
|
[entity name]];
|
|
|
|
}
|
|
|
|
|
|
|
|
[_adaptorContext autoCommitTransaction];
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (unsigned)deleteRowsDescribedByQualifier: (EOQualifier *)qualifier
|
|
|
|
entity: (EOEntity *)entity
|
|
|
|
{
|
|
|
|
EOSQLExpression *sqlexpr = nil;
|
|
|
|
unsigned long rows = 0;
|
2006-09-15 13:01:07 +00:00
|
|
|
PostgreSQLContext *adaptorContext;
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
if (![self isOpen])
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"%@ -- %@ 0x%x: attempt to delete rows with no open channel",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self];
|
|
|
|
|
|
|
|
if (!qualifier || !entity)
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"%@ -- %@ 0x%x: qualifier and entity arguments "
|
|
|
|
@" must not be nil objects",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self];
|
|
|
|
|
|
|
|
if ([self isFetchInProgress])
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"%@ -- %@ 0x%x: attempt to delete rows with fetch in progress",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self];
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
adaptorContext = (PostgreSQLContext *)[self adaptorContext];
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
[self _cancelResults];
|
|
|
|
[_adaptorContext autoBeginTransaction: NO];
|
|
|
|
|
|
|
|
sqlexpr = [[[_adaptorContext adaptor] expressionClass]
|
|
|
|
deleteStatementWithQualifier: qualifier
|
|
|
|
entity: entity];
|
|
|
|
|
|
|
|
if ([self _evaluateExpression: sqlexpr withAttributes: nil])
|
|
|
|
rows = strtoul(PQcmdTuples(_pgResult), NULL, 10);
|
|
|
|
|
|
|
|
[adaptorContext autoCommitTransaction];
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
return rows;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)selectAttributes: (NSArray *)attributes
|
|
|
|
fetchSpecification: (EOFetchSpecification *)fetchSpecification
|
|
|
|
lock: (BOOL)flag
|
|
|
|
entity: (EOEntity *)entity
|
|
|
|
{
|
|
|
|
EOSQLExpression *sqlExpr = nil;
|
|
|
|
|
|
|
|
//objectForKey:EOAdaptorQuotesExternalNames ret: nil
|
|
|
|
//lastObject ret NSRegistrationDomain
|
|
|
|
//objectForKey:NSRegistrationDomain ret dict
|
|
|
|
//objectForKey:EOAdaptorQuotesExternalNames
|
|
|
|
//attr count
|
|
|
|
//PostgreSQLExpression initWithEntity:
|
|
|
|
//setUseliases:YES
|
|
|
|
//prepareSelectExpressionWithAttributes:lock:fetchSpecification:
|
|
|
|
//statement
|
|
|
|
//adaptorContext
|
|
|
|
//a con autoBeginTransaction
|
|
|
|
//end
|
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb",@"%@ -- %@ 0x%x: isFetchInProgress=%s",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self,
|
|
|
|
([self isFetchInProgress] ? "YES" : "NO"));
|
|
|
|
|
|
|
|
if (![self isOpen])
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"%@ -- %@ 0x%x: attempt to select attributes with no open channel",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self];
|
|
|
|
|
|
|
|
if ([self isFetchInProgress])
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"%@ -- %@ 0x%x: attempt to select attributes with fetch in progress",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self];
|
|
|
|
|
|
|
|
if (_delegateRespondsTo.shouldSelectAttributes)
|
|
|
|
if (![_delegate adaptorChannel: self
|
|
|
|
shouldSelectAttributes: attributes
|
|
|
|
fetchSpecification: fetchSpecification
|
|
|
|
lock: flag
|
|
|
|
entity: entity])
|
|
|
|
return;
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"%@ -- %@ 0x%x: isFetchInProgress=%s",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self,
|
|
|
|
([self isFetchInProgress] ? "YES" : "NO"));
|
|
|
|
|
|
|
|
[self _cancelResults];
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"%@ -- %@ 0x%x: isFetchInProgress=%s",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self,
|
|
|
|
([self isFetchInProgress] ? "YES" : "NO"));
|
|
|
|
|
|
|
|
[_adaptorContext autoBeginTransaction: NO];
|
|
|
|
|
|
|
|
ASSIGN(_attributes, attributes);
|
|
|
|
// NSDebugMLLog(@"gsdb",@"00 attributes=%@",_attributes);
|
|
|
|
|
|
|
|
|
|
|
|
NSAssert([attributes count] > 0, @"No Attributes");
|
|
|
|
|
|
|
|
sqlExpr = [[[_adaptorContext adaptor] expressionClass]
|
|
|
|
selectStatementForAttributes: attributes
|
|
|
|
lock: flag
|
|
|
|
fetchSpecification: fetchSpecification
|
|
|
|
entity: entity];
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"sqlExpr=%@", sqlExpr);
|
|
|
|
// NSDebugMLLog(@"gsdb",@"AA attributes=%@",_attributes);
|
|
|
|
|
|
|
|
[self _evaluateExpression: sqlExpr
|
|
|
|
withAttributes: attributes];
|
|
|
|
|
2003-02-03 14:53:03 +00:00
|
|
|
NSDebugMLLog(@"gsdb", @"After _evaluate", "");
|
2002-11-15 22:57:05 +00:00
|
|
|
// NSDebugMLLog(@"gsdb",@"BB attributes=%@",_attributes);
|
|
|
|
[_adaptorContext autoCommitTransaction];
|
2003-02-03 14:53:03 +00:00
|
|
|
NSDebugMLLog(@"gsdb", @"After autoCommitTransaction", "");
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
if (_delegateRespondsTo.didSelectAttributes)
|
|
|
|
[_delegate adaptorChannel: self
|
|
|
|
didSelectAttributes: attributes
|
|
|
|
fetchSpecification: fetchSpecification
|
|
|
|
lock: flag
|
|
|
|
entity: entity];
|
|
|
|
// NSDebugMLLog(@"gsdb",@"CC attributes=%@",_attributes);
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (unsigned int)updateValues: (NSDictionary *)values
|
|
|
|
inRowsDescribedByQualifier: (EOQualifier *)qualifier
|
|
|
|
entity: (EOEntity *)entity
|
|
|
|
{
|
|
|
|
//autoBeginTransaction
|
|
|
|
//entity attributes
|
|
|
|
//externaltype on each attr
|
|
|
|
//adaptor expressionClass
|
|
|
|
//exprclass alloc initwithentity
|
|
|
|
//expr setUseAliases:NO
|
|
|
|
//exp prepareUpdateExpressionWithRow:qualifier:
|
|
|
|
//self evaluateExpression:
|
|
|
|
//autoCommitTransaction
|
|
|
|
//return number of affeted rows
|
|
|
|
//end
|
|
|
|
|
|
|
|
EOSQLExpression *sqlExpr = nil;
|
|
|
|
NSMutableDictionary *mrow = nil;
|
|
|
|
NSMutableArray *invAttributes = nil;
|
|
|
|
NSEnumerator *enumerator = nil;
|
|
|
|
NSString *attrName = nil;
|
|
|
|
NSString *externalType = nil;
|
|
|
|
EOAttribute *attr = nil;
|
2006-09-15 13:01:07 +00:00
|
|
|
PostgreSQLContext *adaptorContext = nil;
|
2002-11-15 22:57:05 +00:00
|
|
|
unsigned long rows = 0;
|
2005-02-13 13:04:19 +00:00
|
|
|
IMP valuesOFK=NULL; // objectForKey:
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
if (![self isOpen])
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"%@ -- %@ 0x%x: attempt to update values with no open channel",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self];
|
|
|
|
|
|
|
|
if ([self isFetchInProgress])
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"%@ -- %@ 0x%x: attempt to update values with fetch in progress",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self];
|
|
|
|
|
|
|
|
if ([values count] > 0)
|
|
|
|
{
|
2005-02-13 13:04:19 +00:00
|
|
|
IMP valueEnumNO=NULL; // nextObject
|
|
|
|
IMP mrowSOFK=NULL; // setObject:forKey;
|
|
|
|
|
2003-02-03 14:53:03 +00:00
|
|
|
mrow = AUTORELEASE([values mutableCopyWithZone: [values zone]]);
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
// Get EOAttributes involved in update operation
|
|
|
|
// Modify "inversion" attributes to NSNumber type with the Oid
|
|
|
|
|
2003-02-03 14:53:03 +00:00
|
|
|
invAttributes = AUTORELEASE([[NSMutableArray alloc] initWithCapacity: [mrow count]]);
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
enumerator = [values keyEnumerator];
|
2005-02-19 12:13:22 +00:00
|
|
|
while ((attrName = PSQLA_NextObjectWithImpPtr(enumerator,&valueEnumNO)))
|
2002-11-15 22:57:05 +00:00
|
|
|
{
|
|
|
|
attr = [entity attributeNamed: attrName];
|
|
|
|
externalType = [attr externalType];
|
|
|
|
|
|
|
|
if (attr == nil)
|
|
|
|
return 0; //???
|
|
|
|
/*
|
|
|
|
[mrow setObject:[attr adaptorValueByConvertingAttributeValue://Not in WO
|
|
|
|
[values objectForKey:attrName]]
|
|
|
|
forKey:attrName];
|
|
|
|
*/
|
2005-02-19 12:13:22 +00:00
|
|
|
PSQLA_SetObjectForKeyWithImpPtr(mrow,&mrowSOFK,
|
|
|
|
PSQLA_ObjectForKeyWithImpPtr(values,&valuesOFK,attrName),
|
2005-02-13 13:04:19 +00:00
|
|
|
attrName);
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
if ([externalType isEqual: @"inversion"])
|
|
|
|
[invAttributes addObject: attr];
|
|
|
|
}
|
|
|
|
|
|
|
|
[self _cancelResults]; //Not in WO
|
2006-09-15 13:01:07 +00:00
|
|
|
adaptorContext = (PostgreSQLContext *)[self adaptorContext];
|
2002-11-15 22:57:05 +00:00
|
|
|
[adaptorContext autoBeginTransaction: YES];
|
|
|
|
|
|
|
|
if ([invAttributes count])
|
|
|
|
{
|
2005-02-13 13:04:19 +00:00
|
|
|
IMP invAttributesNO=NULL; // nextObject
|
2002-11-15 22:57:05 +00:00
|
|
|
// Select with update qualifier to see there is only one row
|
|
|
|
// to be updated and to get the large objects (to be updatetd)
|
|
|
|
// Oid from dataserver - there is a hack here based on the fact that
|
|
|
|
// in update there in only one table and no flattened attributes
|
|
|
|
|
|
|
|
NSDictionary *dbRow = nil;
|
|
|
|
|
|
|
|
sqlExpr = [[[_adaptorContext adaptor] expressionClass]
|
|
|
|
selectStatementForAttributes: invAttributes
|
|
|
|
lock: NO
|
|
|
|
fetchSpecification:
|
|
|
|
[EOFetchSpecification
|
|
|
|
fetchSpecificationWithEntityName: [entity name]
|
|
|
|
qualifier: qualifier
|
|
|
|
sortOrderings: nil]
|
|
|
|
entity: entity];
|
|
|
|
[self _evaluateExpression: sqlExpr withAttributes: nil];
|
|
|
|
|
|
|
|
_fetchBlobsOid = YES;
|
|
|
|
dbRow = [self fetchRowWithZone: NULL];
|
|
|
|
_fetchBlobsOid = NO;
|
|
|
|
|
|
|
|
[self _cancelResults];
|
|
|
|
|
|
|
|
// Update the large objects and modify the row to update with Oid's
|
|
|
|
|
2005-02-13 13:04:19 +00:00
|
|
|
enumerator = [invAttributes objectEnumerator];
|
2005-02-19 12:13:22 +00:00
|
|
|
while ((attr = PSQLA_NextObjectWithImpPtr(enumerator,&invAttributesNO)))
|
2002-11-15 22:57:05 +00:00
|
|
|
{
|
|
|
|
Oid oldOid;
|
|
|
|
Oid newOid;
|
|
|
|
NSData *data;
|
|
|
|
|
|
|
|
attrName = [attr name];
|
|
|
|
data = [mrow objectForKey: attrName];
|
|
|
|
|
|
|
|
oldOid = [[dbRow objectForKey:attrName] longValue];
|
|
|
|
newOid = [self _updateBinaryDataRow: oldOid data: data];
|
|
|
|
|
2005-02-19 12:13:22 +00:00
|
|
|
PSQLA_SetObjectForKeyWithImpPtr(mrow,&mrowSOFK,
|
2005-02-13 13:04:19 +00:00
|
|
|
[NSNumber numberWithUnsignedLong: newOid],
|
|
|
|
attrName);
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we have all: one and only row to update and binary rows
|
|
|
|
// (large objects) where updated and their new Oid set in the row
|
|
|
|
|
|
|
|
rows = 0;
|
|
|
|
|
|
|
|
NSDebugMLLog(@"gsdb", @"[mrow count]=%d", [mrow count]);
|
|
|
|
|
|
|
|
if ([mrow count] > 0)
|
|
|
|
{
|
|
|
|
sqlExpr = [[[_adaptorContext adaptor] expressionClass]
|
|
|
|
updateStatementForRow: mrow
|
|
|
|
qualifier: qualifier
|
|
|
|
entity: entity];
|
|
|
|
|
|
|
|
//wo call evaluateExpression:
|
|
|
|
if ([self _evaluateExpression: sqlExpr withAttributes: nil])
|
|
|
|
rows = strtoul(PQcmdTuples(_pgResult), NULL, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
[adaptorContext autoCommitTransaction];
|
|
|
|
}
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
|
|
|
|
return rows;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The binaryDataRow should contain only one binary attribute */
|
|
|
|
|
|
|
|
- (char *)_readBinaryDataRow: (Oid)oid
|
|
|
|
length: (int *)length
|
|
|
|
zone: (NSZone *)zone;
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
int len, wrt;
|
|
|
|
char *bytes;
|
|
|
|
|
|
|
|
if (oid == 0)
|
|
|
|
{
|
|
|
|
*length = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
fd = lo_open(_pgConn, oid, INV_READ|INV_WRITE);
|
|
|
|
if (fd < 0)
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"cannot open large object Oid = %ld", oid];
|
|
|
|
|
|
|
|
lo_lseek(_pgConn, fd, 0, SEEK_END);
|
|
|
|
len = lo_tell(_pgConn, fd);
|
|
|
|
lo_lseek(_pgConn, fd, 0, SEEK_SET);
|
|
|
|
|
|
|
|
if (len < 0)
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"error while getting size of large object Oid = %ld", oid];
|
|
|
|
|
|
|
|
bytes = NSZoneMalloc(zone, len);
|
|
|
|
wrt = lo_read(_pgConn, fd, bytes, len);
|
|
|
|
|
|
|
|
if (len != wrt)
|
|
|
|
{
|
|
|
|
NSZoneFree(zone, bytes);
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"error while reading large object Oid = %ld", oid];
|
|
|
|
}
|
|
|
|
lo_close(_pgConn, fd);
|
|
|
|
|
|
|
|
*length = len;
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (Oid)_insertBinaryData: (NSData *)binaryData
|
|
|
|
forAttribute: (EOAttribute *)attr
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
const char* bytes;
|
|
|
|
Oid oid;
|
|
|
|
int fd, wrt;
|
|
|
|
|
|
|
|
if ((id)binaryData == [EONull null] || binaryData == nil)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
len = [binaryData length];
|
|
|
|
bytes = [binaryData bytes];
|
|
|
|
|
|
|
|
oid = lo_creat(_pgConn, INV_READ|INV_WRITE);
|
|
|
|
if (oid == 0)
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"cannot create large object"];
|
|
|
|
|
|
|
|
fd = lo_open(_pgConn, oid, INV_READ|INV_WRITE);
|
|
|
|
if (fd < 0)
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"cannot open large object Oid = %ld", oid];
|
|
|
|
|
|
|
|
wrt = lo_write(_pgConn, fd, (char *)bytes, len);
|
|
|
|
|
|
|
|
if (len != wrt)
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"error while writing large object Oid = %ld", oid];
|
|
|
|
|
|
|
|
lo_close(_pgConn, fd);
|
|
|
|
|
|
|
|
return oid;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (Oid)_updateBinaryDataRow: (Oid)oid
|
|
|
|
data: (NSData *)binaryData
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
const char* bytes;
|
|
|
|
int wrt, fd;
|
|
|
|
|
|
|
|
if (oid)
|
|
|
|
lo_unlink(_pgConn, oid);
|
|
|
|
|
|
|
|
if ((id)binaryData == [EONull null] || binaryData == nil)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
len = [binaryData length];
|
|
|
|
bytes = [binaryData bytes];
|
|
|
|
|
|
|
|
oid = lo_creat(_pgConn, INV_READ|INV_WRITE);
|
|
|
|
if (oid == 0)
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"cannot create large object"];
|
|
|
|
|
|
|
|
fd = lo_open(_pgConn, oid, INV_READ|INV_WRITE);
|
|
|
|
if (fd < 0)
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"cannot open large object Oid = %ld", oid];
|
|
|
|
|
|
|
|
wrt = lo_write(_pgConn, fd, (char*)bytes, len);
|
|
|
|
|
|
|
|
if (len != wrt)
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"error while writing large object Oid = %ld", oid];
|
|
|
|
|
|
|
|
lo_close(_pgConn, fd);
|
|
|
|
|
|
|
|
return oid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read type oid and names from the database server.
|
|
|
|
Called on each openChannel to refresh info. */
|
|
|
|
- (void)_describeDatabaseTypes
|
|
|
|
{
|
|
|
|
int i, count;
|
|
|
|
|
|
|
|
_pgResult = PQexec(_pgConn,
|
|
|
|
"SELECT oid, typname FROM pg_type WHERE typrelid = 0");
|
|
|
|
|
|
|
|
if (_pgResult == NULL || PQresultStatus(_pgResult) != PGRES_TUPLES_OK)
|
|
|
|
{
|
|
|
|
_pgResult = NULL;
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"cannot read type name informations from database. "
|
|
|
|
@"bad response from server"];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PQnfields(_pgResult) != 2)
|
|
|
|
{
|
|
|
|
_pgResult = NULL;
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"cannot read type name informations from database. "
|
|
|
|
@"results should have two columns"];
|
|
|
|
}
|
|
|
|
|
|
|
|
[_oidToTypeName removeAllObjects];
|
|
|
|
count = PQntuples(_pgResult);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
char* oid = PQgetvalue(_pgResult, i, 0);
|
|
|
|
char* typ = PQgetvalue(_pgResult, i, 1);
|
|
|
|
|
|
|
|
[_oidToTypeName setObject: [NSString stringWithCString: typ]
|
|
|
|
forKey: [NSNumber numberWithLong: atol(oid)]];
|
|
|
|
}
|
|
|
|
|
|
|
|
PQclear(_pgResult);
|
|
|
|
_pgResult = NULL;
|
|
|
|
}
|
|
|
|
|
2003-06-24 16:27:01 +00:00
|
|
|
- (void)_readServerVersion
|
|
|
|
{
|
|
|
|
NSString *version;
|
|
|
|
|
|
|
|
_pgResult = PQexec(_pgConn,
|
|
|
|
"SELECT version()");
|
|
|
|
|
|
|
|
if (_pgResult == NULL || PQresultStatus(_pgResult) != PGRES_TUPLES_OK)
|
|
|
|
{
|
|
|
|
_pgResult = NULL;
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2003-06-24 16:27:01 +00:00
|
|
|
format: @"cannot read type name informations from database. "
|
|
|
|
@"bad response from server"];
|
|
|
|
}
|
|
|
|
|
|
|
|
version = [NSString stringWithCString: PQgetvalue(_pgResult, 0, 0)];
|
|
|
|
_pgVersion = [version parsedFirstVersionSubstring];
|
|
|
|
|
|
|
|
PQclear(_pgResult);
|
|
|
|
_pgResult = NULL;
|
|
|
|
}
|
|
|
|
|
2002-11-15 22:57:05 +00:00
|
|
|
- (NSArray *)attributesToFetch
|
|
|
|
{
|
|
|
|
return _attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setAttributesToFetch: (NSArray *)attributes
|
|
|
|
{
|
|
|
|
//call adaptorContext
|
2006-09-15 13:01:07 +00:00
|
|
|
NSDebugMLLog(@"gsdb", @"PostgreSQLChannel: setAttributesToFetch %p:%@",
|
2002-11-15 22:57:05 +00:00
|
|
|
attributes, attributes);
|
|
|
|
|
|
|
|
ASSIGN(_attributes, attributes);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *)describeResults
|
|
|
|
{
|
|
|
|
NSArray *desc;
|
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
if (![self isFetchInProgress])
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
format: @"%@ -- %@ 0x%x: attempt to describe results with no fetch in progress",
|
|
|
|
NSStringFromSelector(_cmd),
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
self];
|
|
|
|
|
|
|
|
desc = [self attributesToFetch];
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
|
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)_describeResults
|
|
|
|
{
|
|
|
|
int colsNumber;
|
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
|
|
|
colsNumber=_pgResult ? PQnfields(_pgResult): 0;
|
|
|
|
NSDebugMLLog(@"gsdb", @"colsNumber=%d", colsNumber);
|
|
|
|
|
|
|
|
if (colsNumber == 0)
|
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
[self setAttributesToFetch: PSQLA_NSArray];
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
else if (!_attributes) //??
|
|
|
|
{
|
|
|
|
int i;
|
2005-02-13 13:04:19 +00:00
|
|
|
id *attributes = NULL;
|
|
|
|
IMP origAttributesOAI=NULL;
|
|
|
|
IMP oidToTypeNameOFK=NULL;
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
attributes = alloca(colsNumber * sizeof(id));
|
|
|
|
|
|
|
|
for (i = 0; i < colsNumber; i++)
|
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
EOAttribute *attribute
|
|
|
|
= AUTORELEASE([PSQLA_alloc(EOAttribute) init]);
|
2004-02-25 12:27:43 +00:00
|
|
|
NSString *externalType;
|
2002-11-15 22:57:05 +00:00
|
|
|
NSString *valueClass = @"NSString";
|
|
|
|
NSString *valueType = nil;
|
|
|
|
|
|
|
|
if (_origAttributes)
|
|
|
|
{
|
2005-02-13 13:04:19 +00:00
|
|
|
EOAttribute *origAttr = (EOAttribute *)
|
2005-02-19 12:13:22 +00:00
|
|
|
PSQLA_ObjectAtIndexWithImpPtr(_origAttributes,&origAttributesOAI,i);
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
[attribute setName: [origAttr name]];
|
|
|
|
[attribute setColumnName: [origAttr columnName]];
|
|
|
|
[attribute setExternalType: [origAttr externalType]];
|
|
|
|
[attribute setValueType: [origAttr valueType]];
|
|
|
|
[attribute setValueClassName: [origAttr valueClassName]];
|
|
|
|
}
|
|
|
|
else
|
2004-02-25 12:27:43 +00:00
|
|
|
{
|
|
|
|
NSNumber *externalTypeNumber;
|
|
|
|
externalTypeNumber
|
|
|
|
= [NSNumber numberWithLong: PQftype(_pgResult, i)];
|
2005-02-19 12:13:22 +00:00
|
|
|
externalType = PSQLA_ObjectForKeyWithImpPtr(_oidToTypeName,
|
2005-02-13 13:04:19 +00:00
|
|
|
&oidToTypeNameOFK,externalTypeNumber);
|
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
if (!externalType)
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-11-15 22:57:05 +00:00
|
|
|
format: @"cannot find type for Oid = %d",
|
|
|
|
PQftype(_pgResult, i)];
|
|
|
|
|
|
|
|
[attribute setName: [NSString stringWithFormat: @"attribute%d", i]];
|
|
|
|
[attribute setColumnName: @"unknown"];
|
2004-02-25 12:27:43 +00:00
|
|
|
[attribute setExternalType: externalType];
|
2002-11-15 22:57:05 +00:00
|
|
|
|
COmmit Part 2
* EOAccess/EOAdaptor.m:
o optimization in 'for' loops
* EOAccess/EODatabase.m:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAccess/EODatabaseContext.h:
o added _snapshotForGlobalIDIMP
* EOAccess/EODatabaseContext.m:
o commented NSEmitTODO in
-objectsForSourceGlobalID:relationshipName:editingContext:
o added beter exception format in
qualifierForLockingAttributes:primaryKeyAttributes:entity:snapshot:
o fix compiler warning in -relayPrimaryKey:object:entity:
o logs
o optimizations in -objectsWithFetchSpecification:editingContext:
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o use _snapshotForGlobalIDIMP
o IMP usage optimization
* EOAccess/EOAttribute.[hm]:
o added EOAdaptorUnknownType
o added _adaptorValueType and avoid recomputing it each time
o added _valueTypeChar to avoid string comparaisons
o use EOPriv classes declarations
o Temporary reverted David changes in
-adaptorValueByConvertingAttributeValue
* EOAccess/EOAttributePriv.h:
o added _valueTypeChar to avoid string comparaisons
* EOAccess/EOEntityPriv.h:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.h:
o moved private -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.m:
o better exception in classProperties
o fix compiler warning in -setClassProperties:,
-setPrimaryKeyAttributes:,
-setAttributesUsedForLocking:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLExpression.m:
o optimization in -tableListWithRootEntity:
o optimization in -formatSQLString:format:
o optimization in +sqlPatternFromShellPattern:
o optimization in +sqlPatternFromShellPattern:withEscapeCharacter:
o fix in -sqlStringForKeyValueQualifier:
o added log in -sqlStringForKeyValueQualifier: for not handled
readFormat
o added log -addInsertListAttribute:value: for not handled
writeFormat
o added log -addUpdateListAttribute:value: for not handled
writeFormat
o changed EOFLOGObjectFnStart to EOFLOGObjectFnStartCond
o changed EOFLOGObjectFnStop to EOFLOGObjectFnStopCond
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLQualifier.m:
o implemented EOKeyComparisonQualifier
-schemaBasedQualifierWithRootEntity
* EOAccess/EOUtilities.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOControl/EOPriv.[hm]:
o added. Contains various classes/selectors/IMPs
* EOControl/EOClassDescription.m:
o handle EONull case in -propagateDeleteForObject:editingContext:,
-addObject:toPropertyWithKey:, -snapshot,
-removeObject:fromPropertyWithKey:,
_setObject:forBothSidesOfRelationshipWithKey:,
addObject:toBothSidesOfRelationshipWithKey:,
-removeObject:fromBothSidesOfRelationshipWithKey:
o fix compiler warning in
-dictionaryForInstanceProperties, -shallowCopy,
-updateFromSnapshot:, -snapshot
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o replaced isNilOrEONull() by _isNilOrEONull()
o fix in -validateForSave
o rewritten -validateValue:forKey: selector build
* EOControl/EOEditingContext.h:
o added -hasUnprocessedChanges
* EOControl/EOEditingContext.m:
o added -hasUnprocessedChanges
o added NS_DURING,... to catch exceptions
o replace [EOFault isFault:] by _isFault()
o IMP usage optimization
* EOControl/EOKeyGlobalID.m:
o replaced isNilOrEONull() by _isNilOrEONull()
o include <EOCOntrol/EOPriv.h>
* EOControl/EOGenericRecord.m:
o partially rewritten -description
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o changed variable name type of
_infoForInstanceVariableNamed:retType:retSize:retOffset:
o rewritten valueForKey:,... to use cString NSKeyValueCoding
* EOControl/EOKeyValueCoding.m:
o changed NSAssert in NSArray -valueForKey:
o optimization in NSDictionary -takeValue:forKeyPath:isSmart:
o optimization in NSDictionary -takeStoredValue:forKeyPath:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOKeyValueQualifier.m:
o fixes for EONull/nil in -evaluateWithObject:
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOSortOrdering.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAdaptors/Postgres95SQLExpression.m:
o float formatting in +formatValue:forAttribute:
o added -externalNameQuoteCharacter
o added +sqlPatternFromShellPattern:
o added +sqlPatternFromShellPattern:withEscapeCharacter:
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAdaptors/Postgres95Channel.m:
o logs
* EOAdaptors/Postgres95Values.m:
o logs
o fix in +setPostgres95Format:
o fix calendard format to handle timezone (%z)
o optimizations
* EOControl/EOMutableKnownKeyDictionary.m
o removed EOMKKDArrayMapping
+dictionaryFromDictionary:subsetMapping:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOControl/EONSAddOns.[hm]:
o added NSString(ShellPattern)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@20688 72102866-910b-0410-8b05-ffd578937521
2005-02-11 17:37:23 +00:00
|
|
|
//TODO: Optimize ?
|
2004-02-25 12:27:43 +00:00
|
|
|
if ([externalType isEqual: @"bool"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"c";
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"char"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"c";
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"dt"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSCalendarDate", valueType = nil;
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"date"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSCalendarDate", valueType = nil;
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"time"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSCalendarDate", valueType = nil;
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"float4"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"f";
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"float8"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"d";
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"int2"])
|
2003-11-28 22:30:57 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"s";
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"int4"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"i";
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"int8"] || [externalType isEqual: @"bigint"])
|
2003-11-28 22:30:57 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"u";
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"oid"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"l";
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"varchar"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSString", valueType = nil;
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"bpchar"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSString", valueType = nil;
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual: @"text"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSString", valueType = nil;
|
2004-02-25 12:27:43 +00:00
|
|
|
/* else if ([externalType isEqual:@"cid"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"";
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual:@"tid"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"";
|
2004-02-25 12:27:43 +00:00
|
|
|
else if ([externalType isEqual:@"xid"])
|
2002-11-15 22:57:05 +00:00
|
|
|
valueClass = @"NSNumber", valueType = @"";*/
|
|
|
|
|
|
|
|
[attribute setValueType: valueType];
|
|
|
|
[attribute setValueClassName: valueClass];
|
|
|
|
}
|
|
|
|
|
|
|
|
attributes[i] = attribute;
|
|
|
|
}
|
|
|
|
|
2003-02-03 14:53:03 +00:00
|
|
|
[self setAttributesToFetch: AUTORELEASE([[NSArray alloc]
|
2002-11-15 22:57:05 +00:00
|
|
|
initWithObjects: attributes
|
2003-02-03 14:53:03 +00:00
|
|
|
count: colsNumber])];
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
// NSDebugMLLog(@"gsdb",@"_attributes=%@",_attributes);
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The methods used to generate an model from the meta-information kept by
|
|
|
|
the database. */
|
|
|
|
|
|
|
|
- (NSArray *)describeTableNames
|
|
|
|
{
|
2002-12-30 22:10:43 +00:00
|
|
|
int i, count;
|
2005-02-13 13:04:19 +00:00
|
|
|
NSMutableArray *results = nil;
|
2003-06-24 16:27:01 +00:00
|
|
|
char *tableSelect;
|
2005-02-13 13:04:19 +00:00
|
|
|
IMP resultsAO=NULL; // addObject:
|
2003-06-24 16:27:01 +00:00
|
|
|
|
|
|
|
if (_pgVersion < 70300)
|
|
|
|
{
|
|
|
|
tableSelect = "SELECT tablename FROM pg_tables WHERE tableowner != 'postgres' OR tablename NOT LIKE 'pg_%'";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tableSelect = "SELECT tablename FROM pg_tables WHERE pg_tables.schemaname = 'public'";
|
|
|
|
}
|
|
|
|
|
2002-12-30 22:10:43 +00:00
|
|
|
|
|
|
|
NSAssert(_pgConn, @"Channel not opened");
|
|
|
|
|
2003-06-24 16:27:01 +00:00
|
|
|
_pgResult = PQexec(_pgConn, tableSelect);
|
|
|
|
|
2002-12-30 22:10:43 +00:00
|
|
|
|
|
|
|
if (_pgResult == NULL
|
|
|
|
|| PQresultStatus(_pgResult) != PGRES_TUPLES_OK)
|
|
|
|
{
|
|
|
|
_pgResult = NULL;
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2002-12-30 22:10:43 +00:00
|
|
|
format: @"cannot read list of tables from database. "
|
|
|
|
@"bad response from server"];
|
|
|
|
}
|
|
|
|
|
|
|
|
count = PQntuples(_pgResult);
|
2005-02-19 12:13:22 +00:00
|
|
|
results= AUTORELEASE([PSQLA_alloc(NSMutableArray) initWithCapacity: count]);
|
2002-12-30 22:10:43 +00:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
char *oid = PQgetvalue(_pgResult, i, 0);
|
|
|
|
|
2005-02-19 12:13:22 +00:00
|
|
|
PSQLA_AddObjectWithImpPtr(results,&resultsAO,
|
|
|
|
[NSString stringWithUTF8String: oid]);
|
2002-12-30 22:10:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PQclear(_pgResult);
|
|
|
|
_pgResult = NULL;
|
|
|
|
|
|
|
|
return [NSArray arrayWithArray: results];
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *)describeStoredProcedureNames
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
[self notImplemented: _cmd];
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
- (void)_describeBasicEntityWithName:(NSString *)tableName
|
|
|
|
forModel:(EOModel *)model
|
|
|
|
{
|
|
|
|
EOEntity *entity;
|
|
|
|
NSString *stmt;
|
|
|
|
EOAttribute *attribute;
|
|
|
|
NSString *valueClass = @"NSString";
|
|
|
|
NSString *valueType = nil;
|
|
|
|
NSString *tableOid;
|
2005-02-13 13:04:19 +00:00
|
|
|
unsigned int n, k;
|
|
|
|
int count = 0;
|
2004-02-25 12:27:43 +00:00
|
|
|
|
|
|
|
entity = AUTORELEASE([[EOEntity alloc] init]);
|
|
|
|
[entity setName: tableName];
|
|
|
|
[entity setExternalName: tableName];
|
|
|
|
[entity setClassName: @"EOGenericRecord"];
|
|
|
|
[model addEntity: entity];
|
|
|
|
|
|
|
|
stmt = [NSS_SWF: @"SELECT oid FROM pg_class "
|
|
|
|
@"WHERE relname = '%@' AND relkind = 'r'",tableName];
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
EOAdaptorDebugLog(@"PostgreSQLAdaptor: execute command:\n%@", stmt);
|
2004-02-25 12:27:43 +00:00
|
|
|
_pgResult = PQexec(_pgConn, [stmt cString]);
|
|
|
|
|
|
|
|
if (_pgResult == NULL || PQresultStatus(_pgResult) != PGRES_TUPLES_OK)
|
|
|
|
{
|
|
|
|
_pgResult = NULL;
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2004-02-25 12:27:43 +00:00
|
|
|
format: @"cannot read type name information from database."
|
|
|
|
@"bad response from server"];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PQntuples(_pgResult) != 1)
|
|
|
|
{
|
|
|
|
_pgResult = NULL;
|
2006-09-15 13:01:07 +00:00
|
|
|
[NSException raise: PostgreSQLException
|
2004-02-25 12:27:43 +00:00
|
|
|
format: @"Table %@ doesn't exist", tableName];
|
|
|
|
}
|
|
|
|
|
|
|
|
tableOid = [NSString stringWithCString: PQgetvalue(_pgResult,0,0)];
|
|
|
|
[entity setUserInfo: [NSDictionary dictionaryWithObject:tableOid
|
|
|
|
forKey: @"tableOid"]];
|
|
|
|
stmt = [NSS_SWF: @"SELECT attname,typname,attnum "
|
|
|
|
@"FROM pg_attribute LEFT JOIN pg_type ON atttypid = oid "
|
2005-01-22 10:20:35 +00:00
|
|
|
@"WHERE attnum > 0 AND attrelid=%@"
|
|
|
|
@"AND attisdropped IS FALSE", tableOid];
|
2004-02-25 12:27:43 +00:00
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
EOAdaptorDebugLog(@"PostgreSQLAdaptor: execute command:\n%@", stmt);
|
2004-02-25 12:27:43 +00:00
|
|
|
PQclear(_pgResult);
|
|
|
|
|
|
|
|
_pgResult = PQexec(_pgConn, [stmt cString]);
|
2005-02-13 13:04:19 +00:00
|
|
|
count = PQntuples(_pgResult);
|
2004-02-25 12:27:43 +00:00
|
|
|
|
2005-02-13 13:04:19 +00:00
|
|
|
if (count>0)
|
2004-02-25 12:27:43 +00:00
|
|
|
{
|
2005-02-13 13:04:19 +00:00
|
|
|
for (n = 0; n < count; n++)
|
|
|
|
{
|
|
|
|
NSString *columnName;
|
|
|
|
NSString *externalType;
|
2005-02-19 12:13:22 +00:00
|
|
|
char *name;
|
|
|
|
unsigned length;
|
|
|
|
|
|
|
|
name = PQgetvalue(_pgResult,n,1);
|
|
|
|
length = name ? strlen(name) : 0;
|
2005-02-13 13:04:19 +00:00
|
|
|
|
2005-02-19 12:13:22 +00:00
|
|
|
externalType = [(PSQLA_alloc(NSString)) initWithCString: name
|
|
|
|
length: length];
|
2005-02-13 13:04:19 +00:00
|
|
|
|
|
|
|
//TODO optimize ?
|
|
|
|
if ([externalType isEqual: @"bool"])
|
|
|
|
valueClass = @"NSNumber", valueType = @"c";
|
|
|
|
else if ([externalType isEqual: @"char"])
|
|
|
|
valueClass = @"NSNumber", valueType = @"c";
|
|
|
|
else if ([externalType isEqual: @"dt"])
|
|
|
|
valueClass = @"NSCalendarDate", valueType = nil;
|
|
|
|
else if ([externalType isEqual: @"date"])
|
|
|
|
valueClass = @"NSCalendarDate", valueType = nil;
|
|
|
|
else if ([externalType isEqual: @"time"])
|
|
|
|
valueClass = @"NSCalendarDate", valueType = nil;
|
|
|
|
else if ([externalType isEqual: @"float4"])
|
|
|
|
valueClass = @"NSNumber", valueType = @"f";
|
|
|
|
else if ([externalType isEqual: @"float8"])
|
|
|
|
valueClass = @"NSNumber", valueType = @"d";
|
|
|
|
else if ([externalType isEqual: @"int2"])
|
|
|
|
valueClass = @"NSNumber", valueType = @"i";
|
|
|
|
else if ([externalType isEqual: @"int4"])
|
|
|
|
valueClass = @"NSNumber", valueType = @"i";
|
|
|
|
else if ([externalType isEqual: @"int8"])
|
|
|
|
valueClass = @"NSNumber", valueType = @"l";
|
|
|
|
else if ([externalType isEqual: @"oid"])
|
|
|
|
valueClass = @"NSNumber", valueType = @"l";
|
|
|
|
else if ([externalType isEqual: @"varchar"])
|
|
|
|
valueClass = @"NSString", valueType = nil;
|
|
|
|
else if ([externalType isEqual: @"bpchar"])
|
|
|
|
valueClass = @"NSString", valueType = nil;
|
|
|
|
else if ([externalType isEqual: @"text"])
|
|
|
|
valueClass = @"NSString", valueType = nil;
|
|
|
|
|
2005-02-19 12:13:22 +00:00
|
|
|
name = PQgetvalue(_pgResult, n, 0);
|
|
|
|
length = name ? strlen(name) : 0;
|
|
|
|
columnName = [(PSQLA_alloc(NSString)) initWithCString: name
|
|
|
|
length: length];
|
|
|
|
|
|
|
|
attribute = [PSQLA_alloc(EOAttribute) init];
|
2005-02-13 13:04:19 +00:00
|
|
|
[attribute setName: columnName];
|
|
|
|
[attribute setColumnName: columnName];
|
|
|
|
[attribute setExternalType: externalType];
|
|
|
|
[attribute setValueType: valueType];
|
|
|
|
[attribute setValueClassName: valueClass];
|
|
|
|
[entity addAttribute: attribute];
|
2005-02-19 12:13:22 +00:00
|
|
|
|
|
|
|
RELEASE(externalType);
|
|
|
|
RELEASE(attribute);
|
|
|
|
RELEASE(columnName);
|
2005-02-13 13:04:19 +00:00
|
|
|
}
|
|
|
|
};
|
2004-02-25 12:27:43 +00:00
|
|
|
|
|
|
|
PQclear(_pgResult);
|
|
|
|
|
|
|
|
/* Determint primary key. */
|
|
|
|
stmt = [NSS_SWF: @"SELECT indkey FROM pg_index "
|
|
|
|
@"WHERE indrelid='%@' AND indisprimary = 't'",
|
|
|
|
tableOid];
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
EOAdaptorDebugLog(@"PostgreSQLAdaptor: execute command:\n%@", stmt);
|
2004-02-25 12:27:43 +00:00
|
|
|
_pgResult = PQexec(_pgConn,[stmt cString]);
|
|
|
|
if (PQntuples(_pgResult))
|
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
NSString *pkAttNum
|
|
|
|
= [NSString stringWithCString: PQgetvalue(_pgResult,0,0)];
|
2005-02-13 13:04:19 +00:00
|
|
|
pkAttNum = [pkAttNum stringByReplacingString:@" "
|
|
|
|
withString: @", "];
|
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
stmt = [NSS_SWF: @"SELECT attname FROM pg_attribute "
|
|
|
|
@"WHERE attrelid='%@' and attnum in (%@)",
|
|
|
|
tableOid, pkAttNum];
|
|
|
|
PQclear(_pgResult);
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
EOAdaptorDebugLog(@"PostgreSQLAdaptor: execute command:\n%@", stmt);
|
2004-02-25 12:27:43 +00:00
|
|
|
_pgResult = PQexec(_pgConn,[stmt cString]);
|
|
|
|
|
|
|
|
if (PQntuples(_pgResult))
|
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
NSMutableArray *pkeys;
|
2005-02-13 13:04:19 +00:00
|
|
|
count = PQntuples(_pgResult);
|
2005-02-19 12:13:22 +00:00
|
|
|
pkeys = [PSQLA_alloc(NSMutableArray) initWithCapacity: count];
|
2005-02-13 13:04:19 +00:00
|
|
|
for (k = 0; k < count; k++)
|
2004-02-25 12:27:43 +00:00
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
//TODO: Optimize, it's probably faster to use a mutable
|
|
|
|
// string here instead of alloc/dealloing new strings.
|
2004-02-25 12:27:43 +00:00
|
|
|
NSString *name;
|
2005-02-19 12:13:22 +00:00
|
|
|
const char *cName;
|
|
|
|
unsigned length;
|
2004-02-25 12:27:43 +00:00
|
|
|
|
|
|
|
cName = PQgetvalue(_pgResult,k,0);
|
2005-02-19 12:13:22 +00:00
|
|
|
length = cName ? strlen(cName) : 0;
|
|
|
|
name = [(PSQLA_alloc(NSString)) initWithCString: cName
|
|
|
|
length: length];
|
2004-02-25 12:27:43 +00:00
|
|
|
attribute = [entity attributeNamed: name];
|
|
|
|
NSDebugMLLog(@"adaptor", @"pk(%d) name: %@", k, name);
|
|
|
|
|
2005-02-19 12:13:22 +00:00
|
|
|
[pkeys addObject: attribute];
|
|
|
|
RELEASE(name);
|
2004-02-25 12:27:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NSDebugMLLog(@"adaptor", @"pkeys %@", pkeys);
|
|
|
|
[entity setPrimaryKeyAttributes: pkeys];
|
2005-02-19 12:13:22 +00:00
|
|
|
RELEASE(pkeys);
|
2004-02-25 12:27:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* </primary key stuff> */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)_describeForeignKeysForEntity:(EOEntity *) entity
|
|
|
|
forModel:(EOModel *) model
|
|
|
|
{
|
|
|
|
NSString *stmt;
|
|
|
|
NSString *tableOid;
|
|
|
|
unsigned int i, j, n, m;
|
|
|
|
|
|
|
|
tableOid = [[entity userInfo] objectForKey: @"tableOid"];
|
|
|
|
stmt = [NSS_SWF: @"SELECT tgargs FROM pg_trigger "
|
|
|
|
@"WHERE tgtype=21 AND tgisconstraint='t' AND tgrelid=%@",
|
|
|
|
tableOid];
|
|
|
|
|
|
|
|
PQclear(_pgResult);
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
EOAdaptorDebugLog(@"PostgreSQLAdaptor: execute command:\n%@", stmt);
|
2004-02-25 12:27:43 +00:00
|
|
|
_pgResult = PQexec(_pgConn, [stmt cString]);
|
|
|
|
|
|
|
|
for (i = 0, n = PQntuples(_pgResult); i < n; i++)
|
|
|
|
{
|
|
|
|
NSString *fkString;
|
|
|
|
NSArray *fkComp;
|
|
|
|
NSString *srcEntityName;
|
|
|
|
NSString *dstEntityName;
|
|
|
|
EOEntity *srcEntity;
|
|
|
|
EOEntity *dstEntity;
|
|
|
|
NSString *relationshipName;
|
|
|
|
EORelationship *relationship;
|
|
|
|
NSSet *dstPKSet;
|
|
|
|
NSMutableSet *dstAttribNames;
|
2005-02-19 12:13:22 +00:00
|
|
|
char *name;
|
|
|
|
unsigned length;
|
2004-02-25 12:27:43 +00:00
|
|
|
|
2005-02-19 12:13:22 +00:00
|
|
|
name = PQgetvalue(_pgResult,i,0);
|
|
|
|
length = name ? strlen(name) : 0;
|
|
|
|
fkString = AUTORELEASE([(PSQLA_alloc(NSString)) initWithCString: name
|
|
|
|
length: length]);
|
2004-02-25 12:27:43 +00:00
|
|
|
NSDebugMLLog(@"adaptor", @"foreign key: %@\n",fkString);
|
|
|
|
|
|
|
|
fkComp = [fkString componentsSeparatedByString: @"\\000"];
|
|
|
|
|
|
|
|
NSAssert1([fkComp count]>6, @"Illformed constraint:%@", fkString);
|
|
|
|
|
|
|
|
NSDebugMLLog(@"adaptor", @"constaint anme: %@",
|
|
|
|
[fkComp objectAtIndex:0]);
|
|
|
|
|
|
|
|
/* This assumes that entityName == tableName. */
|
|
|
|
srcEntityName = [fkComp objectAtIndex: 1];
|
|
|
|
dstEntityName = [fkComp objectAtIndex: 2];
|
|
|
|
|
|
|
|
srcEntity = [model entityNamed: srcEntityName];
|
|
|
|
dstEntity = [model entityNamed: dstEntityName];
|
|
|
|
|
|
|
|
relationshipName = [NSS_SWF:@"to%@", dstEntityName];
|
|
|
|
|
|
|
|
for (j = 1;
|
|
|
|
([srcEntity anyAttributeNamed: relationshipName] != nil ||
|
|
|
|
[srcEntity anyRelationshipNamed: relationshipName] != nil);
|
|
|
|
j++)
|
|
|
|
{
|
|
|
|
relationshipName = [NSS_SWF:@"to%@_%d", dstEntityName, j];
|
|
|
|
}
|
|
|
|
|
|
|
|
relationship = AUTORELEASE([EORelationship new]);
|
|
|
|
[relationship setName: relationshipName];
|
|
|
|
[srcEntity addRelationship: relationship];
|
|
|
|
|
|
|
|
dstAttribNames = (id)[NSMutableSet set];
|
|
|
|
|
|
|
|
for (j = 4, m = [fkComp count]; j < m; j = j + 2)
|
|
|
|
{
|
|
|
|
NSString *srcAttribName;
|
|
|
|
NSString *dstAttribName;
|
|
|
|
EOAttribute *srcAttrib;
|
|
|
|
EOAttribute *dstAttrib;
|
|
|
|
EOJoin *join;
|
|
|
|
|
|
|
|
srcAttribName = [fkComp objectAtIndex: j];
|
|
|
|
if ([srcAttribName length] == 0) break;
|
|
|
|
dstAttribName = [fkComp objectAtIndex: j + 1];
|
|
|
|
[dstAttribNames addObject: dstAttribName];
|
|
|
|
|
|
|
|
srcAttrib = [srcEntity attributeNamed: srcAttribName];
|
2004-02-26 10:33:10 +00:00
|
|
|
dstAttrib = [dstEntity attributeNamed: dstAttribName];
|
2004-02-25 12:27:43 +00:00
|
|
|
|
|
|
|
join
|
|
|
|
= AUTORELEASE([[EOJoin alloc] initWithSourceAttribute: srcAttrib
|
|
|
|
destinationAttribute: dstAttrib]);
|
|
|
|
[relationship addJoin: join];
|
|
|
|
}
|
|
|
|
|
|
|
|
dstPKSet = [NSSet setWithArray: [dstEntity primaryKeyAttributeNames]];
|
|
|
|
|
|
|
|
if ([dstPKSet isSubsetOfSet: dstAttribNames])
|
|
|
|
{
|
|
|
|
[relationship setToMany: NO];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[relationship setToMany: YES];
|
|
|
|
}
|
|
|
|
[relationship setJoinSemantic: EOInnerJoin];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-15 22:57:05 +00:00
|
|
|
- (EOModel *)describeModelWithTableNames: (NSArray *)tableNames
|
|
|
|
{
|
COmmit Part 2
* EOAccess/EOAdaptor.m:
o optimization in 'for' loops
* EOAccess/EODatabase.m:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAccess/EODatabaseContext.h:
o added _snapshotForGlobalIDIMP
* EOAccess/EODatabaseContext.m:
o commented NSEmitTODO in
-objectsForSourceGlobalID:relationshipName:editingContext:
o added beter exception format in
qualifierForLockingAttributes:primaryKeyAttributes:entity:snapshot:
o fix compiler warning in -relayPrimaryKey:object:entity:
o logs
o optimizations in -objectsWithFetchSpecification:editingContext:
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o use _snapshotForGlobalIDIMP
o IMP usage optimization
* EOAccess/EOAttribute.[hm]:
o added EOAdaptorUnknownType
o added _adaptorValueType and avoid recomputing it each time
o added _valueTypeChar to avoid string comparaisons
o use EOPriv classes declarations
o Temporary reverted David changes in
-adaptorValueByConvertingAttributeValue
* EOAccess/EOAttributePriv.h:
o added _valueTypeChar to avoid string comparaisons
* EOAccess/EOEntityPriv.h:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.h:
o moved private -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.m:
o better exception in classProperties
o fix compiler warning in -setClassProperties:,
-setPrimaryKeyAttributes:,
-setAttributesUsedForLocking:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLExpression.m:
o optimization in -tableListWithRootEntity:
o optimization in -formatSQLString:format:
o optimization in +sqlPatternFromShellPattern:
o optimization in +sqlPatternFromShellPattern:withEscapeCharacter:
o fix in -sqlStringForKeyValueQualifier:
o added log in -sqlStringForKeyValueQualifier: for not handled
readFormat
o added log -addInsertListAttribute:value: for not handled
writeFormat
o added log -addUpdateListAttribute:value: for not handled
writeFormat
o changed EOFLOGObjectFnStart to EOFLOGObjectFnStartCond
o changed EOFLOGObjectFnStop to EOFLOGObjectFnStopCond
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLQualifier.m:
o implemented EOKeyComparisonQualifier
-schemaBasedQualifierWithRootEntity
* EOAccess/EOUtilities.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOControl/EOPriv.[hm]:
o added. Contains various classes/selectors/IMPs
* EOControl/EOClassDescription.m:
o handle EONull case in -propagateDeleteForObject:editingContext:,
-addObject:toPropertyWithKey:, -snapshot,
-removeObject:fromPropertyWithKey:,
_setObject:forBothSidesOfRelationshipWithKey:,
addObject:toBothSidesOfRelationshipWithKey:,
-removeObject:fromBothSidesOfRelationshipWithKey:
o fix compiler warning in
-dictionaryForInstanceProperties, -shallowCopy,
-updateFromSnapshot:, -snapshot
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o replaced isNilOrEONull() by _isNilOrEONull()
o fix in -validateForSave
o rewritten -validateValue:forKey: selector build
* EOControl/EOEditingContext.h:
o added -hasUnprocessedChanges
* EOControl/EOEditingContext.m:
o added -hasUnprocessedChanges
o added NS_DURING,... to catch exceptions
o replace [EOFault isFault:] by _isFault()
o IMP usage optimization
* EOControl/EOKeyGlobalID.m:
o replaced isNilOrEONull() by _isNilOrEONull()
o include <EOCOntrol/EOPriv.h>
* EOControl/EOGenericRecord.m:
o partially rewritten -description
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o changed variable name type of
_infoForInstanceVariableNamed:retType:retSize:retOffset:
o rewritten valueForKey:,... to use cString NSKeyValueCoding
* EOControl/EOKeyValueCoding.m:
o changed NSAssert in NSArray -valueForKey:
o optimization in NSDictionary -takeValue:forKeyPath:isSmart:
o optimization in NSDictionary -takeStoredValue:forKeyPath:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOKeyValueQualifier.m:
o fixes for EONull/nil in -evaluateWithObject:
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOSortOrdering.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAdaptors/Postgres95SQLExpression.m:
o float formatting in +formatValue:forAttribute:
o added -externalNameQuoteCharacter
o added +sqlPatternFromShellPattern:
o added +sqlPatternFromShellPattern:withEscapeCharacter:
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAdaptors/Postgres95Channel.m:
o logs
* EOAdaptors/Postgres95Values.m:
o logs
o fix in +setPostgres95Format:
o fix calendard format to handle timezone (%z)
o optimizations
* EOControl/EOMutableKnownKeyDictionary.m
o removed EOMKKDArrayMapping
+dictionaryFromDictionary:subsetMapping:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOControl/EONSAddOns.[hm]:
o added NSString(ShellPattern)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@20688 72102866-910b-0410-8b05-ffd578937521
2005-02-11 17:37:23 +00:00
|
|
|
EOModel *model=nil;
|
|
|
|
EOAdaptor *adaptor=nil;
|
|
|
|
EOEntity *entity=nil;
|
|
|
|
NSArray *entityNames=nil;
|
|
|
|
unsigned int i=0;
|
|
|
|
int tableNamesCount=[tableNames count];
|
|
|
|
int entityNamesCount=0;
|
2004-02-25 12:27:43 +00:00
|
|
|
|
2004-02-14 02:02:15 +00:00
|
|
|
adaptor = [[self adaptorContext] adaptor];
|
2003-02-03 14:53:03 +00:00
|
|
|
model = AUTORELEASE([[EOModel alloc] init]);
|
2002-11-15 22:57:05 +00:00
|
|
|
|
2004-02-14 02:02:15 +00:00
|
|
|
[model setAdaptorName: [adaptor name]];
|
|
|
|
[model setConnectionDictionary: [adaptor connectionDictionary]];
|
2002-11-15 22:57:05 +00:00
|
|
|
|
COmmit Part 2
* EOAccess/EOAdaptor.m:
o optimization in 'for' loops
* EOAccess/EODatabase.m:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAccess/EODatabaseContext.h:
o added _snapshotForGlobalIDIMP
* EOAccess/EODatabaseContext.m:
o commented NSEmitTODO in
-objectsForSourceGlobalID:relationshipName:editingContext:
o added beter exception format in
qualifierForLockingAttributes:primaryKeyAttributes:entity:snapshot:
o fix compiler warning in -relayPrimaryKey:object:entity:
o logs
o optimizations in -objectsWithFetchSpecification:editingContext:
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o use _snapshotForGlobalIDIMP
o IMP usage optimization
* EOAccess/EOAttribute.[hm]:
o added EOAdaptorUnknownType
o added _adaptorValueType and avoid recomputing it each time
o added _valueTypeChar to avoid string comparaisons
o use EOPriv classes declarations
o Temporary reverted David changes in
-adaptorValueByConvertingAttributeValue
* EOAccess/EOAttributePriv.h:
o added _valueTypeChar to avoid string comparaisons
* EOAccess/EOEntityPriv.h:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.h:
o moved private -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.m:
o better exception in classProperties
o fix compiler warning in -setClassProperties:,
-setPrimaryKeyAttributes:,
-setAttributesUsedForLocking:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLExpression.m:
o optimization in -tableListWithRootEntity:
o optimization in -formatSQLString:format:
o optimization in +sqlPatternFromShellPattern:
o optimization in +sqlPatternFromShellPattern:withEscapeCharacter:
o fix in -sqlStringForKeyValueQualifier:
o added log in -sqlStringForKeyValueQualifier: for not handled
readFormat
o added log -addInsertListAttribute:value: for not handled
writeFormat
o added log -addUpdateListAttribute:value: for not handled
writeFormat
o changed EOFLOGObjectFnStart to EOFLOGObjectFnStartCond
o changed EOFLOGObjectFnStop to EOFLOGObjectFnStopCond
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLQualifier.m:
o implemented EOKeyComparisonQualifier
-schemaBasedQualifierWithRootEntity
* EOAccess/EOUtilities.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOControl/EOPriv.[hm]:
o added. Contains various classes/selectors/IMPs
* EOControl/EOClassDescription.m:
o handle EONull case in -propagateDeleteForObject:editingContext:,
-addObject:toPropertyWithKey:, -snapshot,
-removeObject:fromPropertyWithKey:,
_setObject:forBothSidesOfRelationshipWithKey:,
addObject:toBothSidesOfRelationshipWithKey:,
-removeObject:fromBothSidesOfRelationshipWithKey:
o fix compiler warning in
-dictionaryForInstanceProperties, -shallowCopy,
-updateFromSnapshot:, -snapshot
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o replaced isNilOrEONull() by _isNilOrEONull()
o fix in -validateForSave
o rewritten -validateValue:forKey: selector build
* EOControl/EOEditingContext.h:
o added -hasUnprocessedChanges
* EOControl/EOEditingContext.m:
o added -hasUnprocessedChanges
o added NS_DURING,... to catch exceptions
o replace [EOFault isFault:] by _isFault()
o IMP usage optimization
* EOControl/EOKeyGlobalID.m:
o replaced isNilOrEONull() by _isNilOrEONull()
o include <EOCOntrol/EOPriv.h>
* EOControl/EOGenericRecord.m:
o partially rewritten -description
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o changed variable name type of
_infoForInstanceVariableNamed:retType:retSize:retOffset:
o rewritten valueForKey:,... to use cString NSKeyValueCoding
* EOControl/EOKeyValueCoding.m:
o changed NSAssert in NSArray -valueForKey:
o optimization in NSDictionary -takeValue:forKeyPath:isSmart:
o optimization in NSDictionary -takeStoredValue:forKeyPath:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOKeyValueQualifier.m:
o fixes for EONull/nil in -evaluateWithObject:
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOSortOrdering.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAdaptors/Postgres95SQLExpression.m:
o float formatting in +formatValue:forAttribute:
o added -externalNameQuoteCharacter
o added +sqlPatternFromShellPattern:
o added +sqlPatternFromShellPattern:withEscapeCharacter:
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAdaptors/Postgres95Channel.m:
o logs
* EOAdaptors/Postgres95Values.m:
o logs
o fix in +setPostgres95Format:
o fix calendard format to handle timezone (%z)
o optimizations
* EOControl/EOMutableKnownKeyDictionary.m
o removed EOMKKDArrayMapping
+dictionaryFromDictionary:subsetMapping:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOControl/EONSAddOns.[hm]:
o added NSString(ShellPattern)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@20688 72102866-910b-0410-8b05-ffd578937521
2005-02-11 17:37:23 +00:00
|
|
|
for (i = 0; i < tableNamesCount; i++)
|
2002-11-15 22:57:05 +00:00
|
|
|
{
|
2004-02-25 12:27:43 +00:00
|
|
|
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
|
|
|
NSString *name;
|
2004-02-14 02:02:15 +00:00
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
NS_DURING
|
|
|
|
name = [tableNames objectAtIndex: i];
|
|
|
|
[self _describeBasicEntityWithName: name forModel: model];
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
RETAIN(localException);
|
|
|
|
[pool release];
|
|
|
|
[AUTORELEASE(localException) raise];
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER
|
2004-02-14 02:02:15 +00:00
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
[pool release];
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
2004-02-25 12:27:43 +00:00
|
|
|
|
|
|
|
/* <foreign key stuff> */
|
|
|
|
entityNames = [model entityNames];
|
COmmit Part 2
* EOAccess/EOAdaptor.m:
o optimization in 'for' loops
* EOAccess/EODatabase.m:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAccess/EODatabaseContext.h:
o added _snapshotForGlobalIDIMP
* EOAccess/EODatabaseContext.m:
o commented NSEmitTODO in
-objectsForSourceGlobalID:relationshipName:editingContext:
o added beter exception format in
qualifierForLockingAttributes:primaryKeyAttributes:entity:snapshot:
o fix compiler warning in -relayPrimaryKey:object:entity:
o logs
o optimizations in -objectsWithFetchSpecification:editingContext:
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o use _snapshotForGlobalIDIMP
o IMP usage optimization
* EOAccess/EOAttribute.[hm]:
o added EOAdaptorUnknownType
o added _adaptorValueType and avoid recomputing it each time
o added _valueTypeChar to avoid string comparaisons
o use EOPriv classes declarations
o Temporary reverted David changes in
-adaptorValueByConvertingAttributeValue
* EOAccess/EOAttributePriv.h:
o added _valueTypeChar to avoid string comparaisons
* EOAccess/EOEntityPriv.h:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.h:
o moved private -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.m:
o better exception in classProperties
o fix compiler warning in -setClassProperties:,
-setPrimaryKeyAttributes:,
-setAttributesUsedForLocking:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLExpression.m:
o optimization in -tableListWithRootEntity:
o optimization in -formatSQLString:format:
o optimization in +sqlPatternFromShellPattern:
o optimization in +sqlPatternFromShellPattern:withEscapeCharacter:
o fix in -sqlStringForKeyValueQualifier:
o added log in -sqlStringForKeyValueQualifier: for not handled
readFormat
o added log -addInsertListAttribute:value: for not handled
writeFormat
o added log -addUpdateListAttribute:value: for not handled
writeFormat
o changed EOFLOGObjectFnStart to EOFLOGObjectFnStartCond
o changed EOFLOGObjectFnStop to EOFLOGObjectFnStopCond
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLQualifier.m:
o implemented EOKeyComparisonQualifier
-schemaBasedQualifierWithRootEntity
* EOAccess/EOUtilities.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOControl/EOPriv.[hm]:
o added. Contains various classes/selectors/IMPs
* EOControl/EOClassDescription.m:
o handle EONull case in -propagateDeleteForObject:editingContext:,
-addObject:toPropertyWithKey:, -snapshot,
-removeObject:fromPropertyWithKey:,
_setObject:forBothSidesOfRelationshipWithKey:,
addObject:toBothSidesOfRelationshipWithKey:,
-removeObject:fromBothSidesOfRelationshipWithKey:
o fix compiler warning in
-dictionaryForInstanceProperties, -shallowCopy,
-updateFromSnapshot:, -snapshot
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o replaced isNilOrEONull() by _isNilOrEONull()
o fix in -validateForSave
o rewritten -validateValue:forKey: selector build
* EOControl/EOEditingContext.h:
o added -hasUnprocessedChanges
* EOControl/EOEditingContext.m:
o added -hasUnprocessedChanges
o added NS_DURING,... to catch exceptions
o replace [EOFault isFault:] by _isFault()
o IMP usage optimization
* EOControl/EOKeyGlobalID.m:
o replaced isNilOrEONull() by _isNilOrEONull()
o include <EOCOntrol/EOPriv.h>
* EOControl/EOGenericRecord.m:
o partially rewritten -description
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o changed variable name type of
_infoForInstanceVariableNamed:retType:retSize:retOffset:
o rewritten valueForKey:,... to use cString NSKeyValueCoding
* EOControl/EOKeyValueCoding.m:
o changed NSAssert in NSArray -valueForKey:
o optimization in NSDictionary -takeValue:forKeyPath:isSmart:
o optimization in NSDictionary -takeStoredValue:forKeyPath:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOKeyValueQualifier.m:
o fixes for EONull/nil in -evaluateWithObject:
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOSortOrdering.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAdaptors/Postgres95SQLExpression.m:
o float formatting in +formatValue:forAttribute:
o added -externalNameQuoteCharacter
o added +sqlPatternFromShellPattern:
o added +sqlPatternFromShellPattern:withEscapeCharacter:
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAdaptors/Postgres95Channel.m:
o logs
* EOAdaptors/Postgres95Values.m:
o logs
o fix in +setPostgres95Format:
o fix calendard format to handle timezone (%z)
o optimizations
* EOControl/EOMutableKnownKeyDictionary.m
o removed EOMKKDArrayMapping
+dictionaryFromDictionary:subsetMapping:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOControl/EONSAddOns.[hm]:
o added NSString(ShellPattern)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@20688 72102866-910b-0410-8b05-ffd578937521
2005-02-11 17:37:23 +00:00
|
|
|
entityNamesCount=[entityNames count];
|
|
|
|
for (i = 0; i < entityNamesCount; i++)
|
2004-02-14 02:02:15 +00:00
|
|
|
{
|
2004-02-25 12:27:43 +00:00
|
|
|
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
|
|
|
NSString *entityName;
|
2004-02-14 02:02:15 +00:00
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
NS_DURING
|
|
|
|
entityName = [entityNames objectAtIndex:i];
|
|
|
|
entity = [model entityNamed: entityName];
|
|
|
|
[self _describeForeignKeysForEntity: entity forModel: model];
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
RETAIN(localException);
|
|
|
|
[pool release];
|
|
|
|
[AUTORELEASE(localException) raise];
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER
|
|
|
|
|
|
|
|
[pool release];
|
|
|
|
}
|
2004-05-15 13:07:52 +00:00
|
|
|
|
COmmit Part 2
* EOAccess/EOAdaptor.m:
o optimization in 'for' loops
* EOAccess/EODatabase.m:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAccess/EODatabaseContext.h:
o added _snapshotForGlobalIDIMP
* EOAccess/EODatabaseContext.m:
o commented NSEmitTODO in
-objectsForSourceGlobalID:relationshipName:editingContext:
o added beter exception format in
qualifierForLockingAttributes:primaryKeyAttributes:entity:snapshot:
o fix compiler warning in -relayPrimaryKey:object:entity:
o logs
o optimizations in -objectsWithFetchSpecification:editingContext:
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o use _snapshotForGlobalIDIMP
o IMP usage optimization
* EOAccess/EOAttribute.[hm]:
o added EOAdaptorUnknownType
o added _adaptorValueType and avoid recomputing it each time
o added _valueTypeChar to avoid string comparaisons
o use EOPriv classes declarations
o Temporary reverted David changes in
-adaptorValueByConvertingAttributeValue
* EOAccess/EOAttributePriv.h:
o added _valueTypeChar to avoid string comparaisons
* EOAccess/EOEntityPriv.h:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.h:
o moved private -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
* EOAccess/EOEntity.m:
o better exception in classProperties
o fix compiler warning in -setClassProperties:,
-setPrimaryKeyAttributes:,
-setAttributesUsedForLocking:
o moved -attributeForPath: and -relationshipForPath: to
EOEntityGDL2Additions category
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLExpression.m:
o optimization in -tableListWithRootEntity:
o optimization in -formatSQLString:format:
o optimization in +sqlPatternFromShellPattern:
o optimization in +sqlPatternFromShellPattern:withEscapeCharacter:
o fix in -sqlStringForKeyValueQualifier:
o added log in -sqlStringForKeyValueQualifier: for not handled
readFormat
o added log -addInsertListAttribute:value: for not handled
writeFormat
o added log -addUpdateListAttribute:value: for not handled
writeFormat
o changed EOFLOGObjectFnStart to EOFLOGObjectFnStartCond
o changed EOFLOGObjectFnStop to EOFLOGObjectFnStopCond
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAccess/EOSQLQualifier.m:
o implemented EOKeyComparisonQualifier
-schemaBasedQualifierWithRootEntity
* EOAccess/EOUtilities.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOControl/EOPriv.[hm]:
o added. Contains various classes/selectors/IMPs
* EOControl/EOClassDescription.m:
o handle EONull case in -propagateDeleteForObject:editingContext:,
-addObject:toPropertyWithKey:, -snapshot,
-removeObject:fromPropertyWithKey:,
_setObject:forBothSidesOfRelationshipWithKey:,
addObject:toBothSidesOfRelationshipWithKey:,
-removeObject:fromBothSidesOfRelationshipWithKey:
o fix compiler warning in
-dictionaryForInstanceProperties, -shallowCopy,
-updateFromSnapshot:, -snapshot
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o replaced isNilOrEONull() by _isNilOrEONull()
o fix in -validateForSave
o rewritten -validateValue:forKey: selector build
* EOControl/EOEditingContext.h:
o added -hasUnprocessedChanges
* EOControl/EOEditingContext.m:
o added -hasUnprocessedChanges
o added NS_DURING,... to catch exceptions
o replace [EOFault isFault:] by _isFault()
o IMP usage optimization
* EOControl/EOKeyGlobalID.m:
o replaced isNilOrEONull() by _isNilOrEONull()
o include <EOCOntrol/EOPriv.h>
* EOControl/EOGenericRecord.m:
o partially rewritten -description
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
o replace [EOFault isFault:] by _isFault()
o changed variable name type of
_infoForInstanceVariableNamed:retType:retSize:retOffset:
o rewritten valueForKey:,... to use cString NSKeyValueCoding
* EOControl/EOKeyValueCoding.m:
o changed NSAssert in NSArray -valueForKey:
o optimization in NSDictionary -takeValue:forKeyPath:isSmart:
o optimization in NSDictionary -takeStoredValue:forKeyPath:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOKeyValueQualifier.m:
o fixes for EONull/nil in -evaluateWithObject:
o replaced [EONull null] by GDL2EONull
o include <EOCOntrol/EOPriv.h>
* EOControl/EOSortOrdering.m:
o include <EOCOntrol/EOPriv.h>
o replaced [EONull null] by GDL2EONull
* EOAdaptors/Postgres95SQLExpression.m:
o float formatting in +formatValue:forAttribute:
o added -externalNameQuoteCharacter
o added +sqlPatternFromShellPattern:
o added +sqlPatternFromShellPattern:withEscapeCharacter:
o replaced isNilOrEONull() by _isNilOrEONull()
* EOAdaptors/Postgres95Channel.m:
o logs
* EOAdaptors/Postgres95Values.m:
o logs
o fix in +setPostgres95Format:
o fix calendard format to handle timezone (%z)
o optimizations
* EOControl/EOMutableKnownKeyDictionary.m
o removed EOMKKDArrayMapping
+dictionaryFromDictionary:subsetMapping:
o include <EOCOntrol/EOPriv.h>
o replaced isNilOrEONull() by _isNilOrEONull()
* EOControl/EONSAddOns.[hm]:
o added NSString(ShellPattern)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@20688 72102866-910b-0410-8b05-ffd578937521
2005-02-11 17:37:23 +00:00
|
|
|
for (i=0; i < entityNamesCount; i++)
|
2004-05-15 13:07:52 +00:00
|
|
|
{
|
|
|
|
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
|
|
|
NSMutableArray *classProperties;
|
|
|
|
|
|
|
|
entity = [model entityNamed:[entityNames objectAtIndex:i]];
|
|
|
|
classProperties = [NSMutableArray arrayWithArray:[entity attributes]];
|
|
|
|
[classProperties removeObjectsInArray: [entity primaryKeyAttributes]];
|
|
|
|
[entity setClassProperties: classProperties];
|
|
|
|
|
|
|
|
[pool release];
|
|
|
|
}
|
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
[model beautifyNames];
|
2004-02-14 02:02:15 +00:00
|
|
|
return model;
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
|
2004-03-06 11:12:49 +00:00
|
|
|
/* extensions for login panel */
|
|
|
|
- (NSArray *)describeDatabaseNames
|
|
|
|
{
|
|
|
|
NSMutableArray *databaseNames = [NSMutableArray array];
|
|
|
|
NSString *stmt = [NSS_SWF:@"SELECT datname FROM pg_database LEFT JOIN pg_user "
|
|
|
|
@"ON datdba = usesysid ORDER BY 1"];
|
|
|
|
int i;
|
|
|
|
_pgResult = PQexec(_pgConn, [stmt cString]);
|
|
|
|
for (i=0; i < PQntuples(_pgResult); i++)
|
|
|
|
{
|
|
|
|
[databaseNames addObject: [NSString stringWithCString:PQgetvalue(_pgResult,i,0)]];
|
|
|
|
}
|
|
|
|
return (NSArray *)databaseNames;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) userNameIsAdministrative:(NSString *)userName
|
|
|
|
{
|
|
|
|
NSString *stmt = [NSS_SWF:@"SELECT usecreatedb FROM pg_user WHERE "
|
|
|
|
@"usename = '%@'",userName];
|
|
|
|
_pgResult = PQexec(_pgConn, [stmt cString]);
|
|
|
|
if (_pgResult != NULL)
|
|
|
|
if (PQntuples(_pgResult))
|
|
|
|
{
|
|
|
|
const char *bytes;
|
|
|
|
|
|
|
|
bytes = PQgetvalue(_pgResult,0,0);
|
|
|
|
if (((char *)bytes)[0] == 't' && ((char *)bytes)[1] == 0)
|
|
|
|
return YES;
|
|
|
|
if (((char *)bytes)[0] == 'f' && ((char *)bytes)[1] == 0)
|
|
|
|
return NO;
|
|
|
|
|
|
|
|
}
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2002-11-15 22:57:05 +00:00
|
|
|
- (void)setDelegate:delegate
|
|
|
|
{
|
|
|
|
[super setDelegate: delegate];
|
|
|
|
|
2006-09-15 12:05:56 +00:00
|
|
|
_postgresDelegateRespondsTo.postgresInsertedRowOid =
|
2002-11-15 22:57:05 +00:00
|
|
|
[delegate respondsToSelector:
|
2006-09-15 12:05:56 +00:00
|
|
|
@selector(postgresChannel:insertedRowWithOid:)];
|
|
|
|
_postgresDelegateRespondsTo.postgresNotification =
|
2002-11-15 22:57:05 +00:00
|
|
|
[delegate respondsToSelector:
|
2006-09-15 12:05:56 +00:00
|
|
|
@selector(postgresChannel:receivedNotification:)];
|
2002-11-15 22:57:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)entity
|
|
|
|
{
|
|
|
|
//entity primaryKeyAttributes
|
|
|
|
//self adaptorContext
|
|
|
|
//on each attr attr: adaptorValueType
|
|
|
|
//entty externalName
|
|
|
|
//context autoBeginTransaction
|
|
|
|
//self cleanupFetch######
|
|
|
|
//attr name
|
|
|
|
//dictionary with...
|
|
|
|
NSDictionary *pk = nil;
|
|
|
|
NSString *sqlString;
|
|
|
|
NSString *key = nil;
|
|
|
|
NSNumber *pkValue = nil;
|
|
|
|
const char *string = NULL;
|
|
|
|
int length = 0;
|
|
|
|
NSString *primaryKeySequenceNameFormat;
|
|
|
|
NSString *sequenceName;
|
2004-02-25 12:27:43 +00:00
|
|
|
EOSQLExpression *expr;
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
primaryKeySequenceNameFormat
|
2006-09-15 13:01:07 +00:00
|
|
|
= [(PostgreSQLContext*)[self adaptorContext] primaryKeySequenceNameFormat];
|
2002-11-15 22:57:05 +00:00
|
|
|
NSAssert(primaryKeySequenceNameFormat, @"No primary sequence name format");
|
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
expr = AUTORELEASE([[[_adaptorContext adaptor] expressionClass] new]);
|
2002-11-15 22:57:05 +00:00
|
|
|
sequenceName = [NSString stringWithFormat: primaryKeySequenceNameFormat,
|
2005-04-19 14:14:37 +00:00
|
|
|
[entity primaryKeyRootName]];
|
2004-02-25 12:27:43 +00:00
|
|
|
sequenceName = [expr sqlStringForSchemaObjectName: sequenceName];
|
2002-11-15 22:57:05 +00:00
|
|
|
sqlString = [NSString stringWithFormat: @"SELECT nextval('%@')",
|
|
|
|
sequenceName];
|
2004-02-25 12:27:43 +00:00
|
|
|
[expr setStatement: sqlString];
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
[self _cancelResults];
|
|
|
|
[_adaptorContext autoBeginTransaction: NO];
|
|
|
|
|
2004-02-25 12:27:43 +00:00
|
|
|
[self _evaluateExpression: expr
|
2002-11-15 22:57:05 +00:00
|
|
|
withAttributes: _pkAttributeArray];
|
|
|
|
|
|
|
|
if ([self isFetchInProgress] == NO
|
|
|
|
|| [self advanceRow] == NO)
|
|
|
|
{
|
|
|
|
[self _cancelResults];
|
|
|
|
[_adaptorContext autoCommitTransaction];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-02-19 12:13:22 +00:00
|
|
|
EOAttribute *attr;
|
2002-11-15 22:57:05 +00:00
|
|
|
string = PQgetvalue(_pgResult, _currentResultRow, 0);
|
|
|
|
length = PQgetlength(_pgResult, _currentResultRow, 0);
|
|
|
|
|
2005-02-19 12:13:22 +00:00
|
|
|
attr = [_pkAttributeArray objectAtIndex: 0];
|
2006-09-15 13:01:07 +00:00
|
|
|
pkValue = AUTORELEASE(PSQLA_PostgreSQLValues_newValueForBytesLengthAttribute(string,length,attr));
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
NSAssert(pkValue, @"no pk value");
|
|
|
|
key = [[entity primaryKeyAttributeNames] objectAtIndex: 0];
|
|
|
|
NSAssert(key, @"pk key");
|
|
|
|
|
|
|
|
[self _cancelResults];
|
|
|
|
[_adaptorContext autoCommitTransaction];
|
|
|
|
|
|
|
|
pk = [NSDictionary dictionaryWithObject: pkValue
|
|
|
|
forKey: key];
|
|
|
|
}
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
|
|
|
|
return pk;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)cleanupFetch
|
|
|
|
{
|
2006-09-15 13:01:07 +00:00
|
|
|
PostgreSQLContext *adaptorContext;
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
adaptorContext = (PostgreSQLContext *)[self adaptorContext];
|
2002-11-15 22:57:05 +00:00
|
|
|
|
|
|
|
NSDebugMLog(@"[self isFetchInProgress]=%s",
|
|
|
|
([self isFetchInProgress] ? "YES" : "NO"));
|
|
|
|
|
|
|
|
if ([self isFetchInProgress])
|
|
|
|
{
|
|
|
|
BOOL ok;
|
|
|
|
|
|
|
|
[self _cancelResults];
|
|
|
|
|
|
|
|
ok = [adaptorContext autoCommitTransaction];
|
|
|
|
//_isTransactionstarted to 0
|
|
|
|
//_evaluationIsDirectCalled=0
|
|
|
|
}
|
|
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
}
|
|
|
|
|
2006-09-15 13:01:07 +00:00
|
|
|
@end /* PostgreSQLChannel */
|