esp32_arduino_sqlite3_lib icon indicating copy to clipboard operation
esp32_arduino_sqlite3_lib copied to clipboard

Fixes and Improvements

Open savejeff opened this issue 2 years ago • 2 comments

Hi, as discussed in the other thread, here are the improvements I implemented for the lib

#55

I have attached multiple versions that are more and more modified from the original version. the earlier might be easier to integrate.

sqlite3lib_github_fixes.zip

i renamed esp32.cpp with jhal.cpp

V1: only minor changes but added debug prints for understanding what the lib is doing V2: most of the fixes implemented but still similar to the original code <- I recommend this for importing fixes V3: refactoring and cleanup V4: my current version with working truncate.

V2-V4 uses my own implementation of a filesystem. it has the same functions as the esp fs classes like sd, sd_mmc, spiffs. replacing with the esp functions should be very easy.

if you have a question, just contact me. I recommend using a diff tool like beyond compare to compare the changes

Here are some additional explanations:

################## The File Struct #######################


struct ESP32File {
	sqlite3_file base;              /* Base class. Must be first. */
	jFileSystemClass* jfs; 	// pointer to filesystem (replace this with esps fs instance like sd, mmc, spiffs, ...)
	jFile* fp;                   	// pointer to file (replace this with File from esps fs::File 
	int lock;				// this is the lock applied to this database file
	int id;				// unique identifier for the database file to make debug prints easy

	char *aBuffer;                  /* Pointer to malloc'd buffer */
	int nBuffer;                    /* Valid bytes of data in zBuffer */
	sqlite3_int64 iBufferOfst;      /* Offset in file of zBuffer[0] */
};

##################### Log functions #########################

Log and LogD are just two levels of logging where LogD indicates debug prints only to the console, Log could also log to a logfile. just replace all LogD with Log


#if JSQL_DEBUG==1 // <- set JSQL_DEBUG to 1 to enable debug printing
#define LogX Log
#define LogXD LogD // <- remove "D" to only use Log
#else
#define LogX(...)
#define LogXD(...)
#endif


#include <stdarg.h>

String s_printf(const char* format, ...)
{
	char loc_buf[64];
	char* temp = loc_buf;
	va_list arg;
	va_list copy;
	va_start(arg, format);
	va_copy(copy, arg);
	int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
	va_end(copy);
	if (len < 0) {
		va_end(arg);
		return "";
	};
	if (len >= sizeof(loc_buf)) {
		temp = (char*)malloc(len + 1);
		if (temp == NULL) {
			va_end(arg);
			return "";
		}
		len = vsnprintf(temp, len + 1, format, arg);
	}
	va_end(arg);
	
	String s = String(temp);
	
	if (temp != loc_buf) {
		free(temp);
	}
	return s;
}



extern void Log(const char* format, ...) __attribute__((format(printf, 1, 2)));
void Log(const char* format, ...)
{
	char loc_buf[64];
	char* temp = loc_buf;
	va_list arg;
	va_list copy;
	va_start(arg, format);
	va_copy(copy, arg);
	int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
	va_end(copy);
	if (len < 0) {
		va_end(arg);
		return;
	};
	if (len >= sizeof(loc_buf)) {
		temp = (char*)malloc(len + 1);
		if (temp == NULL) {
			va_end(arg);
			return;
		}
		len = vsnprintf(temp, len + 1, format, arg);
	}
	va_end(arg);


	SerialOut.print("[");
	SerialOut.print(millis());
	SerialOut.print("] ");
	SerialOut.println(temp);

	

	if (temp != loc_buf) {
		free(temp);
	}
}

void Log(const String& msg)
{
	Log(msg.c_str());
}

##################### truncate #############################

here the implementation of truncate in my file system class:

here the file flags:


// Read and Write with Position at end of file. appends starting from end of file
#define _FILE_FLAG_RW_APPEND "a+"

// Read and Write with Position at start file. overrides starting from position 0
// Can be replaced by APPEND and move to first position (seek(0))
#define _FILE_FLAG_RW "r+"
#define _FILE_FLAG_RW_OVERRIDE "w+"

// For read file only
// in General this might work better than w+ when reading a whole file from start to end
#define _FILE_FLAG_R "r"


bool jFileSystemClass::truncate(const String& path, uint32_t size) 
{
	if(!exists(path))
		return false;

	String ftmp = get_tmp_filename();

	LogXD("jfs.%s.truncate: ftmp=%s", get_tag(), ftmp.c_str());

	rename(path, ftmp);

	jFile* f_old = open(ftmp, jFILE_MODE::FILE_FLAG_R);
	jFile* f_new = open(path, jFILE_MODE::FILE_FLAG_RW_OVERRIDE);

	//if(!f_old->isOpen() || !f_new->isOpen())
	//	return false;

	uint32_t size_new = 0;
	uint8_t buff[128];
	while (size_new < size && f_old->available())
	{
		int len = MIN(128, size - size_new);
		int rlen = f_old->read(buff, len);

		f_new->write(buff, rlen);
		size_new += rlen;
	}

	LogXD("jfs.%s.truncate: size=%d, size_new=%d", get_tag(), size, size_new);

	f_old->close();
	f_new->close();

	delete(f_old);
	delete(f_new);

	remove(ftmp);

	return true;
}

String jFileSystemClass::get_tmp_filename() 
{
	//TODO deadlock in case of all temp files are present -> not likely
	while(true) {
		int x = get_random_int(0, 999);
		String fname = s_printf("TMP%02d.BIN", x);
		if(!exists(fname))
			return fname;
	}
}


savejeff avatar May 14 '23 09:05 savejeff

Hi @savejeff , Thanks for sharing this and sorry about the late response. I will work on it and update the library soon!!

siara-cc avatar May 19 '23 12:05 siara-cc

no problem. just wanted to give something back to the open source community.

I think making SQlite available to the Arduino community is a big thing. With the Filesystem abstraction, I'm also able to use the SdFat library and target other processors like RP2040 and SAMD etc. Teensy still has some problems though

savejeff avatar May 19 '23 12:05 savejeff