{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Transaction and index" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%reload_ext pycozo.ipyext_direct\n", "%cozo_auth tutorial *******" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is true that stored relations and triples look like diametrically opposed concepts in Cozo. With triples you have to set up elaborate schema before use. With stored relations you just store your results, without even needing to pre-declare anything. Yet they are actually designed to work together. The intended way that they work together is through transactions." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have already met transactions when we learned how to insert and mutate data in the triple store. But transactions can in fact contain many more things than `put` and `retract` requests. Let's first have the following schema in place:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 attr_idop
010000030assert
110000031assert
210000032assert
310000033assert
\n" ], "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ ":schema\n", "\n", ":put ap {\n", " code: string unique\n", "}\n", "\n", ":put rt {\n", " src: ref,\n", " dst: ref,\n", " distance: float\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's try to add some data, but with a check:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\u001b[31meval::assert_none_failure\u001b[0m\n", "\n", " \u001b[31m×\u001b[0m Triple store transaction failed as a post-condition failed\n", "\u001b[31m ╰─▶ \u001b[0mThe query is asserted to return no result, but a tuple [-100.0] is found\n", " ╭─[6:1]\n", " \u001b[2m6\u001b[0m │ ?[dist] := [r rt.distance dist], dist < 0\n", " \u001b[2m7\u001b[0m │ :assert none\n", " · \u001b[35;1m ────────────\u001b[0m\n", " \u001b[2m8\u001b[0m │ }\n", " ╰────\n" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ ":tx\n", "\n", "{rt.src: {ap.code: 'A'}, rt.dst: {ap.code: 'B'}, rt.distance: -100}\n", "\n", ":after {\n", " ?[dist] := [r rt.distance dist], dist < 0\n", " :assert none\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have used the transaction directive `:after` signifying we want the query inside its braces to be checked _after_ the main transaction is done. In the `:after` block itself, we used the directive `:assert none` to indicate the above query should return no results at all. The error message also shows us the offending tuple." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can check that in this case, no triple is actually inserted, since the transaction failed:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 rdist
\n" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "?[r, dist] := [r rt.distance dist]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Besides `:after`, there is also the `:before` directive, running before any triple transactions. In the block itself, the function `assert()` can also be very useful in the body of rules. See the manual for more information." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You may have any number of `:put`, `:retract`, `:before` or `:after`. They can be interleaved. When a transaction is run, all `:before` blocks are run in the order they are defined, then all `:put` and `:retract`, and finally all `:after` blocks are run." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The real power of the transaction is that you can put anything in your `:before` and `:after` blocks, including puts or retracts to stored relations!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.6" } }, "nbformat": 4, "nbformat_minor": 4 }