/// <summary> /// Verifica se a tabela já foi inserida. Caso contrário, insere. /// </summary> /// <param name="tabela"></param> public void addTabela(string tabela) { if (!mem.existeTabela(tabela)) { throw new SemanticError("Tabela " + tabela + " não existe."); } if (!tabelas.Exists(c => c.getNome().Equals(tabela))) { tabelas.Add(mem.recuperarMetadados(tabela)); } }
/* * ~Semantico() * { * Base.getInstance().naoEhInsert(); * } */ public void executeAction(int action, Token token) { int index; if ((action != 16 && action != 1) && memoria.getDatabase() == null) { throw new SGDBException("utilize o comando SET DATABASE..."); } switch (action) { case 0: execucaoComandoReal(); acaoZero(); break; case 1: memoria.createDatabase(token.getLexeme().ToLower()); form1.Text = memoria.getDatabase(); break; case 2: if (memoria.existeTabela(token.getLexeme().ToLower())) { throw new SemanticError("Tabela " + token.getLexeme().ToLower() + " já existe", token.getLinha()); } operacao = acao.CriarTabela; metadados.setNome(token.getLexeme().ToLower()); break; case 3: if (memoria.existeIndice(token.getLexeme().ToLower())) { throw new SemanticError("Index " + token.getLexeme().ToLower() + " já existe", token.getLinha()); } operacao = acao.CriarIndex; identificadores.Add(token.getLexeme().ToLower()); break; case 4: if (!memoria.existeTabela(token.getLexeme().ToLower())) { throw new SemanticError("Tabela " + token.getLexeme().ToLower() + " não existe", token.getPosition()); } // Como é so saber o metadados, e ele tem o nome da tabela, não precisa ficar colocando a mesma no array // de identificadores metadados = GerenciadorMemoria.getInstance().recuperarMetadados(token.getLexeme().ToLower()); /* arquivoBinario = new ArquivoBinario(memoria.getPath());*/ if (metadados.getNumeroRegistrosTabela() > 0) { throw new SemanticError("Não se cria index em tabelas que já tenham dados", token.getLinha()); } break; case 5: identificadores.Add(token.getLexeme().ToLower()); break; case 6: if (sexta) { Console.WriteLine(identificadores.Count); Console.WriteLine(valoresColunas.Count); for (int i = 0; i < identificadores.Count; i++) { metadados.addDados(new DadosTabela(identificadores[i], valoresColunas[i].getTipo(), valoresColunas[i].getTamanho())); } identificadores.Clear(); valoresColunas.Clear(); sexta = false; } else { foreach (string id in identificadores) { if (!metadados.getDados().ContainsKey(id)) { throw new SemanticError("Campo " + token.getLexeme() + " não existe", token.getLinha()); } metadados.getDados()[id].setPrimary(true); } identificadores.Clear(); } break; case 7: if (!metadados.getDados().ContainsKey(token.getLexeme())) { throw new SemanticError("Campo " + token.getLexeme() + " não existe", token.getLinha()); } identificadores.Add(token.getLexeme()); break; case 8: if (!memoria.existeTabela(token.getLexeme().ToLower())) { throw new SemanticError("Tabela " + token.getLexeme().ToLower() + " não existe", token.getPosition()); } identificadores.Add(token.getLexeme().ToLower()); break; case 9: if (!memoria.recuperarMetadados(identificadores[1]).getDados().ContainsKey(token.getLexeme().ToLower())) { throw new SemanticError("Campo " + token.getLexeme().ToLower() + " na tabela " + identificadores[1] + "não existe", token.getPosition()); } metadados.getDados()[identificadores[0]].setForeing(identificadores[1], token.getLexeme().ToLower()); // so pra salvar a alteração de mais uma chave estrangeira Metadados aux = memoria.recuperarMetadados(identificadores[1]); //aux.getDadosColuna()[identificadores[1]].incForeing(); //aux.getDados()[identificadores[1]].addForeing(); aux.getDados()[identificadores[1]].incForeing(); memoria.salvarMetadados(aux); identificadores.Clear(); break; case 10: // decidir tamanho valoresColunas.Add(new ValoresCampos("INTEGER", 4)); break; case 11: if (Convert.ToInt32(token.getLexeme()) > 255 || Convert.ToInt32(token.getLexeme()) < 1) { throw new SemanticError("Tamanho do campo " + identificadores.Last() + " inválido", token.getLinha()); } valoresColunas.Add(new ValoresCampos("VARCHAR", Convert.ToInt32(token.getLexeme()))); break; case 12: if (Convert.ToInt32(token.getLexeme()) > 255 || Convert.ToInt32(token.getLexeme()) < 1) { throw new SemanticError("Tamanho do campo " + identificadores.Last() + " inválido", token.getLinha()); } valoresColunas.Add(new ValoresCampos("CHAR", Convert.ToInt32(token.getLexeme()))); break; case 13: //Exclusão com verificação de foreing e exclusão das referencias memoria.dropTable(token.getLexeme().ToLower()); break; case 14: //Exclusão de index if (memoria.existeIndice(token.getLexeme().ToLower())) { identificadores.Add(token.getLexeme().ToLower()); operacao = acao.ExcluirIndex; } else { throw new SemanticError("Index " + token.getLexeme().ToLower() + "não existe", token.getLinha()); } break; case 15: Form1.setResultado(memoria.recuperarMetadados(token.getLexeme().ToLower())); break; case 16: memoria.setDatabase(token.getLexeme().ToLower()); form1.Text = memoria.getDatabase(); break; case 17: if (ultimoFiltro != null) { throw new SGDBException("Falha na operação semântica 17. O Filtro deveria estar nulo."); } ultimoFiltro = new Filtro(); if (token.getId() == 16) { ultimoFiltro.IsAND = true; } else if (token.getId() == 17) { ultimoFiltro.IsOR = true; } break; case 18: // Operador Relacional da cláusula Where do SELECT select.Where = select.Where == null ? new Where() : select.Where; ultimoFiltro = ultimoFiltro == null ? new Filtro() : ultimoFiltro; //Joga o campo para o LValue, caso tenha sido incluído como retorno do select. Acontece no primeiro filtro. //ultimoFiltro.LValue = ultimoFiltro.LValue == null? select.removeUltimoRetorno(): ultimoFiltro.LValue; switch (token.getId()) { case 37: ultimoFiltro.Op = OperadorRel.Igual; break; case 38: ultimoFiltro.Op = OperadorRel.MaiorQue; select.Etapa = Select.EtapaSemantica.WHERE; break; case 39: ultimoFiltro.Op = OperadorRel.MenorQue; select.Etapa = Select.EtapaSemantica.WHERE; break; case 40: ultimoFiltro.Op = OperadorRel.MaiorIgualA; select.Etapa = Select.EtapaSemantica.WHERE; break; case 41: ultimoFiltro.Op = OperadorRel.MenorIgualA; select.Etapa = Select.EtapaSemantica.WHERE; break; case 42: ultimoFiltro.Op = OperadorRel.Diferente; select.Etapa = Select.EtapaSemantica.WHERE; break; default: break; } break; case 19: operacao = acao.InserirDados; metadados = memoria.recuperarMetadados(identificadores[0]); if (identificadores.Count > 1) { allColunas = false; contColunas = identificadores.Count - 1; for (int i = 1; i < identificadores.Count; i++) { if (!metadados.getDados().ContainsKey(identificadores[i])) { throw new SemanticError("Campo " + identificadores[i] + "não existe na tabela " + identificadores[0], token.getLinha()); } } } break; case 20: int indexColuna; if (allColunas) { index = identificadores.Count - 1; indexColuna = index; if (index >= metadados.getNomesColunas().Count) { throw new SemanticError("Mais valores do que campos", token.getLinha()); } } else { index = identificadores.Count - contColunas; indexColuna = metadados.getNomesColunas().IndexOf(identificadores[index]); if ((index - 1) >= contColunas) { throw new SemanticError("Mais valores do que campos", token.getLinha()); } } if (ListaDeSimbolos.getInstance().classeToken(token.getId()).Contains(metadados.getDados()[metadados.getNomesColunas()[indexColuna]].geTipo()) || ListaDeSimbolos.getInstance().classeToken(token.getId()).Equals("null")) { // tipo tá correto // validação de tamanho if (ListaDeSimbolos.getInstance().classeToken(token.getId()).Equals("null")) { identificadores.Add(token.getLexeme()); } else { if (token.getId() == 3) // Integer { if (Convert.ToUInt32(token.getLexeme()) <= UInt32.MaxValue) { identificadores.Add(token.getLexeme()); } else { throw new SemanticError("DadoTabela " + token.getLexeme() + " de tamanho incompativel", token.getLinha()); } } else { if ((token.getLexeme().Length - 2) <= metadados.getDados()[metadados.getNomesColunas()[indexColuna]].getTamanho()) { identificadores.Add(token.getLexeme()); } else { throw new SemanticError("DadoTabela " + token.getLexeme() + " de tamanho incompativel(" + metadados.getDados()[metadados.getNomesColunas()[index]].getTamanho() + ")", token.getLinha()); } } } } else { throw new SemanticError("DadoTabela " + token.getLexeme() + " tem tipo incompativel com o campo " + metadados.getDados()[metadados.getNomesColunas()[index]] + " de tipo " + metadados.getDados()[metadados.getNomesColunas()[index]].geTipo(), token.getLinha()); } break; case 21: // tabela.campo --> Nome da coluna solicitada no SELECT // Caso ainda não tenha sido definido, define a ação SELECT select = Select.singleton(); operacao = acao.Select; // verifica a existencia do campo if (!memoria.recuperarMetadados(identificadores.Last()).getNomesColunas().Exists(s => s.Equals(token.getLexeme()))) { throw new SemanticError("Campo " + identificadores.Last() + "." + token.getLexeme() + " não existe", token.getLinha()); } switch (select.Etapa) { case Select.EtapaSemantica.CAMPOS: // Adiciona o campo de retorno do SELECT select.addTabela(identificadores.Last()); string ret = identificadores.Last() + "." + token.getLexeme().ToLower(); identificadores.Remove(identificadores.Last()); select.addRetorno(ret); break; case Select.EtapaSemantica.TABELA: throw new SGDBException("Não devia passar por aqui. Ação semantica 21. Select.ETAPA = Tabela"); case Select.EtapaSemantica.JOIN: ultimoFiltro = ultimoFiltro == null ? new Filtro() : ultimoFiltro; //necessário na primeira linha do where if (ultimoFiltro.LValue == null) { //se ainda não foi atribuído LValue, então deve estar no lado esquerdo da operação. ultimoFiltro.LValue = identificadores.Last() + "." + token.getLexeme().ToLower(); identificadores.Remove(identificadores.Last()); } else { if (select.Etapa == Select.EtapaSemantica.WHERE) { throw new SemanticError("Os primeiros filtros devem ser de JOIN. Cláusula JOIN já finalizada.", token.getLinha()); } if (ultimoFiltro.IsOR) { throw new SemanticError("JOIN deve utilizar AND", token.getLinha()); } if (ultimoFiltro.LValue.Split('.')[0].Equals(identificadores.Last())) { throw new SemanticError("JOIN deve ser feito entre tabelas distintas", token.getLinha()); } ultimoFiltro.RValue = identificadores.Last() + "." + token.getLexeme(); identificadores.Remove(identificadores.Last()); ultimoFiltro.IsAND = true; select.Where.addJoin(ultimoFiltro); ultimoFiltro = null; } break; case Select.EtapaSemantica.WHERE: ultimoFiltro.LValue = identificadores.Last() + "." + token.getLexeme().ToLower(); identificadores.Remove(identificadores.Last()); break; case Select.EtapaSemantica.ORDER: string campo = identificadores.Last() + "." + token.getLexeme().ToLower(); select.addOrderBy(campo); identificadores.Remove(identificadores.Last()); break; default: throw new SGDBException("Não devia passar por aqui. Ação semantica 21. Select.ETAPA = Default"); } break; case 22: //token do apelido da cláusula AS. O SELECT adiciona o apelido no último campo adicionado. //clausulaAs[identificadores.Last()] = token.getLexeme(); // esta linha é necessária? if (select.Where != null) { //se já passou pelo where, provavelmente está no ORDER BY throw new SemanticError("Não existe AS pra ORDER BY!", token.getLinha()); } select.addApelidoUltimo(token.getLexeme()); break; case 23: //tabela.* --> selecão de todos os campos de uma tabela //Caso ainda não tenha sido definido, define a ação SELECT select = Select.singleton(); operacao = acao.Select; //busca a tabela armazenada na última ação semântica string tabela = identificadores.Last(); identificadores.RemoveAt(identificadores.Count - 1); //inclui a tabela no objeto SELECT select.addTabela(tabela); //busca as colunas da tabela para incluir no retorno foreach (String col in memoria.recuperarMetadados(tabela).getNomesColunas()) { string coluna = tabela + "." + col; identificadores.Add(coluna); //estou inserindo no identificadores também porque ainda não sei se isto será usado em outro momento select.addRetorno(coluna); } select.Asterisco = true; break; case 24: // FROM tabelas // inclui as tabelas numa lista a parte para validar depois com a classe select. fromTabelas.Add(token.getLexeme()); break; case 25: throw new SemanticError("Ação INNER JOIN não suportada neste formato. Insira um filtro no Where."); case 26: throw new SemanticError("Ação LEFT JOIN não suportada."); case 27: throw new SemanticError("Ação RIGHT JOIN não suportada."); case 28: //final do ORDER BY. Verificar se os campos constam no retorno. //Não necessário, pois é verificado ao inserir cada campo, na ação 21. break; case 29: //Define a ordenação dos campos como descrecente select.orderDesc(); break; case 30: select.Etapa = Select.EtapaSemantica.WHERE; ultimoFiltro.RValue = token.getLexeme(); //ultimoFiltro.IsOR? select.Where:break; if (ultimoFiltro.IsOR) { select.Where.addFiltroOR(ultimoFiltro); } else { select.Where.addFiltroAND(ultimoFiltro); } ultimoFiltro = null; break; case 31: //logo depois do FROM select.Etapa = Select.EtapaSemantica.TABELA; break; case 32: //logo antes do Where. o where inicia com possível join. select.Etapa = Select.EtapaSemantica.JOIN; break; case 33: //logo antes do order select.Etapa = Select.EtapaSemantica.ORDER; break; default: throw new SGDBException("Ação " + action + " não implementada."); } //Console.WriteLine("Ação #" + action + ", Token: " + token); }