244 lines
6.4 KiB
C
244 lines
6.4 KiB
C
/************************************************************************
|
|
Copyright (c) 2021 OceanBase.
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02111-1301, USA
|
|
|
|
Part of this code includes code from PHP's mysqlnd extension
|
|
(written by Andrey Hristov, Georg Richter and Ulf Wendel), freely
|
|
|
|
*************************************************************************/
|
|
#include "mysql.h"
|
|
#include <stdint.h>
|
|
|
|
#define DATE_PART_CNT 3
|
|
#define TIME_PART_CNT 4
|
|
#define OTHER_PART_CNT 4
|
|
#define DATETIME_PART_CNT (DATE_PART_CNT + TIME_PART_CNT)
|
|
#define ORACLE_DATE_PART_CNT (DATE_PART_CNT + TIME_PART_CNT - 1)
|
|
#define TOTAL_PART_CNT (DATETIME_PART_CNT + OTHER_PART_CNT)
|
|
#define DT_YEAR 0
|
|
#define DT_MON 1
|
|
#define DT_MDAY 2
|
|
|
|
#define DT_HOUR 3
|
|
#define DT_MIN 4
|
|
#define DT_SEC 5
|
|
#define DT_USEC 6
|
|
|
|
#define DT_DATE 7
|
|
#define DT_YDAY 8
|
|
#define DT_WDAY 9
|
|
#define DT_OFFSET_MIN 10
|
|
|
|
#define OB_MAX_TZ_ABBR_LEN 32
|
|
#define OB_MAX_TZ_NAME_LEN 64
|
|
|
|
//18446744073709551615
|
|
#define MAX_UINT64_STR_LEN 20
|
|
#define MAX_DIGITS10_STR_SIZE MAX_UINT64_STR_LEN + 3
|
|
|
|
#define DT_TYPE_DATE (1UL << 0)
|
|
#define DT_TYPE_TIME (1UL << 1)
|
|
#define DT_WEEK_SUN_BEGIN (1UL << 5) // sunday is the first day of week, otherwise monday.
|
|
#define DT_WEEK_ZERO_BEGIN (1UL << 6) // week num will begin with 0, otherwise 1.
|
|
#define DT_WEEK_GE_4_BEGIN (1UL << 7) // week which has 4 or more days is week 1, otherwise has
|
|
#define DT_TYPE_ORACLE (1UL << 8) //oracle timestamp to nanosecond (nano, tz, ltz)
|
|
// the first sunday of monday.
|
|
#define DT_TYPE_TIMEZONE (1UL << 10) //oracle timestamp with time zone (tz)
|
|
|
|
#define DT_TYPE_DATETIME (DT_TYPE_DATE | DT_TYPE_TIME)
|
|
|
|
#define IS_SUN_BEGIN(mode) ((DT_WEEK_SUN_BEGIN & (mode)) ? 1 : 0)
|
|
#define IS_ZERO_BEGIN(mode) ((DT_WEEK_ZERO_BEGIN & (mode)) ? 1 : 0)
|
|
#define IS_GE_4_BEGIN(mode) ((DT_WEEK_GE_4_BEGIN & (mode)) ? 1 : 0)
|
|
#define HAS_TYPE_ORACLE(mode) ((DT_TYPE_ORACLE & (mode)) ? 1 : 0)
|
|
#define HAS_TYPE_TIMEZONE(mode) ((DT_TYPE_TIMEZONE & (mode)) ? 1 : 0)
|
|
|
|
#define DAYS_PER_WEEK 7
|
|
#define MONS_PER_YEAR 12
|
|
#define SECS_PER_MIN 60
|
|
#define MINS_PER_HOUR 60
|
|
|
|
typedef uint64_t ObDTMode;
|
|
|
|
enum ElementFlag
|
|
{
|
|
INVALID_FLAG = -1,
|
|
AD = 0,
|
|
AD2, //A.D.
|
|
BC,
|
|
BC2, //B.C.
|
|
CC,
|
|
SCC,
|
|
D,
|
|
DAY,
|
|
DD,
|
|
DDD,
|
|
DY,
|
|
FF1,
|
|
FF2,
|
|
FF3,
|
|
FF4,
|
|
FF5,
|
|
FF6,
|
|
FF7,
|
|
FF8,
|
|
FF9,
|
|
FF,
|
|
HH,
|
|
HH24,
|
|
HH12,
|
|
IW,
|
|
I,
|
|
IY,
|
|
IYY,
|
|
IYYY,
|
|
MI,
|
|
MM,
|
|
MONTH,
|
|
MON,
|
|
AM,
|
|
AM2, //A.M.
|
|
PM,
|
|
PM2, //P.M.
|
|
Q,
|
|
RR,
|
|
RRRR,
|
|
SS,
|
|
SSSSS,
|
|
WW,
|
|
W,
|
|
YGYYY,
|
|
YEAR,
|
|
SYEAR,
|
|
YYYY,
|
|
SYYYY,
|
|
YYY,
|
|
YY,
|
|
Y,
|
|
DS,
|
|
DL,
|
|
TZH,
|
|
TZM,
|
|
TZD,
|
|
TZR,
|
|
X,
|
|
J,
|
|
///<<< !!!add any flag before this line!!!
|
|
MAX_FLAG_NUMBER
|
|
};
|
|
|
|
enum ElementGroup
|
|
{
|
|
RUNTIME_CONFLICT_SOLVE_GROUP = -2,
|
|
NON_CONFLICT_GROUP = -1,
|
|
///<<< conflict in group, before this line, will be ignored
|
|
NEVER_APPEAR_GROUP = 0, //the element should never appear
|
|
YEAR_GROUP, //include : SYYYY YYYY YYY YY Y YGYYY RR RRRR
|
|
MERIDIAN_INDICATOR_GROUP, //include : AM PM
|
|
WEEK_OF_DAY_GROUP, //include : D Day Dy
|
|
ERA_GROUP, //include : AD BC
|
|
HOUR_GROUP, //include : HH HH12 HH24
|
|
MONTH_GROUP, //include : MONTH MON MM
|
|
DAY_OF_YEAR_GROUP, //include : DDD, J
|
|
///<<< !!!add any flag before this line!!!
|
|
MAX_CONFLICT_GROUP_NUMBER
|
|
};
|
|
|
|
struct ObTimeConstStr {
|
|
const char *ptr_;
|
|
int32_t len_;
|
|
};
|
|
|
|
struct ObDFMParseCtx
|
|
{
|
|
const char* fmt_str_;
|
|
const char* cur_ch_;
|
|
int64_t remain_len_;
|
|
|
|
//the following values are only used in function str_to_ob_time_oracle_dfm
|
|
int64_t expected_elem_flag_;
|
|
my_bool is_matching_by_expected_len_; //only used for match_int_value
|
|
};
|
|
|
|
enum UpperCaseMode {
|
|
NON_CHARACTER,
|
|
ONLY_FIRST_CHARACTER,
|
|
ALL_CHARACTER
|
|
};
|
|
|
|
struct ObDFMElem
|
|
{
|
|
int64_t elem_flag_; //flag from enum ObDFMFlag
|
|
int64_t offset_; //offset in origin format string
|
|
my_bool is_single_dot_before_; //for the dot before FF
|
|
enum UpperCaseMode upper_case_mode_;
|
|
};
|
|
|
|
struct ObTime
|
|
{
|
|
uint64_t mode_;
|
|
int32_t parts_[TOTAL_PART_CNT];
|
|
// year: [1000, 9999].
|
|
// month: [1, 12].
|
|
// day: [1, 31].
|
|
// hour: [0, 23] or [0, 838] if it is a time.
|
|
// minute: [0, 59].
|
|
// second: [0, 59].
|
|
// usecond: [0, 1000000], 1000000 can only valid after str_to_ob_time, for round.
|
|
// nanosecond: [0, 1000000000], when HAS_TYPE_ORACLE(mode_)
|
|
// date: date value, day count since 1970-1-1.
|
|
// year day: [1, 366].
|
|
// week day: [1, 7], 1 means monday, 7 means sunday.
|
|
// offset minute: [-12*60, 14*60].
|
|
|
|
char tz_name_[OB_MAX_TZ_NAME_LEN];
|
|
char tzd_abbr_[OB_MAX_TZ_ABBR_LEN];//the abbr of time zone region with Daylight Saving Time
|
|
int32_t time_zone_id_;
|
|
uint8_t nano_scale_;
|
|
my_bool is_tz_name_valid_;
|
|
};
|
|
|
|
struct ObFastFormatInt
|
|
{
|
|
char buf_[MAX_DIGITS10_STR_SIZE];
|
|
char *ptr_;
|
|
int64_t len_;
|
|
};
|
|
|
|
struct ObOracleTimeLimiter
|
|
{
|
|
int32_t MIN;
|
|
int32_t MAX;
|
|
int ERROR_CODE;
|
|
};
|
|
longlong strtoll10(const char *nptr, char **endptr, int *error);
|
|
int calculate_str_oracle_dfm_length(const struct ObTime *ob_time,
|
|
const char *fmt_str, const int64_t fmt_len,
|
|
int16_t scale, int64_t *len);
|
|
|
|
int ob_time_to_str_oracle_dfm(const struct ObTime *ob_time,
|
|
const char *fmt_str, const int64_t fmt_len,
|
|
int16_t scale,
|
|
char *buf, int64_t buf_len,
|
|
int64_t *pos);
|
|
|
|
int32_t ob_time_to_date(struct ObTime *ob_time);
|
|
|
|
int str_to_ob_time_oracle_dfm(const char *str, const int64_t str_len,
|
|
const char *fmt_str, const int64_t fmt_len,
|
|
struct ObTime *ob_time,
|
|
int16_t scale);
|