Implement getTableData command.

Reviewed By: lblasa

Differential Revision: D48267029

fbshipit-source-id: a2ee02d3d0c465c83acd99fd7093e0abb5c7c2de
This commit is contained in:
Fúlvio Abrahão de Paula
2023-08-14 11:07:07 -07:00
committed by Facebook GitHub Bot
parent a0510ad1bf
commit 42fb6f09f7
6 changed files with 185 additions and 3 deletions

View File

@@ -39,4 +39,7 @@
start:(NSInteger)start start:(NSInteger)start
count:(NSInteger)count; count:(NSInteger)count;
+ (DatabaseGetTableDataRequest*)getTableDataRequestFromDictionary:
(NSDictionary*)dictionary;
@end @end

View File

@@ -47,4 +47,23 @@
return self; return self;
} }
+ (DatabaseGetTableDataRequest*)getTableDataRequestFromDictionary:
(NSDictionary*)dictionary {
NSInteger databaseId = [dictionary[@"databaseId"] integerValue];
NSString* table = dictionary[@"table"];
NSString* order = dictionary[@"order"];
BOOL reverse = [dictionary[@"reverse"] boolValue];
NSInteger start = [dictionary[@"start"] integerValue];
NSInteger count = [dictionary[@"count"] integerValue];
if (databaseId <= 0 || table.length == 0) {
return nil;
}
return [[DatabaseGetTableDataRequest alloc] initWithDatabaseId:databaseId
table:table
order:order
reverse:reverse
start:start
count:count];
}
@end @end

View File

@@ -8,8 +8,9 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@protocol DatabaseDescriptor; @protocol DatabaseDescriptor;
@class DatabaseGetTableInfoResponse;
@class DatabaseGetTableStructureResponse; @class DatabaseGetTableStructureResponse;
@class DatabaseGetTableInfoResponse;
@class DatabaseGetTableDataResponse;
@protocol DatabaseDriver<NSObject> @protocol DatabaseDriver<NSObject>
- (NSArray<id<DatabaseDescriptor>>*)getDatabases; - (NSArray<id<DatabaseDescriptor>>*)getDatabases;
@@ -22,4 +23,13 @@
getTableInfoWithDatabaseDescriptor: getTableInfoWithDatabaseDescriptor:
(id<DatabaseDescriptor>)databaseDescriptor (id<DatabaseDescriptor>)databaseDescriptor
forTable:(NSString*)tableName; forTable:(NSString*)tableName;
- (DatabaseGetTableDataResponse*)
getTableDataWithDatabaseDescriptor:
(id<DatabaseDescriptor>)databaseDescriptor
forTable:(NSString*)tableName
order:(NSString*)order
reverse:(BOOL)reverse
start:(NSInteger)start
count:(NSInteger)count;
@end @end

View File

@@ -14,6 +14,7 @@
#import "DatabaseDescriptorHolder.h" #import "DatabaseDescriptorHolder.h"
#import "DatabaseDriver.h" #import "DatabaseDriver.h"
#import "DatabaseErrorCodes.h" #import "DatabaseErrorCodes.h"
#import "DatabaseGetTableData.h"
#import "DatabaseGetTableInfo.h" #import "DatabaseGetTableInfo.h"
#import "DatabaseGetTableStructure.h" #import "DatabaseGetTableStructure.h"
#import "ObjectMapper.h" #import "ObjectMapper.h"
@@ -85,8 +86,46 @@
[self.connection [self.connection
receive:@"getTableData" receive:@"getTableData"
withBlock:^(NSDictionary* params, id<FlipperResponder> responder){ withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
DatabaseGetTableDataRequest* request = [DatabaseGetTableDataRequest
getTableDataRequestFromDictionary: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 {
DatabaseGetTableDataResponse* tableDataResponse =
[descriptorHolder.databaseDriver
getTableDataWithDatabaseDescriptor:descriptorHolder
.databaseDescriptor
forTable:request.table
order:request.order
reverse:request.reverse
start:request.start
count:request.count];
NSDictionary* response = [ObjectMapper
databaseGetTableDataResponseToDictionary:tableDataResponse];
[responder success:response];
} @catch (NSException* exception) {
NSDictionary* errorResponse = [ObjectMapper
errorWithCode:DatabasesErrorCodesSqlExecutionException
message:[kDatabasesErrorCodesSqlExecutionExceptionMessage
stringByAppendingString:exception.reason]];
[responder error:errorResponse];
}
}]; }];
[self.connection [self.connection

View File

@@ -6,6 +6,7 @@
*/ */
#import "MockDatabaseDriver.h" #import "MockDatabaseDriver.h"
#import "DatabaseGetTableData.h"
#import "DatabaseGetTableInfo.h" #import "DatabaseGetTableInfo.h"
#import "DatabaseGetTableStructure.h" #import "DatabaseGetTableStructure.h"
#import "MockDatabaseDescriptor.h" #import "MockDatabaseDescriptor.h"
@@ -55,4 +56,28 @@
initWithDefinition:@"This is mocked table definition"]; initWithDefinition:@"This is mocked table definition"];
} }
- (DatabaseGetTableDataResponse*)
getTableDataWithDatabaseDescriptor:
(id<DatabaseDescriptor>)databaseDescriptor
forTable:(NSString*)tableName
order:(NSString*)order
reverse:(BOOL)reverse
start:(NSInteger)start
count:(NSInteger)count {
NSMutableArray* columns = [NSMutableArray array];
NSMutableArray* values = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
NSString* columnName = [NSString stringWithFormat:@"column%d", i + 1];
[columns addObject:columnName];
NSArray* valueRow = @[ @"value1", @"value2", @"value3" ];
[values addObject:valueRow];
}
return [[DatabaseGetTableDataResponse alloc] initWithColumns:[columns copy]
values:[values copy]
start:0
count:100
total:100];
}
@end @end

View File

@@ -15,6 +15,9 @@
@implementation ObjectMapper @implementation ObjectMapper
static const int MAX_BLOB_LENGTH = 100 * 1024;
static NSString* const UNKNOWN_BLOB_LABEL_FORMAT = @"{%d-byte %@ blob}";
+ (NSMutableArray*)databaseListToFlipperArray: + (NSMutableArray*)databaseListToFlipperArray:
(NSMutableSet<DatabaseDescriptorHolder*>*)databaseDescriptorHolderSet { (NSMutableSet<DatabaseDescriptorHolder*>*)databaseDescriptorHolderSet {
NSMutableArray* result = [NSMutableArray new]; NSMutableArray* result = [NSMutableArray new];
@@ -39,7 +42,22 @@
+ (NSDictionary*)databaseGetTableDataResponseToDictionary: + (NSDictionary*)databaseGetTableDataResponseToDictionary:
(DatabaseGetTableDataResponse*)response { (DatabaseGetTableDataResponse*)response {
return @{}; NSMutableArray* rows = [NSMutableArray array];
for (NSArray* row in response.values) {
NSMutableArray* rowValues = [NSMutableArray array];
for (id item in row) {
[rowValues addObject:[self objectAndTypeToFlipperObject:item]];
}
[rows addObject:rowValues];
}
return @{
@"columns" : response.columns,
@"values" : rows,
@"start" : @(response.start),
@"count" : @(response.count),
@"total" : @(response.total)
};
} }
+ (NSDictionary*)errorWithCode:(NSInteger)code message:(NSString*)message { + (NSDictionary*)errorWithCode:(NSInteger)code message:(NSString*)message {
@@ -68,4 +86,72 @@
return @{}; return @{};
} }
+ (NSDictionary*)objectAndTypeToFlipperObject:(id)object {
if (!object) {
return @{@"type" : @"null"};
} else if ([object isKindOfClass:[NSNumber class]]) {
NSNumber* number = (NSNumber*)object;
NSString* type = [NSString stringWithCString:[number objCType]];
if ([type isEqualToString:@"i"]) {
return @{@"type" : @"integer", @"value" : number};
} else if ([type isEqualToString:@"f"] || [type isEqualToString:@"d"]) {
return @{@"type" : @"float", @"value" : number};
} else if ([type isEqualToString:@"B"]) {
return @{@"type" : @"boolean", @"value" : number};
} else {
return @{@"type" : @"integer", @"value" : @([number integerValue])};
}
return @{@"type" : @"integer", @"value" : object};
} else if ([object isKindOfClass:[NSDecimalNumber class]]) {
return @{@"type" : @"float", @"value" : object};
} else if ([object isKindOfClass:[NSString class]]) {
return @{@"type" : @"string", @"value" : object};
} else if ([object isKindOfClass:[NSData class]]) {
NSString* blobString = [self blobToString:(NSData*)object];
return @{@"type" : @"blob", @"value" : blobString};
} else if ([object isKindOfClass:[NSValue class]]) {
return @{@"type" : @"boolean", @"value" : object};
} else {
@throw [NSException exceptionWithName:@"InvalidArgumentException"
reason:@"type of Object is invalid"
userInfo:nil];
}
}
+ (NSString*)blobToString:(NSData*)data {
const uint8_t* bytes = data.bytes;
uint length = data.length;
if (length <= MAX_BLOB_LENGTH) {
if ([self fastIsAscii:bytes length:length]) {
NSStringEncoding encoding = NSASCIIStringEncoding;
return [[NSString alloc] initWithBytesNoCopy:(void*)bytes
length:length
encoding:encoding
freeWhenDone:NO];
} else {
// try UTF-8
NSStringEncoding encoding = NSUTF8StringEncoding;
return [[NSString alloc] initWithBytesNoCopy:(void*)bytes
length:length
encoding:encoding
freeWhenDone:NO];
}
}
return
[NSString stringWithFormat:UNKNOWN_BLOB_LABEL_FORMAT, length, @"binary"];
}
+ (BOOL)fastIsAscii:(const uint8_t*)bytes length:(NSUInteger)length {
for (int i = 0; i < length; i++) {
uint8_t b = bytes[i];
if ((b & ~0x7f) != 0) {
return NO;
}
}
return YES;
}
@end @end