Post by meerkat on Mar 14, 2019 9:11:28 GMT -5
Great work Carl!
I did a test with a program that used to lock in previous test. Since LB5 is single threaded there should be no locks. All SQL commands are serial so it goes through each command and completes it before the next command. No so on multi threaded, but in those cases most interfaces look for locks and reissue the SQL command on your behalf.
Only problem I had was when trying to change a field that was indexed. In that case SQLite not only has to update the record, but also the B-Tree.
Not sure this is a issue. The system reads 10 records 3 times. Each pass it updates the next 3 records it will be reading. It does not see the changes. Other managed DB's they do. I think SQLite already read the records and does not know they are being change. I can live with that if I know that's the rules.
This test does some nasty stuff. It does 3 passes and reads 10 records. As each record is read, 3 updates take place with 3 different connections. The last statement does a SUBSELECT to find the highest numbers updated.
You have the option to create a index on the aCount field or the record number (aNum). If you create the index on the aCount, the system goes away. The aCount field is the field that gets updated, and when you create a b-tree on it, It has problems..
Thanks for all the work on this Carl.
I did a test with a program that used to lock in previous test. Since LB5 is single threaded there should be no locks. All SQL commands are serial so it goes through each command and completes it before the next command. No so on multi threaded, but in those cases most interfaces look for locks and reissue the SQL command on your behalf.
Only problem I had was when trying to change a field that was indexed. In that case SQLite not only has to update the record, but also the B-Tree.
Not sure this is a issue. The system reads 10 records 3 times. Each pass it updates the next 3 records it will be reading. It does not see the changes. Other managed DB's they do. I think SQLite already read the records and does not know they are being change. I can live with that if I know that's the rules.
This test does some nasty stuff. It does 3 passes and reads 10 records. As each record is read, 3 updates take place with 3 different connections. The last statement does a SUBSELECT to find the highest numbers updated.
You have the option to create a index on the aCount field or the record number (aNum). If you create the index on the aCount, the system goes away. The aCount field is the field that gets updated, and when you create a b-tree on it, It has problems..
Thanks for all the work on this Carl.
' ------------------------------------
' LB5 SQLite lock test with 4 cursors
' ------------------------------------
db$ = "test.db"
sqliteconnect #sql1, db$ ' Connect to the DB
sqliteconnect #sql2, db$ ' Connect to the DB
sqliteconnect #sql3, db$ ' Connect to the DB
sqliteconnect #sql4, db$ ' Connect to the DB
' ----------------------------------------------------------
' if the DB don't exist - create it and populate it
' ----------------------------------------------------------
confirm "Start with a fresh copy of DB";g$
if g$ = "yes" then
#sql1 execute("DROP TABLE tblA")
end if
sql1$ = "SELECT * FROM sqlite_master WHERE tbl_name = 'tblA'"
#sql1 execute(sql1$)
rows = #sql1 ROWCOUNT() 'Get the number of rows
print "sqlite_master Table has ";rows;" records"
if rows = 0 then
sql1$ = "
CREATE TABLE tblA (
aNum integer(5),
aDescr VARCHAR(10),
aCount integer(5))"
#sql1 execute(sql1$)
for i = 1 to 100
#sql1 execute("INSERT INTO tblA VALUES (";i;",'tblA_";right$("000"+str$(i),3);"',0)")
next i
confirm "Create index on aCount";g$
if g$ = "yes" then
#sql1 execute("CREATE UNIQUE INDEX tblAx ON tblA(aCount)")
print "Table A Created With aCount index - btree needs to update"
else
#sql1 execute("CREATE UNIQUE INDEX tblAx ON tblA(aNum)")
print "Table A Created With aNum index - btree not updated"
end if
end if
confirm "Continue";g$
print "-----------------------------------------------"
print "Initial look at 10 rows of table before updates"
print "i","Num","Descr","Count"
sql1$ = "SELECT * FROM tblA LIMIT 10"
#sql1 execute(sql1$)
rows1 = #sql1 ROWCOUNT() 'Get the number of rows
for i = 1 to rows1
#row1 = #sql1 #nextrow()
aNum = #row1 aNum()
aDescr$ = #row1 aDescr$()
aCount = #row1 aCount()
print i,aNum,aDescr$,aCount
next i
print "-------------------------------------------------------"
for pass = 1 to 3
print "---------------- Pass:";pass;" -----------------"
confirm "Continue:";g$
if g$ = "no" then end
print "i","Num","Descr","Count"
sql1$ = "SELECT * FROM tblA LIMIT 10"
#sql1 execute(sql1$)
rows1 = #sql1 ROWCOUNT() 'Get the number of rows
for i = 1 to rows1
#row1 = #sql1 #nextrow()
aNum = #row1 aNum()
aDescr$ = #row1 aDescr$()
aCount = #row1 aCount()
print i,aNum,aDescr$,aCount
sql2$ = "UPDATE tblA SET aCount = ";pass;" WHERE aNum = ";i
#sql2 execute(sql2$)
sql3$ = "UPDATE tblA SET aCount = ";pass;" WHERE aNum = ";i+1
#sql3 execute(sql3$)
sql4$ = "UPDATE tblA SET aCount = ";pass;" WHERE aNum = ";i+2
#sql4 execute(sql4$)
' ------------------------------------------------------------------
' Find the largest count that was updated in the prev sql Update commands
' ------------------------------------------------------------------
sql4$ = "SELECT * FROM tblA WHERE tblA.aCount = " _
+ "(SELECT max(ta.aCount) FROM tblA as ta)"
#sql4 execute(sql4$)
rows4 = #sql4 ROWCOUNT() 'Get the number of rows
#row4 = #sql4 #nextrow()
aNum = #row4 aNum()
aDescr$ = #row4 aDescr$()
aCount = #row4 aCount()
print "-----------SUBSELECT Count:"rows4
print i,aNum,aDescr$,aCount
print "-----------------END SubSelect -----------------"
next i
next pass
print "** End of Test **"
#sql1 disconnect()
#sql2 disconnect()
#sql3 disconnect()
#sql4 disconnect()
confirm "END:";g$
if g$ = "yes" then end
wait
end