forked from duartedenio/uffsdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLeia-me[Instrucoes].txt
386 lines (264 loc) · 17.7 KB
/
Leia-me[Instrucoes].txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
########## LEIA-ME PARTE 1 ##############################################################################################################
=> 15 Julho 2014 <=
Universidade Federal da Fronteira Sul – UFFS
Curso: Ciência da Computação
Componente Curricular: Banco de Dados II
Professor: Dr. Denio Duarte
Alunos: Gabrielle Almeida de Souza e Lais Borin
Introdução
Trabalho desenvolvido para o componente curricular de Banco de Dados II, sua finalidade é implementar a criação de tabelas, bem como a inclusão de tuplas em disco e remoção de tuplas do buffer complementando o que ja havia sido feito anteriormente.
Sobre o dicionário de dados e o esquema:
Por definição, o dicionário de dados está no aquivo fs_object.dat e o esquema em fs_schema.dat, os mesmos serão criados no diretório raiz da pasta dos fontes.
São carregados na memória pelas funçõe leObjeto(nTabela) e leSchema(objeto) e tem a seguinte estrutura:
struct fs_objects { // Estrutura usada para carregar fs_object.dat
char nome[20];
int cod;
char nArquivo[20];
int qtdCampos;
};
typedef struct tp_table{ // Estrutura usada para carregar fs_schema.dat
char nome[TAMANHO_NOME_CAMPO];
char tipo;
int tam;
struct tp_table *next;
}tp_table;
O arquivo fs_object.dat organiza-se da seguinte forma:
20B que representam o nome da tabela;
1B que representam o código da tabela;
20B que representa o nome do arquivo onde estão as tuplas da tabela;
4B que representa a quantidade de campos da tabela.
O arquivo fs_schema.dat organiza-se da seguinte forma:
4B que representam o codigo da tabela; (Código que representa a tabela em fs_objects.dat)
40B que representam o nome do campo;
1B que representa o tipo do campo;
4B que representa o tamanho do campo.
Caso os arquivos fs_object.dat e fs_schema.dat não existam ainda, quando chamada, a função finalizaTabela(...) criará os mesmos adicionando os dados da tabela criada.
Sobre a criação e inserção em tabelas:
Para criar uma tabela é necessário uma estrutura do tipo 'table'. Esta estrutura armazenará os dados da tabela a ser criada.
Após a criação de uma istância de 'table' é necessário iniciá-la com o nome da tabla a ser criada usando a função iniciaTabela(nomeTabela):
table *t = NULL;
t = iniciaTabela("Pessoa");
A partir da iniciação da tabela, pode-se adicionar os campos utilizando a função adicionaCampo(t, nomeCampo, tipoCampo, tamanhoCampo):
t = adicionaCampo(t, "Nome", 'S', 20); // Cria um campo de nome 'Nome' do tipo string e de tamanho 20
t = adicionaCampo(t, "Idade", 'I', 4); // Cria um campo de nome 'Idade' do tipo inteiro e de tamanho 4
Agora, para a tabela ser finalmente adicionada ao dicionário de dados e ao esquema, chama-se a função finalizaTabela(t);
Criada a tabela, pode-se inserir os dados.
Quanto da inserção, é necessário criar uma estrutura do tipo 'column' que criará uma lista encadeada de valores a serem adicionados a tabela.
Para adicionar uma tupla na tabela, é preciso inserir valor por valor de cada campo chamando a função insereValor(c, nomeCampo, valorCampo):
column *c = NULL;
c = insereValor(c, "Nome", "Joana");
c = insereValor(c, "Idade", "40");
OBS: A inserção dos dados deve ocorrer na sequência de criação de campo, sendo que não é possível realizar a inserção incompleta de uma tupla
Assim, com os dados já adicionados na tabela, basta chamar a função finalizaInsert(nomeTabela, c) para gravar as tuplas no arquivo nomeTabela.dat, que armazena os dados referente a esta tabela:
finalizaInsert("Pessoa", c);
Sobre inserir uma tupla no buffer:
Para adicionar uma tupla no buffer, realize o seguinte tendo já o bufferpoll, o esquema e o objeto devidamete inicializados:
colocaTuplaBuffer(bufferpoll, 0, esquema, objeto); // Onde '0' é tupla a ser adicionada, relativa a ordem de inserção em sua tabela
Sobre excluir uma tupla do buffer e recuperar uma página do buffer:
Para excluir uma tupla e obter a mesma para impressão, basta chamar a função com o buffer, esquema, a página a excluir uma tupla e a tupla a ser excluida:
column *tuplaE = excluirTuplaBuffer(buffer, esquema, objeto, 0, 2); // '2' é a posição da tupla relativa a página do buffer
Para recuperar uma página do buffer, bem como obter esta página, basta chamar a função com o buffer, o esquema e o número da página a ser recuperada, como segue:
column *pagina = getPage(bufferpoll, esquema, objeto, 0);
A estrutura do tipo 'column' foi criada com o objetivo de armazenar os dados das tabelas, bem como para promover possíveis impressões de dados.
Da compilação:
$ gcc *.c -o prog -Wall
$ ./prog <Nome da Tabela>
########## LEIA-ME PARTE 2 ##############################################################################################################
=> 16 outubro 2014 <=
Universidade Federal da Fronteira Sul – UFFS
Curso: Ciência da Computação
Componente Curricular: Banco de Dados II
Professor: Dr. Denio Duarte
Alunos: Natan J. Mai, Ricardo Zanuzzo, Rogerio T. Schmidt
Introdução
Trabalho desenvolvido para o componente curricular de Banco de Dados II, sua finalidade é implementar a criação de tabelas, bem como a inclusão de tuplas em disco e remoção de tuplas do buffer complementando o que ja havia sido feito anteriormente.
Sobre o dicionário de dados e o esquema:
Por definição, o dicionário de dados está no aquivo fs_object.dat e o esquema em fs_schema.dat, os mesmos serão criados no diretório raiz da pasta dos fontes.
São carregados na memória pelas funçõe leObjeto(nTabela) e leSchema(objeto) e tem a seguinte estrutura:
struct fs_objects { // Estrutura usada para carregar fs_object.dat
char nome[20];
int cod;
char nArquivo[20];
int qtdCampos;
};
typedef struct tp_table{ // Estrutura usada para carregar fs_schema.dat
char nome[TAMANHO_NOME_CAMPO];
char tipo;
int tam;
struct tp_table *next;
}tp_table;
O arquivo fs_object.dat organiza-se da seguinte forma:
20B que representam o nome da tabela;
1B que representam o código da tabela;
20B que representa o nome do arquivo onde estão as tuplas da tabela;
4B que representa a quantidade de campos da tabela.
O arquivo fs_schema.dat organiza-se da seguinte forma:
4B que representam o codigo da tabela; (Código que representa a tabela em fs_objects.dat)
40B que representam o nome do campo;
1B que representa o tipo do campo;
4B que representa o tamanho do campo.
Caso os arquivos fs_object.dat e fs_schema.dat não existam ainda, quando chamada, a função finalizaTabela(...) criará os mesmos adicionando os dados da tabela criada.
Sobre a criação e inserção em tabelas:
Para criar uma tabela é necessário uma estrutura do tipo 'table'. Esta estrutura armazenará os dados da tabela a ser criada.
Após a criação de uma istância de 'table' é necessário iniciá-la com o nome da tabla a ser criada usando a função iniciaTabela(nomeTabela):
table *t = NULL;
t = iniciaTabela("Pessoa");
A partir da iniciação da tabela, pode-se adicionar os campos utilizando a função adicionaCampo(t, nomeCampo, tipoCampo, tamanhoCampo):
t = adicionaCampo(t, "Nome", 'S', 20); // Cria um campo de nome 'Nome' do tipo string e de tamanho 20
t = adicionaCampo(t, "Idade", 'I', 4); // Cria um campo de nome 'Idade' do tipo inteiro e de tamanho 4
Agora, para a tabela ser finalmente adicionada ao dicionário de dados e ao esquema, chama-se a função finalizaTabela(t);
Criada a tabela, pode-se inserir os dados.
Quanto da inserção, é necessário criar uma estrutura do tipo 'column' que criará uma lista encadeada de valores a serem adicionados a tabela.
Para adicionar uma tupla na tabela, é preciso inserir valor por valor de cada campo chamando a função insereValor(c, nomeCampo, valorCampo):
column *c = NULL;
c = insereValor(c, "Nome", "Joana");
c = insereValor(c, "Idade", "40");
OBS: A inserção dos dados deve ocorrer na sequência de criação de campo, sendo que não é possível realizar a inserção incompleta de uma tupla
Assim, com os dados já adicionados na tabela, basta chamar a função finalizaInsert(nomeTabela, c) para gravar as tuplas no arquivo nomeTabela.dat, que armazena os dados referente a esta tabela:
finalizaInsert("Pessoa", c);
Sobre inserir uma tupla no buffer:
Para adicionar uma tupla no buffer, realize o seguinte tendo já o bufferpoll, o esquema e o objeto devidamete inicializados:
colocaTuplaBuffer(bufferpoll, 0, esquema, objeto); // Onde '0' é tupla a ser adicionada, relativa a ordem de inserção em sua tabela
Sobre excluir uma tupla do buffer e recuperar uma página do buffer:
Para excluir uma tupla e obter a mesma para impressão, basta chamar a função com o buffer, esquema, a página a excluir uma tupla e a tupla a ser excluida:
column *tuplaE = excluirTuplaBuffer(buffer, esquema, objeto, 0, 2); // '2' é a posição da tupla relativa a página do buffer
Para recuperar uma página do buffer, bem como obter esta página, basta chamar a função com o buffer, o esquema e o número da página a ser recuperada, como segue:
column *pagina = getPage(bufferpoll, esquema, objeto, 0);
A estrutura do tipo 'column' foi criada com o objetivo de armazenar os dados das tabelas, bem como para promover possíveis impressões de dados.
Da compilação:
$ gcc *.c -o prog -Wall
$ ./prog <Nome da Tabela>
##############LEIA-ME PARTE 3 #############################################################################################################
=> 20 dezembro 2014 <=
Universidade Federal da Fronteira Sul – UFFS
Curso: Ciência da Computação
Componente Curricular: Banco de Dados II
Professor: Dr. Denio Duarte
Alunos: Natan J. Mai, Ricardo Zanuzzo, Rogerio T. Schmidt
=============================================================================================================================================
Introdução:
- Ao criar uma tabela, ter a possibilidade de definir chaves primárias e estrangeiras.
- Fazer uma funcionalidade para abrir uma tabela para trabalhar (uma função que englobe leObjeto e leSchema)
- Fazer uma funcionalidade que exclua uma tabela (um drop table). A tabela deve ser excluída do disco e do dicionário.
- Atualizar o txt com as instruções e comentar o código para facilitar as futuras manutenções.
A definição de chave primária ou chave estrangeira de um atributo é representado por um "flag" que é passado por parametro na criação da tabela. Exemplo abaixo
- NPK (Sem chave);
- PK (Chave primária);
- FK (Chave estrangeira)
Da criação das tabelas:
iniciaTabela("tabela");
adicionaCampo(tabela, "atrib11" , 'I', (sizeof(int)) ,PK ," " ," ");
adicionaCampo(tabela, "atrib12" , 'I', (sizeof(int)) ,NPK ," " ," ");
adicionaCampo(tabela, "atrib13" , 'S', 10 ,NPK ," " ," ");
adicionaCampo(tabela, "atrib14" , 'D', (sizeof(double)) ,NPK ," " ," ");
adicionaCampo(tabela, "atrib11" , 'I', (sizeof(int)) ,FK ,"tabRefer" ,"atribRefer");
finalizaTabela(tabela);
Foi adicionado mais um parâmetro, que é passado para a função adicionaCampo. Trata-se do "flag" que indica o tipo de atributo.
No caso de se tratar de uma chave estrangeira, é necessário apontar a tabela referenciada (tabRefer) e o atributo referenciado (atribRefer).
Obsevação Inserção: Se tabela tiver chave estrangeira FK, o primeiro atributo deve ser PK.
Da inserção de Tuplas:
insereValor(colunas, "nomeAtrib1", "value1");
insereValor(colunas, "nomeAtrib2", "value2");
erro = finalizaInsert("tabela", colunas);
-> Variável colunas do tipo column,
-> Nome do atributo "nomeAtrib" a ser adicionado o valor,
-> Valor adicionado,
Dos retornos - Tratamento de PK e FK:
ERRO_CHAVE_PRIMARIA -> -14
ERRO_CHAVE_ESTRANGEIRA -> -15
ERRO_CRIACAO_TABELA -> -16
Estes podem ser tratados na main.
É possível adicionar apenas UM atributo como chave PK, ou seja, não é tratada a forma de chave composta.
Foi alterado a struct tp_table para podermos trabalhar com as chaves:
typedef struct tp_table{ // Estrutura usada para carregar fs_schema.dat
char nome[TAMANHO_NOME_CAMPO]; // Nome do Campo.
char tipo; // Tipo do Campo.
int tam; // Tamanho do Campo.
int chave; // Tipo da chave
char tabelaApt[TAMANHO_NOME_TABELA]; //Nome da Tabela Apontada
char attApt[TAMANHO_NOME_CAMPO]; //Nome do Atributo Apontado
struct tp_table *next; // Encadeamento para o próximo campo.
}tp_table;
Foi também criado as seguintes funções:
-> IniciaAtributos,
-> ExisteAtributo,
-> VerificaChavePK,
-> VerificaChaveFK,
-> ExcluirArquivo,
-> AbreTabela.
Juntamente com os arquivos do trabalho, foi criado também o "exemploMain.c". Trata-se de um modelo (exemplo) de uma maneira
de criar a main(). Nessa exemplo de main() é necessário se atentar ao seguinte:
-int nrTabelas; ->deve ser setado para a quantidades de tabelas a ser criadas;
- nTabela[0] = existeArquivo("tabela1.dat"); // -> deve ser colocado aqui os nomes das tabelas
nTabela[1] = existeArquivo("tabela2.dat");
nTabela[2] = existeArquivo("tabela3.dat");
- ao final, foi chamado a função imprime("tabela1") que realiza a impressão das tabelas.
Também pode ser utilizado a função excluirArquivo. A mesma apaga a fisicamente tabela e os registros do dicionário de dados
Da compilação:
$ gcc *.c -o prog -Wall
$ ./prog
##############LEIA-ME PARTE 4 #############################################################################################################
=> 15 de junho de 2015 <=
Universidade Federal da Fronteira Sul – UFFS
Curso: Ciência da Computação
Componente Curricular: Banco de Dados II
Professor: Dr. Denio Duarte
Alunos: Igor Beilner, Eliton Traverssini, Régis T. Feyh.
=============================================================================================================================================
O reconhecedor de comandos SQL foi implementado utilizando yacc e lex. Portanto, para aterá-los, basta editar os arquivos .y e .l que se
econtram em /Fonte/interface/. Toda vez que for alterados esses arquivos, é necessário gerar novamente os arquivos do reconhecedor.
Para isso, basta executar o comando 'make' no bash quando estiver na pasta onde estão os arquivos.
Para compilar o projeto inteiro, basta executar o comando 'make' na pasta /Fonte/. Isso irá gerar o executável 'Ibetres'.
Ao executar, o programa conecta-se com o banco "ibetres" por default,
Para conectar-se a outro banco, utiliza-se o comando:
\c <nomedo banco>.
O interpretador reconhece os comandos SQL abaixo:
CREATE DATABASE <NomeBanco>;
CREATE TABLE <NomeTabela>(
<nomeCampo> <tipoCampo>[primary key | references <nomeTabela1>(<nomeCampoPK>)]
[, <nomeCampo> <tipoCampo>[primary key | references <nomeTabela1>(<nomeCampoPK>)]
[...]
);
INSERT INTO <NomeTabela> (<coluna1>,...,<colunaN>) VALUES (<valorNum>, '<valorStr>',...);
INSERT INTO <NomeTabela> VALUES (<valorNum>, '<valorStr>',...); // Desde que o número de valores corresponda ao número de colunas
SELECT * FROM <NomeTabela>;
DROP DATABASE <NomeBanco>;
DROP TABLE <NomeTabela>;
Além disso, interpreta os comandos:
help // retorna um menu de ajuda
\c <NomeBanco> // estabelece conexão com o banco de dados <NomeBanco>
\l // retorna uma lista com os bancos de dados criados no SGBD
\d // retorna uma lista com as tabelas existentes no banco de dados corrente
\t <NomeTabela> // retorna uma lista com o esquema de uma tabela
\q // sai do shell do SGBD
A ordem das colunas especificadas não precisa ser na mesma ordem da criação e não é necessário informar todas. Quando o usuário
não especificar a coluna o SGBD colocará um valor nulo, de acordo com o tipo de dado.
Os comandos SQL e os objetos das relações (i.e. <NomeTabelas>, <NomeCampos> ...) NÃO são case-sensitive.
ex:
<TABELA> e <tabela> se referem a mesma relação.
<INSERT> e <insert> se referem ao mesmo comando SQL.
##############LEIA-ME PARTE 5 #############################################################################################################
=> 15 de fevereiro de 2017 <=
Universidade Federal da Fronteira Sul – UFFS
Curso: Ciência da Computação
Componente Curricular: Banco de Dados II
Professor: Dr. Denio Duarte
Alunos: Jefferson Coppini, Jonathan Rauber, Nicholas Brutti, Ricardo Müller
=============================================================================================================================================
Foi implementada a verificação de índices PK e FK utilizando árvore B+.
Adicionado comando explícito CREATE INDEX:
CREATE INDEX ON tabela (atributo);
Além da implementação do comando CREATE INDEX, os comandos DROP TABLE, CREATE TABLE e INSERT tiveram que ser alterados para
suporte ao índice B+ implementado.
Updates:
-> DROP TABLE: quando uma tabela é deletada todos os índices B+ associados à ela são removidos também.
-> CREATE TABLE: quando uma tabela é criada e ela possui um atributo com chave primária, é construído automaticamente um índice B+ para a PK.
-> INSERT: verifica chave primária através do índice B+. Também verifica com o índice B+ as chaves estrangeiras, caso o atributo apontado em outra tabela
possui índice associado.
A ordem da árvore B+ é dinâmica (o cálculo depende do número de tuplas armazenados na tabela). A árvore possuirá no máximo 5 níveis.
Como é armazenado o índice B+:
Ex.: Cria-se uma tabela ALUNO com o atributo Matricula como chave primária. É gerado o arquivo de índices denso no mesmo diretório
da tabela com o nome de arquivo 'alunomatricula.dat'.
Cada chave no arquivo de índice é gravada da seguinte forma:
valor(string alocada dinamicamente) + $ + endereço(int, offset da tupla no arquivo de dados) + #(delimitador de tupla) + ... + &(fim do indice denso) + número de tuplas na tabela
A construção da árvore b+ é feita através do método Bulking Load, ou seja, carregamento em massa.