~ubuntu-branches/ubuntu/oneiric/postgresql-pljava/oneiric-201109061811

« back to all changes in this revision

Viewing changes to src/C/pljava/type/Timestamp.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Eisentraut
  • Date: 2006-06-26 10:44:55 UTC
  • mfrom: (1.1.1 upstream) (3.1.1 edgy)
  • Revision ID: james.westby@ubuntu.com-20060626104455-135i9wosat2k8vvt
Tags: 1.3.0-1
* New upstream release (closes: #375199)
* Built for postgresql 8.1 (closes: #339641)
* Rebuilt for new libgcj library (closes: #369986)
* Updated copyright file
* Updated standards version
* Made use of cdbs simple patchsys

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 2004, 2005 TADA AB - Taby Sweden
 
2
 * Copyright (c) 2004, 2005, 2006 TADA AB - Taby Sweden
3
3
 * Distributed under the terms shown in the file COPYRIGHT
4
4
 * found in the root folder of this project or at
5
5
 * http://eng.tada.se/osprojects/COPYRIGHT.html
30
30
static jmethodID s_Timestamp_getTime;
31
31
static jmethodID s_Timestamp_setNanos;
32
32
 
33
 
static Type s_Timestamp;
34
33
static TypeClass s_TimestampClass;
35
 
 
36
 
static Type s_Timestamptz;
37
34
static TypeClass s_TimestamptzClass;
38
35
 
39
36
static bool _Timestamp_canReplaceType(Type self, Type other)
40
37
{
41
 
        return other->m_class == s_TimestampClass || other->m_class == s_TimestamptzClass;
 
38
        TypeClass cls = Type_getClass(other);
 
39
        return Type_getClass(self) == cls || cls == s_TimestamptzClass;
42
40
}
43
41
 
44
 
static jvalue Timestamp_coerceDatumTZ_id(Type self, JNIEnv* env, Datum arg, bool tzAdjust)
 
42
static jvalue Timestamp_coerceDatumTZ_id(Type self, Datum arg, bool tzAdjust)
45
43
{
46
44
        jvalue result;
47
45
        int64 ts = DatumGetInt64(arg);
 
46
        int   tz = Timestamp_getTimeZone_id(ts);
48
47
 
49
48
        /* Expect number of microseconds since 01 Jan 2000
50
49
         */
51
50
        jlong mSecs = ts / 1000;                        /* Convert to millisecs */
52
51
        jint  uSecs = (jint)(ts % 1000);        /* preserve remaining microsecs */
53
52
        if(tzAdjust)
54
 
                mSecs += Timestamp_getTimeZone(ts) * 1000;/* Adjust from local time to UTC */
 
53
                mSecs += tz * 1000;                             /* Adjust from local time to UTC */
55
54
        mSecs += EPOCH_DIFF * 1000;                     /* Adjust for diff between Postgres and Java (Unix) */
56
 
        result.l = PgObject_newJavaObject(env, s_Timestamp_class, s_Timestamp_init, mSecs);
 
55
        result.l = JNI_newObject(s_Timestamp_class, s_Timestamp_init, mSecs);
57
56
        if(uSecs != 0)
58
 
                (*env)->CallIntMethod(env, result.l, s_Timestamp_setNanos, uSecs * 1000);
 
57
                JNI_callVoidMethod(result.l, s_Timestamp_setNanos, uSecs * 1000);
59
58
        return result;
60
59
}
61
60
 
62
 
static jvalue Timestamp_coerceDatumTZ_dd(Type self, JNIEnv* env, Datum arg, bool tzAdjust)
 
61
static jvalue Timestamp_coerceDatumTZ_dd(Type self, Datum arg, bool tzAdjust)
63
62
{
64
63
        jlong mSecs;
65
64
        jint  uSecs;
66
65
        jvalue result;
67
66
        double tmp;
68
67
        double ts = DatumGetFloat8(arg);
 
68
        int    tz = Timestamp_getTimeZone_dd(ts);
69
69
 
70
70
        /* Expect <seconds since Jan 01 2000>.<fractions of seconds>
71
71
         */
72
72
        if(tzAdjust)
73
 
                ts += Timestamp_getTimeZone(ts);/* Adjust from local time to UTC */
 
73
                ts += tz;                                               /* Adjust from local time to UTC */
74
74
        ts += EPOCH_DIFF;                                       /* Adjust for diff between Postgres and Java (Unix) */
75
75
        ts *= 1000.0;                                           /* Convert to millisecs */
76
76
        tmp = floor(ts);
77
77
        mSecs = (jlong)tmp;
78
78
        uSecs = ((ts - tmp) * 1000.0);          /* Preserve remaining microsecs */
79
 
        result.l = PgObject_newJavaObject(env, s_Timestamp_class, s_Timestamp_init, mSecs);
 
79
        result.l = JNI_newObject(s_Timestamp_class, s_Timestamp_init, mSecs);
80
80
        if(uSecs != 0)
81
 
                (*env)->CallIntMethod(env, result.l, s_Timestamp_setNanos, uSecs * 1000);
 
81
                JNI_callVoidMethod(result.l, s_Timestamp_setNanos, uSecs * 1000);
82
82
        return result;
83
83
}
84
84
 
85
 
static jvalue Timestamp_coerceDatumTZ(Type self, JNIEnv* env, Datum arg, bool tzAdjust)
 
85
static jvalue Timestamp_coerceDatumTZ(Type self, Datum arg, bool tzAdjust)
86
86
{
87
87
        return integerDateTimes
88
 
                ? Timestamp_coerceDatumTZ_id(self, env, arg, tzAdjust)
89
 
                : Timestamp_coerceDatumTZ_dd(self, env, arg, tzAdjust);
 
88
                ? Timestamp_coerceDatumTZ_id(self, arg, tzAdjust)
 
89
                : Timestamp_coerceDatumTZ_dd(self, arg, tzAdjust);
90
90
}
91
91
 
92
 
static Datum Timestamp_coerceObjectTZ_id(Type self, JNIEnv* env, jobject jts, bool tzAdjust)
 
92
static Datum Timestamp_coerceObjectTZ_id(Type self, jobject jts, bool tzAdjust)
93
93
{
94
94
        int64 ts;
95
 
        jlong mSecs = (*env)->CallLongMethod(env, jts, s_Timestamp_getTime);
96
 
        jint  nSecs = (*env)->CallIntMethod(env, jts, s_Timestamp_getNanos);
 
95
        jlong mSecs = JNI_callLongMethod(jts, s_Timestamp_getTime);
 
96
        jint  nSecs = JNI_callIntMethod(jts, s_Timestamp_getNanos);
97
97
        mSecs -= ((jlong)EPOCH_DIFF) * 1000L;
98
98
        ts  = mSecs * 1000L; /* Convert millisecs to microsecs */
99
99
        if(nSecs != 0)
100
100
                ts += nSecs / 1000;     /* Convert nanosecs  to microsecs */
101
101
        if(tzAdjust)
102
 
                ts -= ((jlong)Timestamp_getTimeZone(ts)) * 1000000L; /* Adjust from UTC to local time */
 
102
                ts -= ((jlong)Timestamp_getTimeZone_id(ts)) * 1000000L; /* Adjust from UTC to local time */
103
103
        return Int64GetDatum(ts);
104
104
}
105
105
 
106
 
static Datum Timestamp_coerceObjectTZ_dd(Type self, JNIEnv* env, jobject jts, bool tzAdjust)
 
106
static Datum Timestamp_coerceObjectTZ_dd(Type self, jobject jts, bool tzAdjust)
107
107
{
108
108
        double ts;
109
 
        jlong mSecs = (*env)->CallLongMethod(env, jts, s_Timestamp_getTime);
110
 
        jint  nSecs = (*env)->CallIntMethod(env, jts, s_Timestamp_getNanos);
 
109
        jlong mSecs = JNI_callLongMethod(jts, s_Timestamp_getTime);
 
110
        jint  nSecs = JNI_callIntMethod(jts, s_Timestamp_getNanos);
111
111
        ts = ((double)mSecs) / 1000.0; /* Convert to seconds */
112
112
        ts -= EPOCH_DIFF;
113
113
        if(nSecs != 0)
114
114
                ts += ((double)nSecs) / 1000000000.0;   /* Convert to seconds */
115
115
        if(tzAdjust)
116
 
                ts -= Timestamp_getTimeZone(ts); /* Adjust from UTC to local time */
 
116
                ts -= Timestamp_getTimeZone_dd(ts); /* Adjust from UTC to local time */
117
117
        return Float8GetDatum(ts);
118
118
}
119
119
 
120
 
static Datum Timestamp_coerceObjectTZ(Type self, JNIEnv* env, jobject jts, bool tzAdjust)
 
120
static Datum Timestamp_coerceObjectTZ(Type self, jobject jts, bool tzAdjust)
121
121
{
122
122
        return integerDateTimes
123
 
                ? Timestamp_coerceObjectTZ_id(self, env, jts, tzAdjust)
124
 
                : Timestamp_coerceObjectTZ_dd(self, env, jts, tzAdjust);
125
 
}
126
 
 
127
 
static jvalue _Timestamp_coerceDatum(Type self, JNIEnv* env, Datum arg)
128
 
{
129
 
        return Timestamp_coerceDatumTZ(self, env, arg, true);
130
 
}
131
 
 
132
 
static Datum _Timestamp_coerceObject(Type self, JNIEnv* env, jobject ts)
133
 
{
134
 
        return Timestamp_coerceObjectTZ(self, env, ts, true);
 
123
                ? Timestamp_coerceObjectTZ_id(self, jts, tzAdjust)
 
124
                : Timestamp_coerceObjectTZ_dd(self, jts, tzAdjust);
 
125
}
 
126
 
 
127
static jvalue _Timestamp_coerceDatum(Type self, Datum arg)
 
128
{
 
129
        return Timestamp_coerceDatumTZ(self, arg, true);
 
130
}
 
131
 
 
132
static Datum _Timestamp_coerceObject(Type self, jobject ts)
 
133
{
 
134
        return Timestamp_coerceObjectTZ(self, ts, true);
135
135
}
136
136
 
137
137
/* 
138
138
 * Timestamp with time zone. Basically same as Timestamp but postgres will pass
139
139
 * this one in GMT timezone so there's no without ajustment for time zone.
140
140
 */
141
 
static jvalue _Timestamptz_coerceDatum(Type self, JNIEnv* env, Datum arg)
142
 
{
143
 
        return Timestamp_coerceDatumTZ(self, env, arg, false);
144
 
}
145
 
 
146
 
static Datum _Timestamptz_coerceObject(Type self, JNIEnv* env, jobject ts)
147
 
{
148
 
        return Timestamp_coerceObjectTZ(self, env, ts, false);
149
 
}
150
 
 
151
 
static Type Timestamp_obtain(Oid typeId)
152
 
{
153
 
        return s_Timestamp;
154
 
}
155
 
 
156
 
static Type Timestamptz_obtain(Oid typeId)
157
 
{
158
 
        return s_Timestamptz;
159
 
}
160
 
 
161
 
int Timestamp_getTimeZone(Timestamp ts)
162
 
{
163
 
#if (PGSQL_MAJOR_VER == 7 && PGSQL_MINOR_VER < 5)
164
 
        struct tm tmp_tm;
 
141
static bool _Timestamptz_canReplaceType(Type self, Type other)
 
142
{
 
143
        TypeClass cls = Type_getClass(other);
 
144
        return Type_getClass(self) == cls || cls == s_TimestampClass;
 
145
}
 
146
 
 
147
static jvalue _Timestamptz_coerceDatum(Type self, Datum arg)
 
148
{
 
149
        return Timestamp_coerceDatumTZ(self, arg, false);
 
150
}
 
151
 
 
152
static Datum _Timestamptz_coerceObject(Type self, jobject ts)
 
153
{
 
154
        return Timestamp_coerceObjectTZ(self, ts, false);
 
155
}
 
156
 
 
157
#if !(PGSQL_MAJOR_VER == 8 && PGSQL_MINOR_VER == 0)
 
158
extern DLLIMPORT pg_tz* global_timezone;
 
159
#endif
 
160
 
 
161
static int Timestamp_getTimeZone(pg_time_t time)
 
162
{
 
163
#if (PGSQL_MAJOR_VER == 8 && PGSQL_MINOR_VER == 0)
 
164
        struct pg_tm* tx = pg_localtime(&time);
165
165
#else
166
 
        struct pg_tm tmp_tm;
 
166
        struct pg_tm* tx = pg_localtime(&time, global_timezone);
167
167
#endif
168
 
        fsec_t fsec;
169
 
        int tz = 0;
170
 
        timestamp2tm(ts, &tz, &tmp_tm, &fsec, NULL);
171
 
        return tz;
172
 
}
173
 
 
174
 
int Timestamp_getCurrentTimeZone(void)
175
 
{
176
 
        int tz;
177
 
        int usec = 0;
178
 
        AbsoluteTime sec = GetCurrentAbsoluteTimeUsec(&usec);
179
 
        tz = Timestamp_getTimeZone(AbsoluteTimeUsecToTimestampTz(sec, usec));
180
 
        return tz;
181
 
}
182
 
 
183
 
/* Make this datatype available to the postgres system.
184
 
 */
185
 
extern Datum Timestamp_initialize(PG_FUNCTION_ARGS);
186
 
PG_FUNCTION_INFO_V1(Timestamp_initialize);
187
 
Datum Timestamp_initialize(PG_FUNCTION_ARGS)
188
 
{
189
 
        JNIEnv* env = (JNIEnv*)PG_GETARG_POINTER(0);
190
 
 
191
 
        s_Timestamp_class = (*env)->NewGlobalRef(
192
 
                                                env, PgObject_getJavaClass(env, "java/sql/Timestamp"));
193
 
        s_Timestamp_init = PgObject_getJavaMethod(
194
 
                                                env, s_Timestamp_class, "<init>", "(J)V");
195
 
        s_Timestamp_getNanos = PgObject_getJavaMethod(
196
 
                                                env, s_Timestamp_class, "getNanos", "()I");
197
 
        s_Timestamp_getTime  = PgObject_getJavaMethod(
198
 
                                                env, s_Timestamp_class, "getTime",  "()J");
199
 
        s_Timestamp_setNanos = PgObject_getJavaMethod(
200
 
                                                env, s_Timestamp_class, "setNanos", "(I)V");
201
 
 
202
 
        s_TimestampClass = TypeClass_alloc("type.Timestamp");
203
 
        s_TimestampClass->JNISignature   = "Ljava/sql/Timestamp;";
204
 
        s_TimestampClass->javaTypeName   = "java.sql.Timestamp";
205
 
        s_TimestampClass->canReplaceType = _Timestamp_canReplaceType;
206
 
        s_TimestampClass->coerceDatum    = _Timestamp_coerceDatum;
207
 
        s_TimestampClass->coerceObject   = _Timestamp_coerceObject;
208
 
        s_Timestamp = TypeClass_allocInstance(s_TimestampClass, TIMESTAMPOID);
209
 
 
210
 
        s_TimestamptzClass = TypeClass_alloc("type.Timestamptz");
211
 
        s_TimestamptzClass->JNISignature   = "Ljava/sql/Timestamp;";
212
 
        s_TimestamptzClass->javaTypeName   = "java.sql.Timestamp";
213
 
        s_TimestamptzClass->canReplaceType = _Timestamp_canReplaceType;
214
 
        s_TimestamptzClass->coerceDatum    = _Timestamptz_coerceDatum;
215
 
        s_TimestamptzClass->coerceObject   = _Timestamptz_coerceObject;
216
 
        s_Timestamptz = TypeClass_allocInstance(s_TimestamptzClass, TIMESTAMPTZOID);
217
 
 
218
 
        Type_registerPgType(TIMESTAMPOID, Timestamp_obtain);
219
 
        Type_registerPgType(TIMESTAMPTZOID, Timestamptz_obtain);
220
 
        Type_registerJavaType("java.sql.Timestamp", Timestamptz_obtain);
221
 
        PG_RETURN_VOID();
 
168
        return -tx->tm_gmtoff;
 
169
}
 
170
 
 
171
int32 Timestamp_getTimeZone_id(int64 dt)
 
172
{
 
173
        return Timestamp_getTimeZone(
 
174
                (dt / INT64CONST(1000000) + (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * 86400));
 
175
}
 
176
int32 Timestamp_getTimeZone_dd(double dt)
 
177
{
 
178
        return Timestamp_getTimeZone(
 
179
                (pg_time_t)rint(dt + (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * 86400));
 
180
}
 
181
 
 
182
int32 Timestamp_getCurrentTimeZone(void)
 
183
{
 
184
        return Timestamp_getTimeZone((pg_time_t)GetCurrentAbsoluteTime());
 
185
}
 
186
 
 
187
extern void Timestamp_initialize(void);
 
188
void Timestamp_initialize(void)
 
189
{
 
190
        TypeClass cls;
 
191
        s_Timestamp_class = JNI_newGlobalRef(PgObject_getJavaClass("java/sql/Timestamp"));
 
192
        s_Timestamp_init = PgObject_getJavaMethod(s_Timestamp_class, "<init>", "(J)V");
 
193
        s_Timestamp_getNanos = PgObject_getJavaMethod(s_Timestamp_class, "getNanos", "()I");
 
194
        s_Timestamp_getTime  = PgObject_getJavaMethod(s_Timestamp_class, "getTime",  "()J");
 
195
        s_Timestamp_setNanos = PgObject_getJavaMethod(s_Timestamp_class, "setNanos", "(I)V");
 
196
 
 
197
        cls = TypeClass_alloc("type.Timestamp");
 
198
        cls->JNISignature   = "Ljava/sql/Timestamp;";
 
199
        cls->javaTypeName   = "java.sql.Timestamp";
 
200
        cls->canReplaceType = _Timestamp_canReplaceType;
 
201
        cls->coerceDatum    = _Timestamp_coerceDatum;
 
202
        cls->coerceObject   = _Timestamp_coerceObject;
 
203
        Type_registerType(0, TypeClass_allocInstance(cls, TIMESTAMPOID));
 
204
        s_TimestampClass = cls;
 
205
 
 
206
        cls = TypeClass_alloc("type.Timestamptz");
 
207
        cls->JNISignature   = "Ljava/sql/Timestamp;";
 
208
        cls->javaTypeName   = "java.sql.Timestamp";
 
209
        cls->canReplaceType = _Timestamptz_canReplaceType;
 
210
        cls->coerceDatum    = _Timestamptz_coerceDatum;
 
211
        cls->coerceObject   = _Timestamptz_coerceObject;
 
212
        Type_registerType("java.sql.Timestamp", TypeClass_allocInstance(cls, TIMESTAMPTZOID));
 
213
        s_TimestamptzClass = cls;
222
214
}