aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks
diff options
context:
space:
mode:
authorstuconnolly <stuart02@gmail.com>2009-07-21 16:47:11 +0000
committerstuconnolly <stuart02@gmail.com>2009-07-21 16:47:11 +0000
commit8b8f3e6cea540b17262aadf6d97a8ad28fe41c03 (patch)
treead6bb7f53b03924aa24d0cf5822a27b3bd453592 /Frameworks
parent383863f98dfc488db0181e01d39da1bb025d421b (diff)
downloadsequelpro-8b8f3e6cea540b17262aadf6d97a8ad28fe41c03.tar.gz
sequelpro-8b8f3e6cea540b17262aadf6d97a8ad28fe41c03.tar.bz2
sequelpro-8b8f3e6cea540b17262aadf6d97a8ad28fe41c03.zip
Merge framework integration branch back to trunk. Summary of changes:
- Includes all custom code from subclasses CMMCPConnection and CMMCPResult, meaning they have subsequently been removed from the project. - All previous Sequel Pro specific code in the above subclasses has been removed in favour of the delegate (currently set to TableDocumet) informing the framework of such information. - All references to CMMCPConnection and CMMCPResult have subsequently been changed to MCPConnection and MCPResult. - Framework includes MySQL 5.1.36 client libraries and source headers. - Framework is now built as a 4-way (32/64 bit, i386/PPC arch) binary. - All import references to <MCPKit_bundled/MCPKit_bundled.h> have been changed to <MCPKit/MCPKit.h>. - New script 'build-mysql-client.sh' can be used to build the MySQL client libraries from the MySQL source. See the script's header for a list of available options or run it with no arguments to display it's usage. Note that there are still a few changes to be made to the framework with regard to removing Sequel Pro specific calls to the delegate. These however can be made later on as they have no effect on functionality and are merely design changes. Also, note that any future development done on the framework should be made to be as 'generic' as possible, with no Sequel Pro specific references. This should allow the framework to be integrated into another project without the need for SP specific code.
Diffstat (limited to 'Frameworks')
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPAttribute.h)66
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.m466
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+MCPEntreprise.h47
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+MCPEntreprise.m186
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+Private.h45
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPClassDescription.h)52
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription.m372
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPEntrepriseNotifications.h36
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPEntrepriseNotifications.m34
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPJoin.h74
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPJoin.m183
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPModel+MCPEntreprise.h35
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPModel+MCPEntreprise.m57
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPModel.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPModel.h)44
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPModel.m230
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPObject.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPObject.h)46
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPObject.m1337
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation+Private.h46
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPRelation.h)55
-rw-r--r--Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation.m486
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h226
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m1995
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPConnectionProxy.h70
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPConstants.h64
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPFastQueries.h46
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPFastQueries.m113
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPKit.h40
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPNull.h35
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPNull.m41
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPNumber.h83
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPNumber.m301
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPResult.h85
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPResult.m1360
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPResultPlus.h42
-rw-r--r--Frameworks/MCPKit/MCPFoundationKit/MCPResultPlus.m188
-rw-r--r--Frameworks/MCPKit/MySQL/include/my_alloc.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/my_alloc.h)9
-rw-r--r--Frameworks/MCPKit/MySQL/include/my_list.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/my_list.h)9
-rw-r--r--Frameworks/MCPKit/MySQL/include/mysql.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql.h)255
-rw-r--r--Frameworks/MCPKit/MySQL/include/mysql_com.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_com.h)207
-rw-r--r--Frameworks/MCPKit/MySQL/include/mysql_embed.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_embed.h)5
-rw-r--r--Frameworks/MCPKit/MySQL/include/mysql_time.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_time.h)5
-rw-r--r--Frameworks/MCPKit/MySQL/include/mysql_version.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_version.h)7
-rw-r--r--Frameworks/MCPKit/MySQL/include/typelib.h (renamed from Frameworks/MCPKit_bundled.framework/Versions/A/Headers/typelib.h)11
-rw-r--r--Frameworks/MCPKit/MySQL/lib/libmysqlclient.abin0 -> 2677984 bytes
-rw-r--r--Frameworks/MCPKit/MySQL/lib/libmysqlclient_r.abin0 -> 2733824 bytes
l---------Frameworks/MCPKit_bundled.framework/Headers1
l---------Frameworks/MCPKit_bundled.framework/MCPKit_bundled1
l---------Frameworks/MCPKit_bundled.framework/PrivateHeaders1
l---------Frameworks/MCPKit_bundled.framework/Resources1
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPClassDescription+MCPEntreprise.h42
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConnection.h158
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConnectionWinCont.h52
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConstants.h33
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPDocument.h95
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPEntrepriseNotifications.h35
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPFastQueries.h47
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPJoin.h68
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPKit_bundled.h38
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPModel+MCPEntreprise.h32
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPNull.h36
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPNumber.h84
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPResult.h110
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPResultPlus.h43
-rwxr-xr-xFrameworks/MCPKit_bundled.framework/Versions/A/MCPKit_bundledbin1748716 -> 0 bytes
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPAttribute+Private.h35
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPClassDescription+Private.h41
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPRelation+Private.h41
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/InfoPlist.stringsbin192 -> 0 bytes
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/JavaCompiling.plist8
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/_MCPConnectionWindow_EOArchive_English.java424
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/classes.nib28
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/info.nib16
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/keyedobjects.nibbin9169 -> 0 bytes
-rw-r--r--Frameworks/MCPKit_bundled.framework/Versions/A/Resources/Info.plist20
l---------Frameworks/MCPKit_bundled.framework/Versions/Current1
75 files changed, 8851 insertions, 1734 deletions
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPAttribute.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.h
index 7044718d..1a474346 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPAttribute.h
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.h
@@ -1,26 +1,30 @@
//
+// $Id: MCPAttribute.h 545 2009-04-10 14:49:45Z stuart02 $
+//
// MCPAttribute.h
-// MCPModeler
+// MCPKit
//
// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
//
-// This code 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 General Public License for more
-// details.
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
+// This program 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 General Public License for more details.
//
-// More info at <http://mysql-cocoa.sourceforge.net/>
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
#import <Foundation/Foundation.h>
@@ -29,24 +33,23 @@
@class MCPRelation;
@class MCPJoin;
-
-@interface MCPAttribute : NSObject < NSCoding > {
+@interface MCPAttribute : NSObject < NSCoding >
+{
@protected
- MCPClassDescription *classDescription; // ClassDescription of which the attribute is attribute
- NSString *name; // Name of the attribute (Obj-C side)
- Class valueClass; // Class used by the attribute (or NULL if the internal type is not an object)
- NSString *internalType; // Name of the class, or type used for the class definition
- NSString *externalName; // Name of the corresponding column in the DB
- NSString *externalType; // Type used to store the attribute (in the DB)
- unsigned int width; // Width (for storing by the DB)
- BOOL allowsNull; // Attribute can be null
- BOOL autoGenerated; // Attribute is auto generated by the DB
- BOOL isPartOfKey; // Attribute is part of theprimary key of the class description
- BOOL isPartOfIdentity; // Attribute is part of the idclass description of the class description
- BOOL hasAccessor; // Does this attribute have an accessor
- id defaultValue; // Default value of the attribute
- NSMutableArray *joins; // An array of the joins using this attribute
-// NSMutableArray *relations; // An array of the relations (MCPRelation) that use this attribue as join
+ MCPClassDescription *classDescription; // ClassDescription of which the attribute is attribute
+ NSString *name; // Name of the attribute (Obj-C side)
+ Class valueClass; // Class used by the attribute (or NULL if the internal type is not an object)
+ NSString *internalType; // Name of the class, or type used for the class definition
+ NSString *externalName; // Name of the corresponding column in the DB
+ NSString *externalType; // Type used to store the attribute (in the DB)
+ unsigned int width; // Width (for storing by the DB)
+ BOOL allowsNull; // Attribute can be null
+ BOOL autoGenerated; // Attribute is auto generated by the DB
+ BOOL isPartOfKey; // Attribute is part of theprimary key of the class description
+ BOOL isPartOfIdentity; // Attribute is part of the idclass description of the class description
+ BOOL hasAccessor; // Does this attribute have an accessor
+ id defaultValue; // Default value of the attribute
+ NSMutableArray *joins; // An array of the joins using this attribute
}
#pragma mark Class methods
@@ -100,5 +103,4 @@
#pragma mark Some general methods:
- (BOOL) isEqual:(id) iObject;
-
@end
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.m b/Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.m
new file mode 100644
index 00000000..34b50284
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPAttribute.m
@@ -0,0 +1,466 @@
+//
+// $Id: MCPAttribute.m 927 2009-06-24 10:53:07Z stuart02 $
+//
+// MCPAttribute.m
+// MCPkit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPAttribute.h"
+
+#import "MCPEntrepriseNotifications.h"
+
+#import "MCPModel.h"
+#import "MCPClassDescription.h"
+#import "MCPRelation.h"
+#import "MCPJoin.h"
+
+static NSArray *MCPRecognisedInternalType;
+
+@interface MCPAttribute (Private)
+
+- (void)setValueClassName:(NSString *) iClassName;
+
+@end
+
+@implementation MCPAttribute
+
+#pragma mark Class methods
++ (void) initialize
+{
+ if (self == [MCPAttribute class]) {
+ [self setVersion:010101]; // Ma.Mi.Re -> MaMiRe
+ MCPRecognisedInternalType = [[NSArray alloc] initWithObjects:@"NSCalendarDate", @"NSData", @"NSNumber", @"NSString", nil];
+ [self setKeys:[NSArray arrayWithObject:@"internalType"] triggerChangeNotificationsForDependentKey:@"valueClassName"];
+ [self setKeys:[NSArray arrayWithObject:@"valueClassName"] triggerChangeNotificationsForDependentKey:@"internalType"];
+ }
+ return;
+}
+
+
+#pragma mark Life cycle
+- (id) initForClassDescription:(MCPClassDescription *) iClassDescription withName:(NSString *) iName
+{
+ self = [super init];
+ {
+ classDescription = iClassDescription;
+ [self setName:iName];
+// relations = (NSMutableArray *)(CFArrayCreateMutable (kCFAllocatorDefault, 0, NULL));
+ joins = [[NSMutableArray alloc] init];
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+// NSArray *theRelations;
+// unsigned int i;
+
+ [name release];
+ [internalType release];
+ [externalName release];
+ [externalType release];
+ [defaultValue release];
+/*
+ while ([relations count]) {
+ [(MCPRelation *)[relations objectAtIndex:0] unjoinAttribute:self];
+ }
+// By now relation should be empty anyway...
+ [relations release];
+ */
+ while ([joins count]) {
+ [[self objectInJoinsAtIndex:0] invalidate];
+ }
+ // By now the joins array should be empty
+ [joins release];
+ [super dealloc];
+}
+
+
+#pragma mark NSCoding protocol
+- (id) initWithCoder:(NSCoder *) decoder
+{
+ self = [super init];
+ if ((self) && ([decoder allowsKeyedCoding])) {
+ NSString *theClassName = [decoder decodeObjectForKey:@"MCPvalueClassName"];
+
+ classDescription = [decoder decodeObjectForKey:@"MCPclassDescription"];
+ [self setName:[decoder decodeObjectForKey:@"MCPname"]];
+ if (theClassName) {
+ [self setValueClass:NSClassFromString(theClassName)];
+ }
+ [self setInternalType:[decoder decodeObjectForKey:@"MCPinternalType"]];
+ [self setExternalName:[decoder decodeObjectForKey:@"MCPexternalName"]];
+ [self setExternalType:[decoder decodeObjectForKey:@"MCPexternalType"]];
+ [self setWidth:(unsigned int)[decoder decodeInt32ForKey:@"MCPwidth"]];
+ [self setAllowsNull:[decoder decodeBoolForKey:@"MCPallowsNull"]];
+ [self setAutoGenerated:[decoder decodeBoolForKey:@"MCPautoGenerated"]];
+ [self setIsPartOfKey:[decoder decodeBoolForKey:@"MCPisPartOfKey"]];
+ [self setIsPartOfIdentity:[decoder decodeBoolForKey:@"MCPisPartOfIdentity"]];
+ [self setHasAccessor:[decoder decodeBoolForKey:@"MCPhasAccessor"]];
+ [self setDefaultValue:[decoder decodeObjectForKey:@"MCPdefaultValue"]];
+// Not sure that the next line is working (getting an array holding weak references), hence doing the thing expelcitly:
+// relations = [[decoder decodeObjectForKey:@"MCPrelations"] retain];
+// relations = (NSMutableArray *)(CFArrayCreateMutable (kCFAllocatorDefault, 0, NULL));
+// [relations addObjectsFromArray:[decoder decodeObjectForKey:@"MCPrelations"]];
+ joins = [[NSMutableArray alloc] init]; // Will be filled in when the relations are read in.
+ }
+ else {
+ NSLog(@"For some reason, unable to decode MCPAttribute from the coder!!!");
+ }
+// NSLog(@"MAKING a new object : %@", self);
+ return self;
+}
+
+- (void) encodeWithCoder:(NSCoder *) encoder
+{
+ NSString *theValueClassName;
+
+ if (! [encoder allowsKeyedCoding]) {
+ NSLog(@"In MCPAttribute -encodeWithCoder : Unable to encode to a non-keyed encoder!!, will not perform encoding!!");
+ return;
+ }
+// theValueClassName = (valueClass) ? [valueClass className] : nil;
+ theValueClassName = (valueClass) ? NSStringFromClass(valueClass) : nil;
+ [encoder encodeObject:[self classDescription] forKey:@"MCPclassDescription"];
+ [encoder encodeObject:[self name] forKey:@"MCPname"];
+ if (theValueClassName) {
+ [encoder encodeObject:theValueClassName forKey:@"MCPvalueClassName"];
+ }
+ [encoder encodeObject:[self internalType] forKey:@"MCPinternalType"];
+ [encoder encodeObject:[self externalName] forKey:@"MCPexternalName"];
+ [encoder encodeObject:[self externalType] forKey:@"MCPexternalType"];
+ [encoder encodeInt32:(int32_t)[self width] forKey:@"MCPwidth"];
+ [encoder encodeBool:[self allowsNull] forKey:@"MCPallowsNull"];
+ [encoder encodeBool:[self autoGenerated] forKey:@"MCPautoGenerated"];
+ [encoder encodeBool:[self isPartOfKey] forKey:@"MCPisPartOfKey"];
+ [encoder encodeBool:[self isPartOfIdentity] forKey:@"MCPisPartOfIdentity"];
+ [encoder encodeBool:[self hasAccessor] forKey:@"MCPhasAccessor"];
+ [encoder encodeObject:[self defaultValue] forKey:@"MCPdefaultValue"];
+// [encoder encodeObject:relations forKey:@"MCPrelation"];
+ // We don't have to save the joins here ... the joins are saving there attributes.
+ // The links are recreated when the joins are decoded.
+}
+
+#pragma mark Setters
+- (void) setName:(NSString *) iName
+{
+ if (iName != name) {
+ [name release];
+ name = [iName retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setValueClass:(Class) iValueClass
+{
+ if (iValueClass != valueClass) {
+ valueClass = iValueClass;
+ if (valueClass) { // Not nil : set the internalType accrodingly.
+ // [internalType release];
+ // internalType = [[valueClass className] copy];
+// [self setValue:[NSString stringWithString:[valueClass className]] forKey:@"internalType"];
+ [self setValue:[NSString stringWithString:NSStringFromClass(valueClass)] forKey:@"internalType"];
+ }
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setInternalType:(NSString *) iInternalType
+{
+ if (iInternalType != internalType) {
+ [internalType release];
+ internalType = [iInternalType retain];
+ if ([MCPRecognisedInternalType containsObject:internalType]) {
+ [self setValueClass:NSClassFromString(internalType)];
+// By itself does NOT provide observers the update.
+// but see setKeys:triggerChangeNotificationsForDependentKey... (in +initialize).
+ }
+ else {
+ [self setValueClass:nil];
+ }
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setExternalType:(NSString *) iExternalType
+{
+ if (iExternalType != externalType) {
+ [externalType release];
+ externalType = [iExternalType retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setExternalName:(NSString *) iExternalName
+{
+ if (iExternalName != externalName) {
+ [externalName release];
+ externalName = [iExternalName retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setWidth:(unsigned int) iWidth
+{
+ if (iWidth != width) {
+ width = iWidth;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setAllowsNull:(BOOL) iAllowsNull
+{
+ if (iAllowsNull != allowsNull) {
+ allowsNull = iAllowsNull;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setAutoGenerated:(BOOL) iAutoGenerated
+{
+ if (iAutoGenerated != autoGenerated) {
+ autoGenerated = iAutoGenerated;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setIsPartOfKey:(BOOL) iIsPartOfKey
+{
+ if (iIsPartOfKey != isPartOfKey) {
+ isPartOfKey = iIsPartOfKey;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setIsPartOfIdentity:(BOOL) iIsPartOfIdentity
+{
+ if (iIsPartOfIdentity != isPartOfIdentity) {
+ isPartOfIdentity = iIsPartOfIdentity;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setHasAccessor:(BOOL) iHasAccessor
+{
+ if (iHasAccessor != hasAccessor) {
+ hasAccessor = iHasAccessor;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) setDefaultValue:(id) iDefaultValue
+{
+ if (iDefaultValue != defaultValue) {
+ [defaultValue release];
+ defaultValue = [iDefaultValue retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[classDescription model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:classDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPAttributeChangedNotification object:self];
+ }
+}
+
+- (void) insertObject:(MCPJoin *) iJoin inJoinsAtIndex:(unsigned int) index
+{
+ [joins insertObject:iJoin atIndex:index];
+}
+
+- (void) removeObjectFromJoinsAtIndex:(unsigned int) index
+{
+ [joins removeObjectAtIndex:index];
+}
+
+/*
+- (void) addRelation:(MCPRelation *) iRelation
+{
+// Following implementation make sure that a given relation is only added once... but I don't see the reason for that to be true.
+ /* if (NSNotFound == [relations indexOfObjectIdenticalTo:iRelation]) {
+ [relations addObject:iRelation];
+ }
+ *//*
+ [relations addObject:iRelation];
+}
+
+- (void) removeRelation:(MCPRelation *) iRelation
+{
+// Following implementation needs only one reference to a given relation to be working properly (not true)
+// [relations removeObjectIdenticalTo:iRelation];
+ unsigned int i;
+
+ i = [relations indexOfObjectIdenticalTo:iRelation];
+ if (NSNotFound != i) {
+ [relations removeObjectAtIndex:i];
+ }
+// If the relation is there more than once, remove it only once.
+}
+*/
+
+#pragma mark Getters
+- (MCPClassDescription *) classDescription
+{
+ return classDescription;
+}
+
+- (NSString *) name
+{
+ return name;
+}
+
+- (Class) valueClass
+{
+ return valueClass;
+}
+
+- (NSString *) valueClassName
+{
+ return NSStringFromClass(valueClass);
+}
+
+- (NSString *) internalType
+{
+ return internalType;
+}
+
+- (NSString *) externalName
+{
+ return externalName;
+}
+
+- (NSString *) externalType
+{
+ return externalType;
+}
+
+- (unsigned int) width
+{
+ return width;
+}
+
+- (BOOL) allowsNull
+{
+ return allowsNull;
+}
+
+- (BOOL) autoGenerated
+{
+ return autoGenerated;
+}
+
+- (BOOL) isPartOfKey
+{
+ return isPartOfKey;
+}
+
+- (BOOL) isPartOfIdentity
+{
+ return isPartOfIdentity;
+}
+
+- (BOOL) hasAccessor
+{
+ return hasAccessor;
+}
+
+- (id) defaultValue
+{
+ return defaultValue;
+}
+
+- (unsigned int) countOfJoins
+{
+ return [joins count];
+}
+
+- (MCPJoin *) objectInJoinsAtIndex:(unsigned int) index
+{
+ return (MCPJoin *)((NSNotFound != index) ? [joins objectAtIndex:index] : nil);
+}
+
+- (unsigned int) indexOfJoinIdenticalTo:(id) iJoin
+{
+ return [joins indexOfObjectIdenticalTo:iJoin];
+}
+
+#pragma mark Some general methods:
+- (BOOL) isEqual:(id) iObject
+// Equal to another attribute, if they have the same name and same class description.
+// Equal to a string (NSString), if the name of the attribute is equal to the string.
+{
+ if ([iObject isKindOfClass:[MCPAttribute class]]) {
+ MCPAttribute *theAttribute = (MCPAttribute *) iObject;
+
+ return ([name isEqualToString:[theAttribute name]]) && ([classDescription isEqual:[theAttribute classDescription]]);
+ }
+ if ([iObject isKindOfClass:[NSString class]]) {
+ return [name isEqualToString:(NSString *)iObject];
+ }
+ return NO;
+}
+
+#pragma mark For debugging the retain counting
+- (id) retain
+{
+ [super retain];
+ return self;
+}
+
+- (void) release
+{
+ [super release];
+ return;
+}
+
+@end
+
+@implementation MCPAttribute (Private)
+
+- (void)setValueClassName:(NSString *) iClassName
+{
+ if (NSClassFromString(iClassName) != valueClass) {
+ [self setValueClass:NSClassFromString(iClassName)];
+ }
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+MCPEntreprise.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+MCPEntreprise.h
new file mode 100644
index 00000000..adc66141
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+MCPEntreprise.h
@@ -0,0 +1,47 @@
+//
+// $Id: MCPClassDescription+MCPEntreprise.h 482 2009-04-05 01:38:48Z stuart02 $
+//
+// MCPClassDescription+MCPEntreprise.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 01/11/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+#import "MCPClassDescription.h"
+
+@interface MCPClassDescription (MCPEntreprise)
+
+#pragma mark Pseudo getters (for NSClassDescription overload)
+- (NSArray *) attributeKeys;
+- (NSString *) inverseRelationshipKey:(NSString *) relationshipKey;
+- (NSArray *) toManyRelationshipKeys;
+- (NSArray *) toOneRelationshipKeys;
+
+#pragma mark Specifics for MCPObject
+- (NSArray *) primaryKeyAttributes;
+- (NSArray *) identityAttributes;
+- (MCPAttribute *) attributeWithName: (NSString *) iName;
+- (MCPRelation *) relationWithName:(NSString *) iRelationName;
+- (BOOL) singleIntAutoGenKey;
+
+@end
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+MCPEntreprise.m b/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+MCPEntreprise.m
new file mode 100644
index 00000000..4c912a1f
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+MCPEntreprise.m
@@ -0,0 +1,186 @@
+//
+// $Id: MCPClassDescription+MCPEntreprise.m 927 2009-06-24 10:53:07Z stuart02 $
+//
+// MCPClassDescription+MCPEntreprise.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 01/11/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPClassDescription+MCPEntreprise.h"
+
+#import "MCPAttribute.h"
+#import "MCPRelation.h"
+
+@implementation MCPClassDescription (MCPEntreprise)
+
+#pragma mark Pseudo getters (for NSClassDescription overload)
+- (NSArray *) attributeKeys
+{
+ NSArray *theRet;
+ NSMutableArray *theKeys =[[NSMutableArray alloc] init];
+ unsigned int i;
+
+ for (i=0; i != [self countOfAttributes]; ++i) {
+ [theKeys insertObject:[(MCPAttribute *)[self objectInAttributesAtIndex:i] name] atIndex:i];
+ }
+ theRet = [NSArray arrayWithArray:theKeys];
+ [theKeys release];
+ return theRet;
+}
+
+- (NSString *) inverseRelationshipKey:(NSString *) relationshipKey
+{
+ unsigned int index = [self indexOfRelation:relationshipKey];
+
+ if (NSNotFound != index) {
+ MCPRelation *theRelation;
+
+ theRelation = (MCPRelation *)[self objectInRelationsAtIndex:index];
+ return [[theRelation inverseRelation] name];
+ }
+ return nil;
+}
+
+- (NSArray *) toManyRelationshipKeys
+{
+ NSArray *theRet;
+ NSMutableArray *theToManyRel = [[NSMutableArray alloc] init];
+ unsigned int i, j;
+
+ j=0;
+ for (i=0; i != [self countOfRelations]; ++i) {
+ MCPRelation *theRelation = (MCPRelation *)[self objectInRelationsAtIndex:i];
+
+ if ([theRelation isToMany]) {
+ [theToManyRel insertObject:[theRelation name] atIndex:j];
+ ++j;
+ }
+ }
+ theRet = [NSArray arrayWithArray:theToManyRel];
+ [theToManyRel release];
+ return theRet;
+}
+
+- (NSArray *) toOneRelationshipKeys;
+{
+ NSArray *theRet;
+ NSMutableArray *theToOneRel = [[NSMutableArray alloc] init];
+ unsigned int i, j;
+
+ j=0;
+ for (i=0; i != [self countOfRelations]; ++i) {
+ MCPRelation *theRelation = (MCPRelation *)[self objectInRelationsAtIndex:i];
+
+ if (! [theRelation isToMany]) {
+ [theToOneRel insertObject:[theRelation name] atIndex:j];
+ ++j;
+ }
+ }
+ theRet = [NSArray arrayWithArray:theToOneRel];
+ [theToOneRel release];
+ return theRet;
+}
+
+#pragma mark Specifics for MCPObject
+- (NSArray *) primaryKeyAttributes
+{
+ NSMutableArray *theRet = [NSMutableArray array];
+ unsigned int i, j;
+
+ j = 0;
+ for (i=0; i != [self countOfAttributes]; ++i) {
+ MCPAttribute *theAttribute = (MCPAttribute *)[self objectInAttributesAtIndex:i];
+
+ if ([theAttribute isPartOfKey]) {
+ [theRet insertObject:theAttribute atIndex:j];
+ ++j;
+ }
+ }
+ return (NSArray *)theRet;
+}
+
+- (NSArray *) identityAttributes
+{
+ NSMutableArray *theRet = [NSMutableArray array];
+ unsigned int i, j;
+
+ j = 0;
+ for (i=0; i != [self countOfAttributes]; ++i) {
+ MCPAttribute *theAttribute = (MCPAttribute *)[self objectInAttributesAtIndex:i];
+
+ if ([theAttribute isPartOfIdentity]) {
+ [theRet insertObject:theAttribute atIndex:j];
+ ++j;
+ }
+ }
+ return (NSArray *)theRet;
+}
+
+- (MCPAttribute *) attributeWithName: (NSString *) iName
+{
+// This type of implementation is NOT working : most likely the isEqual method is called on iName rather than on the objects of the array
+/*
+ unsigned int index = [self indexOfAttribute:iName];
+
+ return (NSNotFound != index) ? (MCPAttribute *)[self objectInAttributesAtIndex:index] : nil ;
+*/
+ unsigned int i;
+
+ for (i = 0; [attributes count] != i; ++i) {
+ if ([[(MCPAttribute *)[attributes objectAtIndex:i] name] isEqualToString:iName]) {
+ return (MCPAttribute *)[attributes objectAtIndex:i];
+ }
+ }
+ return nil;
+}
+
+- (MCPRelation *) relationWithName:(NSString *) iRelationName
+{
+// This type of implementation is NOT working : most likely the isEqual method is called on iName rather than on the objects of the array
+/* unsigned int index = [relations indexOfObject:iRelationName];
+
+ return (NSNotFound != index) ? (MCPRelation *)[relations objectAtIndex:index] : nil;
+*/
+ unsigned int i;
+
+ for (i = 0; [relations count] != i; ++i) {
+ if ([[(MCPRelation *)[relations objectAtIndex:i] name] isEqualToString:iRelationName]) {
+ return (MCPRelation *)[relations objectAtIndex:i];
+ }
+ }
+ return nil;
+}
+
+- (BOOL) singleIntAutoGenKey
+{
+ NSArray *theKeys = [self primaryKeyAttributes];
+
+ if (1 == [theKeys count]) {
+ MCPAttribute *theSingleKey = (MCPAttribute *)[theKeys objectAtIndex:0];
+
+ return [theSingleKey autoGenerated] && [[theSingleKey externalType] isEqualToString:@"INT"];
+ }
+ return NO;
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+Private.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+Private.h
new file mode 100644
index 00000000..46c8a626
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription+Private.h
@@ -0,0 +1,45 @@
+//
+// $Id: MCPClassDescription+Private.h 482 2009-04-05 01:38:48Z stuart02 $
+//
+// MCPClassDescription+Private.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPClassDescription.h"
+
+@interface MCPClassDescription (Private)
+
+#pragma mark Setters
+- (void) setAttributes:(NSArray *) iAttributes;
+- (void) setRelations:(NSArray *) iRelations;
+- (void) insertObject:(MCPRelation *) iRelation inIncomingsAtIndex:(unsigned int) index;
+- (void) removeObjectFromIncomingsAtIndex:(unsigned int) index;
+
+#pragma mark Getters
+- (NSArray *) incomings;
+- (unsigned int) countOfIncomings;
+- (MCPRelation *) objectInIncomingsAtIndex:(unsigned int) index;
+- (unsigned int) indexOfIncoming:(id) iRelation;
+
+@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPClassDescription.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription.h
index 26ca382e..c5119797 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPClassDescription.h
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription.h
@@ -1,26 +1,30 @@
//
+// $Id: MCPClassDescription.h 927 2009-06-24 10:53:07Z stuart02 $
+//
// MCPClassDescription.h
-// MCPModeler
+// MCPKit
//
// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
//
-// This code 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 General Public License for more
-// details.
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
+// This program 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 General Public License for more details.
//
-// More info at <http://mysql-cocoa.sourceforge.net/>
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
#import <Foundation/Foundation.h>
@@ -29,18 +33,18 @@
@class MCPRelation;
@class MCPRelation;
-@interface MCPClassDescription : NSClassDescription < NSCoding > {
+@interface MCPClassDescription : NSClassDescription <NSCoding>
+{
@protected
- MCPModel *model; // The model where we stand
- NSString *name; // Name of the class (can not use className, as it is already used by NSObject).
- NSString *externalName; // Name of the table for storage
- NSMutableArray *attributes; // array of the attributes of the class description
- NSMutableArray *relations; // array of the relations of the class description (both origin and destination)
- NSMutableArray *incomings; // array if the INCOMMING relation (just to be sure we are able to invalidate those if necessary)
- Class representedClass; // the class object that the description represents.
+ MCPModel *model; // The model where we stand
+ NSString *name; // Name of the class (can not use className, as it is already used by NSObject).
+ NSString *externalName; // Name of the table for storage
+ NSMutableArray *attributes; // array of the attributes of the class description
+ NSMutableArray *relations; // array of the relations of the class description (both origin and destination)
+ NSMutableArray *incomings; // array if the INCOMMING relation (just to be sure we are able to invalidate those if necessary)
+ Class representedClass; // the class object that the description represents.
}
-#warning hasSingleIntAutoGenKey should be a method returning the obvious (from the name).
// This correspond to the method singleIntAutoGenKey in the category MCPEntreprise... which name should I change...
#pragma mark Class methods
@@ -85,7 +89,5 @@
#pragma mark Output for logging
- (NSString *) descriptionWithLocale:(NSDictionary *) locale;
-//- (NSString *) descriptionWithLocale:(NSDictionary *) locale;
-//- (NSString *) description;
@end
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription.m b/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription.m
new file mode 100644
index 00000000..fcd79e01
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPClassDescription.m
@@ -0,0 +1,372 @@
+//
+// $Id: MCPClassDescription.m 545 2009-04-10 14:49:45Z stuart02 $
+//
+// MCPClassDescription.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPClassDescription.h"
+#import "MCPClassDescription+Private.h"
+
+#import "MCPEntrepriseNotifications.h"
+
+#import "MCPModel.h"
+#import "MCPAttribute.h"
+#import "MCPRelation.h"
+
+@implementation MCPClassDescription
+
+#pragma mark Class methods
++ (void) initialize
+{
+ if (self = [MCPClassDescription class]) {
+ [self setVersion:010101]; // Major.Minor.Revision -> MaMiRe
+ }
+ return;
+}
+
+#pragma mark Life cycle
+- (id) initInModel:(MCPModel *) iModel withName:(NSString *) iName
+{
+ self = [super init];
+ if (self) {
+ model = iModel;
+ [self setName:iName];
+ attributes = [[NSMutableArray alloc] init];
+ relations = [[NSMutableArray alloc] init];
+ incomings = [[NSMutableArray alloc] init];
+ representedClass = nil;
+ // NSLog(@"MAKING a new object : %@", self);
+ }
+ return self;
+}
+
+- (void) dealloc
+{
+// NSArray *theRelations;
+// unsigned int i;
+
+ [name release];
+ [externalName release];
+ [attributes release];
+ while ([relations count]) {
+ [(MCPRelation *)[relations objectAtIndex:0] invalidateRelation];
+ }
+ [relations release];
+ while ([incomings count]) {
+ [(MCPRelation *)[incomings objectAtIndex:0] invalidateRelation];
+ }
+ [incomings release];
+ [super dealloc];
+}
+
+#pragma mark NSCoding protocol
+- (id) initWithCoder:(NSCoder *) decoder
+{
+ self = [super init];
+ if ((self) && ([decoder allowsKeyedCoding])) {
+ model = [decoder decodeObjectForKey:@"MCPmodel"];
+// NSLog(@"in MCPClassDescription initWithCoder, model = %@ (pointer = %p)", model, model);
+ [self setName:[decoder decodeObjectForKey:@"MCPname"]];
+ [self setExternalName:[decoder decodeObjectForKey:@"MCPexternalName"]];
+ [self setAttributes:[decoder decodeObjectForKey:@"MCPattributes"]];
+// [self setRelations:[decoder decodeObjectForKey:@"MCPrelations"]];
+ relations = [[NSMutableArray alloc] init];
+ incomings = [[NSMutableArray alloc] init];
+ representedClass = nil;
+ [decoder decodeObjectForKey:@"MCPrelations"]; // The relation get linked properly while initted.
+ }
+ else {
+ NSLog(@"For some reason, unable to decode MCPClassDescription from the coder!!!");
+ }
+
+ return self;
+}
+
+- (void) encodeWithCoder:(NSCoder *) encoder
+{
+ if (! [encoder allowsKeyedCoding]) {
+ NSLog(@"In MCPClassDescription -encodeWithCoder : Unable to encode to a non-keyed encoder!!, will not perform encoding!!");
+ return;
+ }
+// [encoder encodeObject:[self model] forKey:@"MCPmodel"];
+ [encoder encodeConditionalObject:[self model] forKey:@"MCPmodel"];
+ [encoder encodeObject:[self name] forKey:@"MCPname"];
+ [encoder encodeObject:[self externalName] forKey:@"MCPexternalName"];
+ [encoder encodeObject:[self attributes] forKey:@"MCPattributes"];
+ [encoder encodeObject:[self relations] forKey:@"MCPrelations"];
+ [encoder encodeObject:@"1.1.1" forKey:@"MCPversion"];
+ return;
+}
+
+#pragma mark Making new attributes and relations
+- (MCPAttribute *) addNewAttributeWithName:(NSString *) iName inPosition:(int) index
+{
+ MCPAttribute *theAttribute = [[MCPAttribute alloc] initForClassDescription:self withName:iName];
+
+// [self addAttribute:theAttribute];
+ [self insertObject:theAttribute inAttributesAtIndex:(index < 0) ? ([self countOfAttributes] + index + 1) : index];
+ [theAttribute release];
+ return theAttribute;
+}
+
+- (MCPRelation *) addNewRelationTo:(MCPClassDescription *) iTo name:(NSString *) iName inPostion:(int) index
+{
+ MCPRelation *theRelation = [[MCPRelation alloc] initWithName:iName from:self to:iTo];
+
+ [theRelation release];
+ return theRelation;
+}
+
+#pragma mark Setters
+- (void) setName:(NSString *) iName
+{
+ if (iName != name) {
+ [name release];
+ name = [iName retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:model];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:self];
+ representedClass = nil;
+ }
+}
+
+- (void) setExternalName:(NSString *) iExternalName
+{
+ if (iExternalName != externalName) {
+ [externalName release];
+ externalName = [iExternalName retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:model];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:self];
+ }
+}
+
+- (void) insertObject:(MCPAttribute *) iAttribute inAttributesAtIndex:(unsigned int) index
+{
+ [attributes insertObject:iAttribute atIndex:index];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:model];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:self];
+}
+
+- (void) removeObjectFromAttributesAtIndex:(unsigned int) index
+{
+ [attributes removeObjectAtIndex:index];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:model];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:self];
+}
+
+- (void) insertObject:(MCPRelation *) iRelation inRelationsAtIndex:(unsigned int) index
+{
+ [relations insertObject:iRelation atIndex:index];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:model];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:self];
+}
+
+- (void) removeObjectFromRelationsAtIndex:(unsigned int) index
+{
+ [relations removeObjectAtIndex:index];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:model];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:self];
+}
+
+#pragma mark Getters
+- (MCPModel *) model
+{
+ return model;
+}
+
+- (NSString *) name
+{
+ return name;
+}
+
+- (NSString *) externalName
+{
+ return externalName;
+}
+
+- (NSArray *) attributes
+{
+ return [NSArray arrayWithArray:attributes];
+}
+
+- (unsigned int) countOfAttributes
+{
+ return [attributes count];
+}
+
+- (MCPAttribute *) objectInAttributesAtIndex:(unsigned int) index
+{
+ return (MCPAttribute *)((NSNotFound != index) ? [attributes objectAtIndex:index] : nil);
+}
+
+- (unsigned int) indexOfAttribute:(id) iAttribute
+{
+ return [attributes indexOfObject:iAttribute];
+}
+
+- (NSArray *) relations
+{
+ return [NSArray arrayWithArray:relations];
+}
+
+- (unsigned int) countOfRelations
+{
+ return [relations count];
+}
+
+- (MCPRelation *) objectInRelationsAtIndex:(unsigned int) index
+{
+ return (MCPRelation *)((NSNotFound != index) ? [relations objectAtIndex:index] : nil);
+}
+
+- (unsigned int) indexOfRelation:(id) iRelation
+{
+ return [relations indexOfObject:iRelation];
+}
+
+- (Class) representedClass
+{
+ if (representedClass) {
+ return representedClass;
+ }
+ representedClass = NSClassFromString(name);
+ return representedClass;
+}
+
+#pragma mark Some general methods:
+- (BOOL) isEqual:(id) iObject
+// Equal to another class description if they have the same name.
+// Equal to a string if the string is equal to the className of the class description.
+{
+ if ([iObject isKindOfClass:[MCPClassDescription class]]) {
+ return [name isEqualToString:[(MCPClassDescription *)iObject name]];
+ }
+ if ([iObject isKindOfClass:[NSString class]]) {
+ return [name isEqualToString:(NSString *)iObject];
+ }
+ return NO;
+}
+
+/*
+- (NSString *) description
+{
+ return [NSString stringWithFormat:@"<MCPClassDescription for class named %@ : %p>", [self name], self];
+}
+
+- (NSString *) descriptionWithLocale:(NSDictionary *) locale
+{
+ return [self description];
+}
+*/
+
+#pragma mark Output for logging
+- (NSString *) descriptionWithLocale:(NSDictionary *) locale
+{
+ NSMutableString *theOutput = [NSMutableString string];
+ unsigned i;
+
+ [theOutput appendFormat:@"MCPClassDescription for class : %@ (table : %@)\n", [self name], [self externalName]];
+ for (i=0; [attributes count] != i; ++i) {
+ MCPAttribute *theAttribute = (MCPAttribute *) [attributes objectAtIndex:i];
+
+ [theOutput appendFormat:@"attribute %u, name = %@, column = %@. Allows null : %c\n", i, [theAttribute name], [theAttribute externalName], ([theAttribute allowsNull] ? 'Y' : 'N')];
+ }
+ return theOutput;
+}
+
+#pragma mark For debugging the retain counting
+- (id) retain
+{
+ [super retain];
+ return self;
+}
+
+- (void) release
+{
+ [super release];
+ return;
+}
+
+@end
+
+@implementation MCPClassDescription (Private)
+
+#pragma mark Setters
+- (void) setAttributes:(NSArray *) iAttributes
+{
+ if (iAttributes != attributes) {
+ [attributes release];
+ attributes = [[NSMutableArray alloc] initWithArray:iAttributes];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:model];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:self];
+ }
+}
+
+- (void) setRelations:(NSArray *) iRelations
+{
+ if (iRelations != relations) {
+ [relations release];
+ relations = [[NSMutableArray alloc] initWithArray:iRelations];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:model];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:self];
+ }
+}
+
+- (void) insertObject:(MCPRelation *) iRelation inIncomingsAtIndex:(unsigned int) index
+{
+ if ([iRelation destination] == self) {
+ [incomings insertObject:iRelation atIndex:index];
+ }
+ else {
+ NSLog(@"in -[MCPClassDescription+Private insertObject:inIncomingsAtIndex:]. ERRROR : self is NOT the destination of the relation");
+ }
+}
+
+- (void) removeObjectFromIncomingsAtIndex:(unsigned int) index
+{
+ [incomings removeObjectAtIndex:index];
+}
+
+#pragma mark Getters
+- (NSArray *) incomings
+{
+ return [NSArray arrayWithArray:incomings];
+}
+
+- (unsigned int) countOfIncomings
+{
+ return [incomings count];
+}
+
+- (MCPRelation *) objectInIncomingsAtIndex:(unsigned int) index
+{
+ return (MCPRelation *)[incomings objectAtIndex:index];
+}
+
+- (unsigned int) indexOfIncoming:(id) iRelation
+{
+ return [incomings indexOfObject:iRelation];
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPEntrepriseNotifications.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPEntrepriseNotifications.h
new file mode 100644
index 00000000..496a448c
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPEntrepriseNotifications.h
@@ -0,0 +1,36 @@
+//
+// $Id: MCPEntrepriseNotifications.h 482 2009-04-05 01:38:48Z stuart02 $
+//
+// MCPEnterpriseNotifications.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+
+#pragma mark Name for notification
+
+extern NSString *MCPModelChangedNotification;
+extern NSString *MCPClassDescriptionChangedNotification;
+extern NSString *MCPAttributeChangedNotification;
+extern NSString *MCPRelationChangedNotification;
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPEntrepriseNotifications.m b/Frameworks/MCPKit/MCPEntrepriseKit/MCPEntrepriseNotifications.m
new file mode 100644
index 00000000..63e580ad
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPEntrepriseNotifications.m
@@ -0,0 +1,34 @@
+//
+// $Id: MCPEntrepriseNotifications.m 482 2009-04-05 01:38:48Z stuart02 $
+//
+// MCPEnterpriseNotifications.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+
+NSString *MCPModelChangedNotification = @"Model has changed";
+NSString *MCPClassDescriptionChangedNotification = @"ClassDescription has changed";
+NSString *MCPAttributeChangedNotification = @"Attribute has changed";
+NSString *MCPRelationChangedNotification = @"Relation has changed";
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPJoin.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPJoin.h
new file mode 100644
index 00000000..c3882fee
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPJoin.h
@@ -0,0 +1,74 @@
+//
+// $Id: MCPJoin.h 545 2009-04-10 14:49:45Z stuart02 $
+//
+// MCPJoin.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 18/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+
+@class MCPModel;
+@class MCPClassDescription;
+@class MCPAttribute;
+@class MCPRelation;
+@class MCPRelation;
+
+@interface MCPJoin : NSObject <NSCoding>
+{
+@protected
+ // Note that NONE of these attributes are retained!!!
+ // Instead all these objects are notified of the existence of the join
+ // and are responsible to invalidate/delete it if necessary.
+ MCPRelation *relation;
+ MCPAttribute *origin;
+ MCPAttribute *destination;
+}
+
+#pragma mark Class methods
++ (void) initialize;
+
+#pragma mark Life cycle
+- (id) initForRelation:(MCPRelation *) iRelation from:(MCPAttribute *) iOrigin to:(MCPAttribute *) iDestination;
+- (void) invalidate;
+- (void) dealloc;
+
+#pragma mark NSCoding protocol
+- (id) initWithCoder:(NSCoder *) decoder;
+- (void) encodeWithCoder:(NSCoder *) encoder;
+
+#pragma mark Setters
+// No setter for relation : should be set at init time!
+- (void) setOrigin:(MCPAttribute *) iOrigin;
+- (void) setDestination:(MCPAttribute *) iDestination;
+
+#pragma mark Getters
+- (MCPRelation *) relation;
+- (MCPAttribute *) origin;
+- (MCPAttribute *) destination;
+- (unsigned int) index;
+
+#pragma mark Some general methods:
+- (BOOL) isEqual:(id) iObject;
+
+@end
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPJoin.m b/Frameworks/MCPKit/MCPEntrepriseKit/MCPJoin.m
new file mode 100644
index 00000000..cf202196
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPJoin.m
@@ -0,0 +1,183 @@
+//
+// $Id: MCPJoin.m 545 2009-04-10 14:49:45Z stuart02 $
+//
+// MCPJoin.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 18/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPJoin.h"
+
+#import "MCPModel.h"
+#import "MCPClassDescription.h"
+#import "MCPAttribute.h"
+#import "MCPRelation.h"
+#import "MCPRelation.h"
+
+@implementation MCPJoin
+
+#pragma mark Class methods
++ (void) initialize
+{
+ if (self = [MCPJoin class]) {
+ [self setVersion:010101]; // Ma.Mi.Re -> MaMiRe
+ }
+ return;
+}
+
+#pragma mark Life cycle
+- (id) initForRelation:(MCPRelation *) iRelation from:(MCPAttribute *) iOrigin to:(MCPAttribute *) iDestination;
+{
+ self = [super init];
+ if (self) {
+ relation = iRelation;
+ [self setOrigin:iOrigin];
+ [self setDestination:iDestination];
+ }
+ return self;
+}
+
+- (void) invalidate
+{
+ [self retain];
+ NSLog(@"Enterring -[MCPJoin invalidate], retain count is %u (after retaining : should be 4)", [self retainCount]);
+ [origin removeObjectFromJoinsAtIndex:[origin indexOfJoinIdenticalTo:self]];
+ [destination removeObjectFromJoinsAtIndex:[destination indexOfJoinIdenticalTo:self]];
+ [relation removeObjectFromJoinsAtIndex:[relation indexOfJoinIdenticalTo:self]];
+ NSLog(@"Enterring -[MCPJoin invalidate], retain count is %u (before releasing : should be 1)", [self retainCount]);
+ [self release];
+ return;
+}
+
+- (void) dealloc
+{
+ // Nothing to release, because the attributes are NOT retained.
+ [super dealloc];
+}
+
+#pragma mark NSCoding protocol
+- (id) initWithCoder:(NSCoder *) decoder
+{
+ self = [super init];
+ if ((self) && ([decoder allowsKeyedCoding])) {
+ relation = [decoder decodeObjectForKey:@"MCPrelation"];
+ [self setOrigin:[decoder decodeObjectForKey:@"MCPorigin"]];
+ [self setDestination:[decoder decodeObjectForKey:@"MCPdestination"]];
+ }
+ else {
+ NSLog(@"For some reason, unable to decode MCPJoin from the coder!!!");
+ }
+ return self;
+}
+
+- (void) encodeWithCoder:(NSCoder *) encoder
+{
+ if (! [encoder allowsKeyedCoding]) {
+ NSLog(@"In MCPJoin -encodeWithCoder : Unable to encode to a non-keyed encoder!!, will not perform encoding!!");
+ return;
+ }
+ [encoder encodeObject:[self relation] forKey:@"MCPrelation"];
+ [encoder encodeObject:[self origin] forKey:@"MCPorigin"];
+ [encoder encodeObject:[self destination] forKey:@"MCPdestination"];
+}
+
+#pragma mark Setters
+- (void) setOrigin:(MCPAttribute *) iOrigin
+{
+ if (origin != iOrigin) {
+ if (origin) {
+ [origin removeObjectFromJoinsAtIndex:[origin indexOfJoinIdenticalTo:self]];
+ }
+ origin = iOrigin;
+ if (origin) {
+ [origin insertObject:self inJoinsAtIndex:[origin countOfJoins]];
+ }
+ }
+}
+
+- (void) setDestination:(MCPAttribute *) iDestination
+{
+ if (destination != iDestination) {
+ if (destination) {
+ [destination removeObjectFromJoinsAtIndex:[destination indexOfJoinIdenticalTo:self]];
+ }
+ destination = iDestination;
+ if (destination) {
+ [destination insertObject:self inJoinsAtIndex:[destination countOfJoins]];
+ }
+ }
+}
+
+#pragma mark Getters
+- (MCPRelation *) relation
+{
+ return relation;
+}
+
+- (MCPAttribute *) origin
+{
+ return origin;
+}
+
+- (MCPAttribute *) destination
+{
+ return destination;
+}
+
+- (unsigned int) index
+{
+ return [relation indexOfJoinIdenticalTo:self];
+}
+
+#pragma mark Some general methods:
+- (BOOL) isEqual:(id) iObject
+{
+ if ([iObject isKindOfClass:[MCPJoin class]]) {
+ MCPJoin *theJoin = (MCPJoin *)iObject;
+
+ return ([relation isEqual:[theJoin relation]]) && ([origin isEqual:[theJoin origin]]) && ([destination isEqual:[theJoin destination]]);
+ }
+ if ([iObject isKindOfClass:[NSDictionary class]]) {
+ NSDictionary *theDict = (NSDictionary *)iObject;
+
+ return ([relation isEqual:[theDict valueForKey:@"relation"]]) && ([origin isEqual:[theDict valueForKey:@"origin"]]) && ([destination isEqual:[theDict valueForKey:@"destination"]]);
+ }
+ return NO;
+}
+
+#pragma mark For debugging the retain counting
+- (id) retain
+{
+ [super retain];
+
+ return self;
+}
+
+- (void) release
+{
+ [super release];
+
+ return;
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel+MCPEntreprise.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel+MCPEntreprise.h
new file mode 100644
index 00000000..cc307752
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel+MCPEntreprise.h
@@ -0,0 +1,35 @@
+//
+// $Id: MCPModel+MCPEntreprise.h 482 2009-04-05 01:38:48Z stuart02 $
+//
+// MCPModel+MCPEntreprise.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 01/11/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPModel.h"
+
+@interface MCPModel (MCPEntreprise)
+
+- (void) registerAsClassDescriptionServer;
+- (void) registerDescriptionForClass:(NSNotification *) notification;
+
+@end
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel+MCPEntreprise.m b/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel+MCPEntreprise.m
new file mode 100644
index 00000000..cb9ebbaa
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel+MCPEntreprise.m
@@ -0,0 +1,57 @@
+//
+// $Id: MCPModel+MCPEntreprise.m 482 2009-04-05 01:38:48Z stuart02 $
+//
+// MCPModel+MCPEntreprise.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 01/11/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPModel+MCPEntreprise.h"
+
+#import "MCPObject.h"
+
+@implementation MCPModel (MCPEntreprise)
+
+#pragma mark Work as a class description server
+
+- (void) registerAsClassDescriptionServer
+{
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(registerDescriptionForClass:) name:NSClassDescriptionNeededForClassNotification object:nil];
+}
+
+- (void) registerDescriptionForClass:(NSNotification *) notification
+{
+ Class theClass = [notification object];
+
+ if ([theClass isSubclassOfClass:[MCPObject class]]) {
+
+ NSString *theClassName = NSStringFromClass(theClass);
+ unsigned int index = [self indexOfClassDescription:theClassName];
+
+ if (NSNotFound != index) {
+ [NSClassDescription registerClassDescription:(NSClassDescription *)[self objectInClassDescriptionsAtIndex:index] forClass:theClass];
+ }
+ }
+}
+
+@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPModel.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel.h
index 362fed72..200b4a4b 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPModel.h
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel.h
@@ -1,25 +1,30 @@
//
+// $Id: MCPModel.h 545 2009-04-10 14:49:45Z stuart02 $
+//
// MCPModel.h
-// MCPModeler
+// MCPKit
//
// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
//
-// This code 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 General Public License for more
-// details.
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
+// This program 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 General Public License for more details.
//
-// More info at <http://mysql-cocoa.sourceforge.net/>
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
#import <Foundation/Foundation.h>
@@ -27,13 +32,14 @@
@class MCPAttribute;
@class MCPRelation;
-@interface MCPModel : NSObject < NSCoding > {
+@interface MCPModel : NSObject <NSCoding>
+{
@protected
- NSString *name; // Name of the model ... useless.
- NSMutableArray *classDescriptions; // Order of the class descriptions in the model.
- BOOL usesInnoDBTables; // The database should use InnoDB tables.
-// Might add a string holding définition of tables.
-// Might also add some sort of template for generated files (at least the header).
+ NSString *name; // Name of the model ... useless.
+ NSMutableArray *classDescriptions; // Order of the class descriptions in the model.
+ BOOL usesInnoDBTables; // The database should use InnoDB tables.
+ // Might add a string holding définition of tables.
+ // Might also add some sort of template for generated files (at least the header).
}
#pragma mark Class methods
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel.m b/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel.m
new file mode 100644
index 00000000..8f9393f2
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPModel.m
@@ -0,0 +1,230 @@
+//
+// $Id: MCPModel.m 545 2009-04-10 14:49:45Z stuart02 $
+//
+// MCPModel.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPModel.h"
+
+#import "MCPEntrepriseNotifications.h"
+
+#import "MCPClassDescription.h"
+#import "MCPAttribute.h"
+#import "MCPRelation.h"
+
+@implementation MCPModel
+
+#pragma mark Class methods
++ (void) initialize
+{
+ if (self = [MCPModel class]) {
+ [self setVersion:010101]; // Ma.Mi.Re -> MaMiRe
+ }
+ return;
+}
+
+#pragma mark Life cycle
+- (id) initWithName:(NSString *) iName
+{
+ self = [super init];
+ if (self) {
+ [self setName:iName];
+ classDescriptions = [[NSMutableArray alloc] init];
+ }
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [name release];
+ [classDescriptions release];
+ [super dealloc];
+}
+
+#pragma mark NSCoding protocol
+- (id) initWithCoder:(NSCoder *) decoder
+{
+ self = [super init];
+ if ((self) && ([decoder allowsKeyedCoding])) {
+ [self setName:[decoder decodeObjectForKey:@"MCPname"]];
+ [self setClassDescriptions:[decoder decodeObjectForKey:@"MCPclassDescriptions"]];
+ [self setUsesInnoDBTables:[decoder decodeBoolForKey:@"MCPusesInnoDBTables"]];
+ }
+ else {
+ NSLog(@"For some reason, unable to decode MCPModel from the coder!!!");
+ }
+
+ return self;
+}
+
+- (void) encodeWithCoder:(NSCoder *) encoder
+{
+ if (! [encoder allowsKeyedCoding]) {
+ NSLog(@"In MCPModel -encodeWithCoder : Unable to encode to a non-keyed encoder!!, will not perform encoding!!");
+ return;
+ }
+// [super encodeWithCoder:encoder];
+ [encoder encodeObject:[self name] forKey:@"MCPname"];
+ [encoder encodeObject:[self classDescriptions] forKey:@"MCPclassDescriptions"];
+ [encoder encodeBool:[self usesInnoDBTables] forKey:@"MCPusesInnoDBTables"];
+ [encoder encodeObject:@"1.1.1" forKey:@"MCPversion"];
+ return;
+}
+
+#pragma mark Making new class description
+- (MCPClassDescription *) addNewClassDescriptionWithName:(NSString *) iName inPosition:(int) index;
+{
+ MCPClassDescription *theClassDescription = [[MCPClassDescription alloc] initInModel:self withName:iName];
+
+// [self addClassDescription:theClassDescription];
+ [self insertObject:theClassDescription inClassDescriptionsAtIndex:(index < 0) ? ([self countOfClassDescriptions] + index + 1) : index];
+ [theClassDescription release];
+ return theClassDescription;
+}
+
+#pragma mark Setters
+- (void) setName:(NSString *) iName
+{
+ if (iName != name) {
+ [name release];
+ name = [iName retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:self];
+ }
+}
+
+- (void) setClassDescriptions:(NSArray *) iClassDescriptions
+{
+ if (iClassDescriptions != classDescriptions) {
+ [classDescriptions release];
+ classDescriptions = [[NSMutableArray alloc] initWithArray:iClassDescriptions];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:self];
+ }
+}
+
+- (void) insertObject:(MCPClassDescription *) iClassDescription inClassDescriptionsAtIndex:(unsigned int) index
+{
+ [classDescriptions insertObject:iClassDescription atIndex:index];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:self];
+}
+
+- (void) removeObjectFromClassDescriptionsAtIndex:(unsigned int) index
+{
+ [classDescriptions removeObjectAtIndex:index];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:self];
+}
+
+- (void) setUsesInnoDBTables:(BOOL) iUsesInnoDB
+{
+ usesInnoDBTables = iUsesInnoDB;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:self];
+}
+
+// Deprecated : non KVC
+/*
+- (void) removeClassDescription:(MCPClassDescription *) iClassDescription
+{
+ [classDescriptions removeObject:iClassDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:self];
+}
+
+ - (void) addClassDescription:(MCPClassDescription *) iClassDescription
+ {
+ [classDescriptions addObject:iClassDescription];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:self];
+ }
+
+ */
+
+#pragma mark Getters
+- (NSString *) name
+{
+ return name;
+// return [NSString stringWithString:name];
+}
+
+- (NSArray *) classDescriptions
+{
+ return [NSArray arrayWithArray:classDescriptions];
+}
+
+- (unsigned int) countOfClassDescriptions
+{
+ return [classDescriptions count];
+}
+
+- (MCPClassDescription *) objectInClassDescriptionsAtIndex:(unsigned int) index
+{
+ return (MCPClassDescription *)((NSNotFound != index) ? [classDescriptions objectAtIndex:index] : nil);
+}
+
+- (MCPClassDescription *) classDescriptionWithClassName:(NSString *) iClassDescriptionClassName
+{
+// Given the implementation of isEqual: for the MCPClassDescription, one should be able to use NSArray method directly:
+ /* unsigned int i;
+
+ for (i=0; ([classDescriptions count] != i) && (! [iClassDescriptionClassName isEqualToString:[(MCPClassDescription *) [classDescriptions objectAtIndex:i] className]]); ++i ) {
+ }
+ return (i == [classDescriptions count]) ? nil : (MCPClassDescription *)[classDescriptions objectAtIndex:i];
+ */
+ unsigned int theIndex = [classDescriptions indexOfObject:iClassDescriptionClassName];
+ return (NSNotFound == theIndex) ? nil : [classDescriptions objectAtIndex:theIndex];
+}
+
+- (unsigned int) indexOfClassDescription:(id) iClassDescription
+{
+ return [classDescriptions indexOfObject:iClassDescription];
+}
+
+- (BOOL) usesInnoDBTables
+{
+ return usesInnoDBTables;
+}
+
+// Deprecated : non KVC
+
+#pragma mark Output for logging
+- (NSString *) descriptionWithLocale:(NSDictionary *) locale
+{
+ return [NSString stringWithFormat:@"<MCPModel with name %@ : %p>", [self name], self];
+}
+
+#pragma mark For debugging the retain counting
+- (id) retain
+{
+ [super retain];
+
+ return self;
+}
+
+- (void) release
+{
+ [super release];
+
+ return;
+}
+
+@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPObject.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPObject.h
index 2496180a..7e6aa3b3 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPObject.h
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPObject.h
@@ -1,31 +1,51 @@
//
+// $Id: MCPObject.h 545 2009-04-10 14:49:45Z stuart02 $
+//
// MCPObject.h
// MCPKit
//
-// Created by Serge Cohen on Wed May 19 2004.
+// Created by Serge Cohen (serge.cohen@m4x.org) on 19/05/04.
// Copyright (c) 2004 Serge Cohen. All rights reserved.
//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
#import <Foundation/Foundation.h>
/*" Possible return code on some operations of the database interaction. "*/
typedef enum {
- MCPDBReturnUnknown = 0, /*"Unknown state, should not happen."*/
- MCPDBReturnDeleted = 1, /*"The entry have been successfuly deleted from DB."*/
- MCPDBReturnUsed = 2, /*"The entry can not be removed, because some entries are still connected to it (some delete restrict/inhibit delete)."*/
- MCPDBReturnNone = 3, /*"No entry exist with this Id."*/
- MCPDBReturnNew = 4, /*"The entry was indeed new and inserted in the database."*/
- MCPDBReturnUpdated = 5, /*"The entry was updated in the DB."*/
- MCPDBReturnIncompleteKey = 6, /*"Part of the primary key is missing, action not taken."*/
- MCPDBReturnMultiple = 7, /*"Multiple rows are found with a query supposed to return at most one row."*/
- MCPDBReturnNoIdentity = 8, /*"The object does not have attributes that defines identity."*/
- MCPDBReturnNoKey = 9, /*"There is no primary key defined for this entity."*/
- MCPDBReturnNoConnection = 10, /*"The MCPObject is not having a connection."*/
+ MCPDBReturnUnknown = 0, /*"Unknown state, should not happen."*/
+ MCPDBReturnDeleted = 1, /*"The entry have been successfuly deleted from DB."*/
+ MCPDBReturnUsed = 2, /*"The entry can not be removed, because some entries are still connected to it (some delete restrict/inhibit delete)."*/
+ MCPDBReturnNone = 3, /*"No entry exist with this Id."*/
+ MCPDBReturnNew = 4, /*"The entry was indeed new and inserted in the database."*/
+ MCPDBReturnUpdated = 5, /*"The entry was updated in the DB."*/
+ MCPDBReturnIncompleteKey = 6, /*"Part of the primary key is missing, action not taken."*/
+ MCPDBReturnMultiple = 7, /*"Multiple rows are found with a query supposed to return at most one row."*/
+ MCPDBReturnNoIdentity = 8, /*"The object does not have attributes that defines identity."*/
+ MCPDBReturnNoKey = 9, /*"There is no primary key defined for this entity."*/
+ MCPDBReturnNoConnection = 10, /*"The MCPObject is not having a connection."*/
MCPDBReturnWrongRelationOrigin = 11, /*"Looking for a relation not which origin is not of the specified class."*/
MCPDBReturnWrongRelationCardinality = 12, /*"Using a method assuming a cardinality of the relation while the relation as the other one."*/
MCPDBReturnNoSuchRelation = 13, /*"There is no relation with such a name starting from this class."*/
MCPDBReturnNotTarget = 14, /*"Tried to remove an object from a relation, while the objects does NOT belong to the relation."*/
- MCPDBReturnOK = 100 /*"Everything went OK."*/
+ MCPDBReturnOK = 100 /*"Everything went OK."*/
} MCPDBReturnCode;
@class MCPConnection;
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPObject.m b/Frameworks/MCPKit/MCPEntrepriseKit/MCPObject.m
new file mode 100644
index 00000000..d3145039
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPObject.m
@@ -0,0 +1,1337 @@
+//
+// $Id: MCPObject.m 927 2009-06-24 10:53:07Z stuart02 $
+//
+// MCPObject.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 19/05/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPObject.h"
+
+#import <MCPKit/MCPKit.h>
+
+#import "MCPClassDescription.h"
+#import "MCPClassDescription+MCPEntreprise.h"
+#import "MCPAttribute.h"
+#import "MCPRelation.h"
+#import "MCPJoin.h"
+
+@implementation MCPObject
+
+#pragma mark Life of the object
+- (id) init
+/*" Taking care of getting the class description for self (after passing the message up). "*/
+{
+// NSArray theAttributes;
+// unsigned int i;
+
+ if (self = [super init]) {
+ classDescription = [[NSClassDescription classDescriptionForClass:[self class]] retain];
+ [self setAttributesToDefault];
+/*
+ theAttributes = [classDescription attributeKeys];
+ for (i=0; [theAttributes count] != i; ++i) { // setting the attributtes with proper defaults.
+ NSString *theKey = (NSString *) [theAttributes objectAtIndex:i];
+
+ [self setValue:[self defaultValueForKey:theKey] forKey:theKey];
+ }
+ */
+ }
+ return self;
+}
+
+- (id) initWithDictionary:(NSDictionary *) dictionary
+/*" This method will use the class description to fetch in the dictionary the values of the attributes of the object....
+ Should try to get this description a bit clearer."*/
+{
+ self = [super init];
+ if (self) {
+ unsigned int i;
+ NSArray *attrArray;
+
+ classDescription = [[NSClassDescription classDescriptionForClass:[self class]] retain];
+ [self setAttributesToDefault];
+ attrArray = [classDescription attributes];
+ for (i=0; [attrArray count] != i; ++i) {
+ MCPAttribute *currentAttribute = (MCPAttribute *)[attrArray objectAtIndex:i];
+ id currentValue = [dictionary objectForKey:[currentAttribute name]];
+
+ if (! currentValue) {
+ currentValue = [dictionary objectForKey:[currentAttribute externalName]];
+ }
+ if (currentValue) {
+ [self setValue:currentValue forKey:[currentAttribute name]];
+ }
+ }
+ }
+ return self;
+}
+
+- (void) dealloc
+/*" Deallocating the class description, then passes the message to super. "*/
+{
+// unsigned int i;
+// NSArray *tmpAttributes = [classDescription attributes];
+
+/* for (i=0; [tmpAttributes count] != i; ++i) {
+ MCPAttribute *tmpAttr = [tmpAttributes objectAtIndex:i];
+ if ([tmpAttr valueClass]) {
+ [self setValue:nil forKey:[tmpAttr name]];
+ }
+ }
+*/
+ [classDescription release];
+ [connection release];
+ [super dealloc];
+}
+
+- (void) setAttributesToDefault
+/*" Set all the attributes to default values, except for auto-generated and primary key attributes, which are set to NULL.
+
+ NOTE : !! In the current version the auto-generated and key are ALSO set to default values!!.
+ "*/
+{
+ NSArray *theAttributes = [classDescription attributes];
+// NSArray *thePrimKeys = [classDescription primaryKeyAttributes];
+ unsigned i;
+
+ for (i=0; [theAttributes count] != i; ++i) {
+ MCPAttribute *theAttribute = (MCPAttribute *) [theAttributes objectAtIndex:i];
+ NSString *theKey = [theAttribute name];
+
+ if (! [theAttribute autoGenerated]) {
+ [self setValue:[self defaultValueForKey:theKey] forKey:theKey];
+ }
+ else { // Auto-generated attribute ... set it to NULL:
+ [self setValue:[self defaultValueForKey:theKey] forKey:theKey];
+ }
+ }
+/*
+ for (i=0; [thePrimKeys count] != i; ++i) {
+ MCPAttribute *theAttribute = (MCPAttribute *) [thePrimKeys objectAtIndex:i];
+ if (! [theAttribute autoGenerated]) {
+ NSString *theKey = [theAttribute name];
+
+ [[self valueForKey:theKey] release];
+ [self setValue:NULL forKey:theKey];
+ }
+ }
+ */
+ return;
+}
+
+#pragma mark Accessor(s)
+- (MCPClassDescription *) classDescription
+{
+ return classDescription;
+}
+
+- (MCPConnection *) connection
+{
+ if ((! connection) || (! [connection checkConnection])) {
+ [self setConnection:nil];
+ }
+ return connection;
+}
+
+- (void) setConnection:(MCPConnection *) iConnection
+{
+ if (iConnection != connection) {
+ [connection release];
+ connection = [iConnection retain];
+ }
+}
+
+
+
+#pragma mark Database interface
+- (id) readFromDBRow:(NSDictionary *) iDictionary withTableName:(NSString *) iTableName
+/*" Uses a query result row (described as a NSDictionary) to set the instance variables of self. If
+ the result contains columns from multiple tables, the iTableName can be used to specify the alias
+ used for the table name corresponding to the class.
+
+If iTableName == nil, the columns will be searched first without table name (column_name) and if
+ not found then with the table name in front (from the class description : table_name.column_name).
+
+Otherwise, the search will be performed in the following order : iTableName.column_name, column_name,
+ table_name.column_name.
+ "*/
+{
+ NSArray *theAttributeKeys = [classDescription attributeKeys];
+ NSArray *thePrefixArray;
+ unsigned i;
+
+// Depending on the value of iTableName, get the search order.
+ if ((nil == iTableName) || ([@"" isEqualToString:iTableName])) {
+ thePrefixArray = [NSArray arrayWithObjects:@"", [NSMutableString stringWithFormat:@"%@.", [classDescription externalName]], nil];
+ }
+ else {
+ thePrefixArray = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%@.", iTableName], [NSMutableString stringWithFormat:@"%@.", [classDescription externalName]], @"", nil];
+ }
+ for (i=0; [theAttributeKeys count] != i; ++i) {
+ id theValue = nil;
+ MCPAttribute *theAttribute = [classDescription attributeWithName:[theAttributeKeys objectAtIndex:i]];
+ unsigned j;
+
+ for (j=0; [thePrefixArray count] != j; ++j) {
+ if (theValue = [iDictionary objectForKey:[NSString stringWithFormat:@"%@%@", [thePrefixArray objectAtIndex:j], [theAttribute externalName]]]) {
+ break;
+ }
+ }
+ if (theValue) {
+ [self takeValue:theValue forKey:[theAttribute name]];
+ }
+ }
+ return self;
+}
+
+
+//- (MCPDBReturnCode) setPrimaryKey:(NSDictionary *) iDictionary andFetchFromDB:(MCPConnection *) iConnection
+- (MCPDBReturnCode) setPrimaryKey:(id) iDictionary andFetchFromDB:(MCPConnection *) iConnection
+/*" This method is used to retrieve an object from the DB given its precise primary key. It will return self.
+ If the object is not found in the DB, then all instance variable are set to the default
+ (and autogenerated/primary-key attributes are set to null)."*/
+{
+ BOOL missingKey = NO;
+ NSArray *theKeyAttr = [classDescription primaryKeyAttributes];
+ unsigned i;
+ NSMutableString *query = [NSMutableString stringWithFormat:@"SELECT * FROM %@ WHERE ", [classDescription externalName]];
+ MCPResult *result;
+ NSDictionary *row;
+
+ [self setConnection:iConnection];
+ if (! iConnection) {
+ return MCPDBReturnNoConnection;
+ }
+ for (i=0; [theKeyAttr count] != i; ++i) {
+ MCPAttribute *theAttr = [classDescription attributeWithName:[(MCPAttribute *)[theKeyAttr objectAtIndex:i] name]];
+ id theKeyValue;
+
+// if (theKeyValue = [iDictionary objectForKey:[theAttr name]]) {
+ if (theKeyValue = [iDictionary valueForKey:[theAttr name]]) {
+ if (i != 0) {
+ [query appendString:@" and "];
+ }
+// Implies the iDictionary IS a dictionary:
+// [query appendFormat:@"(%@ = %@)", [theAttr externalName], [iConnection quoteObject:[iDictionary objectForKey:[theAttr name]]]];
+// If the iDictionary is just an object complying with NSValueCodeing:
+ [query appendFormat:@"(%@ = %@)", [theAttr externalName], [iConnection quoteObject:theKeyValue]];
+ }
+ else { // Part of the primary key is missing... look for the DB name of the attribute
+ if (theKeyValue = [iDictionary valueForKey:[theAttr externalName]]) {
+ if (i != 0) {
+ [query appendString:@" and "];
+ }
+ [query appendFormat:@"(%@ = %@)", [theAttr externalName], [iConnection quoteObject:theKeyValue]];
+ }
+ else { // Not able to find the value for this attribute !!!
+ missingKey = YES;
+ NSLog(@"Unable to find the value for attribute %@ of object of class %@, will make it default", [theAttr name], [self className]);
+ break;
+ }
+ }
+ } // Now the query is prepared... or a key part is missing:
+ if (missingKey) {
+ [self setAttributesToDefault];
+ return MCPDBReturnIncompleteKey;
+ }
+ result = [iConnection queryString:query];
+ if ([result numOfRows] == 0) {
+ [self setAttributesToDefault];
+ return MCPDBReturnNone;
+ }
+ row = [result fetchRowAsDictionary];
+ [self readFromDBRow:row withTableName:@""];
+ if ([result numOfRows] != 1) {
+ NSLog(@"Got more than one row when querying : %@.... will take only the first one!!! that an IMPORTANT flaw in your data model!!!", query);
+ return MCPDBReturnMultiple;
+ }
+ return MCPDBReturnOK;
+}
+
+
+- (NSDictionary *) checkDBId
+/*" Using the identity properties of the class, this method will check if self already exists in the DB,
+ in which case it will set the primary key attributes to match the DB entry. If the object is not present
+ in the DB, the primary key attributes are set to null if they are declared as aut-generated (untouched otherwise).
+
+The returned dictionary contains the values of the primary key attributes. It also contains one entry with
+ key MCPDBReturnCode, which contains the result of the operation (was the object in DB?).
+
+If the identityAttributes of the class description is empty, the entry will always be considered not to be
+ in the DB, AND the primary key attributes of the object will be left unchnaged and returned as they are at
+ call time."*/
+{
+ NSArray *theIdAttr = [classDescription identityAttributes];
+ NSMutableDictionary *theKeys = [NSMutableDictionary dictionary];
+ NSArray *theKeyAttr = [classDescription primaryKeyAttributes];
+ MCPConnection *theConnection = [self connection];
+ MCPResult *theResult;
+ unsigned int i;
+
+ if (! theConnection) {
+ return [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:MCPDBReturnNoConnection], @"MCPDBReturnCode"];
+ }
+ if (! [theKeyAttr count]) { // There is no primary key for this object.
+ [theKeys setObject:[NSNumber numberWithInt:MCPDBReturnNoKey] forKey:@"MCPDBReturnCode"];
+ return [NSDictionary dictionaryWithDictionary:theKeys];
+ }
+ if (! [theIdAttr count]) { // Identity is not defined for this object.
+ [theKeys setObject:[NSNumber numberWithInt:MCPDBReturnNoIdentity] forKey:@"MCPDBReturnCode"];
+ for (i=0; [theKeyAttr count] != i; ++i) {
+ NSString *theKey = [(MCPAttribute*)[theKeyAttr objectAtIndex:i] name];
+ [theKeys setObject:[self valueForKey:theKey] forKey:theKey];
+ }
+ return [NSDictionary dictionaryWithDictionary:theKeys];
+ }
+// Do the fetch in the DB.
+ NSMutableString *theQuery = [NSMutableString stringWithString:@"SELECT "];
+
+ for (i = 0; [theKeyAttr count] != i; ++i) {
+ if (i) {
+ [theQuery appendString:@", "];
+ }
+ [theQuery appendString:[(MCPAttribute *)[theKeyAttr objectAtIndex:i] externalName]];
+ }
+ [theQuery appendFormat:@" FROM %@ WHERE ", [classDescription externalName]];
+ for (i = 0; [theIdAttr count] != i; ++i) {
+ if (i) {
+ [theQuery appendString:@" AND "];
+ }
+/*
+ if ([[(MCPAttribute *)[theIdAttr objectAtIndex:i] valueClass] isSubclassOfClass:[NSString class]]) {
+ if ([(MCPAttribute *)[theIdAttr objectAtIndex:i] width] != 0) {
+ [theQuery appendFormat:@"(BINARY %@ = SUBSTRING(%@ FROM 1 FOR %u)", [(MCPAttribute *)[theIdAttr objectAtIndex:i] externalName], [theConnection quoteObject:[self valueForKey:[(MCPAttribute *)[theIdAttr objectAtIndex:i] name]]], [(MCPAttribute *)[theIdAttr objectAtIndex:i] width]];
+ }
+ else {
+ [theQuery appendFormat:@"(BINARY %@ = %@)", [(MCPAttribute *)[theIdAttr objectAtIndex:i] externalName], [theConnection quoteObject:[self valueForKey:[(MCPAttribute *)[theIdAttr objectAtIndex:i] name]]]];
+ }
+ }
+ */
+ if (([[(MCPAttribute *)[theIdAttr objectAtIndex:i] valueClass] isSubclassOfClass:[NSString class]]) && ([(MCPAttribute *)[theIdAttr objectAtIndex:i] width] != 0)) {
+ [theQuery appendFormat:@"(%@ = SUBSTRING(%@ FROM 1 FOR %u))", [(MCPAttribute *)[theIdAttr objectAtIndex:i] externalName], [theConnection quoteObject:[self valueForKey:[(MCPAttribute *)[theIdAttr objectAtIndex:i] name]]], [(MCPAttribute *)[theIdAttr objectAtIndex:i] width]];
+ }
+ else {
+ [theQuery appendFormat:@"(%@ = %@)", [(MCPAttribute *)[theIdAttr objectAtIndex:i] externalName], [theConnection quoteObject:[self valueForKey:[(MCPAttribute *)[theIdAttr objectAtIndex:i] name]]]];
+ }
+ }
+ [theQuery appendString:@" ORDER BY "];
+ for (i = 0; [theKeyAttr count] != i; ++i) {
+ if (i) {
+ [theQuery appendString:@", "];
+ }
+ [theQuery appendString:[(MCPAttribute *)[theKeyAttr objectAtIndex:i] externalName]];
+ }
+ theResult = [theConnection queryString:theQuery];
+ if ([theResult numOfRows]) { // the object was found.
+ NSDictionary *theFirstRow = [theResult fetchRowAsDictionary];
+ if ([theResult numOfRows] != 1) {
+ NSLog(@"in MCPObject -checkDBIdWithConnection: method.... not only one (as expected) but %i results were found, will take the first one.");
+ [theKeys setObject:[NSNumber numberWithInt:MCPDBReturnMultiple] forKey:@"MCPDBReturnCode"];
+ }
+ else {
+ [theKeys setObject:[NSNumber numberWithInt:MCPDBReturnOK] forKey:@"MCPDBReturnCode"];
+ }
+ [theKeys addEntriesFromDictionary:theFirstRow];
+// Setting the value of self for the primary key to the one just found.
+ for (i=0; [theKeyAttr count] != i; ++i) {
+ MCPAttribute *theAttribute = (MCPAttribute *) [theKeyAttr objectAtIndex:i];
+
+ [self setValue:[theFirstRow objectForKey:[theAttribute externalName]] forKey:[theAttribute name]];
+ }
+ }
+ else { // Object not found in the DB.
+ for (i = 0; [theKeyAttr count] != i; ++i) {
+ MCPAttribute *theAttribute = (MCPAttribute *)[theKeyAttr objectAtIndex:i];
+
+ if ([theAttribute autoGenerated]) {
+ [self setValue:[self defaultValueForKey:[theAttribute name]] forKey:[theAttribute name]];
+ }
+ [theKeys setObject:[self valueForKey:[theAttribute name]] forKey:[theAttribute name]];
+ }
+ [theKeys setObject:[NSNumber numberWithInt:MCPDBReturnNone] forKey:@"MCPDBReturnCode"];
+// Setting the value of self for the primary key to the default values.
+/*
+ for (i=0; [theKeyAttr count] != i; ++i) {
+ MCPAttribute *theAttribute = (MCPAttribute *) [theKeyAttr objectAtIndex:i];
+
+ [self setValue:[self defaultValueForKey:[theAttribute name]] forKey:[theAttribute name]];
+ }
+*/
+ }
+ return [NSDictionary dictionaryWithDictionary:theKeys];
+}
+
+
+- (NSDictionary *) saveInDB
+/*" First will use the checkDBIdWithConnection method to check if the entry is already in the database. If this is the case,
+ it will use the updateInDB... method to update the current DB instance. Otherwise it will make an insert into the database
+ to save the entry, than it makes a select to get the value of autogenerated column, and use them (if necessary) to return
+ the primary key (as NSDictionary).
+
+ As for checkDBId... the returned dictionary also have a MCPDBReturnCode key with a NSNumber as value containing the
+ return code of the operation."*/
+{
+ MCPConnection *theConnection = [self connection];
+ NSDictionary *theCheckReturn = [self checkDBId];
+ NSMutableDictionary *theRet;
+ int theCheckCode = [(NSNumber *)[theCheckReturn objectForKey:@"MCPDBReturnCode"] intValue];
+ unsigned i;
+ unsigned j;
+ NSMutableString *theQuery = [NSMutableString string];
+ NSArray *theAttr = [classDescription attributes];
+
+ switch (theCheckCode) {
+ case MCPDBReturnNoIdentity : // For this object the identity is not set... so we try to save.
+ break;
+
+ case MCPDBReturnOK : // Object already in the DB (found using checkDBId... method).
+ // NSLog(@"in saveUsingConnection: the entry already existed so will update the one with key : %@", theCheckReturn);
+ theCheckCode = [self updateInDB];
+ theRet = [NSMutableDictionary dictionaryWithDictionary:[self primaryKey]];
+ [theRet setObject:[NSNumber numberWithInt:theCheckCode] forKey:@"MCPDBReturnCode"];
+ return [NSDictionary dictionaryWithDictionary:theRet];
+ break;
+
+ case MCPDBReturnMultiple : // Multiple were found, the first one will be updated.
+ NSLog(@"Multiple entries found with the same identity ... will update the first one.");
+ theCheckCode = [self updateInDB];
+ theRet = [NSMutableDictionary dictionaryWithDictionary:[self primaryKey]];
+ [theRet setObject:[NSNumber numberWithInt:theCheckCode] forKey:@"MCPDBReturnCode"];
+ return [NSDictionary dictionaryWithDictionary:theRet];
+ break;
+
+ case MCPDBReturnNone : // The entry is not already in the DB, save it...
+ break;
+
+ case MCPDBReturnNoConnection : // Self does not have a connection.
+ NSLog(@"Can not save when the connection is not working...");
+ break;
+
+ default : // We should not arrive here anyway.
+ NSLog(@"For some resons we got a unexpected result from checkDBId : %i", theCheckCode);
+ break;
+ }
+
+// Generate the INSERT query:
+ [theQuery appendFormat:@"INSERT INTO %@ (", [classDescription externalName]];
+ j = 0;
+ for (i=0; [theAttr count] != i; ++i) {
+ if (! [(MCPAttribute *)[theAttr objectAtIndex:i] autoGenerated]) {
+ if (j) {
+ [theQuery appendString:@", "];
+ }
+ [theQuery appendString:[(MCPAttribute *)[theAttr objectAtIndex:i] externalName]];
+ ++j;
+ }
+ }
+ [theQuery appendString:@") VALUES ("];
+ j = 0;
+ for (i=0; [theAttr count] != i; ++i) {
+ if (! [(MCPAttribute *)[theAttr objectAtIndex:i] autoGenerated]) {
+ if (j) {
+ [theQuery appendString:@", "];
+ }
+ [theQuery appendString:[theConnection quoteObject:[self valueForKey:[(MCPAttribute *)[theAttr objectAtIndex:i] name]]]];
+ ++j;
+ }
+ }
+ [theQuery appendString:@")"];
+// Finished preparing the query.
+
+// Now we perform the query...
+ [theConnection queryString:theQuery];
+ if (1 != (i = [theConnection affectedRows])) { // More than one row affected ... Should NEVER occure.
+ NSLog(@"Problem while saving a MCPObject to the database : number of inserted rows is : %i !!!", i);
+ NSLog(@"Maybe there is an error : %@ ", [theConnection getLastErrorMessage]);
+ NSLog(@"The class of the object is : %@, and it's description is :\n%@", [self className], [self descriptionWithLocale:nil]);
+ theCheckCode = (i == 0) ? MCPDBReturnNone : MCPDBReturnMultiple;
+ }
+ else {
+ theCheckCode = MCPDBReturnOK;
+ }
+
+// Finally we get the primary key of the inserted object:
+ if ([classDescription singleIntAutoGenKey]) {
+ NSString *thePrimKey = [(MCPAttribute *) [[classDescription primaryKeyAttributes] objectAtIndex:0] name];
+
+ [self setValue:[NSNumber numberWithLongLong:[theConnection insertId]] forKey:thePrimKey];
+ }
+ [self getAutoGenerated];
+ theRet = [NSMutableDictionary dictionaryWithDictionary:[self primaryKey]];
+ [theRet setObject:[NSNumber numberWithInt:theCheckCode] forKey:@"MCPDBReturnCode"];
+
+ return [NSDictionary dictionaryWithDictionary:theRet];
+}
+
+
+
+- (MCPDBReturnCode) getAutoGenerated
+/*" This method will use the Identity attributes of the object to retrieve the autogenerated
+attributes from the database.
+
+If the identity is not defined for this class/entity, then it will try to use the primary key
+to get the auto-generated values.
+
+Obviously this might generate a bug if one of the Identity attributes is autogenerated.
+This will create a trouble if some object does not have an identity defined but still contains
+some auto-generated attributes.
+"*/
+{
+ NSMutableArray *theAutoAttr = [NSMutableArray array];
+ NSArray *theAttr = [classDescription attributes];
+ NSArray *theKeyAttr = [classDescription primaryKeyAttributes];
+ unsigned i,j;
+ NSMutableString *theQuery;
+ int theCheckCode;
+ MCPResult *theResult;
+ NSDictionary *theRow;
+ MCPConnection *theConnection = [self connection];
+
+ if (! theConnection) {
+ return MCPDBReturnNoConnection;
+ }
+
+ if (0 != [[classDescription identityAttributes] count]) {
+ theCheckCode = [(NSNumber *)[[self checkDBId] objectForKey:@"MCPDBReturnCode"] intValue];
+ if ((MCPDBReturnOK != theCheckCode) && (MCPDBReturnMultiple != theCheckCode)) {
+ NSLog(@"Unable to get the primary key for the object, will abort now the fetch of autoGenerated attributes (left unchanged)!");
+ return theCheckCode;
+ }
+ if (MCPDBReturnMultiple == theCheckCode) {
+ NSLog(@"Will get the autoGenerated values for the first entry....");
+ }
+ }
+ j = 0;
+ for (i=0; [theAttr count] != i; ++i) { // generate the array with autoGenerated attributes.
+ if ([(MCPAttribute *)[theAttr objectAtIndex:i] autoGenerated]) {
+ [theAutoAttr insertObject:[theAttr objectAtIndex:i] atIndex:j];
+ ++j;
+ }
+ }
+ if (0 == [theAutoAttr count]) {
+ return MCPDBReturnOK;
+ }
+
+// Make the query:
+ theQuery = [NSMutableString stringWithString:@"SELECT "];
+ for (i=0; [theAutoAttr count] != i; ++i) {
+ if (i) {
+ [theQuery appendString:@", "];
+ }
+ [theQuery appendString:[(MCPAttribute *)[theAutoAttr objectAtIndex:i] externalName]];
+ }
+ [theQuery appendFormat:@" FROM %@ WHERE ", [classDescription externalName]];
+// Preparing the Where Clause:
+ for (i=0; [theKeyAttr count] != i; ++i) {
+ if (i) {
+ [theQuery appendString:@" AND "];
+ }
+ [theQuery appendFormat:@"( %@ = %@ )", [(MCPAttribute*)[theKeyAttr objectAtIndex:i] externalName], [theConnection quoteObject:[self valueForKey:[(MCPAttribute*)[theKeyAttr objectAtIndex:i] name]]]];
+ }
+// Query is ready:
+ theResult = [theConnection queryString:theQuery];
+ if (! theResult) {
+ NSLog(@"While fetching the auto-generated part of the object, got an error -a nil MCPResult-. Will report that as a MCPDBReturnNone.");
+ return MCPDBReturnNone;
+ }
+ if (0 == [theResult numOfRows]) { // The entry was not found in the DB.
+ if (0 == [[classDescription identityAttributes] count]) {
+ NSLog(@"It seems that the object is not in the DB... but the identity is not defined so there might be a trouble with having the proper ID.");
+ }
+ return MCPDBReturnNone;
+ }
+// Getting the values from the DB select:
+ theRow = [theResult fetchRowAsDictionary];
+ for (i=0; [theAutoAttr count] != i; ++i) {
+ [self setValue:[theRow objectForKey:[(MCPAttribute*)[theAutoAttr objectAtIndex:i] externalName]] forKey:[(MCPAttribute*)[theAutoAttr objectAtIndex:i] name]];
+ }
+// Returning the proper value:
+ if (1 != [theResult numOfRows]) {
+ NSLog(@"Multiple entries (or none : %llu), got the values for the first one...", [theResult numOfRows]);
+ return MCPDBReturnMultiple;
+ }
+ return MCPDBReturnOK;
+}
+
+
+- (MCPDBReturnCode) updateInDB
+/*"This method will use the primary key value held by the object to modify the object that is saved in the DB.
+
+ (NO YET IMPLEMENTED) If the primary key is not complete (some of the attributes are to null or 0) and the identityAttributes
+ (from class description) is not an empty list then it will perform a checkDBId... to try to retrieve the
+ missing part of the primary key.
+ "*/
+{
+ NSArray *theAttributes = [classDescription attributes];
+ NSArray *thePrimKeyAttributes = [classDescription primaryKeyAttributes];
+ NSMutableString *theQuery = [NSMutableString string];
+ int theCheckCode;
+ unsigned i, j;
+ MCPConnection *theConnection = [self connection];
+
+ if (! theConnection) {
+ return MCPDBReturnNoConnection;
+ }
+// Generate the query
+ [theQuery appendFormat:@"UPDATE %@ SET ", [classDescription externalName]];
+ // Prepare the value key pairs:
+ j=0;
+ for (i=0 ; [theAttributes count] != i; ++i) {
+ id theValue = [self valueForKey:[(MCPAttribute *)[theAttributes objectAtIndex:i] name]];
+
+ if ((theValue) && (! [(MCPAttribute *)[theAttributes objectAtIndex:i] autoGenerated])) {
+ if (j) {
+ [theQuery appendString:@", "];
+ }
+ [theQuery appendFormat:@"%@ = %@ ", [(MCPAttribute *)[theAttributes objectAtIndex:i] externalName], [theConnection quoteObject:theValue]];
+ ++j;
+ }
+ }
+ if (0 == j) { // Nothing has to be updated in this entry....
+ NSLog(@"Tried to update a row from an object that does NOT contain any information!!");
+ return MCPDBReturnNone;
+ }
+ // Prepare the WHERE clause:
+ [theQuery appendFormat:@" WHERE "];
+ j = 0;
+ for (i=0; [thePrimKeyAttributes count] != i; ++i) {
+ id theValue = [self valueForKey:[(MCPAttribute *)[thePrimKeyAttributes objectAtIndex:i] name]];
+
+ if (j) {
+ [theQuery appendString:@" AND "];
+ }
+ if (theValue) {
+ [theQuery appendFormat:@"%@ = %@", [(MCPAttribute *)[thePrimKeyAttributes objectAtIndex:i] externalName], [theConnection quoteObject:theValue]];
+ ++j;
+ }
+ }
+// Perform the update:
+ if (j == [thePrimKeyAttributes count]) {
+ [theConnection queryString:theQuery];
+ i = [theConnection affectedRows];
+ switch (i) {
+ case 0 :
+ theCheckCode = MCPDBReturnNone;
+ break;
+ case 1 :
+ theCheckCode = MCPDBReturnOK;
+ break;
+ default :
+ theCheckCode = MCPDBReturnMultiple;
+ break;
+ }
+ }
+ else {
+ NSDictionary *theKeyCheck = [self checkDBId];
+ int theIdCheckCode = [(NSNumber *) [theKeyCheck objectForKey:@"MCPDBReturnCode"] intValue];
+
+ if (MCPDBReturnOK == theIdCheckCode) {
+ theCheckCode = [self updateInDB];
+ }
+ else {
+ theCheckCode = MCPDBReturnNoKey;
+ }
+ }
+// Return proper code:
+ return theCheckCode;
+}
+
+
+- (MCPDBReturnCode) deleteInDB
+/*" Uses the connection to delete the object from the DB. In this process the autoGenerated attributes are set to null.
+ If the primary key is not completely set, this method calls checkDBId... method to try to complete it
+ (if the identityAttributes of the class description is not empty)."*/
+{
+ NSArray *theKeyAttributes = [classDescription primaryKeyAttributes];
+ NSArray *theAttributes = [classDescription attributes];
+ unsigned i;
+// NSMutableDictionary *theKeyValue = [NSMutableDictionary dictionary];
+ int theCheckCode = MCPDBReturnOK;
+ MCPConnection *theConnection = [self connection];
+
+ if (! theConnection) {
+ return MCPDBReturnNoConnection;
+ }
+// Get the value of the primary key:
+ for (i=0; [theKeyAttributes count] != i; ++i) {
+ id theValue = [self valueForKey:[(MCPAttribute*) [theKeyAttributes objectAtIndex:i] name]];
+ if ((! theValue) || ([theValue isKindOfClass:[NSNumber class]] && (0 == [theValue intValue]))) {
+ theCheckCode = MCPDBReturnIncompleteKey;
+ break;
+ }
+ }
+// If incomplete, try to find the rest, and perform again:
+ if (MCPDBReturnIncompleteKey == theCheckCode) {
+ if (MCPDBReturnOK == [(NSNumber *)[[self checkDBId] objectForKey:@"MCPDBReturnCode"] intValue]) {
+ return [self deleteInDB];
+ }
+ else {
+ return MCPDBReturnIncompleteKey;
+ }
+ }
+
+// Perform the deletion from the DB:
+ theCheckCode = [[self class] deleteInDBUsingConnection:theConnection withId:self];
+
+// set the auto-generated attributes to proper values:
+ for (i=0 ; [theAttributes count] != i; ++i) {
+ MCPAttribute *theAttribute = (MCPAttribute *) [theAttributes objectAtIndex:i];
+ if ([theAttribute autoGenerated]) {
+// [self setValue:NULL forKey:[theAttribute name]];
+ [self setValue:[self defaultValueForKey:[theAttribute name]] forKey:[theAttribute name]];
+ }
+ }
+
+// Finished... just have to return the proper value:
+ return theCheckCode;
+}
+
+
++ (MCPDBReturnCode) deleteInDBUsingConnection:(MCPConnection *) iConnection withId:(id) iId
+/*" Uses the connection to remove from the DB the entry corresponding to the primary key id given by iId.
+ If any part of the primary key is missing, nothing is done."*/
+{
+ NSMutableString *theQuery = [NSMutableString string];
+ MCPClassDescription *theClassDescription = (MCPClassDescription *) [NSClassDescription classDescriptionForClass:[self class]];
+ NSArray *theKeyAttributes = [theClassDescription primaryKeyAttributes];
+ unsigned i;
+
+ if (! [iConnection checkConnection]) {
+ return MCPDBReturnNoConnection;
+ }
+// Generate the query:
+ [theQuery appendFormat:@"DELETE FROM %@ WHERE ", [theClassDescription externalName]];
+// Prepare the WHERE STATEMENT:
+ for (i=0; [theKeyAttributes count] != i; ++i) {
+ if (i) {
+ [theQuery appendString:@" AND "];
+ }
+// [theQuery appendFormat:@"( %@ = %@ )", [(MCPAttribute*)[theKeyAttributes objectAtIndex:i] externalName], [iConnection quoteObject:[iId objectForKey:[(MCPAttribute*)[theKeyAttributes objectAtIndex:i] name]]]];
+ [theQuery appendFormat:@"( %@ = %@ )", [(MCPAttribute*)[theKeyAttributes objectAtIndex:i] externalName], [iConnection quoteObject:[iId valueForKey:[(MCPAttribute*)[theKeyAttributes objectAtIndex:i] name]]]];
+ }
+// Perform the query:
+ [iConnection queryString:theQuery];
+// Return the proper code:
+ i = [iConnection affectedRows];
+
+ if (1 < i) {
+ return MCPDBReturnMultiple;
+ }
+ if (0 == i) {
+ return MCPDBReturnNone;
+ }
+ return MCPDBReturnOK;
+}
+
+
+#pragma mark Handling realtions
+- (id) getTargetOfRelation:(MCPRelation *) iRelation
+/*" This method is using the information from iRelation to fetch the targe of the relation in the DB.
+
+If iRelation is flagged as a to-one, then the return type is the type of the target object (value might be nil, if the target was not found).
+If iRelation is flagged as a to-many, then the return type is NSArray (and might be empty if no target were found).
+
+In any case this method is first checking that iRelation is starting from the class of self, and that self is connected to the DB.
+Also the returned object is ALWAYS autoreleased before being returned.
+"*/
+{
+ NSMutableString *query;
+ MCPClassDescription *destinationDesc;
+ NSArray *joins;
+ NSArray *keys;
+ NSArray *ids;
+ MCPResult *result;
+ unsigned int i;
+ NSDictionary *theRow;
+ id theRet;
+
+ if (! iRelation) {
+ NSLog(@"Tried to get the target of a relation... but the relation object is nil");
+ }
+ else {
+// NSLog(@"Trying to get the target of the realtion : %@", [iRelation descriptionWithLocale:nil]);
+ }
+ if ((! [connection isConnected]) || (! [classDescription isEqual:[iRelation origin]])) { // Error condition.
+ return nil;
+ }
+// Generating the query:
+ destinationDesc = [iRelation destination];
+ keys = [destinationDesc primaryKeyAttributes];
+ joins = [iRelation joins];
+ ids = [destinationDesc identityAttributes];
+ query = [[NSMutableString alloc] initWithString:@"SELECT "];
+ for (i=0; [keys count] != i; ++i) {
+ if (i) {
+ [query appendString:@", "];
+ }
+ [query appendString:[(MCPAttribute *)[keys objectAtIndex:i] externalName]];
+ }
+ [query appendFormat:@" FROM %@ WHERE ", [destinationDesc externalName]];
+ for (i=0; [joins count] != i; ++i) {
+ MCPJoin *theJoin = (MCPJoin *)[joins objectAtIndex:i];
+
+ if (i) {
+ [query appendString:@" and "];
+ }
+ [query appendFormat:@"(%@ = %@)", [[theJoin destination] externalName], [connection quoteObject:[self valueForKey:[[theJoin origin] name]]]];
+ }
+// NSLog(@"in -[MCPObject getTargetOfRelation:%@]; query is %@...", [iRelation descriptionWithLocale:nil], query);
+ [query appendString:[self orderSQLForClassDescription:destinationDesc]];
+// NSLog(@"in -[MCPObject getTargetOfRelation:%@]; query is %@...", [iRelation descriptionWithLocale:nil], query);
+/*
+ [query appendString:@" ORDER BY "];
+ for (i=0; [ids count] != i; ++i) { // Generating the order :
+ if (i) {
+ [query appendString:@", "];
+ }
+ [query appendString:[(MCPAttribute *)[ids objectAtIndex:i] externalName]];
+ }
+*/
+ result = [connection queryString:query];
+ [query release];
+
+// Getting the results in proper objects:
+ if ([iRelation isToMany]) { // To-Many relation
+ NSMutableArray *theArrayRet = [[NSMutableArray alloc] init];
+
+ theRet = theArrayRet;
+ while (theRow = [result fetchRowAsDictionary]) {
+ MCPObject *theTarget = [[[destinationDesc representedClass] alloc] init];
+
+ [theTarget setPrimaryKey:theRow andFetchFromDB:connection];
+ [theArrayRet insertObject:theTarget atIndex:[theArrayRet count]];
+ [theTarget release];
+ }
+ }
+ else { // To-One relation
+ theRow = [result fetchRowAsDictionary];
+ if (theRow) {
+ theRet = [[[destinationDesc representedClass] alloc] init];
+ [theRet setPrimaryKey:theRow andFetchFromDB:connection];
+ }
+ else {
+ theRet = nil;
+ }
+ }
+ [theRet autorelease];
+ return theRet;
+}
+
+- (id) getTargetOfRelationNamed:(NSString *) iRelationName
+{
+ MCPRelation *theRelation = [classDescription relationWithName:iRelationName];
+ return (theRelation) ? [self getTargetOfRelation:theRelation] : nil;
+}
+
+- (MCPDBReturnCode) setTarget:(id) iTarget forRelation:(MCPRelation *) iRelation
+/*" This method will modify the DB content so that the corresponding relation is deleted.
+ If any value corresping to an attribute of self is modified in the DB, then it will update all attributes of self to reflect DB status.
+
+Obviuosly this method is taking care of only to-one relation. It will hence check that iRelation is a to-one relation starting from self.
+Finally, you can use setTarget:nil forRelation:... to 'delete' a previously establlished relation (if the model and DB permit it)."*/
+{
+ unsigned int i;
+ MCPObject *oldTarget;
+
+ if (! [connection isConnected]) {
+ return MCPDBReturnNoConnection;
+ }
+ if (! [classDescription isEqual:[iRelation origin]]) {
+ return MCPDBReturnWrongRelationOrigin;
+ }
+ if ([iRelation isToMany]) {
+ return MCPDBReturnWrongRelationCardinality;
+ }
+
+ oldTarget = [self getTargetOfRelation:iRelation];
+ if ((oldTarget) && ([iTarget isEqual:oldTarget])) { // No need to change the relation's target.
+ return MCPDBReturnOK;
+ }
+ for (i=0; [iRelation countOfJoins] != i; ++i) {
+ MCPJoin *theJoin = [iRelation objectInJoinsAtIndex:i];
+
+ if (([[theJoin origin] isPartOfKey]) && (![[theJoin destination] isPartOfKey])) { // Will change the destination...
+ [iTarget setValue:[self valueForKey:[[theJoin origin] name]] forKey:[[theJoin destination] name]];
+ [oldTarget setValue:[oldTarget defaultValueForKey:[[theJoin destination] name]] forKey:[[theJoin destination] name]];
+ }
+ else { // Will change the origin
+ [self setValue:[iTarget valueForKey:[[theJoin destination] name]] forKey:[[theJoin origin] name]];
+ }
+ }
+ if ([iRelation ownsDestination]) {
+ [oldTarget deleteInDB];
+ }
+ return MCPDBReturnOK;
+}
+
+- (MCPDBReturnCode) setTarget:(id) iTarget forRelationNamed:(NSString *) iRelationName
+{
+ MCPRelation *theRelation = [classDescription relationWithName:iRelationName];
+ return (theRelation) ? [self setTarget:iTarget forRelation:theRelation] : MCPDBReturnNoSuchRelation;
+}
+
+- (unsigned int) countTargetForRelation:(MCPRelation *) iRelation
+{
+ NSMutableString *theQuery;
+ unsigned int i;
+ NSArray *theJoinArray;
+ MCPResult *theResult;
+ NSDictionary *theRow;
+
+ if ((! [connection isConnected]) || (! [classDescription isEqual:[iRelation origin]])){
+ return 0;
+ }
+ theJoinArray = [iRelation joins];
+ theQuery = [[NSMutableString alloc] initWithFormat:@"SELECT COUNT(*) FROM %@ WHERE ", [[iRelation destination] externalName]];
+ for (i=0; [theJoinArray count] != i; ++i) {
+ MCPJoin *theJoin = (MCPJoin *)[theJoinArray objectAtIndex:i];
+ if (i) {
+ [theQuery appendString:@" AND "];
+ }
+ [theQuery appendFormat:@"( %@ = %@ )", [[theJoin destination] externalName], [connection quoteObject:[self valueForKey:[[theJoin origin] name]]]];
+ }
+ theResult = [connection queryString:theQuery];
+ [theQuery release];
+ theRow = [theResult fetchRowAsDictionary];
+ return [(NSNumber *)[theRow objectForKey:@"COUNT(*)"] unsignedIntValue];
+}
+
+- (unsigned int) countTargetForRelationNamed:(NSString *) iRelationName
+{
+ MCPRelation *theRelation = [classDescription relationWithName:iRelationName];
+ return (theRelation) ? [self countTargetForRelation:theRelation] : 0;
+}
+
+
+- (MCPObject *) getTargetOfRelation:(MCPRelation *) iRelation atIndex:(unsigned int) iIndex
+/*" This method will return the specific object which is the iIndex'th object of th relation (after ordering the object using the destination identity).
+
+This method (like other assuming order in the relation targets) will be doubtfull if the class does NOT have a single identity attribute."*/
+{
+ NSMutableString *query;
+ MCPClassDescription *destinationDesc;
+ NSArray *joins;
+ NSArray *keys;
+ NSArray *ids;
+ MCPResult *result;
+ unsigned int i;
+ NSDictionary *theRow;
+ MCPObject *theRet;
+
+ if (! iRelation) {
+ NSLog(@"Tried to get the target of a relation... but the relation object is nil");
+ }
+ else {
+// NSLog(@"Trying to get the target of the realtion : %@", [iRelation descriptionWithLocale:nil]);
+ }
+ if ((! [connection isConnected]) || (! [classDescription isEqual:[iRelation origin]])) { // Error condition.
+ return nil;
+ }
+ if (! [iRelation isToMany]) {
+ NSLog(@"Tried to use the -[MCPObject getTargetOfRelation:atIndex:] on a to-one relation... this does NOT works!!! You should use -[MCPObject getTargetOfRelation:] instead!!!");
+ return [self getTargetOfRelation:iRelation];
+ }
+// Generating the query:
+ destinationDesc = [iRelation destination];
+ keys = [destinationDesc primaryKeyAttributes];
+ joins = [iRelation joins];
+ ids = [destinationDesc identityAttributes];
+ query = [[NSMutableString alloc] initWithString:@"SELECT "];
+ for (i=0; [keys count] != i; ++i) {
+ if (i) {
+ [query appendString:@", "];
+ }
+ [query appendString:[(MCPAttribute *)[keys objectAtIndex:i] externalName]];
+ }
+ [query appendFormat:@" FROM %@ WHERE ", [destinationDesc externalName]];
+ for (i=0; [joins count] != i; ++i) {
+ MCPJoin *theJoin = (MCPJoin *)[joins objectAtIndex:i];
+
+ if (i) {
+ [query appendString:@" and "];
+ }
+ [query appendFormat:@"(%@ = %@)", [[theJoin destination] externalName], [connection quoteObject:[self valueForKey:[[theJoin origin] name]]]];
+ }
+ [query appendString:[self orderSQLForClassDescription:destinationDesc]];
+/*
+ [query appendString:@" ORDER BY "];
+ for (i=0; [ids count] != i; ++i) { // Generating the order :
+ if (i) {
+ [query appendString:@", "];
+ }
+ [query appendString:[(MCPAttribute *)[ids objectAtIndex:i] externalName]];
+ }
+*/
+ [query appendFormat:@" LIMIT 1 OFFSET %u", iIndex];
+ result = [connection queryString:query];
+ [query release];
+
+// Getting the results in proper objects:
+ theRow = [result fetchRowAsDictionary];
+ if (theRow) {
+ theRet = (MCPObject *)[[[destinationDesc representedClass] alloc] init];
+ [theRet setPrimaryKey:theRow andFetchFromDB:connection];
+ [theRet autorelease];
+ }
+ else {
+ theRet = nil;
+ }
+ return theRet;
+}
+
+- (MCPObject *) getTargetOfRelationNamed:(NSString *) iRelationName atIndex:(unsigned int) iIndex
+/*"This is the equivalent of the getTargetOfRelation:atIndex:, but giving a relation name instead of the MCPRelation object itself."*/
+{
+ MCPRelation *theRelation = [classDescription relationWithName:iRelationName];
+ return (theRelation) ? [self getTargetOfRelation:theRelation atIndex:iIndex]: nil;
+}
+
+- (MCPDBReturnCode) addTarget:(MCPObject *) iTarget toRelation:(MCPRelation *) iRelation
+/*" This method will modify the DB content so that the corresponding relation is added.
+If any value corresping to an attribute of self i modified in the DB, then it will update all attributes of self to reflect DB status.
+
+Obviuosly this method is taking care of only to-many relation. It will hence check that iRelation is a to-many relation starting from self."*/
+{
+ NSArray *joins;
+ unsigned int i;
+ NSDictionary *saveReturn;
+
+ if (! [connection isConnected]) {
+ return MCPDBReturnNoConnection;
+ }
+ if (! [classDescription isEqual:[iRelation origin]]) {
+ return MCPDBReturnWrongRelationOrigin;
+ }
+ if (! [iRelation isToMany]) {
+ return MCPDBReturnWrongRelationCardinality;
+ }
+ joins = [iRelation joins];
+ for (i=0; [joins count] != i; ++i) { // Will change only values of iTarget, because it is a to-many relation.
+ MCPJoin *join = (MCPJoin *)[joins objectAtIndex:i];
+
+ [iTarget setValue:[self valueForKey:[[join origin] name]] forKey:[[join destination] name]];
+ }
+ if (! [[iTarget connection] isConnected]) {
+ [iTarget setConnection:connection];
+ }
+ saveReturn = [iTarget saveInDB];
+ return (MCPDBReturnCode)[(NSNumber *)[saveReturn objectForKey:@"MCPDBReturnCode"] unsignedIntValue];
+}
+
+- (MCPDBReturnCode) addTarget:(MCPObject *) iTarget toRelationNamed:(NSString *) iRelationName
+{
+ MCPRelation *theRelation = [classDescription relationWithName:iRelationName];
+ return (theRelation) ? [self addTarget:iTarget toRelation:theRelation] : MCPDBReturnNoSuchRelation;
+}
+
+- (MCPDBReturnCode) removeTarget:(MCPObject *) iTarget toRelation:(MCPRelation *) iRelation
+/*" This method will modify the DB content so that the corresponding relation is removed.
+If any value corresping to an attribute of self i modified in the DB, then it will update all attributes of self to reflect DB status.
+
+Obviuosly this method is taking care of only to-many relation. It will hence check that iRelation is a to-many relation starting from self."*/
+{
+ NSArray *joins;
+ unsigned int i;
+// NSDictionary *saveReturn;
+ BOOL targetIsTarget = YES;
+ MCPDBReturnCode returnCode;
+
+ if (! [connection isConnected]) {
+ return MCPDBReturnNoConnection;
+ }
+ if (! [classDescription isEqual:[iRelation origin]]) {
+ return MCPDBReturnWrongRelationOrigin;
+ }
+ if (! [iRelation isToMany]) {
+ return MCPDBReturnWrongRelationCardinality;
+ }
+ joins = [iRelation joins];
+ for (i=0; [joins count] != i; ++i) {
+ MCPJoin *join = (MCPJoin *)[joins objectAtIndex:i];
+ targetIsTarget = targetIsTarget && [[iTarget valueForKey:[[join destination] name]] isEqual:[self valueForKey:[[join origin] name]]];
+ }
+ if (! targetIsTarget) {
+ return MCPDBReturnNotTarget;
+ }
+ if ([iRelation ownsDestination]) { // just delete the target from the DB.
+ returnCode = [iTarget deleteInDB];
+ }
+ for (i=0; [joins count] != i; ++i) { // Put all the destination to default...
+ MCPJoin *join = (MCPJoin *)[joins objectAtIndex:i];
+
+ [iTarget setValue:[[join destination] defaultValue] forKey:[[join destination] name]];
+ }
+ if (! [iRelation ownsDestination]) {
+ returnCode = [(NSNumber *)[[iTarget saveInDB] objectForKey:@"MCPDBReturnCode"] unsignedIntValue];
+ }
+ return returnCode;
+}
+
+- (MCPDBReturnCode) removeTarget:(MCPObject *) iTarget toRelationNamed:(NSString *) iRelationName
+{
+ MCPRelation *theRelation = [classDescription relationWithName:iRelationName];
+ return (theRelation) ? [self removeTarget:iTarget toRelation:theRelation] : MCPDBReturnNoSuchRelation;
+}
+
+- (MCPDBReturnCode) removeTargetToRelation:(MCPRelation *) iRelation atIndex:(unsigned int) iIndex
+/*" This method will use an index t first query the object that it should remove from the relation, then uses the -[MCPObject removeTarget:toRelation:]
+ method to remove the object from the relation. If the index is out of bound (the returned object is nil), it will return MCPDBReturnNone, to signal
+ there was no object with this index in the relation."*/
+{
+ MCPObject *target;
+
+ if (! [connection isConnected]) {
+ return MCPDBReturnNoConnection;
+ }
+ if (! [classDescription isEqual:[iRelation origin]]) {
+ return MCPDBReturnWrongRelationOrigin;
+ }
+ if (! [iRelation isToMany]) {
+ return MCPDBReturnWrongRelationCardinality;
+ }
+ target = [self getTargetOfRelation:iRelation atIndex:iIndex];
+ if (target) {
+ return [self removeTarget:target toRelation:iRelation];
+ }
+ else {
+ return MCPDBReturnNone;
+ }
+}
+
+- (MCPDBReturnCode) removeTargetToRelationNamed:(NSString *) iRelationName atIndex:(unsigned int) iIndex
+{
+ MCPRelation *theRelation = [classDescription relationWithName:iRelationName];
+ return (theRelation) ? [self removeTargetToRelation:theRelation atIndex:iIndex] : MCPDBReturnNoSuchRelation;
+}
+
+- (unsigned int) indexOfTarget:(MCPObject *) iTarget inRelation:(MCPRelation *) iRelation
+/*" Returns the index of the target object within the relation. Return NSNotFound if the objkect is NOT in the relation!!"*/
+{
+ NSMutableString *query;
+ NSArray *joins;
+ NSArray *keys;
+ NSArray *ids;
+ unsigned int i;
+ MCPResult *result;
+ NSDictionary *row;
+ NSMutableDictionary *targetKey;
+ BOOL targetIsTarget = YES;
+
+ if ((! [connection isConnected]) || (! [classDescription isEqual:[iRelation origin]]) || (! [iRelation isToMany])) { // Checking the realtion object.
+ return NSNotFound;
+ }
+ query = [[NSMutableString alloc] initWithString:@"SELECT "];
+ joins = [iRelation joins];
+// keys = [[iRelation destination] attributeKeys];
+ keys = [[iRelation destination] primaryKeyAttributes];
+ ids = [[iRelation destination] identityAttributes];
+ for (i=0; [keys count] != i; ++i) {
+ if (i) {
+ [query appendString:@", "];
+ }
+ [query appendString:[(MCPAttribute *)[keys objectAtIndex:i] externalName]];
+ }
+ [query appendFormat:@"FROM %@ WHERE ", [[iRelation destination] externalName]];
+ for (i=0; [joins count] != i; ++i) {
+ MCPJoin *join = (MCPJoin *)[joins objectAtIndex:i];
+
+ targetIsTarget = targetIsTarget && [[iTarget valueForKey:[[join destination] name]] isEqual:[self valueForKey:[[join origin] name]]];
+ if (i) {
+ [query appendString:@" AND "];
+ }
+ [query appendFormat:@"( %@ = %@ )", [[join destination] externalName], [connection quoteObject:[self valueForKey:[[join origin] name]]]];
+ }
+ if (! targetIsTarget) { // Checking that iTarget belongs to the relation.
+ [query release];
+ return NSNotFound;
+ }
+ [query appendString:[self orderSQLForClassDescription:[iRelation destination]]];
+/*
+ [query appendString:@" ORDER BY "];
+ for (i=0; [ids count] != i; ++i) {
+ if (i) {
+ [query appendString:@", "];
+ }
+ [query appendString:[(MCPAttribute *)[ids objectAtIndex:i] externalName]];
+ }
+*/
+ targetKey = [[NSMutableDictionary alloc] init];
+ for (i=0; [keys count] != i; ++i) { // Setting the targetKey to the row that should gives the target.
+ MCPAttribute *attribute = (MCPAttribute *)[keys objectAtIndex:i];
+
+ [targetKey setObject:[iTarget valueForKey:[attribute name]] forKey:[attribute externalName]];
+ }
+ result = [connection queryString:query];
+ [query release];
+ i = 0;
+ while (row = [result fetchRowAsDictionary]) {
+ if ([targetKey isEqualToDictionary:row]) { // We have found the proper object return i (after cleaning up);
+ [targetKey release];
+ return i;
+ }
+ ++i;
+ }
+ return NSNotFound;
+}
+
+- (unsigned int) indexOfTarget:(MCPObject *) iTarget inRelationNamed:(NSString *) iRelationName
+/*" The equivalent of -[MCPObject indexOfTarget:inRelation:] but using relation name instead of a MCPRelation
+object. Indeed after getting the MCPRelation object corresponding to the name, this method will only return
+the result of the corresponding call to -[MCPObject indexOfTarget:inRelation:]."*/
+{
+ MCPRelation *theRelation = [classDescription relationWithName:iRelationName];
+ return (theRelation) ? [self indexOfTarget:iTarget inRelation:theRelation] : NSNotFound;
+}
+
+#pragma mark Utility methods
+- (id) defaultValueForKey:(NSString *) iKey
+/*" This method will return the default value (object) for the given key."*/
+{
+ MCPAttribute *theAttribute = [classDescription attributeWithName:iKey];
+
+ if ([theAttribute allowsNull]) {
+// return [NSNull null];
+ return nil;
+ }
+ else {
+ Class theAttrClass = [theAttribute valueClass];
+ id theRet;
+
+ if ([theAttrClass isSubclassOfClass:[NSNumber class]]) {
+ return [NSNumber numberWithInt:0];
+ }
+ theRet = [[[theAttrClass alloc] init] autorelease];
+ if (nil == theRet) {
+ NSLog(@"in MCPObject defaultValueForKey:%@ , for object of class %@, (attribute of class %@) the return value will be nil!!!", iKey, [self className], theAttrClass);
+ }
+ return theRet;
+ }
+}
+
+
+- (NSDictionary *) primaryKey
+/*" Returns a dictionary with the values of the primary key. "*/
+{
+ NSMutableDictionary *theRet = [NSMutableDictionary dictionary];
+ NSArray *theIdAttr = [classDescription primaryKeyAttributes];
+ unsigned i;
+
+ for (i=0; [theIdAttr count] != i; ++i) {
+ NSString *theKey = [(MCPAttribute *)[theIdAttr objectAtIndex:i] name];
+
+ if ([self valueForKey:theKey]) {
+ [theRet setObject:[self valueForKey:theKey] forKey:theKey];
+ }
+ else {
+ [theRet setObject:[NSNull null] forKey:theKey];
+ }
+ }
+ return [NSDictionary dictionaryWithDictionary:theRet];
+}
+
+#pragma mark Testing equality (VERY important for relation management)
+- (BOOL) isEqual:(id) iObject
+{
+ NSArray *theIdAttr;
+ unsigned int i;
+ BOOL theRet;
+
+ if (self == iObject) {
+ return YES;
+ }
+ if ([self class] != [iObject class]) {
+ return NO;
+ }
+ theIdAttr = [classDescription identityAttributes];
+ for (i = 0; [theIdAttr count] != i; ++i) {
+ MCPAttribute *theAttr = [theIdAttr objectAtIndex:i];
+
+ theRet = theRet && [[self valueForKey:[theAttr name]] isEqual:[iObject valueForKey:[theAttr name]]];
+ }
+ return theRet;
+}
+
+
+#pragma mark Output
+- (NSString *) description
+{
+ return [self descriptionWithLocale:nil];
+}
+
+- (NSString *) descriptionWithLocale:(NSDictionary *) locale
+{
+ NSMutableString *theOutput = [NSMutableString string];
+ unsigned int i;
+ NSArray *theAttributes = [classDescription attributes];
+ BOOL trunc = [MCPConnection truncateLongField];
+
+ [theOutput appendFormat:@"MCPObject subclass : %@\n", [self className]];
+ for (i=0; [theAttributes count] != i; ++i) {
+ MCPAttribute *theAttribute = (MCPAttribute *) [theAttributes objectAtIndex:i];
+ id theValue = [self valueForKey:[theAttribute name]];
+
+ if (trunc) {
+ if (([theValue isKindOfClass:[NSString class]]) && (kLengthOfTruncationForLog < [(NSString *)theValue length])) {
+ theValue = [theValue substringToIndex:kLengthOfTruncationForLog];
+ }
+ else if (([theValue isKindOfClass:[NSData class]]) && (kLengthOfTruncationForLog < [(NSData *)theValue length])) {
+ theValue = [NSData dataWithBytes:[theValue bytes] length:kLengthOfTruncationForLog];
+ }
+ }
+ [theOutput appendFormat:@"\tAttribute %u : name = %@, value = %@\n", i, [theAttribute name], theValue];
+ }
+ [theOutput appendString:@"\n"];
+ return theOutput;
+}
+
+#pragma mark Ordering the array for relations
+- (NSString *) orderSQLForClassDescription:(MCPClassDescription *) iClassDescription
+{
+ NSMutableArray *theAttributes = [[NSMutableArray alloc] initWithArray:[iClassDescription identityAttributes]];
+ NSMutableString *theReturn = [NSMutableString string];
+ unsigned int i;
+
+ for (i = 0; [[iClassDescription primaryKeyAttributes] count] != i; ++i) {
+ [theAttributes insertObject:[[iClassDescription primaryKeyAttributes] objectAtIndex:i] atIndex:[theAttributes count]];
+ }
+ for (i = 0; [theAttributes count] != i; ++i) {
+ if (i) {
+ [theReturn appendString:@", "];
+ }
+ else {
+ [theReturn appendString:@" ORDER BY "];
+ }
+ [theReturn appendString:[(MCPAttribute *)[theAttributes objectAtIndex:i] externalName]];
+ }
+ return theReturn;
+}
+
+#pragma mark Anti-crash method...
+- (void) setNilValueForKey:(NSString *) iKey
+{
+ NSLog(@"Try to set %@ to nil .... not possible, will set it to zero instead...", iKey);
+ [self setValue:[NSNumber numberWithInt:0] forKey:iKey];
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation+Private.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation+Private.h
new file mode 100644
index 00000000..c8683aab
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation+Private.h
@@ -0,0 +1,46 @@
+//
+// $Id: MCPRelation+Private.h 482 2009-04-05 01:38:48Z stuart02 $
+//
+// MCPRelation+Private.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 11/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPRelation.h"
+
+@interface MCPRelation (Private)
+
+#pragma mark Making some work
+- (void) invalidateJoins; // Check that the joins are realistics.
+
+#pragma mark Setters
+- (void) setOrigin:(MCPClassDescription *) iOrigin;
+//- (void) setJoins:(NSArray *) iJoins;
+
+#pragma mark Getters
+- (MCPModel *) model;
+
+#pragma mark Fro the controller layer and the UI
+- (void) addNewDefaultJoin;
+
+@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPRelation.h b/Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation.h
index fa359e2e..43ff027a 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPRelation.h
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation.h
@@ -1,33 +1,36 @@
//
+// $Id: MCPRelation.h 545 2009-04-10 14:49:45Z stuart02 $
+//
// MCPRelation.h
-// MCPModeler
+// MCPKit
//
// Created by Serge Cohen (serge.cohen@m4x.org) on 11/08/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
//
-// This code 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 General Public License for more
-// details.
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
+// This program 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 General Public License for more details.
//
-// More info at <http://mysql-cocoa.sourceforge.net/>
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
#import <Foundation/Foundation.h>
@class MCPModel;
@class MCPClassDescription;
@class MCPAttribute;
-
@class MCPJoin;
typedef enum {
@@ -38,18 +41,18 @@ typedef enum {
OnDeleteNoAction = 5
} MCPRelationDeleteRule;
-
-@interface MCPRelation : NSObject < NSCoding > {
+@interface MCPRelation : NSObject <NSCoding>
+{
@protected
- NSString *name; // Name of the relation
- MCPRelationDeleteRule deleteRule; // Delete rule : what to do of the destination when origin is deleted
- MCPRelation *inverseRelation; // The inverse relation (or nil if no inverse present)
- MCPClassDescription *origin; // The class description from which the relation originate
- MCPClassDescription *destination; // The class description to which the relation arrives
- NSMutableArray *joins; // Joining attributes (array of MCPJoin)
- BOOL isToMany; // Is the relation to many (or to one)
- BOOL isMandatory; // Is the relation mandatory for the class description (origin)
- BOOL ownsDestination; // The origin class description owns the destination class description(ies)
+ NSString *name; // Name of the relation
+ MCPRelationDeleteRule deleteRule; // Delete rule : what to do of the destination when origin is deleted
+ MCPRelation *inverseRelation; // The inverse relation (or nil if no inverse present)
+ MCPClassDescription *origin; // The class description from which the relation originate
+ MCPClassDescription *destination; // The class description to which the relation arrives
+ NSMutableArray *joins; // Joining attributes (array of MCPJoin)
+ BOOL isToMany; // Is the relation to many (or to one)
+ BOOL isMandatory; // Is the relation mandatory for the class description (origin)
+ BOOL ownsDestination; // The origin class description owns the destination class description(ies)
}
#pragma mark Class methods
diff --git a/Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation.m b/Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation.m
new file mode 100644
index 00000000..57186fdc
--- /dev/null
+++ b/Frameworks/MCPKit/MCPEntrepriseKit/MCPRelation.m
@@ -0,0 +1,486 @@
+//
+// $Id: MCPRelation.m 927 2009-06-24 10:53:07Z stuart02 $
+//
+// MCPRelation.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 11/08/04.
+// Copyright (c) 2004 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPRelation.h"
+#import "MCPRelation+Private.h"
+
+#import "MCPEntrepriseNotifications.h"
+
+#import "MCPModel.h"
+#import "MCPClassDescription.h"
+#import "MCPClassDescription+Private.h"
+#import "MCPAttribute.h"
+
+#import "MCPJoin.h"
+
+static NSArray *MCPexistingDeleteRules;
+
+@implementation MCPRelation
+
+#pragma mark Class methods
++ (void) initialize
+{
+ if (self = [MCPRelation class]) {
+ NSMutableArray *theExistingDeleteRules = [[NSMutableArray alloc] init];
+
+ [self setVersion:010101]; // Ma.Mi.Re -> MaMiRe
+
+ [theExistingDeleteRules addObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:OnDeleteNullify], @"tag", @"Nullify", @"name", nil]];
+ [theExistingDeleteRules addObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:OnDeleteDeny], @"tag", @"Deny", @"name", nil]];
+ [theExistingDeleteRules addObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:OnDeleteCascade], @"tag", @"Cascade", @"name", nil]];
+ [theExistingDeleteRules addObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:OnDeleteDefault], @"tag", @"Default", @"name", nil]];
+ [theExistingDeleteRules addObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:OnDeleteNoAction], @"tag", @"No Action", @"name", nil]];
+ MCPexistingDeleteRules = [[NSArray alloc] initWithArray:theExistingDeleteRules];
+ [theExistingDeleteRules release];
+ }
+ return;
+}
+
++ (NSArray *) existingDeleteRules
+{
+ return MCPexistingDeleteRules;
+}
+
+- (NSArray *) existingDeleteRules
+{
+ return [MCPRelation existingDeleteRules];
+}
+
+
+#pragma mark Life cycle
+- (id) initWithName:(NSString *) iName from:(MCPClassDescription *) iFrom to:(MCPClassDescription *) iTo
+{
+ self = [super init];
+ if (self) {
+ [self setName:iName];
+ [self setOrigin:iFrom];
+ [self setDestination:iTo];
+ joins = [[NSMutableArray alloc] init];
+ }
+ return self;
+}
+
+- (void) invalidateRelation
+{
+ [self retain]; // To be sure not to be released before the end of the method
+ [self invalidateJoins]; // Remove each of the joins (so that attributes get notified)
+/*
+ [origin removeObjectFromRelationsAtIndex:[[origin relations] indexOfObjectIdenticalTo:self]];
+ origin = nil;
+ [destination removeObjectFromIncomingsAtIndex:[[destination incomings] indexOfObjectIdenticalTo:self]];
+ destination = nil;
+*/
+ [self setOrigin:nil];
+ [self setDestination:nil];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ [self release];
+}
+
+- (void) dealloc
+{
+ [joins release]; // Should be empty by now...
+ [name release];
+// The inverse relation don't have an inverse relation any more...
+// [inverseRelation setInverseRelation:nil];
+ [self setInverseRelation:nil];
+// Other are weak references.
+ [super dealloc];
+}
+
+#pragma mark NSCoding protocol
+- (id) initWithCoder:(NSCoder *) decoder
+{
+ self = [super init];
+ if ((self) && ([decoder allowsKeyedCoding])) {
+ [self setName:[decoder decodeObjectForKey:@"MCPname"]];
+ [self setDeleteRule:(MCPRelationDeleteRule)[decoder decodeInt32ForKey:@"MCPdeleteRule"]];
+ if ([decoder containsValueForKey:@"MCPinverseRelation"]) {
+ [self setInverseRelation:[decoder decodeObjectForKey:@"MCPinverseRelation"]];
+ }
+ else {
+ [self setInverseRelation:nil];
+ }
+ [self setOrigin:[decoder decodeObjectForKey:@"MCPorigin"]];
+ [self setDestination:[decoder decodeObjectForKey:@"MCPdestination"]];
+// [self setJoins:[decoder decodeObjectForKey:@"MCPjoins"]];
+ joins = [[NSMutableArray alloc] initWithArray:[decoder decodeObjectForKey:@"MCPjoins"]];
+ [self setIsToMany:[decoder decodeBoolForKey:@"MCPisToMany"]];
+ [self setIsMandatory:[decoder decodeBoolForKey:@"MCPisMandatory"]];
+ [self setOwnsDestintation:[decoder decodeBoolForKey:@"MCPownsDestination"]];
+ }
+
+ return self;
+}
+
+- (void) encodeWithCoder:(NSCoder *) encoder
+{
+ if (! [encoder allowsKeyedCoding]) {
+ NSLog(@"In MCPRelation -encodeWithCoder : Unable to encode to a non-keyed encoder!!, will not perform encoding!!");
+ return;
+ }
+ [encoder encodeObject:[self name] forKey:@"MCPname"];
+ [encoder encodeInt32:(int32_t)[self deleteRule] forKey:@"MCPdeleteRule"];
+ if ([self inverseRelation]) {
+ [encoder encodeObject:[self inverseRelation] forKey:@"MCPinverseRelation"];
+ }
+ [encoder encodeObject:[self origin] forKey:@"MCPorigin"];
+ [encoder encodeObject:[self destination] forKey:@"MCPdestination"];
+ [encoder encodeObject:[self joins] forKey:@"MCPjoins"];
+ [encoder encodeBool:[self isToMany] forKey:@"MCPisToMany"];
+ [encoder encodeBool:[self isMandatory] forKey:@"MCPisMandatory"];
+ [encoder encodeBool:[self ownsDestination] forKey:@"MCPownsDestination"];
+}
+
+#pragma mark Making new joins
+/*
+- (MCPJoin *) addNewJoin // Usefull for the interface, to be able to create a new join by just using a binding.
+{
+ [self addJoinFrom:[origin objectInAttributesAtIndex:0] to:[destination objectInAttributesAtIndex:0]];
+}
+*/
+
+- (MCPJoin *) addJoinFrom:(MCPAttribute *) iFrom to:(MCPAttribute *) iTo
+{
+ MCPJoin *theJoin;
+
+ if ([iFrom classDescription] != [self origin]) {
+ NSLog(@"Tried to make a join starting from an attribute (%@) that does NOT belong to the origin class description (%@)! Will not perform the link", iFrom, [self origin]);
+ return nil;
+ }
+ if ([iTo classDescription] != [self destination]) {
+ NSLog(@"Tried to make a join arriving to an attribute (%@) that does NOT belong to the destination class description (%@)! Will not perform the link", iTo, [self destination]);
+ return nil;
+ }
+ theJoin = [[MCPJoin alloc] initForRelation:self from:iFrom to:iTo];
+// theJoin = [[MCPJoin alloc] initFrom:iFrom to:iTo];
+// [joins addObject:theJoin];
+ [joins insertObject:theJoin atIndex:[joins count]];
+ [theJoin release];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ return theJoin;
+}
+
+- (void) removeJoinFrom:(MCPAttribute *) iFrom to:(MCPAttribute *) iTo
+{
+ NSDictionary *theJoinDict = [[NSDictionary alloc] initWithObjectsAndKeys:self, @"relation", iFrom, @"origin", iTo, @"destination", nil];
+ unsigned int i = [joins indexOfObject:theJoinDict];
+
+ if (NSNotFound != i) {
+ [[self objectInJoinsAtIndex:i] invalidate];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ }
+ [theJoinDict release];
+}
+
+/*
+- (void) unjoinAttribute:(MCPAttribute *) iAttribute
+{
+ unsigned int i = 0;
+
+#warning HAVE to rewrite this code!!!
+ if ([[iAttribute classDescription] isEqual:origin]) {
+ for (i=0; ([joins count] != i) && ([iAttribute isEqual:[(MCPJoin *)[joins objectAtIndex:i] origin]]); ++i) {
+ }
+ }
+ if ([[iAttribute classDescription] isEqual:destination]) {
+ for (i=0; ([joins count] != i) && ([iAttribute isEqual:[(MCPJoin *)[joins objectAtIndex:i] destination]]); ++i) {
+ }
+ }
+ if ((0 == i) || ([joins count] == i)) { // No joins found using this attribute.
+ return;
+ }
+ [self removeJoinFrom:[(MCPJoin *)[joins objectAtIndex:i] origin] to:[(MCPJoin *)[joins objectAtIndex:i] destination]];
+}
+*/
+
+#pragma mark Setters
+- (void) setDestination:(MCPClassDescription *) iDestination
+{
+ if (iDestination != destination) {
+ [destination removeObjectFromIncomingsAtIndex:[[destination incomings] indexOfObjectIdenticalTo:self]];
+ destination = iDestination;
+ [destination insertObject:self inIncomingsAtIndex:0];
+ [self invalidateJoins];
+ }
+}
+
+
+- (void) setName:(NSString *) iName
+{
+ if (iName != name) {
+ [name release];
+ name = [iName retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[origin model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:origin];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ }
+}
+
+- (void) setDeleteRule:(MCPRelationDeleteRule) iDeleteRule
+{
+ if (iDeleteRule != deleteRule) { // Don't do the notification for nothing!!!
+ deleteRule = iDeleteRule;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[origin model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:origin];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ }
+}
+
+- (void) setInverseRelation:(MCPRelation *) iInverseRelation
+{
+ if (iInverseRelation != inverseRelation) {
+ [inverseRelation release];
+ inverseRelation = [iInverseRelation retain];
+ [inverseRelation setInverseRelation:self];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[origin model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:origin];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ }
+}
+
+- (void) insertObject:(MCPJoin *) iJoin inJoinsAtIndex:(unsigned int) index
+{
+ [joins insertObject:iJoin atIndex:index];
+}
+
+- (void) removeObjectFromJoinsAtIndex:(unsigned int) index
+{
+ [joins removeObjectAtIndex:index];
+}
+
+- (void) setIsToMany:(BOOL) iIsToMany
+{
+ if (iIsToMany != isToMany) { // Don't do the notification for nothing!!!
+ isToMany = iIsToMany;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[origin model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:origin];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ }
+}
+
+- (void) setIsMandatory:(BOOL) iIsMandatory
+{
+ if (iIsMandatory != isMandatory) { // Don't do the notification for nothing!!!
+ isMandatory = iIsMandatory;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[origin model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:origin];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ }
+}
+
+- (void) setOwnsDestintation:(BOOL) iOwnsDestination
+{
+ if (iOwnsDestination != ownsDestination) { // Don't do the notification for nothing!!!
+ ownsDestination = iOwnsDestination;
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPModelChangedNotification object:[origin model]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPClassDescriptionChangedNotification object:origin];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ }
+}
+
+#pragma mark Getters
+- (NSString *) name
+{
+ return name;
+}
+
+- (MCPRelationDeleteRule) deleteRule
+{
+ return deleteRule;
+}
+
+- (MCPRelation *) inverseRelation
+{
+ return inverseRelation;
+}
+
+- (MCPClassDescription *) origin
+{
+ return origin;
+}
+
+- (MCPClassDescription *) destination
+{
+ return destination;
+}
+
+- (NSArray *) joins
+{
+ return [NSArray arrayWithArray:joins];
+}
+
+- (unsigned int) countOfJoins
+{
+ return [joins count];
+}
+
+- (MCPJoin *) objectInJoinsAtIndex:(unsigned int) index
+{
+ return (MCPJoin *)((NSNotFound != index) ? [joins objectAtIndex:index] : nil);
+}
+
+- (unsigned int) indexOfJoinIdenticalTo:(id) iJoin
+{
+ return [joins indexOfObjectIdenticalTo:iJoin];
+}
+
+- (BOOL) isToMany
+{
+ return isToMany;
+}
+
+- (BOOL) isMandatory
+{
+ return isMandatory;
+}
+
+- (BOOL) ownsDestination
+{
+ return ownsDestination;
+}
+
+#pragma mark Some Usefull methods
+
+- (MCPAttribute *) destinationAttributeForOrigin:(MCPAttribute *) iFrom
+{
+ unsigned int i;
+
+ for (i=0; ([joins count] != i) && ([[(MCPJoin *)[joins objectAtIndex:i] origin] isEqual:iFrom]); ++i) {
+ }
+ return ([joins count] == i) ? nil : [(MCPJoin *)[joins objectAtIndex:i] destination];
+}
+
+- (MCPAttribute *) originAttributeForDestination:(MCPAttribute *) iTo
+{
+ unsigned int i;
+
+ for (i=0; ([joins count] != i) && ([[(MCPJoin *)[joins objectAtIndex:i] destination] isEqual:iTo]); ++i) {
+ }
+ return ([joins count] == i) ? nil : [(MCPJoin *)[joins objectAtIndex:i] origin];
+}
+
+
+#pragma mark Some general methods:
+- (BOOL) isEqual:(id) iObject
+// Equal to another relation, if they have the same name and same origin and destination class descriptions (they have the same names).
+// Equal to a string (NSString), if the name of the relation is equal to the string.
+{
+ if ([iObject isKindOfClass:[MCPRelation class]]) {
+ MCPRelation *theRelation = (MCPRelation *) iObject;
+
+ return ([name isEqualToString:[theRelation name]]) && ([[self origin] isEqual:[theRelation origin]]) && ([[self destination] isEqual:[theRelation destination]]);
+ }
+ if ([iObject isKindOfClass:[NSString class]]) {
+ return [name isEqualToString:(NSString *)iObject];
+ }
+ return NO;
+}
+
+- (NSString *) descriptionWithLocale:(NSDictionary *) locale
+{
+ NSMutableString *theRet = [NSMutableString stringWithFormat:@"MCPRelation named %@, going from %@ to %@. Joins :\n", name, [origin name], [destination name]];
+ unsigned int i;
+
+ for (i = 0; [joins count] != i; ++i) {
+ MCPJoin *tmpJoin = (MCPJoin *)[joins objectAtIndex:i];
+ [theRet appendFormat:@"\t\t%@ == %@\n", [[tmpJoin origin] name], [[tmpJoin destination] name]];
+ }
+ return theRet;
+}
+
+
+#pragma mark For debugging the retain counting
+- (id) retain
+{
+ [super retain];
+ return self;
+}
+
+- (void) release
+{
+ [super release];
+ return;
+}
+
+@end
+
+@implementation MCPRelation (Private)
+
+#pragma mark Making some work
+- (void) invalidateJoins
+{
+ while ([joins count]) {
+ [[self objectInJoinsAtIndex:0] invalidate];
+ }
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+}
+
+#pragma mark Setters
+- (void) setOrigin:(MCPClassDescription *) iOrigin
+{
+ if (iOrigin != origin) {
+ [origin removeObjectFromRelationsAtIndex:[[origin relations] indexOfObjectIdenticalTo:self]];
+ origin = iOrigin;
+ [origin insertObject:self inRelationsAtIndex:[origin countOfRelations]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ [self invalidateJoins];
+ }
+}
+
+/*
+- (void) setJoins:(NSArray *) iJoins
+{
+ if (iJoins != joins) {
+ unsigned int i;
+ if (joins) {
+ [self invalidateJoins];
+ }
+ else {
+ joins = [[NSMutableArray alloc] init];
+ }
+ for (i=0; [iJoins count] != i; ++i) {
+ [self addJoinFrom:[(MCPJoin *)[iJoins objectAtIndex:i] origin] to:[(MCPJoin *)[iJoins objectAtIndex:i] destination]];
+ }
+ [[NSNotificationCenter defaultCenter] postNotificationName:MCPRelationChangedNotification object:self];
+ }
+}
+*/
+
+#pragma mark Getters
+- (MCPModel *) model
+{
+ return [origin model];
+}
+
+#pragma mark Fro the controller layer and the UI
+- (void) addNewDefaultJoin // Usefull for the interface, to be able to create a new join by just using a binding.
+{
+ [self addJoinFrom:[origin objectInAttributesAtIndex:0] to:[destination objectInAttributesAtIndex:0]];
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h
new file mode 100644
index 00000000..a6457494
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h
@@ -0,0 +1,226 @@
+//
+// $Id: MCPConnection.h 1069 2009-07-19 23:12:50Z rowanb $
+//
+// MCPConnection.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 08/12/2001.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+
+#import "MCPConstants.h"
+
+#import "mysql.h"
+
+@class MCPResult;
+@protocol MCPConnectionProxy;
+
+/**
+ * NSStringDataUsingLossyEncoding(aStr, enc, lossy) := [aStr dataUsingEncoding:enc allowLossyConversion:lossy]
+ */
+static inline NSData* NSStringDataUsingLossyEncoding(NSString* self, int encoding, int lossy)
+{
+ typedef NSData* (*SPStringDataUsingLossyEncodingMethodPtr)(NSString*, SEL, int, int);
+ static SPStringDataUsingLossyEncodingMethodPtr SPNSStringDataUsingLossyEncoding;
+ if (!SPNSStringDataUsingLossyEncoding) SPNSStringDataUsingLossyEncoding = (SPStringDataUsingLossyEncodingMethodPtr)[self methodForSelector:@selector(dataUsingEncoding:allowLossyConversion:)];
+ NSData* to_return = SPNSStringDataUsingLossyEncoding(self, @selector(dataUsingEncoding:allowLossyConversion:), encoding, lossy);
+ return to_return;
+}
+
+// Connection delegate interface
+@interface NSObject (MCPConnectionDelegate)
+
+- (void)willQueryString:(NSString *)query connection:(id)connection;
+- (void)queryGaveError:(NSString *)error connection:(id)connection;
+- (BOOL)connectionEncodingViaLatin1:(id)connection;
+- (NSString *)keychainPasswordForConnection:(id)connection;
+- (MCPConnectionCheck)connectionLost:(id)connection;
+
+@end
+
+@interface MCPConnection : NSObject
+{
+ MYSQL *mConnection; /* The inited MySQL connection. */
+ BOOL mConnected; /* Reflect the fact that the connection is already in place or not. */
+ NSStringEncoding mEncoding; /* The encoding used by MySQL server, to ISO-1 default. */
+ NSTimeZone *mTimeZone; /* The time zone of the session. */
+ unsigned int mConnectionFlags; /* The flags to be used for the connection to the database. */
+ id delegate; /* Connection delegate */
+
+ NSLock *queryLock; /* Anything that performs a mysql_net_read is not thread-safe: mysql queries, pings */
+
+ BOOL useKeepAlive;
+ int connectionTimeout;
+ float keepAliveInterval;
+
+ id <MCPConnectionProxy> connectionProxy;
+ NSString *connectionLogin;
+ NSString *connectionPassword;
+ NSString *connectionHost;
+ int connectionPort;
+ NSString *connectionSocket;
+ int maxAllowedPacketSize;
+ unsigned long connectionThreadId;
+
+ int currentProxyState;
+
+ double lastQueryExecutionTime;
+ double lastQueryExecutedAtTime;
+ NSString *lastQueryErrorMessage;
+ unsigned int lastQueryErrorId;
+ my_ulonglong lastQueryAffectedRows;
+
+ BOOL isMaxAllowedPacketEditable;
+
+ NSString *serverVersionString;
+
+ NSTimer *keepAliveTimer;
+ NSDate *lastKeepAliveSuccess;
+ uint64_t connectionStartTime;
+
+ BOOL retryAllowed;
+ BOOL delegateQueryLogging;
+ BOOL delegateResponseToWillQueryString;
+
+ // Pointers
+ IMP cStringPtr;
+ IMP willQueryStringPtr;
+ IMP stopKeepAliveTimerPtr;
+ IMP startKeepAliveTimerResettingStatePtr;
+ IMP timeConnectedPtr;
+
+ // Selectors
+ SEL cStringSEL;
+ SEL willQueryStringSEL;
+ SEL stopKeepAliveTimerSEL;
+ SEL startKeepAliveTimerResettingStateSEL;
+ SEL timeConnectedSEL;
+}
+
+@property (readwrite, assign) id delegate;
+@property (readwrite, assign) BOOL useKeepAlive;
+@property (readwrite, assign) BOOL delegateQueryLogging;
+@property (readwrite, assign) int connectionTimeout;
+@property (readwrite, assign) float keepAliveInterval;
+
+// Initialisation
+- (id)initToHost:(NSString *)host withLogin:(NSString *)login usingPort:(int)port;
+- (id)initToSocket:(NSString *)socket withLogin:(NSString *)login;
+
+// Connection details
+- (BOOL)setPort:(int)thePort;
+- (BOOL)setPassword:(NSString *)thePassword;
+
+// Proxy
+- (BOOL)setConnectionProxy:(id <MCPConnectionProxy>)proxy;
+- (void)connectionProxyStateChange:(id <MCPConnectionProxy>)proxy;
+
+// Connection
+- (BOOL)connect;
+- (void)disconnect;
+- (BOOL)reconnect;
+- (BOOL)isConnected;
+- (BOOL)checkConnection;
+- (BOOL)pingConnection;
+- (void)startKeepAliveTimerResettingState:(BOOL)resetState;
+- (void)stopKeepAliveTimer;
+- (void)keepAlive:(NSTimer *)theTimer;
+- (void)threadedKeepAlive;
+- (void)restoreConnectionDetails;
+- (void)setAllowQueryRetries:(BOOL)allow;
+- (double)timeConnected;
+
+// Server versions
+- (int)serverMajorVersion;
+- (int)serverMinorVersion;
+- (int)serverReleaseVersion;
+
+// MySQL defaults
++ (NSDictionary *)getMySQLLocales;
++ (NSStringEncoding)encodingForMySQLEncoding:(const char *)mysqlEncoding;
++ (NSStringEncoding)defaultMySQLEncoding;
++ (BOOL)isErrorNumberConnectionError:(int)theErrorNumber;
+
+// Class maintenance
++ (void)setTruncateLongFieldInLogs:(BOOL)iTruncFlag;
++ (BOOL)truncateLongField;
+- (BOOL)setConnectionOption:(int)option toValue:(BOOL)value;
+- (BOOL)connectWithLogin:(NSString *)login password:(NSString *)pass host:(NSString *)host port:(int)port socket:(NSString *)socket;
+
+- (BOOL)selectDB:(NSString *)dbName;
+
+// Error information
+- (NSString *)getLastErrorMessage;
+- (void)setLastErrorMessage:(NSString *)theErrorMessage;
+- (unsigned int)getLastErrorID;
++ (BOOL)isErrorNumberConnectionError:(int)theErrorNumber;
+
+// Queries
+- (NSString *)prepareBinaryData:(NSData *)theData;
+- (NSString *)prepareString:(NSString *)theString;
+- (NSString *)quoteObject:(id)theObject;
+- (MCPResult *)queryString:(NSString *)query;
+- (MCPResult *)queryString:(NSString *)query usingEncoding:(NSStringEncoding)encoding;
+- (double)lastQueryExecutionTime;
+- (my_ulonglong)affectedRows;
+- (my_ulonglong)insertId;
+
+// Database structure
+- (MCPResult *)listDBs;
+- (MCPResult *)listDBsLike:(NSString *)dbsName;
+- (MCPResult *)listTables;
+- (MCPResult *)listTablesLike:(NSString *)tablesName;
+- (MCPResult *)listTablesFromDB:(NSString *)dbName like:(NSString *)tablesName;
+- (MCPResult *)listFieldsFromTable:(NSString *)tableName;
+- (MCPResult *)listFieldsFromTable:(NSString *)tableName like:(NSString *)fieldsName;
+
+// Server information
+- (NSString *)clientInfo;
+- (NSString *)hostInfo;
+- (NSString *)serverInfo;
+- (NSNumber *)protoInfo;
+- (MCPResult *)listProcesses;
+- (BOOL)killProcess:(unsigned long)pid;
+- (NSString *)findSocketPath;
+
+// Encoding
+- (void)setEncoding:(NSStringEncoding)theEncoding;
+- (NSStringEncoding)encoding;
+
+// Time zone
+- (void)setTimeZone:(NSTimeZone *)iTimeZone;
+- (NSTimeZone *)timeZone;
+
+// Packet size
+- (BOOL)fetchMaxAllowedPacket;
+- (int)getMaxAllowedPacket;
+- (BOOL)isMaxAllowedPacketEditable;
+- (int)setMaxAllowedPacketTo:(int)newSize resetSize:(BOOL)reset;
+
+// Data conversion
+- (const char *)cStringFromString:(NSString *)theString;
+- (const char *)cStringFromString:(NSString *)theString usingEncoding:(NSStringEncoding)encoding;
+- (NSString *)stringWithCString:(const char *)theCString;
+- (NSString *)stringWithText:(NSData *)theTextData;
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m
new file mode 100644
index 00000000..fb0dcc10
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m
@@ -0,0 +1,1995 @@
+//
+// $Id: MCPConnection.m 1070 2009-07-19 23:21:19Z rowanb $
+//
+// MCPConnection.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 08/12/2001.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPConnection.h"
+#import "MCPResult.h"
+#import "MCPNumber.h"
+#import "MCPNull.h"
+#import "MCPConnectionProxy.h"
+
+#include <unistd.h>
+#include <setjmp.h>
+#include <mach/mach_time.h>
+
+static jmp_buf pingTimeoutJumpLocation;
+static void forcePingTimeout(int signalNumber);
+
+const unsigned int kMCPConnectionDefaultOption = CLIENT_COMPRESS;
+const char *kMCPConnectionDefaultSocket = MYSQL_UNIX_ADDR;
+const unsigned int kMCPConnection_Not_Inited = 1000;
+const unsigned int kLengthOfTruncationForLog = 100;
+
+static BOOL sTruncateLongFieldInLogs = YES;
+
+/**
+ * Privte API
+ */
+@interface MCPConnection (PrivateAPI)
+
+- (void)_getServerVersionString;
+
+@end
+
+@implementation MCPConnection
+
+// Synthesize ivars
+@synthesize delegate;
+@synthesize useKeepAlive;
+@synthesize delegateQueryLogging;
+@synthesize connectionTimeout;
+@synthesize keepAliveInterval;
+
+#pragma mark -
+#pragma mark Initialisation
+
+/**
+ * Initialise a MySQLConnection without making a connection, most likely useless, except with !{setConnectionOption:withArgument:}.
+ *
+ * Because this method is not making a connection to any MySQL server, it can not know already what the DB server encoding will be,
+ * hence the encoding is set to some default (at present this is NSISOLatin1StringEncoding). Obviously this is reset to a proper
+ * value as soon as a DB connection is performed.
+ */
+- (id)init
+{
+ if ((self = [super init])) {
+ mConnection = mysql_init(NULL);
+ mConnected = NO;
+
+ if (mConnection == NULL) {
+ [self autorelease];
+
+ return nil;
+ }
+
+ mEncoding = NSISOLatin1StringEncoding;
+ mConnectionFlags = kMCPConnectionDefaultOption;
+
+ queryLock = [[NSLock alloc] init];
+
+ connectionHost = nil;
+ connectionLogin = nil;
+ connectionSocket = nil;
+ connectionPassword = nil;
+ keepAliveTimer = nil;
+ connectionProxy = nil;
+ lastKeepAliveSuccess = nil;
+ connectionStartTime = -1;
+ lastQueryExecutedAtTime = INT_MAX;
+
+ // Initialize ivar defaults
+ connectionTimeout = 10;
+ useKeepAlive = YES;
+ keepAliveInterval = 60;
+
+ connectionThreadId = 0;
+ maxAllowedPacketSize = -1;
+ lastQueryExecutionTime = 0;
+ lastQueryErrorId = 0;
+ lastQueryErrorMessage = nil;
+ lastQueryAffectedRows = 0;
+
+ // Default to allowing queries to be reattempted if they fail due to connection issues
+ retryAllowed = YES;
+
+ // Obtain SEL references
+ willQueryStringSEL = @selector(willQueryString:connection:);
+ stopKeepAliveTimerSEL = @selector(stopKeepAliveTimer);
+ startKeepAliveTimerResettingStateSEL = @selector(startKeepAliveTimerResettingState:);
+ cStringSEL = @selector(cStringFromString:);
+
+ // Obtain pointers
+ cStringPtr = [self methodForSelector:cStringSEL];
+ stopKeepAliveTimerPtr = [self methodForSelector:stopKeepAliveTimerSEL];
+ startKeepAliveTimerResettingStatePtr = [self methodForSelector:startKeepAliveTimerResettingStateSEL];
+ }
+
+ return self;
+}
+
+/**
+ * Inialize connection using the supplied host details.
+ */
+- (id)initToHost:(NSString *)host withLogin:(NSString *)login usingPort:(int)port
+{
+ if ((self = [self init])) {
+ if (!host) host = @"";
+ if (!login) login = @"";
+
+ connectionHost = [[NSString alloc] initWithString:host];
+ connectionLogin = [[NSString alloc] initWithString:login];
+ connectionPort = port;
+ connectionSocket = nil;
+ }
+
+ return self;
+}
+
+/**
+ * Inialize connection using the supplied socket details.
+ */
+- (id)initToSocket:(NSString *)socket withLogin:(NSString *)login
+{
+ if ((self = [self init])) {
+ if (!socket || ![socket length]) {
+ socket = [self findSocketPath];
+ if (!socket) socket = @"";
+ }
+
+ if (!login) login = @"";
+
+ connectionHost = nil;
+ connectionLogin = [[NSString alloc] initWithString:login];
+ connectionSocket = [[NSString alloc] initWithString:socket];
+ connectionPort = 0;
+ }
+
+ return self;
+}
+
+#pragma mark -
+#pragma mark Connection details
+
+/**
+ * Sets or updates the connection port - for use with tunnels.
+ */
+- (BOOL)setPort:(int)thePort
+{
+ connectionPort = thePort;
+
+ return YES;
+}
+
+/**
+ * Sets the password to be stored locally.
+ * Providing a keychain name is much more secure.
+ */
+- (BOOL)setPassword:(NSString *)thePassword
+{
+ if (connectionPassword) [connectionPassword release], connectionPassword = nil;
+
+ if (!thePassword) thePassword = @"";
+
+ connectionPassword = [[NSString alloc] initWithString:thePassword];
+
+ return YES;
+}
+
+#pragma mark -
+#pragma mark Connection proxy
+
+/*
+ * Set a connection proxy object to connect through. This object will be retained locally,
+ * and will be automatically connected/connection checked/reconnected/disconnected
+ * together with the main connection.
+ */
+- (BOOL)setConnectionProxy:(id <MCPConnectionProxy>)proxy
+{
+ connectionProxy = proxy;
+ [connectionProxy retain];
+
+ currentProxyState = [connectionProxy state];
+ [connectionProxy setConnectionStateChangeSelector:@selector(connectionProxyStateChange:) delegate:self];
+
+ return YES;
+}
+
+/**
+ * Handle any state changes in the associated connection proxy.
+ */
+- (void)connectionProxyStateChange:(id <MCPConnectionProxy>)proxy
+{
+ int newState = [proxy state];
+
+ // Restart the tunnel if it dies
+ if (mConnected && newState == PROXY_STATE_IDLE && currentProxyState == PROXY_STATE_CONNECTED) {
+ currentProxyState = newState;
+ [connectionProxy setConnectionStateChangeSelector:nil delegate:nil];
+ [self reconnect];
+
+ return;
+ }
+
+ currentProxyState = newState;
+}
+
+#pragma mark -
+#pragma mark Connection
+
+/**
+ * Add a new connection method, intended for use with the init methods above.
+ * Uses the stored details to instantiate a connection to the specified server,
+ * including custom timeouts - used for pings, not for long-running commands.
+ */
+- (BOOL)connect
+{
+ const char *theLogin = [self cStringFromString:connectionLogin];
+ const char *theHost;
+ const char *thePass;
+ const char *theSocket;
+ void *theRet;
+
+ // Disconnect if a connection is already active
+ if (mConnected) {
+ [self disconnect];
+ mConnection = mysql_init(NULL);
+ if (mConnection == NULL) return NO;
+ }
+
+ if (mConnection != NULL) {
+
+ // Ensure the custom timeout option is set
+ mysql_options(mConnection, MYSQL_OPT_CONNECT_TIMEOUT, (const void *)&connectionTimeout);
+
+ // Set automatic reconnection for use with mysql_ping
+ // TODO: Automatic reconnection is currently used by MCPConnection, using thread IDs to
+ // detect when this has occurred. Custom reconnection may be preferable.
+ my_bool trueBool = TRUE;
+ mysql_options(mConnection, MYSQL_OPT_RECONNECT, &trueBool);
+
+ // Ensure compression is enabled where possible
+ mysql_options(mConnection, MYSQL_OPT_COMPRESS, 0);
+ }
+
+ // Set the host as appropriate
+ if (!connectionHost || ![connectionHost length]) {
+ theHost = NULL;
+
+
+ } else {
+ theHost = [self cStringFromString:connectionHost];
+ }
+
+ // Use the default socket if none is set, or set appropriately
+ if (connectionSocket == nil || ![connectionSocket length]) {
+ theSocket = kMCPConnectionDefaultSocket;
+ } else {
+ theSocket = [self cStringFromString:connectionSocket];
+ }
+
+ // Select the password from the provided method
+ if (!connectionPassword) {
+ if (delegate && [delegate respondsToSelector:@selector(keychainPasswordForConnection:)]) {
+ thePass = [self cStringFromString:[delegate keychainPasswordForConnection:self]];
+ }
+ } else {
+ thePass = [self cStringFromString:connectionPassword];
+ }
+
+ // Connect
+ theRet = mysql_real_connect(mConnection, theHost, theLogin, thePass, NULL, connectionPort, theSocket, mConnectionFlags);
+ thePass = NULL;
+
+ if (theRet != mConnection) {
+ [self setLastErrorMessage:nil];
+
+ lastQueryErrorId = mysql_errno(mConnection);
+
+ return mConnected = NO;
+ }
+
+ mConnected = YES;
+ connectionStartTime = mach_absolute_time();
+ mEncoding = [MCPConnection encodingForMySQLEncoding:mysql_character_set_name(mConnection)];
+ connectionThreadId = mConnection->thread_id;
+ [self timeZone]; // Getting the timezone used by the server.
+
+ isMaxAllowedPacketEditable = [self isMaxAllowedPacketEditable];
+
+ if (![self fetchMaxAllowedPacket]) {
+ [self setLastErrorMessage:nil];
+
+ lastQueryErrorId = mysql_errno(mConnection);
+
+ return mConnected = NO;
+ }
+
+ // Start the keepalive timer
+ [self startKeepAliveTimerResettingState:YES];
+
+ return mConnected;
+}
+
+/**
+ * Disconnect the current connection.
+ */
+- (void)disconnect
+{
+ if (mConnected) {
+ mysql_close(mConnection);
+ mConnection = NULL;
+ }
+
+ mConnected = NO;
+
+ if (connectionProxy) {
+ [connectionProxy disconnect];
+ }
+
+ if (serverVersionString != nil) {
+ [serverVersionString release];
+ serverVersionString = nil;
+ }
+
+ [self stopKeepAliveTimer];
+}
+
+/**
+ * Reconnect to the currently "active" - but possibly disconnected - connection, using the
+ * stored details.
+ * Error checks extensively - if this method fails, it will ask how to proceed and loop depending
+ * on the status, not returning control until either a connection has been established or
+ * the connection and document have been closed.
+ */
+- (BOOL)reconnect
+{
+ NSString *currentEncoding = nil;
+ BOOL currentEncodingUsesLatin1Transport = NO;
+ NSString *currentDatabase = nil;
+
+ // Store the current database and encoding so they can be re-set if reconnection was successful
+ if (delegate && [delegate valueForKey:@"selectedDatabase"]) {
+ currentDatabase = [NSString stringWithString:[delegate valueForKey:@"selectedDatabase"]];
+ }
+
+ if (delegate && [delegate valueForKey:@"_encoding"]) {
+ currentEncoding = [NSString stringWithString:[delegate valueForKey:@"_encoding"]];
+ }
+
+ if (delegate && [delegate respondsToSelector:@selector(connectionEncodingViaLatin1:)]) {
+ currentEncodingUsesLatin1Transport = [delegate connectionEncodingViaLatin1:self];
+ }
+
+ // Close the connection if it exists.
+ if (mConnected) {
+ mysql_close(mConnection);
+ mConnection = NULL;
+ }
+
+ mConnected = NO;
+
+ // If there is a tunnel, ensure it's disconnected and attempt to reconnect it in blocking fashion
+ if (connectionProxy) {
+ [connectionProxy setConnectionStateChangeSelector:nil delegate:nil];
+ if ([connectionProxy state] != PROXY_STATE_IDLE) [connectionProxy disconnect];
+ [connectionProxy connect];
+ NSDate *tunnelStartDate = [NSDate date], *interfaceInteractionTimer;
+
+ // Allow the tunnel to attempt to connect in a loop
+ while (1) {
+ if ([connectionProxy state] == PROXY_STATE_CONNECTED) {
+ connectionPort = [connectionProxy localPort];
+ break;
+ }
+ if ([[NSDate date] timeIntervalSinceDate:tunnelStartDate] > (connectionTimeout + 1)) {
+ [connectionProxy disconnect];
+ break;
+ }
+
+ // Process events for a short time, allowing dialogs to be shown but waiting for the tunnel
+ interfaceInteractionTimer = [NSDate date];
+ [[NSRunLoop currentRunLoop] runMode:NSModalPanelRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
+ tunnelStartDate = [tunnelStartDate addTimeInterval:([[NSDate date] timeIntervalSinceDate:interfaceInteractionTimer] - 0.25)];
+ }
+
+ currentProxyState = [connectionProxy state];
+ [connectionProxy setConnectionStateChangeSelector:@selector(sshTunnelStateChange:) delegate:self];
+ }
+
+ if (!connectionProxy || [connectionProxy state] == PROXY_STATE_CONNECTED) {
+
+ // Attempt to reinitialise the connection - if this fails, it will still be set to NULL.
+ if (mConnection == NULL) {
+ mConnection = mysql_init(NULL);
+ }
+
+ if (mConnection != NULL) {
+
+ // Attempt to reestablish the connection
+ [self connect];
+ }
+ }
+
+ // If the connection was successfully established, reselect the old database and encoding if appropriate.
+ if (mConnected) {
+ if (currentDatabase) {
+ [self selectDB:currentDatabase];
+ }
+
+ if (currentEncoding) {
+ [self queryString:[NSString stringWithFormat:@"/*!40101 SET NAMES '%@' */", currentEncoding]];
+ [self setEncoding:[MCPConnection encodingForMySQLEncoding:[currentEncoding UTF8String]]];
+ if (currentEncodingUsesLatin1Transport) {
+ [self queryString:@"/*!40101 SET CHARACTER_SET_RESULTS=latin1 */"];
+ }
+ }
+ }
+ else {
+ [self setLastErrorMessage:nil];
+
+ // Default to retry
+ MCPConnectionCheck failureDecision = MCPConnectionCheckReconnect;
+
+ // Ask delegate what to do
+ if ([delegate respondsToSelector:@selector(connectionLost:)]) {
+ failureDecision = [delegate connectionLost:self];
+ }
+
+ switch (failureDecision) {
+ case MCPConnectionCheckDisconnect:
+ return NO;
+ default:
+ return [self reconnect];
+ }
+ }
+
+ return mConnected;
+}
+
+/**
+ * Returns YES if the MCPConnection is connected to a DB, NO otherwise.
+ */
+- (BOOL)isConnected
+{
+ return mConnected;
+}
+
+/**
+ * Checks if the connection to the server is still on.
+ * If not, tries to reconnect (changing no parameters from the MYSQL pointer).
+ * This method just uses mysql_ping().
+ */
+- (BOOL)checkConnection
+{
+ if (!mConnected) return NO;
+
+ BOOL connectionVerified = FALSE;
+
+ // Check whether the connection is still operational via a wrapped version of MySQL ping.
+ connectionVerified = [self pingConnection];
+
+ // If the connection doesn't appear to be responding, show a dialog asking how to proceed
+ if (!connectionVerified) {
+
+ // Default to retry
+ MCPConnectionCheck failureDecision = MCPConnectionCheckRetry;
+
+ // Ask delegate what to do
+ if (delegate && [delegate respondsToSelector:@selector(connectionLost:)]) {
+ failureDecision = [delegate connectionLost:self];
+ } else {
+ failureDecision = MCPConnectionCheckDisconnect;
+ }
+
+ switch (failureDecision) {
+ // 'Reconnect' has been selected. Request a reconnect, and retry.
+ case MCPConnectionCheckReconnect:
+ [self reconnect];
+
+ return [self checkConnection];
+
+ // 'Disconnect' has been selected. Close the parent window, which will handle disconnections, and return false.
+ case MCPConnectionCheckDisconnect:
+ return NO;
+
+ // 'Retry' has been selected - return a recursive call.
+ case MCPConnectionCheckRetry:
+ return [self checkConnection];
+ }
+
+ // If a connection exists, check whether the thread id differs; if so, the connection has
+ // probably been reestablished and we need to reset the connection encoding
+ } else if (connectionThreadId != mConnection->thread_id) [self restoreConnectionDetails];
+
+ return connectionVerified;
+}
+
+/**
+ * This function provides a method of pinging the remote server while running a SIGALRM
+ * to enforce the specified connection time. This is low-level but effective, and required
+ * because low-level net reads can block indefintely if the remote server disappears or on
+ * network issues - setting the MYSQL_OPT_READ_TIMEOUT (and the WRITE equivalent) would "fix"
+ * ping, but cause long queries to be terminated.
+ * Unlike mysql_ping, this function returns FALSE on failure and TRUE on success.
+ */
+- (BOOL) pingConnection
+{
+ struct sigaction timeoutAction;
+ NSDate *startDate = [[NSDate alloc] initWithTimeIntervalSinceNow:0];
+ BOOL pingSuccess = FALSE;
+
+ // Construct the SIGALRM to fire after the connection timeout if it isn't cleared, calling the forcePingTimeout function.
+ timeoutAction.sa_handler = forcePingTimeout;
+ sigemptyset(&timeoutAction.sa_mask);
+ timeoutAction.sa_flags = 0;
+ sigaction(SIGALRM, &timeoutAction, NULL);
+ alarm(connectionTimeout+1);
+
+ [queryLock lock];
+
+ // Set up a "restore point", returning 0; if longjmp is used later with this reference, execution
+ // jumps back to this point and returns a nonzero value, so this function evaluates to false when initially
+ // set and true if it's called again.
+ if (setjmp(pingTimeoutJumpLocation)) {
+
+ // The connection timed out - we want to return false.
+ pingSuccess = FALSE;
+
+ // On direct execution:
+ } else {
+
+ // Run mysql_ping, which returns 0 on success, and otherwise an error.
+ pingSuccess = (BOOL)(! mysql_ping(mConnection));
+
+ // If the ping failed within a second, try another one; this is because a terminated-but-then
+ // restored connection is at times restored or functional after a ping, but the ping still returns
+ // an error. This additional check ensures the returned status is correct with minimal other effect.
+ if (!pingSuccess && ([startDate timeIntervalSinceNow] > -1)) {
+ pingSuccess = (BOOL)(! mysql_ping(mConnection));
+ }
+ }
+
+ [queryLock unlock];
+
+ // Reset and clear the SIGALRM used to check connection timeouts.
+ alarm(0);
+ timeoutAction.sa_handler = SIG_IGN;
+ sigemptyset(&timeoutAction.sa_mask);
+ timeoutAction.sa_flags = 0;
+ sigaction(SIGALRM, &timeoutAction, NULL);
+
+ [startDate release];
+
+ return pingSuccess;
+}
+
+/**
+ * This function is paired with pingConnection, and provides a method of enforcing the connection
+ * timeout when mysql_ping does not respect the specified limits.
+ */
+static void forcePingTimeout(int signalNumber)
+{
+ longjmp(pingTimeoutJumpLocation, 1);
+}
+
+/**
+ * Restarts a keepalive to fire in the future.
+ */
+- (void)startKeepAliveTimerResettingState:(BOOL)resetState
+{
+ if (keepAliveTimer) [self stopKeepAliveTimer];
+ if (!mConnected) return;
+
+ if (resetState && lastKeepAliveSuccess) {
+ [lastKeepAliveSuccess release];
+ lastKeepAliveSuccess = nil;
+ }
+
+ if (useKeepAlive && keepAliveInterval) {
+ keepAliveTimer = [NSTimer
+ scheduledTimerWithTimeInterval:keepAliveInterval
+ target:self
+ selector:@selector(keepAlive:)
+ userInfo:nil
+ repeats:NO];
+ [keepAliveTimer retain];
+ }
+}
+
+/**
+ * Stops a keepalive if one is set for the future.
+ */
+- (void)stopKeepAliveTimer
+{
+ if (!keepAliveTimer) return;
+ [keepAliveTimer invalidate];
+ [keepAliveTimer release];
+ keepAliveTimer = nil;
+}
+
+/**
+ * Keeps a connection alive by running a ping.
+ */
+- (void)keepAlive:(NSTimer *)theTimer
+{
+ if (!mConnected) return;
+
+ // If there a successful keepalive record exists, and it was more than 5*keepaliveinterval ago,
+ // abort. This prevents endless spawning of threads in a state where the connection has been
+ // cut but mysql doesn't pick up on the fact - see comment for pingConnection above. The same
+ // forced-timeout approach cannot be used here on a background thread.
+ // When the connection is disconnected in code, these 5 "hanging" threads are automatically cleaned.
+ if (lastKeepAliveSuccess && [lastKeepAliveSuccess timeIntervalSinceNow] < -5 * keepAliveInterval) return;
+
+ [NSThread detachNewThreadSelector:@selector(threadedKeepAlive) toTarget:self withObject:nil];
+ [self startKeepAliveTimerResettingState:NO];
+}
+
+/**
+ * A threaded keepalive to avoid blocking the interface
+ */
+- (void)threadedKeepAlive
+{
+ if (!mConnected) return;
+
+ if (![queryLock tryLock]) return;
+ [queryLock unlock];
+
+ // Don't wrap this ping in a lock - will block main thread on read issues, and can't use
+ // the setjmp/lngjmp safety net in a thread.
+ mysql_ping(mConnection);
+
+ if (lastKeepAliveSuccess) {
+ [lastKeepAliveSuccess release];
+ lastKeepAliveSuccess = nil;
+ }
+
+ lastKeepAliveSuccess = [[NSDate alloc] initWithTimeIntervalSinceNow:0];
+}
+
+/**
+ * Restore the connection encoding details as necessary based on the delegate-provided
+ * details.
+ */
+- (void)restoreConnectionDetails
+{
+ connectionThreadId = mConnection->thread_id;
+ connectionStartTime = mach_absolute_time();
+ [self fetchMaxAllowedPacket];
+
+ if (delegate && [delegate valueForKey:@"_encoding"]) {
+ [self queryString:[NSString stringWithFormat:@"/*!40101 SET NAMES '%@' */", [NSString stringWithString:[delegate valueForKey:@"_encoding"]]]];
+ if (delegate && [delegate respondsToSelector:@selector(connectionEncodingViaLatin1:)]) {
+ if ([delegate connectionEncodingViaLatin1:self]) [self queryString:@"/*!40101 SET CHARACTER_SET_RESULTS=latin1 */"];
+ }
+ }
+}
+
+/**
+ * Allow controlling over whether queries are allowed to retry after a connection failure.
+ * This defaults to YES on init, and is intended to allow temporary disabling in situations
+ * where the query result is checked and displayed to the user without any repurcussions on
+ * failure.
+ */
+- (void)setAllowQueryRetries:(BOOL)allow
+{
+ retryAllowed = allow;
+}
+
+/**
+ * Retrieve the time elapsed since the connection was established, in seconds.
+ * This time is retrieved in a monotonically increasing fashion and is high
+ * precision; it is used internally for query timing, and is reset on reconnections.
+ */
+- (double)timeConnected
+{
+ if (connectionStartTime == -1) return -1;
+
+ uint64_t currentTime_t = mach_absolute_time() - connectionStartTime;
+ Nanoseconds elapsedTime = AbsoluteToNanoseconds(*(AbsoluteTime *)&(currentTime_t));
+
+ return (((double)UnsignedWideToUInt64(elapsedTime)) * 1e-9);
+}
+
+#pragma mark -
+#pragma mark Server versions
+
+/**
+ * rReturn the server major version or -1 on fail
+ */
+- (int)serverMajorVersion
+{
+
+ if (mConnected) {
+ if (serverVersionString == nil) {
+ [self _getServerVersionString];
+ }
+
+ if (serverVersionString != nil) {
+ return [[[serverVersionString componentsSeparatedByString:@"."] objectAtIndex:0] intValue];
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Return the server minor version or -1 on fail
+ */
+- (int)serverMinorVersion
+{
+
+ if (mConnected) {
+ if (serverVersionString == nil) {
+ [self _getServerVersionString];
+ }
+
+ if(serverVersionString != nil) {
+ return [[[serverVersionString componentsSeparatedByString:@"."] objectAtIndex:1] intValue];
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Return the server release version or -1 on fail
+ */
+- (int)serverReleaseVersion
+{
+ if (mConnected) {
+ if (serverVersionString == nil) {
+ [self _getServerVersionString];
+ }
+
+ if (serverVersionString != nil) {
+ NSString *s = [[serverVersionString componentsSeparatedByString:@"."] objectAtIndex:2];
+ return [[[s componentsSeparatedByString:@"-"] objectAtIndex:0] intValue];
+ }
+ }
+
+ return -1;
+}
+
+#pragma mark -
+#pragma mark MySQL defaults
+
+/**
+ * This class is used to keep a connection with a MySQL server, it correspond to the MYSQL structure of the C API, or the database handle of the PERL DBI/DBD interface.
+ *
+ * You have to start any work on a MySQL server by getting a working MCPConnection object.
+ *
+ * Most likely you will use this kind of code:
+ *
+ *
+ * MCPConnection *theConnec = [MCPConnection alloc];
+ * MCPResult *theRes;
+ *
+ * theConnec = [theConnec initToHost:@"albert.com" withLogin:@"toto" password:@"albert" usingPort:0];
+ * [theConnec selectDB:@"db1"];
+ * theRes = [theConnec queryString:@"select * from table1"];
+ * ...
+ *
+ * Failing to properly release your MCPConnection(s) object might cause a MySQL crash!!! (recovered if the server was started using mysqld_safe).
+ *
+ * Gets a proper Locale dictionary to use formater to parse strings from MySQL.
+ * For example strings representing dates should give a proper Locales for use with methods such as NSDate::dateWithNaturalLanguageString: locales:
+ */
++ (NSDictionary *)getMySQLLocales
+{
+ NSMutableDictionary *theLocalDict = [NSMutableDictionary dictionaryWithCapacity:12];
+
+ [theLocalDict setObject:@"." forKey:@"NSDecimalSeparator"];
+
+ return [NSDictionary dictionaryWithDictionary:theLocalDict];
+}
+
+/**
+ * Gets a proper NSStringEncoding according to the given MySQL charset.
+ */
++ (NSStringEncoding) encodingForMySQLEncoding:(const char *)mysqlEncoding
+{
+ // Unicode encodings:
+ if (!strncmp(mysqlEncoding, "utf8", 4)) {
+ return NSUTF8StringEncoding;
+ }
+ if (!strncmp(mysqlEncoding, "ucs2", 4)) {
+ return NSUnicodeStringEncoding;
+ }
+
+ // Roman alphabet encodings:
+ if (!strncmp(mysqlEncoding, "ascii", 5)) {
+ return NSASCIIStringEncoding;
+ }
+ if (!strncmp(mysqlEncoding, "latin1", 6)) {
+ return NSISOLatin1StringEncoding;
+ }
+ if (!strncmp(mysqlEncoding, "macroman", 8)) {
+ return NSMacOSRomanStringEncoding;
+ }
+
+ // Roman alphabet with central/east european additions:
+ if (!strncmp(mysqlEncoding, "latin2", 6)) {
+ return NSISOLatin2StringEncoding;
+ }
+ if (!strncmp(mysqlEncoding, "cp1250", 6)) {
+ return NSWindowsCP1250StringEncoding;
+ }
+ if (!strncmp(mysqlEncoding, "win1250", 7)) {
+ return NSWindowsCP1250StringEncoding;
+ }
+ if (!strncmp(mysqlEncoding, "cp1257", 6)) {
+ return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingWindowsBalticRim);
+ }
+
+ // Additions for Turkish:
+ if (!strncmp(mysqlEncoding, "latin5", 6)) {
+ return NSWindowsCP1254StringEncoding;
+ }
+
+ // Greek:
+ if (!strncmp(mysqlEncoding, "greek", 5)) {
+ return NSWindowsCP1253StringEncoding;
+ }
+
+ // Cyrillic:
+ if (!strncmp(mysqlEncoding, "win1251ukr", 6)) {
+ return NSWindowsCP1251StringEncoding;
+ }
+ if (!strncmp(mysqlEncoding, "cp1251", 6)) {
+ return NSWindowsCP1251StringEncoding;
+ }
+ if (!strncmp(mysqlEncoding, "koi8_ru", 6)) {
+ return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingKOI8_R);
+ }
+ if (!strncmp(mysqlEncoding, "koi8_ukr", 6)) {
+ return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingKOI8_R);
+ }
+
+ // Arabic:
+ if (!strncmp(mysqlEncoding, "cp1256", 6)) {
+ return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingWindowsArabic);
+ }
+
+ // Hebrew:
+ if (!strncmp(mysqlEncoding, "hebrew", 6)) {
+ CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinHebrew);
+ }
+
+ // Asian:
+ if (!strncmp(mysqlEncoding, "ujis", 4)) {
+ return NSJapaneseEUCStringEncoding;
+ }
+ if (!strncmp(mysqlEncoding, "sjis", 4)) {
+ return NSShiftJISStringEncoding;
+ }
+ if (!strncmp(mysqlEncoding, "big5", 4)) {
+ return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingBig5);
+ }
+ if (!strncmp(mysqlEncoding, "euc_kr", 6)) {
+ return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_KR);
+ }
+ if (!strncmp(mysqlEncoding, "euckr", 5)) {
+ return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_KR);
+ }
+
+ // Default to iso latin 1, even if it is not exact (throw an exception?)
+ NSLog(@"WARNING: unknown name for MySQL encoding '%s'!\n\t\tFalling back to iso-latin1.", mysqlEncoding);
+
+ return NSISOLatin1StringEncoding;
+}
+
+/**
+ * Returns the default charset of the library mysqlclient used.
+ */
++ (NSStringEncoding)defaultMySQLEncoding
+{
+ return [MCPConnection encodingForMySQLEncoding:"utf8_general_ci"];
+}
+
+#pragma mark -
+#pragma mark Class maintenance
+
+/**
+ *
+ */
++ (void)setTruncateLongFieldInLogs:(BOOL)iTruncFlag
+{
+ sTruncateLongFieldInLogs = iTruncFlag;
+}
+
+/**
+ *
+ */
++ (BOOL)truncateLongField
+{
+ return sTruncateLongFieldInLogs;
+}
+
+/**
+ * This method is to be used for getting special option for a connection, in which case the MCPConnection
+ * has to be inited with the init method, then option are selected, finally connection is done using one
+ * of the connect methods:
+ *
+ * MCPConnection *theConnect = [[MCPConnection alloc] init];
+ *
+ * [theConnect setConnectionOption: option toValue: value];
+ * [theConnect connectToHost:albert.com withLogin:@"toto" password:@"albert" port:0];
+ *
+ */
+- (BOOL)setConnectionOption:(int)option toValue:(BOOL)value
+{
+ // So far do nothing except for testing if it's proper time for setting option
+ // What about if some option where setted and a connection is made again with connectTo...
+ if ((mConnected) || (! mConnection)) {
+ return FALSE;
+ }
+
+ if (value) { //Set this option to true
+ mConnectionFlags |= option;
+ }
+ else { //Set this option to false
+ mConnectionFlags &= (! option);
+ }
+
+ return YES;
+}
+
+/**
+ * The method used by !{initToHost:withLogin:password:usingPort:} and !{initToSocket:withLogin:password:}. Same information and use of the parameters:
+ *
+ * - login is the user name
+ * - pass is the password corresponding to the user name
+ * - host is the hostname or IP adress
+ * - port is the TCP port to use to connect. If port = 0, uses the default port from mysql.h
+ * - socket is the path to the socket (for the localhost)
+ *
+ * The socket is used if the host is set to !{@"localhost"}, to an empty or a !{nil} string
+ * For the moment the implementation might not be safe if you have a nil pointer to one of the NSString* variables (underestand: I don't know what the result will be).
+ */
+- (BOOL)connectWithLogin:(NSString *)login password:(NSString *)pass host:(NSString *)host port:(int)port socket:(NSString *)socket
+{
+ const char *theLogin = [self cStringFromString:login];
+ const char *theHost = [self cStringFromString:host];
+ const char *thePass = [self cStringFromString:pass];
+ const char *theSocket = [self cStringFromString:socket];
+ void *theRet;
+
+ if (mConnected) {
+ // Disconnect if it was already connected
+ mysql_close(mConnection);
+ mConnection = NULL;
+ mConnected = NO;
+ [self init];
+ }
+
+ if ([host isEqualToString:@""]) {
+ theHost = NULL;
+ }
+
+ if (theSocket == NULL) {
+ theSocket = kMCPConnectionDefaultSocket;
+ }
+
+ theRet = mysql_real_connect(mConnection, theHost, theLogin, thePass, NULL, port, theSocket, mConnectionFlags);
+ if (theRet != mConnection) {
+ return mConnected = NO;
+ }
+
+ mConnected = YES;
+ mEncoding = [MCPConnection encodingForMySQLEncoding:mysql_character_set_name(mConnection)];
+
+ // Getting the timezone used by the server.
+ [self timeZone];
+
+ return mConnected;
+}
+
+/**
+ * Selects a database to work with.
+ *
+ * The MCPConnection object needs to be properly inited and connected to a server.
+ * If a connection is not yet set or the selection of the database didn't work, returns NO. Returns YES in normal cases where the database is properly selected.
+ *
+ * So far, if dbName is a nil pointer it will return NO (as if it cannot connect), most likely this will throw an exception in the future.
+ */
+- (BOOL)selectDB:(NSString *) dbName
+{
+ if (!mConnected) return NO;
+
+ [self stopKeepAliveTimer];
+
+ if (![self checkConnection]) {
+ return NO;
+ }
+
+ if (dbName == nil) {
+ // Here we should throw an exception, impossible to select a databse if the string is indeed a nil pointer
+ return NO;
+ }
+
+ if (mConnected) {
+ const char *theDBName = [self cStringFromString:dbName];
+ [queryLock lock];
+ if (0 == mysql_select_db(mConnection, theDBName)) {
+ [queryLock unlock];
+ [self startKeepAliveTimerResettingState:YES];
+
+ return YES;
+ }
+ [queryLock unlock];
+ }
+
+ [self setLastErrorMessage:nil];
+
+ lastQueryErrorId = mysql_errno(mConnection);
+
+ if (connectionProxy) {
+ [connectionProxy disconnect];
+ }
+
+ return NO;
+}
+
+#pragma mark -
+#pragma mark Error information
+
+/**
+ * Returns a string with the last MySQL error message on the connection.
+ */
+- (NSString *)getLastErrorMessage
+{
+ return lastQueryErrorMessage;
+}
+
+/**
+ * Sets the string for the last MySQL error message on the connection,
+ * managing memory as appropriate. Supply a nil string to store the
+ * last error on the connection.
+ */
+- (void)setLastErrorMessage:(NSString *)theErrorMessage
+{
+ if (!theErrorMessage) theErrorMessage = [self stringWithCString:mysql_error(mConnection)];
+
+ if (lastQueryErrorMessage) [lastQueryErrorMessage release], lastQueryErrorMessage = nil;
+ lastQueryErrorMessage = [[NSString alloc] initWithString:theErrorMessage];
+}
+
+/**
+ * Returns the ErrorID of the last MySQL error on the connection.
+ */
+- (unsigned int)getLastErrorID
+{
+ return lastQueryErrorId;
+}
+
+/**
+ * Determines whether a supplied error number can be classed as a connection error.
+ */
++ (BOOL)isErrorNumberConnectionError:(int)theErrorNumber
+{
+
+ switch (theErrorNumber) {
+ case 2001: // CR_SOCKET_CREATE_ERROR
+ case 2002: // CR_CONNECTION_ERROR
+ case 2003: // CR_CONN_HOST_ERROR
+ case 2004: // CR_IPSOCK_ERROR
+ case 2005: // CR_UNKNOWN_HOST
+ case 2006: // CR_SERVER_GONE_ERROR
+ case 2007: // CR_VERSION_ERROR
+ case 2009: // CR_WRONG_HOST_INFO
+ case 2012: // CR_SERVER_HANDSHAKE_ERR
+ case 2013: // CR_SERVER_LOST
+ case 2027: // CR_MALFORMED_PACKET
+ case 2032: // CR_DATA_TRUNCATED
+ case 2047: // CR_CONN_UNKNOW_PROTOCOL
+ case 2048: // CR_INVALID_CONN_HANDLE
+ case 2050: // CR_FETCH_CANCELED
+ case 2055: // CR_SERVER_LOST_EXTENDED
+ return YES;
+ }
+
+ return NO;
+}
+
+#pragma mark -
+#pragma mark Queries
+
+/**
+ * Takes a NSData object and transform it in a proper string for sending to the server in between quotes.
+ */
+- (NSString *)prepareBinaryData:(NSData *)theData
+{
+ const char *theCDataBuffer = [theData bytes];
+ unsigned long theLength = [theData length];
+ char *theCEscBuffer = (char *)calloc(sizeof(char),(theLength*2) + 1);
+ NSString *theReturn;
+// unsigned long theEscapedLength;
+
+// Using the mysql_hex_string function : (NO other solution found to be able to support blobs while using UTF-8 charset).
+// theEscapedLength = mysql_hex_string(theCEscBuffer, theCDataBuffer, theLength);
+ mysql_hex_string(theCEscBuffer, theCDataBuffer, theLength);
+ theReturn = [NSString stringWithFormat:@"%s", theCEscBuffer];
+ free (theCEscBuffer);
+ return theReturn;
+}
+
+/**
+ * Takes a string and escape any special character (like single quote : ') so that the string can be used directly in a query.
+ */
+- (NSString *)prepareString:(NSString *)theString
+{
+ NSData *theCData = [theString dataUsingEncoding:mEncoding allowLossyConversion:YES];
+ unsigned long theLength = [theCData length];
+ // const char *theCStringBuffer = [self cStringFromString:theString];
+ // unsigned long theLength = [theString length];
+ char *theCEscBuffer;
+ NSString *theReturn;
+ unsigned long theEscapedLength;
+
+ if (theString == nil) {
+ // In the mean time, no one should call this method on a nil string, the test should be done before by the user of this method.
+ return @"";
+ }
+
+ // theLength = strlen(theCStringBuffer);
+ theCEscBuffer = (char *)calloc(sizeof(char),(theLength * 2) + 1);
+ theEscapedLength = mysql_real_escape_string(mConnection, theCEscBuffer, [theCData bytes], theLength);
+ theReturn = [[NSString alloc] initWithData:[NSData dataWithBytes:theCEscBuffer length:theEscapedLength] encoding:mEncoding];
+ // theReturn = [self stringWithCString:theCEscBuffer];
+ free(theCEscBuffer);
+
+ return theReturn;
+}
+
+/**
+ * Use the class of the theObject to know how it should be prepared for usage with the database.
+ * If theObject is a string, this method will put single quotes to both its side and escape any necessary
+ * character using prepareString: method. If theObject is NSData, the prepareBinaryData: method will be
+ * used instead.
+ *
+ * For NSNumber object, the number is just quoted, for calendar dates, the calendar date is formatted in
+ * the preferred format for the database.
+ */
+- (NSString *)quoteObject:(id)theObject
+{
+ if ((! theObject) || ([theObject isNSNull])) {
+ return @"NULL";
+ }
+
+ if ([theObject isKindOfClass:[NSData class]]) {
+ return [NSString stringWithFormat:@"X'%@'", [self prepareBinaryData:(NSData *) theObject]];
+ }
+
+ if ([theObject isKindOfClass:[NSString class]]) {
+ return [NSString stringWithFormat:@"'%@'", [self prepareString:(NSString *) theObject]];
+ }
+
+ if ([theObject isKindOfClass:[NSNumber class]]) {
+ return [NSString stringWithFormat:@"%@", theObject];
+ }
+
+ if ([theObject isKindOfClass:[NSCalendarDate class]]) {
+ return [NSString stringWithFormat:@"'%@'", [(NSCalendarDate *)theObject descriptionWithCalendarFormat:@"%Y-%m-%d %H:%M:%S"]];
+ }
+
+ return [NSString stringWithFormat:@"'%@'", [self prepareString:[theObject description]]];
+}
+
+/**
+ * Takes a query string and return an MCPResult object holding the result of the query.
+ * The returned MCPResult is not retained, the client is responsible for that (it's autoreleased before being returned). If no field are present in the result (like in an insert query), will return nil (#{difference from previous version implementation}). Though, if their is at least one field the result will be non nil (even if no row are selected).
+ *
+ * Note that if you want to use this method with binary data (in the query), you should use !{prepareBinaryData:} to include the binary data in the query string. Also if you want to include in your query a string containing any special character (\, ', " ...) then you should use !{prepareString}.
+ */
+- (MCPResult *)queryString:(NSString *)query
+{
+ return [self queryString:query usingEncoding:mEncoding];
+}
+
+/**
+ * Error checks connection extensively - if this method fails due to a connection error, it will ask how to
+ * proceed and loop depending on the status, not returning control until either the query has been executed
+ * and the result can be returned or the connection and document have been closed.
+ */
+- (MCPResult *)queryString:(NSString *) query usingEncoding:(NSStringEncoding) encoding
+{
+ MCPResult *theResult = nil;
+ double queryStartTime, queryExecutionTime;
+ const char *theCQuery;
+ unsigned long theCQueryLength;
+ int queryResultCode;
+ int queryErrorId = 0;
+ my_ulonglong queryAffectedRows = 0;
+ int currentMaxAllowedPacket = -1;
+ BOOL isQueryRetry = NO;
+ NSString *queryErrorMessage = nil;
+
+ // If no connection is present, return nil.
+ if (!mConnected) {
+ // Write a log entry
+ if ([delegate respondsToSelector:@selector(queryGaveError:connection:)]) [delegate queryGaveError:@"No connection available!" connection:self];
+ // Notify that the query has been performed
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self];
+ // Show an error alert while resetting
+ NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), @"No connection available!",
+ nil, nil, [delegate valueForKeyPath:@"tableWindow"], self, nil, nil, nil, @"No connection available!");
+ return nil;
+ }
+
+ (void)(*stopKeepAliveTimerPtr)(self, stopKeepAliveTimerSEL);
+
+ // Inform the delegate about the query if logging is enabled and delegate responds to willQueryString:connection:
+ if (delegateQueryLogging && delegateResponseToWillQueryString)
+ (void)(NSString*)(*willQueryStringPtr)(delegate, willQueryStringSEL, query);
+
+ // If thirty seconds have elapsed since the last query, check the connection. This provides
+ // a balance between keeping high read/write timeouts for long queries, network issues, and
+ // minimising the impact of performing lots of additional checks.
+ if ([self timeConnected] - lastQueryExecutedAtTime > 30
+ && ![self checkConnection]) return nil;
+
+ // Derive the query string in the correct encoding
+ NSData *d = NSStringDataUsingLossyEncoding(query, encoding, 1);
+ theCQuery = [d bytes];
+ // Set the length of the current query
+ theCQueryLength = [d length];
+
+ // Check query length against max_allowed_packet; if it is larger, the
+ // query would error, so if max_allowed_packet is editable for the user
+ // increase it for the current session and reconnect.
+ if (maxAllowedPacketSize < theCQueryLength) {
+
+ if (isMaxAllowedPacketEditable) {
+
+ currentMaxAllowedPacket = maxAllowedPacketSize;
+ [self setMaxAllowedPacketTo:strlen(theCQuery)+1024 resetSize:NO];
+ [self reconnect];
+
+ } else {
+
+ NSString *errorMessage = [NSString stringWithFormat:NSLocalizedString(@"The query length of %d bytes is larger than max_allowed_packet size (%d).",
+ @"error message if max_allowed_packet < query size"),
+ theCQueryLength, maxAllowedPacketSize];
+
+ // Write a log entry and update the connection error messages for those uses that check it
+ if ([delegate respondsToSelector:@selector(queryGaveError:connection:)]) [delegate queryGaveError:errorMessage connection:self];
+ [self setLastErrorMessage:errorMessage];
+
+ // Notify that the query has been performed
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self];
+ // Show an error alert while resetting
+ NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"),
+ nil, nil, [delegate valueForKeyPath:@"tableWindow"], self, nil, nil, nil, errorMessage);
+
+ return nil;
+ }
+ }
+
+ // In a loop to allow one reattempt, perform the query.
+ while (1) {
+
+ // If this query has failed once already, check the connection
+ if (isQueryRetry) {
+ if (![self checkConnection]) {
+
+ // Notify that the query has been performed
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self];
+ return nil;
+ }
+ }
+
+ [queryLock lock];
+
+ // Run (or re-run) the query, timing the execution time of the query - note
+ // that this time will include network lag.
+ queryStartTime = [self timeConnected];
+ queryResultCode = mysql_real_query(mConnection, theCQuery, theCQueryLength);
+ lastQueryExecutedAtTime = [self timeConnected];
+ queryExecutionTime = lastQueryExecutedAtTime - queryStartTime;
+
+ // On success, capture the results
+ if (0 == queryResultCode) {
+
+ if (mysql_field_count(mConnection) != 0) {
+ theResult = [[MCPResult alloc] initWithMySQLPtr:mConnection encoding:mEncoding timeZone:mTimeZone];
+
+ [queryLock unlock];
+
+ // Ensure no problem occurred during the result fetch
+ if (mysql_errno(mConnection) != 0) {
+ queryErrorMessage = [[NSString alloc] initWithString:[self stringWithCString:mysql_error(mConnection)]];
+ queryErrorId = mysql_errno(mConnection);
+ break;
+ }
+ } else {
+ [queryLock unlock];
+ }
+
+ queryErrorMessage = [[NSString alloc] initWithString:@""];
+ queryErrorId = 0;
+ queryAffectedRows = mysql_affected_rows(mConnection);
+
+ // On failure, set the error messages and IDs
+ } else {
+ [queryLock unlock];
+
+ queryErrorMessage = [[NSString alloc] initWithString:[self stringWithCString:mysql_error(mConnection)]];
+ queryErrorId = mysql_errno(mConnection);
+
+ // If the error was a connection error, retry once
+ if (!isQueryRetry && retryAllowed && [MCPConnection isErrorNumberConnectionError:queryErrorId]) {
+ isQueryRetry = YES;
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ // If the mysql thread id has changed as a result of a connection error,
+ // ensure connection details are still correct
+ if (connectionThreadId != mConnection->thread_id) [self restoreConnectionDetails];
+
+ // If max_allowed_packet was changed, reset it to default
+ if(currentMaxAllowedPacket > -1)
+ [self setMaxAllowedPacketTo:currentMaxAllowedPacket resetSize:YES];
+
+ // Update error strings and IDs
+ lastQueryErrorId = queryErrorId;
+ [self setLastErrorMessage:queryErrorMessage?queryErrorMessage:@""];
+ if (queryErrorMessage) [queryErrorMessage release];
+ lastQueryAffectedRows = queryAffectedRows;
+ lastQueryExecutionTime = queryExecutionTime;
+
+ // If an error occurred, inform the delegate
+ if (queryResultCode & delegateResponseToWillQueryString)
+ [delegate queryGaveError:lastQueryErrorMessage connection:self];
+
+ (void)(*startKeepAliveTimerResettingStatePtr)(self, startKeepAliveTimerResettingStateSEL, YES);
+
+ if (!theResult) return nil;
+ return [theResult autorelease];
+}
+
+/**
+ * Return the time taken to execute the last query. This should be close to the time it took
+ * the server to run the query, but will include network lag and some client library overhead.
+ */
+- (double)lastQueryExecutionTime
+{
+ return lastQueryExecutionTime;
+}
+
+/**
+ * Returns the number of affected rows by the last query.
+ */
+- (my_ulonglong)affectedRows
+{
+ if (mConnected) {
+ return mysql_affected_rows(mConnection);
+ }
+
+ return 0;
+}
+
+/**
+ * If the last query was an insert in a table having a autoindex column, returns the ID
+ * (autoindexed field) of the last row inserted.
+ */
+- (my_ulonglong)insertId
+{
+ if (mConnected) {
+ return mysql_insert_id(mConnection);
+ }
+
+ return 0;
+}
+
+#pragma mark -
+#pragma mark Database structure
+
+/**
+ * Just a fast wrapper for the more complex !{listDBsWithPattern:} method.
+ */
+- (MCPResult *)listDBs
+{
+ return [self listDBsLike:nil];
+}
+
+/**
+ * Returns a list of database which name correspond to the SQL regular expression in 'pattern'.
+ * The comparison is done with wild card extension : % and _.
+ * The result should correspond to the queryString:@"SHOW databases [LIKE wild]"; but implemented with mysql_list_dbs.
+ * If an empty string or nil is passed as pattern, all databases will be shown.
+ */
+- (MCPResult *)listDBsLike:(NSString *)dbsName
+{
+ if (!mConnected) return NO;
+
+ MCPResult *theResult = [MCPResult alloc];
+ MYSQL_RES *theResPtr;
+
+ [self stopKeepAliveTimer];
+
+ if (![self checkConnection]) return [[[MCPResult alloc] init] autorelease];
+
+ [self startKeepAliveTimerResettingState:YES];
+
+ [queryLock lock];
+ if ((dbsName == nil) || ([dbsName isEqualToString:@""])) {
+ if (theResPtr = mysql_list_dbs(mConnection, NULL)) {
+ [theResult initWithResPtr: theResPtr encoding: mEncoding timeZone:mTimeZone];
+ }
+ else {
+ [theResult init];
+ }
+ }
+ else {
+ const char *theCDBsName = (const char *)[self cStringFromString:dbsName];
+
+ if (theResPtr = mysql_list_dbs(mConnection, theCDBsName)) {
+ [theResult initWithResPtr: theResPtr encoding: mEncoding timeZone:mTimeZone];
+ }
+ else {
+ [theResult init];
+ }
+ }
+ [queryLock unlock];
+
+ if (theResult) {
+ [theResult autorelease];
+ }
+
+ return theResult;
+}
+
+/**
+ * Make sure a DB is selected (with !{selectDB:} method) first.
+ */
+- (MCPResult *)listTables
+{
+ return [self listTablesLike:nil];
+}
+
+/**
+ * From within a database, give back the list of table which name correspond to tablesName
+ * (with wild card %, _ extension). Correspond to queryString:@"SHOW tables [LIKE wild]"; uses mysql_list_tables function.
+ *
+ * If an empty string or nil is passed as tablesName, all tables will be shown.
+ *
+ * WARNING: #{produce an error if no databases are selected} (with !{selectDB:} for example).
+ */
+- (MCPResult *)listTablesLike:(NSString *)tablesName
+{
+ if (!mConnected) return NO;
+
+ MCPResult *theResult = [MCPResult alloc];
+ MYSQL_RES *theResPtr;
+
+ [self stopKeepAliveTimer];
+
+ if (![self checkConnection]) return [[[MCPResult alloc] init] autorelease];
+
+ [self startKeepAliveTimerResettingState:YES];
+
+ [queryLock lock];
+ if ((tablesName == nil) || ([tablesName isEqualToString:@""])) {
+ if (theResPtr = mysql_list_tables(mConnection, NULL)) {
+ [theResult initWithResPtr: theResPtr encoding: mEncoding timeZone:mTimeZone];
+ }
+ else {
+ [theResult init];
+ }
+ }
+ else {
+ const char *theCTablesName = (const char *)[self cStringFromString:tablesName];
+ if (theResPtr = mysql_list_tables(mConnection, theCTablesName)) {
+ [theResult initWithResPtr: theResPtr encoding: mEncoding timeZone:mTimeZone];
+ }
+ else {
+ [theResult init];
+ }
+ }
+ [queryLock unlock];
+
+ if (theResult) {
+ [theResult autorelease];
+ }
+ return theResult;
+}
+
+/**
+ * List tables in DB specified by dbName and corresponding to pattern.
+ * This method indeed issues a !{SHOW TABLES FROM dbName LIKE ...} query to the server.
+ * This is done this way to make sure the selected DB is not changed by this method.
+ */
+- (MCPResult *)listTablesFromDB:(NSString *)dbName like:(NSString *)tablesName
+{
+ MCPResult *theResult;
+
+ if ((tablesName == nil) || ([tablesName isEqualToString:@""])) {
+ NSString *theQuery = [NSString stringWithFormat:@"SHOW TABLES FROM %@", dbName];
+ theResult = [self queryString:theQuery];
+ }
+ else {
+ NSString *theQuery = [NSString stringWithFormat:@"SHOW TABLES FROM %@ LIKE '%@'", dbName, tablesName];
+ theResult = [self queryString:theQuery];
+ }
+
+ return theResult;
+}
+
+/**
+ * Just a fast wrapper for the more complex list !{listFieldsWithPattern:forTable:} method.
+ */
+- (MCPResult *)listFieldsFromTable:(NSString *)tableName
+{
+ return [self listFieldsFromTable:tableName like:nil];
+}
+
+/**
+ * Show all the fields of the table tableName which name correspond to pattern (with wild card expansion : %,_).
+ * Indeed, and as recommanded from mysql reference, this method is NOT using mysql_list_fields but the !{queryString:} method.
+ * If an empty string or nil is passed as fieldsName, all fields (of tableName) will be returned.
+ */
+- (MCPResult *)listFieldsFromTable:(NSString *)tableName like:(NSString *)fieldsName
+{
+ MCPResult *theResult;
+
+ if ((fieldsName == nil) || ([fieldsName isEqualToString:@""])) {
+ NSString *theQuery = [NSString stringWithFormat:@"SHOW COLUMNS FROM %@", tableName];
+ theResult = [self queryString:theQuery];
+ }
+ else {
+ NSString *theQuery = [NSString stringWithFormat:@"SHOW COLUMNS FROM %@ LIKE '%@'", tableName, fieldsName];
+ theResult = [self queryString:theQuery];
+ }
+
+ return theResult;
+}
+
+#pragma mark -
+#pragma mark Server information
+
+/**
+ * Returns a string giving the client library version.
+ */
+- (NSString *)clientInfo
+{
+ return [self stringWithCString:mysql_get_client_info()];
+}
+
+/**
+ * Returns a string giving information on the host of the DB server.
+ */
+- (NSString *)hostInfo
+{
+ return [self stringWithCString:mysql_get_host_info(mConnection)];
+}
+
+/**
+ * Returns a string giving the server version.
+ */
+- (NSString *)serverInfo
+{
+ if (mConnected) {
+ return [self stringWithCString: mysql_get_server_info(mConnection)];
+ }
+
+ return @"";
+}
+
+/**
+ * Returns the number of the protocole used to transfer info from server to client
+ */
+- (NSNumber *)protoInfo
+{
+ return [MCPNumber numberWithUnsignedInt:mysql_get_proto_info(mConnection)];
+}
+
+/**
+ * Lists active process
+ */
+- (MCPResult *)listProcesses
+{
+ MCPResult *theResult = [MCPResult alloc];
+ MYSQL_RES *theResPtr;
+
+ [queryLock lock];
+ if (theResPtr = mysql_list_processes(mConnection)) {
+ [theResult initWithResPtr:theResPtr encoding:mEncoding timeZone:mTimeZone];
+ }
+ else {
+ [theResult init];
+ }
+ [queryLock unlock];
+
+ if (theResult) {
+ [theResult autorelease];
+ }
+
+ return theResult;
+}
+
+/**
+ * Kills the process with the given pid.
+ * The users needs the !{Process_priv} privilege.
+ */
+- (BOOL)killProcess:(unsigned long)pid
+{
+ int theErrorCode = mysql_kill(mConnection, pid);
+
+ return (theErrorCode) ? NO : YES;
+}
+
+/*
+ * Check some common locations for the presence of a MySQL socket file, returning
+ * it if successful.
+ */
+- (NSString *)findSocketPath
+{
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+
+ NSArray *possibleSocketLocations = [NSArray arrayWithObjects:
+ @"/tmp/mysql.sock", // Default
+ @"/var/run/mysqld/mysqld.sock", // As used on Debian/Gentoo
+ @"/var/tmp/mysql.sock", // As used on FreeBSD
+ @"/var/lib/mysql/mysql.sock", // As used by Fedora
+ @"/opt/local/lib/mysql/mysql.sock", // Alternate fedora
+ @"/opt/local/var/run/mysqld/mysqld.sock", // Darwinports MySQL
+ @"/opt/local/var/run/mysql4/mysqld.sock", // Darwinports MySQL 4
+ @"/opt/local/var/run/mysql5/mysqld.sock", // Darwinports MySQL 5
+ @"/Applications/MAMP/tmp/mysql/mysql.sock", // MAMP default location
+ nil];
+
+ for (int i = 0; i < [possibleSocketLocations count]; i++)
+ {
+ if ([fileManager fileExistsAtPath:[possibleSocketLocations objectAtIndex:i]])
+ return [possibleSocketLocations objectAtIndex:i];
+ }
+
+ return nil;
+}
+
+#pragma mark -
+#pragma mark Encoding
+
+/**
+ * Sets the encoding used by the server for data transfer.
+ * Used to make sure the output of the query result is ok even for non-ascii characters
+ * The character set (encoding) used by the db is passed to the MCPConnection object upon connection,
+ * so most likely the encoding (from -encoding) method is already the proper one.
+ * That is to say : It's unlikely you will need to call this method directly, and #{if ever you use it, do it at your own risks}.
+ */
+- (void)setEncoding:(NSStringEncoding)theEncoding
+{
+ mEncoding = theEncoding;
+}
+
+/**
+ * Gets the encoding for the connection
+ */
+- (NSStringEncoding)encoding
+{
+ return mEncoding;
+}
+
+#pragma mark -
+#pragma mark Time Zone
+
+/**
+ * Setting the time zone to be used with the server.
+ */
+- (void)setTimeZone:(NSTimeZone *)iTimeZone
+{
+ if (iTimeZone != mTimeZone) {
+ [mTimeZone release];
+ mTimeZone = [iTimeZone retain];
+ }
+
+ if ([self checkConnection]) {
+ if (mTimeZone) {
+ [self queryString:[NSString stringWithFormat:@"SET time_zone = '%@'", [mTimeZone name]]];
+ }
+ else {
+ [self queryString:@"SET time_zone = 'SYSTEM'"];
+ }
+ }
+}
+
+/**
+ * Getting the currently used time zone (in communication with the DB server).
+ */
+- (NSTimeZone *)timeZone
+{
+ if ([self checkConnection]) {
+ MCPResult *theSessionTZ = [self queryString:@"SHOW VARIABLES LIKE '%time_zone'"];
+ NSArray *theRow;
+ id theTZName;
+ NSTimeZone *theTZ;
+
+ [theSessionTZ dataSeek:1ULL];
+ theRow = [theSessionTZ fetchRowAsArray];
+ theTZName = [theRow objectAtIndex:1];
+
+ if ( [theTZName isKindOfClass:[NSData class]] ) {
+ // MySQL 4.1.14 returns the mysql variables as NSData
+ theTZName = [self stringWithText:theTZName];
+ }
+
+ if ([theTZName isEqualToString:@"SYSTEM"]) {
+ [theSessionTZ dataSeek:0ULL];
+ theRow = [theSessionTZ fetchRowAsArray];
+ theTZName = [theRow objectAtIndex:1];
+
+ if ( [theTZName isKindOfClass:[NSData class]] ) {
+ // MySQL 4.1.14 returns the mysql variables as NSData
+ theTZName = [self stringWithText:theTZName];
+ }
+ }
+
+ if (theTZName) { // Old versions of the server does not support there own time zone ?
+ theTZ = [NSTimeZone timeZoneWithName:theTZName];
+ } else {
+ // By default set the time zone to the local one..
+ // Try to get the name using the previously available variable:
+ theSessionTZ = [self queryString:@"SHOW VARIABLES LIKE 'timezone'"];
+ [theSessionTZ dataSeek:0ULL];
+ theRow = [theSessionTZ fetchRowAsArray];
+ theTZName = [theRow objectAtIndex:1];
+ if (theTZName) {
+ // Finally we found one ...
+ theTZ = [NSTimeZone timeZoneWithName:theTZName];
+ } else {
+ theTZ = [NSTimeZone defaultTimeZone];
+ //theTZ = [NSTimeZone systemTimeZone];
+ NSLog(@"The time zone is not defined on the server, set it to the default one : %@", theTZ);
+ }
+ }
+
+ if (theTZ != mTimeZone) {
+ [mTimeZone release];
+ mTimeZone = [theTZ retain];
+ }
+ }
+
+ return mTimeZone;
+}
+
+#pragma mark -
+#pragma mark Packet size
+
+/**
+ * Retrieve the max_allowed_packet size from the server; returns
+ * false if the query fails.
+ */
+- (BOOL)fetchMaxAllowedPacket
+{
+ char *queryString;
+
+ if ([self serverMajorVersion] == 3) queryString = "SHOW VARIABLES LIKE 'max_allowed_packet'";
+ else queryString = "SELECT @@global.max_allowed_packet";
+
+ [queryLock lock];
+ if (0 == mysql_query(mConnection, queryString)) {
+ if (mysql_field_count(mConnection) != 0) {
+ MCPResult *r = [[MCPResult alloc] initWithMySQLPtr:mConnection encoding:mEncoding timeZone:mTimeZone];
+ NSArray *a = [r fetchRowAsArray];
+ [r autorelease];
+ if([a count]) {
+ maxAllowedPacketSize = [[a objectAtIndex:([self serverMajorVersion] == 3)?1:0] intValue];
+ [queryLock unlock];
+ return true;
+ }
+ }
+ }
+ [queryLock unlock];
+
+ return false;
+}
+
+/**
+ * Retrieves max_allowed_packet size set as global variable.
+ * It returns -1 if it fails.
+ */
+- (int)getMaxAllowedPacket
+{
+ MCPResult *r;
+ r = [self queryString:@"SELECT @@global.max_allowed_packet" usingEncoding:mEncoding];
+ if (![[self getLastErrorMessage] isEqualToString:@""]) {
+ if ([self isConnected])
+ NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while retrieving max_allowed_packet size:\n\n%@", [self getLastErrorMessage]], @"OK", nil, nil);
+ return -1;
+ }
+ NSArray *a = [r fetchRowAsArray];
+ if([a count])
+ return [[a objectAtIndex:0] intValue];
+
+ return -1;
+}
+
+/*
+ * It sets max_allowed_packet size to newSize and it returns
+ * max_allowed_packet after setting it to newSize for cross-checking
+ * if the maximal size was reached (e.g. set it to 4GB it'll return 1GB up to now).
+ * If something failed it return -1;
+ */
+- (int)setMaxAllowedPacketTo:(int)newSize resetSize:(BOOL)reset
+{
+ if(![self isMaxAllowedPacketEditable] || newSize < 1024) return maxAllowedPacketSize;
+
+ [queryLock lock];
+ mysql_query(mConnection, [[NSString stringWithFormat:@"SET GLOBAL max_allowed_packet = %d", newSize] UTF8String]);
+ [queryLock unlock];
+
+ // Inform the user via a log entry about that change according to reset value
+ if(delegate && [delegate respondsToSelector:@selector(queryGaveError:connection:)])
+ if(reset)
+ [delegate queryGaveError:[NSString stringWithFormat:@"max_allowed_packet was reset to %d for new session", newSize] connection:self];
+ else
+ [delegate queryGaveError:[NSString stringWithFormat:@"Query too large; max_allowed_packet temporarily set to %d for the current session to allow query to succeed", newSize] connection:self];
+
+ return maxAllowedPacketSize;
+}
+
+/**
+ * It returns whether max_allowed_packet is setable for the user.
+ */
+- (BOOL)isMaxAllowedPacketEditable
+{
+ BOOL isEditable;
+
+ [queryLock lock];
+ isEditable = !mysql_query(mConnection, "SET GLOBAL max_allowed_packet = @@global.max_allowed_packet");
+ [queryLock unlock];
+
+ return isEditable;
+}
+
+#pragma mark -
+#pragma mark Data conversion
+
+/**
+ * For internal use only. Transforms a NSString to a C type string (ending with \0) using the character set from the MCPConnection.
+ * Lossy conversions are enabled.
+ */
+- (const char *)cStringFromString:(NSString *)theString
+{
+ NSMutableData *theData;
+
+ if (! theString) {
+ return (const char *)NULL;
+ }
+
+ theData = [NSMutableData dataWithData:[theString dataUsingEncoding:mEncoding allowLossyConversion:YES]];
+ [theData increaseLengthBy:1];
+
+ return (const char *)[theData bytes];
+}
+
+/**
+ * Modified version of the original to support a supplied encoding.
+ * For internal use only. Transforms a NSString to a C type string (ending with \0).
+ * Lossy conversions are enabled.
+ */
+- (const char *)cStringFromString:(NSString *)theString usingEncoding:(NSStringEncoding)encoding
+{
+ NSMutableData *theData;
+
+ if (! theString) {
+ return (const char *)NULL;
+ }
+
+ theData = [NSMutableData dataWithData:[theString dataUsingEncoding:encoding allowLossyConversion:YES]];
+ [theData increaseLengthBy:1];
+
+ return (const char *)[theData bytes];
+}
+
+/**
+ * Returns a NSString from a C style string encoded with the character set of theMCPConnection.
+ */
+- (NSString *)stringWithCString:(const char *)theCString
+{
+ NSData *theData;
+ NSString *theString;
+
+ if (theCString == NULL) {
+ return @"";
+ }
+
+ theData = [NSData dataWithBytes:theCString length:(strlen(theCString))];
+ theString = [[NSString alloc] initWithData:theData encoding:mEncoding];
+
+ if (theString) {
+ [theString autorelease];
+ }
+
+ return theString;
+}
+
+/**
+ * Use the string encoding to convert the returned NSData to a string (for a Text field).
+ */
+- (NSString *)stringWithText:(NSData *)theTextData
+{
+ NSString *theString;
+
+ if (theTextData == nil) {
+ return nil;
+ }
+
+ theString = [[NSString alloc] initWithData:theTextData encoding:mEncoding];
+
+ if (theString) {
+ [theString autorelease];
+ }
+
+ return theString;
+}
+
+#pragma mark -
+
+/**
+ * Object deallocation.
+ */
+- (void) dealloc
+{
+ delegate = nil;
+
+ if (lastQueryErrorMessage) [lastQueryErrorMessage release];
+ if (connectionHost) [connectionHost release];
+ if (connectionLogin) [connectionLogin release];
+ if (connectionSocket) [connectionSocket release];
+ if (connectionPassword) [connectionPassword release];
+ if (lastKeepAliveSuccess) [lastKeepAliveSuccess release];
+ [queryLock release];
+
+ [super dealloc];
+}
+
+@end
+
+@implementation MCPConnection (PrivateAPI)
+
+/**
+ * Get the server's version string
+ */
+- (void)_getServerVersionString
+{
+ if (mConnected) {
+ MCPResult *theResult = [self queryString:@"SHOW VARIABLES WHERE Variable_name = 'version'"];
+
+ if ([theResult numOfRows]) {
+ [theResult dataSeek:0];
+ serverVersionString = [[NSString stringWithString:[[theResult fetchRowAsArray] objectAtIndex:1]] retain];
+ }
+ }
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnectionProxy.h b/Frameworks/MCPKit/MCPFoundationKit/MCPConnectionProxy.h
new file mode 100644
index 00000000..6d643bfa
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnectionProxy.h
@@ -0,0 +1,70 @@
+//
+// $Id: MCPConnectionProxy.h 1052 2009-07-17 17:49:07Z stuart02 $
+//
+// MCPConnectionProxy.h
+// MCPKit
+//
+// Created by Stuart Connolly (stuconnolly.com) on July 2, 2009.
+// Copyright (c) 2009 Stuart Connolly. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+
+/**
+ * Connection proxy state constants.
+ */
+enum PROXY_TUNNEL_STATES
+{
+ PROXY_STATE_IDLE = 0,
+ PROXY_STATE_CONNECTING = 1,
+ PROXY_STATE_WAITING_FOR_AUTH = 2,
+ PROXY_STATE_CONNECTED = 3,
+ PROXY_STATE_FORWARDING_FAILED = 4
+};
+
+@protocol MCPConnectionProxy <NSObject>
+
+/**
+ * Connect the proxy.
+ */
+- (void)connect;
+
+/**
+ * Disconnect the proxy.
+ */
+- (void)disconnect;
+
+/**
+ * Get the current state of the proxy.
+ */
+- (int)state;
+
+/**
+ * Get the local port being used by the proxy.
+ */
+- (int)localPort;
+
+/**
+ * Sets the method the proxy should call whenever the state of the connection changes.
+ */
+- (BOOL)setConnectionStateChangeSelector:(SEL)theStateChangeSelector delegate:(id)theDelegate;
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConstants.h b/Frameworks/MCPKit/MCPFoundationKit/MCPConstants.h
new file mode 100644
index 00000000..284623cd
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConstants.h
@@ -0,0 +1,64 @@
+//
+// $Id: MCPConstants.h 1036 2009-07-17 00:29:44Z stuart02 $
+//
+// MCPConstants.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 03/06/2001.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+// Result type constants
+typedef enum {
+ MCPTypeArray = 1,
+ MCPTypeDictionary = 2,
+ MCPTypeFlippedArray = 3,
+ MCPTypeFlippedDictionary = 4
+} MCPReturnType;
+
+// Connection check constants
+typedef enum {
+ MCPConnectionCheckRetry = 0,
+ MCPConnectionCheckReconnect = 1,
+ MCPConnectionCheckDisconnect = 2
+} MCPConnectionCheck;
+
+// Charcater set mapping constants
+typedef struct _OUR_CHARSET
+{
+ unsigned int nr;
+ const char *name;
+ const char *collation;
+ unsigned int char_minlen;
+ unsigned int char_maxlen;
+} OUR_CHARSET;
+
+// Deafult connection option
+extern const unsigned int kMCPConnectionDefaultOption;
+
+// Default socket (from the mysql.h used at compile time)
+extern const char *kMCPConnectionDefaultSocket;
+
+// Added to MySQL error code
+extern const unsigned int kMCPConnectionNotInited;
+
+// The length of the truncation if required
+extern const unsigned int kLengthOfTruncationForLog;
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPFastQueries.h b/Frameworks/MCPKit/MCPFoundationKit/MCPFastQueries.h
new file mode 100644
index 00000000..144d8e79
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPFastQueries.h
@@ -0,0 +1,46 @@
+//
+// $Id: MCPFastQueries.h 1056 2009-07-18 10:42:29Z stuart02 $
+//
+// MCPFastQueries.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 03/06/2002.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+
+#import "MCPConnection.h"
+
+@interface MCPConnection (MCPFastQueries)
+
+// For insert queries, get directly the Id of the newly inserted row.
+- (my_ulonglong)insertQuery:(NSString *)query;
+- (my_ulonglong)updateQuery:(NSString *)query;
+
+// Returns directly a proper NS object, or a collection (NSArray, NSDictionary...).
+- (id)getFirstFieldFromQuery:(NSString *)query;
+- (id)getFirstRowFromQuery:(NSString *)query asType:(MCPReturnType)type;
+- (id)getAllRowsFromQuery:(NSString *)query asType:(MCPReturnType)type;
+- (NSArray *)getQuery:(NSString *)query colWithIndex:(unsigned int)col;
+- (NSArray *)getQuery:(NSString *)query colWithName:(NSString *)colName;
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPFastQueries.m b/Frameworks/MCPKit/MCPFoundationKit/MCPFastQueries.m
new file mode 100644
index 00000000..951d29af
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPFastQueries.m
@@ -0,0 +1,113 @@
+//
+// $Id: MCPFastQueries.m 1056 2009-07-18 10:42:29Z stuart02 $
+//
+// MCPFastQueries.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 03/06/2002.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPFastQueries.h"
+#import "MCPResultPlus.h"
+
+/**
+ * This actegory is made up to keep the extra methods out or the core of the framework.
+ *
+ * Basicly this is the place to add methods which are useful, but are just wrappers to the methods of the
+ * core (MCPConnection, MCPResult). The purpous being to have a single line call available for current tasks
+ * which otherwise would need a couple of lines and object defined.
+ */
+@implementation MCPConnection (MCPFastQueries)
+
+/**
+ * Send the query aQuery to the server and retrieve the row id if the table have a autoincrement column.
+ * Returns 0 if nothing have been inserted.
+ */
+- (my_ulonglong)insertQuery:(NSString *)query
+{
+ [self queryString:query];
+
+ return [self insertId];
+}
+
+/**
+ * Send the query aQuery to the server and retrieve the number of affected rows (should work with !{update},
+ * !{delete}, !{insert} and !{select} type of queries).
+ *
+ * NB: This can also be used with a !{select} query if you are only interested in the number of row complying
+ * with the query; you'll get no chance to get the result from the query, except by sending the query
+ * again (with !{queryString:})
+ */
+- (my_ulonglong)updateQuery:(NSString *)query
+{
+ [self queryString:query];
+
+ return [self affectedRows];
+}
+
+/**
+ * Get the first field of the first row of the result from the query (aQuery). Should return nil if no object
+ * at all are selected.
+ */
+- (id)getFirstFieldFromQuery:(NSString *)query
+{
+ return [[[self queryString:query] fetchRowAsType:MCPTypeArray] objectAtIndex:0];
+}
+
+/**
+ * Get the firdst row of the result from the query aQuery, in a collection of type determined by aType
+ * (MCPTypeArray or MCPTypeDictionary)
+ */
+- (id) getFirstRowFromQuery:(NSString *)query asType:(MCPReturnType)type
+{
+ return [[self queryString:query] fetchRowAsType:type];
+}
+
+/**
+ * Get a bidimensional table of the whole rows of the result from the query aQuery. The type of the result is
+ * choosen by aType, it can be (MCPTypeArray, MCPTypeDictionary, MCPTypeFlippedArray & MCPTypeFlippedDictionary).
+ * Description of the types can be found in method !{fetch2DResultAsType:}.
+ */
+- (id)getAllRowsFromQuery:(NSString *)query asType:(MCPReturnType)type
+
+{
+ return [[self queryString:query] fetch2DResultAsType:type];
+}
+
+/**
+ * Get a column (as an NSArray) of the result from the query aQuery. The column is choosen from it's index,
+ * starting from 0.
+ */
+- (NSArray *)getQuery:(NSString *)query colWithIndex:(unsigned int)col
+{
+ return [[self queryString:query] fetchColAtIndex:col];
+}
+
+/**
+ * Get a column (as an NSArray) of the result from the query aQuery. The column is choosen from it's name.
+ */
+- (NSArray *)getQuery:(NSString *)query colWithName:(NSString *)colName
+{
+ return [[self queryString:query] fetchColWithName:colName];
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPKit.h b/Frameworks/MCPKit/MCPFoundationKit/MCPKit.h
new file mode 100644
index 00000000..34df95f7
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPKit.h
@@ -0,0 +1,40 @@
+//
+// $Id: MCPKit.h 1058 2009-07-18 14:53:57Z stuart02 $
+//
+// MCPKit.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 08/12/2001.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+
+#import <MCPKit/MCPConstants.h>
+#import <MCPKit/MCPNull.h>
+#import <MCPKit/MCPResult.h>
+#import <MCPKit/MCPConnection.h>
+#import <MCPKit/MCPNumber.h>
+#import <MCPKit/MCPResultPlus.h>
+#import <MCPKit/MCPFastQueries.h>
+#import <MCPKit/MCPConnectionProxy.h>
+
+#import "mysql.h"
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPNull.h b/Frameworks/MCPKit/MCPFoundationKit/MCPNull.h
new file mode 100644
index 00000000..c017d447
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPNull.h
@@ -0,0 +1,35 @@
+//
+// $Id: MCPNull.h 482 2009-04-05 01:38:48Z stuart02 $
+//
+// MCPNull.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 02/06/2002.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+
+@interface NSObject (MCPNSNullTest)
+
+- (BOOL)isNSNull;
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPNull.m b/Frameworks/MCPKit/MCPFoundationKit/MCPNull.m
new file mode 100644
index 00000000..d3bf2ba6
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPNull.m
@@ -0,0 +1,41 @@
+//
+// $Id: MCPNull.m 482 2009-04-05 01:38:48Z stuart02 $
+//
+// MCPNull.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 02/06/2002.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPNull.h"
+
+@implementation NSObject (MCPNSNullTest)
+
+/**
+ * This Category is meant to make any kind of object the possible target to the test (isNSNull).
+ */
+- (BOOL) isNSNull
+{
+ return [self isMemberOfClass:[NSNull class]];
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPNumber.h b/Frameworks/MCPKit/MCPFoundationKit/MCPNumber.h
new file mode 100644
index 00000000..f959d43b
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPNumber.h
@@ -0,0 +1,83 @@
+//
+// $Id: MCPNumber.h 1033 2009-07-16 23:09:12Z stuart02 $
+//
+// MCPNumber.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 08/12/2002.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+
+@interface MCPNumber : NSNumber
+{
+ const char *typeCode;
+ NSNumber *number;
+}
+
++ (MCPNumber *)numberWithChar:(char)value;
++ (MCPNumber *)numberWithUnsignedChar:(unsigned char)value;
++ (MCPNumber *)numberWithShort:(short)value;
++ (MCPNumber *)numberWithUnsignedShort:(unsigned short)value;
++ (MCPNumber *)numberWithInt:(int)value;
++ (MCPNumber *)numberWithUnsignedInt:(unsigned int)value;
++ (MCPNumber *)numberWithLong:(long)value;
++ (MCPNumber *)numberWithUnsignedLong:(unsigned long)value;
++ (MCPNumber *)numberWithLongLong:(long long)value;
++ (MCPNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
++ (MCPNumber *)numberWithFloat:(float)value;
++ (MCPNumber *)numberWithDouble:(double)value;
++ (MCPNumber *)numberWithBool:(BOOL)value;
+
+- (id)initWithChar:(char)value;
+- (id)initWithUnsignedChar:(unsigned char)value;
+- (id)initWithShort:(short)value;
+- (id)initWithUnsignedShort:(unsigned short)value;
+- (id)initWithInt:(int)value;
+- (id)initWithUnsignedInt:(unsigned int)value;
+- (id)initWithLong:(long)value;
+- (id)initWithUnsignedLong:(unsigned long)value;
+- (id)initWithLongLong:(long long)value;
+- (id)initWithUnsignedLongLong:(unsigned long long)value;
+- (id)initWithFloat:(float)value;
+- (id)initWithDouble:(double)value;
+- (id)initWithBool:(BOOL)value;
+
+// Important NSNumber primitive methods
+- (const char *)objCType;
+- (void)getValue:(void *)buffer;
+
+- (char)charValue;
+- (unsigned char)unsignedCharValue;
+- (short)shortValue;
+- (unsigned short)unsignedShortValue;
+- (int)intValue;
+- (unsigned int)unsignedIntValue;
+- (long)longValue;
+- (unsigned long)unsignedLongValue;
+- (long long)longLongValue;
+- (unsigned long long)unsignedLongLongValue;
+- (float)floatValue;
+- (double)doubleValue;
+- (BOOL)boolValue;
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPNumber.m b/Frameworks/MCPKit/MCPFoundationKit/MCPNumber.m
new file mode 100644
index 00000000..0f422431
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPNumber.m
@@ -0,0 +1,301 @@
+//
+// $Id: MCPNumber.m 1033 2009-07-16 23:09:12Z stuart02 $
+//
+// MCPNumber.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 08/12/2002.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPNumber.h"
+
+@implementation MCPNumber
+
+#pragma mark -
+#pragma mark 'Creator' class methods
+
++ (MCPNumber *)numberWithChar:(char)value
+{
+ return [[[MCPNumber alloc] initWithChar:value] autorelease];
+}
+
++ (MCPNumber *)numberWithUnsignedChar:(unsigned char)value
+{
+ return [[[MCPNumber alloc] initWithUnsignedChar:value] autorelease];
+}
+
++ (MCPNumber *)numberWithShort:(short)value
+{
+ return [[[MCPNumber alloc] initWithShort:value] autorelease];
+}
+
++ (MCPNumber *)numberWithUnsignedShort:(unsigned short)value
+{
+ return [[[MCPNumber alloc] initWithUnsignedShort:value] autorelease];
+}
+
++ (MCPNumber *)numberWithInt:(int)value
+{
+ return [[[MCPNumber alloc] initWithInt:value] autorelease];
+}
+
++ (MCPNumber *)numberWithUnsignedInt:(unsigned int)value
+{
+ return [[[MCPNumber alloc] initWithUnsignedInt:value] autorelease];
+}
+
++ (MCPNumber *)numberWithLong:(long)value
+{
+ return [[[MCPNumber alloc] initWithLong:value] autorelease];
+}
+
++ (MCPNumber *)numberWithUnsignedLong:(unsigned long)value
+{
+ return [[[MCPNumber alloc] initWithUnsignedLong:value] autorelease];
+}
+
++ (MCPNumber *)numberWithLongLong:(long long)value
+{
+ return [[[MCPNumber alloc] initWithLongLong:value] autorelease];
+}
+
++ (MCPNumber *)numberWithUnsignedLongLong:(unsigned long long)value
+{
+ return [[[MCPNumber alloc] initWithUnsignedLongLong:value] autorelease];
+}
+
++ (MCPNumber *)numberWithFloat:(float)value
+{
+ return [[[MCPNumber alloc] initWithFloat:value] autorelease];
+}
+
++ (MCPNumber *)numberWithDouble:(double)value
+{
+ return [[[MCPNumber alloc] initWithDouble:value] autorelease];
+}
+
++ (MCPNumber *)numberWithBool:(BOOL)value
+{
+ return [[[MCPNumber alloc] initWithBool:value] autorelease];
+}
+
+#pragma mark -
+#pragma mark Initialilzers
+
+- (id)initWithChar:(char)value
+{
+ typeCode = @encode(char);
+ number = [[NSNumber alloc] initWithChar:value];
+
+ return self;
+}
+
+- (id)initWithUnsignedChar:(unsigned char)value
+{
+ typeCode = @encode(unsigned char);
+ number = [[NSNumber alloc] initWithUnsignedChar:value];
+
+ return self;
+}
+
+- (id)initWithShort:(short)value
+{
+ typeCode = @encode(short);
+ number = [[NSNumber alloc] initWithShort:value];
+
+ return self;
+}
+
+- (id)initWithUnsignedShort:(unsigned short)value
+{
+ typeCode = @encode(unsigned short);
+ number = [[NSNumber alloc] initWithUnsignedShort:value];
+
+ return self;
+}
+
+- (id)initWithInt:(int)value
+{
+ typeCode = @encode(int);
+ number = [[NSNumber alloc] initWithInt:value];
+
+ return self;
+}
+
+- (id)initWithUnsignedInt:(unsigned int)value
+{
+ typeCode = @encode(unsigned int);
+ number = [[NSNumber alloc] initWithUnsignedInt:value];
+
+ return self;
+}
+
+- (id)initWithLong:(long) value
+{
+ typeCode = @encode(long);
+ number = [[NSNumber alloc] initWithLong:value];
+
+ return self;
+}
+
+- (id)initWithUnsignedLong:(unsigned long)value
+{
+ typeCode = @encode(unsigned long);
+ number = [[NSNumber alloc] initWithUnsignedLong:value];
+
+ return self;
+}
+
+- (id)initWithLongLong:(long long)value
+{
+ typeCode = @encode(long long);
+ number = [[NSNumber alloc] initWithLongLong:value];
+
+ return self;
+}
+
+- (id)initWithUnsignedLongLong:(unsigned long long)value
+{
+ typeCode = @encode(unsigned long long);
+ number = [[NSNumber alloc] initWithUnsignedLongLong:value];
+
+ return self;
+}
+
+- (id)initWithFloat:(float)value
+{
+ typeCode = @encode(float);
+ number = [[NSNumber alloc] initWithFloat:value];
+
+ return self;
+}
+
+- (id)initWithDouble:(double)value
+{
+ typeCode = @encode(double);
+ number = [[NSNumber alloc] initWithDouble:value];
+
+ return self;
+}
+
+- (id)initWithBool:(BOOL)value
+{
+ typeCode = @encode(BOOL);
+ number = [[NSNumber alloc] initWithBool:value];
+
+ return self;
+}
+
+#pragma mark -
+#pragma mark NSValue primitive methods
+
+- (const char *)objCType
+{
+ return typeCode;
+}
+
+- (void)getValue:(void *)buffer
+{
+ [number getValue:buffer];
+}
+
+#pragma mark -
+#pragma mark NSNumber primitive methods
+
+/**
+ * Reparing the absence of primitive methodes in NSNumber
+ */
+- (char)charValue
+{
+ return [number charValue];
+}
+
+- (unsigned char)unsignedCharValue
+{
+ return [number unsignedCharValue];
+}
+
+- (short)shortValue
+{
+ return [number shortValue];
+}
+
+- (unsigned short)unsignedShortValue
+{
+ return [number unsignedShortValue];
+}
+
+- (int)intValue
+{
+ return [number intValue];
+}
+
+- (unsigned int)unsignedIntValue
+{
+ return [number unsignedIntValue];
+}
+
+- (long)longValue
+{
+ return [number longValue];
+}
+
+- (unsigned long)unsignedLongValue
+{
+ return [number unsignedLongValue];
+}
+
+- (long long)longLongValue
+{
+ return [number longLongValue];
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+ return [number unsignedLongLongValue];
+}
+
+- (float)floatValue
+{
+ return [number floatValue];
+}
+
+- (double)doubleValue
+{
+ return [number doubleValue];
+}
+
+- (BOOL)boolValue
+{
+ return [number boolValue];
+}
+
+#pragma mark -
+
+- (void)dealloc
+{
+ [number release];
+
+ [super dealloc];
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPResult.h b/Frameworks/MCPKit/MCPFoundationKit/MCPResult.h
new file mode 100644
index 00000000..b833e0ca
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPResult.h
@@ -0,0 +1,85 @@
+//
+// $Id: MCPResult.h 1065 2009-07-19 10:58:17Z stuart02 $
+//
+// MCPResult.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 08/12/2002.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+#import "MCPConstants.h"
+
+#import "mysql.h"
+
+#define MAGIC_BINARY_CHARSET_NR 63
+
+@interface MCPResult : NSObject
+{
+ MYSQL_RES *mResult; /* The MYSQL_RES structure of the C API. */
+ NSArray *mNames; /* An NSArray holding the name of the columns. */
+ NSDictionary *mMySQLLocales; /* A Locales dictionary to define the locales of MySQL. */
+ NSStringEncoding mEncoding; /* The encoding used by MySQL server, to ISO-1 default. */
+ unsigned int mNumOfFields; /* The number of fields in the result. */
+ NSTimeZone *mTimeZone; /* The time zone of the connection when the query was made. */
+}
+
+// Initialization
+- (id)initWithMySQLPtr:(MYSQL *)mySQLPtr encoding:(NSStringEncoding)theEncoding timeZone:(NSTimeZone *)iTimeZone;
+- (id)initWithResPtr:(MYSQL_RES *)mySQLResPtr encoding:(NSStringEncoding)theEncoding timeZone:(NSTimeZone *)iTimeZone;
+
+// Result info
+- (my_ulonglong)numOfRows;
+- (unsigned int)numOfFields;
+
+// Rows
+- (void)dataSeek:(my_ulonglong)row;
+- (id)fetchRowAsType:(MCPReturnType) aType;
+- (NSArray *)fetchRowAsArray;
+- (NSDictionary *)fetchRowAsDictionary;
+
+// Columns
+- (NSArray *)fetchFieldNames;
+- (id)fetchTypesAsType:(MCPReturnType)aType;
+- (NSArray *)fetchTypesAsArray;
+- (NSDictionary *)fetchTypesAsDictionary;
+- (NSArray *)fetchResultFieldsStructure;
+
+- (unsigned int)fetchFlagsAtIndex:(unsigned int)index;
+- (unsigned int)fetchFlagsForKey:(NSString *)key;
+
+- (BOOL)isBlobAtIndex:(unsigned int)index;
+- (BOOL)isBlobForKey:(NSString *)key;
+
+// Conversion
+- (NSString *)stringWithText:(NSData *)theTextData;
+- (const char *)cStringFromString:(NSString *)theString;
+- (NSString *)stringWithCString:(const char *)theCString;
+
+// Other
+- (NSString *)mysqlTypeToStringForType:(unsigned int)type withCharsetNr:(unsigned int)charsetnr withFlags:(unsigned int)flags withLength:(unsigned long long)length;
+- (NSString *)mysqlTypeToGroupForType:(unsigned int)type withCharsetNr:(unsigned int)charsetnr withFlags:(unsigned int)flags;
+- (NSString *)findCharsetName:(unsigned int)charsetnr;
+- (NSString *)findCharsetCollation:(unsigned int)charsetnr;
+- (unsigned int)findCharsetMaxByteLengthPerChar:(unsigned int)charsetnr;
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m b/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m
new file mode 100644
index 00000000..f8158f7c
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPResult.m
@@ -0,0 +1,1360 @@
+//
+// $Id: MCPResult.m 1065 2009-07-19 10:58:17Z stuart02 $
+//
+// MCPResult.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 08/12/2002.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPConnection.h"
+#import "MCPNull.h"
+#import "MCPNumber.h"
+#import "MCPResult.h"
+
+NSCalendarDate *MCPYear0000;
+
+const OUR_CHARSET our_charsets60[] =
+{
+ {1, "big5","big5_chinese_ci", 1, 2},
+ {3, "dec8", "dec8_swedisch_ci", 1, 1},
+ {4, "cp850", "cp850_general_ci", 1, 1},
+ {6, "hp8", "hp8_english_ci", 1, 1},
+ {7, "koi8r", "koi8r_general_ci", 1, 1},
+ {8, "latin1", "latin1_swedish_ci", 1, 1},
+ {9, "latin2", "latin2_general_ci", 1, 1},
+ {10, "swe7", "swe7_swedish_ci", 1, 1},
+ {11, "ascii", "ascii_general_ci", 1, 1},
+ {12, "ujis", "ujis_japanese_ci", 1, 3},
+ {13, "sjis", "sjis_japanese_ci", 1, 2},
+ {16, "hebrew", "hebrew_general_ci", 1, 1},
+ {18, "tis620", "tis620_thai_ci", 1, 1},
+ {19, "euckr", "euckr_korean_ci", 1, 2},
+ {22, "koi8u", "koi8u_general_ci", 1, 1},
+ {24, "gb2312", "gb2312_chinese_ci", 1, 2},
+ {25, "greek", "greek_general_ci", 1, 1},
+ {26, "cp1250", "cp1250_general_ci", 1, 1},
+ {28, "gbk", "gbk_chinese_ci", 1, 2},
+ {30, "latin5", "latin5_turkish_ci", 1, 1},
+ {32, "armscii8", "armscii8_general_ci", 1, 1},
+ {33, "utf8", "utf8_general_ci", 1, 3},
+ {35, "ucs2", "ucs2_general_ci", 2, 2},
+ {36, "cp866", "cp866_general_ci", 1, 1},
+ {37, "keybcs2", "keybcs2_general_ci", 1, 1},
+ {38, "macce", "macce_general_ci", 1, 1},
+ {39, "macroman", "macroman_general_ci", 1, 1},
+ {40, "cp852", "cp852_general_ci", 1, 1},
+ {41, "latin7", "latin7_general_ci", 1, 1},
+ {51, "cp1251", "cp1251_general_ci", 1, 1},
+ {57, "cp1256", "cp1256_general_ci", 1, 1},
+ {59, "cp1257", "cp1257_general_ci", 1, 1},
+ {63, "binary", "binary", 1, 1},
+ {92, "geostd8", "geostd8_general_ci", 1, 1},
+ {95, "cp932", "cp932_japanese_ci", 1, 2},
+ {97, "eucjpms", "eucjpms_japanese_ci", 1, 3},
+ {2, "latin2", "latin2_czech_cs", 1, 1},
+ {5, "latin1", "latin1_german_ci", 1, 1},
+ {14, "cp1251", "cp1251_bulgarian_ci", 1, 1},
+ {15, "latin1", "latin1_danish_ci", 1, 1},
+ {17, "filename", "filename", 1, 5},
+ {20, "latin7", "latin7_estonian_cs", 1, 1},
+ {21, "latin2", "latin2_hungarian_ci", 1, 1},
+ {23, "cp1251", "cp1251_ukrainian_ci", 1, 1},
+ {27, "latin2", "latin2_croatian_ci", 1, 1},
+ {29, "cp1257", "cp1257_lithunian_ci", 1, 1},
+ {31, "latin1", "latin1_german2_ci", 1, 1},
+ {34, "cp1250", "cp1250_czech_cs", 1, 1},
+ {42, "latin7", "latin7_general_cs", 1, 1},
+ {43, "macce", "macce_bin", 1, 1},
+ {44, "cp1250", "cp1250_croatian_ci", 1, 1},
+ {45, "utf8", "utf8_general_ci", 1, 1},
+ {46, "utf8", "utf8_bin", 1, 1},
+ {47, "latin1", "latin1_bin", 1, 1},
+ {48, "latin1", "latin1_general_ci", 1, 1},
+ {49, "latin1", "latin1_general_cs", 1, 1},
+ {50, "cp1251", "cp1251_bin", 1, 1},
+ {52, "cp1251", "cp1251_general_cs", 1, 1},
+ {53, "macroman", "macroman_bin", 1, 1},
+ {58, "cp1257", "cp1257_bin", 1, 1},
+ {60, "armascii8", "armascii8_bin", 1, 1},
+ {65, "ascii", "ascii_bin", 1, 1},
+ {66, "cp1250", "cp1250_bin", 1, 1},
+ {67, "cp1256", "cp1256_bin", 1, 1},
+ {68, "cp866", "cp866_bin", 1, 1},
+ {69, "dec8", "dec8_bin", 1, 1},
+ {70, "greek", "greek_bin", 1, 1},
+ {71, "hebew", "hebrew_bin", 1, 1},
+ {72, "hp8", "hp8_bin", 1, 1},
+ {73, "keybcs2", "keybcs2_bin", 1, 1},
+ {74, "koi8r", "koi8r_bin", 1, 1},
+ {75, "koi8u", "koi8u_bin", 1, 1},
+ {77, "latin2", "latin2_bin", 1, 1},
+ {78, "latin5", "latin5_bin", 1, 1},
+ {79, "latin7", "latin7_bin", 1, 1},
+ {80, "cp850", "cp850_bin", 1, 1},
+ {81, "cp852", "cp852_bin", 1, 1},
+ {82, "swe7", "swe7_bin", 1, 1},
+ {93, "geostd8", "geostd8_bin", 1, 1},
+ {83, "utf8", "utf8_bin", 1, 3},
+ {84, "big5", "big5_bin", 1, 2},
+ {85, "euckr", "euckr_bin", 1, 2},
+ {86, "gb2312", "gb2312_bin", 1, 2},
+ {87, "gbk", "gbk_bin", 1, 2},
+ {88, "sjis", "sjis_bin", 1, 2},
+ {89, "tis620", "tis620_bin", 1, 1},
+ {90, "ucs2", "ucs2_bin", 2, 2},
+ {91, "ujis", "ujis_bin", 1, 3},
+ {94, "latin1", "latin1_spanish_ci", 1, 1},
+ {96, "cp932", "cp932_bin", 1, 2},
+ {99, "cp1250", "cp1250_polish_ci", 1, 1},
+ {98, "eucjpms", "eucjpms_bin", 1, 3},
+ {128, "ucs2", "ucs2_unicode_ci", 2, 2},
+ {129, "ucs2", "ucs2_icelandic_ci", 2, 2},
+ {130, "ucs2", "ucs2_latvian_ci", 2, 2},
+ {131, "ucs2", "ucs2_romanian_ci", 2, 2},
+ {132, "ucs2", "ucs2_slovenian_ci", 2, 2},
+ {133, "ucs2", "ucs2_polish_ci", 2, 2},
+ {134, "ucs2", "ucs2_estonian_ci", 2, 2},
+ {135, "ucs2", "ucs2_spanish_ci", 2, 2},
+ {136, "ucs2", "ucs2_swedish_ci", 2, 2},
+ {137, "ucs2", "ucs2_turkish_ci", 2, 2},
+ {138, "ucs2", "ucs2_czech_ci", 2, 2},
+ {139, "ucs2", "ucs2_danish_ci", 2, 2},
+ {140, "ucs2", "ucs2_lithunian_ci", 2, 2},
+ {141, "ucs2", "ucs2_slovak_ci", 2, 2},
+ {142, "ucs2", "ucs2_spanish2_ci", 2, 2},
+ {143, "ucs2", "ucs2_roman_ci", 2, 2},
+ {144, "ucs2", "ucs2_persian_ci", 2, 2},
+ {145, "ucs2", "ucs2_esperanto_ci", 2, 2},
+ {146, "ucs2", "ucs2_hungarian_ci", 2, 2},
+ {147, "ucs2", "ucs2_sinhala_ci", 2, 2},
+ {192, "utf8mb3", "utf8mb3_general_ci", 1, 3},
+ {193, "utf8mb3", "utf8mb3_icelandic_ci", 1, 3},
+ {194, "utf8mb3", "utf8mb3_latvian_ci", 1, 3},
+ {195, "utf8mb3", "utf8mb3_romanian_ci", 1, 3},
+ {196, "utf8mb3", "utf8mb3_slovenian_ci", 1, 3},
+ {197, "utf8mb3", "utf8mb3_polish_ci", 1, 3},
+ {198, "utf8mb3", "utf8mb3_estonian_ci", 1, 3},
+ {119, "utf8mb3", "utf8mb3_spanish_ci", 1, 3},
+ {200, "utf8mb3", "utf8mb3_swedish_ci", 1, 3},
+ {201, "utf8mb3", "utf8mb3_turkish_ci", 1, 3},
+ {202, "utf8mb3", "utf8mb3_czech_ci", 1, 3},
+ {203, "utf8mb3", "utf8mb3_danish_ci", 1, 3},
+ {204, "utf8mb3", "utf8mb3_lithunian_ci", 1, 3},
+ {205, "utf8mb3", "utf8mb3_slovak_ci", 1, 3},
+ {206, "utf8mb3", "utf8mb3_spanish2_ci", 1, 3},
+ {207, "utf8mb3", "utf8mb3_roman_ci", 1, 3},
+ {208, "utf8mb3", "utf8mb3_persian_ci", 1, 3},
+ {209, "utf8mb3", "utf8mb3_esperanto_ci", 1, 3},
+ {210, "utf8mb3", "utf8mb3_hungarian_ci", 1, 3},
+ {211, "utf8mb3", "utf8mb3_sinhala_ci", 1, 3},
+ {224, "utf8", "utf8_unicode_ci", 1, 3},
+ {225, "utf8", "utf8_icelandic_ci", 1, 3},
+ {226, "utf8", "utf8_latvian_ci", 1, 3},
+ {227, "utf8", "utf8_romanian_ci", 1, 3},
+ {228, "utf8", "utf8_slovenian_ci", 1, 3},
+ {229, "utf8", "utf8_polish_ci", 1, 3},
+ {230, "utf8", "utf8_estonian_ci", 1, 3},
+ {231, "utf8", "utf8_spanish_ci", 1, 3},
+ {232, "utf8", "utf8_swedish_ci", 1, 3},
+ {233, "utf8", "utf8_turkish_ci", 1, 3},
+ {234, "utf8", "utf8_czech_ci", 1, 3},
+ {235, "utf8", "utf8_danish_ci", 1, 3},
+ {236, "utf8", "utf8_lithuanian_ci", 1, 3},
+ {237, "utf8", "utf8_slovak_ci", 1, 3},
+ {238, "utf8", "utf8_spanish2_ci", 1, 3},
+ {239, "utf8", "utf8_roman_ci", 1, 3},
+ {240, "utf8", "utf8_persian_ci", 1, 3},
+ {241, "utf8", "utf8_esperanto_ci", 1, 3},
+ {242, "utf8", "utf8_hungarian_ci", 1, 3},
+ {243, "utf8", "utf8_sinhala_ci", 1, 3},
+ {254, "utf8mb3", "utf8mb3_general_cs", 1, 3},
+ {0, NULL, NULL, 0, 0}
+};
+
+@implementation MCPResult
+
+/**
+ * Hold the results of a query to a MySQL database server. It correspond to the MYSQL_RES structure of the C API, and to the statement handle of the PERL DBI/DBD.
+ *
+ * Uses the !{mysql_store_result()} function from the C API.
+ *
+ * This object is generated only by a MCPConnection object, in this way (see #{MCPConnection} documentation):
+ *
+ * MCPConnection *theConnec = [MCPConnection alloc];
+ * MCPResult *theRes;
+ * NSDictionary *theDict;
+ * NSArray *theColNames;
+ * int i, j;
+ *
+ * theConnec = [theConnec initToHost:@"albert.com" withLogin:@"toto" password:@"albert" usingPort:0];
+ * [theConnec selectDB:@"db1"];
+ * theRes = [theConnec queryString:@"select * from table1"];
+ * theColNames = [theRes fetchFiedlsName];
+ * i = 0;
+ *
+ * while (theDict = [theRes fetchRowAsDictionary]) {
+ * NSLog(@"Row : %d\n", i);
+ * for (j=0; j<[theColNames count]; j++) {
+ * NSLog(@" Field : %@, contain : %@\n", [theColNames objectAtIndex:j], [theDict objectForKey:[theColNames objectAtIndex:j]]);
+ * }
+ * i++;
+ * }
+ */
+
+/**
+ * Initialize the class version to 3.0.1
+ */
++ (void)initialize
+{
+ if (self = [MCPResult class]) {
+ [self setVersion:030001]; // Ma.Mi.Re -> MaMiRe
+ MCPYear0000 = [[NSCalendarDate dateWithTimeIntervalSinceReferenceDate:-63146822400.0] retain];
+ [MCPYear0000 setCalendarFormat:@"%Y"];
+ }
+}
+
+#pragma mark -
+#pragma mark Initialisation
+
+/**
+ * Empty init, normaly of NO use to the user, again, MCPResult should be made through calls to MCPConnection
+ */
+- (id)init
+{
+ if ((self = [super init])) {
+ mEncoding = [MCPConnection defaultMySQLEncoding];
+
+ if (mResult) {
+ mysql_free_result(mResult);
+ mResult = NULL;
+ }
+
+ if (mNames) {
+ [mNames release];
+ mNames = NULL;
+ }
+
+ if (mMySQLLocales == NULL) {
+ mMySQLLocales = [[MCPConnection getMySQLLocales] retain];
+ }
+
+ mNumOfFields = 0;
+ }
+
+ return self;
+}
+
+/**
+ * Initialise a MCPResult, it is used internally by MCPConnection !{queryString:} method: the only proper
+ * way to get a running MCPResult object.
+ */
+- (id)initWithMySQLPtr:(MYSQL *)mySQLPtr encoding:(NSStringEncoding)iEncoding timeZone:(NSTimeZone *)iTimeZone
+{
+ if ((self = [super init])) {
+ mEncoding = iEncoding;
+ mTimeZone = [iTimeZone retain];
+
+ if (mResult) {
+ mysql_free_result(mResult);
+ mResult = NULL;
+ }
+
+ if (mNames) {
+ [mNames release];
+ mNames = NULL;
+ }
+
+ mResult = mysql_store_result(mySQLPtr);
+
+ if (mResult) {
+ mNumOfFields = mysql_num_fields(mResult);
+ }
+ else {
+ mNumOfFields = 0;
+ }
+
+ if (mMySQLLocales == NULL) {
+ mMySQLLocales = [[MCPConnection getMySQLLocales] retain];
+ }
+ }
+
+ return self;
+}
+
+/**
+ * This metod is used internally by MCPConnection object when it have already a MYSQL_RES object to initialise
+ * MCPResult object. Initialise a MCPResult with the MYSQL_RES pointer (returned by such a function as mysql_list_dbs).
+ * NB: MCPResult should be made by using one of the method of MCPConnection.
+ */
+- (id)initWithResPtr:(MYSQL_RES *)mySQLResPtr encoding:(NSStringEncoding)iEncoding timeZone:(NSTimeZone *)iTimeZone
+{
+ if ((self = [super init])) {
+ mEncoding = iEncoding;
+ mTimeZone = [iTimeZone retain];
+
+ if (mResult) {
+ mysql_free_result(mResult);
+ mResult = NULL;
+ }
+
+ if (mNames) {
+ [mNames release];
+ mNames = NULL;
+ }
+
+ mResult = mySQLResPtr;
+
+ if (mResult) {
+ mNumOfFields = mysql_num_fields(mResult);
+ }
+ else {
+ mNumOfFields = 0;
+ }
+
+ if (mMySQLLocales == NULL) {
+ mMySQLLocales = [[MCPConnection getMySQLLocales] retain];
+ }
+ }
+
+ return self;
+}
+
+#pragma mark -
+#pragma mark Result info
+
+/**
+ * Return the number of rows selected by the query.
+ */
+- (my_ulonglong)numOfRows
+{
+ if (mResult) {
+ return mysql_num_rows(mResult);
+ }
+
+ return 0;
+}
+
+/**
+ * Return the number of fields selected by the query. As a side effect it forces an update of the number of fields.
+ */
+- (unsigned int)numOfFields
+{
+ if (mResult) {
+ return mNumOfFields = mysql_num_fields(mResult);
+ }
+
+ return mNumOfFields = 0;
+}
+
+#pragma mark -
+#pragma mark Rows
+
+/**
+ * Go to a precise row in the selected result. 0 is the very first row.
+ */
+- (void)dataSeek:(my_ulonglong)row
+{
+ my_ulonglong theRow = (row < 0)? 0 : row;
+ theRow = (theRow < [self numOfRows]) ? theRow : ([self numOfRows] - 1);
+ mysql_data_seek(mResult,theRow);
+}
+
+/**
+ *
+ */
+- (id)fetchRowAsType:(MCPReturnType)aType
+{
+ MYSQL_ROW theRow;
+ unsigned long *theLengths;
+ MYSQL_FIELD *theField;
+ int i;
+ id theReturn;
+
+ if (mResult == NULL) {
+ // If there is no results, returns nil, as after the last row...
+ return nil;
+ }
+
+ theRow = mysql_fetch_row(mResult);
+
+ if (theRow == NULL) {
+ return nil;
+ }
+
+ switch (aType) {
+ case MCPTypeArray:
+ theReturn = [NSMutableArray arrayWithCapacity:mNumOfFields];
+ break;
+ case MCPTypeDictionary:
+ if (mNames == nil) {
+ [self fetchFieldNames];
+ }
+ theReturn = [NSMutableDictionary dictionaryWithCapacity:mNumOfFields];
+ break;
+ default :
+ NSLog (@"Unknown type : %d, will return an Array!\n", aType);
+ theReturn = [NSMutableArray arrayWithCapacity:mNumOfFields];
+ break;
+ }
+
+ theLengths = mysql_fetch_lengths(mResult);
+ theField = mysql_fetch_fields(mResult);
+
+ for (i=0; i<mNumOfFields; i++) {
+ id theCurrentObj;
+
+ if (theRow[i] == NULL) {
+ theCurrentObj = [NSNull null];
+ } else {
+ char *theData = calloc(sizeof(char),theLengths[i]+1);
+ //char *theUselLess;
+ memcpy(theData, theRow[i],theLengths[i]);
+ theData[theLengths[i]] = '\0';
+
+ switch (theField[i].type) {
+ case FIELD_TYPE_TINY:
+ case FIELD_TYPE_SHORT:
+ case FIELD_TYPE_INT24:
+ case FIELD_TYPE_LONG:
+ case FIELD_TYPE_LONGLONG:
+ case FIELD_TYPE_DECIMAL:
+ case FIELD_TYPE_NEWDECIMAL:
+ case FIELD_TYPE_FLOAT:
+ case FIELD_TYPE_DOUBLE:
+ case FIELD_TYPE_TIMESTAMP:
+ case FIELD_TYPE_DATE:
+ case FIELD_TYPE_TIME:
+ case FIELD_TYPE_DATETIME:
+ case FIELD_TYPE_YEAR:
+ case FIELD_TYPE_VAR_STRING:
+ case FIELD_TYPE_STRING:
+ case FIELD_TYPE_SET:
+ case FIELD_TYPE_ENUM:
+ case FIELD_TYPE_NEWDATE: // Don't know what the format for this type is...
+ theCurrentObj = [self stringWithCString:theData];
+ break;
+
+ case FIELD_TYPE_BIT:
+ theCurrentObj = [NSString stringWithFormat:@"%u", theData[0]];
+ break;
+
+ case FIELD_TYPE_TINY_BLOB:
+ case FIELD_TYPE_BLOB:
+ case FIELD_TYPE_MEDIUM_BLOB:
+ case FIELD_TYPE_LONG_BLOB:
+ theCurrentObj = [NSData dataWithBytes:theData length:theLengths[i]];
+ if (!(theField[i].flags & BINARY_FLAG)) { // It is TEXT and NOT BLOB...
+ theCurrentObj = [self stringWithText:theCurrentObj];
+ } // #warning Should check for TEXT (using theField[i].flag BINARY_FLAG)
+ break;
+
+ case FIELD_TYPE_NULL:
+ theCurrentObj = [NSNull null];
+ break;
+
+ default:
+ NSLog (@"in fetchRowAsType : Unknown type : %d for column %d, send back a NSData object", (int)theField[i].type, (int)i);
+ theCurrentObj = [NSData dataWithBytes:theData length:theLengths[i]];
+ break;
+ }
+
+ free(theData);
+
+ // Some of the creators return nil object...
+ if (theCurrentObj == nil) {
+ theCurrentObj = [NSNull null];
+ }
+ }
+
+ switch (aType) {
+ case MCPTypeDictionary :
+ [theReturn setObject:theCurrentObj forKey:[mNames objectAtIndex:i]];
+ break;
+
+ case MCPTypeArray :
+ default :
+ [theReturn addObject:theCurrentObj];
+ break;
+ }
+ }
+
+ return theReturn;
+}
+
+/**
+ * Return the next row of the result as an array, the index in select field order, the object a proper object
+ * for handling the information in the field (NSString, NSNumber ...).
+ *
+ * Just a #{typed} wrapper for method !{fetchRosAsType:} (with arg MCPTypeArray).
+ *
+ * NB: Returned object is immutable.
+ */
+- (NSArray *)fetchRowAsArray
+{
+ NSMutableArray *theArray = [self fetchRowAsType:MCPTypeArray];
+
+ return (theArray) ? [NSArray arrayWithArray:theArray] : nil;
+}
+
+/**
+ * Return the next row of the result as a dictionary, the key being the field name, the object a proper object
+ * for handling the information in the field (NSString, NSNumber ...).
+ *
+ * Just a #{typed} wrapper for method !{fetchRosAsType:} (with arg MCPTypeDictionary).
+ *
+ * NB: Returned object is immutable.
+ */
+- (NSDictionary *)fetchRowAsDictionary
+{
+ NSMutableDictionary *theDict = [self fetchRowAsType:MCPTypeDictionary];
+
+ return (theDict) ? [NSDictionary dictionaryWithDictionary:theDict] : nil;
+}
+
+#pragma mark -
+#pragma mark Columns
+
+/**
+ * Generate the mNames if not already generated, and return it.
+ *
+ * mNames is a NSArray holding the names of the fields(columns) of the results.
+ */
+- (NSArray *)fetchFieldNames
+{
+ int i;
+ unsigned int theNumFields;
+ NSMutableArray *theNamesArray;
+ MYSQL_FIELD *theField;
+
+ if (mNames) {
+ return mNames;
+ }
+
+ if (mResult == NULL) {
+ // If no results, give an empty array. Maybe it's better to give a nil pointer?
+ return (mNames = [[NSArray array] retain]);
+ }
+
+ theNumFields = [self numOfFields];
+ theNamesArray = [NSMutableArray arrayWithCapacity: theNumFields];
+ theField = mysql_fetch_fields(mResult);
+
+ for (i=0; i<theNumFields; i++) {
+ NSString *theName = [self stringWithCString:theField[i].name];
+ if ((theName) && (![theName isEqualToString:@""])) {
+ [theNamesArray addObject:theName];
+ }
+ else {
+ [theNamesArray addObject:[NSString stringWithFormat:@"Column %d", i]];
+ }
+ }
+
+ return (mNames = [[NSArray arrayWithArray:theNamesArray] retain]);
+}
+
+/**
+ * Return a collection of the fields's type. The type of collection is choosen by the aType variable
+ * (MCPTypeArray or MCPTypeDictionary).
+ *
+ * This method returned directly the #{mutable} object generated while going through all the columns
+ */
+- (id)fetchTypesAsType:(MCPReturnType)aType
+{
+ int i;
+ id theTypes;
+ MYSQL_FIELD *theField;
+
+ if (mResult == NULL) {
+ // If no results, give an empty array. Maybe it's better to give a nil pointer?
+ return nil;
+ }
+
+ switch (aType) {
+ case MCPTypeArray:
+ theTypes = [NSMutableArray arrayWithCapacity:mNumOfFields];
+ break;
+ case MCPTypeDictionary:
+ if (mNames == nil) {
+ [self fetchFieldNames];
+ }
+ theTypes = [NSMutableDictionary dictionaryWithCapacity:mNumOfFields];
+ break;
+ default :
+ NSLog (@"Unknown type : %d, will return an Array!\n", aType);
+ theTypes = [NSMutableArray arrayWithCapacity:mNumOfFields];
+ break;
+ }
+
+ theField = mysql_fetch_fields(mResult);
+
+ for (i=0; i<mNumOfFields; i++) {
+ NSString *theType;
+ switch (theField[i].type) {
+ case FIELD_TYPE_TINY:
+ theType = @"tiny";
+ break;
+ case FIELD_TYPE_SHORT:
+ theType = @"short";
+ break;
+ case FIELD_TYPE_LONG:
+ theType = @"long";
+ break;
+ case FIELD_TYPE_INT24:
+ theType = @"int24";
+ break;
+ case FIELD_TYPE_LONGLONG:
+ theType = @"longlong";
+ break;
+ case FIELD_TYPE_DECIMAL:
+ theType = @"decimal";
+ break;
+ case FIELD_TYPE_FLOAT:
+ theType = @"float";
+ break;
+ case FIELD_TYPE_DOUBLE:
+ theType = @"double";
+ break;
+ case FIELD_TYPE_TIMESTAMP:
+ theType = @"timestamp";
+ break;
+ case FIELD_TYPE_DATE:
+ theType = @"date";
+ break;
+ case FIELD_TYPE_TIME:
+ theType = @"time";
+ break;
+ case FIELD_TYPE_DATETIME:
+ theType = @"datetime";
+ break;
+ case FIELD_TYPE_YEAR:
+ theType = @"year";
+ break;
+ case FIELD_TYPE_VAR_STRING:
+ theType = @"varstring";
+ break;
+ case FIELD_TYPE_STRING:
+ theType = @"string";
+ break;
+ case FIELD_TYPE_TINY_BLOB:
+ theType = @"tinyblob";
+ break;
+ case FIELD_TYPE_BLOB:
+ theType = @"blob";
+ break;
+ case FIELD_TYPE_MEDIUM_BLOB:
+ theType = @"mediumblob";
+ break;
+ case FIELD_TYPE_LONG_BLOB:
+ theType = @"longblob";
+ break;
+ case FIELD_TYPE_SET:
+ theType = @"set";
+ break;
+ case FIELD_TYPE_ENUM:
+ theType = @"enum";
+ break;
+ case FIELD_TYPE_NULL:
+ theType = @"null";
+ break;
+ case FIELD_TYPE_NEWDATE:
+ theType = @"newdate";
+ break;
+ default:
+ theType = @"unknown";
+ NSLog (@"in fetchTypesAsArray : Unknown type for column %d of the MCPResult, type = %d", (int)i, (int)theField[i].type);
+ break;
+ }
+
+ switch (aType) {
+ case MCPTypeArray :
+ [theTypes addObject:theType];
+ break;
+ case MCPTypeDictionary :
+ [theTypes setObject:theType forKey:[mNames objectAtIndex:i]];
+ break;
+ default :
+ [theTypes addObject:theType];
+ break;
+ }
+ }
+
+ return theTypes;
+}
+
+/**
+ * Return an array of the fields' types.
+ *
+ * NB: Returned object is immutable.
+ */
+- (NSArray *)fetchTypesAsArray
+{
+ NSMutableArray *theArray = [self fetchTypesAsType:MCPTypeArray];
+
+ return (theArray) ? [NSArray arrayWithArray:theArray] : nil;
+}
+
+/**
+ * Return a dictionnary of the fields' types (keys are the fields' names).
+ *
+ * NB: Returned object is immutable.
+ */
+- (NSDictionary*) fetchTypesAsDictionary
+{
+ NSMutableDictionary *theDict = [self fetchTypesAsType:MCPTypeDictionary];
+
+ return (theDict) ? [NSDictionary dictionaryWithDictionary:theDict] : nil;
+}
+
+/**
+ * Return an array of dicts containg column data of the last executed query
+ */
+- (NSArray *)fetchResultFieldsStructure
+{
+ MYSQL_FIELD *theField;
+
+ NSMutableArray *structureResult = [NSMutableArray array];
+
+ unsigned int i;
+ unsigned int numFields = mysql_num_fields(mResult);
+
+ if (mResult == NULL) return nil;
+
+ theField = mysql_fetch_fields(mResult);
+
+ for (i=0; i < numFields; i++)
+ {
+ NSMutableDictionary *fieldStructure = [NSMutableDictionary dictionaryWithCapacity:39];
+
+ /* Original column position */
+ [fieldStructure setObject:[NSNumber numberWithInt:i] forKey:@"datacolumnindex"];
+
+ /* Name of column */
+ [fieldStructure setObject:[self stringWithCString:theField[i].name] forKey:@"name"];
+ // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].name_length] forKey:@"name_length"];
+
+ /* Original column name, if an alias */
+ [fieldStructure setObject:[self stringWithCString:theField[i].org_name] forKey:@"org_name"];
+ // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].org_name_length] forKey:@"org_name_length"];
+
+ /* Table of column if column was a field */
+ [fieldStructure setObject:[self stringWithCString:theField[i].table] forKey:@"table"];
+ // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].table_length] forKey:@"table_length"];
+
+ /* Org table name, if table was an alias */
+ [fieldStructure setObject:[self stringWithCString:theField[i].org_table] forKey:@"org_table"];
+ // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].org_table_length] forKey:@"org_table_length"];
+
+ /* Database for table */
+ [fieldStructure setObject:[self stringWithCString:theField[i].db] forKey:@"db"];
+ // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].db_length] forKey:@"db_length"];
+
+ /* Catalog for table */
+ // [fieldStructure setObject:[self stringWithCString:theField[i].catalog] forKey:@"catalog"];
+ // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].catalog_length] forKey:@"catalog_length"];
+
+ /* Default value (set by mysql_list_fields) */
+ // [fieldStructure setObject:[self stringWithCString:theField[i].def] forKey:@"def"];
+ // [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].def_length] forKey:@"def_length"];
+
+ /* Width of column (real length in bytes) */
+ [fieldStructure setObject:[NSNumber numberWithUnsignedLongLong:theField[i].length] forKey:@"byte_length"];
+ /* Width of column (as in create)*/
+ [fieldStructure setObject:[NSNumber numberWithUnsignedLongLong:theField[i].length/[self findCharsetMaxByteLengthPerChar:theField[i].charsetnr]]
+ forKey:@"char_length"];
+ /* Max width (bytes) for selected set */
+ [fieldStructure setObject:[NSNumber numberWithUnsignedLongLong:theField[i].max_length] forKey:@"max_byte_length"];
+ /* Max width (chars) for selected set */
+ // [fieldStructure setObject:[NSNumber numberWithUnsignedLongLong:theField[i].max_length/[self find_charsetMaxByteLengthPerChar:theField[i].charsetnr]]
+ // forKey:@"max_char_length"];
+
+ /* Div flags */
+ [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].flags] forKey:@"flags"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & NOT_NULL_FLAG) ? YES : NO] forKey:@"null"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & PRI_KEY_FLAG) ? YES : NO] forKey:@"PRI_KEY_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & UNIQUE_KEY_FLAG) ? YES : NO] forKey:@"UNIQUE_KEY_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & MULTIPLE_KEY_FLAG) ? YES : NO] forKey:@"MULTIPLE_KEY_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & BLOB_FLAG) ? YES : NO] forKey:@"BLOB_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & UNSIGNED_FLAG) ? YES : NO] forKey:@"UNSIGNED_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & ZEROFILL_FLAG) ? YES : NO] forKey:@"ZEROFILL_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & BINARY_FLAG) ? YES : NO] forKey:@"BINARY_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & ENUM_FLAG) ? YES : NO] forKey:@"ENUM_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & AUTO_INCREMENT_FLAG) ? YES : NO] forKey:@"AUTO_INCREMENT_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & SET_FLAG) ? YES : NO] forKey:@"SET_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & NUM_FLAG) ? YES : NO] forKey:@"NUM_FLAG"];
+ [fieldStructure setObject:[NSNumber numberWithBool:(theField[i].flags & PART_KEY_FLAG) ? YES : NO] forKey:@"PART_KEY_FLAG"];
+ // [fieldStructure setObject:[NSNumber numberWithInt:(theField[i].flags & GROUP_FLAG) ? 1 : 0] forKey:@"GROUP_FLAG"];
+ // [fieldStructure setObject:[NSNumber numberWithInt:(theField[i].flags & UNIQUE_FLAG) ? 1 : 0] forKey:@"UNIQUE_FLAG"];
+ // [fieldStructure setObject:[NSNumber numberWithInt:(theField[i].flags & BINCMP_FLAG) ? 1 : 0] forKey:@"BINCMP_FLAG"];
+
+ /* Number of decimals in field */
+ [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].decimals] forKey:@"decimals"];
+
+ /* Character set */
+ [fieldStructure setObject:[NSNumber numberWithUnsignedInt:theField[i].charsetnr] forKey:@"charsetnr"];
+ [fieldStructure setObject:[self findCharsetName:theField[i].charsetnr] forKey:@"charset_name"];
+ [fieldStructure setObject:[self findCharsetCollation:theField[i].charsetnr] forKey:@"charset_collation"];
+
+ /* Table type */
+ [fieldStructure setObject:[self mysqlTypeToStringForType:theField[i].type
+ withCharsetNr:theField[i].charsetnr
+ withFlags:theField[i].flags
+ withLength:theField[i].length
+ ] forKey:@"type"];
+
+ /* Table type group*/
+ [fieldStructure setObject:[self mysqlTypeToGroupForType:theField[i].type
+ withCharsetNr:theField[i].charsetnr
+ withFlags:theField[i].flags
+ ] forKey:@"typegrouping"];
+
+ [structureResult addObject:fieldStructure];
+
+ }
+
+ return structureResult;
+
+}
+
+/**
+ * Return the MySQL flags of the column at the given index... Can be used to check if a number is signed or not...
+ */
+- (unsigned int)fetchFlagsAtIndex:(unsigned int)index
+{
+ unsigned int theRet;
+ unsigned int theNumFields;
+ MYSQL_FIELD *theField;
+
+ if (mResult == NULL) {
+ // If no results, give an empty array. Maybe it's better to give a nil pointer?
+ return (0);
+ }
+
+ theNumFields = [self numOfFields];
+ theField = mysql_fetch_fields(mResult);
+
+ if (index >= theNumFields) {
+ // Out of range... should raise an exception
+ theRet = 0;
+ }
+ else {
+ theRet = theField[index].flags;
+ }
+
+ return theRet;
+}
+
+/**
+ *
+ */
+- (unsigned int)fetchFlagsForKey:(NSString *)key
+{
+ unsigned int theRet;
+ unsigned int theNumFields, index;
+ MYSQL_FIELD *theField;
+
+ if (mResult == NULL) {
+ // If no results, give an empty array. Maybe it's better to give a nil pointer?
+ return (0);
+ }
+
+ if (mNames == NULL) {
+ [self fetchFieldNames];
+ }
+
+ theNumFields = [self numOfFields];
+ theField = mysql_fetch_fields(mResult);
+
+ if ([mNames indexOfObject:key] == NSNotFound) {
+ // Non existent key... should raise an exception
+ theRet = 0;
+ }
+ else {
+ index = [mNames indexOfObject:key];
+
+ theRet = theField[index].flags;
+ }
+
+ return theRet;
+}
+
+/**
+ * Return YES if the field with the given index is a BLOB. It should be used to discriminates between BLOBs
+ * and TEXTs.
+ *
+ * #{DEPRECATED}, This method is not consistent with the C API which is supposed to return YES for BOTH
+ * text and blob (and BTW is also deprecated)...
+ *
+ * #{NOTE} That the current version handles properly TEXT, and returns those as NSString (and not NSData as
+ * it used to be).
+ */
+- (BOOL)isBlobAtIndex:(unsigned int)index
+{
+ BOOL theRet;
+ unsigned int theNumFields;
+ MYSQL_FIELD *theField;
+
+ if (mResult == NULL) {
+ // If no results, give an empty array. Maybe it's better to give a nil pointer?
+ return (NO);
+ }
+
+ theNumFields = [self numOfFields];
+ theField = mysql_fetch_fields(mResult);
+
+ if (index >= theNumFields) {
+ // Out of range... should raise an exception
+ theRet = NO;
+ }
+ else {
+ switch(theField[index].type) {
+ case FIELD_TYPE_TINY_BLOB:
+ case FIELD_TYPE_BLOB:
+ case FIELD_TYPE_MEDIUM_BLOB:
+ case FIELD_TYPE_LONG_BLOB:
+ theRet = (theField[index].flags & BINARY_FLAG);
+ break;
+ default:
+ theRet = NO;
+ break;
+ }
+ }
+
+ return theRet;
+}
+
+/**
+ * Return YES if the field (by name) with the given index is a BLOB. It should be used to discriminates
+ * between BLOBs and TEXTs.
+ *
+ * #{DEPRECATED}, This method is not consistent with the C API which is supposed to return YES for BOTH
+ * text and blob (and BTW is also deprecated)...
+ *
+ * #{NOTE} That the current version handles properly TEXT, and returns those as NSString (and not NSData
+ * as it used to be).
+ */
+- (BOOL)isBlobForKey:(NSString *)key
+{
+ BOOL theRet;
+ unsigned int theNumFields, index;
+ MYSQL_FIELD *theField;
+
+ if (mResult == NULL) {
+ // If no results, give an empty array. Maybe it's better to give a nil pointer?
+ return (NO);
+ }
+
+ if (mNames == NULL) {
+ [self fetchFieldNames];
+ }
+
+ theNumFields = [self numOfFields];
+ theField = mysql_fetch_fields(mResult);
+
+ if ([mNames indexOfObject:key] == NSNotFound) {
+ // Non existent key... should raise an exception
+ theRet = NO;
+ }
+ else {
+ index = [mNames indexOfObject:key];
+
+ switch(theField[index].type) {
+ case FIELD_TYPE_TINY_BLOB:
+ case FIELD_TYPE_BLOB:
+ case FIELD_TYPE_MEDIUM_BLOB:
+ case FIELD_TYPE_LONG_BLOB:
+ theRet = (theField[index].flags & BINARY_FLAG);
+ break;
+ default:
+ theRet = NO;
+ break;
+ }
+ }
+
+ return theRet;
+}
+
+#pragma mark -
+#pragma mark Conversion
+
+/**
+ * Use the string encoding to convert the returned NSData to a string (for a TEXT field).
+ */
+- (NSString *)stringWithText:(NSData *)theTextData
+{
+ NSString *theString;
+
+ if (theTextData == nil) {
+ return nil;
+ }
+
+ theString = [[NSString alloc] initWithData:theTextData encoding:mEncoding];
+
+ if (theString) {
+ [theString autorelease];
+ }
+
+ return theString;
+}
+
+/**
+ * Return a (long) string containing the table of results, first line being the fields name, next line(s)
+ * the row(s). Useful to have NSLog logging a MCPResult (example).
+ */
+- (NSString *)description
+{
+ if (mResult == NULL) {
+ return @"This is an empty MCPResult\n";
+ }
+ else {
+ NSMutableString *theString = [NSMutableString stringWithCapacity:0];
+ int i;
+ NSArray *theRow;
+ MYSQL_ROW_OFFSET thePosition;
+ BOOL trunc = [MCPConnection truncateLongField];
+
+ // First line, saying we are displaying a MCPResult
+ [theString appendFormat:@"MCPResult: (encoding : %d, dim %d x %d)\n", (long)mEncoding, (long)mNumOfFields, (long)[self numOfRows]];
+ // Second line: the field names, tab separated
+ [self fetchFieldNames];
+
+ for (i=0; i<(mNumOfFields-1); i++) {
+ [theString appendFormat:@"%@\t", [mNames objectAtIndex:i]];
+ }
+
+ [theString appendFormat:@"%@\n", [mNames objectAtIndex:i]];
+ // Next lines, the records (saving current position to put it back after the full display)
+ thePosition = mysql_row_tell(mResult);
+ [self dataSeek:0];
+
+ while (theRow = [self fetchRowAsArray])
+ {
+ id theField = [theRow objectAtIndex:i];
+
+ if (trunc) {
+ if (([theField isKindOfClass:[NSString class]]) && (kLengthOfTruncationForLog < [(NSString *)theField length])) {
+ theField = [theField substringToIndex:kLengthOfTruncationForLog];
+ }
+ else if (([theField isKindOfClass:[NSData class]]) && (kLengthOfTruncationForLog < [(NSData *)theField length])) {
+ theField = [NSData dataWithBytes:[theField bytes] length:kLengthOfTruncationForLog];
+ }
+ }
+
+ for (i=0; i<(mNumOfFields - 1); i++)
+ {
+ [theString appendFormat:@"%@\t", theField];
+ }
+
+ [theString appendFormat:@"%@\n", theField];
+ }
+
+ // Returning to the proper row
+ mysql_row_seek(mResult, thePosition);
+
+ return theString;
+ }
+}
+
+/**
+ * For internal use only. Transform a NSString to a C type string (ended with \0) using ethe character set
+ * from the MCPConnection. Lossy conversions are enabled.
+ */
+- (const char *)cStringFromString:(NSString *)theString
+{
+ NSMutableData *theData;
+
+ if (!theString) {
+ return (const char *)NULL;
+ }
+
+ theData = [NSMutableData dataWithData:[theString dataUsingEncoding:mEncoding allowLossyConversion:YES]];
+ [theData increaseLengthBy:1];
+
+ return (const char *)[theData bytes];
+}
+
+/**
+ * Return a NSString from a C style string encoded with the character set of theMCPConnection.
+ */
+- (NSString *)stringWithCString:(const char *)theCString
+{
+ NSData *theData;
+ NSString *theString;
+
+ if (theCString == NULL) {
+ return @"";
+ }
+
+ theData = [NSData dataWithBytes:theCString length:(strlen(theCString))];
+ theString = [[NSString alloc] initWithData:theData encoding:mEncoding];
+
+ if (theString) {
+ [theString autorelease];
+ }
+
+ return theString;
+}
+
+#pragma mark -
+#pragma mark Other
+
+/**
+ * Convert a mysql_type to a string
+ */
+- (NSString *)mysqlTypeToStringForType:(unsigned int)type withCharsetNr:(unsigned int)charsetnr withFlags:(unsigned int)flags withLength:(unsigned long long)length
+{
+ // BOOL isUnsigned = (flags & UNSIGNED_FLAG) != 0;
+ // BOOL isZerofill = (flags & ZEROFILL_FLAG) != 0;
+
+ switch (type) {
+ case FIELD_TYPE_BIT:
+ return @"BIT";
+ case MYSQL_TYPE_DECIMAL:
+ //return isUnsigned ? (isZerofill? @"DECIMAL UNSIGNED ZEROFILL" : @"DECIMAL UNSIGNED"):
+ return @"DECIMAL";
+ case MYSQL_TYPE_TINY:
+ // return isUnsigned ? (isZerofill? @"TINYINT UNSIGNED ZEROFILL" : @"TINYINT UNSIGNED"):
+ return @"TINYINT";
+ case MYSQL_TYPE_SHORT:
+ // return isUnsigned ? (isZerofill? @"SMALLINT UNSIGNED ZEROFILL" : @"SMALLINT UNSIGNED"):
+ return @"SMALLINT";
+ case MYSQL_TYPE_LONG:
+ // return isUnsigned ? (isZerofill? @"INT UNSIGNED ZEROFILL" : @"INT UNSIGNED"):
+ return @"INT";
+ case MYSQL_TYPE_FLOAT:
+ // return isUnsigned ? (isZerofill? @"FLOAT UNSIGNED ZEROFILL" : @"FLOAT UNSIGNED"):
+ return @"FLOAT";
+ case MYSQL_TYPE_DOUBLE:
+ // return isUnsigned ? (isZerofill? @"DOUBLE UNSIGNED ZEROFILL" : @"DOUBLE UNSIGNED"):
+ return @"DOUBLE";
+ case MYSQL_TYPE_NULL:
+ return @"NULL";
+ case MYSQL_TYPE_TIMESTAMP:
+ return @"TIMESTAMP";
+ case MYSQL_TYPE_LONGLONG:
+ // return isUnsigned ? (isZerofill? @"BIGINT UNSIGNED ZEROFILL" : @"BIGINT UNSIGNED") :
+ return @"BIGINT";
+ case MYSQL_TYPE_INT24:
+ // return isUnsigned ? (isZerofill? @"MEDIUMINT UNSIGNED ZEROFILL" : @"MEDIUMINT UNSIGNED") :
+ return @"MEDIUMINT";
+ case MYSQL_TYPE_DATE:
+ return @"DATE";
+ case MYSQL_TYPE_TIME:
+ return @"TIME";
+ case MYSQL_TYPE_DATETIME:
+ return @"DATETIME";
+ case MYSQL_TYPE_TINY_BLOB:// should no appear over the wire
+ case MYSQL_TYPE_MEDIUM_BLOB:// should no appear over the wire
+ case MYSQL_TYPE_LONG_BLOB:// should no appear over the wire
+ case MYSQL_TYPE_BLOB:
+ {
+ BOOL isBlob = (charsetnr == MAGIC_BINARY_CHARSET_NR);
+ switch ((int)length/[self findCharsetMaxByteLengthPerChar:charsetnr]) {
+ case 255: return isBlob? @"TINYBLOB":@"TINYTEXT";
+ case 65535: return isBlob? @"BLOB":@"TEXT";
+ case 16777215: return isBlob? @"MEDIUMBLOB":@"MEDIUMTEXT";
+ case 4294967295: return isBlob? @"LONGBLOB":@"LONGTEXT";
+ default:
+ switch (length) {
+ case 255: return isBlob? @"TINYBLOB":@"TINYTEXT";
+ case 65535: return isBlob? @"BLOB":@"TEXT";
+ case 16777215: return isBlob? @"MEDIUMBLOB":@"MEDIUMTEXT";
+ case 4294967295: return isBlob? @"LONGBLOB":@"LONGTEXT";
+ default:
+ return @"UNKNOWN";
+ }
+ }
+ }
+ case MYSQL_TYPE_VAR_STRING:
+ if (flags & ENUM_FLAG) {
+ return @"ENUM";
+ }
+ if (flags & SET_FLAG) {
+ return @"SET";
+ }
+ if (charsetnr == MAGIC_BINARY_CHARSET_NR) {
+ return @"VARBINARY";
+ }
+ return @"VARCHAR";
+ case MYSQL_TYPE_STRING:
+ if (flags & ENUM_FLAG) {
+ return @"ENUM";
+ }
+ if (flags & SET_FLAG) {
+ return @"SET";
+ }
+ if ((flags & BINARY_FLAG) && charsetnr == MAGIC_BINARY_CHARSET_NR) {
+ return @"BINARY";
+ }
+ return @"CHAR";
+ case MYSQL_TYPE_ENUM:
+ /* This should never happen */
+ return @"ENUM";
+ case MYSQL_TYPE_YEAR:
+ return @"YEAR";
+ case MYSQL_TYPE_SET:
+ /* This should never happen */
+ return @"SET";
+ case MYSQL_TYPE_GEOMETRY:
+ return @"GEOMETRY";
+ default:
+ return @"UNKNOWN";
+ }
+}
+
+/**
+ * Merge mysql_types into type groups
+ */
+- (NSString *)mysqlTypeToGroupForType:(unsigned int)type withCharsetNr:(unsigned int)charsetnr withFlags:(unsigned int)flags
+{
+ switch(type){
+ case FIELD_TYPE_BIT:
+ return @"bit";
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_INT24:
+ return @"integer";
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ case MYSQL_TYPE_DECIMAL:
+ return @"float";
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIMESTAMP:
+ return @"date";
+ case MYSQL_TYPE_VAR_STRING:
+ if (flags & ENUM_FLAG) {
+ return @"enum";
+ }
+ if (flags & SET_FLAG) {
+ return @"enum";
+ }
+ if (charsetnr == MAGIC_BINARY_CHARSET_NR) {
+ return @"binary";
+ }
+ return @"string";
+ case MYSQL_TYPE_STRING:
+ if (flags & ENUM_FLAG) {
+ return @"enum";
+ }
+ if (flags & SET_FLAG) {
+ return @"enum";
+ }
+ if ((flags & BINARY_FLAG) && charsetnr == MAGIC_BINARY_CHARSET_NR) {
+ return @"binary";
+ }
+ return @"string";
+ case MYSQL_TYPE_TINY_BLOB: // should no appear over the wire
+ case MYSQL_TYPE_MEDIUM_BLOB: // should no appear over the wire
+ case MYSQL_TYPE_LONG_BLOB: // should no appear over the wire
+ case MYSQL_TYPE_BLOB:
+ {
+ if (charsetnr == MAGIC_BINARY_CHARSET_NR) {
+ return @"blobdata";
+ } else {
+ return @"textdata";
+ }
+ }
+ case MYSQL_TYPE_GEOMETRY:
+ return @"geometry";
+ default:
+ return @"blobdata";
+
+ }
+}
+
+/**
+ * Convert a mysql_charsetnr into a charset name as string
+ */
+- (NSString *)findCharsetName:(unsigned int)charsetnr
+{
+ const OUR_CHARSET * c = our_charsets60;
+
+ do {
+ if (c->nr == charsetnr)
+ return [self stringWithCString:c->name];
+ ++c;
+ } while (c[0].nr != 0);
+
+ return @"UNKNOWN";
+}
+
+/**
+ * Convert a mysql_charsetnr into a collation name as string
+ */
+- (NSString *)findCharsetCollation:(unsigned int)charsetnr
+{
+ const OUR_CHARSET * c = our_charsets60;
+
+ do {
+ if (c->nr == charsetnr)
+ return [self stringWithCString:c->collation];
+ ++c;
+ } while (c[0].nr != 0);
+
+ return @"UNKNOWN";
+}
+
+/**
+ * Return the max byte length to store a char by using
+ * a specific mysql_charsetnr
+ */
+- (unsigned int)findCharsetMaxByteLengthPerChar:(unsigned int)charsetnr
+{
+ const OUR_CHARSET * c = our_charsets60;
+
+ do {
+ if (c->nr == charsetnr)
+ return c->char_maxlen;
+ ++c;
+ } while (c[0].nr != 0);
+
+ return 1;
+}
+
+#pragma mark -
+
+/**
+ * Do one really needs an explanation for this method? Which by the way you should not use...
+ */
+- (void) dealloc
+{
+ if (mResult) {
+ mysql_free_result(mResult);
+ }
+
+ if (mNames) {
+ [mNames autorelease];
+ }
+
+ if (mMySQLLocales) {
+ [mMySQLLocales autorelease];
+ }
+
+ [super dealloc];
+}
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPResultPlus.h b/Frameworks/MCPKit/MCPFoundationKit/MCPResultPlus.h
new file mode 100644
index 00000000..5d836a03
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPResultPlus.h
@@ -0,0 +1,42 @@
+//
+// $Id: MCPResultPlus.h 1056 2009-07-18 10:42:29Z stuart02 $
+//
+// MCPResultPlus.h
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 03/06/2002.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import <Foundation/Foundation.h>
+
+#import "MCPResult.h"
+
+@interface MCPResult (MCPResultPlus)
+
+// Getting a complete column as an array
+- (NSArray *)fetchColAtIndex:(unsigned int)col;
+- (NSArray *)fetchColWithName:(NSString *)colName;
+
+// Getting the complete result as 2D array
+- (id)fetch2DResultAsType:(MCPReturnType)type;
+
+@end
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPResultPlus.m b/Frameworks/MCPKit/MCPFoundationKit/MCPResultPlus.m
new file mode 100644
index 00000000..bee4442a
--- /dev/null
+++ b/Frameworks/MCPKit/MCPFoundationKit/MCPResultPlus.m
@@ -0,0 +1,188 @@
+//
+// $Id: MCPResultPlus.m 1056 2009-07-18 10:42:29Z stuart02 $
+//
+// MCPResultPlus.m
+// MCPKit
+//
+// Created by Serge Cohen (serge.cohen@m4x.org) on 03/06/2002.
+// Copyright (c) 2001 Serge Cohen. All rights reserved.
+//
+// Forked by the Sequel Pro team (sequelpro.com), April 2009
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://mysql-cocoa.sourceforge.net/>
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "MCPResultPlus.h"
+
+/**
+ * This Category is provided to get shortcuts reformat the table obtained by a MCPResult
+ * (fetching a column, a 2D array...).
+ */
+@implementation MCPResult (MCPResultPlus)
+
+/**
+ * Getting a complete column into a NSArray (1D). The index starts from 0 (first column).
+ *
+ * The index 0 of the returned array always correspond to the first row (ie: returned NSArray is indexed
+ * by row number), the read position is restored after to it's initial position after the read.
+ */
+- (NSArray *)fetchColAtIndex:(unsigned int)col
+{
+ NSMutableArray *theCol = [NSMutableArray arrayWithCapacity:[self numOfRows]];
+ MYSQL_ROW_OFFSET thePosition;
+ NSArray *theRow;
+
+ if ((mResult == NULL) || ([self numOfRows] == 0)) {
+ // If there is no results, returns nil.
+ return nil;
+ }
+ if (col >= mNumOfFields) {
+ // Bad column number
+ NSLog (@"The index : %d is not within the range 0 - %d\n", (long)col, (long)mNumOfFields);
+ return nil;
+ }
+
+ thePosition = mysql_row_tell(mResult);
+
+ [self dataSeek:0];
+
+ // One might want to have optimized code here. Maybe in later versions
+ while (theRow = [self fetchRowAsType:MCPTypeArray])
+ {
+ [theCol addObject:[theRow objectAtIndex:col]];
+ }
+
+ // Returning to the proper row
+ mysql_row_seek(mResult, thePosition);
+
+ return [NSArray arrayWithArray:theCol];
+}
+
+/**
+ * The same as !{fetchColAtIndex:}, but the choice of the column is done by it's field name. Indeed it is just
+ * a wrapper to !{fetchColAtIndex}.
+ */
+- (NSArray *)fetchColWithName:(NSString *)colName
+{
+ unsigned int theCol;
+
+ if (mResult == NULL) {
+ // If there is no results, returns nil.
+ return nil;
+ }
+
+ if (mNames == nil) {
+ [self fetchFieldNames];
+ }
+
+ if ([mNames indexOfObject:colName] == NSNotFound) {
+ NSLog(@"No column have been found with name : %@\n", colName);
+ return nil;
+ }
+
+ theCol = [mNames indexOfObject:colName];
+
+ return [self fetchColAtIndex:theCol];
+}
+
+/**
+ * Returns the complete result table in a 2D object, which type depends on aType:
+ *
+ * - !{MCPTypeArray} : a NSArray of rows as NSArray,
+ *
+ * - !{MCPTypeDictionary} : a NSArray of rows as NSDictionary,
+ *
+ * - !{MCPTypeFlippedArray} : a NSArray of columns (as NSArray),
+ *
+ * - !{MCPTypeFlippedDictionary} : a NSDictionary of columns (as NSArray)
+ *
+ * In any case the read position is restored at the end of the call (hence a fetchRow will get the same row
+ * wether this method is called before it or not).
+ */
+- (id) fetch2DResultAsType:(MCPReturnType)type;
+{
+ id theTable, theVect;
+ MYSQL_ROW_OFFSET thePosition;
+ unsigned int i;
+
+ if (mResult == NULL) {
+ // If there is no results, returns nil.
+ return nil;
+ }
+
+ thePosition = mysql_row_tell(mResult);
+
+ [self dataSeek:0];
+
+ switch (type)
+ {
+ case MCPTypeArray :
+ theTable = [NSMutableArray arrayWithCapacity:[self numOfRows]];
+
+ while (theVect = [self fetchRowAsArray])
+ {
+ [theTable addObject:theVect];
+ }
+
+ theTable = [NSArray arrayWithArray:theTable];
+ break;
+ case MCPTypeDictionary :
+ theTable = [NSMutableArray arrayWithCapacity:[self numOfRows]];
+
+ while (theVect = [self fetchRowAsDictionary])
+ {
+ [theTable addObject:theVect];
+ }
+
+ theTable = [NSArray arrayWithArray:theTable];
+ break;
+ case MCPTypeFlippedArray :
+ theTable = [NSMutableArray arrayWithCapacity:mNumOfFields];
+
+ for (i=0; i<mNumOfFields; i++)
+ {
+ [theTable addObject:[self fetchColAtIndex:i]];
+ }
+
+ theTable = [NSArray arrayWithArray:theTable];
+ break;
+ case MCPTypeFlippedDictionary :
+ theTable = [NSMutableDictionary dictionaryWithCapacity:mNumOfFields];
+
+ if (mNames == nil) {
+ [self fetchFieldNames];
+ }
+
+ for (i=0; i<mNumOfFields; i++)
+ {
+ [theTable setObject:[self fetchColAtIndex:i] forKey:[mNames objectAtIndex:i]];
+ }
+
+ theTable = [NSDictionary dictionaryWithDictionary:theTable];
+ break;
+ default :
+ NSLog (@"Unknown MCPReturnType : %d; return nil\n", (int)type);
+ theTable = nil;
+ break;
+ }
+
+ mysql_row_seek(mResult, thePosition);
+
+ return theTable;
+}
+
+@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/my_alloc.h b/Frameworks/MCPKit/MySQL/include/my_alloc.h
index a3dd35d7..93b7438a 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/my_alloc.h
+++ b/Frameworks/MCPKit/MySQL/include/my_alloc.h
@@ -2,8 +2,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -38,12 +37,12 @@ typedef struct st_mem_root
USED_MEM *used; /* blocks almost without free memory */
USED_MEM *pre_alloc; /* preallocated block */
/* if block have less memory it will be put in 'used' list */
- unsigned int min_malloc;
- unsigned int block_size; /* initial block size */
+ size_t min_malloc;
+ size_t block_size; /* initial block size */
unsigned int block_num; /* allocated blocks counter */
/*
first free block in queue test counter (if it exceed
- MAX_BLOCK_USAGE_BEFORE_DROP block will be droped in 'used' list)
+ MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list)
*/
unsigned int first_block_usage;
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/my_list.h b/Frameworks/MCPKit/MySQL/include/my_list.h
index f786621e..775b5658 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/my_list.h
+++ b/Frameworks/MCPKit/MySQL/include/my_list.h
@@ -2,8 +2,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -34,11 +33,11 @@ extern LIST *list_cons(void *data,LIST *root);
extern LIST *list_reverse(LIST *root);
extern void list_free(LIST *root,unsigned int free_data);
extern unsigned int list_length(LIST *);
-extern int list_walk(LIST *,list_walk_action action,gptr argument);
+extern int list_walk(LIST *,list_walk_action action,unsigned char * argument);
-#define rest(a) ((a)->next)
+#define list_rest(a) ((a)->next)
#define list_push(a,b) (a)=list_cons((b),(a))
-#define list_pop(A) {LIST *old=(A); (A)=list_delete(old,old) ; my_free((gptr) old,MYF(MY_FAE)); }
+#define list_pop(A) {LIST *old=(A); (A)=list_delete(old,old) ; my_free((unsigned char *) old,MYF(MY_FAE)); }
#ifdef __cplusplus
}
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql.h b/Frameworks/MCPKit/MySQL/include/mysql.h
index d8a56126..d114afb6 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql.h
+++ b/Frameworks/MCPKit/MySQL/include/mysql.h
@@ -2,8 +2,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,9 +13,24 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/*
+ This file defines the client API to MySQL and also the ABI of the
+ dynamically linked libmysqlclient.
+
+ The ABI should never be changed in a released product of MySQL
+ thus you need to take great care when changing the file. In case
+ the file is changed so the ABI is broken, you must also
+ update the SHAREDLIB_MAJOR_VERSION in configure.in .
+
+*/
+
#ifndef _mysql_h
#define _mysql_h
+#ifdef _AIX /* large-file support will break without this */
+#include <standards.h>
+#endif
+
#ifdef __CYGWIN__ /* CYGWIN implements a UNIX API */
#undef WIN
#undef _WIN
@@ -32,7 +46,7 @@ extern "C" {
#ifndef _global_h /* If not standard header */
#include <sys/types.h>
#ifdef __LCC__
-#include <winsock.h> /* For windows */
+#include <winsock2.h> /* For windows */
#endif
typedef char my_bool;
#if (defined(_WIN32) || defined(_WIN64)) && !defined(__WIN__)
@@ -43,7 +57,6 @@ typedef char my_bool;
#else
#define STDCALL __stdcall
#endif
-typedef char * gptr;
#ifndef my_socket_defined
#ifdef __WIN__
@@ -54,10 +67,9 @@ typedef int my_socket;
#endif /* my_socket_defined */
#endif /* _global_h */
+#include "mysql_version.h"
#include "mysql_com.h"
#include "mysql_time.h"
-#include "mysql_version.h"
-#include "typelib.h"
#include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */
@@ -74,14 +86,15 @@ extern char *mysql_unix_port;
#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG)
#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG)
#define IS_BLOB(n) ((n) & BLOB_FLAG)
-#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR)
+#define IS_NUM(t) ((t) <= MYSQL_TYPE_INT24 || (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL)
#define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG)
-#define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR)
+#define INTERNAL_NUM_FIELD(f) (((f)->type <= MYSQL_TYPE_INT24 && ((f)->type != MYSQL_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == MYSQL_TYPE_YEAR)
+#define IS_LONGDATA(t) ((t) >= MYSQL_TYPE_TINY_BLOB && (t) <= MYSQL_TYPE_STRING)
typedef struct st_mysql_field {
char *name; /* Name of column */
- char *org_name; /* Original column name, if an alias */
+ char *org_name; /* Original column name, if an alias */
char *table; /* Table of column if column was a field */
char *org_table; /* Org table name, if table was an alias */
char *db; /* Database for table */
@@ -100,6 +113,7 @@ typedef struct st_mysql_field {
unsigned int decimals; /* Number of decimals in field */
unsigned int charsetnr; /* Character set */
enum enum_field_types type; /* Type of field. See mysql_com.h for types */
+ void *extension;
} MYSQL_FIELD;
typedef char **MYSQL_ROW; /* return data as array of strings */
@@ -115,8 +129,13 @@ typedef unsigned long long my_ulonglong;
#endif
#endif
+#include "typelib.h"
+
#define MYSQL_COUNT_ERROR (~(my_ulonglong) 0)
+/* backward compatibility define - to be removed eventually */
+#define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED
+
typedef struct st_mysql_rows {
struct st_mysql_rows *next; /* list of rows */
MYSQL_ROW data;
@@ -127,14 +146,15 @@ typedef MYSQL_ROWS *MYSQL_ROW_OFFSET; /* offset to current row */
#include "my_alloc.h"
+typedef struct embedded_query_result EMBEDDED_QUERY_RESULT;
typedef struct st_mysql_data {
- my_ulonglong rows;
- unsigned int fields;
MYSQL_ROWS *data;
+ struct embedded_query_result *embedded_info;
MEM_ROOT alloc;
-#if !defined(CHECK_EMBEDDED_DIFFERENCES) || defined(EMBEDDED_LIBRARY)
- MYSQL_ROWS **prev_ptr;
-#endif
+ my_ulonglong rows;
+ unsigned int fields;
+ /* extra info for embedded library */
+ void *extension;
} MYSQL_DATA;
enum mysql_option
@@ -145,7 +165,9 @@ enum mysql_option
MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT,
MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT,
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
- MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH
+ MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
+ MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT
};
struct st_mysql_options {
@@ -186,6 +208,8 @@ struct st_mysql_options {
char *client_ip;
/* Refuse client connecting to server if it uses old (pre-4.1.1) protocol */
my_bool secure_auth;
+ /* 0 - never report, 1 - always report (default) */
+ my_bool report_data_truncation;
/* function pointers for local infile support */
int (*local_infile_init)(void **, const char *, void *);
@@ -193,6 +217,7 @@ struct st_mysql_options {
void (*local_infile_end)(void *);
int (*local_infile_error)(void *, char *, unsigned int);
void *local_infile_userdata;
+ void *extension;
};
enum mysql_status
@@ -215,20 +240,33 @@ enum mysql_rpl_type
MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE, MYSQL_RPL_ADMIN
};
+typedef struct character_set
+{
+ unsigned int number; /* character set number */
+ unsigned int state; /* character set state */
+ const char *csname; /* collation name */
+ const char *name; /* character set name */
+ const char *comment; /* comment */
+ const char *dir; /* character set directory */
+ unsigned int mbminlen; /* min. length for multibyte strings */
+ unsigned int mbmaxlen; /* max. length for multibyte strings */
+} MY_CHARSET_INFO;
+
struct st_mysql_methods;
+struct st_mysql_stmt;
typedef struct st_mysql
{
NET net; /* Communication parameters */
- gptr connector_fd; /* ConnectorFd for SSL */
- char *host,*user,*passwd,*unix_socket,*server_version,*host_info,*info;
- char *db;
+ unsigned char *connector_fd; /* ConnectorFd for SSL */
+ char *host,*user,*passwd,*unix_socket,*server_version,*host_info;
+ char *info, *db;
struct charset_info_st *charset;
MYSQL_FIELD *fields;
MEM_ROOT field_alloc;
my_ulonglong affected_rows;
my_ulonglong insert_id; /* id if insert on table with NEXTNR */
- my_ulonglong extra_info; /* Used by mysqlshow */
+ my_ulonglong extra_info; /* Not used */
unsigned long thread_id; /* Id for connection in server */
unsigned long packet_length;
unsigned int port;
@@ -269,23 +307,28 @@ typedef struct st_mysql
from mysql_stmt_close if close had to cancel result set of this object.
*/
my_bool *unbuffered_fetch_owner;
+ /* needed for embedded server - no net buffer to store the 'info' */
+ char *info_buffer;
+ void *extension;
} MYSQL;
+
typedef struct st_mysql_res {
- my_ulonglong row_count;
+ my_ulonglong row_count;
MYSQL_FIELD *fields;
MYSQL_DATA *data;
MYSQL_ROWS *data_cursor;
unsigned long *lengths; /* column lengths of current row */
MYSQL *handle; /* for unbuffered reads */
- MEM_ROOT field_alloc;
- unsigned int field_count, current_field;
+ const struct st_mysql_methods *methods;
MYSQL_ROW row; /* If unbuffered read */
MYSQL_ROW current_row; /* buffer to current row */
+ MEM_ROOT field_alloc;
+ unsigned int field_count, current_field;
my_bool eof; /* Used by mysql_fetch_row */
/* mysql_stmt_close() had to cancel this result */
my_bool unbuffered_fetch_cancelled;
- const struct st_mysql_methods *methods;
+ void *extension;
} MYSQL_RES;
#define MAX_MYSQL_MANAGER_ERR 256
@@ -305,21 +348,23 @@ typedef struct st_mysql_res {
typedef struct st_mysql_manager
{
NET net;
- char *host,*user,*passwd;
+ char *host, *user, *passwd;
+ char *net_buf, *net_buf_pos, *net_data_end;
unsigned int port;
- my_bool free_me;
- my_bool eof;
int cmd_status;
int last_errno;
- char* net_buf,*net_buf_pos,*net_data_end;
int net_buf_size;
+ my_bool free_me;
+ my_bool eof;
char last_error[MAX_MYSQL_MANAGER_ERR];
+ void *extension;
} MYSQL_MANAGER;
typedef struct st_mysql_parameters
{
unsigned long *p_max_allowed_packet;
unsigned long *p_net_buffer_length;
+ void *extension;
} MYSQL_PARAMETERS;
#if !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
@@ -334,6 +379,7 @@ typedef struct st_mysql_parameters
*/
int STDCALL mysql_server_init(int argc, char **argv, char **groups);
void STDCALL mysql_server_end(void);
+
/*
mysql_server_init/end need to be called when using libmysqld or
libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so
@@ -381,11 +427,13 @@ unsigned int STDCALL mysql_warning_count(MYSQL *mysql);
const char * STDCALL mysql_info(MYSQL *mysql);
unsigned long STDCALL mysql_thread_id(MYSQL *mysql);
const char * STDCALL mysql_character_set_name(MYSQL *mysql);
+int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname);
MYSQL * STDCALL mysql_init(MYSQL *mysql);
my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
const char *cert, const char *ca,
const char *capath, const char *cipher);
+const char * STDCALL mysql_get_ssl_cipher(MYSQL *mysql);
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db);
MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
@@ -414,6 +462,8 @@ my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
unsigned long length);
my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
unsigned long length);
+void STDCALL mysql_get_character_set_info(MYSQL *mysql,
+ MY_CHARSET_INFO *charset);
/* local infile support */
@@ -486,7 +536,7 @@ MYSQL_RES * STDCALL mysql_list_dbs(MYSQL *mysql,const char *wild);
MYSQL_RES * STDCALL mysql_list_tables(MYSQL *mysql,const char *wild);
MYSQL_RES * STDCALL mysql_list_processes(MYSQL *mysql);
int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option,
- const char *arg);
+ const void *arg);
void STDCALL mysql_free_result(MYSQL_RES *result);
void STDCALL mysql_data_seek(MYSQL_RES *result,
my_ulonglong offset);
@@ -507,16 +557,6 @@ unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql,
char *to,const char *from,
unsigned long length);
void STDCALL mysql_debug(const char *debug);
-char * STDCALL mysql_odbc_escape_string(MYSQL *mysql,
- char *to,
- unsigned long to_length,
- const char *from,
- unsigned long from_length,
- void *param,
- char *
- (*extend_buffer)
- (void *, char *to,
- unsigned long *length));
void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name);
unsigned int STDCALL mysql_thread_safe(void);
my_bool STDCALL mysql_embedded(void);
@@ -548,28 +588,94 @@ enum enum_mysql_stmt_state
};
-/* bind structure */
+/*
+ This structure is used to define bind information, and
+ internally by the client library.
+ Public members with their descriptions are listed below
+ (conventionally `On input' refers to the binds given to
+ mysql_stmt_bind_param, `On output' refers to the binds given
+ to mysql_stmt_bind_result):
+
+ buffer_type - One of the MYSQL_* types, used to describe
+ the host language type of buffer.
+ On output: if column type is different from
+ buffer_type, column value is automatically converted
+ to buffer_type before it is stored in the buffer.
+ buffer - On input: points to the buffer with input data.
+ On output: points to the buffer capable to store
+ output data.
+ The type of memory pointed by buffer must correspond
+ to buffer_type. See the correspondence table in
+ the comment to mysql_stmt_bind_param.
+
+ The two above members are mandatory for any kind of bind.
+
+ buffer_length - the length of the buffer. You don't have to set
+ it for any fixed length buffer: float, double,
+ int, etc. It must be set however for variable-length
+ types, such as BLOBs or STRINGs.
+
+ length - On input: in case when lengths of input values
+ are different for each execute, you can set this to
+ point at a variable containining value length. This
+ way the value length can be different in each execute.
+ If length is not NULL, buffer_length is not used.
+ Note, length can even point at buffer_length if
+ you keep bind structures around while fetching:
+ this way you can change buffer_length before
+ each execution, everything will work ok.
+ On output: if length is set, mysql_stmt_fetch will
+ write column length into it.
+
+ is_null - On input: points to a boolean variable that should
+ be set to TRUE for NULL values.
+ This member is useful only if your data may be
+ NULL in some but not all cases.
+ If your data is never NULL, is_null should be set to 0.
+ If your data is always NULL, set buffer_type
+ to MYSQL_TYPE_NULL, and is_null will not be used.
+
+ is_unsigned - On input: used to signify that values provided for one
+ of numeric types are unsigned.
+ On output describes signedness of the output buffer.
+ If, taking into account is_unsigned flag, column data
+ is out of range of the output buffer, data for this column
+ is regarded truncated. Note that this has no correspondence
+ to the sign of result set column, if you need to find it out
+ use mysql_stmt_result_metadata.
+ error - where to write a truncation error if it is present.
+ possible error value is:
+ 0 no truncation
+ 1 value is out of range or buffer is too small
+
+ Please note that MYSQL_BIND also has internals members.
+*/
+
typedef struct st_mysql_bind
{
unsigned long *length; /* output length pointer */
my_bool *is_null; /* Pointer to null indicator */
void *buffer; /* buffer to get/put data */
- enum enum_field_types buffer_type; /* buffer type */
- unsigned long buffer_length; /* buffer length, must be set for str/binary */
-
- /* Following are for internal use. Set by mysql_stmt_bind_param */
- unsigned char *inter_buffer; /* for the current data position */
+ /* set this if you want to track data truncations happened during fetch */
+ my_bool *error;
+ unsigned char *row_ptr; /* for the current data position */
+ void (*store_param_func)(NET *net, struct st_mysql_bind *param);
+ void (*fetch_result)(struct st_mysql_bind *, MYSQL_FIELD *,
+ unsigned char **row);
+ void (*skip_result)(struct st_mysql_bind *, MYSQL_FIELD *,
+ unsigned char **row);
+ /* output buffer length, must be set when fetching str/binary */
+ unsigned long buffer_length;
unsigned long offset; /* offset position for char/binary fetch */
- unsigned long internal_length; /* Used if length is 0 */
+ unsigned long length_value; /* Used if length is 0 */
unsigned int param_number; /* For null count and error messages */
unsigned int pack_length; /* Internal length for packed data */
+ enum enum_field_types buffer_type; /* buffer type */
+ my_bool error_value; /* used if error is 0 */
my_bool is_unsigned; /* set if integer type is unsigned */
my_bool long_data_used; /* If used with mysql_send_long_data */
- my_bool internal_is_null; /* Used if is_null is 0 */
- void (*store_param_func)(NET *net, struct st_mysql_bind *param);
- void (*fetch_result)(struct st_mysql_bind *, unsigned char **row);
- void (*skip_result)(struct st_mysql_bind *, MYSQL_FIELD *,
- unsigned char **row);
+ my_bool is_null_value; /* Used if is_null is 0 */
+ void *extension;
} MYSQL_BIND;
@@ -584,16 +690,23 @@ typedef struct st_mysql_stmt
MYSQL_FIELD *fields; /* result set metadata */
MYSQL_DATA result; /* cached result set */
MYSQL_ROWS *data_cursor; /* current row in cached result */
- /* copy of mysql->affected_rows after statement execution */
- my_ulonglong affected_rows;
- my_ulonglong insert_id; /* copy of mysql->insert_id */
/*
mysql_stmt_fetch() calls this function to fetch one row (it's different
for buffered, unbuffered and cursor fetch).
*/
int (*read_row_func)(struct st_mysql_stmt *stmt,
unsigned char **row);
+ /* copy of mysql->affected_rows after statement execution */
+ my_ulonglong affected_rows;
+ my_ulonglong insert_id; /* copy of mysql->insert_id */
unsigned long stmt_id; /* Id for prepared statement */
+ unsigned long flags; /* i.e. type of cursor to open */
+ unsigned long prefetch_rows; /* number of rows per one COM_FETCH */
+ /*
+ Copied from mysql->server_status after execute/fetch to know
+ server-side cursor status for this statement.
+ */
+ unsigned int server_status;
unsigned int last_errno; /* error code */
unsigned int param_count; /* input parameter count */
unsigned int field_count; /* number of columns in result set */
@@ -603,7 +716,7 @@ typedef struct st_mysql_stmt
/* Types of input parameters should be sent to server */
my_bool send_types_to_server;
my_bool bind_param_done; /* input buffers were supplied */
- my_bool bind_result_done; /* output buffers were supplied */
+ unsigned char bind_result_done; /* output buffers were supplied */
/* mysql_stmt_close() had to cancel this result */
my_bool unbuffered_fetch_cancelled;
/*
@@ -611,6 +724,7 @@ typedef struct st_mysql_stmt
metadata fields when doing mysql_stmt_store_result.
*/
my_bool update_max_length;
+ void *extension;
} MYSQL_STMT;
enum enum_stmt_attr_type
@@ -622,7 +736,17 @@ enum enum_stmt_attr_type
In the new API we do that only by request because it slows down
mysql_stmt_store_result sufficiently.
*/
- STMT_ATTR_UPDATE_MAX_LENGTH
+ STMT_ATTR_UPDATE_MAX_LENGTH,
+ /*
+ unsigned long with combination of cursor flags (read only, for update,
+ etc)
+ */
+ STMT_ATTR_CURSOR_TYPE,
+ /*
+ Amount of rows to retrieve from server per one fetch if using cursors.
+ Accepts unsigned long attribute in the range 1 - ulong_max
+ */
+ STMT_ATTR_PREFETCH_ROWS
};
@@ -631,11 +755,12 @@ typedef struct st_mysql_methods
my_bool (*read_query_result)(MYSQL *mysql);
my_bool (*advanced_command)(MYSQL *mysql,
enum enum_server_command command,
- const char *header,
+ const unsigned char *header,
unsigned long header_length,
- const char *arg,
+ const unsigned char *arg,
unsigned long arg_length,
- my_bool skip_check);
+ my_bool skip_check,
+ MYSQL_STMT *stmt);
MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
unsigned int fields);
MYSQL_RES * (*use_result)(MYSQL *mysql);
@@ -652,6 +777,7 @@ typedef struct st_mysql_methods
const char *(*read_statistics)(MYSQL *mysql);
my_bool (*next_result)(MYSQL *mysql);
int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
+ int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
#endif
} MYSQL_METHODS;
@@ -661,7 +787,7 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
unsigned long length);
int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt);
int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt);
-int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
+int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind_arg,
unsigned int column,
unsigned long offset);
int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt);
@@ -704,7 +830,8 @@ void STDCALL mysql_close(MYSQL *sock);
/* status return codes */
-#define MYSQL_NO_DATA 100
+#define MYSQL_NO_DATA 100
+#define MYSQL_DATA_TRUNCATED 101
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
@@ -723,9 +850,11 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
*/
#define simple_command(mysql, command, arg, length, skip_check) \
- (*(mysql)->methods->advanced_command)(mysql, command, \
- NullS, 0, arg, length, skip_check)
-unsigned long net_safe_read(MYSQL* mysql);
+ (*(mysql)->methods->advanced_command)(mysql, command, 0, \
+ 0, arg, length, skip_check, NULL)
+#define stmt_command(mysql, command, arg, length, stmt) \
+ (*(mysql)->methods->advanced_command)(mysql, command, 0, \
+ 0, arg, length, 1, stmt)
#ifdef __NETWARE__
#pragma pack(pop) /* restore alignment */
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_com.h b/Frameworks/MCPKit/MySQL/include/mysql_com.h
index 6f941fc0..db5a5eb8 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_com.h
+++ b/Frameworks/MCPKit/MySQL/include/mysql_com.h
@@ -2,8 +2,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,12 +20,24 @@
#ifndef _mysql_com_h
#define _mysql_com_h
-#define NAME_LEN 64 /* Field/table name length */
#define HOSTNAME_LENGTH 60
-#define USERNAME_LENGTH 16
+#define SYSTEM_CHARSET_MBMAXLEN 3
+#define NAME_CHAR_LEN 64 /* Field/table name length */
+#define USERNAME_CHAR_LENGTH 16
+#define NAME_LEN (NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN)
+#define USERNAME_LENGTH (USERNAME_CHAR_LENGTH*SYSTEM_CHARSET_MBMAXLEN)
+
#define SERVER_VERSION_LENGTH 60
#define SQLSTATE_LENGTH 5
+/*
+ USER_HOST_BUFF_SIZE -- length of string buffer, that is enough to contain
+ username and hostname parts of the user identifier with trailing zero in
+ MySQL standard format:
+ user_name_part@host_name_part\0
+*/
+#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_LENGTH + 2
+
#define LOCAL_HOST "localhost"
#define LOCAL_HOST_NAMEDPIPE "."
@@ -36,6 +47,11 @@
#define MYSQL_SERVICENAME "MySQL"
#endif /* __WIN__ */
+/*
+ You should add new commands to the end of this list, otherwise old
+ servers won't be able to handle them as 'unsupported'.
+*/
+
enum enum_server_command
{
COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST,
@@ -43,8 +59,8 @@ enum enum_server_command
COM_PROCESS_INFO, COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING,
COM_TIME, COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE,
- COM_PREPARE, COM_EXECUTE, COM_LONG_DATA, COM_CLOSE_STMT,
- COM_RESET_STMT, COM_SET_OPTION,
+ COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE,
+ COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_DAEMON,
/* don't forget to update const char *command_name[] in sql_parse.cc */
/* Must be last */
@@ -77,11 +93,17 @@ enum enum_server_command
#define AUTO_INCREMENT_FLAG 512 /* field is a autoincrement field */
#define TIMESTAMP_FLAG 1024 /* Field is a timestamp */
#define SET_FLAG 2048 /* field is a set */
+#define NO_DEFAULT_VALUE_FLAG 4096 /* Field doesn't have default value */
+#define ON_UPDATE_NOW_FLAG 8192 /* Field is set to NOW on UPDATE */
#define NUM_FLAG 32768 /* Field is num (for clients) */
#define PART_KEY_FLAG 16384 /* Intern; Part of some key */
#define GROUP_FLAG 32768 /* Intern: Group field */
#define UNIQUE_FLAG 65536 /* Intern: Used by sql_yacc */
#define BINCMP_FLAG 131072 /* Intern: Used by sql_yacc */
+#define GET_FIXED_FIELDS_FLAG (1 << 18) /* Used to get fields in item tree */
+#define FIELD_IN_PART_FUNC_FLAG (1 << 19)/* Field part of partition func */
+#define FIELD_IN_ADD_INDEX (1<< 20) /* Intern: Field used in ADD INDEX */
+#define FIELD_IS_RENAMED (1<< 21) /* Intern: Field is being renamed */
#define REFRESH_GRANT 1 /* Refresh grant tables */
#define REFRESH_LOG 2 /* Start on new log file */
@@ -120,23 +142,89 @@ enum enum_server_command
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
#define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */
#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */
-#define CLIENT_MULTI_STATEMENTS 65536 /* Enable/disable multi-stmt support */
-#define CLIENT_MULTI_RESULTS 131072 /* Enable/disable multi-results */
-#define CLIENT_REMEMBER_OPTIONS (((ulong) 1) << 31)
+#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
+#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */
+
+#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
+#define CLIENT_REMEMBER_OPTIONS (1UL << 31)
+
+/* Gather all possible capabilites (flags) supported by the server */
+#define CLIENT_ALL_FLAGS (CLIENT_LONG_PASSWORD | \
+ CLIENT_FOUND_ROWS | \
+ CLIENT_LONG_FLAG | \
+ CLIENT_CONNECT_WITH_DB | \
+ CLIENT_NO_SCHEMA | \
+ CLIENT_COMPRESS | \
+ CLIENT_ODBC | \
+ CLIENT_LOCAL_FILES | \
+ CLIENT_IGNORE_SPACE | \
+ CLIENT_PROTOCOL_41 | \
+ CLIENT_INTERACTIVE | \
+ CLIENT_SSL | \
+ CLIENT_IGNORE_SIGPIPE | \
+ CLIENT_TRANSACTIONS | \
+ CLIENT_RESERVED | \
+ CLIENT_SECURE_CONNECTION | \
+ CLIENT_MULTI_STATEMENTS | \
+ CLIENT_MULTI_RESULTS | \
+ CLIENT_SSL_VERIFY_SERVER_CERT | \
+ CLIENT_REMEMBER_OPTIONS)
+
+/*
+ Switch off the flags that are optional and depending on build flags
+ If any of the optional flags is supported by the build it will be switched
+ on before sending to the client during the connection handshake.
+*/
+#define CLIENT_BASIC_FLAGS (((CLIENT_ALL_FLAGS & ~CLIENT_SSL) \
+ & ~CLIENT_COMPRESS) \
+ & ~CLIENT_SSL_VERIFY_SERVER_CERT)
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
-#define SERVER_STATUS_MORE_RESULTS 4 /* More results on server */
#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */
#define SERVER_QUERY_NO_GOOD_INDEX_USED 16
#define SERVER_QUERY_NO_INDEX_USED 32
+/**
+ The server was able to fulfill the clients request and opened a
+ read-only non-scrollable cursor for a query. This flag comes
+ in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
+*/
+#define SERVER_STATUS_CURSOR_EXISTS 64
+/**
+ This flag is sent when a read-only cursor is exhausted, in reply to
+ COM_STMT_FETCH command.
+*/
+#define SERVER_STATUS_LAST_ROW_SENT 128
#define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */
+#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512
+/**
+ Sent to the client if after a prepared statement reprepare
+ we discovered that the new statement returns a different
+ number of result set columns.
+*/
+#define SERVER_STATUS_METADATA_CHANGED 1024
+
+/**
+ Server status flags that must be cleared when starting
+ execution of a new SQL statement.
+ Flags from this set are only added to the
+ current server status by the execution engine, but
+ never removed -- the execution engine expects them
+ to disappear automagically by the next command.
+*/
+#define SERVER_STATUS_CLEAR_SET (SERVER_QUERY_NO_GOOD_INDEX_USED| \
+ SERVER_QUERY_NO_INDEX_USED|\
+ SERVER_MORE_RESULTS_EXISTS|\
+ SERVER_STATUS_METADATA_CHANGED)
#define MYSQL_ERRMSG_SIZE 512
#define NET_READ_TIMEOUT 30 /* Timeout on read */
#define NET_WRITE_TIMEOUT 60 /* Timeout on write */
#define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */
+#define ONLY_KILL_QUERY 1
+
+
struct st_vio; /* Only C */
typedef struct st_vio Vio;
@@ -146,41 +234,52 @@ typedef struct st_vio Vio;
#define MAX_INT_WIDTH 10 /* Max width for a LONG w.o. sign */
#define MAX_BIGINT_WIDTH 20 /* Max width for a LONGLONG */
#define MAX_CHAR_WIDTH 255 /* Max length for a CHAR colum */
-#define MAX_BLOB_WIDTH 8192 /* Default width for blob */
+#define MAX_BLOB_WIDTH 16777216 /* Default width for blob */
typedef struct st_net {
#if !defined(CHECK_EMBEDDED_DIFFERENCES) || !defined(EMBEDDED_LIBRARY)
- Vio* vio;
+ Vio *vio;
unsigned char *buff,*buff_end,*write_pos,*read_pos;
my_socket fd; /* For Perl DBI/dbd */
- unsigned long max_packet,max_packet_size;
- unsigned int pkt_nr,compress_pkt_nr;
- unsigned int write_timeout, read_timeout, retry_count;
- int fcntl;
- my_bool compress;
/*
The following variable is set if we are doing several queries in one
command ( as in LOAD TABLE ... FROM MASTER ),
and do not want to confuse the client with OK at the wrong time
*/
unsigned long remain_in_buf,length, buf_length, where_b;
+ unsigned long max_packet,max_packet_size;
+ unsigned int pkt_nr,compress_pkt_nr;
+ unsigned int write_timeout, read_timeout, retry_count;
+ int fcntl;
unsigned int *return_status;
unsigned char reading_or_writing;
char save_char;
- my_bool no_send_ok;
+ my_bool unused0; /* Please remove with the next incompatible ABI change. */
+ my_bool unused; /* Please remove with the next incompatible ABI change */
+ my_bool compress;
+ my_bool unused1; /* Please remove with the next incompatible ABI change. */
/*
Pointer to query object in query cache, do not equal NULL (0) for
queries in cache that have not stored its results yet
*/
#endif
- char last_error[MYSQL_ERRMSG_SIZE], sqlstate[SQLSTATE_LENGTH+1];
+ /*
+ 'query_cache_query' should be accessed only via query cache
+ functions and methods to maintain proper locking.
+ */
+ unsigned char *query_cache_query;
unsigned int last_errno;
- unsigned char error;
- gptr query_cache_query;
- my_bool report_error; /* We should report error (we have unreported error) */
+ unsigned char error;
+ my_bool unused2; /* Please remove with the next incompatible ABI change. */
my_bool return_errno;
+ /** Client library error message buffer. Actually belongs to struct MYSQL. */
+ char last_error[MYSQL_ERRMSG_SIZE];
+ /** Client library sqlstate buffer. Set along with the error message. */
+ char sqlstate[SQLSTATE_LENGTH+1];
+ void *extension;
} NET;
+
#define packet_error (~(unsigned long) 0)
enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
@@ -190,8 +289,9 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
- MYSQL_TYPE_NEWDATE,
- MYSQL_TYPE_NEW_DECIMAL=246,
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
+ MYSQL_TYPE_BIT,
+ MYSQL_TYPE_NEWDECIMAL=246,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
MYSQL_TYPE_TINY_BLOB=249,
@@ -207,6 +307,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
/* For backward compatibility */
#define CLIENT_MULTI_QUERIES CLIENT_MULTI_STATEMENTS
#define FIELD_TYPE_DECIMAL MYSQL_TYPE_DECIMAL
+#define FIELD_TYPE_NEWDECIMAL MYSQL_TYPE_NEWDECIMAL
#define FIELD_TYPE_TINY MYSQL_TYPE_TINY
#define FIELD_TYPE_SHORT MYSQL_TYPE_SHORT
#define FIELD_TYPE_LONG MYSQL_TYPE_LONG
@@ -221,7 +322,6 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
#define FIELD_TYPE_DATETIME MYSQL_TYPE_DATETIME
#define FIELD_TYPE_YEAR MYSQL_TYPE_YEAR
#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE
-#define FIELD_TYPE_NEW_DECIMAL MYSQL_TYPE_NEW_DECIMAL
#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM
#define FIELD_TYPE_SET MYSQL_TYPE_SET
#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB
@@ -233,6 +333,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY
#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM
#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
+#define FIELD_TYPE_BIT MYSQL_TYPE_BIT
/* Shutdown/kill enums and constants */
@@ -267,6 +368,16 @@ enum mysql_enum_shutdown_level {
KILL_CONNECTION= 255
};
+
+enum enum_cursor_type
+{
+ CURSOR_TYPE_NO_CURSOR= 0,
+ CURSOR_TYPE_READ_ONLY= 1,
+ CURSOR_TYPE_FOR_UPDATE= 2,
+ CURSOR_TYPE_SCROLLABLE= 4
+};
+
+
/* options for mysql_set_option */
enum enum_mysql_set_option
{
@@ -283,16 +394,21 @@ extern "C" {
my_bool my_net_init(NET *net, Vio* vio);
void my_net_local_init(NET *net);
void net_end(NET *net);
-void net_clear(NET *net);
-my_bool net_realloc(NET *net, unsigned long length);
+ void net_clear(NET *net, my_bool clear_buffer);
+my_bool net_realloc(NET *net, size_t length);
my_bool net_flush(NET *net);
-my_bool my_net_write(NET *net,const char *packet,unsigned long len);
+my_bool my_net_write(NET *net,const unsigned char *packet, size_t len);
my_bool net_write_command(NET *net,unsigned char command,
- const char *header, unsigned long head_len,
- const char *packet, unsigned long len);
-int net_real_write(NET *net,const char *packet,unsigned long len);
+ const unsigned char *header, size_t head_len,
+ const unsigned char *packet, size_t len);
+int net_real_write(NET *net,const unsigned char *packet, size_t len);
unsigned long my_net_read(NET *net);
+#ifdef _global_h
+void my_net_set_write_timeout(NET *net, uint timeout);
+void my_net_set_read_timeout(NET *net, uint timeout);
+#endif
+
/*
The following function is not meant for normal usage
Currently it's used internally by manager.c
@@ -312,7 +428,8 @@ struct rand_struct {
/* The following is for user defined functions */
-enum Item_result {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT};
+enum Item_result {STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT,
+ DECIMAL_RESULT};
typedef struct st_udf_args
{
@@ -321,18 +438,26 @@ typedef struct st_udf_args
char **args; /* Pointer to argument */
unsigned long *lengths; /* Length of string arguments */
char *maybe_null; /* Set to 1 for all maybe_null args */
+ char **attributes; /* Pointer to attribute name */
+ unsigned long *attribute_lengths; /* Length of attribute arguments */
+ void *extension;
} UDF_ARGS;
/* This holds information about the result */
typedef struct st_udf_init
{
- my_bool maybe_null; /* 1 if function can return NULL */
- unsigned int decimals; /* for real functions */
- unsigned long max_length; /* For string functions */
- char *ptr; /* free pointer for function data */
- my_bool const_item; /* 0 if result is independent of arguments */
+ my_bool maybe_null; /* 1 if function can return NULL */
+ unsigned int decimals; /* for real functions */
+ unsigned long max_length; /* For string functions */
+ char *ptr; /* free pointer for function data */
+ my_bool const_item; /* 1 if function always returns the same value */
+ void *extension;
} UDF_INIT;
+/*
+ TODO: add a notion for determinism of the UDF.
+ See Item_udf_func::update_used_tables ()
+*/
/* Constants when using compression */
#define NET_HEADER_SIZE 4 /* standard header size */
@@ -368,24 +493,22 @@ my_bool check_scramble(const char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
void make_password_from_salt(char *to, const unsigned char *hash_stage2);
+char *octet2hex(char *to, const char *str, unsigned int len);
/* end of password.c */
-char *get_tty_password(char *opt_message);
+char *get_tty_password(const char *opt_message);
const char *mysql_errno_to_sqlstate(unsigned int mysql_errno);
/* Some other useful functions */
-my_bool my_init(void);
-int load_defaults(const char *conf_file, const char **groups,
- int *argc, char ***argv);
my_bool my_thread_init(void);
void my_thread_end(void);
#ifdef _global_h
ulong STDCALL net_field_length(uchar **packet);
my_ulonglong net_field_length_ll(uchar **packet);
-char *net_store_length(char *pkg, ulonglong length);
+uchar *net_store_length(uchar *pkg, ulonglong length);
#endif
#ifdef __cplusplus
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_embed.h b/Frameworks/MCPKit/MySQL/include/mysql_embed.h
index 603af8e8..4a7fd3ef 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_embed.h
+++ b/Frameworks/MCPKit/MySQL/include/mysql_embed.h
@@ -2,8 +2,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,9 +21,7 @@
/* TODO HF add #undef HAVE_VIO if we don't want client in embedded library */
#undef HAVE_PSTACK /* No stacktrace */
-#undef HAVE_DLOPEN /* No udf functions */
#undef HAVE_OPENSSL
-#undef HAVE_ISAM
#undef HAVE_SMEM /* No shared memory */
#undef HAVE_NDBCLUSTER_DB /* No NDB cluster */
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_time.h b/Frameworks/MCPKit/MySQL/include/mysql_time.h
index 5f4fc12c..0a3f17a8 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_time.h
+++ b/Frameworks/MCPKit/MySQL/include/mysql_time.h
@@ -1,9 +1,8 @@
-/* Copyright (C) 2004 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_version.h b/Frameworks/MCPKit/MySQL/include/mysql_version.h
index 9f38c100..3f0a5073 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/mysql_version.h
+++ b/Frameworks/MCPKit/MySQL/include/mysql_version.h
@@ -9,12 +9,13 @@
#include <custom_conf.h>
#else
#define PROTOCOL_VERSION 10
-#define MYSQL_SERVER_VERSION "4.1.12"
-#define MYSQL_BASE_VERSION "mysqld-4.1"
+#define MYSQL_SERVER_VERSION "5.1.36"
+#define MYSQL_BASE_VERSION "mysqld-5.1"
#define MYSQL_SERVER_SUFFIX_DEF ""
#define FRM_VER 6
-#define MYSQL_VERSION_ID 40112
+#define MYSQL_VERSION_ID 50136
#define MYSQL_PORT 3306
+#define MYSQL_PORT_DEFAULT 0
#define MYSQL_UNIX_ADDR "/tmp/mysql.sock"
#define MYSQL_CONFIG_NAME "my"
#define MYSQL_COMPILATION_COMMENT "Source distribution"
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/typelib.h b/Frameworks/MCPKit/MySQL/include/typelib.h
index 4d6a90ad..46106d1b 100644
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/typelib.h
+++ b/Frameworks/MCPKit/MySQL/include/typelib.h
@@ -2,8 +2,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,6 +17,8 @@
#ifndef _typelib_h
#define _typelib_h
+#include "my_alloc.h"
+
typedef struct st_typelib { /* Different types saved here */
unsigned int count; /* How many types */
const char *name; /* Name of typelib */
@@ -25,9 +26,13 @@ typedef struct st_typelib { /* Different types saved here */
unsigned int *type_lengths;
} TYPELIB;
-extern int find_type(char *x,TYPELIB *typelib,unsigned int full_name);
+extern my_ulonglong find_typeset(char *x, TYPELIB *typelib,int *error_position);
+extern int find_type_or_exit(const char *x, TYPELIB *typelib,
+ const char *option);
+extern int find_type(char *x, const TYPELIB *typelib, unsigned int full_name);
extern void make_type(char *to,unsigned int nr,TYPELIB *typelib);
extern const char *get_type(TYPELIB *typelib,unsigned int nr);
+extern TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from);
extern TYPELIB sql_protocol_typelib;
diff --git a/Frameworks/MCPKit/MySQL/lib/libmysqlclient.a b/Frameworks/MCPKit/MySQL/lib/libmysqlclient.a
new file mode 100644
index 00000000..a7c3e213
--- /dev/null
+++ b/Frameworks/MCPKit/MySQL/lib/libmysqlclient.a
Binary files differ
diff --git a/Frameworks/MCPKit/MySQL/lib/libmysqlclient_r.a b/Frameworks/MCPKit/MySQL/lib/libmysqlclient_r.a
new file mode 100644
index 00000000..1cb1676d
--- /dev/null
+++ b/Frameworks/MCPKit/MySQL/lib/libmysqlclient_r.a
Binary files differ
diff --git a/Frameworks/MCPKit_bundled.framework/Headers b/Frameworks/MCPKit_bundled.framework/Headers
deleted file mode 120000
index fc757d7c..00000000
--- a/Frameworks/MCPKit_bundled.framework/Headers
+++ /dev/null
@@ -1 +0,0 @@
-Versions/Current/Headers/ \ No newline at end of file
diff --git a/Frameworks/MCPKit_bundled.framework/MCPKit_bundled b/Frameworks/MCPKit_bundled.framework/MCPKit_bundled
deleted file mode 120000
index 88bf2d87..00000000
--- a/Frameworks/MCPKit_bundled.framework/MCPKit_bundled
+++ /dev/null
@@ -1 +0,0 @@
-Versions/Current/MCPKit_bundled \ No newline at end of file
diff --git a/Frameworks/MCPKit_bundled.framework/PrivateHeaders b/Frameworks/MCPKit_bundled.framework/PrivateHeaders
deleted file mode 120000
index 834d4c04..00000000
--- a/Frameworks/MCPKit_bundled.framework/PrivateHeaders
+++ /dev/null
@@ -1 +0,0 @@
-Versions/Current/PrivateHeaders/ \ No newline at end of file
diff --git a/Frameworks/MCPKit_bundled.framework/Resources b/Frameworks/MCPKit_bundled.framework/Resources
deleted file mode 120000
index 089faccc..00000000
--- a/Frameworks/MCPKit_bundled.framework/Resources
+++ /dev/null
@@ -1 +0,0 @@
-Versions/Current/Resources/ \ No newline at end of file
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPClassDescription+MCPEntreprise.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPClassDescription+MCPEntreprise.h
deleted file mode 100644
index a41a4617..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPClassDescription+MCPEntreprise.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// MCPClassDescription+MCPEntreprise.h
-// MCPModeler
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on 01/11/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-
-#import <Foundation/Foundation.h>
-#import "MCPClassDescription.h"
-
-@interface MCPClassDescription (MCPEntreprise)
-
-#pragma mark Pseudo getters (for NSClassDescription overload)
-- (NSArray *) attributeKeys;
-- (NSString *) inverseRelationshipKey:(NSString *) relationshipKey;
-- (NSArray *) toManyRelationshipKeys;
-- (NSArray *) toOneRelationshipKeys;
-
-#pragma mark Specifics for MCPObject
-- (NSArray *) primaryKeyAttributes;
-- (NSArray *) identityAttributes;
-- (MCPAttribute *) attributeWithName: (NSString *) iName;
-- (MCPRelation *) relationWithName:(NSString *) iRelationName;
-- (BOOL) singleIntAutoGenKey;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConnection.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConnection.h
deleted file mode 100644
index 5b2f2eaf..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConnection.h
+++ /dev/null
@@ -1,158 +0,0 @@
-//
-// MCPConnection.h
-// SMySQL
-//
-// Created by serge cohen (serge.cohen@m4x.org) on Sat Dec 08 2001.
-// Copyright (c) 2001 Serge Cohen.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-// $Id: MCPConnection.h 335 2006-01-08 21:14:07Z serge $
-// $Author: serge $
-
-
-#import <Foundation/Foundation.h>
-#import "mysql.h"
-#import "MCPConstants.h"
-
-
-@class MCPResult;
-
-// Deafult connection option
-extern const unsigned int kMCPConnectionDefaultOption;
-
-// Default socket (from the mysql.h used at compile time)
-extern const char *kMCPConnectionDefaultSocket;
-
-// Added to mysql error code
-extern const unsigned int kMCPConnectionNotInited;
-
-// The length of the truncation if required:
-extern const unsigned int kLengthOfTruncationForLog;
-
-@interface MCPConnection : NSObject {
-@protected
- MYSQL *mConnection; /*"The inited MySQL connection."*/
- BOOL mConnected; /*"Reflect the fact that the connection is already in place or not."*/
- NSStringEncoding mEncoding; /*"The encoding used by MySQL server, to ISO-1 default."*/
- NSTimeZone *mTimeZone; /*"The time zone of the session."*/
- unsigned int mConnectionFlags; /*"The flags to be used for the connection to the database."*/
-}
-/*"
-Getting default of MySQL
-"*/
-+ (NSDictionary *) getMySQLLocales;
-+ (NSStringEncoding) encodingForMySQLEncoding:(const char *) mysqlEncoding;
-+ (NSStringEncoding) defaultMySQLEncoding;
-
-/*"
-Class maintenance
-"*/
-+ (void) initialize;
-+ (void) setLogQueries:(BOOL) iLogFlag;
-+ (void) setTruncateLongFieldInLogs:(BOOL) iTruncFlag;
-+ (BOOL) truncateLongField;
-
-/*"
-Initialisation
-"*/
-- (id) init;
-// Port to 0 to use the default port
-- (id) initToHost:(NSString *) host withLogin:(NSString *) login password:(NSString *) pass usingPort:(int) port;
-- (id) initToSocket:(NSString *) socket withLogin:(NSString *) login password:(NSString *) pass;
-
-- (BOOL) setConnectionOption:(int) option toValue:(BOOL) value;
-// Port to 0 to use the default port
-- (BOOL) connectWithLogin:(NSString *) login password:(NSString *) pass host:(NSString *) host port:(int) port socket:(NSString *) socket;
-
-- (BOOL) selectDB:(NSString *) dbName;
-
-/*"
-Errors information
-"*/
-
-- (NSString *) getLastErrorMessage;
-- (unsigned int) getLastErrorID;
-- (BOOL) isConnected;
-- (BOOL) checkConnection;
-
-/*"
-Queries
-"*/
-
-- (NSString *) prepareBinaryData:(NSData *) theData;
-- (NSString *) prepareString:(NSString *) theString;
-- (NSString *) quoteObject:(id) theObject;
-
-- (MCPResult *) queryString:(NSString *) query;
-
-- (my_ulonglong) affectedRows;
-- (my_ulonglong) insertId;
-
-
-/*"
-Getting description of the database structure
-"*/
-- (MCPResult *) listDBs;
-- (MCPResult *) listDBsLike:(NSString *) dbsName;
-- (MCPResult *) listTables;
-- (MCPResult *) listTablesLike:(NSString *) tablesName;
-// Next method uses SHOW TABLES FROM db to be sure that the db is not changed during this call.
-- (MCPResult *) listTablesFromDB:(NSString *) dbName like:(NSString *) tablesName;
-- (MCPResult *) listFieldsFromTable:(NSString *) tableName;
-- (MCPResult *) listFieldsFromTable:(NSString *) tableName like:(NSString *) fieldsName;
-
-
-/*"
-Server information and control
-"*/
-
-- (NSString *) clientInfo;
-- (NSString *) hostInfo;
-- (NSString *) serverInfo;
-- (NSNumber *) protoInfo;
-- (MCPResult *) listProcesses;
-- (BOOL) killProcess:(unsigned long) pid;
-
-//- (BOOL)createDBWithName:(NSString *)dbName;
-//- (BOOL)dropDBWithName:(NSString *)dbName;
-
-/*"
-Disconnection
-"*/
-- (void) disconnect;
-- (void) dealloc;
-
-/*"
-String encoding concerns (C string type to NSString).
-It's unlikely that users of the framework needs to use these methods which are used internally
-"*/
-- (void) setEncoding:(NSStringEncoding) theEncoding;
-- (NSStringEncoding) encoding;
-
-- (const char *) cStringFromString:(NSString *) theString;
-- (NSString *) stringWithCString:(const char *) theCString;
-
-/*"
-Text data convertion to string
-"*/
-- (NSString *) stringWithText:(NSData *) theTextData;
-
-/*" Time Zone handling ."*/
-- (void) setTimeZone:(NSTimeZone *) iTimeZone;
-- (NSTimeZone *) timeZone;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConnectionWinCont.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConnectionWinCont.h
deleted file mode 100644
index 98195e9f..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConnectionWinCont.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// MCPConnectionWinCont.h
-// Vacations
-//
-// Created by Serge Cohen on Mon May 26 2003.
-// Copyright (c) 2003 ARP/wARP. All rights reserved.
-//
-
-#import <AppKit/AppKit.h>
-
-// External classes, forward reference.
-@class MCPDocument;
-
-
-@interface MCPConnectionWinCont : NSWindowController
-{
- IBOutlet NSTextField *mHostField;
- IBOutlet NSTextField *mLoginField;
- IBOutlet NSTextField *mDatabaseField;
- IBOutlet NSTextField *mPortField;
-
- IBOutlet NSPanel *mPasswordSheet;
- IBOutlet NSTextField *mPasswordField;
-
- IBOutlet NSButton *mCreateButton;
-// MCPDocument *mMCPDocument;
-}
-
-
-/*" Actions for Interface Builder "*/
-/*" For the clear text information. "*/
-- (IBAction) doGo:(id) sender;
-- (IBAction) doCancel:(id) sender;
-- (IBAction) doCreate:(id) sender;
-- (IBAction) modifyInstance:(id) sender;
-
-
-/*" For the password. "*/
-- (IBAction) passwordClick:(id) sender;
-- (IBAction) askPassword:(id) sender;
-- (NSString *) Password;
-
-
-/*" Overrides of NSWindowController method, to adapt to this Window Controller. "*/
-- (id) init;
-- (void) dealloc;
-- (void) windowDidLoad;
-
-/*" Getting the button for creating a DB. "*/
-- (NSButton*) getCreateButton;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConstants.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConstants.h
deleted file mode 100644
index cccdfe8c..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPConstants.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// MCPConstants.h
-// SMySQL
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on Mon Jun 03 2002.
-// Copyright (c) 2001 Serge Cohen.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-// $Id: MCPConstants.h 335 2006-01-08 21:14:07Z serge $
-// $Author: serge $
-
-
-typedef enum {
- MCPTypeArray = 1,
- MCPTypeDictionary = 2,
- MCPTypeFlippedArray = 3,
- MCPTypeFlippedDictionary = 4
-} MCPReturnType;
-
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPDocument.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPDocument.h
deleted file mode 100644
index 28f375da..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPDocument.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//
-// MCPDocument.h
-// Vacations
-//
-// Created by Serge Cohen on Sat May 24 2003.
-// Copyright (c) 2003 ARP/wARP. All rights reserved.
-//
-
-
-#import <Cocoa/Cocoa.h>
-
-// External classes, forward reference.
-@class MCPConnection;
-@class MCPResult;
-
-
-@interface MCPDocument : NSDocument
-{
- BOOL MCPConInfoNeeded, MCPPassNeeded;
- NSString *MCPHost, *MCPLogin, *MCPDatabase;
- unsigned int MCPPort;
- MCPConnection *MCPConnect;
-
-// Handling of windows.
- NSWindowController *MCPMainWinCont;
- Class MCPConnectedWinCont; /*" Window controller used once the connection is established (As a class). "*/
-// Handling the DB creation state.
- NSString *MCPModelName;
- BOOL MCPWillCreateNewDB;
-}
-
-/*" Class Maintenance "*/
-+ (void) initialize;
-
-// Standards
-/*" Initialisation and deallocation "*/
-- (id) init;
-- (void) dealloc;
-
-/*" Connection to the databse related "*/
-- (MCPResult *) MCPqueryString:(NSString *) query;
-- (unsigned int) MCPinsertRow:(NSString *) insert;
-- (MCPConnection *) MCPgetConnection;
-
-// Accessors
-/*" Accessors to the parameters of the connection "*/
-- (void) setMCPHost:(NSString *) theHost;
-- (void) setMCPLogin:(NSString *) theLogin;
-- (void) setMCPDatabase:(NSString *) theDatabase;
-- (void) setMCPPort:(unsigned int) thePort;
-- (void) setMCPConInfoNeeded:(BOOL) theConInfoNeeded;
-
-- (NSString *) MCPHost;
-- (NSString *) MCPLogin;
-- (NSString *) MCPDatabase;
-- (unsigned int) MCPPort;
-- (BOOL) MCPConInfoNeeded;
-- (BOOL) MCPPassNeeded;
-
-- (BOOL) MCPisConnected;
-- (MCPConnection *) MCPConnect;
-
-/*" Accessor to the window generated once the connection is established "*/
-- (void) setMCPConnectedWinCont:(Class) theConnectedWinCont;
-
-- (Class) MCPConnectedWinCont;
-
-/*" Accessors to the main window (connection or connected window), through their window controller. "*/
-- (NSWindowController *) MCPMainWinCont;
-
-/*" Accessors to the DB creation instances. "*/
-- (void) setMCPModelName:(NSString *) theModelName;
-- (void) setMCPWillCreateNewDB:(BOOL) theWillCreateNewDB;
-
-- (NSString *) MCPModelName;
-- (BOOL) MCPWillCreateNewDB;
-
-/*" Practical creation of the database, from a model file. "*/
-- (BOOL) createModelDB;
-
-/*" Overrides of NSDocument methods. "*/
-// Managing the document in file format
-- (NSData *) dataRepresentationOfType:(NSString *) aType;
-- (BOOL)loadDataRepresentation:(NSData *) data ofType:(NSString *)aType;
-
-// Managing NSWindowController(s)
-- (NSArray *) makeWindowControllers;
-- (void) windowControllerDidLoadNib:(NSWindowController *) aController;
-
-/*" Method to take care of the password sheet. "*/
-// Callback from sheet
-- (void) MCPPasswordSheetDidEnd:(NSWindow *) sheet returnCode:(int) returnCode contextInfo:(void *) contextInfo;
-
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPEntrepriseNotifications.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPEntrepriseNotifications.h
deleted file mode 100644
index 824051e6..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPEntrepriseNotifications.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// MCPEntrepriseNotifications.h
-// MCPModeler
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-
-
-#import <Foundation/Foundation.h>
-
-// The instance are defined in MMDocument.h
-
-#pragma mark Name for notification
-
-extern NSString *MCPModelChangedNotification;
-extern NSString *MCPClassDescriptionChangedNotification;
-extern NSString *MCPAttributeChangedNotification;
-extern NSString *MCPRelationChangedNotification;
-
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPFastQueries.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPFastQueries.h
deleted file mode 100644
index cea22a11..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPFastQueries.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-// MCPFastQueries.h
-// SMySQL
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on Mon Jun 03 2002.
-// Copyright (c) 2001 Serge Cohen.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-// $Id: MCPFastQueries.h 334 2006-01-08 20:32:38Z serge $
-// $Author: serge $
-
-#import <Foundation/Foundation.h>
-
-#import "MCPConnection.h"
-
-@interface MCPConnection (MCPFastQueries)
-/*"
-For insert queries, get directly the Id of the newly inserted row
-"*/
-- (my_ulonglong) insertQuery:(NSString *) aQuery;
-- (my_ulonglong) updateQuery:(NSString *) aQuery;
-
-
-/*"
-Returns directly a proper NS object, or a collection (NSArray, NSDictionary...).
-"*/
-- (id) getFirstFieldFromQuery:(NSString *) aQuery;
-- (id) getFirstRowFromQuery:(NSString *) aQuery asType:(MCPReturnType) aType;
-- (id) getAllRowsFromQuery:(NSString *) aQuery asType:(MCPReturnType) aType;
-- (NSArray *) getQuery:(NSString *) aQuery colWithIndex:(unsigned int) aCol;
-- (NSArray *) getQuery:(NSString *) aQuery colWithName:(NSString *) aColName;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPJoin.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPJoin.h
deleted file mode 100644
index 4784a30b..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPJoin.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//
-// MCPJoin.h
-// MCPModeler
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on 18/08/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-
-#import <Foundation/Foundation.h>
-
-@class MCPModel;
-@class MCPClassDescription;
-@class MCPAttribute;
-@class MCPRelation;
-@class MCPRelation;
-
-@interface MCPJoin : NSObject < NSCoding > {
-@protected
-// Note that NONE of these attributes are retained!!!
-// Instead all these objects are notified of the existence of the join
-// and are responsible to invalidate/delete it if necessary.
- MCPRelation *relation;
- MCPAttribute *origin;
- MCPAttribute *destination;
-}
-
-#pragma mark Class methods
-+ (void) initialize;
-
-#pragma mark Life cycle
-- (id) initForRelation:(MCPRelation *) iRelation from:(MCPAttribute *) iOrigin to:(MCPAttribute *) iDestination;
-- (void) invalidate;
-- (void) dealloc;
-
-#pragma mark NSCoding protocol
-- (id) initWithCoder:(NSCoder *) decoder;
-- (void) encodeWithCoder:(NSCoder *) encoder;
-
-#pragma mark Setters
-// No setter for relation : should be set at init time!
-- (void) setOrigin:(MCPAttribute *) iOrigin;
-- (void) setDestination:(MCPAttribute *) iDestination;
-
-#pragma mark Getters
-- (MCPRelation *) relation;
-- (MCPAttribute *) origin;
-- (MCPAttribute *) destination;
-- (unsigned int) index;
-
-#pragma mark Some general methods:
-- (BOOL) isEqual:(id) iObject;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPKit_bundled.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPKit_bundled.h
deleted file mode 100644
index 3242a9dd..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPKit_bundled.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * MCPKit_bundled.h
- * MCPKit
- *
- * Created by serge cohen (serge.cohen@m4x.org) on Sat Dec 08 2001.
- * Copyright (c) 2001 Serge Cohen.
- *
- * This code is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or any later version.
- *
- * This code 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 General Public License for more
- * details.
- *
- * For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
- * write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * More info at <http://mysql-cocoa.sourceforge.net/>
- *
- *
- * $Id: MCPKit_bundled.h 335 2006-01-08 21:14:07Z serge $
- * $Author: serge $
- */
-
-#import <Foundation/Foundation.h>
-
-#import <MCPKit_bundled/MCPConstants.h>
-#import <MCPKit_bundled/MCPNull.h>
-#import <MCPKit_bundled/MCPResult.h>
-#import <MCPKit_bundled/MCPConnection.h>
-#import <MCPKit_bundled/MCPNumber.h>
-#import <MCPKit_bundled/MCPResultPlus.h>
-#import <MCPKit_bundled/MCPFastQueries.h>
-#import "mysql.h"
-//#import <SMySQL/mysql.h>
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPModel+MCPEntreprise.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPModel+MCPEntreprise.h
deleted file mode 100644
index 069c9862..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPModel+MCPEntreprise.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// MCPModel+MCPEntreprise.h
-// MCPModeler
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on 01/11/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-
-#import "MCPModel.h"
-
-@interface MCPModel (MCPEntreprise)
-
-#pragma mark Work as a class description server
-- (void) registerAsClassDescriptionServer;
-- (void) registerDescriptionForClass:(NSNotification *) notification;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPNull.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPNull.h
deleted file mode 100644
index 1fa0babd..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPNull.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// MCPNull.h
-// SMySQL
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on Sun Jun 02 2002.
-// Copyright (c) 2001 Serge Cohen.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-// $Id: MCPNull.h 334 2006-01-08 20:32:38Z serge $
-// $Author: serge $
-
-#import <Foundation/Foundation.h>
-
-
-@interface NSObject (MCPNSNullTest)
-
-/*"
-Addin to NSObject.
-"*/
-- (BOOL) isNSNull;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPNumber.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPNumber.h
deleted file mode 100644
index f4851e2a..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPNumber.h
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// MCPNumber.h
-// NumberTest
-//
-// Created by serge cohen (serge.cohen@m4x.org) on Sat Dec 08 2001.
-// Copyright (c) 2001 Serge Cohen.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-// $Id: MCPNumber.h 334 2006-01-08 20:32:38Z serge $
-// $Author: serge $
-
-#import <Foundation/Foundation.h>
-
-
-@interface MCPNumber : NSNumber {
- const char *typeCode;
- NSNumber *number;
-}
-
-- (id) initWithChar:(char) value;
-- (id) initWithUnsignedChar:(unsigned char) value;
-- (id) initWithShort:(short) value;
-- (id) initWithUnsignedShort:(unsigned short) value;
-- (id) initWithInt:(int) value;
-- (id) initWithUnsignedInt:(unsigned int) value;
-- (id) initWithLong:(long) value;
-- (id) initWithUnsignedLong:(unsigned long) value;
-- (id) initWithLongLong:(long long) value;
-- (id) initWithUnsignedLongLong:(unsigned long long) value;
-- (id) initWithFloat:(float) value;
-- (id) initWithDouble:(double) value;
-- (id) initWithBool:(BOOL) value;
-
-+ (MCPNumber *) numberWithChar:(char) value;
-+ (MCPNumber *) numberWithUnsignedChar:(unsigned char) value;
-+ (MCPNumber *) numberWithShort:(short) value;
-+ (MCPNumber *) numberWithUnsignedShort:(unsigned short) value;
-+ (MCPNumber *) numberWithInt:(int) value;
-+ (MCPNumber *) numberWithUnsignedInt:(unsigned int) value;
-+ (MCPNumber *) numberWithLong:(long) value;
-+ (MCPNumber *) numberWithUnsignedLong:(unsigned long) value;
-+ (MCPNumber *) numberWithLongLong:(long long) value;
-+ (MCPNumber *) numberWithUnsignedLongLong:(unsigned long long) value;
-+ (MCPNumber *) numberWithFloat:(float) value;
-+ (MCPNumber *) numberWithDouble:(double) value;
-+ (MCPNumber *) numberWithBool:(BOOL) value;
-
-- (void) dealloc;
-
-/*" Most important : NSNumber primitive methods: "*/
-- (const char *) objCType;
-- (void) getValue:(void *) buffer;
-
-//- (NSString *) descriptionWithLocale:(NSDictionary *) aLocale; // Not Primitive, but buggy...
-
-- (char) charValue;
-- (unsigned char) unsignedCharValue;
-- (short) shortValue;
-- (unsigned short) unsignedShortValue;
-- (int) intValue;
-- (unsigned int) unsignedIntValue;
-- (long) longValue;
-- (unsigned long) unsignedLongValue;
-- (long long) longLongValue;
-- (unsigned long long) unsignedLongLongValue;
-- (float) floatValue;
-- (double) doubleValue;
-- (BOOL) boolValue;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPResult.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPResult.h
deleted file mode 100644
index 91b69fb5..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPResult.h
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// MCPResult.h
-// SMySQL
-//
-// Created by serge cohen (serge.cohen@m4x.org) on Sat Dec 08 2001.
-// Copyright (c) 2001 Serge Cohen.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-// $Id: MCPResult.h 335 2006-01-08 21:14:07Z serge $
-// $Author: serge $
-
-
-#import <Foundation/Foundation.h>
-#import "mysql.h"
-#import "MCPConstants.h"
-
-
-@interface MCPResult : NSObject {
-@protected
- MYSQL_RES *mResult; /*" The MYSQL_RES structure of the C API. "*/
- NSArray *mNames; /*" An NSArray holding the name of the columns. "*/
- NSDictionary *mMySQLLocales; /*" A Locales dictionary to define the locales of MySQL. "*/
- NSStringEncoding mEncoding; /*" The encoding used by MySQL server, to ISO-1 default. "*/
- unsigned int mNumOfFields; /*" The number of fields in the result. "*/
- NSTimeZone *mTimeZone; /*" The time zone of the connection when the query was made. "*/
-}
-/*"
-Class maintenance
- "*/
-
-+ (void) initialize;
-
- /*"
- Init used #{only} by #{MCPConnection}
- "*/
-
-- (id) initWithMySQLPtr:(MYSQL *) mySQLPtr encoding:(NSStringEncoding) theEncoding timeZone:(NSTimeZone *) iTimeZone;
-- (id) initWithResPtr:(MYSQL_RES *) mySQLResPtr encoding:(NSStringEncoding) theEncoding timeZone:(NSTimeZone *) iTimeZone;
-- (id) init;
-
- /*"
- General info on the result
- "*/
-
-- (my_ulonglong) numOfRows;
-- (unsigned int) numOfFields;
-
- /*"
- Getting the rows
- "*/
-
-- (void) dataSeek:(my_ulonglong) row;
-
-- (id) fetchRowAsType:(MCPReturnType) aType;
-- (NSArray *) fetchRowAsArray;
-- (NSDictionary *) fetchRowAsDictionary;
-
- /*"
- Getting information on columns
- "*/
-
-- (NSArray *) fetchFieldNames;
-
-- (id) fetchTypesAsType:(MCPReturnType) aType;
-- (NSArray *) fetchTypesAsArray;
-- (NSDictionary *) fetchTypesAsDictionary;
-
-- (unsigned int) fetchFlagsAtIndex:(unsigned int) index;
-- (unsigned int) fetchFlagsForKey:(NSString *) key;
-
-- (BOOL) isBlobAtIndex:(unsigned int) index;
-- (BOOL) isBlobForKey:(NSString *) key;
-
- /*"
- Text data convertion to string
- "*/
-- (NSString *) stringWithText:(NSData *) theTextData;
-
- /*"
- Utility method
- "*/
-- (NSString *) description;
-
- /*"
- End of the scope...
- "*/
-
-- (void) dealloc;
-
- /*"
- Private methods, internal use only
- "*/
-- (const char *) cStringFromString:(NSString *) theString;
-- (NSString *) stringWithCString:(const char *) theCString;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPResultPlus.h b/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPResultPlus.h
deleted file mode 100644
index 28d6ff2f..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Headers/MCPResultPlus.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// MCPResultPlus.h
-// SMySQL
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on Mon Jun 03 2002.
-// Copyright (c) 2001 Serge Cohen.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-// $Id: MCPResultPlus.h 334 2006-01-08 20:32:38Z serge $
-// $Author: serge $
-
-#import <Foundation/Foundation.h>
-
-#import "MCPResult.h"
-
-@interface MCPResult (MCPResultPlus)
-
-/*"
-Getting a complete column as an array
-"*/
-- (NSArray *) fetchColAtIndex:(unsigned int) aCol;
-- (NSArray *) fetchColWithName:(NSString *) aColName;
-
-/*"
-Getting the complete result as 2D array
-"*/
-- (id) fetch2DResultAsType:(MCPReturnType) aType;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/MCPKit_bundled b/Frameworks/MCPKit_bundled.framework/Versions/A/MCPKit_bundled
deleted file mode 100755
index 160ce713..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/MCPKit_bundled
+++ /dev/null
Binary files differ
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPAttribute+Private.h b/Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPAttribute+Private.h
deleted file mode 100644
index 2426b16a..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPAttribute+Private.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// MCPAttribute+Private.h
-// MCPModeler
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-
-#import "MCPAttribute.h"
-
-@interface MCPAttribute (Private)
-
-
-#pragma mark Setters
-- (void) setValueClassName:(NSString *) iClassName;
-
-#pragma mark Pseudo-getters
-
-@end
-
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPClassDescription+Private.h b/Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPClassDescription+Private.h
deleted file mode 100644
index fa4ffab3..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPClassDescription+Private.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// MCPClassDescription+Private.h
-// MCPModeler
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on 09/08/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-
-
-#import "MCPClassDescription.h"
-
-@interface MCPClassDescription (Private)
-
-#pragma mark Setters
-- (void) setAttributes:(NSArray *) iAttributes;
-- (void) setRelations:(NSArray *) iRelations;
-- (void) insertObject:(MCPRelation *) iRelation inIncomingsAtIndex:(unsigned int) index;
-- (void) removeObjectFromIncomingsAtIndex:(unsigned int) index;
-
-#pragma mark Getters
-- (NSArray *) incomings;
-- (unsigned int) countOfIncomings;
-- (MCPRelation *) objectInIncomingsAtIndex:(unsigned int) index;
-- (unsigned int) indexOfIncoming:(id) iRelation;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPRelation+Private.h b/Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPRelation+Private.h
deleted file mode 100644
index aa286787..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/PrivateHeaders/MCPRelation+Private.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// MCPRelation+Private.h
-// MCPModeler
-//
-// Created by Serge Cohen (serge.cohen@m4x.org) on 11/08/04.
-// Copyright 2004 Serge Cohen. All rights reserved.
-//
-// This code is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 of the License, or any later version.
-//
-// This code 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 General Public License for more
-// details.
-//
-// For a copy of the GNU General Public License, visit <http://www.gnu.org/> or
-// write to the Free Software Foundation, Inc., 59 Temple Place--Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// More info at <http://mysql-cocoa.sourceforge.net/>
-//
-
-#import "MCPRelation.h"
-
-@interface MCPRelation (Private)
-
-#pragma mark Making some work
-- (void) invalidateJoins; // Check that the joins are realistics.
-
-#pragma mark Setters
-- (void) setOrigin:(MCPClassDescription *) iOrigin;
-//- (void) setJoins:(NSArray *) iJoins;
-
-#pragma mark Getters
-- (MCPModel *) model;
-
-#pragma mark Fro the controller layer and the UI
-- (void) addNewDefaultJoin;
-
-@end
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/InfoPlist.strings b/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/InfoPlist.strings
deleted file mode 100644
index 8177d470..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/InfoPlist.strings
+++ /dev/null
Binary files differ
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/JavaCompiling.plist b/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/JavaCompiling.plist
deleted file mode 100644
index e0a16f9b..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/JavaCompiling.plist
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>JavaSourceSubpath</key>
- <string>_MCPConnectionWindow_EOArchive_English.java</string>
-</dict>
-</plist>
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/_MCPConnectionWindow_EOArchive_English.java b/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/_MCPConnectionWindow_EOArchive_English.java
deleted file mode 100644
index 5ba619a6..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/_MCPConnectionWindow_EOArchive_English.java
+++ /dev/null
@@ -1,424 +0,0 @@
-// _MCPConnectionWindow_EOArchive_English.java
-// Generated by EnterpriseObjects palette at vendredi 14 mai 2004 11 h 08 Europe/Amsterdam
-
-import com.webobjects.eoapplication.*;
-import com.webobjects.eocontrol.*;
-import com.webobjects.eointerface.*;
-import com.webobjects.eointerface.swing.*;
-import com.webobjects.foundation.*;
-import java.awt.*;
-import javax.swing.*;
-import javax.swing.border.*;
-import javax.swing.table.*;
-import javax.swing.text.*;
-
-public class _MCPConnectionWindow_EOArchive_English extends com.webobjects.eoapplication.EOArchive {
- IBHelpConnector _iBHelpConnector0, _iBHelpConnector1, _iBHelpConnector2, _iBHelpConnector3;
- com.webobjects.eointerface.swing.EOFrame _eoFrame0, _eoFrame1;
- com.webobjects.eointerface.swing.EOTextField _nsTextField0, _nsTextField1, _nsTextField2, _nsTextField3, _nsTextField4, _nsTextField5, _nsTextField6, _nsTextField7, _nsTextField8, _nsTextField9;
- com.webobjects.eointerface.swing.EOView _nsBox0, _nsBox1, _nsBox2, _nsBox3;
- javax.swing.JButton _nsButton0, _nsButton1, _nsButton2, _nsButton3, _nsButton4;
- javax.swing.JPanel _nsView0, _nsView1;
- javax.swing.JPasswordField _nsSecureTextField0;
-
- public _MCPConnectionWindow_EOArchive_English(Object owner, NSDisposableRegistry registry) {
- super(owner, registry);
- }
-
- protected void _construct() {
- Object owner = _owner();
- EOArchive._ObjectInstantiationDelegate delegate = (owner instanceof EOArchive._ObjectInstantiationDelegate) ? (EOArchive._ObjectInstantiationDelegate)owner : null;
- Object replacement;
-
- super._construct();
-
- _nsBox3 = (com.webobjects.eointerface.swing.EOView)_registered(new com.webobjects.eointerface.swing.EOView(), "NSView");
- _nsBox2 = (com.webobjects.eointerface.swing.EOView)_registered(new com.webobjects.eointerface.swing.EOView(), "NSBox1");
-
- if ((delegate != null) && ((replacement = delegate.objectForOutletPath(this, "mCreateButton")) != null)) {
- _nsButton4 = (replacement == EOArchive._ObjectInstantiationDelegate.NullObject) ? null : (javax.swing.JButton)replacement;
- _replacedObjects.setObjectForKey(replacement, "_nsButton4");
- } else {
- _nsButton4 = (javax.swing.JButton)_registered(new javax.swing.JButton("Create DB"), "NSButton2");
- }
-
- _nsButton3 = (javax.swing.JButton)_registered(new javax.swing.JButton("Cancel"), "NSButton1");
- _nsButton2 = (javax.swing.JButton)_registered(new javax.swing.JButton("Go"), "NSButton");
- _nsBox1 = (com.webobjects.eointerface.swing.EOView)_registered(new com.webobjects.eointerface.swing.EOView(), "NSView");
- _nsBox0 = (com.webobjects.eointerface.swing.EOView)_registered(new com.webobjects.eointerface.swing.EOView(), "NSBox1");
- _nsTextField9 = (com.webobjects.eointerface.swing.EOTextField)_registered(new com.webobjects.eointerface.swing.EOTextField(), "NSTextField23");
- _nsTextField8 = (com.webobjects.eointerface.swing.EOTextField)_registered(new com.webobjects.eointerface.swing.EOTextField(), "NSTextField22");
- _nsTextField7 = (com.webobjects.eointerface.swing.EOTextField)_registered(new com.webobjects.eointerface.swing.EOTextField(), "NSTextField21");
- _nsTextField6 = (com.webobjects.eointerface.swing.EOTextField)_registered(new com.webobjects.eointerface.swing.EOTextField(), "NSTextField2");
-
- if ((delegate != null) && ((replacement = delegate.objectForOutletPath(this, "window")) != null)) {
- _eoFrame1 = (replacement == EOArchive._ObjectInstantiationDelegate.NullObject) ? null : (com.webobjects.eointerface.swing.EOFrame)replacement;
- _replacedObjects.setObjectForKey(replacement, "_eoFrame1");
- } else {
- _eoFrame1 = (com.webobjects.eointerface.swing.EOFrame)_registered(new com.webobjects.eointerface.swing.EOFrame(), "Window");
- }
-
- _nsView1 = (JPanel)_eoFrame1.getContentPane();
- _iBHelpConnector3 = (IBHelpConnector)_registered(new IBHelpConnector(), "");
- _iBHelpConnector2 = (IBHelpConnector)_registered(new IBHelpConnector(), "");
- _iBHelpConnector1 = (IBHelpConnector)_registered(new IBHelpConnector(), "");
- _iBHelpConnector0 = (IBHelpConnector)_registered(new IBHelpConnector(), "");
-
- if ((delegate != null) && ((replacement = delegate.objectForOutletPath(this, "mHostField.nextFocusableComponent.nextFocusableComponent.nextFocusableComponent")) != null)) {
- _nsTextField5 = (replacement == EOArchive._ObjectInstantiationDelegate.NullObject) ? null : (com.webobjects.eointerface.swing.EOTextField)replacement;
- _replacedObjects.setObjectForKey(replacement, "_nsTextField5");
- } else {
- _nsTextField5 = (com.webobjects.eointerface.swing.EOTextField)_registered(new com.webobjects.eointerface.swing.EOTextField(), "NSTextField12");
- }
-
- if ((delegate != null) && ((replacement = delegate.objectForOutletPath(this, "mHostField.nextFocusableComponent.nextFocusableComponent")) != null)) {
- _nsTextField4 = (replacement == EOArchive._ObjectInstantiationDelegate.NullObject) ? null : (com.webobjects.eointerface.swing.EOTextField)replacement;
- _replacedObjects.setObjectForKey(replacement, "_nsTextField4");
- } else {
- _nsTextField4 = (com.webobjects.eointerface.swing.EOTextField)_registered(new com.webobjects.eointerface.swing.EOTextField(), "NSTextField11");
- }
-
- if ((delegate != null) && ((replacement = delegate.objectForOutletPath(this, "mHostField.nextFocusableComponent")) != null)) {
- _nsTextField3 = (replacement == EOArchive._ObjectInstantiationDelegate.NullObject) ? null : (com.webobjects.eointerface.swing.EOTextField)replacement;
- _replacedObjects.setObjectForKey(replacement, "_nsTextField3");
- } else {
- _nsTextField3 = (com.webobjects.eointerface.swing.EOTextField)_registered(new com.webobjects.eointerface.swing.EOTextField(), "NSTextField1");
- }
-
- if ((delegate != null) && ((replacement = delegate.objectForOutletPath(this, "mHostField.nextFocusableComponent.nextFocusableComponent.nextFocusableComponent.nextFocusableComponent")) != null)) {
- _nsTextField2 = (replacement == EOArchive._ObjectInstantiationDelegate.NullObject) ? null : (com.webobjects.eointerface.swing.EOTextField)replacement;
- _replacedObjects.setObjectForKey(replacement, "_nsTextField2");
- } else {
- _nsTextField2 = (com.webobjects.eointerface.swing.EOTextField)_registered(new com.webobjects.eointerface.swing.EOTextField(), "NSTextField");
- }
-
- _nsButton1 = (javax.swing.JButton)_registered(new javax.swing.JButton("Cancel"), "NSButton1");
-
- if ((delegate != null) && ((replacement = delegate.objectForOutletPath(this, "mPasswordField.nextFocusableComponent")) != null)) {
- _nsButton0 = (replacement == EOArchive._ObjectInstantiationDelegate.NullObject) ? null : (javax.swing.JButton)replacement;
- _replacedObjects.setObjectForKey(replacement, "_nsButton0");
- } else {
- _nsButton0 = (javax.swing.JButton)_registered(new javax.swing.JButton("OK"), "NSButton");
- }
-
- if ((delegate != null) && ((replacement = delegate.objectForOutletPath(this, "mPasswordField")) != null)) {
- _nsSecureTextField0 = (replacement == EOArchive._ObjectInstantiationDelegate.NullObject) ? null : (javax.swing.JPasswordField)replacement;
- _replacedObjects.setObjectForKey(replacement, "_nsSecureTextField0");
- } else {
- _nsSecureTextField0 = (javax.swing.JPasswordField)_registered(new javax.swing.JPasswordField(), "NSTextField");
- }
-
- _nsTextField1 = (com.webobjects.eointerface.swing.EOTextField)_registered(new com.webobjects.eointerface.swing.EOTextField(), "NSTextField21");
- _nsTextField0 = (com.webobjects.eointerface.swing.EOTextField)_registered(new com.webobjects.eointerface.swing.EOTextField(), "NSTextField2");
-
- if ((delegate != null) && ((replacement = delegate.objectForOutletPath(this, "mPasswordSheet")) != null)) {
- _eoFrame0 = (replacement == EOArchive._ObjectInstantiationDelegate.NullObject) ? null : (com.webobjects.eointerface.swing.EOFrame)replacement;
- _replacedObjects.setObjectForKey(replacement, "_eoFrame0");
- } else {
- _eoFrame0 = (com.webobjects.eointerface.swing.EOFrame)_registered(new com.webobjects.eointerface.swing.EOFrame(), "Panel");
- }
-
- _nsView0 = (JPanel)_eoFrame0.getContentPane();
- }
-
- protected void _awaken() {
- super._awaken();
-
- if (_replacedObjects.objectForKey("_eoFrame0") == null) {
- _connect(_eoFrame0, _owner(), "delegate");
- }
-
- _nsButton0.addActionListener((com.webobjects.eointerface.swing.EOControlActionAdapter)_registered(new com.webobjects.eointerface.swing.EOControlActionAdapter(_owner(), "passwordClick", _nsButton0), ""));
-
- if (_replacedObjects.objectForKey("_eoFrame0") == null) {
- _connect(_owner(), _eoFrame0, "mPasswordSheet");
- }
-
- if (_replacedObjects.objectForKey("_nsSecureTextField0") == null) {
- _connect(_owner(), _nsSecureTextField0, "mPasswordField");
- }
-
- if (_replacedObjects.objectForKey("_nsButton4") == null) {
- _connect(_owner(), _nsButton4, "mCreateButton");
- }
-
- _nsButton4.addActionListener((com.webobjects.eointerface.swing.EOControlActionAdapter)_registered(new com.webobjects.eointerface.swing.EOControlActionAdapter(_owner(), "doCreate", _nsButton4), ""));
- _nsButton3.addActionListener((com.webobjects.eointerface.swing.EOControlActionAdapter)_registered(new com.webobjects.eointerface.swing.EOControlActionAdapter(_owner(), "doCancel", _nsButton3), ""));
- _nsButton2.addActionListener((com.webobjects.eointerface.swing.EOControlActionAdapter)_registered(new com.webobjects.eointerface.swing.EOControlActionAdapter(_owner(), "doGo", _nsButton2), ""));
-
- if (_replacedObjects.objectForKey("_eoFrame1") == null) {
- _connect(_owner(), _eoFrame1, "window");
- }
-
- _nsTextField2.addActionListener((com.webobjects.eointerface.swing.EOControlActionAdapter)_registered(new com.webobjects.eointerface.swing.EOControlActionAdapter(_owner(), "modifyInstance", _nsTextField2), ""));
-
- if (_replacedObjects.objectForKey("_nsTextField3") == null) {
- _connect(_owner(), _nsTextField3, "mLoginField");
- }
-
- _nsTextField3.addActionListener((com.webobjects.eointerface.swing.EOControlActionAdapter)_registered(new com.webobjects.eointerface.swing.EOControlActionAdapter(_owner(), "modifyInstance", _nsTextField3), ""));
-
- if (_replacedObjects.objectForKey("_nsTextField4") == null) {
- _connect(_owner(), _nsTextField4, "mDatabaseField");
- }
-
- _nsTextField4.addActionListener((com.webobjects.eointerface.swing.EOControlActionAdapter)_registered(new com.webobjects.eointerface.swing.EOControlActionAdapter(_owner(), "modifyInstance", _nsTextField4), ""));
-
- if (_replacedObjects.objectForKey("_nsTextField5") == null) {
- _connect(_owner(), _nsTextField5, "mPortField");
- }
-
- _nsTextField5.addActionListener((com.webobjects.eointerface.swing.EOControlActionAdapter)_registered(new com.webobjects.eointerface.swing.EOControlActionAdapter(_owner(), "modifyInstance", _nsTextField5), ""));
-
- if (_replacedObjects.objectForKey("_nsTextField2") == null) {
- _connect(_owner(), _nsTextField2, "mHostField");
- }
-
- _nsButton1.addActionListener((com.webobjects.eointerface.swing.EOControlActionAdapter)_registered(new com.webobjects.eointerface.swing.EOControlActionAdapter(_owner(), "passwordClick", _nsButton1), ""));
- }
-
- protected void _init() {
- super._init();
- if (!(_nsBox2.getLayout() instanceof EOViewLayout)) { _nsBox2.setLayout(new EOViewLayout()); }
- _nsBox3.setSize(401, 1);
- _nsBox3.setLocation(2, 2);
- ((EOViewLayout)_nsBox2.getLayout()).setAutosizingMask(_nsBox3, EOViewLayout.MinYMargin);
- _nsBox2.add(_nsBox3);
- _nsBox2.setBorder(new com.webobjects.eointerface.swing._EODefaultBorder("", true, "Lucida Grande", 13, Font.PLAIN));
-
- if (_replacedObjects.objectForKey("_nsButton4") == null) {
- _setFontForComponent(_nsButton4, "Lucida Grande", 13, Font.PLAIN);
- _nsButton4.setMargin(new Insets(0, 2, 0, 2));
- }
-
- _setFontForComponent(_nsButton3, "Lucida Grande", 13, Font.PLAIN);
- _nsButton3.setMargin(new Insets(0, 2, 0, 2));
- _setFontForComponent(_nsButton2, "Lucida Grande", 13, Font.PLAIN);
- _nsButton2.setMargin(new Insets(0, 2, 0, 2));
- if (!(_nsBox0.getLayout() instanceof EOViewLayout)) { _nsBox0.setLayout(new EOViewLayout()); }
- _nsBox1.setSize(328, 1);
- _nsBox1.setLocation(2, 2);
- ((EOViewLayout)_nsBox0.getLayout()).setAutosizingMask(_nsBox1, EOViewLayout.MinYMargin);
- _nsBox0.add(_nsBox1);
- _nsBox0.setBorder(new com.webobjects.eointerface.swing._EODefaultBorder("", true, "Lucida Grande", 13, Font.PLAIN));
- _setFontForComponent(_nsTextField9, "Lucida Grande", 13, Font.PLAIN);
- _nsTextField9.setEditable(false);
- _nsTextField9.setOpaque(false);
- _nsTextField9.setText("Port :");
- _nsTextField9.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
- _nsTextField9.setSelectable(true);
- _nsTextField9.setEnabled(true);
- _nsTextField9.setBorder(null);
- _setFontForComponent(_nsTextField8, "Lucida Grande", 13, Font.PLAIN);
- _nsTextField8.setEditable(false);
- _nsTextField8.setOpaque(false);
- _nsTextField8.setText("Database :");
- _nsTextField8.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
- _nsTextField8.setSelectable(true);
- _nsTextField8.setEnabled(true);
- _nsTextField8.setBorder(null);
- _setFontForComponent(_nsTextField7, "Lucida Grande", 13, Font.PLAIN);
- _nsTextField7.setEditable(false);
- _nsTextField7.setOpaque(false);
- _nsTextField7.setText("Login :");
- _nsTextField7.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
- _nsTextField7.setSelectable(true);
- _nsTextField7.setEnabled(true);
- _nsTextField7.setBorder(null);
- _setFontForComponent(_nsTextField6, "Lucida Grande", 13, Font.PLAIN);
- _nsTextField6.setEditable(false);
- _nsTextField6.setOpaque(false);
- _nsTextField6.setText("Host :");
- _nsTextField6.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
- _nsTextField6.setSelectable(true);
- _nsTextField6.setEnabled(true);
- _nsTextField6.setBorder(null);
- if (!(_nsView1.getLayout() instanceof EOViewLayout)) { _nsView1.setLayout(new EOViewLayout()); }
- _nsTextField6.setSize(72, 17);
- _nsTextField6.setLocation(11, 17);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsTextField6, EOViewLayout.MaxXMargin | EOViewLayout.MaxYMargin);
- _nsView1.add(_nsTextField6);
- _nsTextField7.setSize(72, 17);
- _nsTextField7.setLocation(11, 47);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsTextField7, EOViewLayout.MaxXMargin | EOViewLayout.MaxYMargin);
- _nsView1.add(_nsTextField7);
- _nsTextField8.setSize(72, 17);
- _nsTextField8.setLocation(11, 77);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsTextField8, EOViewLayout.MaxXMargin | EOViewLayout.MaxYMargin);
- _nsView1.add(_nsTextField8);
- _nsTextField9.setSize(72, 17);
- _nsTextField9.setLocation(11, 107);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsTextField9, EOViewLayout.MaxXMargin | EOViewLayout.MaxYMargin);
- _nsView1.add(_nsTextField9);
- _nsTextField2.setSize(242, 22);
- _nsTextField2.setLocation(88, 14);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsTextField2, EOViewLayout.MinXMargin | EOViewLayout.WidthSizable | EOViewLayout.MaxYMargin);
- _nsView1.add(_nsTextField2);
- _nsTextField3.setSize(242, 22);
- _nsTextField3.setLocation(88, 44);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsTextField3, EOViewLayout.MinXMargin | EOViewLayout.WidthSizable | EOViewLayout.MaxYMargin);
- _nsView1.add(_nsTextField3);
- _nsTextField4.setSize(242, 22);
- _nsTextField4.setLocation(88, 74);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsTextField4, EOViewLayout.MinXMargin | EOViewLayout.WidthSizable | EOViewLayout.MaxYMargin);
- _nsView1.add(_nsTextField4);
- _nsTextField5.setSize(242, 22);
- _nsTextField5.setLocation(88, 104);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsTextField5, EOViewLayout.MinXMargin | EOViewLayout.WidthSizable | EOViewLayout.MaxYMargin);
- _nsView1.add(_nsTextField5);
- _nsBox0.setSize(332, 5);
- _nsBox0.setLocation(5, 130);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsBox0, EOViewLayout.WidthSizable | EOViewLayout.MaxYMargin);
- _nsView1.add(_nsBox0);
- _nsButton2.setSize(77, 26);
- _nsButton2.setLocation(256, 144);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsButton2, EOViewLayout.MinXMargin | EOViewLayout.MinYMargin);
- _nsView1.add(_nsButton2);
- _nsButton3.setSize(77, 26);
- _nsButton3.setLocation(172, 144);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsButton3, EOViewLayout.MinXMargin | EOViewLayout.MinYMargin);
- _nsView1.add(_nsButton3);
- _nsButton4.setSize(96, 26);
- _nsButton4.setLocation(12, 144);
- ((EOViewLayout)_nsView1.getLayout()).setAutosizingMask(_nsButton4, EOViewLayout.MinYMargin);
- _nsView1.add(_nsButton4);
-
- if (_replacedObjects.objectForKey("_eoFrame1") == null) {
- _nsView1.setSize(342, 180);
- _eoFrame1.setTitle("New Connection Parameters");
- _eoFrame1.setLocation(111, 492);
- _eoFrame1.setSize(342, 180);
- }
-
- if (_replacedObjects.objectForKey("_nsTextField5") == null) {
- _connect(_nsTextField5, _nsTextField2, "nextFocusableComponent");
- }
-
- if (_replacedObjects.objectForKey("_nsTextField5") == null) {
- _setFontForComponent(_nsTextField5, "Lucida Grande", 13, Font.PLAIN);
- _nsTextField5.setEditable(true);
- _nsTextField5.setOpaque(true);
- _nsTextField5.setText("");
- _nsTextField5.setHorizontalAlignment(javax.swing.JTextField.LEFT);
- _nsTextField5.setSelectable(true);
- _nsTextField5.setEnabled(true);
- }
-
- if (_replacedObjects.objectForKey("_nsTextField4") == null) {
- _connect(_nsTextField4, _nsTextField5, "nextFocusableComponent");
- }
-
- if (_replacedObjects.objectForKey("_nsTextField4") == null) {
- _setFontForComponent(_nsTextField4, "Lucida Grande", 13, Font.PLAIN);
- _nsTextField4.setEditable(true);
- _nsTextField4.setOpaque(true);
- _nsTextField4.setText("");
- _nsTextField4.setHorizontalAlignment(javax.swing.JTextField.LEFT);
- _nsTextField4.setSelectable(true);
- _nsTextField4.setEnabled(true);
- }
-
- if (_replacedObjects.objectForKey("_nsTextField3") == null) {
- _connect(_nsTextField3, _nsTextField4, "nextFocusableComponent");
- }
-
- if (_replacedObjects.objectForKey("_nsTextField3") == null) {
- _setFontForComponent(_nsTextField3, "Lucida Grande", 13, Font.PLAIN);
- _nsTextField3.setEditable(true);
- _nsTextField3.setOpaque(true);
- _nsTextField3.setText("");
- _nsTextField3.setHorizontalAlignment(javax.swing.JTextField.LEFT);
- _nsTextField3.setSelectable(true);
- _nsTextField3.setEnabled(true);
- }
-
- if (_replacedObjects.objectForKey("_nsTextField2") == null) {
- _connect(_nsTextField2, _nsTextField3, "nextFocusableComponent");
- }
-
- if (_replacedObjects.objectForKey("_nsTextField2") == null) {
- _setFontForComponent(_nsTextField2, "Lucida Grande", 13, Font.PLAIN);
- _nsTextField2.setEditable(true);
- _nsTextField2.setOpaque(true);
- _nsTextField2.setText("");
- _nsTextField2.setHorizontalAlignment(javax.swing.JTextField.LEFT);
- _nsTextField2.setSelectable(true);
- _nsTextField2.setEnabled(true);
- }
-
- _connect(_nsButton1, _nsSecureTextField0, "nextFocusableComponent");
- _setFontForComponent(_nsButton1, "Lucida Grande", 13, Font.PLAIN);
- _nsButton1.setMargin(new Insets(0, 2, 0, 2));
-
- if (_replacedObjects.objectForKey("_nsButton0") == null) {
- _connect(_nsButton0, _nsButton1, "nextFocusableComponent");
- }
-
- if (_replacedObjects.objectForKey("_nsButton0") == null) {
- _setFontForComponent(_nsButton0, "Lucida Grande", 13, Font.PLAIN);
- _nsButton0.setMargin(new Insets(0, 2, 0, 2));
- }
-
- if (_replacedObjects.objectForKey("_nsSecureTextField0") == null) {
- _connect(_nsSecureTextField0, _nsButton0, "nextFocusableComponent");
- }
-
- if (_replacedObjects.objectForKey("_nsSecureTextField0") == null) {
- _setFontForComponent(_nsSecureTextField0, "Lucida Grande", 13, Font.PLAIN);
- _nsSecureTextField0.setEditable(true);
- _nsSecureTextField0.setOpaque(true);
- _nsSecureTextField0.setText("");
- _nsSecureTextField0.setHorizontalAlignment(javax.swing.JTextField.LEFT);
- _nsSecureTextField0.setEnabled(true);
- }
-
- _setFontForComponent(_nsTextField1, "Lucida Grande", 13, Font.PLAIN);
- _nsTextField1.setEditable(false);
- _nsTextField1.setOpaque(false);
- _nsTextField1.setText("Password :");
- _nsTextField1.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
- _nsTextField1.setSelectable(false);
- _nsTextField1.setEnabled(true);
- _nsTextField1.setBorder(null);
- _setFontForComponent(_nsTextField0, "Lucida Grande", 13, Font.PLAIN);
- _nsTextField0.setEditable(false);
- _nsTextField0.setOpaque(false);
- _nsTextField0.setText("Please enter your password for DB server ");
- _nsTextField0.setHorizontalAlignment(javax.swing.JTextField.CENTER);
- _nsTextField0.setSelectable(false);
- _nsTextField0.setEnabled(true);
- _nsTextField0.setBorder(null);
- if (!(_nsView0.getLayout() instanceof EOViewLayout)) { _nsView0.setLayout(new EOViewLayout()); }
- _nsTextField0.setSize(395, 17);
- _nsTextField0.setLocation(11, 14);
- ((EOViewLayout)_nsView0.getLayout()).setAutosizingMask(_nsTextField0, EOViewLayout.WidthSizable | EOViewLayout.MaxYMargin);
- _nsView0.add(_nsTextField0);
- _nsTextField1.setSize(73, 17);
- _nsTextField1.setLocation(11, 51);
- ((EOViewLayout)_nsView0.getLayout()).setAutosizingMask(_nsTextField1, EOViewLayout.MaxXMargin | EOViewLayout.MaxYMargin);
- _nsView0.add(_nsTextField1);
- _nsSecureTextField0.setSize(314, 22);
- _nsSecureTextField0.setLocation(89, 48);
- ((EOViewLayout)_nsView0.getLayout()).setAutosizingMask(_nsSecureTextField0, EOViewLayout.WidthSizable | EOViewLayout.MinYMargin);
- _nsView0.add(_nsSecureTextField0);
- _nsBox2.setSize(405, 5);
- _nsBox2.setLocation(5, 37);
- ((EOViewLayout)_nsView0.getLayout()).setAutosizingMask(_nsBox2, EOViewLayout.MinYMargin);
- _nsView0.add(_nsBox2);
- _nsButton0.setSize(77, 26);
- _nsButton0.setLocation(329, 88);
- ((EOViewLayout)_nsView0.getLayout()).setAutosizingMask(_nsButton0, EOViewLayout.MinYMargin);
- _nsView0.add(_nsButton0);
- _nsButton1.setSize(77, 26);
- _nsButton1.setLocation(245, 88);
- ((EOViewLayout)_nsView0.getLayout()).setAutosizingMask(_nsButton1, EOViewLayout.MinYMargin);
- _nsView0.add(_nsButton1);
-
- if (_replacedObjects.objectForKey("_eoFrame0") == null) {
- _nsView0.setSize(415, 124);
- _eoFrame0.setTitle("Password");
- _eoFrame0.setLocation(95, 422);
- _eoFrame0.setSize(415, 124);
- }
- }
-}
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/classes.nib b/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/classes.nib
deleted file mode 100644
index e9dc7fa3..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/classes.nib
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- IBClasses = (
- {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
- {
- ACTIONS = {
- askPassword = id;
- doCancel = id;
- doCreate = id;
- doGo = id;
- modifyInstance = id;
- passwordClick = id;
- };
- CLASS = MCPConnectionWinCont;
- LANGUAGE = ObjC;
- OUTLETS = {
- mCreateButton = NSButton;
- mDatabaseField = NSTextField;
- mHostField = NSTextField;
- mLoginField = NSTextField;
- mPasswordField = NSTextField;
- mPasswordSheet = NSPanel;
- mPortField = NSTextField;
- };
- SUPERCLASS = NSWindowController;
- }
- );
- IBVersion = 1;
-} \ No newline at end of file
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/info.nib b/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/info.nib
deleted file mode 100644
index 10b70ee6..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/info.nib
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>IBDocumentLocation</key>
- <string>193 200 356 240 0 0 1280 832 </string>
- <key>IBFramework Version</key>
- <string>364.0</string>
- <key>IBOpenObjects</key>
- <array>
- <integer>5</integer>
- </array>
- <key>IBSystem Version</key>
- <string>7F44</string>
-</dict>
-</plist>
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/keyedobjects.nib b/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/keyedobjects.nib
deleted file mode 100644
index d0ebc199..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/English.lproj/MCPConnectionWindow.nib/keyedobjects.nib
+++ /dev/null
Binary files differ
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/Info.plist b/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/Info.plist
deleted file mode 100644
index c5731f54..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/A/Resources/Info.plist
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>CFBundleDevelopmentRegion</key>
- <string>English</string>
- <key>CFBundleExecutable</key>
- <string>MCPKit_bundled</string>
- <key>CFBundleIdentifier</key>
- <string>net.chocolatnoir.MCPKit_bundled</string>
- <key>CFBundleInfoDictionaryVersion</key>
- <string>6.0</string>
- <key>CFBundlePackageType</key>
- <string>FMWK</string>
- <key>CFBundleSignature</key>
- <string>????</string>
- <key>CFBundleVersion</key>
- <string>1.0</string>
-</dict>
-</plist>
diff --git a/Frameworks/MCPKit_bundled.framework/Versions/Current b/Frameworks/MCPKit_bundled.framework/Versions/Current
deleted file mode 120000
index 8c7e5a66..00000000
--- a/Frameworks/MCPKit_bundled.framework/Versions/Current
+++ /dev/null
@@ -1 +0,0 @@
-A \ No newline at end of file