#include "util.h"
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "consts.h"
#include "crsqlite.h"
size_t crsql_strnlen(const char *s, size_t n) {
const char *p = memchr(s, 0, n);
return p ? p - s : n;
}
char *crsql_strndup(const char *s, size_t n) {
size_t l = crsql_strnlen(s, n);
char *d = sqlite3_malloc(l + 1);
if (!d) return NULL;
memcpy(d, s, l);
d[l] = 0;
return d;
}
char *crsql_strdup(const char *s) {
size_t l = strlen(s);
char *d = sqlite3_malloc(l + 1);
if (!d) return NULL;
return memcpy(d, s, l + 1);
}
static char *joinHelper(char **in, size_t inlen, size_t inpos, size_t accum) {
if (inpos == inlen) {
return strcpy((char *)sqlite3_malloc(accum + 1) + accum, "");
} else {
size_t mylen = strlen(in[inpos]);
return memcpy(joinHelper(in, inlen, inpos + 1, accum + mylen) - mylen,
in[inpos], mylen);
}
}
const char *crsql_identity(const char *x) { return x; }
char *crsql_join(char **in, size_t inlen) {
return joinHelper(in, inlen, 0, 0);
}
void crsql_joinWith(char *dest, char **src, size_t srcLen, char delim) {
int j = 0;
for (size_t i = 0; i < srcLen; ++i) {
strcpy(dest + j, src[i]);
j += strlen(src[i]);
if (i < srcLen - 1) {
dest[j] = delim;
j += 1;
}
}
}
char *crsql_join2(char *(*map)(const char *), char **in, size_t len,
char *delim) {
if (len == 0) {
return 0;
}
char **toJoin = sqlite3_malloc(len * sizeof(char *));
int resultLen = 0;
char *ret = 0;
for (size_t i = 0; i < len; ++i) {
toJoin[i] = map(in[i]);
resultLen += strlen(toJoin[i]);
}
resultLen += (len - 1) * strlen(delim);
ret = sqlite3_malloc((resultLen + 1) * sizeof(char));
ret[resultLen] = '\0';
int j = 0;
for (size_t i = 0; i < len; ++i) {
strcpy(ret + j, toJoin[i]);
j += strlen(toJoin[i]);
if (i < len - 1) {
strcpy(ret + j, delim);
j += strlen(delim);
}
sqlite3_free(toJoin[i]);
}
sqlite3_free(toJoin);
return ret;
}
char *crsql_getDbVersionUnionQuery(int numRows, char **tableNames) {
char **unionsArr = sqlite3_malloc(numRows * sizeof(char *));
char *unionsStr;
char *ret;
int i = 0;
for (i = 0; i < numRows; ++i) {
unionsArr[i] = sqlite3_mprintf(
"SELECT max(__crsql_db_version) as version FROM \"%w\" %s ",
tableNames[i + 1],
i < numRows - 1 ? UNION_ALL : "");
}
unionsStr = crsql_join(unionsArr, numRows);
for (i = 0; i < numRows; ++i) {
sqlite3_free(unionsArr[i]);
}
sqlite3_free(unionsArr);
ret = sqlite3_mprintf(
"SELECT max(version) as version FROM (%z UNION SELECT value as "
"version "
"FROM crsql_master WHERE key = 'pre_compact_dbversion')",
unionsStr);
return ret;
}
int crsql_getCount(sqlite3 *db, char *zSql) {
int rc = SQLITE_OK;
int count = 0;
sqlite3_stmt *pStmt = 0;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if (rc != SQLITE_OK) {
sqlite3_finalize(pStmt);
return -1 * rc;
}
rc = sqlite3_step(pStmt);
if (rc != SQLITE_ROW) {
sqlite3_finalize(pStmt);
return -1 * rc;
}
count = sqlite3_column_int(pStmt, 0);
sqlite3_finalize(pStmt);
return count;
}