/ExportWindowController.mm

http://github.com/bububa/MongoHub-Mac · Objective C++ · 292 lines · 265 code · 17 blank · 10 comment · 47 complexity · e8400e700b12ebc2fb9c25688e08429d MD5 · raw file

  1. //
  2. // ExportWindowController.m
  3. // MongoHub
  4. //
  5. // Created by Syd on 10-6-22.
  6. // Copyright 2010 ThePeppersStudio.COM. All rights reserved.
  7. //
  8. #import "ExportWindowController.h"
  9. #import "Configure.h"
  10. #import "DatabasesArrayController.h"
  11. #import "Database.h"
  12. #import "Connection.h"
  13. #import "NSString+Extras.h"
  14. #import "MongoDB.h"
  15. #import <MCPKit_bundled/MCPKit_bundled.h>
  16. #import "FieldMapTableController.h"
  17. #import "FieldMapDataObject.h"
  18. @implementation ExportWindowController
  19. @synthesize dbname;
  20. @synthesize conn;
  21. @synthesize db;
  22. @synthesize mongoDB;
  23. @synthesize databasesArrayController;
  24. @synthesize managedObjectContext;
  25. @synthesize dbsArrayController;
  26. @synthesize tablesArrayController;
  27. @synthesize hostTextField;
  28. @synthesize portTextField;
  29. @synthesize userTextField;
  30. @synthesize passwdTextField;
  31. @synthesize collectionTextField;
  32. @synthesize progressIndicator;
  33. @synthesize tablesPopUpButton;
  34. @synthesize fieldMapTableController;
  35. - (id)init {
  36. if (![super initWithWindowNibName:@"Export"]) return nil;
  37. return self;
  38. }
  39. - (void)dealloc {
  40. [dbname release];
  41. [managedObjectContext release];
  42. [databasesArrayController release];
  43. [conn release];
  44. [db release];
  45. [mongoDB release];
  46. [dbsArrayController release];
  47. [tablesArrayController release];
  48. [hostTextField release];
  49. [portTextField release];
  50. [userTextField release];
  51. [passwdTextField release];
  52. [collectionTextField release];
  53. [progressIndicator release];
  54. [tablesPopUpButton release];
  55. [fieldMapTableController release];
  56. [super dealloc];
  57. }
  58. - (void)windowDidLoad {
  59. //NSLog(@"New Connection Window Loaded");
  60. [super windowDidLoad];
  61. }
  62. - (void)windowWillClose:(NSNotification *)notification {
  63. [[NSNotificationCenter defaultCenter] postNotificationName:kExportWindowWillClose object:dbname];
  64. dbname = nil;
  65. db = nil;
  66. [self initInterface];
  67. }
  68. - (IBAction)export:(id)sender {
  69. [progressIndicator setUsesThreadedAnimation:YES];
  70. [progressIndicator startAnimation: self];
  71. [progressIndicator setDoubleValue:0];
  72. NSString *collection = [[NSString alloc] initWithString:[collectionTextField stringValue]];
  73. if (![collection isPresent]) {
  74. NSRunAlertPanel(@"Error", @"Collection name could not be empty!", @"OK", nil, nil);
  75. return;
  76. }
  77. NSString *tablename = [[NSString alloc] initWithString:[tablesPopUpButton titleOfSelectedItem]];
  78. NSString *user=nil;
  79. NSString *password=nil;
  80. Database *mongodb = [databasesArrayController dbInfo:conn name:dbname];
  81. if (mongodb) {
  82. user = mongodb.user;
  83. password = mongodb.password;
  84. }
  85. [mongodb release];
  86. long long int total = [self exportCount:collection user:user password:password];
  87. if (total == 0) {
  88. return;
  89. }
  90. NSString *query = [[NSString alloc] initWithFormat:@"select * from %@ limit 1", tablename];
  91. MCPResult *theResult = [db queryString:query];
  92. [query release];
  93. NSDictionary *fieldTypes = [theResult fetchTypesAsDictionary];
  94. mongo::BSONObjBuilder fieldsBSONBuilder;
  95. for(FieldMapDataObject *field in fieldMapTableController.nsMutaryDataObj)
  96. {
  97. fieldsBSONBuilder.append([field.mongoKey UTF8String], 1);
  98. }
  99. mongo::BSONObj fieldsBSONObj = fieldsBSONBuilder.obj();
  100. std::auto_ptr<mongo::DBClientCursor> cursor = [mongoDB findAllCursorInDB:dbname collection:collection user:user password:password fields:fieldsBSONObj];
  101. int i = 1;
  102. while( cursor->more() )
  103. {
  104. mongo::BSONObj b = cursor->next();
  105. [self doExportToTable:tablename data:b fieldTypes:fieldTypes];
  106. [progressIndicator setDoubleValue:(double)i/total];
  107. i ++;
  108. }
  109. [progressIndicator stopAnimation: self];
  110. [tablename release];
  111. [collection release];
  112. }
  113. - (long long int)exportCount:(NSString *)collection user:(NSString *)user password:(NSString *)password
  114. {
  115. long long int result = [mongoDB countInDB:dbname collection:collection user:user password:password critical:nil];
  116. return result;
  117. }
  118. - (void)doExportToTable:(NSString *)tableName data:(mongo::BSONObj) bsonObj fieldTypes:(NSDictionary *)fieldTypes
  119. {
  120. int fieldsCount = [fieldMapTableController.nsMutaryDataObj count];
  121. NSMutableArray *fields = [[NSMutableArray alloc] initWithCapacity:fieldsCount];
  122. NSMutableArray *values = [[NSMutableArray alloc] initWithCapacity:fieldsCount];
  123. for(FieldMapDataObject *field in fieldMapTableController.nsMutaryDataObj)
  124. {
  125. id value;
  126. mongo::BSONElement e = bsonObj.getFieldDotted([field.mongoKey UTF8String]);
  127. if (e.eoo() == true) {
  128. continue;
  129. }
  130. if (e.type() == mongo::jstNULL) {
  131. continue;
  132. }else if (e.type() == mongo::Array) {
  133. continue;
  134. }else if (e.type() == mongo::Object) {
  135. continue;
  136. }else if (e.type() == mongo::Bool) {
  137. if (e.boolean()) {
  138. value = [[NSString alloc] initWithString:@"1" ];
  139. }else {
  140. value = [[NSString alloc] initWithString:@"0"];
  141. }
  142. }else if (e.type() == mongo::NumberDouble) {
  143. value = [[NSNumber alloc] initWithDouble: e.numberDouble()];
  144. }else if (e.type() == mongo::NumberInt) {
  145. NSString *ft = [fieldTypes objectForKey:field.sqlKey];
  146. if ([ft isEqualToString:@"date"] || [ft isEqualToString:@"datetime"]) {
  147. value = [[NSDate alloc] initWithTimeIntervalSince1970:e.numberInt()];
  148. }else {
  149. value = [[NSNumber alloc] initWithInt: e.numberInt()];
  150. }
  151. }else if (e.type() == mongo::Date) {
  152. mongo::Date_t dt = (time_t)e.date();
  153. time_t timestamp = dt / 1000;
  154. value = [[NSDate alloc] initWithTimeIntervalSince1970:timestamp];
  155. }else if (e.type() == mongo::Timestamp) {
  156. time_t timestamp = (time_t)e.timestampTime();
  157. value = [[NSDate alloc] initWithTimeIntervalSince1970:timestamp];
  158. }else if (e.type() == mongo::BinData) {
  159. int binlen;
  160. const char* data = e.binData(binlen);
  161. value = [[NSData alloc] initWithBytes:data length:binlen];
  162. }else if (e.type() == mongo::NumberLong) {
  163. NSString *ft = [fieldTypes objectForKey:field.sqlKey];
  164. if ([ft isEqualToString:@"date"] || [ft isEqualToString:@"datetime"]) {
  165. value = [[NSDate alloc] initWithTimeIntervalSince1970:e.numberLong()];
  166. }else {
  167. value = [[NSNumber alloc] initWithLong: e.numberLong()];
  168. }
  169. }else if ([field.mongoKey isEqualToString:@"_id" ]) {
  170. if (e.type() == mongo::jstOID)
  171. {
  172. value = [[NSString alloc] initWithUTF8String: e.__oid().str().c_str()];
  173. }else {
  174. value = [[NSString alloc] initWithUTF8String: e.str().c_str()];
  175. }
  176. }else {
  177. value = [[NSString alloc] initWithUTF8String:e.str().c_str()];
  178. }
  179. NSString *sqlKey = [[NSString alloc] initWithString:field.sqlKey];
  180. NSString *quotedValue = [[NSString alloc] initWithString:[db quoteObject:value]];
  181. [value release];
  182. [fields addObject:sqlKey];
  183. [values addObject:quotedValue];
  184. [quotedValue release];
  185. [sqlKey release];
  186. }
  187. if ([fields count] > 0) {
  188. NSString *query = [[NSString alloc] initWithFormat:@"INSERT INTO %@ (%@) values (%@)", tableName, [fields componentsJoinedByString:@","], [values componentsJoinedByString:@","]];
  189. //NSLog(@"query: %@", query);
  190. [db queryString:query];
  191. [query release];
  192. }
  193. [fields release];
  194. [values release];
  195. }
  196. - (IBAction)connect:(id)sender {
  197. if (db) {
  198. [self initInterface];
  199. [db release];
  200. }
  201. db = [[MCPConnection alloc] initToHost:[hostTextField stringValue] withLogin:[userTextField stringValue] password:[passwdTextField stringValue] usingPort:[portTextField intValue] ];
  202. NSLog(@"Connect: %d", [db isConnected]);
  203. if (![db isConnected])
  204. {
  205. NSRunAlertPanel(@"Error", @"Could not connect to the mysql server!", @"OK", nil, nil);
  206. }
  207. [db queryString:@"SET NAMES utf8"];
  208. [db queryString:@"SET CHARACTER SET utf8"];
  209. [db queryString:@"SET COLLATION_CONNECTION='utf8_general_ci'"];
  210. [db setEncoding:NSUTF8StringEncoding];
  211. MCPResult *dbs = [db listDBs];
  212. NSArray *row;
  213. NSMutableArray *databases = [[NSMutableArray alloc] initWithCapacity:[dbs numOfRows]];
  214. while (row = [dbs fetchRowAsArray]) {
  215. NSDictionary *database = [[NSDictionary alloc] initWithObjectsAndKeys:[row objectAtIndex:0], @"name", nil];
  216. [databases addObject:database];
  217. [database release];
  218. }
  219. [dbsArrayController setContent:databases];
  220. [databases release];
  221. //[self showTables:nil];
  222. }
  223. - (IBAction)showTables:(id)sender
  224. {
  225. NSString *dbn;
  226. if (sender == nil && [[dbsArrayController arrangedObjects] count] > 0) {
  227. dbn = [[[dbsArrayController arrangedObjects] objectAtIndex:0] objectForKey:@"name"];
  228. }else {
  229. NSPopUpButton *pb = sender;
  230. dbn = [[NSString alloc] initWithString:[pb titleOfSelectedItem]];
  231. }
  232. if (![dbn isPresent]) {
  233. [dbn release];
  234. return;
  235. }
  236. [db selectDB:dbn];
  237. [dbn release];
  238. MCPResult *tbs = [db listTables];
  239. NSArray *row;
  240. NSMutableArray *tables = [[NSMutableArray alloc] initWithCapacity:[tbs numOfRows]];
  241. while (row = [tbs fetchRowAsArray]) {
  242. NSDictionary *table = [[NSDictionary alloc] initWithObjectsAndKeys:[row objectAtIndex:0], @"name", nil];
  243. [tables addObject:table];
  244. [table release];
  245. }
  246. [tablesArrayController setContent:tables];
  247. [tables release];
  248. [self showFields:nil];
  249. }
  250. - (IBAction)showFields:(id)sender
  251. {
  252. NSString *tablename = [[NSString alloc] initWithString:[tablesPopUpButton titleOfSelectedItem]];
  253. MCPResult *theResult = [db queryString:[NSString stringWithFormat:@"select * from %@ limit 1", tablename]];
  254. [tablename release];
  255. NSArray *theFields = [theResult fetchFieldNames];
  256. NSMutableArray *fields = [[NSMutableArray alloc] initWithCapacity:[theFields count] ];
  257. for (int i=0; i<[theFields count]; i++) {
  258. NSString *fieldName = [theFields objectAtIndex:i];
  259. FieldMapDataObject *fd = [[FieldMapDataObject alloc] initWithSqlKey:fieldName andMongoKey:fieldName];
  260. [fields addObject:fd];
  261. [fd release];
  262. }
  263. [fieldMapTableController setNsMutaryDataObj:fields];
  264. [fieldMapTableController.idTableView reloadData];
  265. [fields release];
  266. }
  267. - (void)initInterface
  268. {
  269. [dbsArrayController setContent:nil];
  270. [tablesArrayController setContent:nil];
  271. [progressIndicator setDoubleValue:0.0];
  272. [fieldMapTableController.nsMutaryDataObj removeAllObjects];
  273. [fieldMapTableController.idTableView reloadData];
  274. }
  275. @end