]> err.no Git - sope/blob - sope-gdl1/SQLite3/SQLiteChannel+Model.m
fixed gcc 4.0 warnings
[sope] / sope-gdl1 / SQLite3 / SQLiteChannel+Model.m
1 /* 
2    SQLiteChannel+Model.m
3
4    Copyright (C) 2003-2005 SKYRIX Software AG
5
6    Author: Helge Hess (helge.hess@skyrix.com)
7
8    This file is part of the SQLite Adaptor Library
9
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Library General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Library General Public License for more details.
19
20    You should have received a copy of the GNU Library General Public
21    License along with this library; see the file COPYING.LIB.
22    If not, write to the Free Software Foundation,
23    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25
26 #include "SQLiteChannel.h"
27 #include "NSString+SQLite.h"
28 #include "EOAttribute+SQLite.h"
29 #include "common.h"
30
31 @interface EORelationship(FixMe)
32 - (void)addJoin:(id)_join;
33 @end
34
35 @implementation SQLiteChannel(ModelFetching)
36
37 - (NSArray *)_attributesForTableName:(NSString *)_tableName {
38   NSMutableArray *attributes;
39   NSString       *sqlExpr;
40   NSArray        *resultDescription;
41   NSDictionary   *row;
42   
43   if ([_tableName length] == 0)
44     return nil;
45   
46   attributes = [self->_attributesForTableName objectForKey:_tableName];
47   if (attributes == nil) {
48 #if 1
49     // TODO: we would need to parse the SQL field of 'sqlite_master'?
50     NSLog(@"ERROR(%s): operation not supported on SQLite!",
51           __PRETTY_FUNCTION__);
52     return nil;
53 #else
54     sqlExpr = [NSString stringWithFormat:sqlExpr, _tableName];
55 #endif
56   
57     if (![self evaluateExpression:sqlExpr]) {
58       fprintf(stderr,
59               "Couldn`t evaluate column-describe '%s' on table '%s'\n",
60               [sqlExpr cString], [_tableName cString]);
61       return nil;
62     }
63   
64     resultDescription = [self describeResults];
65     attributes = [NSMutableArray arrayWithCapacity:16];
66   
67     while ((row = [self fetchAttributes:resultDescription withZone:NULL])) {
68       EOAttribute *attribute;
69       NSString    *columnName   = nil;
70       NSString    *externalType = nil;
71       NSString    *attrName     = nil;
72
73       columnName   = [[row objectForKey:@"attname"] stringValue];
74       attrName     = [columnName _sqlite3ModelMakeInstanceVarName];
75       externalType = [[row objectForKey:@"typname"] stringValue];
76     
77       attribute = [[EOAttribute alloc] init];
78       [attribute setColumnName:columnName];
79       [attribute setName:attrName];
80       [attribute setExternalType:externalType];
81       [attribute loadValueClassForExternalSQLiteType:externalType];
82       [attributes addObject:attribute];
83       [attribute release];
84     }
85     [self->_attributesForTableName setObject:attributes forKey:_tableName];
86     //NSLog(@"got attrs: %@", attributes);
87   }
88   return attributes;
89 }
90
91 - (NSArray *)_primaryKeysNamesForTableName:(NSString *)_tableName {
92   //NSArray *pkNameForTableName = nil;
93
94   if ([_tableName length] == 0)
95     return nil;
96   
97   NSLog(@"ERROR(%s): operation not supported on SQLite!", __PRETTY_FUNCTION__);
98   return nil;
99 }
100
101 - (NSArray *)_foreignKeysForTableName:(NSString *)_tableName {
102   return nil;
103 }
104
105 - (EOModel *)describeModelWithTableNames:(NSArray *)_tableNames {
106   // TODO: is this correct for SQLite?!
107   NSMutableArray *buildRelShips;
108   EOModel *model;
109   int cnt, tc;
110
111   buildRelShips = [NSMutableArray arrayWithCapacity:64];
112   model = [[[EOModel alloc] init] autorelease];
113   
114   for (cnt = 0, tc = [_tableNames count]; cnt < tc; cnt++) {
115     NSMutableDictionary *relNamesUsed;
116     NSMutableArray      *classProperties, *primaryKeyAttributes;
117     NSString *tableName;
118     NSArray  *attributes, *pkeys, *fkeys;
119     EOEntity *entity;
120     int      cnt2, ac, fkc;
121     
122     relNamesUsed         = [NSMutableDictionary dictionaryWithCapacity:16];
123     classProperties      = [NSMutableArray arrayWithCapacity:16];
124     primaryKeyAttributes = [NSMutableArray arrayWithCapacity:2];
125     tableName            = [_tableNames objectAtIndex:cnt];
126     attributes           = [self _attributesForTableName:tableName];
127     pkeys                = [self _primaryKeysNamesForTableName:tableName];
128     fkeys                = [self _foreignKeysForTableName:tableName];
129     entity               = [[[EOEntity alloc] init] autorelease];
130     ac                   = [attributes count];
131     fkc                  = [fkeys      count];
132
133     [entity setName:[tableName _sqlite3ModelMakeClassName]];
134     [entity setClassName:
135               [@"EO" stringByAppendingString:
136                   [tableName _sqlite3ModelMakeClassName]]];
137     [entity setExternalName:tableName];
138     [classProperties addObjectsFromArray:[entity classProperties]];
139     [primaryKeyAttributes addObjectsFromArray:[entity primaryKeyAttributes]];
140     [model addEntity:entity];
141
142     for (cnt2 = 0; cnt2 < ac; cnt2++) {
143       EOAttribute *attribute  = [attributes objectAtIndex:cnt2];
144       NSString    *columnName = [attribute columnName];
145
146       [entity addAttribute:attribute];
147       [classProperties addObject:attribute];
148
149       if ([pkeys containsObject:columnName])
150         [primaryKeyAttributes addObject:attribute];
151     }
152     [entity setClassProperties:classProperties];
153     [entity setPrimaryKeyAttributes:primaryKeyAttributes];
154     
155     for (cnt2 = 0; cnt2 < fkc; cnt2++) {
156       NSDictionary   *fkey;
157       NSMutableArray *classProperties;
158       NSString       *sa, *da, *dt;
159       EORelationship *rel;
160       EOJoin         *join; // TODO: fix me, EOJoin is deprecated
161       NSString       *relName;
162       
163       fkey             = [fkeys objectAtIndex:cnt2];
164       classProperties  = [NSMutableArray arrayWithCapacity:8];
165       sa               = [fkey objectForKey:@"sourceAttr"];
166       da               = [fkey objectForKey:@"targetAttr"];
167       dt               = [fkey objectForKey:@"targetTable"];
168       rel              = [[[EORelationship alloc] init] autorelease];
169
170       // TODO: fix me
171       join = [[[NSClassFromString(@"EOJoin") alloc] init] autorelease];
172
173       if ([pkeys containsObject:sa]) {
174         relName = [@"to" stringByAppendingString:
175                       [dt _sqlite3ModelMakeClassName]];
176       }
177       else {
178         relName = [@"to" stringByAppendingString:
179                     [[sa _sqlite3ModelMakeInstanceVarName]
180                          _sqlite3StringWithCapitalizedFirstChar]];
181         if ([relName hasSuffix:@"Id"]) {
182           int cLength = [relName cStringLength];
183
184           relName = [relName substringToIndex:cLength - 2];
185         }
186       }
187       if ([relNamesUsed objectForKey:relName]) {
188         int useCount = [[relNamesUsed objectForKey:relName] intValue];
189         
190         [relNamesUsed setObject:[NSNumber numberWithInt:(useCount++)] 
191                       forKey:relName];
192         relName = [NSString stringWithFormat:@"%s%d",
193                               [relName cString], useCount];
194       }
195       else
196         [relNamesUsed setObject:[NSNumber numberWithInt:0] forKey:relName];
197
198       [rel setName:relName];
199       //[rel setDestinationEntity:(EOEntity *)[dt _sqlite3ModelMakeClassName]];
200       [rel setToMany:NO];
201
202       // TODO: EOJoin is removed, fix this ...
203       [(id)join setSourceAttribute:
204              (EOAttribute *)[sa _sqlite3ModelMakeInstanceVarName]];
205       [(id)join setDestinationAttribute:
206              (EOAttribute *)[da _sqlite3ModelMakeInstanceVarName]];
207       [rel addJoin:join];
208       
209       [entity addRelationship:rel];
210       [classProperties addObjectsFromArray:[entity classProperties]];
211       [classProperties addObject:rel];
212       [entity setClassProperties:classProperties];
213       [buildRelShips addObject:rel];
214     }
215
216     [entity setAttributesUsedForLocking:[entity attributes]];
217   }
218
219   [buildRelShips makeObjectsPerformSelector:
220                    @selector(replaceStringsWithObjects)];
221   /*
222   // make reverse relations
223   {
224     int cnt, rc = [buildRelShips count];
225
226     for (cnt = 0; cnt < rc; cnt++) {
227       EORelationship *rel     = [buildRelShips objectAtIndex:cnt];
228       NSMutableArray *classProperties  = [NSMutableArray new];   
229       EORelationship *reverse = [rel reversedRelationShip];
230       EOEntity       *entity  = [rel destinationEntity];
231       NSArray        *pkeys   = [entity primaryKeyAttributes];
232       BOOL           isToMany = [reverse isToMany];
233       EOAttribute    *sa      = [[[reverse joins] lastObject] sourceAttribute];
234       NSString       *relName = nil;
235
236       if ([pkeys containsObject:sa]
237           || isToMany)
238         relName = [@"to" stringByAppendingString:
239                     [(EOEntity *)[reverse destinationEntity] name]];
240       else {
241         relName = [@"to" stringByAppendingString:
242                     [[[sa name] _sqlite3ModelMakeInstanceVarName]
243                           _sqlite3StringWithCapitalizedFirstChar]];
244         if ([relName hasSuffix:@"Id"]) {
245           int cLength = [relName cStringLength];
246
247           relName = [relName substringToIndex:cLength - 2];
248         }
249       }
250
251       if ([entity relationshipNamed:relName]) {
252         int cnt = 1;
253         NSString *numName;
254
255         numName = [NSString stringWithFormat:@"%s%d", [relName cString], cnt];
256         while ([entity relationshipNamed:numName]) {
257           cnt++;
258           numName = [NSString stringWithFormat:@"%s%d", [relName cString], cnt];
259         }
260
261         relName = numName;
262       }
263
264       [reverse setName:relName];
265
266       [entity addRelationship:reverse];
267       
268       [classProperties addObjectsFromArray:[entity classProperties]];
269       [classProperties addObject:reverse];
270       [entity setClassProperties:classProperties];
271     }
272   }
273   */
274   [model setAdaptorName:@"SQLite"];
275   [model setAdaptorClassName:@"SQLiteAdaptor"];
276   [model setConnectionDictionary:
277            [[adaptorContext adaptor] connectionDictionary]];
278   
279   return model;
280 }
281
282 - (NSArray *)describeTableNames {
283   NSMutableArray *tableNames        = nil;
284   NSArray        *resultDescription = nil;
285   NSString       *attributeName     = nil;
286   NSDictionary   *row               = nil;
287   NSString       *selectExpression  = nil;
288   
289   selectExpression = @"SELECT name FROM sqlite_master WHERE type='table'";
290   if (![self evaluateExpression:selectExpression]) {
291     fprintf(stderr, "Could not evaluate table-describe expression '%s'\n",
292             [selectExpression cString]);
293     return nil;
294   }
295   
296   resultDescription = [self describeResults];
297   attributeName = [(EOAttribute *)[resultDescription objectAtIndex:0] name];
298   tableNames    = [NSMutableArray arrayWithCapacity:16];
299   
300   while ((row = [self fetchAttributes:resultDescription withZone:NULL])!=nil)
301     [tableNames addObject:[row objectForKey:attributeName]];
302   
303   return tableNames;
304 }
305
306 @end /* SQLiteChannel(ModelFetching) */
307
308 void __link_SQLiteChannelModel() {
309   // used to force linking of object file
310   __link_SQLiteChannelModel();
311 }