-
Notifications
You must be signed in to change notification settings - Fork 0
/
tabela_generica_IMP.py
164 lines (147 loc) · 5.83 KB
/
tabela_generica_IMP.py
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
# Imlementação do módulo {tabela_generica}.
import base_sql
import identificador
import conversao_sql
import sys # Para depuração.
from utils_testes import erro_prog, mostra
# FUNÇÕES INTERNAS
def constroi_colunas_SQL(cols):
"""Constrói a descrição SQL das colunas de uma tabela,
dada a lista de propriedades {cols} como fornecida
a {cria_tabela}. Omite colunas com tipo SQL {None}."""
colunas = "indice integer NOT NULL PRIMARY KEY"
for cp in cols:
chave = cp[0]
tipo_SQL = cp[2]
if tipo_SQL != None:
# O campo é uma coluna da tabela.
nulo_ok = cp[3] # O valor da coluna pode ser NULL?
colunas = colunas + ", " + chave + " " + tipo_SQL + (' NOT NULL' if not nulo_ok else '')
return colunas
def extrai_nomes_de_colunas_SQL(cols):
"""Extrai a lista dos nomes das colunas de uma tabela,
dada a lista de propriedades {cols} como fornecida
a {cria_tabela}. Omite colunas com tipo SQL {None}."""
nomes = [].copy()
for cp in cols:
chave = cp[0]
tipo_SQL = cp[2]
if tipo_SQL != None:
# O campo é uma coluna da tabela.
nomes.append(chave)
return nomes
# IMPLEMENTAÇÕES
def cria_tabela(nome_tb, cols):
colunas = constroi_colunas_SQL(cols)
res = base_sql.executa_comando_CREATE_TABLE(nome_tb, colunas);
if res != None:
assert type(res) is str
erro_prog("CREATE_TABLE falhou " + str(res))
return
def acrescenta(nome_tb, cache, let, cols, def_obj, atrs_SQL):
# Descobre o indice da última entrada na tabela:
num_ents = base_sql.num_entradas(nome_tb, 'indice')
if not type(num_ents) is int:
erro_prog("base_sql.num_entradas: result = '" + str(num_ents) + "'")
# Tenta criar o objeto:
ind = num_ents + 1 # Indice esperado do objeto na tabela.
ident = identificador.de_indice(let, ind)
obj = def_obj(None, ident, atrs_SQL)
# Insere na base de dados e obtém o índice na mesma:
ind_insert = base_sql.executa_comando_INSERT(nome_tb, atrs_SQL)
if (not type(ind_insert) is int) or (ind_insert != ind):
erro_prog("indice de inserção inválido " + str(ind))
cache[ident] = obj
return obj
def atualiza(nome_tb, cache, let, cols, def_obj, ident, mods_SQL):
# Obtém o objeto com esse identificador e garante que está em {cache}:
obj = busca_por_identificador(nome_tb, cache, let, cols, def_obj, ident)
if obj == None:
# Objeto não existe:
erro_prog("identificador '" + ident + "' nao encontrado")
# Atualiza os atributos do objeto na memória:
res = def_obj(obj, ident, mods_SQL)
assert res == obj
# Atualiza a base de dados:
ind = identificador.para_indice(let, ident)
cond = "indice = " + str(ind)
res = base_sql.executa_comando_UPDATE(nome_tb, cond, mods_SQL)
if res != None:
erro_prog("UPDATE da tabela '" + nome_tb + "' falhou")
return obj
def busca_por_identificador(nome_tb, cache, let, cols, def_obj, ident):
if ident in cache:
return cache[ident]
else:
ind = identificador.para_indice(let, ident)
return busca_por_identificador_e_indice(nome_tb, cache, let, cols, def_obj, ident, ind)
def busca_por_indice(nome_tb, cache, let, cols, def_obj, ind):
ident = identificador.de_indice(let, ind)
if ident in cache:
return cache[ident]
else:
return busca_por_identificador_e_indice(nome_tb, cache, let, cols, def_obj, ident, ind)
def busca_por_identificador_e_indice(nome_tb, cache, let, cols, def_obj, ident, ind):
"""Função interna: mesmo que {busca_por identificador}, mas exige o índice inteiro {ind}
da linha da tabela, além do identificador {ident}."""
cond = "indice = " + str(ind)
col_nomes = extrai_nomes_de_colunas_SQL(cols)
res = base_sql.executa_comando_SELECT(nome_tb, cond, col_nomes)
sys.stderr.write("busca_por_identificador_e_indice: res = " + str(res) + "\n")
if res == None:
return None
res = list(res)
if len(res) == 0:
return None
elif len(res) > 1:
erro_prog("SELECT com índice em '" + nome_tb + "' não é único, res = " + str(res))
col_vals = list(res[0])
assert len(col_vals) == len(col_nomes)
atrs_SQL = dict(zip(col_nomes, col_vals))
obj = def_obj(None, ident, atrs_SQL)
cache[ident] = obj
return obj
def busca_por_campo(nome_tb, let, cols, chave, valor, res_cols):
# Converte {valor} para string na linguagem SQL:
valor = base_sql.codifica_valor(valor)
# Supõe que o cache é um subconjuto da base em disco, então procura só na última:
cond = chave + " = " + valor
if res_cols == None:
cols = ['indice']
else:
cols = res_cols
res = base_sql.executa_comando_SELECT(nome_tb, cond, cols)
if res == None:
res = [].copy()
elif type(res) is str:
erro_prog("SELECT falhou " + str(res))
else:
if res_cols == None:
# Converte lista de índices para lista de identificadores:
res = identificador.de_lista_de_indices(let, res)
return res
def busca_por_semelhanca(nome_tb, let, cols, chaves, valores):
cond = ""
for key in chaves:
for value in valores:
cond += (key + " LIKE '%" + value + "%' OR ")
cond = cond[:-4]
res = base_sql.executa_comando_SELECT(nome_tb, cond, ['indice'])
if res != None and type(res) is str:
erro_prog("SELECT falhou " + str(res))
sys.stderr.write("busca_por_semelhanca: res = " + str(res) + "\n")
return identificador.de_lista_de_indices(let, res)
def busca_por_valor(nome_tb, let, cols, chaves, valores):
cond = "preco < " + str(valores)
res = base_sql.executa_comando_SELECT(nome_tb, cond, ['indice'])
if res != None and type(res) is str:
erro_prog("SELECT falhou " + str(res))
sys.stderr.write("busca_por_valor: res = " + str(res) + "\n")
return identificador.de_lista_de_indices(let, res)
def limpa_tabela(nome_tb, cols):
res = base_sql.executa_comando_DROP_TABLE(nome_tb);
if res != None:
assert type(res) is str
erro_prog("DROP_TABLE de " + nome_tb + " falhou, res = '" + str(res) + "' falhou")
cria_tabela(nome_tb, cols)
return