📄 sqlite3odbc.c
字号:
if (!q || q == p) {
if (*q == '\0') {
if (i == 0) {
err = 1;
}
goto done;
}
}
if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
switch (i) {
case 0: ds->year = n; break;
case 1: ds->month = n; break;
case 2: ds->day = n; break;
}
++i;
if (*q) {
++q;
}
} else {
i = 0;
while (*q && !ISDIGIT(*q)) {
++q;
}
}
p = q;
}
done:
/* final check for overflow */
if (err ||
ds->month < 1 || ds->month > 12 ||
ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
return -1;
}
return 0;
}
/**
* Convert string to ODBC TIME_STRUCT.
* @param str string to be converted
* @param ts output TIME_STRUCT
* @result 0 on success, -1 on error
*
* Strings of the format 'HHMMSS' or 'HH:MM:SS'
* are converted to a TIME_STRUCT.
*/
static int
str2time(char *str, TIME_STRUCT *ts)
{
int i, err = 0;
char *p, *q;
ts->hour = ts->minute = ts->second = 0;
p = str;
while (*p && !ISDIGIT(*p)) {
++p;
}
q = p;
i = 0;
while (*q && ISDIGIT(*q)) {
++i;
++q;
}
if (i >= 6) {
char buf[4];
strncpy(buf, p + 0, 2); buf[2] = '\0';
ts->hour = strtol(buf, NULL, 10);
strncpy(buf, p + 2, 2); buf[2] = '\0';
ts->minute = strtol(buf, NULL, 10);
strncpy(buf, p + 4, 2); buf[2] = '\0';
ts->second = strtol(buf, NULL, 10);
goto done;
}
i = 0;
while (i < 3) {
int n;
q = NULL;
n = strtol(p, &q, 10);
if (!q || q == p) {
if (*q == '\0') {
if (i == 0) {
err = 1;
}
goto done;
}
}
if (*q == ':' || *q == '\0' || i == 2) {
switch (i) {
case 0: ts->hour = n; break;
case 1: ts->minute = n; break;
case 2: ts->second = n; break;
}
++i;
if (*q) {
++q;
}
} else {
i = 0;
while (*q && !ISDIGIT(*q)) {
++q;
}
}
p = q;
}
done:
/* final check for overflow */
if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
return -1;
}
return 0;
}
/**
* Convert string to ODBC TIMESTAMP_STRUCT.
* @param str string to be converted
* @param tss output TIMESTAMP_STRUCT
* @result 0 on success, -1 on error
*
* Strings of the format 'YYYYMMDDhhmmssff' or 'YYYY-MM-DD hh:mm:ss ff'
* or 'YYYY/MM/DD hh:mm:ss ff' or 'hh:mm:ss ff YYYY-MM-DD' are
* converted to a TIMESTAMP_STRUCT. The ISO8601 formats
* YYYY-MM-DDThh:mm:ss[.f]Z
* YYYY-MM-DDThh:mm:ss[.f]shh:mm
* are also supported. In case a time zone field is present,
* the resulting TIMESTAMP_STRUCT is expressed in UTC.
*/
static int
str2timestamp(char *str, TIMESTAMP_STRUCT *tss)
{
int i, m, n, err = 0;
char *p, *q, in = '\0';
tss->year = tss->month = tss->day = 0;
tss->hour = tss->minute = tss->second = 0;
tss->fraction = 0;
p = str;
while (*p && !ISDIGIT(*p)) {
++p;
}
q = p;
i = 0;
while (*q && ISDIGIT(*q)) {
++i;
++q;
}
if (i >= 14) {
char buf[16];
strncpy(buf, p + 0, 4); buf[4] = '\0';
tss->year = strtol(buf, NULL, 10);
strncpy(buf, p + 4, 2); buf[2] = '\0';
tss->month = strtol(buf, NULL, 10);
strncpy(buf, p + 6, 2); buf[2] = '\0';
tss->day = strtol(buf, NULL, 10);
strncpy(buf, p + 8, 2); buf[2] = '\0';
tss->hour = strtol(buf, NULL, 10);
strncpy(buf, p + 10, 2); buf[2] = '\0';
tss->minute = strtol(buf, NULL, 10);
strncpy(buf, p + 12, 2); buf[2] = '\0';
tss->second = strtol(buf, NULL, 10);
if (i > 14) {
m = i - 14;
strncpy(buf, p + 14, m);
while (m < 9) {
buf[m] = '0';
++m;
}
buf[m] = '\0';
tss->fraction = strtol(buf, NULL, 0);
}
m = 7;
goto done;
}
m = i = 0;
while ((m & 7) != 7) {
q = NULL;
n = strtol(p, &q, 10);
if (!q || q == p) {
if (*q == '\0') {
if (m < 1) {
err = 1;
}
goto done;
}
}
if (in == '\0') {
switch (*q) {
case '-':
case '/':
if ((m & 1) == 0) {
in = *q;
i = 0;
}
break;
case ':':
if ((m & 2) == 0) {
in = *q;
i = 0;
}
break;
case ' ':
case '.':
break;
default:
in = '\0';
i = 0;
break;
}
}
switch (in) {
case '-':
case '/':
switch (i) {
case 0: tss->year = n; break;
case 1: tss->month = n; break;
case 2: tss->day = n; break;
}
if (++i >= 3) {
i = 0;
m |= 1;
if (!(m & 2)) {
m |= 8;
}
goto skip;
} else {
++q;
}
break;
case ':':
switch (i) {
case 0: tss->hour = n; break;
case 1: tss->minute = n; break;
case 2: tss->second = n; break;
}
if (++i >= 3) {
i = 0;
m |= 2;
if (*q == '.') {
in = '.';
goto skip2;
}
if (*q == ' ') {
if ((m & 1) == 0) {
char *e = NULL;
int dummy;
dummy = strtol(q + 1, &e, 10);
if (e && *e == '-') {
goto skip;
}
}
in = '.';
goto skip2;
}
goto skip;
} else {
++q;
}
break;
case '.':
if (++i >= 1) {
int ndig = q - p;
if (p[0] == '+' || p[0] == '-') {
ndig--;
}
while (ndig < 9) {
n = n * 10;
++ndig;
}
tss->fraction = n;
m |= 4;
i = 0;
}
default:
skip:
in = '\0';
skip2:
while (*q && !ISDIGIT(*q)) {
++q;
}
}
p = q;
}
if ((m & 7) > 1 && (m & 8)) {
/* ISO8601 timezone */
if (p > str && ISDIGIT(*p)) {
int nn, sign;
q = p - 1;
if (*q != '+' && *q != '-') {
goto done;
}
sign = (*q == '+') ? -1 : 1;
q = NULL;
n = strtol(p, &q, 10);
if (!q || *q++ != ':' || !ISDIGIT(*q)) {
goto done;
}
p = q;
q = NULL;
nn = strtol(p, &q, 0);
tss->minute += nn * sign;
if ((SQLSMALLINT) tss->minute < 0) {
tss->hour -= 1;
tss->minute += 60;
} else if (tss->minute >= 60) {
tss->hour += 1;
tss->minute -= 60;
}
tss->hour += n * sign;
if ((SQLSMALLINT) tss->hour < 0) {
tss->day -= 1;
tss->hour += 24;
} else if (tss->hour >= 24) {
tss->day += 1;
tss->hour -= 24;
}
if ((short) tss->day < 1 || tss->day >= 28) {
int mday, pday, pmon;
mday = getmdays(tss->year, tss->month);
pmon = tss->month - 1;
if (pmon < 1) {
pmon = 12;
}
pday = getmdays(tss->year, pmon);
if ((SQLSMALLINT) tss->day < 1) {
tss->month -= 1;
tss->day = pday;
} else if (tss->day > mday) {
tss->month += 1;
tss->day = 1;
}
if ((SQLSMALLINT) tss->month < 1) {
tss->year -= 1;
tss->month = 12;
} else if (tss->month > 12) {
tss->year += 1;
tss->month = 1;
}
}
}
}
done:
/* final check for overflow */
if (err ||
tss->month < 1 || tss->month > 12 ||
tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
tss->hour > 23 || tss->minute > 60 || tss->second > 60) {
return -1;
}
return ((m & 7) < 1) ? -1 : 0;
}
/**
* Get boolean flag from string.
* @param string string to be inspected
* @result true or false
*/
static int
getbool(char *string)
{
if (string) {
return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
}
return 0;
}
/**
* SQLite trace callback
* @param arg DBC pointer
* @param msg log message, SQL text
*/
static void
dbtrace(void *arg, const char *msg)
{
DBC *d = (DBC *) arg;
if (msg && d->trace) {
int len = strlen(msg);
if (len > 0) {
char *end = "\n";
if (msg[len - 1] != ';') {
end = ";\n";
}
fprintf(d->trace, "%s%s", msg, end);
fflush(d->trace);
}
}
}
/**
* Trace function for SQLite API calls
* @param d pointer to database connection handle
* @param fn SQLite function name
* @param sql SQL string
*/
static void
dbtraceapi(DBC *d, char *fn, const char *sql)
{
if (fn && d->trace) {
if (sql) {
fprintf(d->trace, "-- %s: %s\n", fn, sql);
} else {
fprintf(d->trace, "-- %s\n", fn);
}
fflush(d->trace);
}
}
/**
* Trace function for SQLite return codes
* @param d pointer to database connection handle
* @param rc SQLite return code
* @param err error string or NULL
*/
static void
dbtracerc(DBC *d, int rc, char *err)
{
if (rc != SQLITE_OK && d->trace) {
fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
fprintf(d->trace, err ? ": %s\n" : "\n", err);
fflush(d->trace);
}
}
/**
* Open SQLite database file given file name and flags.
* @param d DBC pointer
* @param name file name
* @param isu true/false: file name is UTF8 encoded
* @param dsn data source name
* @param sflag STEPAPI flag
* @param spflag SyncPragma string
* @param ntflag NoTransaction string
* @param busy busy/lock timeout
* @result ODBC error code
*/
static SQLRETURN
dbopen(DBC *d, char *name, char *pass, int isu, char *dsn, char *sflag,
char *spflag, char *ntflag, char *busy)
{
char *endp = NULL;
int rc, tmp, busyto = 100000;
#if defined(HAVE_SQLITE3VFS) && HAVE_SQLITE3VFS
int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
char *uname = name;
const char *vfs_name = NULL;
#endif
if (d->sqlite) {
if (strcmp(d->dbpass,d->dboldpass)!=0) {
if (strcmp(d->dbpass,"NULL")==0) {
sqlite3_rekey(d->sqlite, "", 0);
}else{
sqlite3_rekey(d->sqlite, d->dbpass, strlen(d->dbpass));
}
freep(&d->dboldpass);
d->dboldpass = xstrdup(d->dbpass);
}
if (d->trace) {
fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
d->dbname);
fflush(d->trace);
}
sqlite3_close(d->sqlite);
d->sqlite = NULL;
}
#if defined(HAVE_SQLITE3VFS) && HAVE_SQLITE3VFS
if (d->nocreat) {
flags &= ~ SQLITE_OPEN_CREATE;
}
#ifdef _WIN32
if (!isu) {
uname = wmb_to_utf(name, -1);
if (!uname) {
rc = SQLITE_NOMEM;
setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
return SQL_ERROR;
}
}
#endif
#if defined(ENABLE_NVFS) && ENABLE_NVFS
vfs_name = nvfs_makevfs(uname);
#endif
rc = sqlite3_open_v2(uname, &d->sqlite, flags, vfs_name);
#if defined(WINTERFACE) || defined(_WIN32)
if (uname != name) {
uc_free(uname);
}
#endif
#else
#ifdef _WIN32
if (d->nocreat) {
char *cname = NULL;
if (isu) {
cname = utf_to_wmb(name, -1);
}
if (GetFileAttributesA(cname ? cname : name) == 0xffffffff) {
uc_free(cname);
rc = SQLITE_CANTOPEN;
setstatd(d, rc, "cannot open database",
(*d->ov3) ? "HY000" : "S1000");
return SQL_ERROR;
}
uc_free(cname);
}
#else
if (d->nocreat && access(name, 004) < 0) {
rc = SQLITE_CANTOPEN;
setstatd(d, rc, "cannot open database", (*d->ov3) ? "HY000" : "S1000");
return SQL_ERROR;
}
#endif
#ifdef _WIN32
if (!isu) {
WCHAR *wname = wmb_to_uc(name, -1);
if (!wname) {
rc = SQLITE_NOMEM;
setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
return SQL_ERROR;
}
rc = sqlite3_open16(wname, &d->sqlite);
uc_free(wname);
} else
#endif
rc = sqlite3_open(name, &d->sqlite);
#endif /* !HAVE_SQLITE3VFS */
if (rc != SQLITE_OK) {
connfail:
setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
if (d->sqlite) {
sqlite3_close(d->sqlite);
d->sqlite = NULL;
}
return SQL_ERROR;
}
if (strlen(pass) > 0) sqlite3_key(d->sqlite, pass, strlen(pass));
if (d->trace) {
sqlite3_trace(d->sqlite, dbtrace, d);
}
d->step_enable = getbool(sflag);
d->trans_disable = getbool(ntflag);
d->curtype = d->step_enable ?
SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
tmp = strtol(busy, &endp, 0);
if (endp && *endp == '\0' && endp != busy) {
busyto = tmp;
}
if (busyto < 1 || busyto > 1000000) {
busyto = 1000000;
}
d->timeout = busyto;
if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE_OK) {
if (d->trace) {
fprintf(d->trace, "-- sqlite3_close: '%s'\n",
d->dbname);
fflush(d->trace);
}
sqlite3_close(d->sqlite);
d->sqlite = NULL;
goto connfail;
}
if (!spflag || spflag[0] == '\0') {
spflag = "NORMAL";
}
if (spflag[0] != '\0') {
char syncp[128];
sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
}
freep(&d->dbname);
d->dbname = xstrdup(name);
freep(&d->dsn);
d->dsn = xstrdup(dsn);
freep(&d->dbpass)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -