]> err.no Git - sope/blob - sope-gdl1/FrontBase2/FBAdaptor+Types.m
added missing inline pathes
[sope] / sope-gdl1 / FrontBase2 / FBAdaptor+Types.m
1 /* 
2    FBAdaptor+Types.m
3
4    Copyright (C) 1999 MDlink online service center GmbH and Helge Hess
5
6    Author: Helge Hess (helge.hess@mdlink.de)
7
8    This file is part of the FB 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 // $Id: FBAdaptor+Types.m 1 2004-08-20 10:38:46Z znek $
26
27 #import "common.h"
28 #include "FrontBase2Adaptor.h"
29 #include "FBChannel.h"
30 #include "FBContext.h"
31
32 @interface FrontBase2Adaptor(DomainResolver)
33 - (BOOL)fetchDomainInfo;
34 @end
35
36 @implementation FrontBase2Adaptor(DomainResolver)
37
38 typedef struct _InternalTypeMapping {
39   int      code;
40   NSString *name;
41 } InternalTypeMapping;
42
43 static InternalTypeMapping internalTypeMappings[] = {
44   { FB_PrimaryKey,   @"PRIMARYKEY" },
45   { FB_Boolean,      @"BOOLEAN"  },
46   { FB_Integer,      @"INTEGER"  },
47   { FB_SmallInteger, @"SMALLINT" },
48   { FB_Float,        @"FLOAT"    },
49   { FB_Real,         @"REAL"     },
50   { FB_Double,       @"DOUBLE"   },
51   { FB_Numeric,      @"NUMERIC"  },
52   { FB_Decimal,      @"DECIMAL"  },
53   { FB_Character,    @"CHAR"     },
54   { FB_VCharacter,   @"VARCHAR"  },
55   { FB_Bit,          @"BIT"      },
56   { FB_VBit,         @"VARBIT"   },
57   { FB_Date,         @"DATE"     },
58   { FB_Time,         @"TIME"     },
59   { FB_TimeTZ,       @"TIME WITH TIME ZONE"      },
60   { FB_Timestamp,    @"TIMESTAMP"                },
61   { FB_TimestampTZ,  @"TIMESTAMP WITH TIME ZONE" },
62   { FB_YearMonth,    @"INTERVAL YEAR TO MONTH"   },
63   { FB_DayTime,      @"INTERVAL DAY TO SECOND"   },
64   { FB_CLOB,         @"CLOB" },
65   { FB_BLOB,         @"BLOB" },
66   { -1, nil } // end marker
67 };
68
69 static NSString *DomainQuery =
70   @"SELECT \"DOMAIN_NAME\" FROM INFORMATION_SCHEMA.domains";
71
72 - (void)_resetTypeMapping {
73   if (self->typeNameToCode) {
74     NSFreeMapTable(self->typeNameToCode);
75     self->typeNameToCode = NULL;
76   }
77   if (self->typeCodeToName) {
78     NSFreeMapTable(self->typeCodeToName);
79     self->typeCodeToName = NULL;
80   }
81 }
82
83 - (void)_loadStandardTypes {
84   register InternalTypeMapping *mapping;
85   
86   if (self->typeNameToCode == NULL) {
87     self->typeNameToCode = NSCreateMapTable(NSObjectMapKeyCallBacks,
88                                             NSIntMapValueCallBacks,
89                                             64);
90   }
91   if (self->typeCodeToName == NULL) {
92     self->typeCodeToName = NSCreateMapTable(NSIntMapKeyCallBacks,
93                                             NSObjectMapValueCallBacks,
94                                             64);
95   }
96
97   mapping = &(internalTypeMappings[1]);
98
99   while (mapping->name != nil) {
100     NSMapInsert(self->typeCodeToName,
101                 (void *)(mapping->code),
102                 (void *)mapping->name);
103     NSMapInsert(self->typeNameToCode,
104                 (void *)mapping->name,
105                 (void *)(mapping->code));
106     mapping++;
107   }
108 }
109
110 - (BOOL)fetchDomainInfo {
111   FrontBaseContext *ctx;
112   FrontBaseChannel *channel;
113   BOOL result;
114
115   if (self->typeNameToCode == NULL)
116     [self _loadStandardTypes];
117
118   result  = NO;
119   ctx     = (FrontBaseContext *)[self createAdaptorContext];
120   channel = (FrontBaseChannel *)[ctx  createAdaptorChannel];
121
122   if ([channel openChannel]) {
123     if ([ctx beginTransaction]) {
124       if ([channel evaluateExpression:DomainQuery]) {
125         NSArray        *attributes;
126         NSDictionary   *record;
127         NSMutableArray *domains;
128
129         attributes = [channel describeResults];
130         domains    = nil;
131
132         while ((record = [channel fetchAttributes:attributes withZone:NULL])) {
133           NSString *domainName;
134
135           if ((domainName = [record objectForKey:@"domainName"])) {
136             if (![domainName hasPrefix:@"T_"])
137               continue;
138             
139             if (domains == nil)
140               domains = [NSMutableArray arrayWithCapacity:32];
141             [domains addObject:domainName];
142           }
143           else
144             NSLog(@"no domain name in record %@ ?", record);
145         }
146
147         /* no get the meta-info of the domains */
148
149         if ([domains count] > 0) {
150           /* we need to resolve domains, construct a VALUES expression .. */
151           NSMutableString *expr;
152           NSEnumerator *e;
153           NSString     *domainName;
154           BOOL         isFirst = YES;
155
156           expr = [NSMutableString stringWithCapacity:512];
157           [expr appendString:@"VALUES("];
158           
159           e = [domains objectEnumerator];
160           while ((domainName = [e nextObject])) {
161             if (isFirst) isFirst = NO;
162             else [expr appendString:@","];
163
164             [expr appendString:@"CAST(NULL AS \""];
165             [expr appendString:domainName];
166             [expr appendString:@"\")"];
167           }
168
169           [expr appendString:@")"];
170
171           //NSLog(@"expr: %@", expr);
172           
173           /* now execute expression */
174
175           if ([channel evaluateExpression:expr]) {
176             int *dc = channel->datatypeCodes;
177             int i;
178
179             for (i = 0; i < channel->numberOfColumns; i++) {
180               if (dc[i] > 0) {
181                 NSString *domainName;
182
183                 domainName = [[domains objectAtIndex:i] uppercaseString];
184                 
185                 //NSMapInsert(self->typeCodeToName, (void *)dc[i], domainName);
186                 NSMapInsert(self->typeNameToCode, domainName, (void *)dc[i]);
187 #if 0
188                 NSLog(@"domain %@ is code %i type %@",
189                       domainName,
190                       dc[i],
191                       NSMapGet(self->typeCodeToName, (void*)dc[i]));
192 #endif
193               }
194             }
195             
196             [channel cancelFetch];
197             
198             result = YES;
199             if (![ctx commitTransaction])
200               NSLog(@"couldn't common tx for domain-resolver ..");
201           }
202           else
203             NSLog(@"couldn't evaluate expression: %@", expr);
204         }
205       }
206       else
207         NSLog(@"couldn't evaluate expression: %@", DomainQuery);
208       if (!result) [ctx rollbackTransaction];
209     }
210     else
211       NSLog(@"couldn't begin tx for domain-resolver ..");
212
213     [channel closeChannel];
214   }
215   else
216     NSLog(@"couldn't open channel for domain-resolver ..");
217   
218   return result;
219 }
220
221 @end
222
223 @implementation FrontBase2Adaptor(ExternalTyping)
224
225 - (int)typeCodeForExternalName:(NSString *)_typeName {
226   int code;
227
228   _typeName = [_typeName uppercaseString];
229   
230   if (self->typeNameToCode == NULL)
231     [self fetchDomainInfo];
232
233   if (self->typeNameToCode == NULL)
234     return FB_VCharacter;
235
236   if ((code = (int)NSMapGet(self->typeNameToCode, _typeName)))
237     return code;
238
239   return FB_VCharacter;
240 }
241
242 - (NSString *)externalNameForTypeCode:(int)_typeCode {
243   if (_typeCode == 0)
244     return nil;
245
246   if (self->typeCodeToName == NULL)
247     [self fetchDomainInfo];
248   
249   return NSMapGet(self->typeCodeToName, (void *)_typeCode);
250 }
251
252 - (BOOL)isInternalBlobType:(int)_type {
253   switch (_type) {
254     case FB_BLOB:
255     case FB_CLOB:
256       return YES;
257
258     default:
259       return NO;
260   }
261 }
262
263 - (BOOL)isBlobAttribute:(EOAttribute *)_attr {
264   int fbType;
265   
266   NSAssert(_attr, @"missing attribute parameter");
267
268   fbType = [self typeCodeForExternalName:[_attr externalType]];
269   
270   return [self isInternalBlobType:fbType];
271 }
272
273 - (BOOL)isValidQualifierType:(NSString *)_typeName {
274   switch ([self typeCodeForExternalName:_typeName]) {
275     case FB_BLOB:
276     case FB_CLOB:
277       return NO;
278
279     default:
280       return YES;
281   }
282 }
283
284 - (BOOL)attributeAllowedInDistinctSelects:(EOAttribute *)_attr {
285   NSAssert(_attr, @"missing attribute parameter");
286   return YES;
287 }
288
289 @end