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

📄 sqlite3odbc.c

📁 定时器for timer for ic chip
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Get maximum display size and number of digits after decimal point
 * from field type specification.
 * @param typename field type specification
 * @param sqltype target SQL data type
 * @param mp pointer to maximum display size or NULL
 * @param dp pointer to number of digits after decimal point or NULL
 */

static void
getmd(const char *typename, int sqltype, int *mp, int *dp)
{
    int m = 0, d = 0;

    switch (sqltype) {
    case SQL_INTEGER:       m = 10; d = 9; break;
    case SQL_TINYINT:       m = 4; d = 3; break;
    case SQL_SMALLINT:      m = 6; d = 5; break;
    case SQL_FLOAT:         m = 25; d = 24; break;
    case SQL_DOUBLE:        m = 54; d = 53; break;
    case SQL_VARCHAR:       m = 255; d = 0; break;
#ifdef WINTERFACE
#ifdef SQL_WVARCHAR
    case SQL_WVARCHAR:      m = 255; d = 0; break;
#endif
#endif
#ifdef SQL_TYPE_DATE
    case SQL_TYPE_DATE:
#endif
    case SQL_DATE:          m = 10; d = 0; break;
#ifdef SQL_TYPE_TIME
    case SQL_TYPE_TIME:
#endif
    case SQL_TIME:          m = 8; d = 0; break;
#ifdef SQL_TYPE_TIMESTAMP
    case SQL_TYPE_TIMESTAMP:
#endif
    case SQL_TIMESTAMP:     m = 32; d = 0; break;
#ifdef SQL_LONGVARCHAR
    case SQL_LONGVARCHAR :  m = 65536; d = 0; break;
#endif
#ifdef WINTERFACE
#ifdef SQL_WLONGVARCHAR
    case SQL_WLONGVARCHAR:  m = 65536; d = 0; break;
#endif
#endif
    case SQL_VARBINARY:     m = 255; d = 0; break;
    case SQL_LONGVARBINARY: m = 65536; d = 0; break;
#ifdef SQL_BIGINT
    case SQL_BIGINT:        m = 20; d = 19; break;
#endif
    }
    if (m && typename) {
	int mm, dd;

	if (sscanf(typename, "%*[^(](%d)", &mm) == 1) {
	    m = d = mm;
	} else if (sscanf(typename, "%*[^(](%d,%d)", &mm, &dd) == 2) {
	    m = mm;
	    d = dd;
	}
    }
    if (mp) {
	*mp = m;
    }
    if (dp) {
	*dp = d;
    }
}

/**
 * Map SQL_C_DEFAULT to proper C type.
 * @param type input C type
 * @param stype input SQL type
 * @param nosign 0=signed, 0>unsigned, 0<undefined
 * @param nowchar when compiled with WINTERFACE don't use WCHAR
 * @result C type
 */

static int
mapdeftype(int type, int stype, int nosign, int nowchar)
{
    if (type == SQL_C_DEFAULT) {
	switch (stype) {
	case SQL_INTEGER:
	    type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
	    break;
	case SQL_TINYINT:
	    type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
	    break;
	case SQL_SMALLINT:
	    type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
	    break;
	case SQL_FLOAT:
	    type = SQL_C_FLOAT;
	    break;
	case SQL_DOUBLE:
	    type = SQL_C_DOUBLE;
	    break;
	case SQL_TIMESTAMP:
	    type = SQL_C_TIMESTAMP;
	    break;
	case SQL_TIME:
	    type = SQL_C_TIME;
	    break;
	case SQL_DATE:
	    type = SQL_C_DATE;
	    break;
#ifdef SQL_C_TYPE_TIMESTAMP
	case SQL_TYPE_TIMESTAMP:
	    type = SQL_C_TYPE_TIMESTAMP;
	    break;
#endif
#ifdef SQL_C_TYPE_TIME
	case SQL_TYPE_TIME:
	    type = SQL_C_TYPE_TIME;
	    break;
#endif
#ifdef SQL_C_TYPE_DATE
	case SQL_TYPE_DATE:
	    type = SQL_C_TYPE_DATE;
	    break;
#endif
#ifdef WINTERFACE
	case SQL_WVARCHAR:
	case SQL_WCHAR:
#ifdef SQL_WLONGVARCHAR
	case SQL_WLONGVARCHAR:
#endif
	    type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
	    break;
#endif
	case SQL_BINARY:
	case SQL_VARBINARY:
	case SQL_LONGVARBINARY:
	    type = SQL_C_BINARY;
	    break;
#ifdef SQL_BIT
	case SQL_BIT:
	    type = SQL_C_BIT;
	    break;
#endif
#ifdef SQL_BIGINT
	case SQL_BIGINT:
	    type = (nosign > 0) ? SQL_C_UBIGINT : SQL_C_SBIGINT;
	    break;
#endif
	default:
#ifdef WINTERFACE
	    type = SQL_C_WCHAR;
#else
	    type = SQL_C_CHAR;
#endif
	}
    }
#ifdef WINTERFACE
    if (nowchar) {
	if (type == SQL_C_WCHAR) {
	    type = SQL_C_CHAR;
	}
    }
#endif
    return type;
}

/**
 * Fixup query string with optional parameter markers.
 * @param sql original query string
 * @param sqlLen length of query string or SQL_NTS
 * @param nparam output number of parameters
 * @param isselect output indicator for SELECT statement
 * @param errmsg output error message
 * @result newly allocated string containing query string for SQLite or NULL
 */

static char *
fixupsql(char *sql, int sqlLen, int *nparam, int *isselect, char **errmsg)
{
    char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
    int np = 0, isddl = -1, size;

    *errmsg = NULL;
    if (sqlLen != SQL_NTS) {
	qz = q = xmalloc(sqlLen + 1);
	if (!qz) {
	    return NULL;
	}
	memcpy(q, sql, sqlLen);
	q[sqlLen] = '\0';
	size = sqlLen * 4;
    } else {
	size = strlen(sql) * 4;
    }
    size += sizeof (char *) - 1;
    size &= ~(sizeof (char *) - 1);
    p = xmalloc(size);
    if (!p) {
errout:
	freep(&qz);
	return NULL;
    }
    out = p;
    while (*q) {
	switch (*q) {
	case '\'':
	case '\"':
	    if (q == inq) {
		inq = NULL;
	    } else if (!inq) {
		inq = q + 1;

		while (*inq) {
		    if (*inq == *q) {
			if (inq[1] == *q) {
			    inq++;
			} else {
			    break;
			}
		    }
		    inq++;
		}
	    }
	    *p++ = *q;
	    break;
	case '?':
	    *p++ = *q;
	    if (!inq) {
		np++;
	    }
	    break;
	case ';':
	    if (!inq) {
		if (isddl < 0) {
		    char *qq = out;

		    while (*qq && ISSPACE(*qq)) {
			++qq;
		    }
		    if (*qq && *qq != ';') {
			size = strlen(qq);
			if ((size >= 5) &&
			    (strncasecmp(qq, "create", 5) == 0)) {
			    isddl = 1;
			} else if ((size >= 4) &&
				   (strncasecmp(qq, "drop", 4) == 0)) {
			    isddl = 1;
			} else {
			    isddl = 0;
			}
		    }
		}
		if (isddl == 0) {
		    char *qq = q;

		    do {
			++qq;
		    } while (*qq && ISSPACE(*qq));
		    if (*qq && *qq != ';') {
			freep(&out);
			*errmsg = "only one SQL statement allowed";
			goto errout;
		    }
		}
	    }
	    *p++ = *q;
	    break;
	case '{':
	    /* deal with {d 'YYYY-MM-DD'}, {t ...}, and {ts ...} */
	    if (!inq) {
		char *end = q + 1;

		while (*end && *end != '}') {
		    ++end;
		}
		if (*end == '}') {
		    char *start = q + 1;
		    char *end2 = end - 1;

		    while (start < end2 && *start != '\'') {
			++start;
		    }
		    while (end2 > start && *end2 != '\'') {
			--end2;
		    }
		    if (*start == '\'' && *end2 == '\'') {
			while (start <= end2) {
			    *p++ = *start;
			    ++start;
			}
			q = end;
			break;
		    }
		}
	    }
	    /* FALL THROUGH */
	default:
	    *p++ = *q;
	}
	++q;
    }
    freep(&qz);
    *p = '\0';
    if (nparam) {
	*nparam = np;
    }
    if (isselect) {
	if (isddl > 0) {
	    *isselect = 0;
	} else {
	    p = out;
	    while (*p && ISSPACE(*p)) {
		++p;
	    }
	    size = strlen(p);
	    *isselect = (size >= 6) && (strncasecmp(p, "select", 6) == 0);
	}
    }
    return out;
}

/**
 * Find column given name in string array.
 * @param cols string array
 * @param ncols number of strings
 * @param name column name
 * @result >= 0 on success, -1 on error
 */

static int
findcol(char **cols, int ncols, char *name)
{
    int i;

    if (cols) {
	for (i = 0; i < ncols; i++) {
	    if (strcmp(cols[i], name) == 0) {
		return i;
	    }
	}
    }
    return -1;
}

/**
 * Fixup column information for a running statement.
 * @param s statement to get fresh column information
 * @param d DBC pointer
 *
 * The column labels get the table names stripped
 * when there's more than one column and all table
 * names are identical.
 *
 * The "dyncols" field of STMT is filled with column
 * information obtained by SQLite "PRAGMA table_info"
 * for each column whose table name is known. If the
 * types are already present as with SQLite 2.5.7
 * this information is used instead.
 */

static void
fixupdyncols(STMT *s, DBC *d)
{
    int i, k, pk, nn, t, r, nrows, ncols;
    char **rowp, *flagp, flags[128];

    if (!s->dyncols) {
	return;
    }
    /* fixup labels */
    if (!s->longnames) {
	if (s->dcols > 1) {
	    char *table = s->dyncols[0].table;

	    for (i = 1; table[0] && i < s->dcols; i++) {
		if (strcmp(s->dyncols[i].table, table)) {
		    break;
		}
	    }
	    if (i >= s->dcols) {
		for (i = 0; i < s->dcols; i++) {
		    s->dyncols[i].label = s->dyncols[i].column;
		}
	    }
	} else if (s->dcols == 1) {
	    s->dyncols[0].label = s->dyncols[0].column;
	}
    }
    for (i = 0; i < s->dcols; i++) {
	s->dyncols[i].type =
	    mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
		       s->nowchar[0] || s->nowchar[1]);
	getmd(s->dyncols[i].typename, s->dyncols[i].type,
	      &s->dyncols[i].size, NULL);
#ifdef SQL_LONGVARCHAR
	if (s->dyncols[i].type == SQL_VARCHAR &&
	    s->dyncols[i].size > 255) {
	    s->dyncols[i].type = SQL_LONGVARCHAR;
	}
#endif
#ifdef WINTERFACE
#ifdef SQL_WLONGVARCHAR
	if (s->dyncols[i].type == SQL_WVARCHAR &&
	    s->dyncols[i].size > 255) {
	    s->dyncols[i].type = SQL_WLONGVARCHAR;
	}
#endif
#endif
	if (s->dyncols[i].type == SQL_VARBINARY &&
	    s->dyncols[i].size > 255) {
	    s->dyncols[i].type = SQL_LONGVARBINARY;
	}
    }
    if (s->dcols > array_size(flags)) {
	flagp = xmalloc(sizeof (flags[0]) * s->dcols);
	if (flagp == NULL) {
	    return;
	}
    } else {
	flagp = flags;
    }
    memset(flagp, 0, sizeof (flags[0]) * s->dcols);
    for (i = 0; i < s->dcols; i++) {
	s->dyncols[i].autoinc = SQL_FALSE;
	s->dyncols[i].notnull = SQL_NULLABLE;
    }
    for (i = 0; i < s->dcols; i++) {
	int ret, lastpk = -1, autoinccount = 0;
	char *sql;

	if (!s->dyncols[i].table[0]) {
	    continue;
	}
	if (flagp[i]) {
	    continue;
	}
	sql = sqlite3_mprintf("PRAGMA table_info(%Q)", s->dyncols[i].table);
	if (!sql) {
	    continue;
	}
	dbtraceapi(d, "sqlite3_get_table", sql);
	ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
	sqlite3_free(sql);
	if (ret != SQLITE_OK) {
	    continue;
	}
	k = findcol(rowp, ncols, "name");
	t = findcol(rowp, ncols, "type");
	pk = findcol(rowp, ncols, "pk");
	nn = findcol(rowp, ncols, "notnull");
	if (k < 0 || t < 0) {
	    goto freet;
	}
	for (r = 1; r <= nrows; r++) {
	    int m;

	    for (m = i; m < s->dcols; m++) {
		char *colname = s->dyncols[m].column;

		if (s->longnames) {
		    char *dotp = strchr(colname, '.');

		    if (dotp) {
			colname = dotp + 1;
		    }
		}
		if (!flagp[m] &&
		    strcmp(colname, rowp[r * ncols + k]) == 0 &&
		    strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
		    char *typename = rowp[r * ncols + t];

		    flagp[m] = 1;
		    freep(&s->dyncols[m].typename);
		    s->dyncols[m].typename = xstrdup(typename);
		    s->dyncols[m].type =
			mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
				   s->nowchar[0] || s->nowchar[1]);
		    getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
			  NULL);
#ifdef SQL_LONGVARCHAR
		    if (s->dyncols[m].type == SQL_VARCHAR &&
			s->dyncols[m].size > 255) {
			s->dyncols[m].type = SQL_LONGVARCHAR;
		    }
#endif
#ifdef WINTERFACE
#ifdef SQL_WLONGVARCHAR
		    if (s->dyncols[i].type == SQL_WVARCHAR &&
			s->dyncols[i].size > 255) {
			s->dyncols[i].type = SQL_WLONGVARCHAR;
		    }
#endif
#endif
		    if (s->dyncols[i].type == SQL_VARBINARY &&
			s->dyncols[i].size > 255) {
			s->dyncols[i].type = SQL_LONGVARBINARY;
		    }
		    if (pk >= 0	&& strcmp(rowp[r * ncols + pk], "1") == 0) {
			if (++autoinccount > 1) {
			    if (lastpk >= 0) {
				s->dyncols[lastpk].autoinc = SQL_FALSE;
				lastpk = -1;
			    }
			} else {
			    lastpk = m;
			    if (strlen(typename) == 7 &&
				strncasecmp(typename, "integer", 7) == 0) {
				s->dyncols[m].autoinc = SQL_TRUE;
			    }
			}
		    }
		    if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
			s->dyncols[m].notnull = SQL_NO_NULLS;
		    }
		}
	    }
	}
freet:
	sqlite3_free_table(rowp);
    }
    if (flagp != flags) {
	freep(&flagp);
    }
}

/**
 * Return number of month days.
 * @param year
 * @param month 1..12
 * @result number of month days or 0
 */

static int
getmdays(int year, int month)
{
    static const int mdays[] = {
	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    int mday;

    if (month < 1) {
	return 0;
    }
    mday = mdays[(month - 1) % 12];
    if (mday == 28 && year % 4 == 0 &&
	(!(year % 100 == 0) || year % 400 == 0)) {
	mday++;
    }
    return mday;
}

/**
 * Convert string to ODBC DATE_STRUCT.
 * @param str string to be converted
 * @param ds output DATE_STRUCT
 * @result 0 on success, -1 on error
 *
 * Strings of the format 'YYYYMMDD' or 'YYYY-MM-DD' or
 * 'YYYY/MM/DD' are converted to a DATE_STRUCT.
 */

static int
str2date(char *str, DATE_STRUCT *ds)
{
    int i, err = 0;
    char *p, *q;

    ds->year = ds->month = ds->day = 0;
    p = str;
    while (*p && !ISDIGIT(*p)) {
	++p;
    }
    q = p;
    i = 0;
    while (*q && !ISDIGIT(*q)) {
	++i;
	++q;
    }
    if (i >= 8) {
	char buf[8];

	strncpy(buf, p + 0, 4); buf[4] = '\0';
	ds->year = strtol(buf, NULL, 10);
	strncpy(buf, p + 4, 2); buf[2] = '\0';
	ds->month = strtol(buf, NULL, 10);
	strncpy(buf, p + 6, 2); buf[2] = '\0';
	ds->day = strtol(buf, NULL, 10);
	goto done;
    }
    i = 0;
    while (i < 3) {
	int n;

	q = NULL; 
	n = strtol(p, &q, 10);

⌨️ 快捷键说明

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