At the moment I write my own Database in PureBasic. Complete from the scratch, without any given codes. While development, I learned a lot of things about PB. And I think, I want to share this here.
Maps:
Code: Select all
;Slow
ForEach *db\schema("Test")\table("Test")\datas()
...
Next
;Fast
Protected *schema.strSchema=FindMapElement(*db\schema(),"Test")
Protected *table.strTable=FindMapElement(*schema\table(),"Test")
ForEach *table\datas()
...
Next
Write to File:
Code: Select all
;Slow
WriteByte(file,4)
WriteString(file,"Test")
WriteByte(file,4)
WriteString(file,"Test")
;Fast
*m=AllocateMemory(10)
PokeB(*m,4)
PokeS(*m+1,"Test")
PokeB(*m+5,4)
PokeS(*m+6,"Test")
WriteData(file,*m,10)
Code: Select all
;Always use Encoding for Strings and Files
#ENCODING = #PB_UTF8
#PEEKS_ENCODING = #ENCODING | #PB_ByteLength
#POKES_ENCODING = #ENCODING | #PB_String_NoZero
#FILE_FLAGS = #ENCODING | #PB_File_SharedRead | #PB_File_SharedWrite | #PB_File_NoBuffering
#WRITE_STRING = #ENCODING | #PB_File_IgnoreEOL
Code: Select all
Global T_USERNAME.s=ComputerName()+"\"+UserName()
Global T_S_BYTE=SizeOf(Byte)
Global T_S_INTEGER=SizeOf(Integer)
Global T_S_LONG=SizeOf(Long)
Global T_S_QUAD=SizeOf(Quad)
Global T_S_DOUBLE=SizeOf(Double)
Global T_S_FLOAT=SizeOf(Float)
Global T_S_ROOT=SizeOf(strRoot)
- In Memory
- DB with File
- Reopen a File
Code: Select all
;Faster FindString
ImportC ""
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
_wcsstr_(*String1, *String2) As "wcsstr"
CompilerElse
_wcsstr_(*String1, *String2) As "_wcsstr"
CompilerEndIf
EndImport
Procedure.i FindStringC(s.s, c.s)
Protected.i *pcs = _wcsstr_(@s, @c)
If *pcs
ProcedureReturn (*pcs - @s) >> 1 + 1
EndIf
EndProcedure[size=200][/size]
; I don't have a better Replacement for ReplaceString
Code: Select all
;Slow
result.b=PeekB(*buffer+pos):pos+SizeOf(Byte)
;Fast
Procedure.b _peek_byte(*pos.Quad,*buffer)
Protected result.b=PeekB(*buffer+*pos\q)
*pos\q+T_S_BYTE
ProcedureReturn Result
EndProcedure
result.b=_peek_byte(@pos,*m)
If you work with FileBuffers, there is a big different between Filesize("test.txt") and LOF(file).
FileSize gives you the Size of the File on the HardDrive.
LOF gives you the size of the file on the HardDrive + the Data writen in the Buffer.
Date:
Use your own Date Format and Date Procedures. My DateTime can have Time between the years -999.999 > 999.999.
------------------------------------------------------------------------------------------------------------------------
There are much more Things, but this were the biggest mistakes I did and slowed down my DB.
At the Moment my DB has this Interface. But I'm working on a DLL Version and SQL.
Code: Select all
Enumeration _datatype
#_DATATYPE_NONE
#_DATATYPE_STRING
#_DATATYPE_BYTE
#_DATATYPE_INTEGER
#_DATATYPE_LONG
#_DATATYPE_QUAD
#_DATATYPE_DOUBLE
#_DATATYPE_FLOAT
#_DATATYPE_DATE
#_DATATYPE_TIME
#_DATATYPE_DATETIME
#_DATATYPE_MEMORY
EndEnumeration
Enumeration _type
#_TYPE_NONE
#_TYPE_DB
#_TYPE_TABLE
#_TYPE_DATA
#_TYPE_VIEW
#_TYPE_JOIN
#_TYPE_UNION
#_TYPE_USER
#_TYPE_SCHEMA
#_TYPE_RESULT
EndEnumeration
Enumeration _join
#_JOIN_CROSS
#_JOIN_INNER
#_JOIN_LEFT
#_JOIN_RIGHT
EndEnumeration
Interface Object
Free()
GetLastError.s()
EndInterface
Interface Head Extends Object
GetID.q()
GetCreated.q()
GetModified.q()
GetVersion.q()
GetType.b()
EndInterface
Interface Named Extends Head
GetCreator.s():GetModifier.s()
GetName.s():SetName(name.s)
GetSchema.s():SetSchema(schema.s)
EndInterface
#CURRENT_TIME="CURRENT_TIME"
#CURRENT_DATE="CURRENT_DATE"
#CURRENT_DATETIME="CURRENT_DATETIME"
#CURRENT_TIMESTAMP="CURRENT_TIMESTAMP"
Interface DataContainer Extends Named
EndInterface
Interface Table Extends DataContainer
AddString(name.s,nullable.b=#True,defaultvalue.s="",index.b=#False,unique.b=#False,primarykey.b=#False)
AddByte(name.s,nullable.b=#True,defaultvalue.s="",index.b=#False,unique.b=#False,primarykey.b=#False)
AddInteger(name.s,nullable.b=#True,defaultvalue.s="",index.b=#False,unique.b=#False,primarykey.b=#False)
AddLong(name.s,nullable.b=#True,defaultvalue.s="",index.b=#False,unique.b=#False,primarykey.b=#False)
AddQuad(name.s,nullable.b=#True,defaultvalue.s="",index.b=#False,unique.b=#False,primarykey.b=#False)
AddDouble(name.s,decimal.b=2,nullable.b=#True,defaultvalue.s="",index.b=#False,unique.b=#False,primarykey.b=#False)
AddFloat(name.s,decimal.b=2,nullable.b=#True,defaultvalue.s="",index.b=#False,unique.b=#False,primarykey.b=#False)
AddDate(name.s,format.s="%dd.%mm.%yyyy",nullable.b=#True,defaultvalue.s="",index.b=#False,unique.b=#False,primarykey.b=#False)
AddTime(name.s,format.s="%hh:%ii:%ss",nullable.b=#True,defaultvalue.s="",index.b=#False,unique.b=#False,primarykey.b=#False)
AddDateTime(name.s,format.s="%dd.%mm.%yyyy %hh:%ii:%ss",nullable.b=#True,defaultvalue.s="",index.b=#False,unique.b=#False,primarykey.b=#False)
AddMemory(name.s,nullable.b=#True)
AddIndex(field.s,gruppe.s="")
AddUnique(field.s,gruppe.s="")
AddPrimaryKey(field.s)
EndInterface
Interface Result Extends Head
GetCreator.s():GetModifier.s()
GetSchema.s()
GetTable.s()
GetFieldNames(List names.s())
GetFieldType.b(name.s)
GetString.s(name.s)
GetByte.b(name.s)
GetInteger.i(name.s)
GetLong.l(name.s)
GetQuad.q(name.s)
GetDouble.d(name.s)
GetFloat.f(name.s)
GetDate.s(name.s)
GetTime.s(name.s)
GetDateTime.s(name.s)
GetFormat.s(name.s)
GetMemory(name.s,*buffer,len.q)
GetMemoryLen.q(name.s)
AsString.s(name.s)
AsNumeric.q(name.s)
AsDecimal.d(name.s)
EndInterface
Interface Data Extends Result
SetSchema(schema.s)
SetTable(table.s)
SetString(name.s,value.s)
SetByte(name.s,value.b)
SetInteger(name.s,value.i)
SetLong(name.s,value.l)
SetQuad(name.s,value.q)
SetDouble(name.s,value.d)
SetFloat(name.s,value.f)
SetDate(name.s,value.s,format.s="%dd.%mm.%yyyy")
SetTime(name.s,value.s,format.s="%hh:%ii:%ss")
SetDateTime(name.s,value.s,format.s="%dd.%mm.%yyyy %hh:%ii:%ss")
SetMemory(name.s,*buffer,len.q)
SetDecimal(name.s,value.s)
SetNull(name.s)
EndInterface
Prototype.b ProtoWhere(*result.Result)
Interface View Extends DataContainer
GetDatacontainer.s():SetDatacontainer(datacontainer.s)
AddGroupBy(field.s)
AddOrderBy(field.s)
SetOrderOption(option.b=#PB_Sort_Ascending)
AddField(field.s,name.s="")
AddMax(field.s,name.s="")
AddMin(field.s,name.s="")
AddAvg(field.s,name.s="")
AddCount(field.s,name.s="")
AddSum(field.s,name.s="")
AddConcat(field.s,seperator.s=", ",name.s="")
EndInterface
Interface Join Extends DataContainer
GetJoin.b():SetJoin(join.b=#_JOIN_INNER)
SetDatacontainer1(datacontainer.s)
SetDatacontainer2(datacontainer.s)
AddField1(field.s)
AddField2(field.s)
AddJoinField1(field.s)
AddJoinField2(field.s)
EndInterface
Interface Union Extends DataContainer
AddDatacontainer(datacontainer.s)
EndInterface
Interface Schema Extends Head
GetName.s():SetName(name.s)
EndInterface
Interface DB Extends Head
GetDBVersion.s()
insertTable(*table.Table)
insertData(*data.Data)
insertJoin(*join.Join)
insertUnion(*union.Union)
insertView(*view.View)
insertSchema(*schema.Schema)
BeginBatch()
Commit()
Rollback()
Vacuum()
Reload()
IsReadOnly.b()
countTable(schema.s="")
countData(table.s,schema.s="")
countJoin(schema.s="")
countUnion(schema.s="")
countView(schema.s="")
countSchema()
TableNames(List names.s(),schema.s="")
JoinNames(List names.s(),schema.s="")
UnionNames(List names.s(),schema.s="")
ViewNames(List names.s(),schema.s="")
SchemaNames(List names.s())
IndexNames(table.s,gruppe.s,List names.s(),schema.s="")
UniqueNames(table.s,gruppe.s,List names.s(),schema.s="")
deleteTable(name.s,schema.s="")
deleteJoin(name.s,schema.s="")
deleteUnion(name.s,schema.s="")
deleteView(name.s,schema.s="")
deleteSchema(name.s)
DeleteDatas.q(table.s,where.ProtoWhere=0,schema.s="")
UpdateDatas.q(table.s,*data.Data,where.ProtoWhere=0,schema.s="")
ListTableDatas.q(table.s,List datas.Result(),where.ProtoWhere=0,schema.s="",offset.q=-1,limit.q=-1)
ListViewData.q(view.s,List result.Result(),where.ProtoWhere=0,schema.s="",offset.q=-1,limit.q=-1)
ListUnionData.q(union.s,List result.Result(),where.ProtoWhere=0,schema.s="",offset.q=-1,limit.q=-1)
ListJoinData.q(join.s,List result.Result(),where.ProtoWhere=0,schema.s="",offset.q=-1,limit.q=-1)
ListContainerData.q(datacontainer.s,List result.Result(),where.ProtoWhere=0,schema.s="",offset.q=-1,limit.q=-1)
ListTableIndexDatas.q(table.s,index.s,value.s,List datas.Result(),where.ProtoWhere=0,schema.s="",offset.q=-1,limit.q=-1)
hasTable.b(name.s,schema.s="")
hasJoin.b(name.s,schema.s="")
hasUnion.b(name.s,schema.s="")
hasView.b(name.s,schema.s="")
hasSchema.b(name.s)
EndInterface