Em blogs anteriores, abordamos a execução do N1QL a partir do JavaScript funções, processamento de documentos por meio de iteradorese manipulação de dados.
Passamos agora a tratar os erros dos comandos N1QL.
Tratamento de erros
Quando um erro de qualquer natureza é encontrado, o jsevaluator por padrão, interromperá a execução da função e retornará um erro:
Nesse caso específico, o segundo INSERT falhará porque a chave k10 já existe:
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 |
[ { "código": 10109, "msg": "Erro ao executar a função 'doInsert' (n1ql:doInsert)", "razão": { "detalhes": { "Código": " var q2 = N1QL('insert into b1 values(\\\\"k10\\\", {\\\"f1\\\": 10});', {}, true);", "Exceção": { "chamador": "couchbase:2088", "causa": { "chamador": "couchbase:1961", "código": 17012, "chave": "dml.statement.duplicatekey", "mensagem": "Chave duplicada: k10" }, "código": 12009, "icause": "Chave duplicada: k10", "chave": "datastore.couchbase.DML_error", "mensagem": "Erro DML, as possíveis causas incluem modificação simultânea. Falha ao executar INSERT na chave k10", "retry": falso }, "Localização": "functions/n1ql.js:21", "Pilha": " at doInsert (functions/n1ql.js:3:14)" }, "tipo": "Exceções do código JS" } } ] |
Você não precisa se ater ao comportamento padrão, pois o JavaScript permite capturar erros e lidar com eles:
Nesse caso, a função doInsert() retornos falha porque a chave k10 já existe.
Retorno vs. arremesso
O captura pode ser usado para tratar a falha da maneira que for útil para sua lógica comercial.
As opções disponíveis se resumem a 1) tomar alguma ação evasiva e continuar a execução, 2) retornar mais cedo com sucesso e 3) retornar mais cedo com falha.
A diferença entre o sucesso e o fracasso é simplesmente usar retorno para retornar um valor como no exemplo acima vs lançar para retornar um erro.
A diferença entre os dois é importante, pois se você optar por retornar um resultado, a solicitação do chamador continuará a execução. Por outro lado, se você lançar um erro, toda a solicitação falhará com o erro, portanto, tenha cuidado com o que deseja usar, pois isso fará a diferença entre o funcionamento correto e o mau funcionamento da solicitação.
Expressão retornada
A segunda coisa a ter em mente é que, independentemente de retornar ou lançar um erro, você pode muito bem querer fornecer informações significativas.
Considere o código a seguir:
Isso falhará com algo como:
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 |
[ { "código": 10109, "msg": "Erro ao executar a função 'doInsert' (n1ql:doInsert)", "razão": { "detalhes": { "Código": " throw err;", "Exceção": { "chamador": "couchbase:2088", "causa": { "chamador": "couchbase:1961", "código": 17012, "chave": "dml.statement.duplicatekey", "mensagem": "Chave duplicada: k10" }, "código": 12009, "icause": "Chave duplicada: k10", "chave": "datastore.couchbase.DML_error", "mensagem": "Erro DML, as possíveis causas incluem modificação simultânea. Falha ao executar INSERT na chave k10", "retry": falso }, "Localização": "functions/n1ql.js:6", "Pilha": " at doInsert (functions/n1ql.js:3:17)" }, "tipo": "Exceções do código JS" } } ] |
Assim como no exemplo anterior, o que concluímos disso é que erro é um objeto e é retornado no razão campo.
No entanto, se você alterar o lançar declaração dessa forma:
O doInsert() agora lançará uma string e não um objeto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[ { "código": 10109, "msg": "Erro ao executar a função 'doInsert' (n1ql:doInsert)", "razão": { "detalhes": { "Código": " throw \"failure\" + err;", "Exceção": "failure {\"caller\":\"couchbase:2088\",\"cause\":{\"caller\":\"couchbase:1961\",\"code\":17012,\"key\":\"dml.statement.duplicatekey\",\"message\":\"Chave duplicada: k10\"},\"code\":12009,\"icause\":\"Chave duplicada: k10\",\"key\":\"datastore.couchbase.DML_error\",\"message\":\"Erro de DML, as possíveis causas incluem modificação simultânea. Falha ao executar INSERT na chave k10\",\"retry\":false}", "Localização": "functions/n1ql.js:6" }, "tipo": "Exceções do código JS" } } ] |
O erro agora é transformado em uma cadeia de caracteres e, de repente, seu erro não é tão legível.
Isso se aplica a retorno também: em particular, por padrão erro contém cadeias de caracteres que contêm objetos JSON manipulados.
Por exemplo:
Devoluções:
1 2 3 4 5 6 |
[ { "mensagem": "{\"caller\":\"couchbase:2088\",\"cause\":{\"caller\":\"couchbase:1961\",\"code\":17012,\"key\":\"dml.statement.duplicatekey\",\"message\":\"Chave duplicada: k10\"},\"code\":12009,\"icause\":\"Chave duplicada: k10\",\"key\":\"datastore.couchbase.DML_error\",\"message\":\"Erro de DML, as possíveis causas incluem modificação simultânea. Falha ao executar INSERT na chave k10\",\"retry\":false}", "pilha": "Erro\n em doInsert (functions/n1ql.js:3:17)" } ] |
Se você quiser obter um bom valor retornado, terá que analisar o error.message antes de devolvê-lo:
O que resulta em:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[ { "chamador": "couchbase:2088", "causa": { "chamador": "couchbase:1961", "código": 17012, "chave": "dml.statement.duplicatekey", "mensagem": "Chave duplicada: k10" }, "código": 12009, "icause": "Chave duplicada: k10", "chave": "datastore.couchbase.DML_error", "mensagem": "Erro DML, as possíveis causas incluem modificação simultânea. Falha ao executar INSERT na chave k10", "retry": falso } ] |
E se você quiser incluir a pilha também, terá que construir um novo objeto da seguinte forma:
Wque produz:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[ { "chamador": "couchbase:2088", "causa": { "chamador": "couchbase:1961", "código": 17012, "chave": "dml.statement.duplicatekey", "mensagem": "Chave duplicada: k10" }, "código": 12009, "icause": "Chave duplicada: k10", "chave": "datastore.couchbase.DML_error", "mensagem": "Erro DML, as possíveis causas incluem modificação simultânea. Falha ao executar INSERT na chave k10", "retry": falso, "pilha": "Erro\n em doInsert (functions/n1ql.js:3:17)" } ] |
A moral da história é: tenha cuidado com a forma como você retorna seu erro e tenha cuidado com a forma como você o formata.
Conclusão
Ao longo de vários blogs, abordamos a execução do N1QL, o processamento de documentos e a manipulação de dados, além do tratamento de erros.
Na próxima parte da série, passaremos às declarações preparadas.