Skip to content
This repository was archived by the owner on Sep 27, 2019. It is now read-only.

Commit 68a51d8

Browse files
committed
REALLY simple Date support
1 parent dc95fcb commit 68a51d8

File tree

3 files changed

+264
-112
lines changed

3 files changed

+264
-112
lines changed

src/function/date_functions.cpp

Lines changed: 151 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,17 @@
66
//
77
// Identification: src/function/date_functions.cpp
88
//
9-
// Copyright (c) 2015-2017, Carnegie Mellon University Database Group
9+
// Copyright (c) 2015-2018, Carnegie Mellon University Database Group
1010
//
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "function/date_functions.h"
1414

1515
#include <date/date.h>
1616
#include <date/iso_week.h>
17-
#include <inttypes.h>
18-
#include <time.h>
1917
#include <sys/time.h>
2018

19+
#include "codegen/runtime_functions.h"
2120
#include "common/internal_types.h"
2221
#include "type/value.h"
2322
#include "type/value_factory.h"
@@ -63,10 +62,156 @@ type::Value DateFunctions::_Now(
6362
return type::ValueFactory::GetTimestampValue(Now());
6463
}
6564

65+
int32_t DateFunctions::DateToJulian(int32_t year, int32_t month, int32_t day) {
66+
// From Postgres date2j()
67+
68+
if (month > 2) {
69+
month += 1;
70+
year += 4800;
71+
} else {
72+
month += 13;
73+
year += 4799;
74+
}
75+
76+
int32_t century = year / 100;
77+
78+
int32_t julian = year * 365 - 32167;
79+
julian += year / 4 - century + century / 4;
80+
julian += 7834 * month / 256 + day;
81+
82+
return julian;
83+
}
84+
85+
void DateFunctions::JulianToDate(int32_t julian_date, int32_t &year, int32_t &month,
86+
int32_t &day) {
87+
// From Postgres j2date()
88+
89+
uint32_t julian = static_cast<uint32_t>(julian_date);
90+
julian += 32044;
91+
92+
uint32_t quad = julian / 146097;
93+
94+
uint32_t extra = (julian - quad * 146097) * 4 + 3;
95+
julian += 60 + quad * 3 + extra / 146097;
96+
quad = julian / 1461;
97+
julian -= quad * 1461;
98+
99+
int32_t y = julian * 4 / 1461;
100+
julian = ((y != 0) ? (julian + 305) % 365 : (julian + 306) % 366) + 123;
101+
y += quad * 4;
102+
103+
// Set year
104+
year = static_cast<uint32_t>(y - 4800);
105+
quad = julian * 2141 / 65536;
106+
107+
// Set day
108+
day = julian - 7834 * quad / 256;
109+
110+
// Set month
111+
month = (quad + 10) % 12 + 1;
112+
}
113+
114+
namespace {
115+
116+
template <typename T>
117+
bool TryParseInt(const char *&data, const char *end, T &out) {
118+
static_assert(std::is_integral<T>::value,
119+
"ParseInt() must only be called with integer types");
120+
121+
// Initialize
122+
out = 0;
123+
124+
// Trim leading whitespace
125+
while (*data == ' ') {
126+
data++;
127+
}
128+
129+
// Return if no more data
130+
if (data == end) {
131+
return false;
132+
}
133+
134+
const char *snapshot = data;
135+
while (data != end) {
136+
if (*data < '0' || *data > '9') {
137+
// Not a valid integer, stop
138+
break;
139+
}
140+
141+
// Update running sum
142+
out = (out * 10) + (*data - '0');
143+
144+
// Move along
145+
data++;
146+
}
147+
148+
return snapshot != data;
149+
}
150+
151+
} // namespace
152+
66153
int32_t DateFunctions::InputDate(
67-
UNUSED_ATTRIBUTE const codegen::type::Type &type,
68-
UNUSED_ATTRIBUTE const char *data, UNUSED_ATTRIBUTE uint32_t len) {
69-
return 0;
154+
UNUSED_ATTRIBUTE const codegen::type::Type &type, const char *data,
155+
uint32_t len) {
156+
// Okay, Postgres supports a crap-tonne of different date-time and timestamp
157+
// formats. I don't want to spend time implementing them all. For now, let's
158+
// cover the most common formats: yyyy-mm-dd
159+
160+
const char *curr_ptr = data;
161+
const char *end = data + len;
162+
163+
uint32_t nums[3] = {0, 0, 0};
164+
uint32_t year, month, day;
165+
166+
for (uint32_t i = 0; i < 3; i++) {
167+
bool parsed = TryParseInt(curr_ptr, end, nums[i]);
168+
169+
bool unexpected_next_char = (*curr_ptr != '-' && *curr_ptr != '/');
170+
if (!parsed || (i != 2 && unexpected_next_char)) {
171+
goto unsupported;
172+
}
173+
174+
curr_ptr++;
175+
}
176+
177+
// Looks okay ... let's check the components.
178+
year = nums[0], month = nums[1], day = nums[2];
179+
180+
if (month == 0 || month > 12 || day == 0 || day > 31) {
181+
goto unsupported;
182+
}
183+
184+
switch (month) {
185+
case 2: {
186+
uint32_t days_in_feb =
187+
((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 29 : 28;
188+
if (day > days_in_feb) {
189+
goto unsupported;
190+
}
191+
break;
192+
}
193+
case 4:
194+
case 6:
195+
case 9:
196+
case 11: {
197+
if (day > 30) {
198+
goto unsupported;
199+
}
200+
break;
201+
}
202+
default: {
203+
if (day > 31) {
204+
goto unsupported;
205+
}
206+
break;
207+
}
208+
}
209+
210+
return DateToJulian(year, month, day);
211+
212+
unsupported:
213+
codegen::RuntimeFunctions::ThrowInvalidInputStringException();
214+
__builtin_unreachable();
70215
}
71216

72217
} // namespace expression

src/include/function/date_functions.h

Lines changed: 76 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,76 @@
1-
//===----------------------------------------------------------------------===//
2-
//
3-
// Peloton
4-
//
5-
// date_functions.h
6-
//
7-
// Identification: src/include/function/date_functions.h
8-
//
9-
// Copyright (c) 2015-2017, Carnegie Mellon University Database Group
10-
//
11-
//===----------------------------------------------------------------------===//
12-
13-
#pragma once
14-
15-
#include <string>
16-
#include <vector>
17-
18-
#include "common/logger.h"
19-
#include "common/internal_types.h"
20-
#include "type/value.h"
21-
22-
namespace peloton {
23-
24-
namespace codegen {
25-
namespace type {
26-
class Type;
27-
} // namespace type
28-
} // namespace codegen
29-
30-
namespace function {
31-
32-
class DateFunctions {
33-
public:
34-
/**
35-
* Function used to return the current date/time. Normally called at the start
36-
* of a transaction, and consistent throughout its duration.
37-
*
38-
* @return The current date at the time of invocation
39-
*/
40-
static int64_t Now();
41-
static type::Value _Now(const std::vector<type::Value> &args);
42-
43-
/**
44-
*
45-
* @param data
46-
* @param len
47-
* @return
48-
*/
49-
static int32_t InputDate(const codegen::type::Type &type, const char *data,
50-
uint32_t len);
51-
};
52-
53-
} // namespace function
54-
} // namespace peloton
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Peloton
4+
//
5+
// date_functions.h
6+
//
7+
// Identification: src/include/function/date_functions.h
8+
//
9+
// Copyright (c) 2015-2018, Carnegie Mellon University Database Group
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#pragma once
14+
15+
#include <cstdint>
16+
#include <vector>
17+
18+
#include "type/value.h"
19+
20+
namespace peloton {
21+
22+
namespace codegen {
23+
namespace type {
24+
class Type;
25+
} // namespace type
26+
} // namespace codegen
27+
28+
namespace function {
29+
30+
class DateFunctions {
31+
public:
32+
/**
33+
* Function used to return the current date/time. Normally called at the start
34+
* of a transaction, and consistent throughout its duration.
35+
*
36+
* @return The current date at the time of invocation
37+
*/
38+
static int64_t Now();
39+
static type::Value _Now(const std::vector<type::Value> &args);
40+
41+
/**
42+
* Convert the given input into a Julian date format.
43+
*
44+
* @param year The year
45+
* @param month The month (1-based)
46+
* @param day The day (1-based)
47+
* @return The equivalent 32-bit integer representation of the date
48+
*/
49+
static int32_t DateToJulian(int32_t year, int32_t month, int32_t day);
50+
51+
/**
52+
* Decompose the given 32-bit Julian date value into year, month, and day
53+
* components.
54+
*
55+
* @param julian_date The julian date
56+
* @param year[out] Where the year is written
57+
* @param month[out] Where the result month is written
58+
* @param day[out] Where the result day is written
59+
*/
60+
static void JulianToDate(int32_t julian_date, int32_t &year, int32_t &month,
61+
int32_t &day);
62+
63+
/**
64+
* Convert the given input string into a date.
65+
*
66+
* @param data A pointer to a string representation of a date
67+
* @param len The length of the string
68+
* @return A suitable date representation of the given input string that can
69+
* be stored in the data tables. This typically means a Julian date.
70+
*/
71+
static int32_t InputDate(const codegen::type::Type &type, const char *data,
72+
uint32_t len);
73+
};
74+
75+
} // namespace function
76+
} // namespace peloton

0 commit comments

Comments
 (0)