The attached code will use a combination of SQLitening (remote database) and SQLite (local database) to make a row by row copy of the remote database to a local copy.
If the local database doesn't exist it will be created. If the database exists, new remote rows for each table are copied over to the local database tables.
WARNING: The database is currently 678MB...the first build may take a few minutes. My testing was taking about 3.5 minutes to get the full database. Lots of things impact this speed.
If the local database doesn't exist it will be created. If the database exists, new remote rows for each table are copied over to the local database tables.
WARNING: The database is currently 678MB...the first build may take a few minutes. My testing was taking about 3.5 minutes to get the full database. Lots of things impact this speed.
Code:
#BREAK ON #COMPILE EXE #DEBUG DISPLAY ON #DEBUG ERROR ON #DIM ALL #OPTIMIZE SPEED #REGISTER NONE #TOOLS OFF #INCLUDE ONCE "SQLitening.inc" #INCLUDE ONCE "sqlite3.inc" #IF NOT %DEF(%NULL) %NULL = 0??? #ENDIF ' SQLite macro helpers MACRO SQL_EXE(phDB_Stmt,Variable) MACROTEMP dwRC LOCAL dwRC AS DWORD dwRC = sqlite3_exec(phDB_Stmt,BYVAL STRPTR(Variable),%NULL,%NULL,%NULL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "Error...""sqlite3_exec"" failed Error Code = " + FORMAT$(dwRC) CON.STDOUT Variable END IF END MACRO MACRO SQL_BindInt(phDB_Stmt,SQL_StmtParmIndex,Variable) MACROTEMP dwRC LOCAL dwRC AS DWORD dwRC = sqlite3_bind_int(phDB_Stmt,SQL_StmtParmIndex,Variable) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "Error...""sqlite3_bind_int"" failed Error Code = " + FORMAT$(dwRC) END IF END MACRO MACRO SQL_BindString(phDB_Stmt,SQL_StmtParmIndex,Variable) MACROTEMP dwRC LOCAL dwRC AS DWORD dwRC = sqlite3_bind_text(phDB_Stmt,SQL_StmtParmIndex,BYVAL STRPTR(Variable),LEN(Variable),%SQLITE_STATIC) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "Error...""sqlite3_bind_text"" failed Error Code = " + FORMAT$(dwRC) END IF END MACRO FUNCTION PBMAIN LOCAL dwRC AS LONG LOCAL dwWork AS LONG LOCAL pDB AS LONG POINTER LOCAL hSQL AS DWORD LOCAL sSQL AS STRING LOCAL sDB_LOCAL_FileName AS STRING ' Database table fields LOCAL dwCol_RowID AS DWORD LOCAL sCol_RecordAddedDate AS STRING LOCAL sCol_Name AS STRING LOCAL sCol_ForumURL AS STRING LOCAL sCol_Author AS STRING LOCAL dwCol_ThreadNumber AS DWORD LOCAL sCol_ThreadURL AS STRING LOCAL dwCol_Forum_Link AS DWORD LOCAL sCol_ThreadTitle AS STRING LOCAL dwCol_Thread_Link AS DWORD LOCAL dwCol_PostNumber AS DWORD LOCAL dwCol_Author_Link AS DWORD LOCAL sCol_PostDate AS STRING LOCAL sCol_PostContent AS STRING sDB_LOCAL_FileName = EXE.Path$ + "PBforum_LOCAL.db" ' Create/Open the LOCAL SQLite database dwRC = sqlite3_open_v2(BYVAL STRPTR(sDB_LOCAL_FileName),pDB,%SQLITE_OPEN_READWRITE OR %SQLITE_OPEN_CREATE,"") IF dwRC <> %SQLITE_OK THEN STDOUT "Error opening database" EXIT FUNCTION END IF ' Set SQLite Database Options sSQL = "PRAGMA foreign_keys=TRUE; " + _ "PRAGMA journal_mode=DELETE; " + _ "PRAGMA synchronous=NORMAL;" SQL_EXE(pDB,sSQL) ' Create the LOCAL database tables if they don't exist sSQL = "CREATE TABLE IF NOT EXISTS Forums " + _ "(RowID INTEGER PRIMARY KEY AUTOINCREMENT, " + _ " RecordAddedDate TEXT(15) NOT NULL, " + _ " Name TEXT(50) UNIQUE NOT NULL COLLATE NOCASE, " + _ " ForumURL TEXT UNIQUE NOT NULL COLLATE NOCASE); " + _ "CREATE TABLE IF NOT EXISTS ForumAuthors " + _ "(RowID INTEGER PRIMARY KEY AUTOINCREMENT, " + _ " RecordAddedDate TEXT(15) NOT NULL, " + _ " Author TEXT(25) UNIQUE NOT NULL COLLATE NOCASE); " + _ "CREATE TABLE IF NOT EXISTS Threads " + _ "(RowID INTEGER PRIMARY KEY AUTOINCREMENT, " + _ " RecordAddedDate TEXT(15) NOT NULL, " + _ " ThreadNumber INTEGER UNIQUE NOT NULL, " + _ " ThreadURL TEXT UNIQUE NOT NULL COLLATE NOCASE, " + _ " Forum_Link INTEGER NOT NULL, " + _ " ThreadTitle TEXT(20) NOT NULL COLLATE NOCASE, " + _ " FOREIGN KEY(Forum_Link) REFERENCES Forums(RowID)); " + _ "CREATE TABLE IF NOT EXISTS ThreadContent " + _ "(RowID INTEGER PRIMARY KEY AUTOINCREMENT, " + _ " RecordAddedDate TEXT(15) NOT NULL, " + _ " Thread_Link INTEGER NOT NULL, " + _ " PostNumber INTEGER NOT NULL, " + _ " Author_Link INTEGER NOT NULL, " + _ " PostDate TEXT(15) NOT NULL, " + _ " PostContent TEXT NOT NULL, " + _ " FOREIGN KEY(Thread_Link) REFERENCES Threads(ThreadNumber)," + _ " FOREIGN KEY(Author_Link) REFERENCES ForumAuthors(RowID));" SQL_EXE(pDB,sSQL) ' Connect and Open the remote database slConnect "38.17.54.213",51234 slOpen "PBforum\PBforum.db" + $BS + "Read%Only", "R" '1 open with read-only password sSQL = "BEGIN TRANSACTION" SQL_EXE(pDB,sSQL) ' Begin SQLite transaction ' ------------------------ Copy table "Forums" -------------------------- ' Prepare the INSERT statement for the LOCAL database sSQL = "INSERT INTO Forums " + _ " (RowID, " + _ " RecordAddedDate, " + _ " Name, " + _ " ForumURL) " + _ " VALUES(?,?,?,?)" dwRC = sqlite3_prepare_v2(pDB,BYVAL STRPTR(sSQL),LEN(sSQL),hSQL,%NULL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_prepare_v2 failed " + FORMAT$(dwRC) CON.STDOUT sSQL EXIT FUNCTION END IF ' Select rows from the REMOTE database sSQL = "SELECT T1.RowID, " + _ " T1.RecordAddedDate, " + _ " T1.Name, " + _ " T1.ForumURL " + _ " FROM Forums T1 " + _ " WHERE T1.RowID > " + FORMAT$(GetTableMaxRowID(pDB,"Forums")) slSel sSQL DO WHILE slGetRow dwCol_RowID = VAL(slF(1)) sCol_RecordAddedDate = slF(2) sCol_Name = slF(3) sCol_ForumURL = slF(4) SQL_BindInt(hSQL,1,dwCol_RowID) SQL_BindString(hSQL,2,sCol_RecordAddedDate) SQL_BindString(hSQL,3,sCol_Name) SQL_BindString(hSQL,4,sCol_ForumURL) dwRC = sqlite3_step(hSQL) IF dwRC <> %SQLITE_DONE THEN CON.STDOUT "sqlite3_step failed " + FORMAT$(dwRC) EXIT FUNCTION END IF dwRC = sqlite3_reset(hSQL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_reset failed " + FORMAT$(dwRC) EXIT FUNCTION END IF LOOP dwRC = sqlite3_finalize(hSQL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_finalize failed " + FORMAT$(dwRC) EXIT FUNCTION END IF ' ---------------------- Copy table "ForumAuthors" ---------------------- ' Prepare the INSERT statement for the LOCAL database sSQL = "INSERT INTO ForumAuthors " + _ " (RowID, " + _ " RecordAddedDate, " + _ " Author) " + _ " VALUES(?,?,?)" dwRC = sqlite3_prepare_v2(pDB,BYVAL STRPTR(sSQL),LEN(sSQL),hSQL,%NULL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_prepare_v2 failed " + FORMAT$(dwRC) CON.STDOUT sSQL EXIT FUNCTION END IF ' Select rows from the REMOTE database sSQL = "SELECT T1.RowID, " + _ " T1.RecordAddedDate, " + _ " T1.Author " + _ " FROM ForumAuthors T1 " + _ " WHERE T1.RowID > " + FORMAT$(GetTableMaxRowID(pDB,"ForumAuthors")) slSel sSQL DO WHILE slGetRow dwCol_RowID = VAL(slF(1)) sCol_RecordAddedDate = slF(2) sCol_Author = slF(3) SQL_BindInt(hSQL,1,dwCol_RowID) SQL_BindString(hSQL,2,sCol_RecordAddedDate) SQL_BindString(hSQL,3,sCol_Author) dwRC = sqlite3_step(hSQL) IF dwRC <> %SQLITE_DONE THEN CON.STDOUT "sqlite3_step failed " + FORMAT$(dwRC) EXIT FUNCTION END IF dwRC = sqlite3_reset(hSQL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_reset failed " + FORMAT$(dwRC) EXIT FUNCTION END IF LOOP dwRC = sqlite3_finalize(hSQL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_finalize failed " + FORMAT$(dwRC) EXIT FUNCTION END IF ' ------------------------ Copy table "Threads" ------------------------- ' Prepare the INSERT statement for the LOCAL database sSQL = "INSERT INTO Threads " + _ " (RowID, " + _ " RecordAddedDate, " + _ " ThreadNumber, " + _ " ThreadURL, " + _ " Forum_Link, " + _ " ThreadTitle) " + _ " VALUES(?,?,?,?,?,?)" dwRC = sqlite3_prepare_v2(pDB,BYVAL STRPTR(sSQL),LEN(sSQL),hSQL,%NULL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_prepare_v2 failed " + FORMAT$(dwRC) CON.STDOUT sSQL EXIT FUNCTION END IF ' Select rows from the REMOTE database sSQL = "SELECT T1.RowID, " + _ " T1.RecordAddedDate, " + _ " T1.ThreadNumber, " + _ " T1.ThreadURL, " + _ " T1.Forum_Link, " + _ " T1.ThreadTitle " + _ " FROM Threads T1 " + _ " WHERE T1.RowID > " + FORMAT$(GetTableMaxRowID(pDB,"Threads")) slSel sSQL DO WHILE slGetRow dwCol_RowID = VAL(slF(1)) sCol_RecordAddedDate = slF(2) dwCol_ThreadNumber = VAL(slF(3)) sCol_ThreadURL = slF(4) dwCol_Forum_Link = VAL(slF(5)) sCol_ThreadTitle = slF(6) SQL_BindInt(hSQL,1,dwCol_RowID) SQL_BindString(hSQL,2,sCol_RecordAddedDate) SQL_BindInt(hSQL,3,dwCol_ThreadNumber) SQL_BindString(hSQL,4,sCol_ThreadURL) SQL_BindInt(hSQL,5,dwCol_Forum_Link) SQL_BindString(hSQL,6,sCol_ThreadTitle) dwRC = sqlite3_step(hSQL) IF dwRC <> %SQLITE_DONE THEN CON.STDOUT "sqlite3_step failed " + FORMAT$(dwRC) EXIT FUNCTION END IF dwRC = sqlite3_reset(hSQL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_reset failed " + FORMAT$(dwRC) EXIT FUNCTION END IF LOOP dwRC = sqlite3_finalize(hSQL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_finalize failed " + FORMAT$(dwRC) EXIT FUNCTION END IF ' --------------------- Copy table "ThreadContent" ---------------------- ' Prepare the INSERT statement for the LOCAL database sSQL = "INSERT INTO ThreadContent " + _ " (RowID, " + _ " RecordAddedDate, " + _ " Thread_Link, " + _ " PostNumber, " + _ " Author_Link, " + _ " PostDate, " + _ " PostContent) " + _ " VALUES(?,?,?,?,?,?,?)" dwRC = sqlite3_prepare_v2(pDB,BYVAL STRPTR(sSQL),LEN(sSQL),hSQL,%NULL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_prepare_v2 failed " + FORMAT$(dwRC) CON.STDOUT sSQL EXIT FUNCTION END IF ' Select rows from the REMOTE database sSQL = "SELECT T1.RowID, " + _ " T1.RecordAddedDate, " + _ " T1.Thread_Link, " + _ " T1.PostNumber, " + _ " T1.Author_Link, " + _ " T1.PostDate, " + _ " T1.PostContent " + _ " FROM ThreadContent T1 " + _ " WHERE T1.RowID > " + FORMAT$(GetTableMaxRowID(pDB,"ThreadContent")) slSel sSQL DO WHILE slGetRow dwCol_RowID = VAL(slF(1)) sCol_RecordAddedDate = slF(2) dwCol_Thread_Link = VAL(slF(3)) dwCol_PostNumber = VAL(slF(4)) dwCol_Author_Link = VAL(slF(5)) sCol_PostDate = slF(6) sCol_PostContent = slF(7) SQL_BindInt(hSQL,1,dwCol_RowID) SQL_BindString(hSQL,2,sCol_RecordAddedDate) SQL_BindInt(hSQL,3,dwCol_Thread_Link) SQL_BindInt(hSQL,4,dwCol_PostNumber) SQL_BindInt(hSQL,5,dwCol_Author_Link) SQL_BindString(hSQL,6,sCol_PostDate) SQL_BindString(hSQL,7,sCol_PostContent) dwRC = sqlite3_step(hSQL) IF dwRC <> %SQLITE_DONE THEN CON.STDOUT "sqlite3_step failed " + FORMAT$(dwRC) EXIT FUNCTION END IF dwRC = sqlite3_reset(hSQL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_reset failed " + FORMAT$(dwRC) EXIT FUNCTION END IF LOOP dwRC = sqlite3_finalize(hSQL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_finalize failed " + FORMAT$(dwRC) EXIT FUNCTION END IF sSQL = "END TRANSACTION" SQL_EXE(pDB,sSQL) ' End SQLite transaction sSQL = "VACUUM" SQL_EXE(pDB,sSQL) ' Vacuum the database ' Close and Disconnect the remote database slClose slDisconnect ' Close the LOCAL database dwRC = sqlite3_close(pDB) IF dwRC <> %SQLITE_OK THEN STDOUT "Error closing SQLite database " + FORMAT$(dwRC) END IF END FUNCTION FUNCTION GetTableMaxRowID(pDB AS DWORD,sTableName AS STRING) AS DWORD LOCAL dwRC AS DWORD LOCAL hSQL AS DWORD LOCAL sSQL AS STRING LOCAL dwRowCount AS DWORD sSQL = "SELECT MAX(RowID) FROM " + sTableName dwRC = sqlite3_prepare_v2(pDB,BYVAL STRPTR(sSQL),LEN(sSQL),hSQL,%NULL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_prepare_v2 failed " + FORMAT$(dwRC) CON.STDOUT sSQL EXIT FUNCTION END IF dwRC = sqlite3_step(hSQL) IF dwRC <> %SQLITE_ROW THEN CON.STDOUT "sqlite3_step failed " + FORMAT$(dwRC) CON.STDOUT sSQL EXIT FUNCTION END IF dwRowCount = sqlite3_column_int(hSQL,0) dwRC = sqlite3_reset(hSQL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_reset failed " + FORMAT$(dwRC) EXIT FUNCTION END IF dwRC = sqlite3_finalize(hSQL) IF dwRC <> %SQLITE_OK THEN CON.STDOUT "sqlite3_finalize failed " + FORMAT$(dwRC) EXIT FUNCTION END IF FUNCTION = dwRowCount END FUNCTION
Comment