AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 77251977
Accepted
Gary
Gary
Asked: 2023-10-08 09:03:42 +0800 CST2023-10-08 09:03:42 +0800 CST 2023-10-08 09:03:42 +0800 CST

Usando incrblob para determinar a localização do byte em um segmento BLOB com base na localização de um caractere na string de texto?

  • 772

Minha pergunta diz respeito a esse cenário. Estou armazenando texto como um BLOB usando E/S de blob incremental do SQLite na interface Tcl. Outra tabela no banco de dados contém linhas de dados de ponteiro que apontam para segmentos deste BLOB. Como os canais Tcl procuram locais de bytes e não locais de caracteres (o que presumo ser comum, não estou criticando o Tcl), preciso rastrear o byte_start, char_start, byte_length, char_length de cada ponteiro.

Chega uma solicitação ao Tcl que indica que um ponteiro existente (não os dados reais do buffer, mas apenas o próprio ponteiro) precisa ser dividido em dois ponteiros, começando em algum local de caractere. A solicitação vem da UI e esse código não sabe nada sobre a localização dos bytes e realmente nada sobre o BLOB.

Portanto, preciso extrair o segmento do BLOB, convertê-lo em texto e determinar o comprimento de bytes de pelo menos uma das duas novas partes e usar essas informações para determinar o byte inicial e o comprimento de bytes de ambos os novos ponteiros.

Eu usaria algo como abaixo no SQLite, mas, de acordo com o Dr. Hipp, todo o BLOB deve ser lido na memória para usar substr em um BLOB.

select
   octet_length(
      substr(
         cast(
            substr(
               buffer,
               byte_start,
               byte_length
            ) as text
         ),
         1,
         :len
      )
   )
from
   mem.pt_buffers
where
       doc_id = :doc_id
   and buffer_id = :buffer_id_s
;

Portanto, estou usando incrblob em Tcl que este exemplo ilustra. Parece gerar os resultados corretos, mas também parece dar muito trabalho. Por exemplo, o conteúdo está sendo extraído do BLOB apenas para determinar a posição do byte da posição do caractere do ponto de divisão. O conteúdo não é utilizado de outra forma, nem o BLOB está sendo modificado. Se não houvesse o problema de a posição dos bytes ser desconhecida pela UI, o conteúdo não precisaria ser extraído e a operação seria apenas aritmética.

Minhas perguntas são:

  1. Estou fazendo isso da maneira mais difícil; existe uma abordagem mais simples?
  2. Pode/deve ser feito mais diretamente no SQLite?

Obrigado por considerar minha pergunta.

package require sqlite3
sqlite3 db
db eval {create table test (id integer, data blob);}
db eval {insert into test values (1, zeroblob(100));}
puts [db eval {select id, cast(data as text) from test;}]
# 1 {}

# Previously, a request had to come in to append this string
# to the BLOB; to the non-zero portion, anyway. This is re-
# quired set-up for the question.
set fdBlob [db incrblob main test data 1]
chan configure $fdBlob -translation binary -buffering none
set bindata [encoding convertto utf-8\
     {This is some הַ / נָּבִ֑יא text cast as a BLOB.}]
chan puts -nonewline $fdBlob $bindata

puts [db eval {
   select
      length(data),
      length(cast(data as text)),
      length(:bindata)
   from
      test
   ;
}]
# 100 47 57

# Pre-split pointer data:
# piece  char_start char_length byte_start byte_length
# -----  ---------- ----------- ---------- -----------
# orig        0          47           0         57

# Request comes in to split the pointer at the 27th character
# into two pointers: characters 0-26 and 27-end.

# Retrieve the segment of the BLOB. Have to retrieve the full
# piece because do not know where to split the bytes. Convert
# from binary to text. Note [chan read numChars] reads chars,
# but since channel is configured as binary, same as bytes.
chan seek $fdBlob 0 start
set data [encoding convertfrom utf-8 [chan read $fdBlob 57]]

# Split the piece. Need only one or the other, not both.
set frontEnd [string range $data 0 26]
set tailEnd [string range $data 27 end]
puts "\"$frontEnd\" \"$tailEnd\""
# "This is some הַ / נָּבִ֑יא " "text cast as a BLOB."

# Convert the substring back to binary and determine byte length.
set frontEndByteLen [string length [encoding convertto utf-8 $frontEnd]]
set tailEndByteLen [expr {57-$frontEndByteLen}]
puts "Front-end data: byte_start: 0 byte_length $frontEndByteLen"
puts "Tail-end data: byte_start: $frontEndByteLen byte_length $tailEndByteLen"
# Front-end data: byte_start: 0 byte_length 37
# Tail-end data: byte_start: 37 byte_length 20

# Test it out by seeking to the start byte and extracting the tail-end.
chan seek $fdBlob $frontEndByteLen start
set data [encoding convertfrom utf-8 [chan read $fdBlob $tailEndByteLen]]
puts $data
# text cast as a BLOB.

# Then the pointer table will have these new pieces inserted.
# piece  char_start char_length byte_start byte_length
# -----  ---------- ----------- ---------- -----------
# front       0          27           0         37
# tail       27          20          37         20

sqlite
  • 1 1 respostas
  • 32 Views

1 respostas

  • Voted
  1. Best Answer
    Cyan Ogilvie
    2023-10-08T20:52:52+08:002023-10-08T20:52:52+08:00

    Seu exemplo é como eu abordaria isso, especialmente se o deslocamento do caractere vier de uma UI Tcl. Como o sqlite está em processo, não há nenhuma consideração sobre a latência da rede - é apenas se os cálculos de deslocamento de caracteres estão sendo executados pelo código do sqlite ou pelo Tcl. Tcl é realmente muito bom nisso (gostando muito de strings e tudo mais).

    Principalmente se a UI for Tcl, já que os índices de caracteres concordarão em situações como pares substitutos, etc.

    Pode ser mais eficiente apenas selecionar o valor do blob, dividir com string rangecomandos e atualizar a linha, mas isso dependerá de detalhes sobre como o encapsulamento do canal do valor db é implementado e qual a complexidade que isso implica. É melhor avaliar seu caso real para saber. Outra consideração é que, embora chan seekopere em deslocamentos de bytes, chan readfuncione em caracteres, então pode ser mais fácil buscar as peças dessa maneira (principalmente se for a primeira parte que você deseja - basta procurar 0 e ler tantos caracteres)

    • 0

relate perguntas

  • Restrição CHECK correspondente ao início do valor

  • Discord bot - por que o sqlite não está carregando? Nome do arquivo/erro nulo

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve