mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-15 16:11:42 +00:00
some optimisations
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@38466 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
fe1d368d66
commit
19a68d1abd
1 changed files with 219 additions and 41 deletions
246
Postgres.m
246
Postgres.m
|
@ -41,6 +41,7 @@
|
|||
#import <Foundation/NSProcessInfo.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSThread.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
#import <Foundation/NSUserDefaults.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
|
@ -72,6 +73,8 @@ typedef struct {
|
|||
static NSDate *future = nil;
|
||||
static NSNull *null = nil;
|
||||
|
||||
static NSTimeZone *zones[47]; // For -23 to +23 hours
|
||||
|
||||
@implementation SQLClientPostgres
|
||||
|
||||
+ (void) initialize
|
||||
|
@ -84,6 +87,10 @@ static NSNull *null = nil;
|
|||
[future retain];
|
||||
null = [NSNull null];
|
||||
[null retain];
|
||||
for (int i = -23; i <= 23; i++)
|
||||
{
|
||||
zones[i + 23] = [[NSTimeZone timeZoneForSecondsFromGMT: i * 60 * 60] retain];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,28 +478,13 @@ connectQuote(NSString *str)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned int trim(char *str)
|
||||
static inline unsigned int trim(char *str, unsigned len)
|
||||
{
|
||||
char *start = str;
|
||||
|
||||
while (isspace(*str))
|
||||
while (len > 0 && isspace(str[len - 1]))
|
||||
{
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
if (str != start)
|
||||
{
|
||||
strcpy(start, str);
|
||||
}
|
||||
str = start;
|
||||
while (*str != '\0')
|
||||
{
|
||||
str++;
|
||||
}
|
||||
while (str > start && isspace(str[-1]))
|
||||
{
|
||||
*--str = '\0';
|
||||
}
|
||||
return (str - start);
|
||||
return len;
|
||||
}
|
||||
|
||||
- (char*) parseIntoArray: (NSMutableArray *)a type: (int)t from: (char*)p
|
||||
|
@ -589,7 +581,7 @@ static unsigned int trim(char *str)
|
|||
}
|
||||
save = *p;
|
||||
*p = '\0';
|
||||
len = trim(start);
|
||||
len = trim(start, p - start);
|
||||
if (strcmp(start, "NULL") == 0)
|
||||
{
|
||||
v = null;
|
||||
|
@ -632,22 +624,24 @@ static unsigned int trim(char *str)
|
|||
return p;
|
||||
}
|
||||
|
||||
- (id) parseField: (char *)p type: (int)t
|
||||
- (id) newParseField: (char *)p type: (int)t size: (int)s
|
||||
{
|
||||
char arrayType = 0;
|
||||
|
||||
switch (t)
|
||||
{
|
||||
case 1082: // Date
|
||||
return [self dbToDateFromBuffer: p length: trim(p)];
|
||||
return [self newDateFromBuffer: p length: trim(p, s)];
|
||||
|
||||
case 1083: // Time (treat as string)
|
||||
trim(p);
|
||||
return [NSString stringWithUTF8String: p];
|
||||
s = trim(p, s);
|
||||
return [[NSString alloc] initWithBytes: p
|
||||
length: s
|
||||
encoding: NSASCIIStringEncoding];
|
||||
|
||||
case 1114: // Timestamp without time zone.
|
||||
case 1184: // Timestamp with time zone.
|
||||
return [self dbToDateFromBuffer: p length: trim(p)];
|
||||
return [self newDateFromBuffer: p length: trim(p, s)];
|
||||
|
||||
case 16: // BOOL
|
||||
if (*p == 't')
|
||||
|
@ -660,16 +654,20 @@ static unsigned int trim(char *str)
|
|||
}
|
||||
|
||||
case 17: // BYTEA
|
||||
return [self dataFromBLOB: p];
|
||||
return [[self dataFromBLOB: p] retain];
|
||||
|
||||
case 18: // "char"
|
||||
return [NSString stringWithUTF8String: p];
|
||||
return [[NSString alloc] initWithBytes: p
|
||||
length: s
|
||||
encoding: NSUTF8StringEncoding];
|
||||
|
||||
case 20: // INT8
|
||||
case 21: // INT2
|
||||
case 23: // INT4
|
||||
trim(p);
|
||||
return [NSString stringWithUTF8String: p];
|
||||
s = trim(p, s);
|
||||
return [[NSString alloc] initWithBytes: p
|
||||
length: s
|
||||
encoding: NSASCIIStringEncoding];
|
||||
break;
|
||||
|
||||
case 1182: // DATE ARRAY
|
||||
|
@ -693,7 +691,7 @@ static unsigned int trim(char *str)
|
|||
{
|
||||
NSMutableArray *a;
|
||||
|
||||
a = [NSMutableArray arrayWithCapacity: 10];
|
||||
a = [[NSMutableArray alloc] initWithCapacity: 10];
|
||||
p = [self parseIntoArray: a type: arrayType from: p];
|
||||
if ([self debugging] > 2)
|
||||
{
|
||||
|
@ -706,9 +704,11 @@ static unsigned int trim(char *str)
|
|||
default:
|
||||
if (YES == _shouldTrim)
|
||||
{
|
||||
trim(p);
|
||||
s = trim(p, s);
|
||||
}
|
||||
return [NSString stringWithUTF8String: p];
|
||||
return [[NSString alloc] initWithBytes: p
|
||||
length: s
|
||||
encoding: NSUTF8StringEncoding];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -773,6 +773,7 @@ static unsigned int trim(char *str)
|
|||
int fmod[fieldCount];
|
||||
int fformat[fieldCount];
|
||||
SQLRecordKeys *k = nil;
|
||||
int d = [self debugging];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < fieldCount; i++)
|
||||
|
@ -784,6 +785,20 @@ static unsigned int trim(char *str)
|
|||
}
|
||||
|
||||
records = [[ltype alloc] initWithCapacity: recordCount];
|
||||
|
||||
/* Create buffers to store the previous row from the
|
||||
* database and the previous objc values.
|
||||
*/
|
||||
int len[fieldCount];
|
||||
const char *ptr[fieldCount];
|
||||
id obj[fieldCount];
|
||||
|
||||
for (i = 0; i < fieldCount; i++)
|
||||
{
|
||||
len[i] = -1;
|
||||
obj[i] = nil;
|
||||
}
|
||||
|
||||
for (i = 0; i < recordCount; i++)
|
||||
{
|
||||
SQLRecord *record;
|
||||
|
@ -799,14 +814,27 @@ static unsigned int trim(char *str)
|
|||
char *p = PQgetvalue(result, i, j);
|
||||
int size = PQgetlength(result, i, j);
|
||||
|
||||
if ([self debugging] > 1)
|
||||
if (d > 1)
|
||||
{
|
||||
[self debug: @"%@ type:%d mod:%d size: %d\n",
|
||||
keys[j], ftype[j], fmod[j], size];
|
||||
}
|
||||
/* Often many rows will contain the same data in
|
||||
* one or more columns, so we check to see if the
|
||||
* value we have just read is small and identical
|
||||
* to the value in the same column of the previous
|
||||
* row. Only if it isn't do we create a new object.
|
||||
*/
|
||||
if (size != len[j] || size > 20
|
||||
|| memcmp(p, ptr[j], (size_t)len) != 0)
|
||||
{
|
||||
[obj[j] release];
|
||||
if (fformat[j] == 0) // Text
|
||||
{
|
||||
v = [self parseField: p type: ftype[j]];
|
||||
v = [self newParseField: p
|
||||
type: ftype[j]
|
||||
size: size];
|
||||
obj[j] = v;
|
||||
}
|
||||
else // Binary
|
||||
{
|
||||
|
@ -815,6 +843,7 @@ static unsigned int trim(char *str)
|
|||
keys[j], ftype[j], fmod[j], size);
|
||||
}
|
||||
}
|
||||
}
|
||||
values[j] = v;
|
||||
}
|
||||
if (nil == k)
|
||||
|
@ -839,6 +868,10 @@ static unsigned int trim(char *str)
|
|||
[records addObject: record];
|
||||
[record release];
|
||||
}
|
||||
for (i = 0; i < fieldCount; i++)
|
||||
{
|
||||
[obj[i] release];
|
||||
}
|
||||
}
|
||||
else if (PQresultStatus(result) == PGRES_COMMAND_OK)
|
||||
{
|
||||
|
@ -1196,6 +1229,151 @@ static unsigned int trim(char *str)
|
|||
return d;
|
||||
}
|
||||
|
||||
- (NSDate*) newDateFromBuffer: (char*)b length: (int)l
|
||||
{
|
||||
NSCalendarDate *d;
|
||||
NSTimeZone *zone;
|
||||
int milliseconds = 0;
|
||||
int timezone = 0;
|
||||
int day;
|
||||
int month;
|
||||
int year;
|
||||
int hour;
|
||||
int minute;
|
||||
int second;
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
year = b[i++] - '0';
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
year = year * 10 + b[i++] - '0';
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
year = year * 10 + b[i++] - '0';
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
year = year * 10 + b[i++] - '0';
|
||||
|
||||
if (i >= l || b[i++] != '-') return nil;
|
||||
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
month = b[i++] - '0';
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
month = month * 10 + b[i++] - '0';
|
||||
if (month < 1 || month > 12) return nil;
|
||||
|
||||
if (i >= l || b[i++] != '-') return nil;
|
||||
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
day = b[i++] - '0';
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
day = day * 10 + b[i++] - '0';
|
||||
if (day < 1 || day > 31) return nil;
|
||||
|
||||
if (i == l)
|
||||
{
|
||||
hour = 0;
|
||||
minute = 0;
|
||||
second = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i >= l || b[i++] != ' ') return nil;
|
||||
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
hour = b[i++] - '0';
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
hour = hour * 10 + b[i++] - '0';
|
||||
if (hour < 0 || hour > 23) return nil;
|
||||
|
||||
if (i >= l || b[i++] != ':') return nil;
|
||||
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
minute = b[i++] - '0';
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
minute = minute * 10 + b[i++] - '0';
|
||||
if (minute < 0 || minute > 59) return nil;
|
||||
|
||||
if (i >= l || b[i++] != ':') return nil;
|
||||
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
second = b[i++] - '0';
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
second = second * 10 + b[i++] - '0';
|
||||
if (second < 0 || second > 60) return nil;
|
||||
|
||||
if (i < l && '.' == b[i])
|
||||
{
|
||||
i++;
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
milliseconds = b[i++] - '0';
|
||||
milliseconds *=- 10;
|
||||
if (i < l && isdigit(b[i]))
|
||||
milliseconds += b[i++] - '0';
|
||||
milliseconds *=- 10;
|
||||
if (i < l && isdigit(b[i]))
|
||||
milliseconds += b[i++] - '0';
|
||||
while (i < l && isdigit(b[i]))
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i < l && ('+' == b[i] || '-' == b[i]))
|
||||
{
|
||||
char sign = b[i++];
|
||||
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
timezone = b[i++] - '0';
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
timezone = timezone * 10 + b[i++] - '0';
|
||||
if (timezone < 0 || timezone > 23) return nil;
|
||||
timezone *= 60; // Convert to minutes
|
||||
if (i < l && ':' == b[i])
|
||||
{
|
||||
int tzmin;
|
||||
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
tzmin = b[i++] - '0';
|
||||
if (i >= l || !isdigit(b[i])) return nil;
|
||||
tzmin = tzmin * 10 + b[i++] - '0';
|
||||
if (tzmin < 0 || tzmin > 59) return nil;
|
||||
|
||||
timezone += tzmin;
|
||||
}
|
||||
if ('-' == sign)
|
||||
timezone = -timezone;
|
||||
}
|
||||
}
|
||||
if (timezone % 60 == 0)
|
||||
{
|
||||
zone = zones[timezone / 60];
|
||||
}
|
||||
else
|
||||
{
|
||||
zone = [NSTimeZone timeZoneForSecondsFromGMT: timezone * 60];
|
||||
}
|
||||
|
||||
d = [[NSCalendarDate alloc] initWithYear: year
|
||||
month: month
|
||||
day: day
|
||||
hour: hour
|
||||
minute: minute
|
||||
second: second
|
||||
timeZone: zone];
|
||||
|
||||
if (milliseconds > 0)
|
||||
{
|
||||
NSTimeInterval ti;
|
||||
|
||||
ti = milliseconds;
|
||||
ti /= 1000.0;
|
||||
ti += [d timeIntervalSinceReferenceDate];
|
||||
d = [d initWithTimeIntervalSinceReferenceDate: ti];
|
||||
[d setTimeZone: zone];
|
||||
}
|
||||
[d setCalendarFormat: @"%Y-%m-%d %H:%M:%S %z"];
|
||||
return d;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (extra != 0)
|
||||
|
|
Loading…
Reference in a new issue