0
0
mirror of https://github.com/tursodatabase/libsql.git synced 2025-06-16 13:23:27 +00:00
Files
.cargo
.github
bindings
bottomless
bottomless-cli
docker-compose
docs
libsql
libsql-ffi
libsql-hrana
libsql-replication
libsql-server
libsql-shell
libsql-sqlite3
art
autoconf
contrib
crates
doc
ext
mptest
src
test
tool
win
GetFile.cs
GetTclKit.bat
Replace.cs
build-all-msvc.bat
build-shell.sh
cg_anno.tcl
checkSpacing.c
cktclsh.sh
custom.txt
dbhash.c
dbtotxt.c
dbtotxt.md
enlargedb.c
extract-sqlite3h.tcl
extract.c
fast_vacuum.c
fragck.tcl
fuzzershell.c
generate-artifacts.sh
genfkey.README
genfkey.test
getlock.c
index_usage.c
kvtest-speed.sh
lemon.c
lempar.c
libvers.c
loadfts.c
logest.c
max-limits.c
merge-test.tcl
mkautoconfamal.sh
mkccode.tcl
mkctimec.tcl
mkkeywordhash.c
mkmsvcmin.tcl
mkopcodec.tcl
mkopcodeh.tcl
mkopts.tcl
mkpragmatab.tcl
mkshellc.tcl
mksourceid.c
mkspeedsql.tcl
mksqlite3c-noext.tcl
mksqlite3c.tcl
mksqlite3h.tcl
mksqlite3internalh.tcl
mktoolzip.tcl
mkvsix.tcl
offsets.c
omittest-msvc.tcl
omittest.tcl
opcodesum.tcl
pagesig.c
pre-release.sh
replace.tcl
restore_jrnl.tcl
rollback-test.c
run-speed-test.sh
showdb.c
showjournal.c
showlocks.c
showshm.c
showstat4.c
showwal.c
soak1.tcl
spaceanal.tcl
speed-check.sh
speedtest.tcl
speedtest16.c
speedtest2.tcl
speedtest8.c
speedtest8inst1.c
spellsift.tcl
split-sqlite3c.tcl
sqldiff.c
sqlite3_analyzer.c.in
sqltclsh.c.in
sqltclsh.tcl
src-verify.c
srcck1.c
srctree-check.tcl
stack_usage.tcl
stripccomments.c
symbols-mingw.sh
symbols.sh
varint.c
vdbe-compress.tcl
vdbe_profile.tcl
version-info.c
warnings-clang.sh
warnings.sh
vsixtest
.gitignore
Dockerfile-wasm-udf
LIBSQL_VERSION
LICENSE.md
Makefile.in
Makefile.linux-gcc
Makefile.msc
README-SQLite.md
VERSION
aclocal.m4
config.guess
config.sub
configure
configure.ac
install-sh
libsql.pc.in
ltmain.sh
magic.txt
main.mk
manifest
manifest.uuid
spec.template
sqlite.pc.in
sqlite3.1
sqlite3.pc.in
sqlite_cfg.h.in
libsql-sys
tools
vendored
xtask
.dockerignore
.env
.gitignore
.gitmodules
CODE_OF_CONDUCT.md
Cargo.lock
Cargo.toml
Dockerfile
Dockerfile.dev
LICENSE.md
README-libsql.md
README.md
docker-entrypoint.sh
fly.toml
rust-toolchain.toml
libsql/libsql-sqlite3/tool/fragck.tcl
2023-10-16 13:58:16 +02:00

150 lines
4.2 KiB
Tcl

# Run this TCL script using "testfixture" to get a report that shows
# the sequence of database pages used by a particular table or index.
# This information is used for fragmentation analysis.
#
# Get the name of the database to analyze
#
if {[llength $argv]!=2} {
puts stderr "Usage: $argv0 database-name table-or-index-name"
exit 1
}
set file_to_analyze [lindex $argv 0]
if {![file exists $file_to_analyze]} {
puts stderr "No such file: $file_to_analyze"
exit 1
}
if {![file readable $file_to_analyze]} {
puts stderr "File is not readable: $file_to_analyze"
exit 1
}
if {[file size $file_to_analyze]<512} {
puts stderr "Empty or malformed database: $file_to_analyze"
exit 1
}
set objname [lindex $argv 1]
# Open the database
#
sqlite3 db [lindex $argv 0]
set DB [btree_open [lindex $argv 0] 1000 0]
# This proc is a wrapper around the btree_cursor_info command. The
# second argument is an open btree cursor returned by [btree_cursor].
# The first argument is the name of an array variable that exists in
# the scope of the caller. If the third argument is non-zero, then
# info is returned for the page that lies $up entries upwards in the
# tree-structure. (i.e. $up==1 returns the parent page, $up==2 the
# grandparent etc.)
#
# The following entries in that array are filled in with information retrieved
# using [btree_cursor_info]:
#
# $arrayvar(page_no) = The page number
# $arrayvar(entry_no) = The entry number
# $arrayvar(page_entries) = Total number of entries on this page
# $arrayvar(cell_size) = Cell size (local payload + header)
# $arrayvar(page_freebytes) = Number of free bytes on this page
# $arrayvar(page_freeblocks) = Number of free blocks on the page
# $arrayvar(payload_bytes) = Total payload size (local + overflow)
# $arrayvar(header_bytes) = Header size in bytes
# $arrayvar(local_payload_bytes) = Local payload size
# $arrayvar(parent) = Parent page number
#
proc cursor_info {arrayvar csr {up 0}} {
upvar $arrayvar a
foreach [list a(page_no) \
a(entry_no) \
a(page_entries) \
a(cell_size) \
a(page_freebytes) \
a(page_freeblocks) \
a(payload_bytes) \
a(header_bytes) \
a(local_payload_bytes) \
a(parent) \
a(first_ovfl) ] [btree_cursor_info $csr $up] break
}
# Determine the page-size of the database. This global variable is used
# throughout the script.
#
set pageSize [db eval {PRAGMA page_size}]
# Find the root page of table or index to be analyzed. Also find out
# if the object is a table or an index.
#
if {$objname=="sqlite_master"} {
set rootpage 1
set type table
} else {
db eval {
SELECT rootpage, type FROM sqlite_master
WHERE name=$objname
} break
if {![info exists rootpage]} {
puts stderr "no such table or index: $objname"
exit 1
}
if {$type!="table" && $type!="index"} {
puts stderr "$objname is something other than a table or index"
exit 1
}
if {![string is integer -strict $rootpage]} {
puts stderr "invalid root page for $objname: $rootpage"
exit 1
}
}
# The cursor $csr is pointing to an entry. Print out information
# about the page that $up levels above that page that contains
# the entry. If $up==0 use the page that contains the entry.
#
# If information about the page has been printed already, then
# this is a no-op.
#
proc page_info {csr up} {
global seen
cursor_info ci $csr $up
set pg $ci(page_no)
if {[info exists seen($pg)]} return
set seen($pg) 1
# Do parent pages first
#
if {$ci(parent)} {
page_info $csr [expr {$up+1}]
}
# Find the depth of this page
#
set depth 1
set i $up
while {$ci(parent)} {
incr i
incr depth
cursor_info ci $csr $i
}
# print the results
#
puts [format {LEVEL %d: %6d} $depth $pg]
}
# Loop through the object and print out page numbers
#
set csr [btree_cursor $DB $rootpage 0]
for {btree_first $csr} {![btree_eof $csr]} {btree_next $csr} {
page_info $csr 0
set i 1
foreach pg [btree_ovfl_info $DB $csr] {
puts [format {OVFL %3d: %6d} $i $pg]
incr i
}
}
exit 0