
//
//  MCPGDatabase.h
//  MCPostgresPersistence
//
//  Created by Michael Clark on 24/08/08.
//  Copyright 2008 Marketcircle Inc.. All rights reserved.
//

#import <Foundation/Foundation.h>

#include "libpq-fe.h"



#define kTextResultFormat	0
#define kBinaryResultFormat	1


extern NSString * kMCPGHostConnectionInfoKey;
extern NSString * kMCPGInternalHostConnectionInfoKey;
extern NSString * kMCPGPortConnectionInfoKey;
extern NSString * kMCPGDatabaseConnectionInfoKey;
extern NSString * kMCPGSchemaConnectionInfoKey;
extern NSString * kMCPGUserNameConnectionInfoKey;
extern NSString * kMCPGPasswordConnectionInfoKey;


@class MCPGQueryResult;

@interface MCPGDatabase : NSObject {
	PGconn*         dbConnection;
	
	BOOL            logSQL;
	
	NSDictionary*   connectionSettings;
    
    id              connectionDelegate;  // weak ref
}

#pragma mark -
#pragma mark Initialization
- (MCPGDatabase*)initWithConnectionSettings: (NSDictionary*)aConnectionSettings;
- (MCPGDatabase*)initWithHost: (NSString *)aHost port: (NSNumber *)aPort databaseName: (NSString *)aDatabaseName userName: (NSString *)aUserName password: (NSString *)aPassword;
- (MCPGDatabase*)initWithHost: (NSString *)aHost port: (NSNumber *)aPort databaseName: (NSString *)aDatabaseName userName: (NSString *)aUserName password: (NSString *)aPassword schema:(NSString *)schema;


#pragma mark -
#pragma mark Connection
- (NSDictionary*)connectionSettings;
- (BOOL)isConnected;
- (BOOL)connectWithConnectionSettings: (NSDictionary*)connectionSettings error: (NSError**)error; // Sets the connectionSettings ivar and calls connectAndReturnError:
- (BOOL)connectAndReturnError: (NSError**)error;
- (BOOL)disconnect;

#pragma mark -
#pragma mark Utility Methods
- (NSString*)escapeStringForSQLInclusion: (NSString*)in_str;
	
	
#pragma mark -
#pragma mark Querying
- (BOOL)executeSQL:(NSString *)sql error: (NSError **)error;

- (BOOL)resultWithQuery:(NSString *)sql arguments:(NSArray *)anArray error: (NSError **)error; 
- (BOOL)resultWithQuery:(NSString *)sql bindings:(id)aKVCConformingObject error: (NSError **)error;

- (MCPGQueryResult*)resultSetWithQuery:(NSString *)sql arguments:(NSArray *)anArray error: (NSError **)error; 
- (MCPGQueryResult*)resultSetWithQuery:(NSString *)sql bindings:(id)aKVCConformingObject error: (NSError **)error;
  // If no aKVCConformingObject is provided then parsing of sql is skipped and we proceed
  // If aKVCConformingObject is provided then sql is parsed looking for $key entries and they are translated to $x and the value is passed along for that placeholder

#pragma mark -
#pragma mark Locking
- (BOOL)createAdvisoryLockWithKey1: (NSNumber*)key1 key2: (NSNumber*)key2;
- (BOOL)releaseAdvisoryLockWithKey1: (NSNumber*)key1 key2: (NSNumber*)key2;

#pragma mark -
#pragma mark State
- (BOOL)logSQL;
- (void)setLogSQL: (BOOL)flag;


#pragma mark -
#pragma mark Accessors
- (PGconn*)connection;
- (NSString*)clientEncoding;
- (NSString*)databaseName;
- (NSDictionary*)connectionSettings;

- (id)connectionDelegate;
- (void)setConnectionDelegate:(id)aConnectionDelegate;

@end

#pragma mark -
#pragma mark Dictionary Based Interface
@interface MCPGDatabase (DictionaryInterface)

- (NSArray*)rowsForTable: (NSString*)aTableName matchingValues: (NSDictionary*)values error: (NSError**)error;

- (NSArray*)rowsForRawSQL: (NSString*)sql error: (NSError**)error;

- (BOOL)insertInto: (NSString*)aTableName row: (NSDictionary*)aRow error: (NSError**)error;

- (BOOL)deleteFrom: (NSString*)aTableName rowsMatchingValues: (NSDictionary*)values error: (NSError**)error;
- (BOOL)deleteFrom: (NSString*)aTableName row: (NSDictionary*)aRow primaryKey: (NSString*)aPKey error: (NSError**)error;

- (BOOL)update: (NSString*)aTableName row: (NSDictionary*)aRow primaryKey: (NSString*)aPKey error: (NSError**)error;

@end



#pragma mark -
#pragma mark Connection Dictionary Conveniences
@interface NSDictionary (MCPGConnectionInfoConveniences)

- (NSString*)host;
- (NSString*)internalHost;
- (NSNumber*)port;
- (NSString*)databaseName;
- (NSString*)schemaName;
- (NSString*)userName;
- (NSString*)password;

@end

@interface NSMutableDictionary (MCPGConnectionInfoConveniences)

- (void)setHost: (NSString*)aHost;
- (void)setInternalHost: (NSString*)aHost;
- (void)setPort: (NSNumber*)aPort;
- (void)setDatabaseName: (NSString*)aDatabaseName;
- (void)setSchemaName: (NSString*)aSchemaName;
- (void)setUserName: (NSString*)aUserName;
- (void)setPassword: (NSString*)aPassword;

@end



#pragma mark -
#pragma mark Connection Delegate
@interface NSObject (MCPGDatabaseConnectionDelegate)

// The delegate should take measures to reconnect where applicable - Generally a GUI based app would probably want to warn the user the connection was lost and give them the option to reconnect.  The reason that an automatic reconnect should not take place is because at this level it might be too risky, i.e. we were in the middle of a transaction and we should fail right out instead of continuing halfway through or the higherlevel frameworks/apps might put temp tables on the connection that are required for proper functionaing and reconnecting down here would not get those recreated
//   It is safest to make connnection loss at this level a heavier operation w.r.t. the user unfortunately.
- (void)databaseLostConnection: (MCPGDatabase*)database;

@end
