Implement executeSql command.
Reviewed By: lblasa Differential Revision: D48310925 fbshipit-source-id: 136b7f09a3a1b886111b6e3cb0e377b73b126e59
This commit is contained in:
committed by
Facebook GitHub Bot
parent
42fb6f09f7
commit
7ba548d6e7
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
#include <objc/NSObjCRuntime.h>
|
||||||
|
|
||||||
@interface DatabaseExecuteSqlResponse : NSObject
|
@interface DatabaseExecuteSqlResponse : NSObject
|
||||||
|
|
||||||
@@ -15,6 +16,12 @@
|
|||||||
@property(nonatomic, strong) NSNumber* insertedId;
|
@property(nonatomic, strong) NSNumber* insertedId;
|
||||||
@property(nonatomic, assign) NSInteger affectedCount;
|
@property(nonatomic, assign) NSInteger affectedCount;
|
||||||
|
|
||||||
|
- (instancetype)initWithType:(NSString*)type
|
||||||
|
columns:(NSArray*)columns
|
||||||
|
values:(NSArray*)values
|
||||||
|
insertedId:(NSNumber*)insertedId
|
||||||
|
affectedCount:(NSInteger)affectedCount;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface DatabaseExecuteSqlRequest : NSObject
|
@interface DatabaseExecuteSqlRequest : NSObject
|
||||||
@@ -23,5 +30,7 @@
|
|||||||
@property(nonatomic, copy, readonly) NSString* value;
|
@property(nonatomic, copy, readonly) NSString* value;
|
||||||
|
|
||||||
- (instancetype)initWithDatabaseId:(NSInteger)databaseId value:(NSString*)value;
|
- (instancetype)initWithDatabaseId:(NSInteger)databaseId value:(NSString*)value;
|
||||||
|
+ (DatabaseExecuteSqlRequest*)getExecuteSqlRequestFromDictionary:
|
||||||
|
(NSDictionary*)dictionary;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DatabaseExecuteSql.h"
|
#include "DatabaseExecuteSql.h"
|
||||||
|
#include <objc/NSObjCRuntime.h>
|
||||||
|
|
||||||
@implementation DatabaseExecuteSqlResponse
|
@implementation DatabaseExecuteSqlResponse
|
||||||
|
|
||||||
@@ -39,4 +40,15 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (DatabaseExecuteSqlRequest*)getExecuteSqlRequestFromDictionary:
|
||||||
|
(NSDictionary*)dictionary {
|
||||||
|
NSInteger databaseId = [dictionary[@"databaseId"] integerValue];
|
||||||
|
NSString* value = dictionary[@"value"];
|
||||||
|
if (databaseId <= 0 || value.length == 0) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return [[DatabaseExecuteSqlRequest alloc] initWithDatabaseId:databaseId
|
||||||
|
value:value];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
@class DatabaseGetTableStructureResponse;
|
@class DatabaseGetTableStructureResponse;
|
||||||
@class DatabaseGetTableInfoResponse;
|
@class DatabaseGetTableInfoResponse;
|
||||||
@class DatabaseGetTableDataResponse;
|
@class DatabaseGetTableDataResponse;
|
||||||
|
@class DatabaseExecuteSqlResponse;
|
||||||
|
|
||||||
@protocol DatabaseDriver<NSObject>
|
@protocol DatabaseDriver<NSObject>
|
||||||
- (NSArray<id<DatabaseDescriptor>>*)getDatabases;
|
- (NSArray<id<DatabaseDescriptor>>*)getDatabases;
|
||||||
@@ -32,4 +33,5 @@
|
|||||||
reverse:(BOOL)reverse
|
reverse:(BOOL)reverse
|
||||||
start:(NSInteger)start
|
start:(NSInteger)start
|
||||||
count:(NSInteger)count;
|
count:(NSInteger)count;
|
||||||
|
- (DatabaseExecuteSqlResponse*)executeSQL:(NSString*)sql;
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#import "DatabaseDescriptorHolder.h"
|
#import "DatabaseDescriptorHolder.h"
|
||||||
#import "DatabaseDriver.h"
|
#import "DatabaseDriver.h"
|
||||||
#import "DatabaseErrorCodes.h"
|
#import "DatabaseErrorCodes.h"
|
||||||
|
#import "DatabaseExecuteSql.h"
|
||||||
#import "DatabaseGetTableData.h"
|
#import "DatabaseGetTableData.h"
|
||||||
#import "DatabaseGetTableInfo.h"
|
#import "DatabaseGetTableInfo.h"
|
||||||
#import "DatabaseGetTableStructure.h"
|
#import "DatabaseGetTableStructure.h"
|
||||||
@@ -214,6 +215,37 @@
|
|||||||
[self.connection
|
[self.connection
|
||||||
receive:@"execute"
|
receive:@"execute"
|
||||||
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
|
DatabaseExecuteSqlRequest* request = [DatabaseExecuteSqlRequest
|
||||||
|
getExecuteSqlRequestFromDictionary:params];
|
||||||
|
if (!request) {
|
||||||
|
NSDictionary* errorResponse = [ObjectMapper
|
||||||
|
errorWithCode:DatabasesErrorCodesInvalidRequest
|
||||||
|
message:kDatabasesErrorCodesInvalidRequestMessage];
|
||||||
|
[responder error:errorResponse];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DatabaseDescriptorHolder* descriptorHolder =
|
||||||
|
self.databaseDescriptorHolders[@(request.databaseId)];
|
||||||
|
if (!descriptorHolder) {
|
||||||
|
NSDictionary* errorResponse = [ObjectMapper
|
||||||
|
errorWithCode:DatabasesErrorCodesDatabaseInvalid
|
||||||
|
message:kDatabasesErrorCodesDatabaseInvalidMessage];
|
||||||
|
[responder error:errorResponse];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@try {
|
||||||
|
DatabaseExecuteSqlResponse* sqlResponse =
|
||||||
|
[descriptorHolder.databaseDriver executeSQL:request.value];
|
||||||
|
NSDictionary* response =
|
||||||
|
[ObjectMapper databaseExecuteSqlResponseToDictionary:sqlResponse];
|
||||||
|
[responder success:response];
|
||||||
|
} @catch (NSException* exception) {
|
||||||
|
NSDictionary* errorResponse = [ObjectMapper
|
||||||
|
errorWithCode:DatabasesErrorCodesSqlExecutionException
|
||||||
|
message:[kDatabasesErrorCodesSqlExecutionExceptionMessage
|
||||||
|
stringByAppendingString:exception.reason]];
|
||||||
|
[responder error:errorResponse];
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#import "MockDatabaseDriver.h"
|
#import "MockDatabaseDriver.h"
|
||||||
|
#import "DatabaseExecuteSql.h"
|
||||||
#import "DatabaseGetTableData.h"
|
#import "DatabaseGetTableData.h"
|
||||||
#import "DatabaseGetTableInfo.h"
|
#import "DatabaseGetTableInfo.h"
|
||||||
#import "DatabaseGetTableStructure.h"
|
#import "DatabaseGetTableStructure.h"
|
||||||
@@ -80,4 +81,39 @@
|
|||||||
total:100];
|
total:100];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (DatabaseExecuteSqlResponse*)executeSQL:(NSString*)sql {
|
||||||
|
// Generate a mock response with a random type
|
||||||
|
NSString* type;
|
||||||
|
NSArray* columns = @[ @"id", @"name" ];
|
||||||
|
NSMutableArray* values = [NSMutableArray array];
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
[values addObject:@[ @(i), [NSString stringWithFormat:@"Name %d", i] ]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Randomly select a type
|
||||||
|
NSArray<NSString*>* types = @[ @"SELECT", @"INSERT", @"UPDATE", @"DELETE" ];
|
||||||
|
int index = arc4random_uniform((u_int32_t)types.count);
|
||||||
|
type = types[index];
|
||||||
|
|
||||||
|
// Set affectedCount and insertedId based on type
|
||||||
|
NSInteger affectedCount = 0;
|
||||||
|
NSNumber* insertedId = nil;
|
||||||
|
if ([type isEqualToString:@"INSERT"]) {
|
||||||
|
affectedCount = 1;
|
||||||
|
insertedId = @(15);
|
||||||
|
} else if (
|
||||||
|
[type isEqualToString:@"UPDATE"] || [type isEqualToString:@"DELETE"]) {
|
||||||
|
affectedCount = values.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseExecuteSqlResponse* response =
|
||||||
|
[[DatabaseExecuteSqlResponse alloc] initWithType:type
|
||||||
|
columns:columns
|
||||||
|
values:[values copy]
|
||||||
|
insertedId:insertedId
|
||||||
|
affectedCount:affectedCount];
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -83,7 +83,29 @@ static NSString* const UNKNOWN_BLOB_LABEL_FORMAT = @"{%d-byte %@ blob}";
|
|||||||
|
|
||||||
+ (NSDictionary*)databaseExecuteSqlResponseToDictionary:
|
+ (NSDictionary*)databaseExecuteSqlResponseToDictionary:
|
||||||
(DatabaseExecuteSqlResponse*)response {
|
(DatabaseExecuteSqlResponse*)response {
|
||||||
return @{};
|
NSMutableArray* rows = [NSMutableArray array];
|
||||||
|
if (response.values) {
|
||||||
|
for (NSArray* row in response.values) {
|
||||||
|
NSMutableArray* rowValues = [NSMutableArray array];
|
||||||
|
for (id item in row) {
|
||||||
|
[rowValues addObject:[self objectAndTypeToFlipperObject:item]];
|
||||||
|
}
|
||||||
|
[rows addObject:rowValues];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableDictionary* result = [NSMutableDictionary dictionaryWithDictionary:@{
|
||||||
|
@"type" : response.type,
|
||||||
|
@"columns" : response.columns,
|
||||||
|
@"values" : rows,
|
||||||
|
@"affectedCount" : @(response.affectedCount)
|
||||||
|
}];
|
||||||
|
|
||||||
|
if (response.insertedId) {
|
||||||
|
result[@"insertedId"] = response.insertedId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSDictionary*)objectAndTypeToFlipperObject:(id)object {
|
+ (NSDictionary*)objectAndTypeToFlipperObject:(id)object {
|
||||||
|
|||||||
Reference in New Issue
Block a user