• Nenhum resultado encontrado

Gerenciador de Cache do Integra

5.4 Identificador de Subconsultas

5.4.4 Comparador de Consultas

O comparador de consultas do Integra é o módulo responsável por executar uma compara- ção entre duas consultas (representadas em XML) para identificar se uma delas está contida na outra, ou seja, se a resposta de uma delas está contida na resposta da outra.

Uma das representações XML de consulta que são comparadas nesse módulo é enviada pelo módulo Conversor de Consultas, e corresponde à representação XML da consulta submetida pelo usuário. A outra representação XML de consulta é proveniente do módulo Buscador de Consulta, escolhida entre as consultas cujos resultados estão presentes em cache.

O comparador de consultas do Integra foi desenvolvido na linguagem orientada a objetos Java [59]. Para a escolha da linguagem de desenvolvimento do módulo foram levados em consideração alguns fatores, tais como:

• Todos os demais componentes do Integra, inclusive o módulo Conversor de Consulta foram desenvolvidos em Java; desenvolver componentes que interagem entre si numa mesma linguagem facilita a comunicação entre eles;

• Java possui uma vasta API para trabalhar com XML, com funcionalidades que facilitam a navegação e análise de documentos em XML; e

• A linguagem Java é portável, permitindo que o Integra possa rodar em qualquer plata- forma.

5.4.4.1 Implementação

Tendo recebido as duas representações XML referentes à consulta do usuário e à consulta da cache que serão comparadas, o módulo Comparador de Consultas varre as estruturas de cada XML em paralelo, comparando elemento a elemento, como mostra o algoritmo na Figura 5.6.

A primeira ação (linhas 2-3) do algoritmo é verificar se a quantidade de nós do documento XML que representa a consulta submetida pelo usuário (xml_cons_usuario) é maior que a do XML que representa a consulta da cache (xml_cons_cache). Se essa comparação for verda- deira, o sistema já identifica que a consulta do usuário não poderá ser respondida pela consulta

Figura 5.6 Pseudo-código da função IsSubConsulta

que está na cache visto que, certamente, algum nó do primeiro documento XML não terá um correspondente no segundo documento.

Caso a comparação retorne falso, o sistema varrerá cada um dos documentos XML pro- curando encontrar, para cada nó presente no XML do usuário, um correspondente no XML da cache. Essa tarefa será executada pela função ComparacaoElementos (linhas 7-8), cujo pseudo-código é mostrado na Figura 5.7.

A função ComparacaoElementos varre o XML da consulta usuário em paralelo ao XML da consulta da cache. A cada nó do XML do usuário é realizada uma comparação com o nó do XML da cache, através da função IsElementoCorrespondido (linha 6) para saber se o nó do XML do usuário possui correspondência com o da cache. Esta última função será descrita a seguir, mas basicamente compara os tipos e os valores dos elementos. Se esta função retornar Verdadeiro, significa que os tipos dos dois elementos são iguais e o valor do nó do XML do usuário é igual ou está contido no nó do XML da cache.

Havendo a correspondência entre os elementos, a função ComparacaoElementos é chamada recursivamente (linhas 8-11), tendo como parâmetros os nós sucessores do XML do usuário e da cache. Essa chamada recursiva é feita para dar continuidade à comparação com o resto dos elementos.

Caso não haja correspondência entre os elementos, verifica-se se ainda há mais elementos no XML da cache, através da função TemMaisElementos (linha 13). Se houver, a função Com- paracaoElementos é chamada recursivamente (linhas 15-18) tendo como parâmetros o mesmo nó do XML do usuário e o nó sucessor do XML da cache. O nó do XML do usuário permanece o mesmo para que a função busque algum correspondente para ele no XML da cache. Caso a função TemMaisElementos retorne Falso, significa que se chegou ao final do XML da cache e não foi encontrado um nó correspondente ao do XML do usuário.

62

Figura 5.7 Pseudo-código da função ComparacaoElementos

Ao final da execução, a função retorna Falso, indicando que não há equivalência entre os documentos XML.

O pseudo-código da função IsElementoCorrespondido, citada anteriormente, está descrito no algoritmo da Figura 5.8.

A primeira tarefa da função IsElementoCorrespondido é comparar os tipos dos dois ele- mentos recebidos como parâmetro (linha 3). Os tipos dos elementos são definidos pela tag que identifica cada nó do documento XML. Assim, o elemento cuja tag é forClause é considerado do tipo forClause, e só será considerado igual a um outro nó de mesmo tipo. Este elemento especificamente corresponde à representação XML da cláusula for dentro de uma consulta e pode ser visto na Figura 5.3.

Outro tipo de elemento é o generalComp, que corresponde à representação XML de uma comparação que esteja presente na consulta, como “maior que”, “menor que”, “igual”, entre outras.

Figura 5.8 Pseudo-código da função IsElementoCorrespondido

Dessa forma, para cada tipo de elemento o módulo executa uma comparação específica considerando o que chamamos de valor do elemento (linha 4), através da função IsValorCor- responde. Essa avaliação determinará finalmente se o nó do XML do usuário é correspondente ao nó do XML da cache. A seguir mostraremos como é feita essa última comparação para cada tipo de elemento.

Correspondência entre elementos

A cláusula for em XQuery é basicamente formada por atribuições de variáveis. As atri- buições também poderão envolver documentos XML. Essas variáveis poderão ser utilizadas dentro do corpo do for para a montagem da resposta.

Na representação XML produzida pelo XQNSTA, a cláusula for apresenta a seguinte estru- tura: < f o r C l a u s e > < f o r A s s i g n m e n t v a r i a b l e ="X" > . . . </ f o r A s s i g n m e n t > < f o r A s s i g n m e n t v a r i a b l e ="Y" > . . . </ f o r A s s i g n m e n t > </ f o r C l a u s e >

64

Cada atribuição de variável (forAssignment) é composta por um atributo chamado variable, que corresponde à variável que está recebendo a atribuição. A comparação de elementos do tipo forAssignment é feita inicialmente comparando o atributo variable de cada elemento. O sistema verifica se esse atributo possui o mesmo valor nos dois elementos. Se a resposta for positiva, significa que a consulta submetida pelo usuário – pelo menos em relação a este elemento – pode sim estar contida na consulta que está na cache.

Já a comparação de elementos do tipo generalComp é realizada de forma diferente, consi- derando a abrangência de cada comparador. Se a consulta submetida pelo usuário possuir um elemento generalComp, a consulta da cache também deverá possuir um elemento do mesmo tipo, só que de abrangência igual ou maior à primeira. Assim, se a consulta submetida pelo usuário possuir o comparador “=” (igual), a consulta que está na cache poderá responder a primeira consulta se o comparador for “=” (igual), “>=” (maior ou igual) ou “<=” (menor ou igual). A Figura 5.9 mostra como é feita a análise de abrangência de cada comparador. A primeira coluna representa o comparador encontrado na consulta submetida pelo usuário. A se- gunda coluna mostra que situações de comparação devem existir na consulta da cache para que esta consulta possa ser considerada mais abrangente que a primeira, e assim poder respondê-la.

Figura 5.9 Análise de abrangência de comparadores

Assim sendo, se na consulta submetida pelo usuário houver a seguinte comparação na cláu- sula where:

e se na consulta que está em cache for encontrada uma das seguintes comparações: $a = 30 ou $a >= 30 ou $a > 20

o sistema identificará que a consulta submetida pelo usuário poderá estar contida na con- sulta da cache. No entanto, se na consulta da cache, a comparação for:

$a > 30 ou $a < 30 ou $a = 10

o sistema acusará que não há uma relação de inclusão entre as duas consultas.

A cada comparação de elementos de mesmo tipo bem sucedida, o sistema continua var- rendo as duas consultas, executando o mesmo procedimento para os elementos seguintes. Se a comparação dos elementos for negativa, o procedimento de comparação se repete entre o mesmo nó da consulta submetida pelo usuário com o nó seguinte da consulta encontrada na cache. Esse processo se repetirá até que a comparação retorne um resultado positivo ou quando não houver mais elementos a serem comparados na consulta da cache.

5.4.4.2 Funcionamento

O funcionamento do módulo Comparador de Consultas é ilustrado através de dois exem- plos.

Exemplo 1

Considere uma consulta submetida pelo usuário como a representada pela Figura 5.10. O usuário deseja saber o título e o autor de todos os livros cujo preço seja menor ou igual a 30.

Baseado nessa consulta, considere que o buscador de consulta encontrou como consulta que mais se assemelha àquela do usuário a consulta representada pela Figura 5.11.

Os elementos que serão analisados pelo comparador estão sublinhados nas duas consultas. São esses elementos que vão definir se uma consulta está contida em outra.

1º Passo

A comparação entre as duas consultas é feita a partir de cada elemento da consulta sub- metida pelo usuário, que deverá possuir um correspondente na consulta da cache. O primeiro elemento a ser comparado é a variável $b, que é definido dentro do escopo da expressão for. Na representação XML da consulta, esse elemento é do tipo forAssignment. Por ser uma variável, o sistema tem que verificar duas condições:

66

Figura 5.10 Consulta submetida pelo usuário

Figura 5.11 Consulta da cache retornada pelo buscador de consulta

• Se existe uma variável com a mesma identificação criada na consulta da cache; e • Se essa variável é inicializada com o mesmo valor nas duas consultas.

A primeira condição foi criada apenas para facilitar a implementação do módulo compara- dor de consultas, visto que a inexistência dela forçaria o módulo a buscar na consulta da cache outra variável que, mesmo sem possuir a mesma identificação da variável que está na con- sulta submetida pelo usuário, tivesse o mesmo conteúdo, ou seja, o mesmo valor de atribuição. Uma vez encontrada essa variável, o módulo teria que verificar se todas as operações realizadas com a variável da consulta submetida pelo usuário também seriam realizadas com a variável semelhante encontrada na consulta da cache.

No entanto, a forma como o Integra foi idealizado permite que levemos em consideração alguns aspectos que facilitam a implementação do módulo comparador. Um desses aspectos é a garantia de que uma consulta submetida por um usuário sempre será elaborada da mesma forma quantas vezes ela for submetida posteriormente.

Quando o Integra estiver finalizado, ele vai permitir aos seus usuários que elaborem as consultas que desejarem de forma bastante simples e intuitiva. O Gerenciador de Consultas [6] montará o comando da consulta, em XQuery, de forma padronizada. E é a consulta em XQuery que o Gerenciador de Cache receberá e repassará para os módulos buscador e comparador de consultas.

Dessa forma, para a variável em questão ($b), o sistema verificará que a primeira condição é verdadeira, visto que existe na consulta da cache uma variável identificada pelo mesmo nome. E a segunda condição também é verdadeira visto que o conteúdo de inicialização de ambas é o mesmo (doc(“bib.xml”)/bib/livro).

Para as demais variáveis ($t e $a) inicializadas na cláusula for, o sistema também verificará as duas condições e identificará que, até o momento, existe uma relação de inclusão entre as duas consultas.

2º Passo

Comparados os elementos do tipo forAssignment, o sistema irá comparar o próximo ele- mento, que representa a condição necessária para que os registros sejam navegados dentro do loop for. Essa condição é identificada pela cláusula where. Na representação XML da consulta, essa condição se traduz num elemento do tipo whereClause.

No exemplo que estamos analisando, a cláusula where traz uma condição através de um elemento comparador que, na representação XML, é identificado por generalComp. Todo ele- mento comparador envolve dois outros elementos. No caso que estamos analisando, ele envolve uma variável (tipo variable) e um valor (tipo literal).

O sistema verifica se na consulta da cache há um elemento comparador e se ele envolve também uma variável e um valor. Certo disso, deve ser verificado se a variável que está sendo comparada é a mesma em ambas as consultas e só depois é feita a análise do elemento compa- rador nessas consultas.

No exemplo atual, podemos constatar que em ambas as consultas o elemento comparador envolve os mesmos tipos de elemento (variável e valor) e que a variável envolvida na com- paração da consulta submetida pelo usuário ($b/preco) também está envolvida na comparação presente na consulta da cache. Partindo dessa afirmação, o sistema poderá comparar o elemento

68

comparador e o valor envolvido nas duas consultas.

Na consulta submetida pelo usuário, o comparador é menor ou igual. De acordo com a terceira linha da Figura 5.9, quando essa situação ocorre a consulta da cache só tem duas opções de comparador para ser mais abrangente que a submetida pelo usuário, e assim poder respondê-la: menor que ou menor ou igual.

Além disso, devem ser verificados os valores aos quais as variáveis estão sendo comparadas nas duas consultas. O valor na consulta submetida pelo usuário é 30. Se a consulta da cache apresentar o comparador menor que, o valor ao qual a variável está sendo comparada nessa consulta deverá ser um número maior que 30. Caso a consulta da cache apresente o comparador menor ou igual, o valor deverá ser um número maior ou igual a 30.

Como podemos observar na Figura 5.11, o comparador presente na cláusula where da con- sulta proveniente da cache é o menor que e o valor ao qual a variável está sendo comparada é 40. Assim sendo, obedece à condição prevista na Figura 5.9 e o sistema considera que, até então, a consulta da cache é capaz de responder a consulta submetida pelo usuário.

3º Passo

Continuando a comparação entre as duas consultas, o sistema encontra na consulta sub- metida pelo usuário o elemento de retorno (tag <return>). Esse elemento contém o que será retornado pela consulta e como esse resultado estará organizado. É necessário que em ambas as consultas esse elemento seja equivalente porque o que interessa ao sistema no final são os dados retornados pela consulta. Se eles não estiverem adequados ao que o usuário solicitou serão inúteis para a resposta.

O elemento de retorno é identificado dentro da representação XML como do tipo return e é formado por tags e seus respectivos conteúdos. A tag de retorno, que na representação XML é um elemento do tipo tagName, deve existir também na consulta da cache e deve possuir o mesmo identificador em ambas as consultas.

O sistema verifica que nas duas consultas o identificador da tag é o mesmo (livro) e passará, então, a analisar o conteúdo das tags, que é considerado um elemento do tipo elementContent na representação XML.

Na consulta submetida pelo usuário, o conteúdo da tag de retorno é composto por duas variáveis: $t e $a. Podemos observar que esse é o mesmo conteúdo encontrado na tag de retorno da consulta da cache. O sistema identifica essa semelhança e encerra a comparação entre as duas consultas, visto que todos os elementos da consulta submetida pelo usuário foram analisados.

Por ter chegado ao fim da comparação entre as duas consultas de forma positiva, o sistema conclui que a consulta da cache pode responder o que o usuário solicitou, sem a necessidade de ir buscar as informações nas fontes de dados.

Exemplo 2

Consideremos agora uma outra consulta submetida pelo usuário. Suponhamos que ele de- seja conhecer o título e o ano de todos os livros cujos títulos contenham a frase “Database Cache” e tenham sido publicados no ano de 2004 ou 2005.

Essa consulta pode ser representada como na Figura 5.12.

Figura 5.12 Mais uma consulta submetida pelo usuário

Novamente o módulo buscador de consulta tentará encontrar uma consulta que se assemelhe à submetida pelo usuário.

Consideremos que o buscador encontrou na cache a consulta mostrada na Figura 5.13. Encontrada a consulta na cache, o comparador de consulta analisa se a consulta submetida pelo usuário pode ser respondida pela encontrada pelo buscador. Para isso, o comparador varre cada elemento da consulta do usuário buscando um correspondente na consulta da cache.

1º Passo

O procedimento para a verificação da definição e inicialização das variáveis dentro da cláu- sula for já foi discutido no exemplo anterior. Portanto, não entraremos em detalhe sobre tal ponto. No entanto, nota-se que a variável $a, que representa o ano de publicação do livro, está

70

Figura 5.13 Consulta da cache retornada pelo buscador de consulta

restrita a um “domínio” específico. Ou seja, o usuário definiu um conjunto finito de possibili- dades para a restrição sobre o ano de publicação do livro. No caso, o usuário só quer que sejam listados os livros cujo ano seja 2004 ou 2005.

Esse domínio, que na representação XML da consulta é identificado como do tipo expressi- onSequence tem que ser analisado de forma diferenciada pelo sistema, visto que o comparador tem que verificar se o domínio escolhido pelo usuário está contido no domínio da consulta proveniente da cache.

Analisando a consulta da cache, o sistema constata que a variável $a também está definida como um domínio. Nesse caso, o conjunto de anos possíveis para o livro é formado pelos anos 2003, 2004 e 2005. Nota-se que o conjunto do domínio presente na consulta da cache contém o conjunto do domínio definido pelo usuário. Sendo assim, o comparador considera positiva a comparação entre esses dois elementos e passa a analisar o próximo elemento da consulta do usuário.

2º Passo

O próximo elemento a ser analisado pelo comparador merece também uma atenção espe- cial, pois é um elemento de restrição (cláusula where) e apresenta uma função da linguagem XQuery que poderá ser encontrada em várias consultas submetidas pelos usuários: a função contains. Essa função recebe como parâmetros duas strings, dessa forma

contains(string1, string2)

Essa função é bastante útil para se fazer consultas com restrição a partes de um texto, por exemplo. No exemplo, o usuário deseja obter na resposta títulos que contenham a frase “Database Cache”. Assim, um livro cujo título seja “Introduction to Database Cache” deve ser retornado ao usuário.

O comparador de consultas faz um tratamento específico para elementos que envolvam a função contains, verificando as seguintes condições:

• Se na consulta da cache também há o mesmo elemento envolvendo a função contains; • Se a função contains na consulta da cache recebe como primeiro parâmetro a mesma

variável que na consulta do usuário; e

• Se a string passada como segundo parâmetro para a função contains na consulta da cache está contida na string passada na consulta do usuário; ou seja, se a consulta da cache é mais abrangente que a do usuário.

Observando as duas consultas, notamos que o elemento envolvendo a função contains tam- bém está presente na consulta da cache. Constatamos ainda que a variável passada como parâ- metro para essa função é a mesma nas duas consultas. Por fim, o sistema deve verificar a string passada como parâmetro nas duas consultas.

Na consulta submetida pelo usuário, a string passada como parâmetro para a função con- tains é “Database Cache”; já na consulta proveniente da cache, a string é “Cache”. Ou seja, a consulta da cache traz livros cujos títulos contenham a palavra “Cache”. Recupera, portanto, um conjunto de livros maior que a consulta do usuário, sendo mais abrangente.

Assim, o sistema reconhece que as três condições listadas acima foram satisfeitas e, por conseguinte, que até o elemento atual a consulta da cache está dando condições para responder a consulta do usuário.

Os demais elementos são analisados da mesma forma como no primeiro exemplo mostrado, e, ao final da análise de toda a consulta do usuário, o módulo comparador de consulta constata que ela pode ser respondida pela consulta proveniente da cache, sem a necessidade de ser feito acesso às fontes de dados.

Nos dois exemplos citados, mostramos algumas consultas simples, para o fácil entendi- mento e explicação nesse trabalho, mas com os recursos vistos se é capaz de montar consultas bem mais complexas, e que o comparador de consultas consegue tratar.

No entanto, o comparador de consultas ainda trabalha com um subconjunto dos recursos que a linguagem XQuery pode oferecer. Porém, o que se tem hoje é um módulo capaz de atender boa parte das necessidades do sistema Integra.

72

Documentos relacionados