⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sqlite3odbc.c

📁 定时器for timer for ic chip
💻 C
📖 第 1 页 / 共 5 页
字号:
    *resp = &tres.resarr[1];
    if (ncolp) {
	*ncolp = tres.ncol;
    }
    if (nrowp) {
	*nrowp = tres.nrow;
    }
    return rc;
}

/**
 * Set error message and SQL state on DBC
 * @param d database connection pointer
 * @param naterr native error code
 * @param msg error message
 * @param st SQL state
 */

#if defined(__GNUC__) && (__GNUC__ >= 2)
static void setstatd(DBC *, int, char *, char *, ...)
    __attribute__((format (printf, 3, 5)));
#endif

static void
setstatd(DBC *d, int naterr, char *msg, char *st, ...)
{
    va_list ap;

    if (!d) {
	return;
    }
    d->naterr = naterr;
    d->logmsg[0] = '\0';
    if (msg) {
	int count;

	va_start(ap, st);
	count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
	va_end(ap);
	if (count < 0) {
	    d->logmsg[sizeof (d->logmsg) - 1] = '\0';
	}
    }
    if (!st) {
	st = "?????";
    }
    strncpy(d->sqlstate, st, 5);
    d->sqlstate[5] = '\0';
}

/**
 * Set error message and SQL state on statement
 * @param s statement pointer
 * @param naterr native error code
 * @param msg error message
 * @param st SQL state
 */

#if defined(__GNUC__) && (__GNUC__ >= 2)
static void setstat(STMT *, int, char *, char *, ...)
    __attribute__((format (printf, 3, 5)));
#endif

static void
setstat(STMT *s, int naterr, char *msg, char *st, ...)
{
    va_list ap;

    if (!s) {
	return;
    }
    s->naterr = naterr;
    s->logmsg[0] = '\0';
    if (msg) {
	int count;

	va_start(ap, st);
	count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
	va_end(ap);
	if (count < 0) {
	    s->logmsg[sizeof (s->logmsg) - 1] = '\0';
	}
    }
    if (!st) {
	st = "?????";
    }
    strncpy(s->sqlstate, st, 5);
    s->sqlstate[5] = '\0';
}

/**
 * Report IM001 (not implemented) SQL error code for HDBC.
 * @param dbc database connection handle
 * @result ODBC error code
 */

static SQLRETURN
drvunimpldbc(HDBC dbc)
{
    DBC *d;

    if (dbc == SQL_NULL_HDBC) {
	return SQL_INVALID_HANDLE;
    }
    d = (DBC *) dbc;
    setstatd(d, -1, "not supported", "IM001");
    return SQL_ERROR;
}

/**
 * Report IM001 (not implemented) SQL error code for HSTMT.
 * @param stmt statement handle
 * @result ODBC error code
 */

static SQLRETURN
drvunimplstmt(HSTMT stmt)
{
    STMT *s;

    if (stmt == SQL_NULL_HSTMT) {
	return SQL_INVALID_HANDLE;
    }
    s = (STMT *) stmt;
    setstat(s, -1, "not supported", "IM001");
    return SQL_ERROR;
}

/**
 * Free memory given pointer to memory pointer.
 * @param x pointer to pointer to memory to be free'd
 */

static void
freep(void *x)
{
    if (x && ((char **) x)[0]) {
	xfree(((char **) x)[0]);
	((char **) x)[0] = NULL;
    }
}

/**
 * Report S1000 (out of memory) SQL error given STMT.
 * @param s statement pointer
 * @result ODBC error code
 */

static SQLRETURN
nomem(STMT *s)
{
    setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
    return SQL_ERROR;
}

/**
 * Report S1000 (not connected) SQL error given STMT.
 * @param s statement pointer
 * @result ODBC error code
 */

static SQLRETURN
noconn(STMT *s)
{
    setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
    return SQL_ERROR;
}

/**
 * Internal locale neutral strtod function.
 * @param data pointer to string
 * @param endp pointer for ending character
 * @result double value
 */

static double
ln_strtod(const char *data, char **endp)
{
#if defined(HAVE_LOCALECONV) || defined(_WIN32)
    struct lconv *lc;
    char buf[128], *p, *end;
    double value;

    lc = localeconv();
    if (lc && lc->decimal_point && lc->decimal_point[0] &&
	lc->decimal_point[0] != '.') {
	strncpy(buf, data, sizeof (buf) - 1);
	buf[sizeof (buf) - 1] = '\0';
	p = strchr(buf, '.');
	if (p) {
	    *p = lc->decimal_point[0];
	}
	p = buf;
    } else {
	p = (char *) data;
    }
    value = strtod(p, &end);
    end = (char *) data + (end - p);
    if (endp) {
	*endp = end;
    }
    return value;
#else
    return strtod(data, endp);
#endif
}

/**
 * Strip quotes from quoted string in-place.
 * @param str string
 */

static char *
unquote(char *str)
{
    if (str) {
	int len = strlen(str);

	if (len > 1) {
	    if ((str[0] == '\'' && str[len - 1] == '\'') ||
		(str[0] == '"' && str[len - 1] == '"') ||
		(str[0] == '[' && str[len - 1] == ']')) {
		str[len - 1] = '\0';
		strcpy(str, str + 1);
	    }
	}
    }
    return str;
}

/**
 * Unescape search pattern for e.g. table name in
 * catalog functions. Replacements in string are done in-place.
 * @param str string
 * @result number of pattern characters in string or 0
 */

static int
unescpat(char *str)
{
    char *p, *q;
    int count = 0;

    p = str;
    while ((q = strchr(p, '_')) != NULL) {
	if (q == str || q[-1] != '\\') {
	    count++;
	}
	p = q + 1;
    }
    p = str;
    while ((q = strchr(p, '%')) != NULL) {
	if (q == str || q[-1] != '\\') {
	    count++;
	}
	p = q + 1;
    }
    p = str;
    while ((q = strchr(p, '\\')) != NULL) {
	if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
	    strcpy(q, q + 1);
	}
	p = q + 1;
    }
    return count;
}

/**
 * SQL LIKE string match with optional backslash escape handling.
 * @param str string
 * @param pat pattern
 * @param esc when true, treat literally "\\" as "\", "\?" as "?", "\_" as "_"
 * @result true when pattern matched
 */

static int
namematch(char *str, char *pat, int esc)
{
    int cp, ch;

    while (1) {
	cp = TOLOWER(*pat);
	if (cp == '\0') {
	    if (*str != '\0') {
		goto nomatch;
	    }
	    break;
	}
	if (*str == '\0' && cp != '%') {
	    goto nomatch;
	}
	if (cp == '%') {
	    while (*pat == '%') {
		++pat;
	    }
	    cp = TOLOWER(*pat);
	    if (cp == '\0') {
		break;
	    }
	    while (1) {
		if (cp != '_' && cp != '\\') {
		    while (*str) {
			ch = TOLOWER(*str);
			if (ch == cp) {
			    break;
			}
			++str;
		    }
		}
		if (namematch(str, pat, esc)) {
		    goto match;
		}
		if (*str == '\0') {
		    goto nomatch;
		}
		ch = TOLOWER(*str);
		++str;
	    }
	}
	if (cp == '_') {
	    pat++;
	    str++;
	    continue;
	}
	if (esc && cp == '\\' &&
	    (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
	    ++pat;
	    cp = TOLOWER(*pat);
	}
	ch = TOLOWER(*str++);
	++pat;
	if (ch != cp) {
	    goto nomatch;
	}
    }
match:
    return 1;
nomatch:
    return 0;
}

/**
 * Busy callback for SQLite.
 * @param udata user data, pointer to DBC
 * @param count count of subsequenct calls
 * @result true or false
 */

static int
busy_handler(void *udata, int count)
{
    DBC *d = (DBC *) udata;
    long t1;
    int ret = 0;
#ifndef _WIN32
    struct timeval tv;
#endif

    if (d->busyint) {
	d->busyint = 0;
	return ret;
    }
    if (d->timeout <= 0) {
	return ret;
    }
    if (count <= 1) {
#ifdef _WIN32
	d->t0 = GetTickCount();
#else
	gettimeofday(&tv, NULL);
	d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
#endif
    }
#ifdef _WIN32
    t1 = GetTickCount();
#else
    gettimeofday(&tv, NULL);
    t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
#endif
    if (t1 - d->t0 > d->timeout) {
	goto done;
    }
#ifdef _WIN32
    Sleep(10);
#else
#ifdef HAVE_USLEEP
    usleep(10000);
#else
    tv.tv_sec = 0;
    tv.tv_usec = 10000;
    select(0, NULL, NULL, NULL, &tv);
#endif
#endif
    ret = 1;
done:
    return ret;
}

/**
 * Set SQLite options (PRAGMAs) given SQLite handle.
 * @param x SQLite database handle
 * @param d DBC pointer
 * @result SQLite error code
 *
 * SQLite < 3.3.x and not shortnames DSN option:
 * "full_column_names" is always turned on and "short_column_names"
 * is always turned off, to get the table names in column labels.
 */

static int
setsqliteopts(sqlite3 *x, DBC *d)
{
    int count = 0, step = 0, max, rc = SQLITE_ERROR;

#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
    max = d->longnames ? 3 : 1;
#else
    max = 3;
#endif
    if (d->shortnames) {
	max = 3;
    }
    while (step < max) {
	if (step < 1) {
	    rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
			      NULL, NULL, NULL);
	} else if (step < 2) {
	    rc = sqlite3_exec(x, d->shortnames ?
			      "PRAGMA full_column_names = off;" :
			      "PRAGMA full_column_names = on;",
			      NULL, NULL, NULL);
	} else if (step < 3) {
	    rc = sqlite3_exec(x, d->shortnames ?
			      "PRAGMA short_column_names = on;" :
			      "PRAGMA short_column_names = off;",
			      NULL, NULL, NULL);
	}
	if (rc != SQLITE_OK) {
	    if (rc != SQLITE_BUSY ||
		!busy_handler((void *) d, ++count)) {
		return rc;
	    }
	    continue;
	}
	count = 0;
	++step;
    }
    sqlite3_busy_handler(x, busy_handler, (void *) d);
    return SQLITE_OK;
}

/**
 * Free counted array of char pointers.
 * @param rowp pointer to char pointer array
 *
 * The -1-th element of the array holds the array size.
 * All non-NULL pointers of the array and then the array
 * itself are free'd.
 */

static void
freerows(char **rowp)
{
    PTRDIFF_T size, i;

    if (!rowp) {
	return;
    }
    --rowp;
    size = (PTRDIFF_T) rowp[0];
    for (i = 1; i <= size; i++) {
	freep(&rowp[i]);
    }
    freep(&rowp);
}

/**
 * Map SQL field type from string to ODBC integer type code.
 * @param typename field type string
 * @param nosign pointer to indicator for unsigned field or NULL
 * @param ov3 boolean, true for SQL_OV_ODBC3
 * @param nowchar boolean, for WINTERFACE don't use WCHAR
 * @result SQL data type
 */

static int
mapsqltype(const char *typename, int *nosign, int ov3, int nowchar)
{
    char *p, *q;
    int testsign = 0, result;

#ifdef WINTERFACE
    result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
#else
    result = SQL_VARCHAR;
#endif
    if (!typename) {
	return result;
    }
    q = p = xmalloc(strlen(typename) + 1);
    if (!p) {
	return result;
    }
    strcpy(p, typename);
    while (*q) {
	*q = TOLOWER(*q);
	++q;
    }
    if (strncmp(p, "inter", 5) == 0) {
    } else if (strncmp(p, "int", 3) == 0 ||
	strncmp(p, "mediumint", 9) == 0) {
	testsign = 1;
	result = SQL_INTEGER;
    } else if (strncmp(p, "numeric", 7) == 0) {
	result = SQL_DOUBLE;
    } else if (strncmp(p, "tinyint", 7) == 0) {
	testsign = 1;
	result = SQL_TINYINT;
    } else if (strncmp(p, "smallint", 8) == 0) {
	testsign = 1;
	result = SQL_SMALLINT;
    } else if (strncmp(p, "float", 5) == 0) {
	result = SQL_DOUBLE;
    } else if (strncmp(p, "double", 6) == 0 ||
	strncmp(p, "real", 4) == 0) {
	result = SQL_DOUBLE;
    } else if (strncmp(p, "timestamp", 9) == 0) {
#ifdef SQL_TYPE_TIMESTAMP
	result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
#else
	result = SQL_TIMESTAMP;
#endif
    } else if (strncmp(p, "datetime", 8) == 0) {
#ifdef SQL_TYPE_TIMESTAMP
	result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
#else
	result = SQL_TIMESTAMP;
#endif
    } else if (strncmp(p, "time", 4) == 0) {
#ifdef SQL_TYPE_TIME
	result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
#else
	result = SQL_TIME;
#endif
    } else if (strncmp(p, "date", 4) == 0) {
#ifdef SQL_TYPE_DATE
	result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
#else
	result = SQL_DATE;
#endif
#ifdef SQL_LONGVARCHAR
    } else if (strncmp(p, "text", 4) == 0 ||
	       strncmp(p, "memo", 4) == 0) {
#ifdef WINTERFACE
	result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
#else
	result = SQL_LONGVARCHAR;
#endif
#ifdef WINTERFACE
    } else if (strncmp(p, "wtext", 5) == 0 ||
	       strncmp(p, "wvarchar", 8) == 0 ||
	       strncmp(p, "longwvarchar", 12) == 0) {
	result = SQL_WLONGVARCHAR;
#endif
#endif
#ifdef SQL_BIT
    } else if (strncmp(p, "bool", 4) == 0 ||
	       strncmp(p, "bit", 3) == 0) {
	result = SQL_BIT;
#endif
#ifdef SQL_BIGINT
    } else if (strncmp(p, "bigint", 6) == 0) {
	result = SQL_BIGINT;
#endif
    } else if (strncmp(p, "blob", 4) == 0) {
	result = SQL_BINARY;
    } else if (strncmp(p, "varbinary", 9) == 0) {
	result = SQL_VARBINARY;
    } else if (strncmp(p, "longvarbinary", 13) == 0) {
	result = SQL_LONGVARBINARY;
    }
    if (nosign) {
	if (testsign) {
	    *nosign = strstr(p, "unsigned") != NULL;
	} else {
	    *nosign = 1;
	}
    }
    xfree(p);
    return result;
}

/**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -