Commit 91a579d87e6ffebdba7d258ed7a6657e0127f8fd
1 parent
6a899680
*** empty log message ***
Showing
11 changed files
with
2192 additions
and
1023 deletions
Show diff stats
anubis_dev/compiler/src/lex.yy.c
| ... | ... | @@ -971,6 +971,7 @@ char *path_prefix(char *name) |
| 971 | 971 | int i = strlen(name); |
| 972 | 972 | if (i >= path_prefix_length-5) |
| 973 | 973 | { |
| 974 | + err_line_col(linecol()); | |
| 974 | 975 | fprintf(errfile, |
| 975 | 976 | msgtext_file_path_too_long[language], |
| 976 | 977 | name); |
| ... | ... | @@ -1028,6 +1029,7 @@ FILE *fopensrc(char *name) |
| 1028 | 1029 | /* if path is absolute do not try the libraries */ |
| 1029 | 1030 | if (name[0] == '/' || name[0] == '\\') |
| 1030 | 1031 | { |
| 1032 | + err_line_col(linecol()); | |
| 1031 | 1033 | fprintf(errfile, |
| 1032 | 1034 | msgtext_cannot_find_src_file[language], |
| 1033 | 1035 | name, |
| ... | ... | @@ -1066,6 +1068,7 @@ FILE *fopensrc(char *name) |
| 1066 | 1068 | } |
| 1067 | 1069 | |
| 1068 | 1070 | /* The file is not found: send a message and exit */ |
| 1071 | + err_line_col(linecol()); | |
| 1069 | 1072 | fprintf(errfile, |
| 1070 | 1073 | msgtext_cannot_find_src_file[language], |
| 1071 | 1074 | name, |
| ... | ... | @@ -1172,6 +1175,7 @@ void add_to_already_included(char *name) |
| 1172 | 1175 | //printf("Adding '%s'.\n",name); |
| 1173 | 1176 | if (next_already_included == max_already_included) |
| 1174 | 1177 | { |
| 1178 | + err_line_col(linecol()); | |
| 1175 | 1179 | fprintf(errfile, |
| 1176 | 1180 | msgtext_too_many_files[language]); |
| 1177 | 1181 | anb_exit(1); |
| ... | ... | @@ -1390,7 +1394,7 @@ static char *rec_name(char *s, int del) |
| 1390 | 1394 | /* state STRTL is used when a string is too long. */ |
| 1391 | 1395 | /* states CONF and CONFCOM are used to read 'compiler.conf'.*/ |
| 1392 | 1396 | /* the lexer ----------------------------------------------------------------------------*/ |
| 1393 | -#line 1394 "lex.yy.c" | |
| 1397 | +#line 1398 "lex.yy.c" | |
| 1394 | 1398 | |
| 1395 | 1399 | /* Macros after this point can all be overridden by user definitions in |
| 1396 | 1400 | * section 1. |
| ... | ... | @@ -1555,9 +1559,9 @@ YY_DECL |
| 1555 | 1559 | register char *yy_cp, *yy_bp; |
| 1556 | 1560 | register int yy_act; |
| 1557 | 1561 | |
| 1558 | -#line 562 "lexer.y" | |
| 1562 | +#line 566 "lexer.y" | |
| 1559 | 1563 | |
| 1560 | -#line 1561 "lex.yy.c" | |
| 1564 | +#line 1565 "lex.yy.c" | |
| 1561 | 1565 | |
| 1562 | 1566 | if ( yy_init ) |
| 1563 | 1567 | { |
| ... | ... | @@ -1643,27 +1647,27 @@ do_action: /* This label is used only to access EOF actions. */ |
| 1643 | 1647 | |
| 1644 | 1648 | case 1: |
| 1645 | 1649 | YY_RULE_SETUP |
| 1646 | -#line 563 "lexer.y" | |
| 1650 | +#line 567 "lexer.y" | |
| 1647 | 1651 | { comlevel = 1; BEGIN COM; } |
| 1648 | 1652 | YY_BREAK |
| 1649 | 1653 | case 2: |
| 1650 | 1654 | YY_RULE_SETUP |
| 1651 | -#line 564 "lexer.y" | |
| 1655 | +#line 568 "lexer.y" | |
| 1652 | 1656 | { comlevel++; } |
| 1653 | 1657 | YY_BREAK |
| 1654 | 1658 | case 3: |
| 1655 | 1659 | YY_RULE_SETUP |
| 1656 | -#line 565 "lexer.y" | |
| 1660 | +#line 569 "lexer.y" | |
| 1657 | 1661 | { comlevel--; if (!comlevel) { BEGIN PAR; } } |
| 1658 | 1662 | YY_BREAK |
| 1659 | 1663 | case 4: |
| 1660 | 1664 | YY_RULE_SETUP |
| 1661 | -#line 566 "lexer.y" | |
| 1665 | +#line 570 "lexer.y" | |
| 1662 | 1666 | { } |
| 1663 | 1667 | YY_BREAK |
| 1664 | 1668 | case 5: |
| 1665 | 1669 | YY_RULE_SETUP |
| 1666 | -#line 567 "lexer.y" | |
| 1670 | +#line 571 "lexer.y" | |
| 1667 | 1671 | { } |
| 1668 | 1672 | YY_BREAK |
| 1669 | 1673 | case 6: |
| ... | ... | @@ -1671,17 +1675,17 @@ case 6: |
| 1671 | 1675 | yy_c_buf_p = yy_cp -= 1; |
| 1672 | 1676 | YY_DO_BEFORE_ACTION; /* set up yytext again */ |
| 1673 | 1677 | YY_RULE_SETUP |
| 1674 | -#line 568 "lexer.y" | |
| 1678 | +#line 572 "lexer.y" | |
| 1675 | 1679 | { /* dbl_slash_comment(yytext+2); */ } |
| 1676 | 1680 | YY_BREAK |
| 1677 | 1681 | case 7: |
| 1678 | 1682 | YY_RULE_SETUP |
| 1679 | -#line 569 "lexer.y" | |
| 1683 | +#line 573 "lexer.y" | |
| 1680 | 1684 | { BEGIN STR; str_index = 0; } |
| 1681 | 1685 | YY_BREAK |
| 1682 | 1686 | case 8: |
| 1683 | 1687 | YY_RULE_SETUP |
| 1684 | -#line 570 "lexer.y" | |
| 1688 | +#line 574 "lexer.y" | |
| 1685 | 1689 | { BEGIN PAR; |
| 1686 | 1690 | str_buf[str_index] = 0; |
| 1687 | 1691 | yylval.expr = new_string(str_buf); |
| ... | ... | @@ -1689,598 +1693,598 @@ YY_RULE_SETUP |
| 1689 | 1693 | YY_BREAK |
| 1690 | 1694 | case 9: |
| 1691 | 1695 | YY_RULE_SETUP |
| 1692 | -#line 574 "lexer.y" | |
| 1696 | +#line 578 "lexer.y" | |
| 1693 | 1697 | { store_str_char('\"'); } |
| 1694 | 1698 | YY_BREAK |
| 1695 | 1699 | case 10: |
| 1696 | 1700 | YY_RULE_SETUP |
| 1697 | -#line 575 "lexer.y" | |
| 1701 | +#line 579 "lexer.y" | |
| 1698 | 1702 | { store_str_char('\n'); } |
| 1699 | 1703 | YY_BREAK |
| 1700 | 1704 | case 11: |
| 1701 | 1705 | YY_RULE_SETUP |
| 1702 | -#line 576 "lexer.y" | |
| 1706 | +#line 580 "lexer.y" | |
| 1703 | 1707 | { store_str_char('\r'); } |
| 1704 | 1708 | YY_BREAK |
| 1705 | 1709 | case 12: |
| 1706 | 1710 | YY_RULE_SETUP |
| 1707 | -#line 577 "lexer.y" | |
| 1711 | +#line 581 "lexer.y" | |
| 1708 | 1712 | { store_str_char('\t'); } |
| 1709 | 1713 | YY_BREAK |
| 1710 | 1714 | case 13: |
| 1711 | 1715 | YY_RULE_SETUP |
| 1712 | -#line 578 "lexer.y" | |
| 1716 | +#line 582 "lexer.y" | |
| 1713 | 1717 | { store_str_char('\\'); } |
| 1714 | 1718 | YY_BREAK |
| 1715 | 1719 | case 14: |
| 1716 | 1720 | YY_RULE_SETUP |
| 1717 | -#line 579 "lexer.y" | |
| 1721 | +#line 583 "lexer.y" | |
| 1718 | 1722 | { store_str_char('\n'); } |
| 1719 | 1723 | YY_BREAK |
| 1720 | 1724 | case 15: |
| 1721 | 1725 | YY_RULE_SETUP |
| 1722 | -#line 580 "lexer.y" | |
| 1726 | +#line 584 "lexer.y" | |
| 1723 | 1727 | { store_str_char(yytext[0]); } |
| 1724 | 1728 | YY_BREAK |
| 1725 | 1729 | case 16: |
| 1726 | 1730 | YY_RULE_SETUP |
| 1727 | -#line 581 "lexer.y" | |
| 1731 | +#line 585 "lexer.y" | |
| 1728 | 1732 | { BEGIN PAR; } |
| 1729 | 1733 | YY_BREAK |
| 1730 | 1734 | case 17: |
| 1731 | 1735 | YY_RULE_SETUP |
| 1732 | -#line 582 "lexer.y" | |
| 1736 | +#line 586 "lexer.y" | |
| 1733 | 1737 | { } |
| 1734 | 1738 | YY_BREAK |
| 1735 | 1739 | case 18: |
| 1736 | 1740 | YY_RULE_SETUP |
| 1737 | -#line 583 "lexer.y" | |
| 1741 | +#line 587 "lexer.y" | |
| 1738 | 1742 | { } |
| 1739 | 1743 | YY_BREAK |
| 1740 | 1744 | case 19: |
| 1741 | 1745 | YY_RULE_SETUP |
| 1742 | -#line 584 "lexer.y" | |
| 1746 | +#line 588 "lexer.y" | |
| 1743 | 1747 | { yylval.integer = (int)(unsigned char)yytext[1]; return yy__char; } |
| 1744 | 1748 | YY_BREAK |
| 1745 | 1749 | case 20: |
| 1746 | 1750 | YY_RULE_SETUP |
| 1747 | -#line 585 "lexer.y" | |
| 1751 | +#line 589 "lexer.y" | |
| 1748 | 1752 | { yylval.integer = (int)'\n'; return yy__char; } |
| 1749 | 1753 | YY_BREAK |
| 1750 | 1754 | case 21: |
| 1751 | 1755 | YY_RULE_SETUP |
| 1752 | -#line 586 "lexer.y" | |
| 1756 | +#line 590 "lexer.y" | |
| 1753 | 1757 | { yylval.integer = (int)'\r'; return yy__char; } |
| 1754 | 1758 | YY_BREAK |
| 1755 | 1759 | case 22: |
| 1756 | 1760 | YY_RULE_SETUP |
| 1757 | -#line 587 "lexer.y" | |
| 1761 | +#line 591 "lexer.y" | |
| 1758 | 1762 | { yylval.integer = (int)'\t'; return yy__char; } |
| 1759 | 1763 | YY_BREAK |
| 1760 | 1764 | case 23: |
| 1761 | 1765 | YY_RULE_SETUP |
| 1762 | -#line 588 "lexer.y" | |
| 1766 | +#line 592 "lexer.y" | |
| 1763 | 1767 | { yylval.integer = (int)'\"'; return yy__char; } |
| 1764 | 1768 | YY_BREAK |
| 1765 | 1769 | case 24: |
| 1766 | 1770 | YY_RULE_SETUP |
| 1767 | -#line 589 "lexer.y" | |
| 1771 | +#line 593 "lexer.y" | |
| 1768 | 1772 | { yylval.integer = (int)'\\'; return yy__char; } |
| 1769 | 1773 | YY_BREAK |
| 1770 | 1774 | case 25: |
| 1771 | 1775 | YY_RULE_SETUP |
| 1772 | -#line 590 "lexer.y" | |
| 1776 | +#line 594 "lexer.y" | |
| 1773 | 1777 | { yylval.integer = (int)'\''; return yy__char; } |
| 1774 | 1778 | YY_BREAK |
| 1775 | 1779 | case 26: |
| 1776 | 1780 | YY_RULE_SETUP |
| 1777 | -#line 591 "lexer.y" | |
| 1781 | +#line 595 "lexer.y" | |
| 1778 | 1782 | { yylval.expr = linecol(); return yy__lpar; } |
| 1779 | 1783 | YY_BREAK |
| 1780 | 1784 | case 27: |
| 1781 | 1785 | YY_RULE_SETUP |
| 1782 | -#line 592 "lexer.y" | |
| 1786 | +#line 596 "lexer.y" | |
| 1783 | 1787 | { yylval.expr = linecol(); return yy__rpar; } |
| 1784 | 1788 | YY_BREAK |
| 1785 | 1789 | case 28: |
| 1786 | 1790 | YY_RULE_SETUP |
| 1787 | -#line 593 "lexer.y" | |
| 1791 | +#line 597 "lexer.y" | |
| 1788 | 1792 | { yylval.expr = linecol(); return yy__rpar; } |
| 1789 | 1793 | YY_BREAK |
| 1790 | 1794 | case 29: |
| 1791 | 1795 | YY_RULE_SETUP |
| 1792 | -#line 594 "lexer.y" | |
| 1796 | +#line 598 "lexer.y" | |
| 1793 | 1797 | { yylval.expr = linecol(); return yy__lbrace; } |
| 1794 | 1798 | YY_BREAK |
| 1795 | 1799 | case 30: |
| 1796 | 1800 | YY_RULE_SETUP |
| 1797 | -#line 595 "lexer.y" | |
| 1801 | +#line 599 "lexer.y" | |
| 1798 | 1802 | { yylval.expr = linecol(); return yy__rbrace; } |
| 1799 | 1803 | YY_BREAK |
| 1800 | 1804 | case 31: |
| 1801 | 1805 | YY_RULE_SETUP |
| 1802 | -#line 596 "lexer.y" | |
| 1806 | +#line 600 "lexer.y" | |
| 1803 | 1807 | { yylval.expr = linecol(); return yy__rbrace; } |
| 1804 | 1808 | YY_BREAK |
| 1805 | 1809 | case 32: |
| 1806 | 1810 | YY_RULE_SETUP |
| 1807 | -#line 597 "lexer.y" | |
| 1811 | +#line 601 "lexer.y" | |
| 1808 | 1812 | { yylval.expr = linecol(); return yy__lbracket; } |
| 1809 | 1813 | YY_BREAK |
| 1810 | 1814 | case 33: |
| 1811 | 1815 | YY_RULE_SETUP |
| 1812 | -#line 598 "lexer.y" | |
| 1816 | +#line 602 "lexer.y" | |
| 1813 | 1817 | { yylval.expr = linecol(); return yy__rbracket; } |
| 1814 | 1818 | YY_BREAK |
| 1815 | 1819 | case 34: |
| 1816 | 1820 | YY_RULE_SETUP |
| 1817 | -#line 599 "lexer.y" | |
| 1821 | +#line 603 "lexer.y" | |
| 1818 | 1822 | { yylval.expr = linecol(); return yy__rbracket; } |
| 1819 | 1823 | YY_BREAK |
| 1820 | 1824 | case 35: |
| 1821 | 1825 | YY_RULE_SETUP |
| 1822 | -#line 600 "lexer.y" | |
| 1826 | +#line 604 "lexer.y" | |
| 1823 | 1827 | { yylval.expr = linecol(); return yy__colon; } |
| 1824 | 1828 | YY_BREAK |
| 1825 | 1829 | case 36: |
| 1826 | 1830 | YY_RULE_SETUP |
| 1827 | -#line 601 "lexer.y" | |
| 1831 | +#line 605 "lexer.y" | |
| 1828 | 1832 | { yylval.expr = linecol(); return yy__semicolon; } |
| 1829 | 1833 | YY_BREAK |
| 1830 | 1834 | case 37: |
| 1831 | 1835 | YY_RULE_SETUP |
| 1832 | -#line 602 "lexer.y" | |
| 1836 | +#line 606 "lexer.y" | |
| 1833 | 1837 | { yylval.expr = linecol(); return yy__minus; } |
| 1834 | 1838 | YY_BREAK |
| 1835 | 1839 | case 38: |
| 1836 | 1840 | YY_RULE_SETUP |
| 1837 | -#line 603 "lexer.y" | |
| 1841 | +#line 607 "lexer.y" | |
| 1838 | 1842 | { yylval.expr = linecol(); return yy__dot; } |
| 1839 | 1843 | YY_BREAK |
| 1840 | 1844 | case 39: |
| 1841 | 1845 | YY_RULE_SETUP |
| 1842 | -#line 604 "lexer.y" | |
| 1846 | +#line 608 "lexer.y" | |
| 1843 | 1847 | { yylval.expr = linecol(); return yy__percent; } |
| 1844 | 1848 | YY_BREAK |
| 1845 | 1849 | case 40: |
| 1846 | 1850 | YY_RULE_SETUP |
| 1847 | -#line 605 "lexer.y" | |
| 1851 | +#line 609 "lexer.y" | |
| 1848 | 1852 | { yylval.expr = linecol(); return yy__comma; } |
| 1849 | 1853 | YY_BREAK |
| 1850 | 1854 | case 41: |
| 1851 | 1855 | YY_RULE_SETUP |
| 1852 | -#line 606 "lexer.y" | |
| 1856 | +#line 610 "lexer.y" | |
| 1853 | 1857 | { yylval.expr = linecol(); return yy__tilde; } |
| 1854 | 1858 | YY_BREAK |
| 1855 | 1859 | case 42: |
| 1856 | 1860 | YY_RULE_SETUP |
| 1857 | -#line 607 "lexer.y" | |
| 1861 | +#line 611 "lexer.y" | |
| 1858 | 1862 | { yylval.expr = linecol(); return yy__equals; } |
| 1859 | 1863 | YY_BREAK |
| 1860 | 1864 | case 43: |
| 1861 | 1865 | YY_RULE_SETUP |
| 1862 | -#line 608 "lexer.y" | |
| 1866 | +#line 612 "lexer.y" | |
| 1863 | 1867 | { yylval.expr = linecol(); return yy__non_equal; } |
| 1864 | 1868 | YY_BREAK |
| 1865 | 1869 | case 44: |
| 1866 | 1870 | YY_RULE_SETUP |
| 1867 | -#line 609 "lexer.y" | |
| 1871 | +#line 613 "lexer.y" | |
| 1868 | 1872 | { yylval.expr = linecol(); return yy__plus; } |
| 1869 | 1873 | YY_BREAK |
| 1870 | 1874 | case 45: |
| 1871 | 1875 | YY_RULE_SETUP |
| 1872 | -#line 610 "lexer.y" | |
| 1876 | +#line 614 "lexer.y" | |
| 1873 | 1877 | { yylval.expr = linecol(); return yy__star; } |
| 1874 | 1878 | YY_BREAK |
| 1875 | 1879 | case 46: |
| 1876 | 1880 | YY_RULE_SETUP |
| 1877 | -#line 611 "lexer.y" | |
| 1881 | +#line 615 "lexer.y" | |
| 1878 | 1882 | { yylval.expr = linecol(); return yy__carret; } |
| 1879 | 1883 | YY_BREAK |
| 1880 | 1884 | case 47: |
| 1881 | 1885 | YY_RULE_SETUP |
| 1882 | -#line 612 "lexer.y" | |
| 1886 | +#line 616 "lexer.y" | |
| 1883 | 1887 | { yylval.expr = linecol(); return yy__ampersand; } |
| 1884 | 1888 | YY_BREAK |
| 1885 | 1889 | case 48: |
| 1886 | 1890 | YY_RULE_SETUP |
| 1887 | -#line 613 "lexer.y" | |
| 1891 | +#line 617 "lexer.y" | |
| 1888 | 1892 | { yylval.expr = linecol(); return yy__vbar; } |
| 1889 | 1893 | YY_BREAK |
| 1890 | 1894 | case 49: |
| 1891 | 1895 | YY_RULE_SETUP |
| 1892 | -#line 614 "lexer.y" | |
| 1896 | +#line 618 "lexer.y" | |
| 1893 | 1897 | { yylval.expr = linecol(); return yy__right_shift; } |
| 1894 | 1898 | YY_BREAK |
| 1895 | 1899 | case 50: |
| 1896 | 1900 | YY_RULE_SETUP |
| 1897 | -#line 615 "lexer.y" | |
| 1901 | +#line 619 "lexer.y" | |
| 1898 | 1902 | { yylval.expr = linecol(); return yy__left_shift; } |
| 1899 | 1903 | YY_BREAK |
| 1900 | 1904 | case 51: |
| 1901 | 1905 | YY_RULE_SETUP |
| 1902 | -#line 616 "lexer.y" | |
| 1906 | +#line 620 "lexer.y" | |
| 1903 | 1907 | { yylval.expr = linecol(); return yy__implies; } |
| 1904 | 1908 | YY_BREAK |
| 1905 | 1909 | case 52: |
| 1906 | 1910 | YY_RULE_SETUP |
| 1907 | -#line 617 "lexer.y" | |
| 1911 | +#line 621 "lexer.y" | |
| 1908 | 1912 | { yylval.expr = linecol(); return yy__forall; } |
| 1909 | 1913 | YY_BREAK |
| 1910 | 1914 | case 53: |
| 1911 | 1915 | YY_RULE_SETUP |
| 1912 | -#line 618 "lexer.y" | |
| 1916 | +#line 622 "lexer.y" | |
| 1913 | 1917 | { yylval.expr = linecol(); return yy__exists; } |
| 1914 | 1918 | YY_BREAK |
| 1915 | 1919 | case 54: |
| 1916 | 1920 | YY_RULE_SETUP |
| 1917 | -#line 619 "lexer.y" | |
| 1921 | +#line 623 "lexer.y" | |
| 1918 | 1922 | { yylval.expr = linecol(); return yy__exists_unique; } |
| 1919 | 1923 | YY_BREAK |
| 1920 | 1924 | case 55: |
| 1921 | 1925 | YY_RULE_SETUP |
| 1922 | -#line 620 "lexer.y" | |
| 1926 | +#line 624 "lexer.y" | |
| 1923 | 1927 | { yylval.expr = linecol(); return yy__description; } |
| 1924 | 1928 | YY_BREAK |
| 1925 | 1929 | case 56: |
| 1926 | 1930 | YY_RULE_SETUP |
| 1927 | -#line 621 "lexer.y" | |
| 1931 | +#line 625 "lexer.y" | |
| 1928 | 1932 | { yylval.expr = linecol(); return yy__slash; } |
| 1929 | 1933 | YY_BREAK |
| 1930 | 1934 | case 57: |
| 1931 | 1935 | YY_RULE_SETUP |
| 1932 | -#line 622 "lexer.y" | |
| 1936 | +#line 626 "lexer.y" | |
| 1933 | 1937 | { yylval.expr = linecol(); return yy__mod; } |
| 1934 | 1938 | YY_BREAK |
| 1935 | 1939 | case 58: |
| 1936 | 1940 | YY_RULE_SETUP |
| 1937 | -#line 623 "lexer.y" | |
| 1941 | +#line 627 "lexer.y" | |
| 1938 | 1942 | { yylval.expr = linecol(); return yy__less; } |
| 1939 | 1943 | YY_BREAK |
| 1940 | 1944 | case 59: |
| 1941 | 1945 | YY_RULE_SETUP |
| 1942 | -#line 624 "lexer.y" | |
| 1946 | +#line 628 "lexer.y" | |
| 1943 | 1947 | { yylval.expr = linecol(); return yy__greater; } |
| 1944 | 1948 | YY_BREAK |
| 1945 | 1949 | case 60: |
| 1946 | 1950 | YY_RULE_SETUP |
| 1947 | -#line 625 "lexer.y" | |
| 1951 | +#line 629 "lexer.y" | |
| 1948 | 1952 | { yylval.expr = linecol(); return yy__lessoreq; } |
| 1949 | 1953 | YY_BREAK |
| 1950 | 1954 | case 61: |
| 1951 | 1955 | YY_RULE_SETUP |
| 1952 | -#line 626 "lexer.y" | |
| 1956 | +#line 630 "lexer.y" | |
| 1953 | 1957 | { yylval.expr = linecol(); return yy__greateroreq; } |
| 1954 | 1958 | YY_BREAK |
| 1955 | 1959 | case 62: |
| 1956 | 1960 | YY_RULE_SETUP |
| 1957 | -#line 627 "lexer.y" | |
| 1961 | +#line 631 "lexer.y" | |
| 1958 | 1962 | { yylval.expr = linecol(); return yy__write; } |
| 1959 | 1963 | YY_BREAK |
| 1960 | 1964 | case 63: |
| 1961 | 1965 | YY_RULE_SETUP |
| 1962 | -#line 628 "lexer.y" | |
| 1966 | +#line 632 "lexer.y" | |
| 1963 | 1967 | { yylval.expr = linecol(); return yy__exchange; } |
| 1964 | 1968 | YY_BREAK |
| 1965 | 1969 | case 64: |
| 1966 | 1970 | YY_RULE_SETUP |
| 1967 | -#line 629 "lexer.y" | |
| 1971 | +#line 633 "lexer.y" | |
| 1968 | 1972 | { yylval.expr = linecol(); return yy__arrow; } |
| 1969 | 1973 | YY_BREAK |
| 1970 | 1974 | case 65: |
| 1971 | 1975 | YY_RULE_SETUP |
| 1972 | -#line 630 "lexer.y" | |
| 1976 | +#line 634 "lexer.y" | |
| 1973 | 1977 | { yylval.expr = linecol(); return yy__arroww; } |
| 1974 | 1978 | YY_BREAK |
| 1975 | 1979 | case 66: |
| 1976 | 1980 | YY_RULE_SETUP |
| 1977 | -#line 631 "lexer.y" | |
| 1981 | +#line 635 "lexer.y" | |
| 1978 | 1982 | { yylval.expr = linecol(); return yy__mapsto; } |
| 1979 | 1983 | YY_BREAK |
| 1980 | 1984 | case 67: |
| 1981 | 1985 | YY_RULE_SETUP |
| 1982 | -#line 632 "lexer.y" | |
| 1986 | +#line 636 "lexer.y" | |
| 1983 | 1987 | { yylval.expr = linecol(); return yy__mapstoo; } |
| 1984 | 1988 | YY_BREAK |
| 1985 | 1989 | case 68: |
| 1986 | 1990 | YY_RULE_SETUP |
| 1987 | -#line 633 "lexer.y" | |
| 1991 | +#line 637 "lexer.y" | |
| 1988 | 1992 | { yylval.expr = linecol(); return yy__dots; } |
| 1989 | 1993 | YY_BREAK |
| 1990 | 1994 | case 69: |
| 1991 | 1995 | YY_RULE_SETUP |
| 1992 | -#line 634 "lexer.y" | |
| 1996 | +#line 638 "lexer.y" | |
| 1993 | 1997 | { yylval.expr = linecol(); return yy__rpar_arrow; } |
| 1994 | 1998 | YY_BREAK |
| 1995 | 1999 | case 70: |
| 1996 | 2000 | YY_RULE_SETUP |
| 1997 | -#line 635 "lexer.y" | |
| 2001 | +#line 639 "lexer.y" | |
| 1998 | 2002 | { yylval.expr = linecol(); return yy__type_String; } |
| 1999 | 2003 | YY_BREAK |
| 2000 | 2004 | case 71: |
| 2001 | 2005 | YY_RULE_SETUP |
| 2002 | -#line 636 "lexer.y" | |
| 2006 | +#line 640 "lexer.y" | |
| 2003 | 2007 | { yylval.expr = linecol(); return yy__type_ByteArray; } |
| 2004 | 2008 | YY_BREAK |
| 2005 | 2009 | case 72: |
| 2006 | 2010 | YY_RULE_SETUP |
| 2007 | -#line 637 "lexer.y" | |
| 2011 | +#line 641 "lexer.y" | |
| 2008 | 2012 | { yylval.expr = linecol(); return yy__type_Int32; } |
| 2009 | 2013 | YY_BREAK |
| 2010 | 2014 | case 73: |
| 2011 | 2015 | YY_RULE_SETUP |
| 2012 | -#line 638 "lexer.y" | |
| 2016 | +#line 642 "lexer.y" | |
| 2013 | 2017 | { yylval.expr = linecol(); return yy__type_Omega; } |
| 2014 | 2018 | YY_BREAK |
| 2015 | 2019 | case 74: |
| 2016 | 2020 | YY_RULE_SETUP |
| 2017 | -#line 639 "lexer.y" | |
| 2021 | +#line 643 "lexer.y" | |
| 2018 | 2022 | { yylval.expr = linecol(); return yy__bit_width; } |
| 2019 | 2023 | YY_BREAK |
| 2020 | 2024 | case 75: |
| 2021 | 2025 | YY_RULE_SETUP |
| 2022 | -#line 640 "lexer.y" | |
| 2026 | +#line 644 "lexer.y" | |
| 2023 | 2027 | { yylval.expr = linecol(); return yy__indirect; } |
| 2024 | 2028 | YY_BREAK |
| 2025 | 2029 | case 76: |
| 2026 | 2030 | YY_RULE_SETUP |
| 2027 | -#line 641 "lexer.y" | |
| 2031 | +#line 645 "lexer.y" | |
| 2028 | 2032 | { if (reading_predef) |
| 2029 | 2033 | { yylval.expr = linecol(); return yy__vcopy; } |
| 2030 | 2034 | else lexical_error(); } |
| 2031 | 2035 | YY_BREAK |
| 2032 | 2036 | case 77: |
| 2033 | 2037 | YY_RULE_SETUP |
| 2034 | -#line 644 "lexer.y" | |
| 2038 | +#line 648 "lexer.y" | |
| 2035 | 2039 | { if (reading_predef) |
| 2036 | 2040 | { yylval.expr = linecol(); return yy__load_module; } |
| 2037 | 2041 | else lexical_error(); } |
| 2038 | 2042 | YY_BREAK |
| 2039 | 2043 | case 78: |
| 2040 | 2044 | YY_RULE_SETUP |
| 2041 | -#line 647 "lexer.y" | |
| 2045 | +#line 651 "lexer.y" | |
| 2042 | 2046 | { if (reading_predef) |
| 2043 | 2047 | { yylval.expr = linecol(); return yy__serialize; } |
| 2044 | 2048 | else lexical_error(); } |
| 2045 | 2049 | YY_BREAK |
| 2046 | 2050 | case 79: |
| 2047 | 2051 | YY_RULE_SETUP |
| 2048 | -#line 650 "lexer.y" | |
| 2052 | +#line 654 "lexer.y" | |
| 2049 | 2053 | { if (reading_predef) |
| 2050 | 2054 | { yylval.expr = linecol(); return yy__unserialize; } |
| 2051 | 2055 | else lexical_error(); } |
| 2052 | 2056 | YY_BREAK |
| 2053 | 2057 | case 80: |
| 2054 | 2058 | YY_RULE_SETUP |
| 2055 | -#line 653 "lexer.y" | |
| 2059 | +#line 657 "lexer.y" | |
| 2056 | 2060 | { yylval.expr = linecol(); return yy__type_Float; } |
| 2057 | 2061 | YY_BREAK |
| 2058 | 2062 | case 81: |
| 2059 | 2063 | YY_RULE_SETUP |
| 2060 | -#line 654 "lexer.y" | |
| 2064 | +#line 658 "lexer.y" | |
| 2061 | 2065 | { if (reading_predef) |
| 2062 | 2066 | { yylval.expr = linecol(); return yy__type_Listener; } |
| 2063 | 2067 | else lexical_error(); } |
| 2064 | 2068 | YY_BREAK |
| 2065 | 2069 | case 82: |
| 2066 | 2070 | YY_RULE_SETUP |
| 2067 | -#line 657 "lexer.y" | |
| 2071 | +#line 661 "lexer.y" | |
| 2068 | 2072 | { if (reading_predef) |
| 2069 | 2073 | { yylval.expr = linecol(); return yy__StructPtr; } |
| 2070 | 2074 | else lexical_error(); } |
| 2071 | 2075 | YY_BREAK |
| 2072 | 2076 | case 83: |
| 2073 | 2077 | YY_RULE_SETUP |
| 2074 | -#line 660 "lexer.y" | |
| 2078 | +#line 664 "lexer.y" | |
| 2075 | 2079 | { if (reading_predef) |
| 2076 | 2080 | { yylval.expr = linecol(); return yy__avm; } |
| 2077 | 2081 | else lexical_error(); } |
| 2078 | 2082 | YY_BREAK |
| 2079 | 2083 | case 84: |
| 2080 | 2084 | YY_RULE_SETUP |
| 2081 | -#line 663 "lexer.y" | |
| 2085 | +#line 667 "lexer.y" | |
| 2082 | 2086 | { yylval.expr = linecol(); return yy__if; } |
| 2083 | 2087 | YY_BREAK |
| 2084 | 2088 | case 85: |
| 2085 | 2089 | YY_RULE_SETUP |
| 2086 | -#line 664 "lexer.y" | |
| 2090 | +#line 668 "lexer.y" | |
| 2087 | 2091 | { yylval.expr = linecol(); return yy__proof; } |
| 2088 | 2092 | YY_BREAK |
| 2089 | 2093 | case 86: |
| 2090 | 2094 | YY_RULE_SETUP |
| 2091 | -#line 665 "lexer.y" | |
| 2095 | +#line 669 "lexer.y" | |
| 2092 | 2096 | { yylval.expr = linecol(); return yy__type_Proof; } |
| 2093 | 2097 | YY_BREAK |
| 2094 | 2098 | case 87: |
| 2095 | 2099 | YY_RULE_SETUP |
| 2096 | -#line 666 "lexer.y" | |
| 2100 | +#line 670 "lexer.y" | |
| 2097 | 2101 | { yylval.expr = linecol(); return yy__since; } |
| 2098 | 2102 | YY_BREAK |
| 2099 | 2103 | case 88: |
| 2100 | 2104 | YY_RULE_SETUP |
| 2101 | -#line 667 "lexer.y" | |
| 2105 | +#line 671 "lexer.y" | |
| 2102 | 2106 | { return yy__is; } |
| 2103 | 2107 | YY_BREAK |
| 2104 | 2108 | case 89: |
| 2105 | 2109 | YY_RULE_SETUP |
| 2106 | -#line 668 "lexer.y" | |
| 2110 | +#line 672 "lexer.y" | |
| 2107 | 2111 | { yylval.expr = linecol(); return yy__then; } |
| 2108 | 2112 | YY_BREAK |
| 2109 | 2113 | case 90: |
| 2110 | 2114 | YY_RULE_SETUP |
| 2111 | -#line 669 "lexer.y" | |
| 2115 | +#line 673 "lexer.y" | |
| 2112 | 2116 | { yylval.expr = linecol(); return yy__alert; } |
| 2113 | 2117 | YY_BREAK |
| 2114 | 2118 | case 91: |
| 2115 | 2119 | YY_RULE_SETUP |
| 2116 | -#line 670 "lexer.y" | |
| 2120 | +#line 674 "lexer.y" | |
| 2117 | 2121 | { yylval.expr = linecol(); return yy__protect; } |
| 2118 | 2122 | YY_BREAK |
| 2119 | 2123 | case 92: |
| 2120 | 2124 | YY_RULE_SETUP |
| 2121 | -#line 671 "lexer.y" | |
| 2125 | +#line 675 "lexer.y" | |
| 2122 | 2126 | { yylval.expr = linecol(); return yy__lock; } |
| 2123 | 2127 | YY_BREAK |
| 2124 | 2128 | case 93: |
| 2125 | 2129 | YY_RULE_SETUP |
| 2126 | -#line 672 "lexer.y" | |
| 2130 | +#line 676 "lexer.y" | |
| 2127 | 2131 | { yylval.expr = linecol(); return yy__succeeds; } |
| 2128 | 2132 | YY_BREAK |
| 2129 | 2133 | case 94: |
| 2130 | 2134 | YY_RULE_SETUP |
| 2131 | -#line 673 "lexer.y" | |
| 2135 | +#line 677 "lexer.y" | |
| 2132 | 2136 | { yylval.expr = linecol(); return yy__succeeds_as; } |
| 2133 | 2137 | YY_BREAK |
| 2134 | 2138 | case 95: |
| 2135 | 2139 | YY_RULE_SETUP |
| 2136 | -#line 674 "lexer.y" | |
| 2140 | +#line 678 "lexer.y" | |
| 2137 | 2141 | { yylval.expr = linecol(); return yy__wait_for; } |
| 2138 | 2142 | YY_BREAK |
| 2139 | 2143 | case 96: |
| 2140 | 2144 | YY_RULE_SETUP |
| 2141 | -#line 675 "lexer.y" | |
| 2145 | +#line 679 "lexer.y" | |
| 2142 | 2146 | { yylval.expr = linecol(); return yy__checking_every; } |
| 2143 | 2147 | YY_BREAK |
| 2144 | 2148 | case 97: |
| 2145 | 2149 | YY_RULE_SETUP |
| 2146 | -#line 676 "lexer.y" | |
| 2150 | +#line 680 "lexer.y" | |
| 2147 | 2151 | { yylval.expr = linecol(); return yy__delegate; } |
| 2148 | 2152 | YY_BREAK |
| 2149 | 2153 | case 98: |
| 2150 | 2154 | YY_RULE_SETUP |
| 2151 | -#line 677 "lexer.y" | |
| 2155 | +#line 681 "lexer.y" | |
| 2152 | 2156 | { yylval.expr = linecol(); return yy__else; } |
| 2153 | 2157 | YY_BREAK |
| 2154 | 2158 | case 99: |
| 2155 | 2159 | YY_RULE_SETUP |
| 2156 | -#line 678 "lexer.y" | |
| 2160 | +#line 682 "lexer.y" | |
| 2157 | 2161 | { yylval.expr = linecol(); return yy__with; } |
| 2158 | 2162 | YY_BREAK |
| 2159 | 2163 | case 100: |
| 2160 | 2164 | YY_RULE_SETUP |
| 2161 | -#line 679 "lexer.y" | |
| 2165 | +#line 683 "lexer.y" | |
| 2162 | 2166 | { yylval.expr = linecol(); return yy__alt_number; } |
| 2163 | 2167 | YY_BREAK |
| 2164 | 2168 | case 101: |
| 2165 | 2169 | YY_RULE_SETUP |
| 2166 | -#line 680 "lexer.y" | |
| 2170 | +#line 684 "lexer.y" | |
| 2167 | 2171 | { yylval.expr = linecol(); return yy__RAddr; } |
| 2168 | 2172 | YY_BREAK |
| 2169 | 2173 | case 102: |
| 2170 | 2174 | YY_RULE_SETUP |
| 2171 | -#line 681 "lexer.y" | |
| 2175 | +#line 685 "lexer.y" | |
| 2172 | 2176 | { yylval.expr = linecol(); return yy__WAddr; } |
| 2173 | 2177 | YY_BREAK |
| 2174 | 2178 | case 103: |
| 2175 | 2179 | YY_RULE_SETUP |
| 2176 | -#line 682 "lexer.y" | |
| 2180 | +#line 686 "lexer.y" | |
| 2177 | 2181 | { yylval.expr = linecol(); return yy__RWAddr; } |
| 2178 | 2182 | YY_BREAK |
| 2179 | 2183 | case 104: |
| 2180 | 2184 | YY_RULE_SETUP |
| 2181 | -#line 683 "lexer.y" | |
| 2185 | +#line 687 "lexer.y" | |
| 2182 | 2186 | { yylval.expr = linecol(); return yy__GAddr; } |
| 2183 | 2187 | YY_BREAK |
| 2184 | 2188 | case 105: |
| 2185 | 2189 | YY_RULE_SETUP |
| 2186 | -#line 684 "lexer.y" | |
| 2190 | +#line 688 "lexer.y" | |
| 2187 | 2191 | { yylval.expr = linecol(); return yy__Var; } |
| 2188 | 2192 | YY_BREAK |
| 2189 | 2193 | case 106: |
| 2190 | 2194 | YY_RULE_SETUP |
| 2191 | -#line 685 "lexer.y" | |
| 2195 | +#line 689 "lexer.y" | |
| 2192 | 2196 | { yylval.expr = linecol(); return yy__MVar; } |
| 2193 | 2197 | YY_BREAK |
| 2194 | 2198 | case 107: |
| 2195 | 2199 | YY_RULE_SETUP |
| 2196 | -#line 686 "lexer.y" | |
| 2200 | +#line 690 "lexer.y" | |
| 2197 | 2201 | { yylval.expr = linecol(); return yy__connect_to_file; } |
| 2198 | 2202 | YY_BREAK |
| 2199 | 2203 | case 108: |
| 2200 | 2204 | YY_RULE_SETUP |
| 2201 | -#line 687 "lexer.y" | |
| 2205 | +#line 691 "lexer.y" | |
| 2202 | 2206 | { yylval.expr = linecol(); return yy__connect_to_IP; } |
| 2203 | 2207 | YY_BREAK |
| 2204 | 2208 | case 109: |
| 2205 | 2209 | YY_RULE_SETUP |
| 2206 | -#line 688 "lexer.y" | |
| 2210 | +#line 692 "lexer.y" | |
| 2207 | 2211 | { yylval.expr = linecol(); return yy__debug_avm; } |
| 2208 | 2212 | YY_BREAK |
| 2209 | 2213 | case 110: |
| 2210 | 2214 | YY_RULE_SETUP |
| 2211 | -#line 689 "lexer.y" | |
| 2215 | +#line 693 "lexer.y" | |
| 2212 | 2216 | { yylval.expr = linecol(); return yy__terminal; } |
| 2213 | 2217 | YY_BREAK |
| 2214 | 2218 | case 111: |
| 2215 | 2219 | YY_RULE_SETUP |
| 2216 | -#line 690 "lexer.y" | |
| 2220 | +#line 694 "lexer.y" | |
| 2217 | 2221 | { yylval.expr = linecol(); return yy__we_have; } |
| 2218 | 2222 | YY_BREAK |
| 2219 | 2223 | case 112: |
| 2220 | 2224 | YY_RULE_SETUP |
| 2221 | -#line 691 "lexer.y" | |
| 2225 | +#line 695 "lexer.y" | |
| 2222 | 2226 | { yylval.expr = linecol(); |
| 2223 | 2227 | return yy__enough; } |
| 2224 | 2228 | YY_BREAK |
| 2225 | 2229 | case 113: |
| 2226 | 2230 | YY_RULE_SETUP |
| 2227 | -#line 693 "lexer.y" | |
| 2231 | +#line 697 "lexer.y" | |
| 2228 | 2232 | { yylval.expr = linecol(); return yy__let; } |
| 2229 | 2233 | YY_BREAK |
| 2230 | 2234 | case 114: |
| 2231 | 2235 | YY_RULE_SETUP |
| 2232 | -#line 694 "lexer.y" | |
| 2236 | +#line 698 "lexer.y" | |
| 2233 | 2237 | { yylval.expr = linecol(); return yy__assume; } |
| 2234 | 2238 | YY_BREAK |
| 2235 | 2239 | case 115: |
| 2236 | 2240 | YY_RULE_SETUP |
| 2237 | -#line 695 "lexer.y" | |
| 2241 | +#line 699 "lexer.y" | |
| 2238 | 2242 | { yylval.expr = linecol(); return yy__hence; } |
| 2239 | 2243 | YY_BREAK |
| 2240 | 2244 | case 116: |
| 2241 | 2245 | YY_RULE_SETUP |
| 2242 | -#line 696 "lexer.y" | |
| 2246 | +#line 700 "lexer.y" | |
| 2243 | 2247 | { yylval.expr = linecol(); return yy__indeed; } |
| 2244 | 2248 | YY_BREAK |
| 2245 | 2249 | case 117: |
| 2246 | 2250 | YY_RULE_SETUP |
| 2247 | -#line 697 "lexer.y" | |
| 2251 | +#line 701 "lexer.y" | |
| 2248 | 2252 | { BEGIN CONF; return yy__stop_after; } |
| 2249 | 2253 | YY_BREAK |
| 2250 | 2254 | case 118: |
| 2251 | 2255 | YY_RULE_SETUP |
| 2252 | -#line 698 "lexer.y" | |
| 2256 | +#line 702 "lexer.y" | |
| 2253 | 2257 | { BEGIN CONF; return yy__djed; } |
| 2254 | 2258 | YY_BREAK |
| 2255 | 2259 | case 119: |
| 2256 | 2260 | YY_RULE_SETUP |
| 2257 | -#line 699 "lexer.y" | |
| 2261 | +#line 703 "lexer.y" | |
| 2258 | 2262 | { return yy__verbose; } |
| 2259 | 2263 | YY_BREAK |
| 2260 | 2264 | case 120: |
| 2261 | 2265 | YY_RULE_SETUP |
| 2262 | -#line 700 "lexer.y" | |
| 2266 | +#line 704 "lexer.y" | |
| 2263 | 2267 | { BEGIN CONF; return yy__language; } |
| 2264 | 2268 | YY_BREAK |
| 2265 | 2269 | case 121: |
| 2266 | 2270 | YY_RULE_SETUP |
| 2267 | -#line 701 "lexer.y" | |
| 2271 | +#line 705 "lexer.y" | |
| 2268 | 2272 | { fprintf(errfile,msgtext_syntax_error_in_conf_file[language], |
| 2269 | 2273 | my_anubis_directory,lineno); anb_exit(1); } |
| 2270 | 2274 | YY_BREAK |
| 2271 | 2275 | case 122: |
| 2272 | 2276 | YY_RULE_SETUP |
| 2273 | -#line 703 "lexer.y" | |
| 2277 | +#line 707 "lexer.y" | |
| 2274 | 2278 | { } |
| 2275 | 2279 | YY_BREAK |
| 2276 | 2280 | case 123: |
| 2277 | 2281 | YY_RULE_SETUP |
| 2278 | -#line 704 "lexer.y" | |
| 2282 | +#line 708 "lexer.y" | |
| 2279 | 2283 | { } |
| 2280 | 2284 | YY_BREAK |
| 2281 | 2285 | case 124: |
| 2282 | 2286 | YY_RULE_SETUP |
| 2283 | -#line 705 "lexer.y" | |
| 2287 | +#line 709 "lexer.y" | |
| 2284 | 2288 | { |
| 2285 | 2289 | yytext[yyleng-1] = 0; |
| 2286 | 2290 | yylval.expr = new_string(yytext+1); |
| ... | ... | @@ -2289,118 +2293,118 @@ YY_RULE_SETUP |
| 2289 | 2293 | YY_BREAK |
| 2290 | 2294 | case 125: |
| 2291 | 2295 | YY_RULE_SETUP |
| 2292 | -#line 710 "lexer.y" | |
| 2296 | +#line 714 "lexer.y" | |
| 2293 | 2297 | { |
| 2294 | 2298 | yylval.expr = new_string(yytext); |
| 2295 | 2299 | return yy__conf_symbol; } |
| 2296 | 2300 | YY_BREAK |
| 2297 | 2301 | case 126: |
| 2298 | 2302 | YY_RULE_SETUP |
| 2299 | -#line 713 "lexer.y" | |
| 2303 | +#line 717 "lexer.y" | |
| 2300 | 2304 | { yylval.expr = new_integer(atoi(yytext)); return yy__conf_int; } |
| 2301 | 2305 | YY_BREAK |
| 2302 | 2306 | case 127: |
| 2303 | 2307 | YY_RULE_SETUP |
| 2304 | -#line 714 "lexer.y" | |
| 2308 | +#line 718 "lexer.y" | |
| 2305 | 2309 | { } |
| 2306 | 2310 | YY_BREAK |
| 2307 | 2311 | case 128: |
| 2308 | 2312 | YY_RULE_SETUP |
| 2309 | -#line 715 "lexer.y" | |
| 2313 | +#line 719 "lexer.y" | |
| 2310 | 2314 | { BEGIN CONFCOM; } |
| 2311 | 2315 | YY_BREAK |
| 2312 | 2316 | case 129: |
| 2313 | 2317 | YY_RULE_SETUP |
| 2314 | -#line 716 "lexer.y" | |
| 2318 | +#line 720 "lexer.y" | |
| 2315 | 2319 | { BEGIN CONFCOM; fprintf(errfile,msgtext_syntax_error_in_conf_file[language], |
| 2316 | 2320 | my_anubis_directory,lineno); anb_exit(1); } |
| 2317 | 2321 | YY_BREAK |
| 2318 | 2322 | case 130: |
| 2319 | 2323 | YY_RULE_SETUP |
| 2320 | -#line 718 "lexer.y" | |
| 2324 | +#line 722 "lexer.y" | |
| 2321 | 2325 | { printf(yytext); fflush(stdout); } |
| 2322 | 2326 | YY_BREAK |
| 2323 | 2327 | case 131: |
| 2324 | 2328 | YY_RULE_SETUP |
| 2325 | -#line 719 "lexer.y" | |
| 2329 | +#line 723 "lexer.y" | |
| 2326 | 2330 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2327 | 2331 | yylval.expr = linecol(); return yy__type; } |
| 2328 | 2332 | YY_BREAK |
| 2329 | 2333 | case 132: |
| 2330 | 2334 | YY_RULE_SETUP |
| 2331 | -#line 721 "lexer.y" | |
| 2335 | +#line 725 "lexer.y" | |
| 2332 | 2336 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2333 | 2337 | yylval.expr = linecol(); return yy__p_type; } |
| 2334 | 2338 | YY_BREAK |
| 2335 | 2339 | case 133: |
| 2336 | 2340 | YY_RULE_SETUP |
| 2337 | -#line 723 "lexer.y" | |
| 2341 | +#line 727 "lexer.y" | |
| 2338 | 2342 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2339 | 2343 | yylval.expr = linecol(); return yy__variable; } |
| 2340 | 2344 | YY_BREAK |
| 2341 | 2345 | case 134: |
| 2342 | 2346 | YY_RULE_SETUP |
| 2343 | -#line 725 "lexer.y" | |
| 2347 | +#line 729 "lexer.y" | |
| 2344 | 2348 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2345 | 2349 | yylval.expr = linecol(); return yy__p_variable; } |
| 2346 | 2350 | YY_BREAK |
| 2347 | 2351 | case 135: |
| 2348 | 2352 | YY_RULE_SETUP |
| 2349 | -#line 727 "lexer.y" | |
| 2353 | +#line 731 "lexer.y" | |
| 2350 | 2354 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2351 | 2355 | yylval.expr = linecol(); return yy__theorem; } |
| 2352 | 2356 | YY_BREAK |
| 2353 | 2357 | case 136: |
| 2354 | 2358 | YY_RULE_SETUP |
| 2355 | -#line 729 "lexer.y" | |
| 2359 | +#line 733 "lexer.y" | |
| 2356 | 2360 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2357 | 2361 | yylval.expr = linecol(); return yy__p_theorem; } |
| 2358 | 2362 | YY_BREAK |
| 2359 | 2363 | case 137: |
| 2360 | 2364 | YY_RULE_SETUP |
| 2361 | -#line 731 "lexer.y" | |
| 2365 | +#line 735 "lexer.y" | |
| 2362 | 2366 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2363 | 2367 | yylval.expr = linecol(); return yy__operation; } |
| 2364 | 2368 | YY_BREAK |
| 2365 | 2369 | case 138: |
| 2366 | 2370 | YY_RULE_SETUP |
| 2367 | -#line 733 "lexer.y" | |
| 2371 | +#line 737 "lexer.y" | |
| 2368 | 2372 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2369 | 2373 | yylval.expr = linecol(); return yy__g_operation; } |
| 2370 | 2374 | YY_BREAK |
| 2371 | 2375 | case 139: |
| 2372 | 2376 | YY_RULE_SETUP |
| 2373 | -#line 735 "lexer.y" | |
| 2377 | +#line 739 "lexer.y" | |
| 2374 | 2378 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2375 | 2379 | yylval.expr = linecol(); return yy__operation; } |
| 2376 | 2380 | YY_BREAK |
| 2377 | 2381 | case 140: |
| 2378 | 2382 | YY_RULE_SETUP |
| 2379 | -#line 737 "lexer.y" | |
| 2383 | +#line 741 "lexer.y" | |
| 2380 | 2384 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2381 | 2385 | yylval.expr = linecol(); return yy__g_operation; } |
| 2382 | 2386 | YY_BREAK |
| 2383 | 2387 | case 141: |
| 2384 | 2388 | YY_RULE_SETUP |
| 2385 | -#line 739 "lexer.y" | |
| 2389 | +#line 743 "lexer.y" | |
| 2386 | 2390 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2387 | 2391 | yylval.expr = linecol(); return yy__p_operation; } |
| 2388 | 2392 | YY_BREAK |
| 2389 | 2393 | case 142: |
| 2390 | 2394 | YY_RULE_SETUP |
| 2391 | -#line 741 "lexer.y" | |
| 2395 | +#line 745 "lexer.y" | |
| 2392 | 2396 | { if (polish) { yylval.expr = linecol(); BEGIN INCL; return yy__read; } |
| 2393 | 2397 | else if (!gindex && !errors) { BEGIN INCL; } } |
| 2394 | 2398 | YY_BREAK |
| 2395 | 2399 | case 143: |
| 2396 | 2400 | YY_RULE_SETUP |
| 2397 | -#line 743 "lexer.y" | |
| 2401 | +#line 747 "lexer.y" | |
| 2398 | 2402 | { BEGIN PAR; par_seen = 1; current_par_line = lineno; |
| 2399 | 2403 | yylval.expr = linecol(); return yy__C_constr_for; } |
| 2400 | 2404 | YY_BREAK |
| 2401 | 2405 | case 144: |
| 2402 | 2406 | YY_RULE_SETUP |
| 2403 | -#line 745 "lexer.y" | |
| 2407 | +#line 749 "lexer.y" | |
| 2404 | 2408 | { if (polish) |
| 2405 | 2409 | { |
| 2406 | 2410 | yylval.expr = new_string(yytext); |
| ... | ... | @@ -2421,6 +2425,7 @@ YY_RULE_SETUP |
| 2421 | 2425 | else |
| 2422 | 2426 | { if (include_stack_ptr >= max_include) |
| 2423 | 2427 | { |
| 2428 | + err_line_col(linecol()); | |
| 2424 | 2429 | fprintf(errfile, |
| 2425 | 2430 | msgtext_include_too_deeply[language], |
| 2426 | 2431 | max_include); |
| ... | ... | @@ -2456,12 +2461,12 @@ YY_RULE_SETUP |
| 2456 | 2461 | YY_BREAK |
| 2457 | 2462 | case 145: |
| 2458 | 2463 | YY_RULE_SETUP |
| 2459 | -#line 797 "lexer.y" | |
| 2464 | +#line 802 "lexer.y" | |
| 2460 | 2465 | { lexical_kwread_error(); } |
| 2461 | 2466 | YY_BREAK |
| 2462 | 2467 | case 146: |
| 2463 | 2468 | YY_RULE_SETUP |
| 2464 | -#line 798 "lexer.y" | |
| 2469 | +#line 803 "lexer.y" | |
| 2465 | 2470 | { lexical_kwread_error(); } |
| 2466 | 2471 | YY_BREAK |
| 2467 | 2472 | case YY_STATE_EOF(INITIAL): |
| ... | ... | @@ -2472,7 +2477,7 @@ case YY_STATE_EOF(STR): |
| 2472 | 2477 | case YY_STATE_EOF(STRTL): |
| 2473 | 2478 | case YY_STATE_EOF(CONF): |
| 2474 | 2479 | case YY_STATE_EOF(CONFCOM): |
| 2475 | -#line 799 "lexer.y" | |
| 2480 | +#line 804 "lexer.y" | |
| 2476 | 2481 | { if (include_stack_ptr == 0) |
| 2477 | 2482 | { |
| 2478 | 2483 | yyterminate(); |
| ... | ... | @@ -2505,44 +2510,44 @@ case YY_STATE_EOF(CONFCOM): |
| 2505 | 2510 | YY_BREAK |
| 2506 | 2511 | case 147: |
| 2507 | 2512 | YY_RULE_SETUP |
| 2508 | -#line 828 "lexer.y" | |
| 2513 | +#line 833 "lexer.y" | |
| 2509 | 2514 | { yylval.integer = atoi(yytext); return yy__integer; } |
| 2510 | 2515 | YY_BREAK |
| 2511 | 2516 | case 148: |
| 2512 | 2517 | YY_RULE_SETUP |
| 2513 | -#line 829 "lexer.y" | |
| 2518 | +#line 834 "lexer.y" | |
| 2514 | 2519 | { yylval.expr = new_string(yytext); return yy__float; } |
| 2515 | 2520 | YY_BREAK |
| 2516 | 2521 | case 149: |
| 2517 | 2522 | YY_RULE_SETUP |
| 2518 | -#line 830 "lexer.y" | |
| 2523 | +#line 835 "lexer.y" | |
| 2519 | 2524 | { yylval.expr = new_utvar(yytext+1); return yy__utvar; } |
| 2520 | 2525 | YY_BREAK |
| 2521 | 2526 | case 150: |
| 2522 | 2527 | YY_RULE_SETUP |
| 2523 | -#line 831 "lexer.y" | |
| 2528 | +#line 836 "lexer.y" | |
| 2524 | 2529 | { yylval.expr = new_string(yytext); return yy__Symbol; } |
| 2525 | 2530 | YY_BREAK |
| 2526 | 2531 | case 151: |
| 2527 | 2532 | YY_RULE_SETUP |
| 2528 | -#line 832 "lexer.y" | |
| 2533 | +#line 837 "lexer.y" | |
| 2529 | 2534 | { yylval.expr = new_string(yytext); return yy__symbol; } |
| 2530 | 2535 | YY_BREAK |
| 2531 | 2536 | case 152: |
| 2532 | 2537 | YY_RULE_SETUP |
| 2533 | -#line 833 "lexer.y" | |
| 2538 | +#line 838 "lexer.y" | |
| 2534 | 2539 | { yylval.expr = new_string(rec_name(yytext,4)); |
| 2535 | 2540 | return yy__rec_mapsto; } |
| 2536 | 2541 | YY_BREAK |
| 2537 | 2542 | case 153: |
| 2538 | 2543 | YY_RULE_SETUP |
| 2539 | -#line 835 "lexer.y" | |
| 2544 | +#line 840 "lexer.y" | |
| 2540 | 2545 | { yylval.expr = new_string(rec_name(yytext,5)); |
| 2541 | 2546 | return yy__rec_mapstoo; } |
| 2542 | 2547 | YY_BREAK |
| 2543 | 2548 | case 154: |
| 2544 | 2549 | YY_RULE_SETUP |
| 2545 | -#line 837 "lexer.y" | |
| 2550 | +#line 842 "lexer.y" | |
| 2546 | 2551 | { if (reading_predef) |
| 2547 | 2552 | { yylval.expr = new_string(yytext); return yy__Symbol; } |
| 2548 | 2553 | else lexical_error(); |
| ... | ... | @@ -2550,7 +2555,7 @@ YY_RULE_SETUP |
| 2550 | 2555 | YY_BREAK |
| 2551 | 2556 | case 155: |
| 2552 | 2557 | YY_RULE_SETUP |
| 2553 | -#line 841 "lexer.y" | |
| 2558 | +#line 846 "lexer.y" | |
| 2554 | 2559 | { if (reading_predef) |
| 2555 | 2560 | { yylval.expr = new_string(yytext); return yy__symbol; } |
| 2556 | 2561 | else lexical_error(); |
| ... | ... | @@ -2558,7 +2563,7 @@ YY_RULE_SETUP |
| 2558 | 2563 | YY_BREAK |
| 2559 | 2564 | case 156: |
| 2560 | 2565 | YY_RULE_SETUP |
| 2561 | -#line 845 "lexer.y" | |
| 2566 | +#line 850 "lexer.y" | |
| 2562 | 2567 | { if (reading_predef) |
| 2563 | 2568 | { yylval.expr = new_string(yytext); return yy__symbol; } |
| 2564 | 2569 | else lexical_error(); |
| ... | ... | @@ -2566,35 +2571,35 @@ YY_RULE_SETUP |
| 2566 | 2571 | YY_BREAK |
| 2567 | 2572 | case 157: |
| 2568 | 2573 | YY_RULE_SETUP |
| 2569 | -#line 849 "lexer.y" | |
| 2574 | +#line 854 "lexer.y" | |
| 2570 | 2575 | { } |
| 2571 | 2576 | YY_BREAK |
| 2572 | 2577 | case 158: |
| 2573 | 2578 | YY_RULE_SETUP |
| 2574 | -#line 850 "lexer.y" | |
| 2579 | +#line 855 "lexer.y" | |
| 2575 | 2580 | { } |
| 2576 | 2581 | YY_BREAK |
| 2577 | 2582 | case 159: |
| 2578 | 2583 | YY_RULE_SETUP |
| 2579 | -#line 851 "lexer.y" | |
| 2584 | +#line 856 "lexer.y" | |
| 2580 | 2585 | { lexical_error(); } |
| 2581 | 2586 | YY_BREAK |
| 2582 | 2587 | case 160: |
| 2583 | 2588 | YY_RULE_SETUP |
| 2584 | -#line 852 "lexer.y" | |
| 2589 | +#line 857 "lexer.y" | |
| 2585 | 2590 | { if (gindex) store_external_comment('\n'); } |
| 2586 | 2591 | YY_BREAK |
| 2587 | 2592 | case 161: |
| 2588 | 2593 | YY_RULE_SETUP |
| 2589 | -#line 853 "lexer.y" | |
| 2594 | +#line 858 "lexer.y" | |
| 2590 | 2595 | { if (gindex) store_external_comment(yytext[0]); } |
| 2591 | 2596 | YY_BREAK |
| 2592 | 2597 | case 162: |
| 2593 | 2598 | YY_RULE_SETUP |
| 2594 | -#line 854 "lexer.y" | |
| 2599 | +#line 859 "lexer.y" | |
| 2595 | 2600 | ECHO; |
| 2596 | 2601 | YY_BREAK |
| 2597 | -#line 2598 "lex.yy.c" | |
| 2602 | +#line 2603 "lex.yy.c" | |
| 2598 | 2603 | |
| 2599 | 2604 | case YY_END_OF_BUFFER: |
| 2600 | 2605 | { |
| ... | ... | @@ -3484,7 +3489,7 @@ int main() |
| 3484 | 3489 | return 0; |
| 3485 | 3490 | } |
| 3486 | 3491 | #endif |
| 3487 | -#line 854 "lexer.y" | |
| 3492 | +#line 859 "lexer.y" | |
| 3488 | 3493 | |
| 3489 | 3494 | |
| 3490 | 3495 | ... | ... |
anubis_dev/compiler/src/lexer.y
| ... | ... | @@ -137,6 +137,7 @@ char *path_prefix(char *name) |
| 137 | 137 | int i = strlen(name); |
| 138 | 138 | if (i >= path_prefix_length-5) |
| 139 | 139 | { |
| 140 | + err_line_col(linecol()); | |
| 140 | 141 | fprintf(errfile, |
| 141 | 142 | msgtext_file_path_too_long[language], |
| 142 | 143 | name); |
| ... | ... | @@ -194,6 +195,7 @@ FILE *fopensrc(char *name) |
| 194 | 195 | /* if path is absolute do not try the libraries */ |
| 195 | 196 | if (name[0] == '/' || name[0] == '\\') |
| 196 | 197 | { |
| 198 | + err_line_col(linecol()); | |
| 197 | 199 | fprintf(errfile, |
| 198 | 200 | msgtext_cannot_find_src_file[language], |
| 199 | 201 | name, |
| ... | ... | @@ -232,6 +234,7 @@ FILE *fopensrc(char *name) |
| 232 | 234 | } |
| 233 | 235 | |
| 234 | 236 | /* The file is not found: send a message and exit */ |
| 237 | + err_line_col(linecol()); | |
| 235 | 238 | fprintf(errfile, |
| 236 | 239 | msgtext_cannot_find_src_file[language], |
| 237 | 240 | name, |
| ... | ... | @@ -338,6 +341,7 @@ void add_to_already_included(char *name) |
| 338 | 341 | //printf("Adding '%s'.\n",name); |
| 339 | 342 | if (next_already_included == max_already_included) |
| 340 | 343 | { |
| 344 | + err_line_col(linecol()); | |
| 341 | 345 | fprintf(errfile, |
| 342 | 346 | msgtext_too_many_files[language]); |
| 343 | 347 | anb_exit(1); |
| ... | ... | @@ -762,6 +766,7 @@ static char *rec_name(char *s, int del) |
| 762 | 766 | else |
| 763 | 767 | { if (include_stack_ptr >= max_include) |
| 764 | 768 | { |
| 769 | + err_line_col(linecol()); | |
| 765 | 770 | fprintf(errfile, |
| 766 | 771 | msgtext_include_too_deeply[language], |
| 767 | 772 | max_include); | ... | ... |
anubis_dev/compiler/src/predef.aux
| ... | ... | @@ -4117,10 +4117,12 @@ nil), |
| 4117 | 4117 | cons(cons(cons(type_struct_ptr, |
| 4118 | 4118 | new_integer(3)), |
| 4119 | 4119 | new_string("handle")), |
| 4120 | -nil), | |
| 4120 | +cons(cons(type_Int32, | |
| 4121 | +new_string("max")), | |
| 4122 | +nil)), | |
| 4121 | 4123 | no_term); |
| 4122 | 4124 | |
| 4123 | -new_op_scheme(18832910,0, | |
| 4125 | +new_op_scheme(18833934,0, | |
| 4124 | 4126 | new_string("Bool"), |
| 4125 | 4127 | cons(new_string("£default_host_window_handling"), |
| 4126 | 4128 | nil), |
| ... | ... | @@ -4163,7 +4165,7 @@ new_string("event_handler")), |
| 4163 | 4165 | nil))))), |
| 4164 | 4166 | no_term); |
| 4165 | 4167 | |
| 4166 | -new_op_scheme(18839566,0, | |
| 4168 | +new_op_scheme(18840590,0, | |
| 4167 | 4169 | new_string("One"), |
| 4168 | 4170 | cons(new_string("£begin_paint"), |
| 4169 | 4171 | nil), |
| ... | ... | @@ -4172,7 +4174,7 @@ new_string("window")), |
| 4172 | 4174 | nil), |
| 4173 | 4175 | no_term); |
| 4174 | 4176 | |
| 4175 | -new_op_scheme(18843150,0, | |
| 4177 | +new_op_scheme(18844174,0, | |
| 4176 | 4178 | new_string("One"), |
| 4177 | 4179 | cons(new_string("£end_paint"), |
| 4178 | 4180 | nil), |
| ... | ... | @@ -4181,7 +4183,7 @@ new_string("window")), |
| 4181 | 4183 | nil), |
| 4182 | 4184 | no_term); |
| 4183 | 4185 | |
| 4184 | -new_op_scheme(18847246,0, | |
| 4186 | +new_op_scheme(18848270,0, | |
| 4185 | 4187 | new_string("Bool"), |
| 4186 | 4188 | cons(new_string("£handle_host_window_events"), |
| 4187 | 4189 | nil), |
| ... | ... | @@ -4219,7 +4221,7 @@ new_string("eh")), |
| 4219 | 4221 | nil)))), |
| 4220 | 4222 | no_term); |
| 4221 | 4223 | |
| 4222 | -new_op_scheme(18864142,0, | |
| 4224 | +new_op_scheme(18865166,0, | |
| 4223 | 4225 | new_string("Bool"), |
| 4224 | 4226 | cons(new_string("£default_host_window_handling"), |
| 4225 | 4227 | nil), |
| ... | ... | @@ -4262,7 +4264,7 @@ new_string("event_handler")), |
| 4262 | 4264 | nil))))), |
| 4263 | 4265 | no_term); |
| 4264 | 4266 | |
| 4265 | -new_op_scheme(18875420,1, | |
| 4267 | +new_op_scheme(18876444,1, | |
| 4266 | 4268 | new_string("One"), |
| 4267 | 4269 | cons(new_string("generic_host_window_handler"), |
| 4268 | 4270 | nil), |
| ... | ... | @@ -4320,7 +4322,7 @@ nil), |
| 4320 | 4322 | nil), |
| 4321 | 4323 | nil)),0,1); |
| 4322 | 4324 | |
| 4323 | -new_op_scheme(18890766,0, | |
| 4325 | +new_op_scheme(18891790,0, | |
| 4324 | 4326 | cons(app_ts, |
| 4325 | 4327 | cons(new_string("Maybe"), |
| 4326 | 4328 | cons(cons(app_ts, |
| ... | ... | @@ -4348,7 +4350,7 @@ new_string("sort")), |
| 4348 | 4350 | nil)))))), |
| 4349 | 4351 | no_term); |
| 4350 | 4352 | |
| 4351 | -new_op_scheme(18898972,1, | |
| 4353 | +new_op_scheme(18899996,1, | |
| 4352 | 4354 | cons(app_ts, |
| 4353 | 4355 | cons(new_string("Maybe"), |
| 4354 | 4356 | cons(new_string("HostWindow"), |
| ... | ... | @@ -4402,7 +4404,7 @@ new_string("compress")), |
| 4402 | 4404 | nil)))))), |
| 4403 | 4405 | no_term); |
| 4404 | 4406 | |
| 4405 | -new_op_scheme(18915356,1, | |
| 4407 | +new_op_scheme(18916380,1, | |
| 4406 | 4408 | new_string("One"), |
| 4407 | 4409 | cons(new_string("show"), |
| 4408 | 4410 | nil), |
| ... | ... | @@ -4411,7 +4413,7 @@ new_string("win")), |
| 4411 | 4413 | nil), |
| 4412 | 4414 | no_term); |
| 4413 | 4415 | |
| 4414 | -new_op_scheme(18919452,1, | |
| 4416 | +new_op_scheme(18920476,1, | |
| 4415 | 4417 | new_string("One"), |
| 4416 | 4418 | cons(new_string("hide"), |
| 4417 | 4419 | nil), |
| ... | ... | @@ -4420,7 +4422,7 @@ new_string("win")), |
| 4420 | 4422 | nil), |
| 4421 | 4423 | no_term); |
| 4422 | 4424 | |
| 4423 | -new_op_scheme(18929180,1, | |
| 4425 | +new_op_scheme(18930204,1, | |
| 4424 | 4426 | new_string("Bool"), |
| 4425 | 4427 | cons(new_string("queue_event"), |
| 4426 | 4428 | nil), |
| ... | ... | @@ -4434,7 +4436,7 @@ new_string("e")), |
| 4434 | 4436 | nil)), |
| 4435 | 4437 | no_term); |
| 4436 | 4438 | |
| 4437 | -new_op_scheme(18939420,1, | |
| 4439 | +new_op_scheme(18940444,1, | |
| 4438 | 4440 | new_string("One"), |
| 4439 | 4441 | cons(new_string("paint_rectangle"), |
| 4440 | 4442 | nil), |
| ... | ... | @@ -4447,7 +4449,7 @@ new_string("color")), |
| 4447 | 4449 | nil))), |
| 4448 | 4450 | no_term); |
| 4449 | 4451 | |
| 4450 | -new_op_scheme(18945052,1, | |
| 4452 | +new_op_scheme(18946076,1, | |
| 4451 | 4453 | new_string("One"), |
| 4452 | 4454 | cons(new_string("paint_rectangle"), |
| 4453 | 4455 | nil), |
| ... | ... | @@ -4460,7 +4462,7 @@ new_string("color")), |
| 4460 | 4462 | nil))), |
| 4461 | 4463 | no_term); |
| 4462 | 4464 | |
| 4463 | -new_op_scheme(18962460,1, | |
| 4465 | +new_op_scheme(18963484,1, | |
| 4464 | 4466 | new_string("One"), |
| 4465 | 4467 | cons(new_string("paint_image"), |
| 4466 | 4468 | nil), |
| ... | ... | @@ -4477,7 +4479,7 @@ new_string("image")), |
| 4477 | 4479 | nil))))), |
| 4478 | 4480 | no_term); |
| 4479 | 4481 | |
| 4480 | -new_op_scheme(18969116,1, | |
| 4482 | +new_op_scheme(18970140,1, | |
| 4481 | 4483 | new_string("One"), |
| 4482 | 4484 | cons(new_string("paint_image"), |
| 4483 | 4485 | nil), |
| ... | ... | @@ -4494,7 +4496,7 @@ new_string("image")), |
| 4494 | 4496 | nil))))), |
| 4495 | 4497 | no_term); |
| 4496 | 4498 | |
| 4497 | -new_op_scheme(18975260,1, | |
| 4499 | +new_op_scheme(18976284,1, | |
| 4498 | 4500 | new_string("One"), |
| 4499 | 4501 | cons(new_string("map_to_host_window"), |
| 4500 | 4502 | nil), | ... | ... |
anubis_dev/compiler/src/show.c
| ... | ... | @@ -822,9 +822,10 @@ void show_symbol_ambiguity(FILE *fp, |
| 822 | 822 | |
| 823 | 823 | case operation: /* (operation <lc> <opid> <name> <parms> <type> . <types>) */ |
| 824 | 824 | opid = integer_value(third(car(interp))); |
| 825 | + show_type(fp,type_from_interpretation(car(interp),cdr(interp)),cdr(interp)); | |
| 825 | 826 | sprintf(buf,msgtext_file_line[language],string_content(operations[opid].file_name), |
| 826 | 827 | integer_value(operations[opid].line)); |
| 827 | - fprintf(fp,"%s (%s)\n",string_content(forth(car(interp))),buf); | |
| 828 | + fprintf(fp," %s (%s)\n",string_content(forth(car(interp))),buf); | |
| 828 | 829 | break; |
| 829 | 830 | |
| 830 | 831 | default: internal_error("not a symbol interpretation",interp); | ... | ... |
anubis_dev/library/examples/paint.anubis
| ... | ... | @@ -63,7 +63,7 @@ define (HostWindow hw, HostWindowEvent(One) e) -> List(Rectangle) |
| 63 | 63 | pointer_entering then [], |
| 64 | 64 | pointer_leaving then [], |
| 65 | 65 | key_down(ks,kk) then [], |
| 66 | - mouse_move(ks,x,y) then with r = rect(x,y,x+1,y+1), | |
| 66 | + mouse_move(ks,x,y) then with r = rect(x,y,x+4,y+2), | |
| 67 | 67 | (if mouse_left(ks) |
| 68 | 68 | then paint_rectangle(buffer,r,rgb(255,255,0)) |
| 69 | 69 | else unique); |
| ... | ... | @@ -77,7 +77,7 @@ define (HostWindow hw, HostWindowEvent(One) e) -> List(Rectangle) |
| 77 | 77 | |
| 78 | 78 | |
| 79 | 79 | Finally, here is our program. It first creates the buffer, then opens the host |
| 80 | - window. If the host windows has been opened, it must be shown by 'show', otherwise it | |
| 80 | + window. If the host window has been opened, it must be shown by 'show', otherwise it | |
| 81 | 81 | remains invisible. |
| 82 | 82 | |
| 83 | 83 | global define One | ... | ... |
anubis_dev/library/examples/runge_kutta.anubis
| ... | ... | @@ -34,20 +34,29 @@ |
| 34 | 34 | |
| 35 | 35 | read tools/maybefloat.anubis |
| 36 | 36 | |
| 37 | +define Maybe(Float) _1 = success(1). | |
| 38 | +define Maybe(Float) _2 = success(2). | |
| 39 | +define Maybe(Float) _3 = success(3). | |
| 40 | + | |
| 37 | 41 | define Maybe(Float) |
| 38 | 42 | f |
| 39 | 43 | ( |
| 40 | 44 | Maybe(Float) x, |
| 41 | 45 | Maybe(Float) y |
| 42 | - ) = | |
| 46 | + ) = | |
| 47 | + abs(x)^y. | |
| 48 | + x+y*y*y. | |
| 49 | + x*x + y. | |
| 50 | + x*x - y*y. | |
| 43 | 51 | x - y*y. |
| 44 | - success(1)/y. | |
| 52 | + x - y*x*y. | |
| 53 | + _3 * ((y*y)^(_1/_3)). | |
| 45 | 54 | sin(x*y). |
| 46 | - success(3)* ((y*y)^(success(1)/success(3))). | |
| 47 | - | |
| 55 | + success(1)/y. | |
| 48 | 56 | sin(y). |
| 49 | 57 | |
| 50 | 58 | |
| 59 | + | |
| 51 | 60 | |
| 52 | 61 | The Runge-Kutta method allows the computation of points on the graph of a solution |
| 53 | 62 | starting at some point of this graph. Starting at a point (x_0,y_0) in the domain of | ... | ... |
anubis_dev/library/network/dns.anubis
| ... | ... | @@ -284,6 +284,9 @@ global define One |
| 284 | 284 | *** The command line tool. |
| 285 | 285 | |
| 286 | 286 | --------------------------------------------------------------------------------------- |
| 287 | + | |
| 288 | +read tools/basis.anubis | |
| 289 | +read tools/connections.anubis | |
| 287 | 290 | |
| 288 | 291 | //define One debogge(String s) = print(s). |
| 289 | 292 | define One debogge(String s) = unique. | ... | ... |
anubis_dev/library/predefined.anubis
| ... | ... | @@ -3999,11 +3999,13 @@ define HostWindowEvent($E) |
| 3999 | 3999 | define List(HostWindowEvent($E)) |
| 4000 | 4000 | £get_host_window_events |
| 4001 | 4001 | ( |
| 4002 | - £StructPtr(HostWindow) handle | |
| 4002 | + £StructPtr(HostWindow) handle, | |
| 4003 | + Int32 max // maximal number of events to get | |
| 4003 | 4004 | ) = |
| 4005 | + if max =< 0 then [] else | |
| 4004 | 4006 | if £window_event_pending(handle) |
| 4005 | 4007 | then with first = £get_host_window_event(handle), |
| 4006 | - others = £get_host_window_events(handle), | |
| 4008 | + others = £get_host_window_events(handle,max-1), | |
| 4007 | 4009 | [first . others] |
| 4008 | 4010 | else [ ]. |
| 4009 | 4011 | |
| ... | ... | @@ -4103,7 +4105,7 @@ public define One |
| 4103 | 4105 | (HostWindow,HostWindowEvent($E)) -> List(Rectangle) event_handler, |
| 4104 | 4106 | List(HostWindowEvent($E)) -> List(HostWindowEvent($E)) compress |
| 4105 | 4107 | ) = |
| 4106 | - if £handle_host_window_events(compress(£get_host_window_events(£handle(window))), | |
| 4108 | + if £handle_host_window_events(compress(£get_host_window_events(£handle(window),200)), | |
| 4107 | 4109 | window,paint_method,event_handler) |
| 4108 | 4110 | then unique |
| 4109 | 4111 | else wait_for_event; | ... | ... |
anubis_dev/library/tools/sdbms.anubis
| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | |
| 10 | 10 | Author: Alain Prouté |
| 11 | 11 | |
| 12 | - Last revision: November 2005. | |
| 12 | + Last revision: January 2005. | |
| 13 | 13 | |
| 14 | 14 | |
| 15 | 15 | |
| ... | ... | @@ -17,27 +17,17 @@ |
| 17 | 17 | ----------------------------------- Contents ------------------------------------------ |
| 18 | 18 | |
| 19 | 19 | *** (1) Overview. |
| 20 | - *** (2) Data base and table structure. | |
| 21 | - *** (2.1) Tables. | |
| 22 | - *** (2.2) Data bases. | |
| 23 | - *** (2.3) Initializing a data base and its tables. | |
| 24 | - *** (2.4) Handling changes in table formats. | |
| 25 | - *** (2.5) Row identifiers. | |
| 26 | - *** (3) Using the data base. | |
| 27 | - *** (3.1) Errors. | |
| 28 | - *** (3.2) Adding rows to a table. | |
| 29 | - *** (3.3) Getting rows from a table. | |
| 30 | - *** (3.4) Testing a number of rows. | |
| 31 | - *** (3.5) Updating rows in a table. | |
| 32 | - *** (3.6) Deleting rows from a table. | |
| 33 | - *** (3.7) Multi-tables queries. | |
| 34 | - *** (4) Indexing. | |
| 35 | - *** (4.1) Principles of indexing. | |
| 36 | - *** (4.2) Main indexing. | |
| 37 | - *** (4.3) Families of tables. | |
| 38 | - *** (4.4) Secondary indexing. | |
| 39 | - *** (4.5) Handling changes of your indexing methods. | |
| 40 | - *** (5) Using it with 'web/making_a_web_site.anubis'. | |
| 20 | + *** (2) Errors. | |
| 21 | + *** (3) Tables and data bases. | |
| 22 | + *** (4) Managing changes in table formats. | |
| 23 | + *** (5) Row identifiers. | |
| 24 | + *** (6) Adding rows to a table. | |
| 25 | + *** (7) Getting rows from a table. | |
| 26 | + *** (8) Testing a number of rows. | |
| 27 | + *** (9) Updating rows in a table. | |
| 28 | + *** (10) Deleting rows from a table. | |
| 29 | + *** (11) Multi-tables queries. | |
| 30 | + *** (12) Using it with 'web/making_a_web_site.anubis'. | |
| 41 | 31 | |
| 42 | 32 | --------------------------------------------------------------------------------------- |
| 43 | 33 | |
| ... | ... | @@ -53,8 +43,8 @@ |
| 53 | 43 | |
| 54 | 44 | - restructuring commands, like adding columns in a table, deleting columns, etc... |
| 55 | 45 | |
| 56 | - Normally, if a data base is restructured, programs using that database must themself be | |
| 57 | - restructured, while the transformation of the data base by utilization commands does | |
| 46 | + Normally, if a data base is restructured, programs using that database must themselves | |
| 47 | + be restructured, while the transformation of the data base by utilization commands does | |
| 58 | 48 | not require any modification of the programs which are using the data base. |
| 59 | 49 | |
| 60 | 50 | Our aim is to provide a data base mecanism, which is as much as possible in the spirit |
| ... | ... | @@ -73,39 +63,48 @@ |
| 73 | 63 | because it puts de facto at different levels aspects of data base management which are |
| 74 | 64 | otherwise consider of the same kind. |
| 75 | 65 | |
| 76 | - | |
| 77 | 66 | |
| 78 | 67 | |
| 79 | - *** (2) Data base and table structure. | |
| 68 | + | |
| 69 | + *** (2) Errors. | |
| 70 | + | |
| 71 | + Errors may occur during the normal management of the data base. | |
| 72 | + | |
| 73 | +public type DBError: | |
| 74 | + file_not_found (String path), | |
| 75 | + file_reading_problem (String path), | |
| 76 | + file_type_problem (String path), | |
| 77 | + cannot_open_file (String path), | |
| 78 | + cannot_write_file (String path), | |
| 79 | + record_not_found. | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 80 | 84 | |
| 81 | 85 | |
| 82 | - *** (2.1) Tables. | |
| 86 | + *** (3) Tables and data bases. | |
| 83 | 87 | |
| 84 | 88 | The type of the rows of a table is up to you (but must be serializable). However, this |
| 85 | 89 | data base management system includes a mecanism for handling the possible changes in |
| 86 | 90 | the definition of the types of the rows of a table, in such a way that updating the |
| 87 | 91 | actual tables files on the disk is automatic. For this reason, the type scheme |
| 88 | - 'DBTable($Row,$HRow)' representing tables has two type parameters. The first one | |
| 89 | - represents the current type of the rows of the table, the second one represents the | |
| 90 | - history of all successive types of the rows of the table. With this mecanism, and if | |
| 91 | - you repects some principles explained below, your program will always be able to read | |
| 92 | - old tables saved in old formats. When tables are written to disk, they are always | |
| 93 | - written in the most recent format. | |
| 94 | - | |
| 95 | - So, tables are represented by the following opaque type scheme, where the parameter | |
| 96 | - '$Row' is the current type of the rows of the table, and '$HRow' ('H' like 'History') | |
| 97 | - is a type containing the history of all successive formats of rows in the table: | |
| 92 | + 'DBTable' representing tables has two type parameters. The first one represents the | |
| 93 | + current type of the rows of the table, the second one represents the history of all | |
| 94 | + successive types of the rows of the table. With this mecanism, and if you repects some | |
| 95 | + principles explained below, your program will always be able to read old tables saved | |
| 96 | + in old formats. | |
| 97 | + | |
| 98 | + Tables are represented by the following opaque type scheme, where the parameter '$Row' | |
| 99 | + is the current type of the rows of the table, and '$HRow' ('H' like 'History') is a | |
| 100 | + type containing the history of all the successive formats of rows in the table: | |
| 98 | 101 | |
| 99 | 102 | public type DBTable($Row,$HRow):... |
| 100 | 103 | |
| 101 | - | |
| 102 | - | |
| 103 | - *** (2.2) Data bases. | |
| 104 | - | |
| 105 | 104 | The first thing you have to do if you want to use this data base management system, is |
| 106 | - to define the type of your data base (you may have several of them). Since a data base | |
| 107 | - is essentially a set of tables, the type of your data base should be something like | |
| 108 | - this (at the beginning, you can use the same type for '$Row' and '$HRow'): | |
| 105 | + to define the type of your data base. Since a data base is essentially a set of | |
| 106 | + tables, the type of your data base should be something like this (at the beginning, you | |
| 107 | + can use the same type for '$Row' and '$HRow'): | |
| 109 | 108 | |
| 110 | 109 | type MY_DB: |
| 111 | 110 | my_db(DBTable(Client,Client) clients, |
| ... | ... | @@ -128,12 +127,7 @@ public type DBTable($Row,$HRow):... |
| 128 | 127 | public type DB($MY_DB):... (again an opaque type scheme) |
| 129 | 128 | |
| 130 | 129 | where the parameter '$MY_DB' may be instantiated to your type 'MY_DB'. Several |
| 131 | - instantiations allow the creation of several data bases (in general of different | |
| 132 | - types). | |
| 133 | - | |
| 134 | - | |
| 135 | - | |
| 136 | - *** (2.3) Initializing a data base and its tables. | |
| 130 | + instantiations allow the creation of several data bases. | |
| 137 | 131 | |
| 138 | 132 | Now, when you start your program (may be a web site), you need to start the data base |
| 139 | 133 | manager. This amounts to initialize each table, and use the initialized tables to |
| ... | ... | @@ -145,7 +139,7 @@ public type DB($MY_DB):... (again an opaque type scheme) |
| 145 | 139 | init_dbtable ("suppliers", compare, identity, identity), |
| 146 | 140 | ...)), |
| 147 | 141 | |
| 148 | - where 'init_db' is: | |
| 142 | + where 'init_db' is declared as: | |
| 149 | 143 | |
| 150 | 144 | public define DB($MY_DB) |
| 151 | 145 | init_db |
| ... | ... | @@ -154,7 +148,7 @@ public define DB($MY_DB) |
| 154 | 148 | $MY_DB tables |
| 155 | 149 | ). |
| 156 | 150 | |
| 157 | - and where 'init_dbtable' is: | |
| 151 | + and where 'init_dbtable' is declared as: | |
| 158 | 152 | |
| 159 | 153 | public define DBTable($Row,$HRow) |
| 160 | 154 | init_dbtable |
| ... | ... | @@ -167,9 +161,9 @@ public define DBTable($Row,$HRow) |
| 167 | 161 | |
| 168 | 162 | Notice that the name 'table_name' above becomes part of the names of the files |
| 169 | 163 | containing the tables (located in the directory 'data_base_directory' above). |
| 170 | - 'init_dbtable' does not load the table from the disk. A table is loaded only when | |
| 164 | + 'init_table' does not load the table from the disk. A table is loaded only when | |
| 171 | 165 | needed. If the table does not exist on the disk, 'init_table' creates an empty table |
| 172 | - of the right type. 'init_dbtable' should be executed only once per table, when your | |
| 166 | + of the right type. 'init_table' should be executed only once per table, when your | |
| 173 | 167 | program starts. |
| 174 | 168 | |
| 175 | 169 | The 'compare' function is used for sorting the rows of the table. The table is sorted |
| ... | ... | @@ -182,7 +176,7 @@ public define DBTable($Row,$HRow) |
| 182 | 176 | ordering the table. You can always reorder the result of 'get_rows' for any purpose. |
| 183 | 177 | |
| 184 | 178 | The 'update' and 'store' functions are used for automating the changes of format of the |
| 185 | - tables. This is explained below in the section 'Handling changes in table formats'. At | |
| 179 | + tables. This is explained below in the section 'Managing changes in table formats'. At | |
| 186 | 180 | the beginning, while the two types '$Row' and '$HRow' are identical, you can use the |
| 187 | 181 | function 'identity' (actually a scheme of function, defined in 'tools/basis.anubis') |
| 188 | 182 | for both 'update' and 'store'. |
| ... | ... | @@ -194,39 +188,11 @@ public define DBTable($Row,$HRow) |
| 194 | 188 | dynamically typed) data base system. Of course, you can use several such data bases in |
| 195 | 189 | a program. |
| 196 | 190 | |
| 197 | - For security reasons, you may want to protect some informations in a table so that this | |
| 198 | - information cannot be modified. For example, in a 'products' table the reference of the | |
| 199 | - product should perhaps not be modified. In order to ensure this, you just have to | |
| 200 | - provide one more argument to 'init_dbtable': | |
| 201 | - | |
| 202 | -public define DBTable($Row,$HRow) | |
| 203 | - init_dbtable | |
| 204 | - ( | |
| 205 | - String table_name, | |
| 206 | - ($Row,$Row) -> Bool compare, | |
| 207 | - $HRow -> $Row update, | |
| 208 | - $Row -> $HRow store, | |
| 209 | - $Row -> $L locked | |
| 210 | - ). | |
| 211 | 191 | |
| 212 | - The new argument 'locked' is of type '$Row -> $L' where $L is any serializable | |
| 213 | - type. When the system is on the point to update a row in a table it first checks if | |
| 214 | - 'locked(r1) = locked(r2)', where 'r1' and 'r2' are the previous and new values of the | |
| 215 | - row. If this check fails the row is not updated. | |
| 216 | 192 | |
| 217 | - For example, for initializing your table of products, locking the two fields 'supplier' | |
| 218 | - and 'name', you just have to provide a function of type: | |
| 219 | 193 | |
| 220 | - Product -> (String,String) | |
| 221 | 194 | |
| 222 | - extracting the supplier name and product name from the row. | |
| 223 | - | |
| 224 | - | |
| 225 | - | |
| 226 | - | |
| 227 | - | |
| 228 | - | |
| 229 | - *** (2.4) Handling changes in table formats. | |
| 195 | + *** (4) Managing changes in table formats. | |
| 230 | 196 | |
| 231 | 197 | Up to here the types used as instantiations of '$Row' and '$HRow' are the same one. |
| 232 | 198 | That's OK, and you have begun to distribute your program and your users have created |
| ... | ... | @@ -275,7 +241,7 @@ public define DBTable($Row,$HRow) |
| 275 | 241 | String address), |
| 276 | 242 | version_2(String name, |
| 277 | 243 | String address, |
| 278 | - Int32 age). | |
| 244 | + Int32 age). | |
| 279 | 245 | |
| 280 | 246 | Important notice: When a change intervenes in the type of rows of the table, the |
| 281 | 247 | alternative representing the new type of rows must be added at the end of the type |
| ... | ... | @@ -319,7 +285,7 @@ public define DBTable($Row,$HRow) |
| 319 | 285 | Of course, in the case of a row in the old format (version_1), we need a default value |
| 320 | 286 | for the age. We have chosen 0 in the example, but you may choose anything. In any |
| 321 | 287 | traditional data base system, when you add a column to a table, you need to fill this |
| 322 | - column with a default value, even if this default value is 'NULL'. | |
| 288 | + column with a default value, even if this default value is 'NULL' (not filled at all). | |
| 323 | 289 | |
| 324 | 290 | The other function does not require default values in principle, because it is mainly a |
| 325 | 291 | conversion between the current version and the latest one (i.e. essentially the same |
| ... | ... | @@ -336,12 +302,12 @@ public define DBTable($Row,$HRow) |
| 336 | 302 | The type used for storing the data on the disk is always 'HClient' (hence the name of |
| 337 | 303 | the function 'store'), and according to the above function they are stored as |
| 338 | 304 | 'version_2(...)'. The type 'Client' is used only internally. This is required for |
| 339 | - being able to handle file containing different versions of the tables. | |
| 305 | + being able of handling file containing different versions of the tables. | |
| 340 | 306 | |
| 341 | 307 | |
| 342 | 308 | |
| 343 | 309 | |
| 344 | - *** (2.5) Row identifiers. | |
| 310 | + *** (5) Row identifiers. | |
| 345 | 311 | |
| 346 | 312 | The system generates an identifier for each newly created row in a table. It is |
| 347 | 313 | warranted that not two rows in the same table can have the same row identifier. Row |
| ... | ... | @@ -354,8 +320,8 @@ public type DBRowId($Row):... |
| 354 | 320 | between tables. |
| 355 | 321 | |
| 356 | 322 | The type scheme 'DBRowId' should be considered as absolutely opaque. The author |
| 357 | - reserves the possibility of modifying the definition this type in the future. Hence, | |
| 358 | - use only the public interface for manipulating data of this type. | |
| 323 | + reserves the possibility of modifying this type in the future. Hence, use only the | |
| 324 | + public interface for manipulating data of this type. | |
| 359 | 325 | |
| 360 | 326 | It would have been possible to define the type 'DBRowId' without the parameter, but in |
| 361 | 327 | this case, identifiers corresponding to tables of different types could not be |
| ... | ... | @@ -366,27 +332,8 @@ public type DBRowId($Row):... |
| 366 | 332 | |
| 367 | 333 | |
| 368 | 334 | |
| 369 | - | |
| 370 | - | |
| 371 | - | |
| 372 | - *** (3) Using the data base. | |
| 373 | - | |
| 374 | - *** (3.1) Errors. | |
| 375 | - | |
| 376 | - Errors may occur during the normal management of the data base. | |
| 377 | - | |
| 378 | -public type DBError: | |
| 379 | - file_not_found (String path), | |
| 380 | - file_reading_problem (String path), | |
| 381 | - file_type_problem (String path), | |
| 382 | - cannot_open_file (String path), | |
| 383 | - cannot_write_file (String path), | |
| 384 | - record_not_found. | |
| 385 | - | |
| 386 | - | |
| 387 | - | |
| 388 | 335 | |
| 389 | - *** (3.2) Adding rows to a table. | |
| 336 | + *** (6) Adding rows to a table. | |
| 390 | 337 | |
| 391 | 338 | Adding rows to a table is performed by the following function: |
| 392 | 339 | |
| ... | ... | @@ -398,9 +345,6 @@ public define Result(DBError,List(DBRowId($Row))) |
| 398 | 345 | List($Row) new_rows |
| 399 | 346 | ). |
| 400 | 347 | |
| 401 | - Notice that the argument 'the_table' above is supposed to be an implicit destructor of | |
| 402 | - the type which instantiates '$MY_DB'. This is why it is a function. | |
| 403 | - | |
| 404 | 348 | For example, you may write: |
| 405 | 349 | |
| 406 | 350 | add_rows(my_data_base,clients,[row1,row2,row3]) |
| ... | ... | @@ -421,19 +365,19 @@ public define Result(DBError,DBRowId($Row)) |
| 421 | 365 | |
| 422 | 366 | |
| 423 | 367 | |
| 424 | - *** (3.3) Getting rows from a table. | |
| 368 | + *** (7) Getting rows from a table. | |
| 425 | 369 | |
| 426 | 370 | In order to get rows from a table, you have two methods: |
| 427 | 371 | |
| 428 | 372 | (1) you know the row identifiers of the rows you want, |
| 429 | - (2) you want to get all the rows satisfying some condition. | |
| 373 | + (2) you want to get all rows satisfying some condition. | |
| 430 | 374 | |
| 431 | 375 | You get rows in the form of: |
| 432 | 376 | |
| 433 | 377 | public type DBRow($Row): |
| 434 | 378 | dbrow(DBRowId($Row) row_id, |
| 435 | 379 | Int32 version, |
| 436 | - $Row row). | |
| 380 | + $Row row). | |
| 437 | 381 | |
| 438 | 382 | A datum of type DBRow($Row) contains the identifier of the row, a version number and |
| 439 | 383 | the row itself. The version number is 0 when the row is created (by 'add_row' or |
| ... | ... | @@ -448,9 +392,8 @@ public define Result(DBError,DBRow($Row)) |
| 448 | 392 | DBRowId($Row) row_id |
| 449 | 393 | ). |
| 450 | 394 | |
| 451 | - If no error occurs, the function returns the row whose row identifier is given. The | |
| 452 | - next one can be used for getting several rows by their row identifiers. With the | |
| 453 | - variant below you can get several rows in one operation. | |
| 395 | + If no error occurs, the function returns the wanted row. The next one can be used for | |
| 396 | + getting several rows. | |
| 454 | 397 | |
| 455 | 398 | public define Result(DBError,List(DBRow($Row))) |
| 456 | 399 | get_rows |
| ... | ... | @@ -460,9 +403,6 @@ public define Result(DBError,List(DBRow($Row))) |
| 460 | 403 | List(DBRowId($Row)) row_ids |
| 461 | 404 | ). |
| 462 | 405 | |
| 463 | - Now, if you prefer to use a condition instead of a list of row identifiers, use this | |
| 464 | - one: | |
| 465 | - | |
| 466 | 406 | public define Result(DBError,List(DBRow($Row))) |
| 467 | 407 | get_rows |
| 468 | 408 | ( |
| ... | ... | @@ -488,7 +428,7 @@ public define Result(DBError,List(DBRow($Row))) |
| 488 | 428 | |
| 489 | 429 | |
| 490 | 430 | |
| 491 | - *** (3.4) Testing a number of rows. | |
| 431 | + *** (8) Testing a number of rows. | |
| 492 | 432 | |
| 493 | 433 | It may be useful to get the number of rows satisfying some condition in a table. It may |
| 494 | 434 | also be useful to know if a table contains more rows satisfying a condition than a |
| ... | ... | @@ -524,7 +464,7 @@ public define Result(DBError,Bool) |
| 524 | 464 | |
| 525 | 465 | |
| 526 | 466 | |
| 527 | - *** (3.5) Updating rows in a table. | |
| 467 | + *** (9) Updating rows in a table. | |
| 528 | 468 | |
| 529 | 469 | Updating rows in a table is generally the consequence of a previous reading of these |
| 530 | 470 | rows. Indeed, interactive programs will first show the row to be updated to a human |
| ... | ... | @@ -595,7 +535,7 @@ public define Result(DBError,List(DBUpdateResult($Row))) |
| 595 | 535 | |
| 596 | 536 | |
| 597 | 537 | |
| 598 | - *** (3.6) Deleting rows from a table. | |
| 538 | + *** (10) Deleting rows from a table. | |
| 599 | 539 | |
| 600 | 540 | public define Result(DBError,$Row) |
| 601 | 541 | delete_row |
| ... | ... | @@ -625,7 +565,7 @@ public define Result(DBError,List($Row)) |
| 625 | 565 | |
| 626 | 566 | |
| 627 | 567 | |
| 628 | - *** (3.7) Multi-tables queries. | |
| 568 | + *** (11) Multi-tables queries. | |
| 629 | 569 | |
| 630 | 570 | The SQL language has an important feature which is the 'SELECT' command. We need |
| 631 | 571 | something analogous to the SQL query: |
| ... | ... | @@ -656,7 +596,7 @@ public define Result(DBError,List($Row)) |
| 656 | 596 | (essentially the security provided by the strong typing mecanism), and the flexibility |
| 657 | 597 | of usual data bases could be realized only with a more elaborate version of Anubis, |
| 658 | 598 | including meta-programming, and maybe another virtual machine able to optimize on the |
| 659 | - fly. All these new features are part of the Anubis2 project. | |
| 599 | + fly. All these new features are part of the Anubis2/Paradize project. | |
| 660 | 600 | |
| 661 | 601 | For the time being, we content ourself with the following recursive querying |
| 662 | 602 | mecanism. Actually, the recursion is on the number of tables concerned by the query. |
| ... | ... | @@ -700,285 +640,68 @@ public define List($Out) |
| 700 | 640 | named "Yoyo". Here is the query (which returns a list of type 'List(String)'): |
| 701 | 641 | |
| 702 | 642 | query(my_data_base, |
| 703 | - clients, // begin with the table 'clients' | |
| 704 | - (DBRow(Client) clt) |-> country(row(clt)) = "France", // consider only French clients | |
| 705 | - (DBRow(Client) clt, One u) |-> name(row(clt)), // keep only the name of the client | |
| 706 | - (DBRow(Client) clt) |-> // the subquery for this client 'clt' | |
| 707 | - query(my_data_base, | |
| 708 | - commands, // continue with the table 'commands' | |
| 709 | - (DBRow(Command) cmd) |-> row_id(clt) = client_id(row(cmd)), | |
| 710 | - (DBRow(Command) cmd, One u) |-> u, // do not keep anything from 'commands' | |
| 711 | - (DBRow(Command) cmd) |-> | |
| 712 | - query(my_data_base, | |
| 713 | - products, | |
| 714 | - (DBRow(Product) prd) |-> row_id(prd) = product_id(cmd) & | |
| 715 | - name(row(prd)) = "Yoyo", | |
| 716 | - (DBRow(Product) prd, One u) |-> u, | |
| 717 | - (DBRow(Product) prd) |-> unique))) | |
| 718 | - | |
| 719 | - This is actually not more complicated than: | |
| 643 | + clients, // begin with the table 'clients' | |
| 644 | + (DBRow(Client) clt) |-> // consider only French clients | |
| 645 | + country(row(clt)) = "France", | |
| 646 | + (DBRow(Client) clt, One u) |-> // keep only the name of the client | |
| 647 | + name(row(clt)), | |
| 648 | + (DBRow(Client) clt) |-> // the subquery for this client 'clt' | |
| 649 | + query(my_data_base, | |
| 650 | + commands, // continue with the table 'commands' | |
| 651 | + (DBRow(Command) cmd) |-> | |
| 652 | + row_id(clt) = client_id(row(cmd)), | |
| 653 | + (DBRow(Command) cmd, One u) |-> u, // do not keep anything from 'commands' | |
| 654 | + (DBRow(Command) cmd) |-> | |
| 655 | + query(my_data_base, | |
| 656 | + products, | |
| 657 | + (DBRow(Product) prd) |-> | |
| 658 | + row_id(prd) = product_id(cmd) & | |
| 659 | + name(row(prd)) = "Yoyo", | |
| 660 | + (DBRow(Product) prd, One u) |-> u, | |
| 661 | + (DBRow(Product) prd) |-> unique))) | |
| 662 | + | |
| 663 | + Of course, this is more complicated than: | |
| 720 | 664 | |
| 721 | 665 | SELECT clients.name |
| 722 | 666 | FROM clients, commands_2005, products |
| 723 | 667 | WHERE clients.id = commands_2005.client_id AND |
| 724 | 668 | commands_2005.product_id = products.id AND |
| 725 | - products.name = "Yoyo" AND | |
| 726 | - client.country = "France" | |
| 669 | + products.name = "Yoyo" | |
| 727 | 670 | |
| 728 | - just a little heavier to write down, but meta-programming could automatically transform | |
| 729 | - the later into the former (in the future). | |
| 671 | + but meta-programming could automatically transform the later into the former (in the | |
| 672 | + future). | |
| 730 | 673 | |
| 731 | 674 | Now, the query may also be more efficient (computed faster) if the tables are put in a |
| 732 | - different order. | |
| 733 | - | |
| 734 | - | |
| 735 | - | |
| 736 | - | |
| 737 | - | |
| 738 | - | |
| 739 | - | |
| 740 | - | |
| 741 | - | |
| 742 | - *** (4) Indexing. | |
| 743 | - | |
| 744 | - In order to speed up the access to the data, especially when dealing with big tables, | |
| 745 | - and also to optimize memory usage, you may need an indexing system. | |
| 746 | - | |
| 747 | - | |
| 748 | - | |
| 749 | - *** (4.1) Principles of indexing. | |
| 750 | - | |
| 751 | - An index is some way of reaching rows of a table more quickly than by just having a | |
| 752 | - look at all rows until the wanted rows are found. This is similar to a dictionary. When | |
| 753 | - you are looking for a word in a dictionary, you don't start at the beginning and check | |
| 754 | - all words until you find yours. You have some more efficient process. | |
| 755 | - | |
| 756 | - Notice however that this process is specific to the method used for selecting items | |
| 757 | - from the dictionary. In this case, the items you want to find are selected 'by | |
| 758 | - name'. Since items in the dictionary are ordered by name, the search may be performed | |
| 759 | - quickly. However, what about finding all words, the definition of which contains the | |
| 760 | - word 'dog' ? This is much more difficult, and requires a priori a complete search item | |
| 761 | - by item. | |
| 762 | - | |
| 763 | - In order to solve this problem, the dictionary could have an 'index' (in general it | |
| 764 | - does not have one), within which you should easily find the word 'dog', and get a list | |
| 765 | - of pages or item numbers or item names whose definition contains the word 'dog'. You | |
| 766 | - may also want to find all words of containing the string 'gap' in their name. In this | |
| 767 | - case, you need yet another kind of index. | |
| 768 | - | |
| 769 | - From this dictionary story, we should remember two things: | |
| 770 | - | |
| 771 | - 1. The dictionary is ordered in such a way that finding an item 'by name' is easy, | |
| 772 | - 2. If we want to find items according to other criteria, we need an extra index | |
| 773 | - (maybe one for each criterium). | |
| 774 | - | |
| 775 | - The way the dictionary is ordered could be called the 'main indexing'. Each extra | |
| 776 | - index may be calld a 'secondary indexing'. The same principles apply to data bases, | |
| 777 | - except that instead of ordering items by alphabetical order we use 'hashing methods'. | |
| 778 | - | |
| 779 | - | |
| 780 | - *** (4.2) Main indexing. | |
| 781 | - | |
| 782 | - Given a table in your data base, you may ignore indexing or decide some 'main' way of | |
| 783 | - indexing the table. We begin by an example. Consider the 'clients' table. Each client | |
| 784 | - has a name, and several other data attached to him. In general, when you are looking | |
| 785 | - for a client, you got the name of that client (alternatively you may have a 'client | |
| 786 | - number'). Hence searching a client is most often performed 'by name'. So, you may | |
| 787 | - decide that the main indexing of the 'clients' table should speed up the search 'by | |
| 788 | - name'. In that case the 'search criterion' will be represented by the function mapping | |
| 789 | - a row of the table to the 'name' field. This function may be for example the implicit | |
| 790 | - destructor 'name', which is of type: | |
| 791 | - | |
| 792 | - Client -> String | |
| 793 | - | |
| 794 | - In order to take this 'main indexing' into account, use the following variant of | |
| 795 | - 'init_dbtable', for initializing your table: | |
| 796 | - | |
| 797 | -public define DBTable($Row,$HRow) | |
| 798 | - init_dbtable | |
| 799 | - ( | |
| 800 | - String table_name, | |
| 801 | - ($Row,$Row) -> Bool compare, | |
| 802 | - $HRow -> $Row update, | |
| 803 | - $Row -> $HRow store, | |
| 804 | - $Row -> $L locked, | |
| 805 | - $Row -> $N main_search_criterion | |
| 806 | - ). | |
| 807 | - | |
| 808 | - Actually, you have a big freedom in choosing the type '$N'. The only constraint is that | |
| 809 | - it must be serializable. | |
| 810 | - | |
| 811 | - Now, when you want to get rows from that table using this main indexing, you have to | |
| 812 | - use variants 'get_rows'. Indeed, instead of giving row identifiers or search | |
| 813 | - criterions, you give a datum of type 'DBIndexVal($N)'. Notice that unlike the search by | |
| 814 | - row identifiers, the search by index may produce several rows for the same index | |
| 815 | - value. Hence, 'get_row' is not concerned by indexing. Only 'get_rows' (and similarly | |
| 816 | - 'update_rows' and 'delete_rows') is concerned. | |
| 817 | - | |
| 818 | - | |
| 819 | -public type DBIndexVal($Row,$N):... (an opaque type) | |
| 820 | - | |
| 821 | -public define Result(DBError,List(DBRow($Row))) | |
| 822 | - get_rows | |
| 823 | - ( | |
| 824 | - DB($MY_DB) the_data_base, | |
| 825 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 826 | - DBIndexVal($Row,$N) main_index_value | |
| 827 | - ). | |
| 828 | - | |
| 829 | - | |
| 830 | - The same principles apply to other utilization functions: | |
| 831 | - | |
| 832 | -public define Result(DBError,Int32) | |
| 833 | - get_number_of_rows | |
| 834 | - ( | |
| 835 | - DB($MY_DB) the_data_base, | |
| 836 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 837 | - DBIndexVal($Row,$N) main_index_value | |
| 838 | - ). | |
| 839 | - | |
| 840 | -public define Result(DBError,Bool) | |
| 841 | - has_more_rows_than | |
| 842 | - ( | |
| 843 | - DB($MY_DB) the_data_base, | |
| 844 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 845 | - DBIndexVal($Row,$N) main_index_value, | |
| 846 | - Int32 n | |
| 847 | - ). | |
| 848 | - | |
| 849 | -public define Result(DBError,List(DBUpdateResult($Row))) | |
| 850 | - update_rows | |
| 851 | - ( | |
| 852 | - DB($MY_DB) the_data_base, | |
| 853 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 854 | - DBIndexVal($Row,$N) main_index_value, | |
| 855 | - DBRow($Row) -> Maybe($Row) how | |
| 856 | - ). | |
| 857 | - | |
| 858 | -public define Result(DBError,$Row) | |
| 859 | - delete_rows | |
| 860 | - ( | |
| 861 | - DB($MY_DB) the_data_base, | |
| 862 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 863 | - DBIndexVal($Row,$N) main_index_value | |
| 864 | - ). | |
| 865 | - | |
| 675 | + different order. For example, we may consider the following equivalent query (with the | |
| 676 | + tables in reverse order): | |
| 866 | 677 | |
| 678 | + query(my_data_base, | |
| 679 | + products, | |
| 680 | + (DBRow(Product) prd) |-> name(row(prd)) = "Yoyo", | |
| 681 | + (DBRow(Product) prd, String cltname) |-> cltname, | |
| 682 | + (DBRow(Product) prd) |-> | |
| 683 | + query(my_data_base, | |
| 684 | + commands, | |
| 685 | + (DBRow(Command) cmd) |-> | |
| 686 | + row_id(prd) = product_id(row(cmd)), | |
| 687 | + (DBRow(Command) cmd, String cltname) |-> cltname, | |
| 688 | + (DBRow(Command) cmd) |-> | |
| 689 | + query(my_data_base, | |
| 690 | + clients, | |
| 691 | + (DBRow(Client) clt) |-> | |
| 692 | + country(row(clt)) = "France" & | |
| 693 | + row_id(clt) = client_id(row(cmd)), | |
| 694 | + (DBRow(Client) clt, One u) |-> name(row(clt)), | |
| 695 | + (DBRow(Client) clt) |-> unique))) | |
| 696 | + | |
| 697 | + This one may be more efficient than the first one. The order into which the tables are | |
| 698 | + looked up may be important for performances. | |
| 867 | 699 | |
| 868 | 700 | |
| 869 | - *** (4.3) Families of tables. | |
| 870 | 701 | |
| 871 | - It may be the case that you prefer to use a family of small tables (of the same type) | |
| 872 | - instead of a big unique table. For example, if you are managing products in a shop, you | |
| 873 | - may have a very big number of products, each one with many informations, and want (say) | |
| 874 | - one table by product. | |
| 875 | - | |
| 876 | - Actually, this is just a matter of performances and memory management. The only thing | |
| 877 | - you have to do in order to split your big table into a lot of small tables is just to | |
| 878 | - have a main index. The table will be automatically split into a familly of smaller | |
| 879 | - tables. The number of these tables may change during exploitation of your table, | |
| 880 | - depending on the number of rows. In any case, it is automatic. | |
| 881 | - | |
| 882 | - Nevertheless, the type '$N' of main index values must be such that rows are | |
| 883 | - sufficiently separated from each other. At the limit, if you choose 'One' for this | |
| 884 | - type, all rows will have the same index value, and the system will not be able to | |
| 885 | - create more than one file for the whole table. So, 'One' is a very bad choice. In | |
| 886 | - practice, for a table of products, the name of the product, or the supplier reference | |
| 887 | - for that product should provide a good main indexation, which will allow the system to | |
| 888 | - split the table into almost as many files as there are possible values for this index. | |
| 889 | - | |
| 890 | - | |
| 891 | - | |
| 892 | - *** (4.4) Secondary indexing. | |
| 893 | - | |
| 894 | - Now, you may also have to perform searches according to several criteria in a given | |
| 895 | - table. Hence, you may need 'secondary' indexing methods. | |
| 896 | - | |
| 897 | - Secondary indexes are not part of the table (unlike main indexing, they have no | |
| 898 | - influence on how the table is implemented). Hence, secondary indexes must be | |
| 899 | - initialized by themself. Secondary indexes for a table whose row type is '$Row' are | |
| 900 | - data of the following type: | |
| 901 | - | |
| 902 | -public type DBSecondaryIndex($Row,$S):... (an opaque type) | |
| 903 | - | |
| 904 | - | |
| 905 | - A secondary index is initialized by: | |
| 906 | - | |
| 907 | -public define DBSecondaryIndex($Row,$S) | |
| 908 | - init_dbindex | |
| 909 | - ( | |
| 910 | - String index_name, // used as part of a file name | |
| 911 | - DB($MY_DB) the_data_base, | |
| 912 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 913 | - $Row -> $S secondary_search_criterion | |
| 914 | - ). | |
| 915 | - | |
| 916 | - As for tables, the initialization of an index must be performed only once when your | |
| 917 | - program starts. | |
| 918 | - | |
| 919 | - Now, you also need variants of 'get_rows', etc... for searching according to secondary | |
| 920 | - indexing. Here they are. | |
| 921 | - | |
| 922 | -public define Result(DBError,List(DBRow($Row))) | |
| 923 | - get_rows | |
| 924 | - ( | |
| 925 | - DB($MY_DB) the_data_base, | |
| 926 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 927 | - DBSecondaryIndex($Row,$S) index, | |
| 928 | - DBIndexVal($Row,$S) secondary_index_value | |
| 929 | - ). | |
| 930 | - | |
| 931 | -public define Result(DBError,Int32) | |
| 932 | - get_number_of_rows | |
| 933 | - ( | |
| 934 | - DB($MY_DB) the_data_base, | |
| 935 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 936 | - DBSecondaryIndex($Row,$S) index, | |
| 937 | - DBIndexVal($Row,$S) secondary_index_value | |
| 938 | - ). | |
| 939 | - | |
| 940 | -public define Result(DBError,Bool) | |
| 941 | - has_more_rows_than | |
| 942 | - ( | |
| 943 | - DB($MY_DB) the_data_base, | |
| 944 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 945 | - DBSecondaryIndex($Row,$S) index, | |
| 946 | - DBIndexVal($Row,$S) secondary_index_value, | |
| 947 | - Int32 n | |
| 948 | - ). | |
| 949 | - | |
| 950 | -public define Result(DBError,List(DBUpdateResult($Row))) | |
| 951 | - update_rows | |
| 952 | - ( | |
| 953 | - DB($MY_DB) the_data_base, | |
| 954 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 955 | - DBSecondaryIndex($Row,$S) index, | |
| 956 | - DBIndexVal($Row,$S) secondary_index_value, | |
| 957 | - DBRow($Row) -> Maybe($Row) how | |
| 958 | - ). | |
| 959 | - | |
| 960 | -public define Result(DBError,$Row) | |
| 961 | - delete_rows | |
| 962 | - ( | |
| 963 | - DB($MY_DB) the_data_base, | |
| 964 | - $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 965 | - DBSecondaryIndex($Row,$S) index, | |
| 966 | - DBIndexVal($Row,$S) secondary_index_value | |
| 967 | - ). | |
| 968 | - | |
| 969 | - | |
| 970 | - | |
| 971 | - | |
| 972 | - | |
| 973 | - | |
| 974 | - *** (4.5) Handling changes of your indexing methods. | |
| 975 | - | |
| 976 | - | |
| 977 | - | |
| 978 | - | |
| 979 | 702 | |
| 980 | 703 | |
| 981 | - *** (5) Using it with 'web/making_a_web_site.anubis'. | |
| 704 | + *** (12) Using it with 'web/making_a_web_site.anubis'. | |
| 982 | 705 | |
| 983 | 706 | You may want to use this data base manager in conjunction with our web site making |
| 984 | 707 | method. You should proceed as follows in order to start the data base and the web |
| ... | ... | @@ -1066,204 +789,33 @@ public define Result(DBError,$Row) |
| 1066 | 789 | --- That's all for the public part ! -------------------------------------------------- |
| 1067 | 790 | |
| 1068 | 791 | |
| 1069 | - ----------------------------------- Contents ------------------------------------------ | |
| 1070 | - | |
| 1071 | - *** [1] Opaque types. | |
| 1072 | - *** [1.1] Row identifiers. | |
| 1073 | - *** [1.2] Tables. | |
| 1074 | - *** [1.2.1] Type 1 (simple tables). | |
| 1075 | - *** [1.2.2] Type 2 (hash-split tables). | |
| 1076 | - *** [1.3] All tables. | |
| 1077 | - *** [1.4] Data bases. | |
| 1078 | - *** [1.5] Indexing. | |
| 1079 | - | |
| 1080 | - *** [2] Tools. | |
| 1081 | - *** [2.1] Comparing rows. | |
| 1082 | - *** [2.2] Removing an element from a list. | |
| 1083 | - *** [2.3] Inserting elements in a sorted list. | |
| 1084 | - *** [2.4] Removing repeated elements from a list. | |
| 1085 | - *** [2.5] Flattening a list of lists. | |
| 1086 | - | |
| 1087 | - *** [3] Loading and saving table chunks. | |
| 1088 | - *** [3.1] Loading a table chunk. | |
| 1089 | - *** [3.1.1] Type 1 tables. | |
| 1090 | - *** [3.1.2] Type 2 tables. | |
| 1091 | - *** [3.2] Saving a table chunk. | |
| 1092 | - *** [3.2.1] Type 1 tables. | |
| 1093 | - *** [3.2.2] Type 2 tables. | |
| 1094 | - | |
| 1095 | - *** [4] Initializing a data base. | |
| 1096 | - | |
| 1097 | - *** [5] Utilization commands. | |
| 1098 | - *** [5.1] Accessing a table. | |
| 1099 | - *** [5.1.1] Type 1 tables. | |
| 1100 | - *** [5.1.2] Type 2 tables. | |
| 1101 | - *** [5.2] Adding rows to a table. | |
| 1102 | - *** [5.2.1] Type 1 tables. | |
| 1103 | - *** [5.2.2] Type 2 tables. | |
| 1104 | - *** [5.3] Getting rows from a table. | |
| 1105 | - *** [5.3.1] Type 1 tables. | |
| 1106 | - *** [5.3.2] Type 2 tables. | |
| 1107 | - *** [5.4] Getting a number of rows. | |
| 1108 | - *** [5.4.1] Type 1 tables. | |
| 1109 | - *** [5.4.2] Type 2 tables. | |
| 1110 | - *** [5.5] Updating rows. | |
| 1111 | - *** [5.5.1] Type 1 tables. | |
| 1112 | - *** [5.5.2] Type 2 tables. | |
| 1113 | - *** [5.6] Deleting rows. | |
| 1114 | - *** [5.6.1] Type 1 tables. | |
| 1115 | - *** [5.6.2] Type 2 tables. | |
| 1116 | - *** [5.7] Multi-tables queries. | |
| 1117 | - | |
| 1118 | - *** [6] Indexing. | |
| 1119 | - | |
| 1120 | - --------------------------------------------------------------------------------------- | |
| 1121 | - | |
| 1122 | -read tools/basis.anubis required for 'qsort' | |
| 1123 | -read tools/hashtable.anubis because hashtables are better than lists for performances | |
| 1124 | - | |
| 1125 | - | |
| 1126 | - | |
| 1127 | - | |
| 1128 | - *** [1] Opaque types. | |
| 1129 | - | |
| 1130 | - | |
| 1131 | - *** [1.1] Row identifiers. | |
| 1132 | - | |
| 1133 | 792 | Row identifiers are just integers, but this may change in the future, because integers |
| 1134 | 793 | may not be enough. |
| 1135 | 794 | |
| 1136 | 795 | public type DBRowId($Row): |
| 1137 | 796 | dbrowid(Int32 index). |
| 1138 | 797 | |
| 1139 | - | |
| 1140 | - | |
| 1141 | - | |
| 1142 | - *** [1.2] Tables. | |
| 1143 | - | |
| 1144 | - There are several types of tables (different implementations in memory and on disk). A | |
| 1145 | - type 1 table is saved into a single file. A type 2 table is split into chunks and each | |
| 1146 | - chunk is saved into a separate file. | |
| 1147 | - | |
| 1148 | - Tables or table chunks are loaded into memory only on demand. During the loading the | |
| 1149 | - format is changed to some format appropriate for the memory. | |
| 1150 | - | |
| 1151 | - | |
| 1152 | - *** [1.2.1] Type 1 (simple tables). | |
| 1153 | - | |
| 1154 | - Type 1 (simple tables) is good for small tables (tables with very few rows). The table | |
| 1155 | - is saved into a single file. It is loaded only on demand. | |
| 1156 | - | |
| 1157 | 798 | When a table is loaded, a boolean variable 'changed' indicates if it has to be saved. A |
| 1158 | 799 | integer variable contains the counter for creating identifiers for new rows. Another |
| 1159 | 800 | variable contains the list of all loaded rows. |
| 1160 | 801 | |
| 1161 | -type DBLoadedTable1($Row,$HRow): | |
| 802 | +type DBLoadedTable($Row,$HRow): | |
| 1162 | 803 | table(String table_name, |
| 1163 | 804 | (DBRow($Row),DBRow($Row)) -> Bool compare, |
| 1164 | 805 | $Row -> $HRow store, |
| 1165 | 806 | Var(Bool) changed_v, |
| 1166 | 807 | Var(Int32) counter_v, |
| 1167 | 808 | Var(List(DBRow($Row))) rows_v). |
| 1168 | - | |
| 1169 | - Now, tables in the data base are either loaded or not. | |
| 1170 | - | |
| 1171 | -type DBTableState1($Row,$HRow): | |
| 1172 | - not_loaded (String table_name, | |
| 1173 | - ($Row,$Row) -> Bool compare, | |
| 1174 | - $HRow -> $Row update, | |
| 1175 | - $Row -> $HRow store), | |
| 1176 | - loaded (DBLoadedTable1($Row,$HRow)). | |
| 1177 | - | |
| 1178 | - Now a table is just a variable containing either a non loaded table or a loaded table. | |
| 1179 | - | |
| 1180 | - | |
| 1181 | - | |
| 1182 | - | |
| 1183 | - | |
| 1184 | - | |
| 1185 | - | |
| 1186 | - | |
| 1187 | - *** [1.2.2] Type 2 (hash-split tables). | |
| 1188 | - | |
| 1189 | - split_table(String table_name, | |
| 1190 | - (DBRow($Row),DBRow($Row)) -> Bool compare, | |
| 1191 | - Var(Bool) changed_v, | |
| 1192 | - Var(Int32) counter_v, | |
| 1193 | - HashTable(Int32,List(DBRow($Row))) rows). | |
| 1194 | - | |
| 1195 | - | |
| 1196 | 809 | |
| 810 | + Of course, tables are not saved on disk as 'DBLoadedTable($Row,$HRow)' because variable | |
| 811 | + types (and functional types for the time being) are not serializable, and also because | |
| 812 | + data of type '$Row' are not saved on the disk. Tables are saved as data of type | |
| 813 | + 'DBSavedTable($HRow)'. | |
| 1197 | 814 | |
| 815 | +type DBSavedTable($HRow): | |
| 816 | + myversion_1(Int32 counter, | |
| 817 | + List(DBRow($HRow)) rows). | |
| 1198 | 818 | |
| 1199 | - *** [1.3] Table file formats. | |
| 1200 | - | |
| 1201 | - Of course, tables are not saved on disk as 'DBLoadedTable1($Row,$HRow)' because | |
| 1202 | - variable types (and functional types for the time being) are not serializable, and also | |
| 1203 | - because data of type '$Row' are not saved on the disk. Tables are saved as data of | |
| 1204 | - type 'TableFileContent($HRow)'. | |
| 1205 | - | |
| 1206 | -type TableFileContent($HRow): | |
| 1207 | - type_1(Int32 counter, | |
| 1208 | - List(DBRow($HRow)) rows). | |
| 1209 | - | |
| 1210 | - | |
| 1211 | - | |
| 1212 | - | |
| 1213 | - | |
| 1214 | - *** [1.3] All tables. | |
| 1215 | - | |
| 1216 | -public type DBTable($Row,$HRow): | |
| 1217 | - db_table_1(Var(DBTableState1($Row,$HRow))). | |
| 1218 | - db_table_2(Var(DBTableState2($Row,$HRow))). | |
| 1219 | - | |
| 1220 | - | |
| 1221 | - | |
| 1222 | - *** [1.4] Data bases. | |
| 1223 | - | |
| 1224 | - The data base itself is made of the directory path for table files, and the set of | |
| 1225 | - tables (loaded or not). | |
| 1226 | - | |
| 1227 | -public type DB($MY_DB): | |
| 1228 | - db(String directory, | |
| 1229 | - $MY_DB tables). | |
| 1230 | - | |
| 1231 | - | |
| 1232 | - | |
| 1233 | - | |
| 1234 | - | |
| 1235 | - *** [1.5] Indexing. | |
| 1236 | - | |
| 1237 | -public type DBIndexVal($Row,$N): | |
| 1238 | - index_val($N). | |
| 1239 | - | |
| 1240 | - | |
| 1241 | -type DBLoadedIndex($Row,$S): | |
| 1242 | - index(String index_name, | |
| 1243 | - String directory_name, | |
| 1244 | - Var(Bool) changed_v, | |
| 1245 | - Var(HashTable(Int32,List(Int32))) entries). | |
| 1246 | - | |
| 1247 | -type IndexState($Row,$S): | |
| 1248 | - not_loaded(String index_name, | |
| 1249 | - String directory_name, | |
| 1250 | - $Row -> $S secondary_search_criterion), | |
| 1251 | - loaded(DBLoadedIndex($Row,$S)). | |
| 1252 | - | |
| 1253 | -public type DBSecondaryIndex($Row,$N): | |
| 1254 | - secondary_index(Var(IndexState($Row,$N))). | |
| 1255 | - | |
| 1256 | - | |
| 1257 | - | |
| 1258 | - | |
| 1259 | - | |
| 1260 | - | |
| 1261 | - | |
| 1262 | - *** [2] Tools. | |
| 1263 | - | |
| 1264 | - | |
| 1265 | - | |
| 1266 | - *** [2.1] Comparing rows. | |
| 1267 | 819 | |
| 1268 | 820 | We will have to compare the rows of a loaded table. The function able to compare loaded |
| 1269 | 821 | rows must be constructed from the function comparing nude rows. This is the job of the |
| ... | ... | @@ -1279,116 +831,23 @@ define (DBRow($Row),DBRow($Row)) -> Bool |
| 1279 | 831 | if dbr2 is dbrow(id2,v2,r2) then |
| 1280 | 832 | compare(r1,r2). |
| 1281 | 833 | |
| 1282 | - | |
| 1283 | - | |
| 1284 | - | |
| 1285 | - *** [2.2] Removing an element from a list. | |
| 1286 | - | |
| 1287 | -define List($T) | |
| 1288 | - remove | |
| 1289 | - ( | |
| 1290 | - $T x, | |
| 1291 | - List($T) l | |
| 1292 | - ) = | |
| 1293 | - if l is | |
| 1294 | - { | |
| 1295 | - [ ] then [ ], | |
| 1296 | - [h . t] then | |
| 1297 | - if x = h | |
| 1298 | - then t | |
| 1299 | - else [h . remove(x,t)] | |
| 1300 | - }. | |
| 1301 | - | |
| 1302 | - | |
| 1303 | - | |
| 1304 | - | |
| 1305 | - *** [2.3] Inserting elements in a sorted list. | |
| 1306 | - | |
| 1307 | - The next function receives two lists (of the same type) which are both already sorted. | |
| 1308 | - It inserts the elements of the first list at the right place in the second list. | |
| 1309 | - | |
| 1310 | -define List($T) | |
| 1311 | - insert // insert elements of l1 into l2 | |
| 1312 | - ( | |
| 1313 | - List($T) l1, | |
| 1314 | - List($T) l2, | |
| 1315 | - ($T,$T) -> Bool less | |
| 1316 | - ) = | |
| 1317 | - if l1 is | |
| 1318 | - { | |
| 1319 | - [ ] then l2, | |
| 1320 | - [h1 . t1] then | |
| 1321 | - if l2 is | |
| 1322 | - { | |
| 1323 | - [ ] then l1, | |
| 1324 | - [h2 . t2] then | |
| 1325 | - if less(h1,h2) | |
| 1326 | - then [h1 . insert(t1,l2,less)] | |
| 1327 | - else [h2 . insert(l1,t2,less)] | |
| 1328 | - } | |
| 1329 | - }. | |
| 1330 | - | |
| 1331 | - | |
| 1332 | - | |
| 1333 | - | |
| 1334 | - | |
| 1335 | - *** [2.4] Removing repeated elements from a list. | |
| 1336 | - | |
| 1337 | -define List($Out) | |
| 1338 | - remove_repetitions | |
| 1339 | - ( | |
| 1340 | - List($Out) l | |
| 1341 | - ) = | |
| 1342 | - if l is | |
| 1343 | - { | |
| 1344 | - [ ] then [ ], | |
| 1345 | - [h . t] then | |
| 1346 | - if member(t,h) | |
| 1347 | - then remove_repetitions(t) | |
| 1348 | - else [h . remove_repetitions(t)] | |
| 1349 | - }. | |
| 1350 | - | |
| 1351 | - | |
| 1352 | - | |
| 1353 | - *** [2.5] Flattening a list of lists. | |
| 1354 | - | |
| 1355 | -define List($T) | |
| 1356 | - flatten | |
| 1357 | - ( | |
| 1358 | - List(List($T)) l | |
| 1359 | - ) = | |
| 1360 | - if l is | |
| 1361 | - { | |
| 1362 | - [ ] then [ ], | |
| 1363 | - [h . t] then h + flatten(t) | |
| 1364 | - }. | |
| 1365 | - | |
| 1366 | - | |
| 1367 | - | |
| 1368 | - | |
| 1369 | - | |
| 1370 | - *** [3] Loading and saving table chunks. | |
| 1371 | - | |
| 1372 | - | |
| 1373 | - *** [3.1] Loading a table chunk. | |
| 1374 | - | |
| 1375 | - | |
| 1376 | - *** [3.1.1] Type 1 tables. | |
| 1377 | 834 | |
| 1378 | 835 | Tables need to be installed (which involves installing all rows). |
| 1379 | 836 | |
| 1380 | -define DBLoadedTable1($Row,$HRow) | |
| 837 | +read tools/basis.anubis required for 'qsort' | |
| 838 | + | |
| 839 | +define DBLoadedTable($Row,$HRow) | |
| 1381 | 840 | install_table |
| 1382 | 841 | ( |
| 1383 | 842 | String table_name, |
| 1384 | 843 | ($Row,$Row) -> Bool compare, |
| 1385 | 844 | $HRow -> $Row update, |
| 1386 | 845 | $Row -> $HRow store, |
| 1387 | - TableFileContent($HRow) st | |
| 846 | + DBSavedTable($HRow) st | |
| 1388 | 847 | ) = |
| 1389 | 848 | if st is |
| 1390 | 849 | { |
| 1391 | - type_1(count,rows) then | |
| 850 | + myversion_1(count,rows) then | |
| 1392 | 851 | with db_compare = dbrow(compare), |
| 1393 | 852 | updated_rows = map((DBRow($HRow) dbr) |-> |
| 1394 | 853 | if dbr is dbrow(row_id,version,row) |
| ... | ... | @@ -1404,15 +863,6 @@ define DBLoadedTable1($Row,$HRow) |
| 1404 | 863 | }. |
| 1405 | 864 | |
| 1406 | 865 | |
| 1407 | - | |
| 1408 | - *** [3.1.2] Type 2 tables. | |
| 1409 | - | |
| 1410 | - | |
| 1411 | - | |
| 1412 | - *** [3.2] Saving a table chunk. | |
| 1413 | - | |
| 1414 | - | |
| 1415 | - *** [3.2.1] Type 1 tables. | |
| 1416 | 866 | |
| 1417 | 867 | Saving a table on the disk (the table also persists in memory). |
| 1418 | 868 | |
| ... | ... | @@ -1420,11 +870,11 @@ define Result(DBError,One) |
| 1420 | 870 | save_table |
| 1421 | 871 | ( |
| 1422 | 872 | String dbdir, |
| 1423 | - DBLoadedTable1($Row,$HRow) t | |
| 873 | + DBLoadedTable($Row,$HRow) t | |
| 1424 | 874 | ) = |
| 1425 | 875 | if t is table(table_name,compare,store,changed_v,counter_v,rows_v) then |
| 1426 | 876 | with path = dbdir+"/"+table_name, |
| 1427 | - if protect save((TableFileContent($HRow))type_1(*counter_v, | |
| 877 | + if protect save((DBSavedTable($HRow))myversion_1(*counter_v, | |
| 1428 | 878 | map((DBRow($Row) dbr) |-> |
| 1429 | 879 | if dbr is dbrow(row_id,version,row) then |
| 1430 | 880 | if row_id is dbrowid(i) then |
| ... | ... | @@ -1439,15 +889,29 @@ define Result(DBError,One) |
| 1439 | 889 | |
| 1440 | 890 | |
| 1441 | 891 | |
| 1442 | - *** [3.2.2] Type 2 tables. | |
| 892 | + Tables in the data base are either loaded or not. | |
| 893 | + | |
| 894 | +type DBTableState($Row,$HRow): | |
| 895 | + not_loaded (String table_name, | |
| 896 | + ($Row,$Row) -> Bool compare, | |
| 897 | + $HRow -> $Row update, | |
| 898 | + $Row -> $HRow store), | |
| 899 | + loaded (DBLoadedTable($Row,$HRow)). | |
| 1443 | 900 | |
| 901 | + Now a table is just a variable containing either a non loaded table or a loaded table. | |
| 1444 | 902 | |
| 903 | +public type DBTable($Row,$HRow): | |
| 904 | + db_table(Var(DBTableState($Row,$HRow))). | |
| 1445 | 905 | |
| 1446 | 906 | |
| 907 | + The data base itself is made of the directory path for table files, and the set of | |
| 908 | + tables (loaded or not). | |
| 1447 | 909 | |
| 1448 | - | |
| 1449 | - *** [4] Initializing a data base. | |
| 910 | +public type DB($MY_DB): | |
| 911 | + db(String directory, | |
| 912 | + $MY_DB tables). | |
| 1450 | 913 | |
| 914 | + | |
| 1451 | 915 | public define DB($MY_DB) |
| 1452 | 916 | init_db |
| 1453 | 917 | ( |
| ... | ... | @@ -1457,9 +921,6 @@ public define DB($MY_DB) |
| 1457 | 921 | forget(make_directory(data_base_directory,default_directory_mode)); |
| 1458 | 922 | db(data_base_directory,tables). |
| 1459 | 923 | |
| 1460 | - | |
| 1461 | - | |
| 1462 | - | |
| 1463 | 924 | public define DBTable($Row,$HRow) |
| 1464 | 925 | init_dbtable |
| 1465 | 926 | ( |
| ... | ... | @@ -1468,41 +929,28 @@ public define DBTable($Row,$HRow) |
| 1468 | 929 | $HRow -> $Row update, |
| 1469 | 930 | $Row -> $HRow store |
| 1470 | 931 | ) = |
| 1471 | - db_table_1(var(not_loaded(table_name,compare,update,store))). | |
| 1472 | - | |
| 1473 | - | |
| 1474 | - | |
| 1475 | - | |
| 1476 | - | |
| 932 | + db_table(var(not_loaded(table_name,compare,update,store))). | |
| 1477 | 933 | |
| 1478 | - *** [5] Utilization commands. | |
| 1479 | - | |
| 1480 | - | |
| 1481 | - | |
| 1482 | - *** [5.1] Accessing a table. | |
| 1483 | 934 | |
| 1484 | 935 | Given a data base and a table in the form of a destructor of type MY_DB, the next |
| 1485 | 936 | function returns the table in the form of a loaded table. |
| 1486 | 937 | |
| 1487 | - | |
| 1488 | - *** [5.1.1] Type 1 tables. | |
| 1489 | - | |
| 1490 | -define Result(DBError,DBLoadedTable1($Row,$HRow)) | |
| 938 | +define Result(DBError,DBLoadedTable($Row,$HRow)) | |
| 1491 | 939 | get_table |
| 1492 | 940 | ( |
| 1493 | 941 | DB($MY_DB) the_data_base, |
| 1494 | 942 | $MY_DB -> DBTable($Row,$HRow) the_table, |
| 1495 | 943 | ) = |
| 1496 | 944 | if the_data_base is db(dbdir,my_db) then |
| 1497 | - if the_table(my_db) is db_table_1(table_v) then | |
| 945 | + if the_table(my_db) is db_table(table_v) then | |
| 1498 | 946 | if *table_v is |
| 1499 | 947 | { |
| 1500 | 948 | not_loaded(table_name,compare,update,store) then |
| 1501 | 949 | with file_path = dbdir+"/"+table_name, |
| 1502 | - if (RetrieveResult(TableFileContent($HRow)))retrieve(file_path) is | |
| 950 | + if (RetrieveResult(DBSavedTable($HRow)))retrieve(file_path) is | |
| 1503 | 951 | { |
| 1504 | 952 | cannot_find_file then |
| 1505 | - with new_table = install_table(table_name,compare,update,store,type_1(0,[])), | |
| 953 | + with new_table = install_table(table_name,compare,update,store,myversion_1(0,[])), | |
| 1506 | 954 | table_v <- loaded(new_table); |
| 1507 | 955 | ok(new_table), |
| 1508 | 956 | |
| ... | ... | @@ -1519,21 +967,37 @@ define Result(DBError,DBLoadedTable1($Row,$HRow)) |
| 1519 | 967 | }. |
| 1520 | 968 | |
| 1521 | 969 | |
| 970 | + Inserting rows. The next function receives two lists (of the same type) which are both | |
| 971 | + already sorted. It inserts the elements of the first list at the right place in the | |
| 972 | + second list. | |
| 1522 | 973 | |
| 974 | +define List($T) | |
| 975 | + insert // insert elements of l1 into l2 | |
| 976 | + ( | |
| 977 | + List($T) l1, | |
| 978 | + List($T) l2, | |
| 979 | + ($T,$T) -> Bool less | |
| 980 | + ) = | |
| 981 | + if l1 is | |
| 982 | + { | |
| 983 | + [ ] then l2, | |
| 984 | + [h1 . t1] then | |
| 985 | + if l2 is | |
| 986 | + { | |
| 987 | + [ ] then l1, | |
| 988 | + [h2 . t2] then | |
| 989 | + if less(h1,h2) | |
| 990 | + then [h1 . insert(t1,l2,less)] | |
| 991 | + else [h2 . insert(l1,t2,less)] | |
| 992 | + } | |
| 993 | + }. | |
| 1523 | 994 | |
| 995 | + | |
| 1524 | 996 | |
| 1525 | - *** [5.1.2] Type 2 tables. | |
| 1526 | - | |
| 1527 | - | |
| 1528 | - *** [5.2] Adding rows to a table. | |
| 1529 | - | |
| 1530 | - *** [5.2.1] Type 1 tables. | |
| 1531 | - | |
| 1532 | - | |
| 1533 | - The table contains a list of 'DBRow($Row)' which is already sorted. The new rows arrive | |
| 1534 | - as data of type '$Row', and need first to be sorted. Then they are transformed into | |
| 1535 | - 'DBRow($Row)' and inserted in the table. Hence, we need to compare data of type | |
| 1536 | - 'DBRow($Row)'. | |
| 997 | + Adding rows. The table contains a list of 'DBRow($Row)' which is already sorted. The | |
| 998 | + new rows arrive as data of type '$Row', and need first to be sorted. Then they are | |
| 999 | + transformed into 'DBRow($Row)' and inserted in the table. Hence, we need to compare | |
| 1000 | + data of type 'DBRow($Row)'. | |
| 1537 | 1001 | |
| 1538 | 1002 | The next function gets a list of nude rows (of type '$Row'), and transforms it into a |
| 1539 | 1003 | list of loaded rows, creating a new identifier for each row. This function is run |
| ... | ... | @@ -1611,20 +1075,10 @@ public define Result(DBError,DBRowId($Row)) |
| 1611 | 1075 | } |
| 1612 | 1076 | }. |
| 1613 | 1077 | |
| 1614 | - | |
| 1615 | - | |
| 1616 | - | |
| 1617 | - *** [5.2.2] Type 2 tables. | |
| 1618 | - | |
| 1619 | - | |
| 1620 | - | |
| 1621 | 1078 | |
| 1622 | - *** [5.3] Getting rows from a table. | |
| 1623 | 1079 | |
| 1624 | 1080 | |
| 1625 | 1081 | |
| 1626 | - *** [5.3.1] Type 1 tables. | |
| 1627 | - | |
| 1628 | 1082 | Getting a row by its identifier. |
| 1629 | 1083 | |
| 1630 | 1084 | define Result(DBError,DBRow($Row)) |
| ... | ... | @@ -1663,6 +1117,21 @@ public define Result(DBError,DBRow($Row)) |
| 1663 | 1117 | Getting rows by their identifiers. |
| 1664 | 1118 | |
| 1665 | 1119 | |
| 1120 | +define List($T) | |
| 1121 | + remove | |
| 1122 | + ( | |
| 1123 | + $T x, | |
| 1124 | + List($T) l | |
| 1125 | + ) = | |
| 1126 | + if l is | |
| 1127 | + { | |
| 1128 | + [ ] then [ ], | |
| 1129 | + [h . t] then | |
| 1130 | + if x = h | |
| 1131 | + then t | |
| 1132 | + else [h . remove(x,t)] | |
| 1133 | + }. | |
| 1134 | + | |
| 1666 | 1135 | define Result(DBError,List(DBRow($Row))) |
| 1667 | 1136 | get_rows |
| 1668 | 1137 | ( |
| ... | ... | @@ -1750,15 +1219,6 @@ public define Result(DBError,List(DBRow($Row))) |
| 1750 | 1219 | (DBRow($Row) r) |-> which(row(r))). |
| 1751 | 1220 | |
| 1752 | 1221 | |
| 1753 | - *** [5.3.2] Type 2 tables. | |
| 1754 | - | |
| 1755 | - | |
| 1756 | - | |
| 1757 | - | |
| 1758 | - *** [5.4] Getting a number of rows. | |
| 1759 | - | |
| 1760 | - | |
| 1761 | - *** [5.4.1] Type 1 tables. | |
| 1762 | 1222 | |
| 1763 | 1223 | Getting a number of rows. |
| 1764 | 1224 | |
| ... | ... | @@ -1829,16 +1289,8 @@ public define Result(DBError,Bool) |
| 1829 | 1289 | }. |
| 1830 | 1290 | |
| 1831 | 1291 | |
| 1832 | - *** [5.4.2] Type 2 tables. | |
| 1833 | - | |
| 1834 | 1292 | |
| 1835 | 1293 | |
| 1836 | - | |
| 1837 | - *** [5.5] Updating rows. | |
| 1838 | - | |
| 1839 | - | |
| 1840 | - *** [5.5.1] Type 1 tables. | |
| 1841 | - | |
| 1842 | 1294 | Updating rows. Rows which satisfy the 'which' condition are first extracted from the |
| 1843 | 1295 | table and updated by 'how'. Then the list of updated rows is sorted, and reinserted |
| 1844 | 1296 | into the table. Subsequently, the table is saved. |
| ... | ... | @@ -1994,16 +1446,8 @@ public define Result(DBError,List(DBUpdateResult($Row))) |
| 1994 | 1446 | } |
| 1995 | 1447 | }. |
| 1996 | 1448 | |
| 1997 | - | |
| 1998 | - | |
| 1999 | - *** [5.5.2] Type 2 tables. | |
| 2000 | 1449 | |
| 2001 | 1450 | |
| 2002 | - *** [5.6] Deleting rows. | |
| 2003 | - | |
| 2004 | - | |
| 2005 | - *** [5.6.1] Type 1 tables. | |
| 2006 | - | |
| 2007 | 1451 | Deleting rows. |
| 2008 | 1452 | |
| 2009 | 1453 | |
| ... | ... | @@ -2097,12 +1541,37 @@ public define Result(DBError,List($Row)) |
| 2097 | 1541 | |
| 2098 | 1542 | |
| 2099 | 1543 | |
| 2100 | - *** [5.6.2] Type 2 tables. | |
| 2101 | 1544 | |
| 2102 | 1545 | |
| 2103 | - *** [5.7] Multi-tables queries. | |
| 1546 | + | |
| 1547 | + Multi-tables queries. | |
| 2104 | 1548 | |
| 2105 | 1549 | |
| 1550 | +define List($Out) | |
| 1551 | + remove_repetitions | |
| 1552 | + ( | |
| 1553 | + List($Out) l | |
| 1554 | + ) = | |
| 1555 | + if l is | |
| 1556 | + { | |
| 1557 | + [ ] then [ ], | |
| 1558 | + [h . t] then | |
| 1559 | + if member(t,h) | |
| 1560 | + then remove_repetitions(t) | |
| 1561 | + else [h . remove_repetitions(t)] | |
| 1562 | + }. | |
| 1563 | + | |
| 1564 | + | |
| 1565 | +define List($T) | |
| 1566 | + flatten | |
| 1567 | + ( | |
| 1568 | + List(List($T)) l | |
| 1569 | + ) = | |
| 1570 | + if l is | |
| 1571 | + { | |
| 1572 | + [ ] then [ ], | |
| 1573 | + [h . t] then h + flatten(t) | |
| 1574 | + }. | |
| 2106 | 1575 | |
| 2107 | 1576 | public define List($Out) |
| 2108 | 1577 | query |
| ... | ... | @@ -2125,9 +1594,6 @@ public define List($Out) |
| 2125 | 1594 | |
| 2126 | 1595 | |
| 2127 | 1596 | |
| 2128 | - | |
| 2129 | - *** [6] Indexing. | |
| 2130 | - | |
| 2131 | 1597 | |
| 2132 | 1598 | |
| 2133 | 1599 | ... | ... |
| 1 | + | |
| 2 | + | |
| 3 | + The Anubis/Paradize Project. | |
| 4 | + | |
| 5 | + A Simple Data Base Management System. | |
| 6 | + | |
| 7 | + Copyright (c) Alain Prouté 2004-2005. | |
| 8 | + | |
| 9 | + | |
| 10 | + Author: Alain Prouté | |
| 11 | + | |
| 12 | + Last revision: January 2005. | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + ----------------------------------- Contents ------------------------------------------ | |
| 18 | + | |
| 19 | + *** (1) Overview. | |
| 20 | + *** (2) Errors. | |
| 21 | + *** (3) Tables and data bases. | |
| 22 | + *** (4) Managing changes in table formats. | |
| 23 | + *** (5) Row identifiers. | |
| 24 | + *** (6) Adding rows to a table. | |
| 25 | + *** (7) Getting rows from a table. | |
| 26 | + *** (8) Testing a number of rows. | |
| 27 | + *** (9) Updating rows in a table. | |
| 28 | + *** (10) Deleting rows from a table. | |
| 29 | + *** (11) Multi-tables queries. | |
| 30 | + *** (12) Using it with 'web/making_a_web_site.anubis'. | |
| 31 | + | |
| 32 | + --------------------------------------------------------------------------------------- | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + *** (1) Overview. | |
| 38 | + | |
| 39 | + Relational data base management systems provide two kinds of commands: | |
| 40 | + | |
| 41 | + - utilization commands, like adding, updating or deleting rows in a table, or | |
| 42 | + querying using the SQL command 'SELECT'. | |
| 43 | + | |
| 44 | + - restructuring commands, like adding columns in a table, deleting columns, etc... | |
| 45 | + | |
| 46 | + Normally, if a data base is restructured, programs using that database must themselves | |
| 47 | + be restructured, while the transformation of the data base by utilization commands does | |
| 48 | + not require any modification of the programs which are using the data base. | |
| 49 | + | |
| 50 | + Our aim is to provide a data base mecanism, which is as much as possible in the spirit | |
| 51 | + of Anubis. Our first demand is that cells in a table should be able to contain data of | |
| 52 | + any (serializable) Anubis type (one type per column of the table of course). More | |
| 53 | + precisely, if T is a type, we want to consider tables whose rows are data of type T. A | |
| 54 | + consequence of this is that adding a column to a table requires a modification of an | |
| 55 | + Anubis type, hence a modification of the program using the data base. But this is | |
| 56 | + precisely in the spirit of Anubis, because this will force a corresponding modification | |
| 57 | + of the program, so ensuring more security. | |
| 58 | + | |
| 59 | + This data base management program is highly experimental. Indeed, the obligation of | |
| 60 | + deciding everything about types of data at compile time, introduces a rigidity which | |
| 61 | + renders the mimicking of the usual data base manipulations quite difficult (at least as | |
| 62 | + far as the SELECT command is concerned). Nevertheless, it's an interesting adventure | |
| 63 | + because it puts de facto at different levels aspects of data base management which are | |
| 64 | + otherwise consider of the same kind. | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + *** (2) Errors. | |
| 70 | + | |
| 71 | + Errors may occur during the normal management of the data base. | |
| 72 | + | |
| 73 | +public type DBError: | |
| 74 | + file_not_found (String path), | |
| 75 | + file_reading_problem (String path), | |
| 76 | + file_type_problem (String path), | |
| 77 | + cannot_open_file (String path), | |
| 78 | + cannot_write_file (String path), | |
| 79 | + record_not_found. | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + *** (3) Tables and data bases. | |
| 87 | + | |
| 88 | + The type of the rows of a table is up to you (but must be serializable). However, this | |
| 89 | + data base management system includes a mecanism for handling the possible changes in | |
| 90 | + the definition of the types of the rows of a table, in such a way that updating the | |
| 91 | + actual tables files on the disk is automatic. For this reason, the type scheme | |
| 92 | + 'DBTable' representing tables has two type parameters. The first one represents the | |
| 93 | + current type of the rows of the table, the second one represents the history of all | |
| 94 | + successive types of the rows of the table. With this mecanism, and if you repects some | |
| 95 | + principles explained below, your program will always be able to read old tables saved | |
| 96 | + in old formats. | |
| 97 | + | |
| 98 | + Tables are represented by the following opaque type scheme, where the parameter '$Row' | |
| 99 | + is the current type of the rows of the table, and '$HRow' ('H' like 'History') is a | |
| 100 | + type containing the history of all the successive formats of rows in the table: | |
| 101 | + | |
| 102 | +public type DBTable($Row,$HRow):... | |
| 103 | + | |
| 104 | + The first thing you have to do if you want to use this data base management system, is | |
| 105 | + to define the type of your data base. Since a data base is essentially a set of | |
| 106 | + tables, the type of your data base should be something like this (at the beginning, you | |
| 107 | + can use the same type for '$Row' and '$HRow'): | |
| 108 | + | |
| 109 | + type MY_DB: | |
| 110 | + my_db(DBTable(Client,Client) clients, | |
| 111 | + DBTable(Product,Product) products, | |
| 112 | + DBTable(Supplier,Supplier) suppliers, | |
| 113 | + ...). | |
| 114 | + | |
| 115 | + where the types 'Client', 'Product', ... have been previously defined by you. Notice | |
| 116 | + that a datum of type 'Client' is just an entire row in the 'clients' table. Hence, | |
| 117 | + 'Client' is probably a type with just one alternative and the components needed for a | |
| 118 | + 'client', like 'name', 'address', etc... | |
| 119 | + | |
| 120 | + What if the type $Row has several alternatives ? This means that your table has several | |
| 121 | + sorts of rows. But in this case, you should perhaps better use several | |
| 122 | + tables. Nevertheless, this makes no problem. | |
| 123 | + | |
| 124 | + Actually, a datum of type MY_DB is not the whole data base. The system requires more | |
| 125 | + informations. This is the reason why the actual type of the data base is: | |
| 126 | + | |
| 127 | +public type DB($MY_DB):... (again an opaque type scheme) | |
| 128 | + | |
| 129 | + where the parameter '$MY_DB' may be instantiated to your type 'MY_DB'. Several | |
| 130 | + instantiations allow the creation of several data bases. | |
| 131 | + | |
| 132 | + Now, when you start your program (may be a web site), you need to start the data base | |
| 133 | + manager. This amounts to initialize each table, and use the initialized tables to | |
| 134 | + initialize the data base itself: | |
| 135 | + | |
| 136 | + with my_data_base = init_db(my_data_base_directory, | |
| 137 | + my_db(init_dbtable ("clients", compare, identity, identity), | |
| 138 | + init_dbtable ("products", compare, identity, identity), | |
| 139 | + init_dbtable ("suppliers", compare, identity, identity), | |
| 140 | + ...)), | |
| 141 | + | |
| 142 | + where 'init_db' is declared as: | |
| 143 | + | |
| 144 | +public define DB($MY_DB) | |
| 145 | + init_db | |
| 146 | + ( | |
| 147 | + String data_base_directory, | |
| 148 | + $MY_DB tables | |
| 149 | + ). | |
| 150 | + | |
| 151 | + and where 'init_dbtable' is declared as: | |
| 152 | + | |
| 153 | +public define DBTable($Row,$HRow) | |
| 154 | + init_dbtable | |
| 155 | + ( | |
| 156 | + String table_name, | |
| 157 | + ($Row,$Row) -> Bool compare, | |
| 158 | + $HRow -> $Row update, | |
| 159 | + $Row -> $HRow store | |
| 160 | + ). | |
| 161 | + | |
| 162 | + Notice that the name 'table_name' above becomes part of the names of the files | |
| 163 | + containing the tables (located in the directory 'data_base_directory' above). | |
| 164 | + 'init_table' does not load the table from the disk. A table is loaded only when | |
| 165 | + needed. If the table does not exist on the disk, 'init_table' creates an empty table | |
| 166 | + of the right type. 'init_table' should be executed only once per table, when your | |
| 167 | + program starts. | |
| 168 | + | |
| 169 | + The 'compare' function is used for sorting the rows of the table. The table is sorted | |
| 170 | + when it is read from the disk, and whenever a row is added or updated, it is placed at | |
| 171 | + the right position in the table according to the order defined by the 'compare' | |
| 172 | + function. More precisely, if 'r1' and 'r2' are rows in the table, and if | |
| 173 | + 'compare(r1,r2)' is 'true', 'r1' is placed before 'r2' in the table. When you get rows | |
| 174 | + from the table (using 'get_rows' declared below) you get your rows in the order defined | |
| 175 | + by the 'compare' function. Of course, the 'compare' function is just a default way of | |
| 176 | + ordering the table. You can always reorder the result of 'get_rows' for any purpose. | |
| 177 | + | |
| 178 | + The 'update' and 'store' functions are used for automating the changes of format of the | |
| 179 | + tables. This is explained below in the section 'Managing changes in table formats'. At | |
| 180 | + the beginning, while the two types '$Row' and '$HRow' are identical, you can use the | |
| 181 | + function 'identity' (actually a scheme of function, defined in 'tools/basis.anubis') | |
| 182 | + for both 'update' and 'store'. | |
| 183 | + | |
| 184 | + At that point you have the datum 'my_data_base' at hand, which is of type 'DB($MY_DB)', | |
| 185 | + and which represents the whole data base. The preparation above determines the whole | |
| 186 | + structure of the data base. With a datum of type 'DB($MY_DB)' at hand, the Anubis | |
| 187 | + compiler is able to detect many errors that would not be detected by an untyped (or | |
| 188 | + dynamically typed) data base system. Of course, you can use several such data bases in | |
| 189 | + a program. | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + *** (4) Managing changes in table formats. | |
| 196 | + | |
| 197 | + Up to here the types used as instantiations of '$Row' and '$HRow' are the same one. | |
| 198 | + That's OK, and you have begun to distribute your program and your users have created | |
| 199 | + tables whose types are your types 'Client', 'Product' etc... If you simply modify the | |
| 200 | + definition of (say) the type 'Client', your new program will not work with the tables | |
| 201 | + created by your users, which is obviously a catastrophe. Fortunately, there is a | |
| 202 | + remedy, and here it is. | |
| 203 | + | |
| 204 | + Assume that you want to change the definition of the type 'Client', because you need | |
| 205 | + more columns in the table of clients. As an example, assume that your type 'Client' | |
| 206 | + was first defined as: | |
| 207 | + | |
| 208 | + type Client: | |
| 209 | + client(String name, | |
| 210 | + String address). | |
| 211 | + | |
| 212 | + and you want to add a new component (column of the table): | |
| 213 | + | |
| 214 | + Int32 age | |
| 215 | + | |
| 216 | + | |
| 217 | + --- Step 1: | |
| 218 | + | |
| 219 | + The first thing to do is to make two copies of your original type, because from now on, | |
| 220 | + the types '$Row' and '$HRow' are no more identical: | |
| 221 | + | |
| 222 | + type Client: // current type of rows of 'clients' table | |
| 223 | + client(String name, | |
| 224 | + String address). | |
| 225 | + | |
| 226 | + type HClient: // history of type of rows of 'clients' table | |
| 227 | + client(String name, | |
| 228 | + String address). | |
| 229 | + | |
| 230 | + | |
| 231 | + --- Step 2: | |
| 232 | + | |
| 233 | + The first alternative of 'HClient' should never be changed, because it represents an | |
| 234 | + 'historical' way of representing clients. The only thing that you can do is change the | |
| 235 | + name of the alternative. We recommend to name it 'version_1', and to use the name | |
| 236 | + 'version_2' for the second alternative representing the new type of rows. Hence, the | |
| 237 | + type 'HClient' becomes: | |
| 238 | + | |
| 239 | + type HClient: | |
| 240 | + version_1(String name, | |
| 241 | + String address), | |
| 242 | + version_2(String name, | |
| 243 | + String address, | |
| 244 | + Int32 age). | |
| 245 | + | |
| 246 | + Important notice: When a change intervenes in the type of rows of the table, the | |
| 247 | + alternative representing the new type of rows must be added at the end of the type | |
| 248 | + 'HClient' (or any other instance of '$HRow'). This is because in serialized data the | |
| 249 | + alternative names are lost, and replaced by their number in the list of | |
| 250 | + alternatives. Also notice that another method will be required if you create more than | |
| 251 | + 256 versions. | |
| 252 | + | |
| 253 | + The type 'Client' must also be changed in order to reflect the new format: | |
| 254 | + | |
| 255 | + type Client: | |
| 256 | + client(String name, | |
| 257 | + String address, | |
| 258 | + Int32 age). | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + --- Step 3: | |
| 264 | + | |
| 265 | + Now, we need 'conversion' functions in both directions between 'Client' and | |
| 266 | + 'HClient'. Presisely, we need the functions: | |
| 267 | + | |
| 268 | + (HClient -> Client)update | |
| 269 | + (Client -> HClient)store | |
| 270 | + | |
| 271 | + The function 'update' gets an 'historical' row (hence of type 'HClient') and must | |
| 272 | + transform it into a row in the current format. In our example, it could be: | |
| 273 | + | |
| 274 | + define Client | |
| 275 | + update | |
| 276 | + ( | |
| 277 | + HClient hc | |
| 278 | + ) = | |
| 279 | + if hc is | |
| 280 | + { | |
| 281 | + version_1(name,addr) then client(name,addr,0), | |
| 282 | + version_2(name,addr,age) then client(name,addr,age) | |
| 283 | + }. | |
| 284 | + | |
| 285 | + Of course, in the case of a row in the old format (version_1), we need a default value | |
| 286 | + for the age. We have chosen 0 in the example, but you may choose anything. In any | |
| 287 | + traditional data base system, when you add a column to a table, you need to fill this | |
| 288 | + column with a default value, even if this default value is 'NULL' (not filled at all). | |
| 289 | + | |
| 290 | + The other function does not require default values in principle, because it is mainly a | |
| 291 | + conversion between the current version and the latest one (i.e. essentially the same | |
| 292 | + one): | |
| 293 | + | |
| 294 | + define HClient | |
| 295 | + store | |
| 296 | + ( | |
| 297 | + Client c | |
| 298 | + ) = | |
| 299 | + if c is client(name,addr,age) then version_2(name,addr,age). | |
| 300 | + | |
| 301 | + | |
| 302 | + The type used for storing the data on the disk is always 'HClient' (hence the name of | |
| 303 | + the function 'store'), and according to the above function they are stored as | |
| 304 | + 'version_2(...)'. The type 'Client' is used only internally. This is required for | |
| 305 | + being able of handling file containing different versions of the tables. | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + *** (5) Row identifiers. | |
| 311 | + | |
| 312 | + The system generates an identifier for each newly created row in a table. It is | |
| 313 | + warranted that not two rows in the same table can have the same row identifier. Row | |
| 314 | + identifiers are of type 'DBRowId($Row)' (an opaque type scheme). | |
| 315 | + | |
| 316 | +public type DBRowId($Row):... | |
| 317 | + | |
| 318 | + (where '$Row' is the type of rows of the table). It is possible to use it as a | |
| 319 | + component in the type of rows in another table. This is how you can create 'links' | |
| 320 | + between tables. | |
| 321 | + | |
| 322 | + The type scheme 'DBRowId' should be considered as absolutely opaque. The author | |
| 323 | + reserves the possibility of modifying this type in the future. Hence, use only the | |
| 324 | + public interface for manipulating data of this type. | |
| 325 | + | |
| 326 | + It would have been possible to define the type 'DBRowId' without the parameter, but in | |
| 327 | + this case, identifiers corresponding to tables of different types could not be | |
| 328 | + distinguished by the compiler. The role of the parameter '$Row' is to identify the | |
| 329 | + type of the table to which the identifier refers. Introducing this parameter enhances | |
| 330 | + the security because it forbids the use of a row identifier with a table to which it | |
| 331 | + cannot actually apply. | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + *** (6) Adding rows to a table. | |
| 337 | + | |
| 338 | + Adding rows to a table is performed by the following function: | |
| 339 | + | |
| 340 | +public define Result(DBError,List(DBRowId($Row))) | |
| 341 | + add_rows | |
| 342 | + ( | |
| 343 | + DB($MY_DB) the_data_base, | |
| 344 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 345 | + List($Row) new_rows | |
| 346 | + ). | |
| 347 | + | |
| 348 | + For example, you may write: | |
| 349 | + | |
| 350 | + add_rows(my_data_base,clients,[row1,row2,row3]) | |
| 351 | + | |
| 352 | + where 'row1','row2' and 'row3' are of type 'Client'. The function returns (if no error | |
| 353 | + occurs) the list of the row identifiers of the newly created rows. | |
| 354 | + | |
| 355 | + The following variant is more convenient for adding just one row. | |
| 356 | + | |
| 357 | +public define Result(DBError,DBRowId($Row)) | |
| 358 | + add_row | |
| 359 | + ( | |
| 360 | + DB($MY_DB) the_data_base, | |
| 361 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 362 | + $Row new_row | |
| 363 | + ). | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + *** (7) Getting rows from a table. | |
| 369 | + | |
| 370 | + In order to get rows from a table, you have two methods: | |
| 371 | + | |
| 372 | + (1) you know the row identifiers of the rows you want, | |
| 373 | + (2) you want to get all rows satisfying some condition. | |
| 374 | + | |
| 375 | + You get rows in the form of: | |
| 376 | + | |
| 377 | +public type DBRow($Row): | |
| 378 | + dbrow(DBRowId($Row) row_id, | |
| 379 | + Int32 version, | |
| 380 | + $Row row). | |
| 381 | + | |
| 382 | + A datum of type DBRow($Row) contains the identifier of the row, a version number and | |
| 383 | + the row itself. The version number is 0 when the row is created (by 'add_row' or | |
| 384 | + 'add_rows' above) and is incremented by 1 each time the row is updated. This may be | |
| 385 | + used to detect the fact that the row has been modified between two operations. | |
| 386 | + | |
| 387 | +public define Result(DBError,DBRow($Row)) | |
| 388 | + get_row | |
| 389 | + ( | |
| 390 | + DB($MY_DB) the_data_base, | |
| 391 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 392 | + DBRowId($Row) row_id | |
| 393 | + ). | |
| 394 | + | |
| 395 | + If no error occurs, the function returns the wanted row. The next one can be used for | |
| 396 | + getting several rows. | |
| 397 | + | |
| 398 | +public define Result(DBError,List(DBRow($Row))) | |
| 399 | + get_rows | |
| 400 | + ( | |
| 401 | + DB($MY_DB) the_data_base, | |
| 402 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 403 | + List(DBRowId($Row)) row_ids | |
| 404 | + ). | |
| 405 | + | |
| 406 | +public define Result(DBError,List(DBRow($Row))) | |
| 407 | + get_rows | |
| 408 | + ( | |
| 409 | + DB($MY_DB) the_data_base, | |
| 410 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 411 | + $Row -> Bool which | |
| 412 | + ). | |
| 413 | + | |
| 414 | + This function returns the list of all rows from the table which satisfy the given | |
| 415 | + condition 'which'. | |
| 416 | + | |
| 417 | + Now, the test 'which' may also be performed on the complete row: | |
| 418 | + | |
| 419 | +public define Result(DBError,List(DBRow($Row))) | |
| 420 | + get_rows | |
| 421 | + ( | |
| 422 | + DB($MY_DB) the_data_base, | |
| 423 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 424 | + DBRow($Row) -> Bool which | |
| 425 | + ). | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + *** (8) Testing a number of rows. | |
| 432 | + | |
| 433 | + It may be useful to get the number of rows satisfying some condition in a table. It may | |
| 434 | + also be useful to know if a table contains more rows satisfying a condition than a | |
| 435 | + given number. | |
| 436 | + | |
| 437 | +public define Result(DBError,Int32) | |
| 438 | + get_number_of_rows | |
| 439 | + ( | |
| 440 | + DB($MY_DB) the_data_base, | |
| 441 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 442 | + DBRow($Row) -> Bool which | |
| 443 | + ). | |
| 444 | + | |
| 445 | + This function returns the number of rows satisfying the condition 'which'. | |
| 446 | + | |
| 447 | +public define Result(DBError,Bool) | |
| 448 | + has_more_rows_than | |
| 449 | + ( | |
| 450 | + DB($MY_DB) the_data_base, | |
| 451 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 452 | + DBRow($Row) -> Bool which, | |
| 453 | + Int32 n | |
| 454 | + ). | |
| 455 | + | |
| 456 | + This function returns 'ok(true)' if the table has strictly more than 'n' rows satifying | |
| 457 | + the condition, 'ok(false)' if it has at most 'n' rows satisfying the condition. | |
| 458 | + | |
| 459 | + Note: of course, these functions could be simulated using 'get_rows', but they may be | |
| 460 | + much more efficient, especially the last one when 'n' is much less than the number of | |
| 461 | + rows satisfying the condition, because it does not need to examine the whole table. | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + *** (9) Updating rows in a table. | |
| 468 | + | |
| 469 | + Updating rows in a table is generally the consequence of a previous reading of these | |
| 470 | + rows. Indeed, interactive programs will first show the row to be updated to a human | |
| 471 | + user (phase 1). The user is supposed to modify the data by hand. When the data are | |
| 472 | + modified, they may be put in the table in order to replace the previous values (phase | |
| 473 | + 2). | |
| 474 | + | |
| 475 | + This makes a problem because, the same data may have been modified by another human | |
| 476 | + user (or in some automatic way) in the meantime (i.e. between phase 1 and phase 2). | |
| 477 | + Hence, phase 2 should perhaps not be performed if the data have been modified in the | |
| 478 | + meantime. For this reason, when you want to update one or several rows in a table, you | |
| 479 | + do not provide the new values, but a function (denoted 'how' below) of type: | |
| 480 | + | |
| 481 | + DBRow($Row) -> Maybe($Row) | |
| 482 | + | |
| 483 | + This function is supposed to remember the version number of the row got during phase 1. | |
| 484 | + It receives as its argument the new row as it stands in the data base when phase 2 | |
| 485 | + begins. It should compare the version number with the one it remembers and decide if | |
| 486 | + the row must be updated or not. If the row must not be updated, the function 'how' | |
| 487 | + must return 'failure'. If on the contrary, the row must be updated, it must return the | |
| 488 | + value 'success(r)', where 'r' is the new value of the row. | |
| 489 | + | |
| 490 | + Now, if no error occurs, the 'update_row' function returns a datum of type: | |
| 491 | + | |
| 492 | +public type DBUpdateResult($Row): | |
| 493 | + not_updated (DBRow($Row) the_row), | |
| 494 | + updated (DBRow($Row) the_row). | |
| 495 | + | |
| 496 | + i.e. the result is either 'not_updated(r)' or 'updated(r)'. It is 'not_updated(r)' | |
| 497 | + when the row has not been updated, i.e. when the 'how' function has returned | |
| 498 | + 'failure', and it is 'updated(r)' if the row has been updated. In both cases, 'r' is | |
| 499 | + the new current value of the row as recorded in the table. | |
| 500 | + | |
| 501 | + Again, you may just want to update the row(s) the id(s) of which you have at hand, or | |
| 502 | + update all rows satisfying some condition. | |
| 503 | + | |
| 504 | +public define Result(DBError,DBUpdateResult($Row)) | |
| 505 | + update_row | |
| 506 | + ( | |
| 507 | + DB($MY_DB) the_data_base, | |
| 508 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 509 | + DBRowId($Row) row_id, | |
| 510 | + DBRow($Row) -> Maybe($Row) how | |
| 511 | + ). | |
| 512 | + | |
| 513 | +public define Result(DBError,List(DBUpdateResult($Row))) | |
| 514 | + update_rows | |
| 515 | + ( | |
| 516 | + DB($MY_DB) the_data_base, | |
| 517 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 518 | + List(DBRowId($Row)) row_ids, | |
| 519 | + DBRow($Row) -> Maybe($Row) how | |
| 520 | + ). | |
| 521 | + | |
| 522 | +public define Result(DBError,List(DBUpdateResult($Row))) | |
| 523 | + update_rows | |
| 524 | + ( | |
| 525 | + DB($MY_DB) the_data_base, | |
| 526 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 527 | + $Row -> Bool which, | |
| 528 | + DBRow($Row) -> Maybe($Row) how | |
| 529 | + ). | |
| 530 | + | |
| 531 | + For the last function 'update_rows', only the rows which satify the 'which' condition | |
| 532 | + are eventually updated. Of course the function returns a list of | |
| 533 | + 'DBUpdateResult($Row)', one for each row satisfying the 'which' condition. | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + *** (10) Deleting rows from a table. | |
| 539 | + | |
| 540 | +public define Result(DBError,$Row) | |
| 541 | + delete_row | |
| 542 | + ( | |
| 543 | + DB($MY_DB) the_data_base, | |
| 544 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 545 | + DBRowId($Row) row_id | |
| 546 | + ). | |
| 547 | + | |
| 548 | + If no error occurs, the row is deleted from the table, and returned by the function as | |
| 549 | + 'ok(row)'. You may forget this result, but you may also use it for archiving purpose | |
| 550 | + for example. | |
| 551 | + | |
| 552 | +public define Result(DBError,List($Row)) | |
| 553 | + delete_rows | |
| 554 | + ( | |
| 555 | + DB($MY_DB) the_data_base, | |
| 556 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 557 | + $Row -> Bool which | |
| 558 | + ). | |
| 559 | + | |
| 560 | + The rows satisfying the condition 'which' are deleted from the table. Of course, the | |
| 561 | + result, if no error occurs, is the list of the deleted rows. | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + *** (11) Multi-tables queries. | |
| 569 | + | |
| 570 | + The SQL language has an important feature which is the 'SELECT' command. We need | |
| 571 | + something analogous to the SQL query: | |
| 572 | + | |
| 573 | + SELECT column_1 ... column_k | |
| 574 | + FROM table_1 ... table_n | |
| 575 | + WHERE condition | |
| 576 | + | |
| 577 | + From a purely mathematical viewpoint, the above query means the following. Consider the | |
| 578 | + tables 'table_1' ... 'table_n' as relations between data types (i.e subsets of | |
| 579 | + cartesian products of data types, where each row of the table is precisely an element | |
| 580 | + of the relation, and each column is a data type). Make the cartesian products 'P' of | |
| 581 | + these relations. Then consider the subset of 'P' of those elements which satisfy the | |
| 582 | + 'condition'. Finally, apply the canonical projection towards the cartesian product of | |
| 583 | + the data types represented by 'column_1' ... 'column_k'. This is the result of the | |
| 584 | + query. | |
| 585 | + | |
| 586 | + Of course, the above description, even if probably the simplest possible one from a | |
| 587 | + theoretical viewpoint, is not efficient from the computational viewpoint. This is | |
| 588 | + mainly because the cartesian product of the relations 'table_1' ... 'table_n' may be | |
| 589 | + very big. This big product is first reduced by applying the condition, and further | |
| 590 | + reduced by the canonical projection. The question is how can we do for computing | |
| 591 | + without these big intermediate data. | |
| 592 | + | |
| 593 | + Usual data bases first optimize the query before it is executed. With Anubis, we cannot | |
| 594 | + optimize the query, except if it is given in a symbolic form. This is not the way we | |
| 595 | + have chosen, at least for the time being. Actually, combining the advantages of Anubis | |
| 596 | + (essentially the security provided by the strong typing mecanism), and the flexibility | |
| 597 | + of usual data bases could be realized only with a more elaborate version of Anubis, | |
| 598 | + including meta-programming, and maybe another virtual machine able to optimize on the | |
| 599 | + fly. All these new features are part of the Anubis2/Paradize project. | |
| 600 | + | |
| 601 | + For the time being, we content ourself with the following recursive querying | |
| 602 | + mecanism. Actually, the recursion is on the number of tables concerned by the query. | |
| 603 | + | |
| 604 | +public define List($Out) | |
| 605 | + query | |
| 606 | + ( | |
| 607 | + DB($MY_DB) the_data_base, | |
| 608 | + $MY_DB -> DBTable($Row,$HRow) the_first_table, | |
| 609 | + DBRow($Row) -> Bool the_first_condition, | |
| 610 | + (DBRow($Row),$In) -> $Out the_first_selection, | |
| 611 | + DBRow($Row) -> List($In) the_subquery | |
| 612 | + ). | |
| 613 | + | |
| 614 | + The parameter '$Row' represents the type of the rows of the first table (we assume | |
| 615 | + there is at least one table concerned by the query). This table (the first table) will | |
| 616 | + be looked at first, and only the rows satisfying the condition 'the_first_condition' | |
| 617 | + are considered. For each such row of the first table, a subquery ('the_subquery') is | |
| 618 | + executed. Notice that the subquery takes that row as an argument. The subquery | |
| 619 | + concernes only the remaining tables (i.e. all the tables concerned by the original | |
| 620 | + query, except the first one). It returns a list of results of type 'List($In)'. Now, | |
| 621 | + the row of the first table is paired to each element of this list, and the projection | |
| 622 | + 'the_first_projection' is applied. This yields a list of type 'List($Out)', one for | |
| 623 | + each selected row of the first table. Finally, all these lists are merged together (and | |
| 624 | + repetitions are removed). | |
| 625 | + | |
| 626 | + Well, an example is probably required. Here it is. We consider the tables 'clients', | |
| 627 | + 'commands' and 'products' , whose types of rows are respectively: 'Client', 'Command' | |
| 628 | + and 'Product'. It is assumed that the type 'Command' has (among others) the | |
| 629 | + components: | |
| 630 | + | |
| 631 | + client_id of type DBRowId(Client) | |
| 632 | + product_id of type DBRowId(Product) | |
| 633 | + | |
| 634 | + so that to each command (probably only a 'command item') corresponds a client and a | |
| 635 | + product. Also, the types 'Client' and 'Product' have a component 'name' (of type | |
| 636 | + String), giving the name of the client or of the product. The type 'Client' also has a | |
| 637 | + component 'country'. | |
| 638 | + | |
| 639 | + We want to get the list of all clients living in France, who have bought the product | |
| 640 | + named "Yoyo". Here is the query (which returns a list of type 'List(String)'): | |
| 641 | + | |
| 642 | + query(my_data_base, | |
| 643 | + clients, // begin with the table 'clients' | |
| 644 | + (DBRow(Client) clt) |-> // consider only French clients | |
| 645 | + country(row(clt)) = "France", | |
| 646 | + (DBRow(Client) clt, One u) |-> // keep only the name of the client | |
| 647 | + name(row(clt)), | |
| 648 | + (DBRow(Client) clt) |-> // the subquery for this client 'clt' | |
| 649 | + query(my_data_base, | |
| 650 | + commands, // continue with the table 'commands' | |
| 651 | + (DBRow(Command) cmd) |-> | |
| 652 | + row_id(clt) = client_id(row(cmd)), | |
| 653 | + (DBRow(Command) cmd, One u) |-> u, // do not keep anything from 'commands' | |
| 654 | + (DBRow(Command) cmd) |-> | |
| 655 | + query(my_data_base, | |
| 656 | + products, | |
| 657 | + (DBRow(Product) prd) |-> | |
| 658 | + row_id(prd) = product_id(cmd) & | |
| 659 | + name(row(prd)) = "Yoyo", | |
| 660 | + (DBRow(Product) prd, One u) |-> u, | |
| 661 | + (DBRow(Product) prd) |-> unique))) | |
| 662 | + | |
| 663 | + Of course, this is more complicated than: | |
| 664 | + | |
| 665 | + SELECT clients.name | |
| 666 | + FROM clients, commands_2005, products | |
| 667 | + WHERE clients.id = commands_2005.client_id AND | |
| 668 | + commands_2005.product_id = products.id AND | |
| 669 | + products.name = "Yoyo" | |
| 670 | + | |
| 671 | + but meta-programming could automatically transform the later into the former (in the | |
| 672 | + future). | |
| 673 | + | |
| 674 | + Now, the query may also be more efficient (computed faster) if the tables are put in a | |
| 675 | + different order. For example, we may consider the following equivalent query (with the | |
| 676 | + tables in reverse order): | |
| 677 | + | |
| 678 | + query(my_data_base, | |
| 679 | + products, | |
| 680 | + (DBRow(Product) prd) |-> name(row(prd)) = "Yoyo", | |
| 681 | + (DBRow(Product) prd, String cltname) |-> cltname, | |
| 682 | + (DBRow(Product) prd) |-> | |
| 683 | + query(my_data_base, | |
| 684 | + commands, | |
| 685 | + (DBRow(Command) cmd) |-> | |
| 686 | + row_id(prd) = product_id(row(cmd)), | |
| 687 | + (DBRow(Command) cmd, String cltname) |-> cltname, | |
| 688 | + (DBRow(Command) cmd) |-> | |
| 689 | + query(my_data_base, | |
| 690 | + clients, | |
| 691 | + (DBRow(Client) clt) |-> | |
| 692 | + country(row(clt)) = "France" & | |
| 693 | + row_id(clt) = client_id(row(cmd)), | |
| 694 | + (DBRow(Client) clt, One u) |-> name(row(clt)), | |
| 695 | + (DBRow(Client) clt) |-> unique))) | |
| 696 | + | |
| 697 | + This one may be more efficient than the first one. The order into which the tables are | |
| 698 | + looked up may be important for performances. | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + *** (12) Using it with 'web/making_a_web_site.anubis'. | |
| 705 | + | |
| 706 | + You may want to use this data base manager in conjunction with our web site making | |
| 707 | + method. You should proceed as follows in order to start the data base and the web | |
| 708 | + site. | |
| 709 | + | |
| 710 | + You should not define the actions of your web site at the top level, like this: | |
| 711 | + | |
| 712 | + define State | |
| 713 | + act_do_something | |
| 714 | + ( | |
| 715 | + HTTP_Info http_info, | |
| 716 | + List(Web_arg) lwa, | |
| 717 | + State previous | |
| 718 | + )= ... | |
| 719 | + | |
| 720 | + What you should do (for each action) is defining a function which constructs the above | |
| 721 | + one using the data base, like this: | |
| 722 | + | |
| 723 | + define (HTTP_Info http_info, | |
| 724 | + List(Web_arg) lwa, | |
| 725 | + State previous) -> State | |
| 726 | + make_act_do_something | |
| 727 | + ( | |
| 728 | + DB(MY_DB) my_data_base | |
| 729 | + ) = | |
| 730 | + (HTTP_Info http_info, | |
| 731 | + List(Web_arg) lwa, | |
| 732 | + State previous) |-> | |
| 733 | + ... here the body of the function may use the data base ... | |
| 734 | + | |
| 735 | + | |
| 736 | + Now, when defining the list of all actions of your web site, you need to provide the | |
| 737 | + data base: | |
| 738 | + | |
| 739 | + define List(Web_Action(State)) | |
| 740 | + make_actions | |
| 741 | + ( | |
| 742 | + DB(MY_DB) my_data_base | |
| 743 | + ) = | |
| 744 | + [ | |
| 745 | + http_action("do_something", | |
| 746 | + make_allow_something(my_data_base), | |
| 747 | + make_act_do_something(my_data_base)), | |
| 748 | + ...etc... | |
| 749 | + ]. | |
| 750 | + | |
| 751 | + | |
| 752 | + Finally, when you start the whole stuff, do as follows. First start the data base: | |
| 753 | + | |
| 754 | + with my_data_base = (DB(MY_DB))init_db(...), | |
| 755 | + | |
| 756 | + Next, construct the list of actions of the web site: | |
| 757 | + | |
| 758 | + with actions = make_actions(my_data_base), | |
| 759 | + | |
| 760 | + finally, start the web sites: | |
| 761 | + | |
| 762 | + start_web_sites | |
| 763 | + (0, | |
| 764 | + 80, | |
| 765 | + 443, | |
| 766 | + "georges", | |
| 767 | + [ | |
| 768 | + make_web_site_description | |
| 769 | + (common_name, | |
| 770 | + default_state, | |
| 771 | + actions, // here the actions constructed above are used (hence the data base) | |
| 772 | + compute_page, | |
| 773 | + ... etc...) | |
| 774 | + ]) | |
| 775 | + | |
| 776 | + Of course, if you have several web sites, you may also have several data bases, but the | |
| 777 | + method is essentially the same one. You may also need several data bases for a single | |
| 778 | + web site. | |
| 779 | + | |
| 780 | + Recall that the function 'compute_page' should perhaps not use the data base, because | |
| 781 | + otherwise, the page sent to the client may be incoherent with the state saved on the | |
| 782 | + server's disk. | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + --- That's all for the public part ! -------------------------------------------------- | |
| 790 | + | |
| 791 | + | |
| 792 | + Row identifiers are just integers, but this may change in the future, because integers | |
| 793 | + may not be enough. | |
| 794 | + | |
| 795 | +public type DBRowId($Row): | |
| 796 | + dbrowid(Int32 index). | |
| 797 | + | |
| 798 | + When a table is loaded, a boolean variable 'changed' indicates if it has to be saved. A | |
| 799 | + integer variable contains the counter for creating identifiers for new rows. Another | |
| 800 | + variable contains the list of all loaded rows. | |
| 801 | + | |
| 802 | +type DBLoadedTable($Row,$HRow): | |
| 803 | + table(String table_name, | |
| 804 | + (DBRow($Row),DBRow($Row)) -> Bool compare, | |
| 805 | + $Row -> $HRow store, | |
| 806 | + Var(Bool) changed_v, | |
| 807 | + Var(Int32) counter_v, | |
| 808 | + Var(List(DBRow($Row))) rows_v). | |
| 809 | + | |
| 810 | + Of course, tables are not saved on disk as 'DBLoadedTable($Row,$HRow)' because variable | |
| 811 | + types (and functional types for the time being) are not serializable, and also because | |
| 812 | + data of type '$Row' are not saved on the disk. Tables are saved as data of type | |
| 813 | + 'DBSavedTable($HRow)'. | |
| 814 | + | |
| 815 | +type DBSavedTable($HRow): | |
| 816 | + myversion_1(Int32 counter, | |
| 817 | + List(DBRow($HRow)) rows). | |
| 818 | + | |
| 819 | + | |
| 820 | + We will have to compare the rows of a loaded table. The function able to compare loaded | |
| 821 | + rows must be constructed from the function comparing nude rows. This is the job of the | |
| 822 | + following 'function maker': | |
| 823 | + | |
| 824 | +define (DBRow($Row),DBRow($Row)) -> Bool | |
| 825 | + dbrow | |
| 826 | + ( | |
| 827 | + ($Row,$Row) -> Bool compare | |
| 828 | + ) = | |
| 829 | + (DBRow($Row) dbr1, DBRow($Row) dbr2) |-> | |
| 830 | + if dbr1 is dbrow(id1,v1,r1) then | |
| 831 | + if dbr2 is dbrow(id2,v2,r2) then | |
| 832 | + compare(r1,r2). | |
| 833 | + | |
| 834 | + | |
| 835 | + Tables need to be installed (which involves installing all rows). | |
| 836 | + | |
| 837 | +read tools/basis.anubis required for 'qsort' | |
| 838 | + | |
| 839 | +define DBLoadedTable($Row,$HRow) | |
| 840 | + install_table | |
| 841 | + ( | |
| 842 | + String table_name, | |
| 843 | + ($Row,$Row) -> Bool compare, | |
| 844 | + $HRow -> $Row update, | |
| 845 | + $Row -> $HRow store, | |
| 846 | + DBSavedTable($HRow) st | |
| 847 | + ) = | |
| 848 | + if st is | |
| 849 | + { | |
| 850 | + myversion_1(count,rows) then | |
| 851 | + with db_compare = dbrow(compare), | |
| 852 | + updated_rows = map((DBRow($HRow) dbr) |-> | |
| 853 | + if dbr is dbrow(row_id,version,row) | |
| 854 | + then if row_id is dbrowid(i) | |
| 855 | + then dbrow(dbrowid(i),version,update(row)), | |
| 856 | + rows), | |
| 857 | + table(table_name, | |
| 858 | + db_compare, | |
| 859 | + store, | |
| 860 | + var(false), | |
| 861 | + var(count), | |
| 862 | + var(qsort(updated_rows,db_compare))) | |
| 863 | + }. | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + Saving a table on the disk (the table also persists in memory). | |
| 868 | + | |
| 869 | +define Result(DBError,One) | |
| 870 | + save_table | |
| 871 | + ( | |
| 872 | + String dbdir, | |
| 873 | + DBLoadedTable($Row,$HRow) t | |
| 874 | + ) = | |
| 875 | + if t is table(table_name,compare,store,changed_v,counter_v,rows_v) then | |
| 876 | + with path = dbdir+"/"+table_name, | |
| 877 | + if protect save((DBSavedTable($HRow))myversion_1(*counter_v, | |
| 878 | + map((DBRow($Row) dbr) |-> | |
| 879 | + if dbr is dbrow(row_id,version,row) then | |
| 880 | + if row_id is dbrowid(i) then | |
| 881 | + dbrow(dbrowid(i),version,store(row)), | |
| 882 | + *rows_v)), | |
| 883 | + path) is | |
| 884 | + { | |
| 885 | + cannot_open_file then error(cannot_open_file(path)), | |
| 886 | + write_error then error(cannot_write_file(path)) | |
| 887 | + ok then changed_v <- false; ok(unique) | |
| 888 | + }. | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + Tables in the data base are either loaded or not. | |
| 893 | + | |
| 894 | +type DBTableState($Row,$HRow): | |
| 895 | + not_loaded (String table_name, | |
| 896 | + ($Row,$Row) -> Bool compare, | |
| 897 | + $HRow -> $Row update, | |
| 898 | + $Row -> $HRow store), | |
| 899 | + loaded (DBLoadedTable($Row,$HRow)). | |
| 900 | + | |
| 901 | + Now a table is just a variable containing either a non loaded table or a loaded table. | |
| 902 | + | |
| 903 | +public type DBTable($Row,$HRow): | |
| 904 | + db_table(Var(DBTableState($Row,$HRow))). | |
| 905 | + | |
| 906 | + | |
| 907 | + The data base itself is made of the directory path for table files, and the set of | |
| 908 | + tables (loaded or not). | |
| 909 | + | |
| 910 | +public type DB($MY_DB): | |
| 911 | + db(String directory, | |
| 912 | + $MY_DB tables). | |
| 913 | + | |
| 914 | + | |
| 915 | +public define DB($MY_DB) | |
| 916 | + init_db | |
| 917 | + ( | |
| 918 | + String data_base_directory, | |
| 919 | + $MY_DB tables | |
| 920 | + ) = | |
| 921 | + forget(make_directory(data_base_directory,default_directory_mode)); | |
| 922 | + db(data_base_directory,tables). | |
| 923 | + | |
| 924 | +public define DBTable($Row,$HRow) | |
| 925 | + init_dbtable | |
| 926 | + ( | |
| 927 | + String table_name, | |
| 928 | + ($Row,$Row) -> Bool compare, | |
| 929 | + $HRow -> $Row update, | |
| 930 | + $Row -> $HRow store | |
| 931 | + ) = | |
| 932 | + db_table(var(not_loaded(table_name,compare,update,store))). | |
| 933 | + | |
| 934 | + | |
| 935 | + Given a data base and a table in the form of a destructor of type MY_DB, the next | |
| 936 | + function returns the table in the form of a loaded table. | |
| 937 | + | |
| 938 | +define Result(DBError,DBLoadedTable($Row,$HRow)) | |
| 939 | + get_table | |
| 940 | + ( | |
| 941 | + DB($MY_DB) the_data_base, | |
| 942 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 943 | + ) = | |
| 944 | + if the_data_base is db(dbdir,my_db) then | |
| 945 | + if the_table(my_db) is db_table(table_v) then | |
| 946 | + if *table_v is | |
| 947 | + { | |
| 948 | + not_loaded(table_name,compare,update,store) then | |
| 949 | + with file_path = dbdir+"/"+table_name, | |
| 950 | + if (RetrieveResult(DBSavedTable($HRow)))retrieve(file_path) is | |
| 951 | + { | |
| 952 | + cannot_find_file then | |
| 953 | + with new_table = install_table(table_name,compare,update,store,myversion_1(0,[])), | |
| 954 | + table_v <- loaded(new_table); | |
| 955 | + ok(new_table), | |
| 956 | + | |
| 957 | + read_error then error(file_reading_problem(file_path)), | |
| 958 | + type_error then error(file_type_problem(file_path)), | |
| 959 | + ok(t) then | |
| 960 | + with new_table = install_table(table_name,compare,update,store,t), | |
| 961 | + table_v <- loaded(new_table); | |
| 962 | + ok(new_table) | |
| 963 | + }, | |
| 964 | + | |
| 965 | + loaded(t) then | |
| 966 | + ok(t) | |
| 967 | + }. | |
| 968 | + | |
| 969 | + | |
| 970 | + Inserting rows. The next function receives two lists (of the same type) which are both | |
| 971 | + already sorted. It inserts the elements of the first list at the right place in the | |
| 972 | + second list. | |
| 973 | + | |
| 974 | +define List($T) | |
| 975 | + insert // insert elements of l1 into l2 | |
| 976 | + ( | |
| 977 | + List($T) l1, | |
| 978 | + List($T) l2, | |
| 979 | + ($T,$T) -> Bool less | |
| 980 | + ) = | |
| 981 | + if l1 is | |
| 982 | + { | |
| 983 | + [ ] then l2, | |
| 984 | + [h1 . t1] then | |
| 985 | + if l2 is | |
| 986 | + { | |
| 987 | + [ ] then l1, | |
| 988 | + [h2 . t2] then | |
| 989 | + if less(h1,h2) | |
| 990 | + then [h1 . insert(t1,l2,less)] | |
| 991 | + else [h2 . insert(l1,t2,less)] | |
| 992 | + } | |
| 993 | + }. | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + Adding rows. The table contains a list of 'DBRow($Row)' which is already sorted. The | |
| 998 | + new rows arrive as data of type '$Row', and need first to be sorted. Then they are | |
| 999 | + transformed into 'DBRow($Row)' and inserted in the table. Hence, we need to compare | |
| 1000 | + data of type 'DBRow($Row)'. | |
| 1001 | + | |
| 1002 | + The next function gets a list of nude rows (of type '$Row'), and transforms it into a | |
| 1003 | + list of loaded rows, creating a new identifier for each row. This function is run | |
| 1004 | + 'protected'. | |
| 1005 | + | |
| 1006 | +define DBRow($Row) | |
| 1007 | + load_row | |
| 1008 | + ( | |
| 1009 | + $Row row, | |
| 1010 | + Var(Int32) counter_v | |
| 1011 | + ) = | |
| 1012 | + protect | |
| 1013 | + with c1 = *counter_v, | |
| 1014 | + counter_v <- c1+1; | |
| 1015 | + dbrow(dbrowid(c1),0,row). | |
| 1016 | + | |
| 1017 | +define List(DBRow($Row)) | |
| 1018 | + load_rows | |
| 1019 | + ( | |
| 1020 | + List($Row) rows, | |
| 1021 | + Var(Int32) counter_v | |
| 1022 | + ) = | |
| 1023 | + map(($Row r) |-> load_row(r,counter_v), | |
| 1024 | + rows). | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + Finally, in order to add rows to a table, we have to load them (using 'load_rows' | |
| 1028 | + above), to sort them, and to insert them in the table. The table is subsequently | |
| 1029 | + saved. | |
| 1030 | + | |
| 1031 | +public define Result(DBError,List(DBRowId($Row))) | |
| 1032 | + add_rows | |
| 1033 | + ( | |
| 1034 | + DB($MY_DB) the_data_base, | |
| 1035 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1036 | + List($Row) new_rows | |
| 1037 | + ) = | |
| 1038 | + if get_table(the_data_base,the_table) is | |
| 1039 | + { | |
| 1040 | + error(msg) then error(msg), | |
| 1041 | + ok(loaded_table) then protect | |
| 1042 | + if loaded_table is table(table_name,compare,store,changed_v,counter_v,rows_v) then | |
| 1043 | + with new_loaded_rows = qsort(load_rows(new_rows,counter_v),compare), | |
| 1044 | + new_table_rows = insert(new_loaded_rows,*rows_v,compare), | |
| 1045 | + changed_v <- true; | |
| 1046 | + rows_v <- new_table_rows; | |
| 1047 | + if save_table(directory(the_data_base),loaded_table) is | |
| 1048 | + { | |
| 1049 | + error(msg) then error(msg), | |
| 1050 | + ok(_) then ok(map(row_id,new_loaded_rows)) | |
| 1051 | + } | |
| 1052 | + }. | |
| 1053 | + | |
| 1054 | + | |
| 1055 | +public define Result(DBError,DBRowId($Row)) | |
| 1056 | + add_row | |
| 1057 | + ( | |
| 1058 | + DB($MY_DB) the_data_base, | |
| 1059 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1060 | + $Row new_row | |
| 1061 | + ) = | |
| 1062 | + if get_table(the_data_base,the_table) is | |
| 1063 | + { | |
| 1064 | + error(msg) then error(msg), | |
| 1065 | + ok(loaded_table) then protect | |
| 1066 | + if loaded_table is table(table_name,compare,store,changed_v,counter_v,rows_v) then | |
| 1067 | + with new_loaded_row = load_row(new_row,counter_v), | |
| 1068 | + new_table_rows = insert([new_loaded_row],*rows_v,compare), | |
| 1069 | + changed_v <- true; | |
| 1070 | + rows_v <- new_table_rows; | |
| 1071 | + if save_table(directory(the_data_base),loaded_table) is | |
| 1072 | + { | |
| 1073 | + error(msg) then error(msg), | |
| 1074 | + ok(_) then ok(row_id(new_loaded_row)) | |
| 1075 | + } | |
| 1076 | + }. | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + Getting a row by its identifier. | |
| 1083 | + | |
| 1084 | +define Result(DBError,DBRow($Row)) | |
| 1085 | + get_row | |
| 1086 | + ( | |
| 1087 | + List(DBRow($Row)) rows, | |
| 1088 | + DBRowId($Row) row_id | |
| 1089 | + ) = | |
| 1090 | + if rows is | |
| 1091 | + { | |
| 1092 | + [ ] then error(record_not_found), | |
| 1093 | + [row1 . others] then if row1 is dbrow(id,ver,row) then | |
| 1094 | + if row_id = id | |
| 1095 | + then ok(row1) | |
| 1096 | + else get_row(others,row_id) | |
| 1097 | + }. | |
| 1098 | + | |
| 1099 | + | |
| 1100 | +public define Result(DBError,DBRow($Row)) | |
| 1101 | + get_row | |
| 1102 | + ( | |
| 1103 | + DB($MY_DB) the_data_base, | |
| 1104 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1105 | + DBRowId($Row) row_id | |
| 1106 | + ) = | |
| 1107 | + if get_table(the_data_base,the_table) is | |
| 1108 | + { | |
| 1109 | + error(msg) then error(msg), | |
| 1110 | + ok(loaded_table) then if loaded_table is | |
| 1111 | + table(table_name,compare,store,changed_v,counter_v,rows_v) then | |
| 1112 | + get_row(*rows_v,row_id) | |
| 1113 | + }. | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + Getting rows by their identifiers. | |
| 1118 | + | |
| 1119 | + | |
| 1120 | +define List($T) | |
| 1121 | + remove | |
| 1122 | + ( | |
| 1123 | + $T x, | |
| 1124 | + List($T) l | |
| 1125 | + ) = | |
| 1126 | + if l is | |
| 1127 | + { | |
| 1128 | + [ ] then [ ], | |
| 1129 | + [h . t] then | |
| 1130 | + if x = h | |
| 1131 | + then t | |
| 1132 | + else [h . remove(x,t)] | |
| 1133 | + }. | |
| 1134 | + | |
| 1135 | +define Result(DBError,List(DBRow($Row))) | |
| 1136 | + get_rows | |
| 1137 | + ( | |
| 1138 | + List(DBRow($Row)) rows, | |
| 1139 | + List(DBRowId($Row)) row_ids, | |
| 1140 | + List(DBRow($Row)) so_far | |
| 1141 | + ) = | |
| 1142 | + if rows is | |
| 1143 | + { | |
| 1144 | + [ ] then ok(reverse(so_far)), | |
| 1145 | + [row1 . others] then | |
| 1146 | + if row_ids is | |
| 1147 | + { | |
| 1148 | + [ ] then ok(reverse(so_far)), | |
| 1149 | + [_._] then | |
| 1150 | + if row1 is dbrow(id,_,_) then | |
| 1151 | + if member(row_ids,id) | |
| 1152 | + then get_rows(others,remove(id,row_ids),[row1 . so_far]) | |
| 1153 | + else get_rows(others,row_ids,so_far) | |
| 1154 | + } | |
| 1155 | + }. | |
| 1156 | + | |
| 1157 | +public define Result(DBError,List(DBRow($Row))) | |
| 1158 | + get_rows | |
| 1159 | + ( | |
| 1160 | + DB($MY_DB) the_data_base, | |
| 1161 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1162 | + List(DBRowId($Row)) row_ids | |
| 1163 | + ) = | |
| 1164 | + if get_table(the_data_base,the_table) is | |
| 1165 | + { | |
| 1166 | + error(msg) then error(msg), | |
| 1167 | + ok(loaded_table) then if loaded_table is | |
| 1168 | + table(table_name,compare,store,changed_v,counter_v,rows_v) then | |
| 1169 | + get_rows(*rows_v,row_ids,[]) | |
| 1170 | + }. | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + Getting rows satifying a condition. | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | +define Result(DBError,List(DBRow($Row))) | |
| 1180 | + get_rows | |
| 1181 | + ( | |
| 1182 | + List(DBRow($Row)) rows, | |
| 1183 | + DBRow($Row) -> Bool which, | |
| 1184 | + List(DBRow($Row)) so_far | |
| 1185 | + ) = | |
| 1186 | + if rows is | |
| 1187 | + { | |
| 1188 | + [ ] then ok(reverse(so_far)), | |
| 1189 | + [row1 . others] then | |
| 1190 | + if which(row1) | |
| 1191 | + then get_rows(others,which,[row1 . so_far]) | |
| 1192 | + else get_rows(others,which,so_far) | |
| 1193 | + }. | |
| 1194 | + | |
| 1195 | +public define Result(DBError,List(DBRow($Row))) | |
| 1196 | + get_rows | |
| 1197 | + ( | |
| 1198 | + DB($MY_DB) the_data_base, | |
| 1199 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1200 | + DBRow($Row) -> Bool which | |
| 1201 | + ) = | |
| 1202 | + if get_table(the_data_base,the_table) is | |
| 1203 | + { | |
| 1204 | + error(msg) then error(msg), | |
| 1205 | + ok(loaded_table) then if loaded_table is | |
| 1206 | + table(table_name,compare,store,changed_v,counter_v,rows_v) then | |
| 1207 | + get_rows(*rows_v,which,[]) | |
| 1208 | + }. | |
| 1209 | + | |
| 1210 | + | |
| 1211 | +public define Result(DBError,List(DBRow($Row))) | |
| 1212 | + get_rows | |
| 1213 | + ( | |
| 1214 | + DB($MY_DB) the_data_base, | |
| 1215 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1216 | + $Row -> Bool which | |
| 1217 | + ) = | |
| 1218 | + get_rows(the_data_base,the_table, | |
| 1219 | + (DBRow($Row) r) |-> which(row(r))). | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + Getting a number of rows. | |
| 1224 | + | |
| 1225 | +define Result(DBError,Int32) | |
| 1226 | + count_rows | |
| 1227 | + ( | |
| 1228 | + List(DBRow($Row)) rows, | |
| 1229 | + DBRow($Row) -> Bool which, | |
| 1230 | + Int32 so_far | |
| 1231 | + ) = | |
| 1232 | + if rows is | |
| 1233 | + { | |
| 1234 | + [ ] then ok(so_far), | |
| 1235 | + [h . t] then | |
| 1236 | + if which(h) | |
| 1237 | + then count_rows(t,which,so_far+1) | |
| 1238 | + else count_rows(t,which,so_far) | |
| 1239 | + }. | |
| 1240 | + | |
| 1241 | +public define Result(DBError,Int32) | |
| 1242 | + get_number_of_rows | |
| 1243 | + ( | |
| 1244 | + DB($MY_DB) the_data_base, | |
| 1245 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1246 | + DBRow($Row) -> Bool which | |
| 1247 | + ) = | |
| 1248 | + if get_table(the_data_base,the_table) is | |
| 1249 | + { | |
| 1250 | + error(msg) then error(msg), | |
| 1251 | + ok(loaded_table) then if loaded_table is | |
| 1252 | + table(table_name,compare,store,changed_v,counter_v,rows_v) then | |
| 1253 | + count_rows(*rows_v,which,0) | |
| 1254 | + }. | |
| 1255 | + | |
| 1256 | + | |
| 1257 | +define Result(DBError,Bool) | |
| 1258 | + has_more_rows_than | |
| 1259 | + ( | |
| 1260 | + List(DBRow($Row)) rows, | |
| 1261 | + DBRow($Row) -> Bool which, | |
| 1262 | + Int32 n | |
| 1263 | + ) = | |
| 1264 | + if rows is | |
| 1265 | + { | |
| 1266 | + [ ] then ok(false), | |
| 1267 | + [h . t] then | |
| 1268 | + if which(h) | |
| 1269 | + then if n =< 0 | |
| 1270 | + then ok(true) | |
| 1271 | + else has_more_rows_than(t,which,n-1) | |
| 1272 | + else has_more_rows_than(t,which,n) | |
| 1273 | + }. | |
| 1274 | + | |
| 1275 | +public define Result(DBError,Bool) | |
| 1276 | + has_more_rows_than | |
| 1277 | + ( | |
| 1278 | + DB($MY_DB) the_data_base, | |
| 1279 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1280 | + DBRow($Row) -> Bool which, | |
| 1281 | + Int32 n | |
| 1282 | + ) = | |
| 1283 | + if get_table(the_data_base,the_table) is | |
| 1284 | + { | |
| 1285 | + error(msg) then error(msg), | |
| 1286 | + ok(loaded_table) then if loaded_table is | |
| 1287 | + table(table_name,compare,store,changed_v,counter_v,rows_v) then | |
| 1288 | + has_more_rows_than(*rows_v,which,n) | |
| 1289 | + }. | |
| 1290 | + | |
| 1291 | + | |
| 1292 | + | |
| 1293 | + | |
| 1294 | + Updating rows. Rows which satisfy the 'which' condition are first extracted from the | |
| 1295 | + table and updated by 'how'. Then the list of updated rows is sorted, and reinserted | |
| 1296 | + into the table. Subsequently, the table is saved. | |
| 1297 | + | |
| 1298 | + The next function receives a list and a test applicable to elements of that list. It | |
| 1299 | + separates the list into the list of those elements which satisfy the test, and the list | |
| 1300 | + of those element which do not satisfy the test. | |
| 1301 | + | |
| 1302 | +define ( | |
| 1303 | + List($T), // those satisfying the test | |
| 1304 | + List($T) // those not satisfying the test | |
| 1305 | + ) | |
| 1306 | + separ_list | |
| 1307 | + ( | |
| 1308 | + List($T) l, | |
| 1309 | + $T -> Bool test | |
| 1310 | + ) = | |
| 1311 | + if l is | |
| 1312 | + { | |
| 1313 | + [ ] then ([],[]), | |
| 1314 | + [h . t] then if separ_list(t,test) is (others_yes,others_no) then | |
| 1315 | + if test(h) | |
| 1316 | + then ([h . others_yes],others_no) | |
| 1317 | + else (others_yes,[h . others_no]) | |
| 1318 | + }. | |
| 1319 | + | |
| 1320 | + The same one for separating only one element. | |
| 1321 | + | |
| 1322 | +define ( | |
| 1323 | + Maybe($T), // separated element | |
| 1324 | + List($T) // other elements | |
| 1325 | + ) | |
| 1326 | + separ_element | |
| 1327 | + ( | |
| 1328 | + List($T) l, | |
| 1329 | + $T -> Bool test | |
| 1330 | + ) = | |
| 1331 | + if l is | |
| 1332 | + { | |
| 1333 | + [ ] then (failure,[]), | |
| 1334 | + [h . t] then | |
| 1335 | + if test(h) | |
| 1336 | + then (success(h),t) | |
| 1337 | + else if separ_element(t,test) is (mb_e,t1) then (mb_e,[h . t1]) | |
| 1338 | + }. | |
| 1339 | + | |
| 1340 | + | |
| 1341 | + | |
| 1342 | + | |
| 1343 | +public define Result(DBError,DBUpdateResult($Row)) | |
| 1344 | + update_row | |
| 1345 | + ( | |
| 1346 | + DB($MY_DB) the_data_base, | |
| 1347 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1348 | + DBRowId($Row) row_id, | |
| 1349 | + DBRow($Row) -> Maybe($Row) how | |
| 1350 | + ) = | |
| 1351 | + if get_table(the_data_base,the_table) is | |
| 1352 | + { | |
| 1353 | + error(msg) then error(msg), | |
| 1354 | + ok(loaded_table) then if loaded_table is | |
| 1355 | + table(table_name,compare,store,changed_v,counter_v,rows_v) then protect | |
| 1356 | + changed_v <- true; | |
| 1357 | + if separ_element(*rows_v,(DBRow($Row) r) |-> | |
| 1358 | + if r is dbrow(rid,ver,row) then rid = row_id) | |
| 1359 | + is (mb_extracted_row,other_rows) then | |
| 1360 | + if mb_extracted_row is | |
| 1361 | + { | |
| 1362 | + failure then error(record_not_found), | |
| 1363 | + success(idrow) then | |
| 1364 | + if how(idrow) is | |
| 1365 | + { | |
| 1366 | + failure then ok(not_updated(idrow)), | |
| 1367 | + success(new_row) then | |
| 1368 | + with new_idrow = dbrow(row_id,version(idrow)+1,new_row), | |
| 1369 | + rows_v <- insert([new_idrow],other_rows,compare); | |
| 1370 | + if save_table(directory(the_data_base),loaded_table) is | |
| 1371 | + { | |
| 1372 | + error(msg) then error(msg), | |
| 1373 | + ok(_) then ok(updated(new_idrow)) | |
| 1374 | + } | |
| 1375 | + } | |
| 1376 | + } | |
| 1377 | + }. | |
| 1378 | + | |
| 1379 | + | |
| 1380 | +public define Result(DBError,List(DBUpdateResult($Row))) | |
| 1381 | + update_rows | |
| 1382 | + ( | |
| 1383 | + DB($MY_DB) the_data_base, | |
| 1384 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1385 | + List(DBRowId($Row)) row_ids, | |
| 1386 | + DBRow($Row) -> Maybe($Row) how | |
| 1387 | + ) = | |
| 1388 | + if get_table(the_data_base,the_table) is | |
| 1389 | + { | |
| 1390 | + error(msg) then error(msg), | |
| 1391 | + ok(loaded_table) then if loaded_table is | |
| 1392 | + table(table_name,compare,store,changed_v,counter_v,rows_v) then protect | |
| 1393 | + changed_v <- true; | |
| 1394 | + if separ_list(*rows_v,(DBRow($Row) r) |-> | |
| 1395 | + if r is dbrow(row_id,ver,row) then member(row_ids,row_id)) | |
| 1396 | + is (extracted_rows,other_rows) then | |
| 1397 | + with updated_rows = qsort(map((DBRow($Row) r) |-> | |
| 1398 | + if how(r) is | |
| 1399 | + { | |
| 1400 | + failure then not_updated(r) | |
| 1401 | + success(new_r) then updated(dbrow(row_id(r),version(r)+1,new_r)) | |
| 1402 | + }, | |
| 1403 | + extracted_rows), | |
| 1404 | + (DBUpdateResult($Row) ur1, DBUpdateResult($Row) ur2) |-> | |
| 1405 | + compare(the_row(ur1),the_row(ur2))), | |
| 1406 | + rows_v <- insert(map(the_row,updated_rows),other_rows,compare); | |
| 1407 | + if save_table(directory(the_data_base),loaded_table) is | |
| 1408 | + { | |
| 1409 | + error(msg) then error(msg), | |
| 1410 | + ok(_) then ok(updated_rows) | |
| 1411 | + } | |
| 1412 | + }. | |
| 1413 | + | |
| 1414 | + | |
| 1415 | +public define Result(DBError,List(DBUpdateResult($Row))) | |
| 1416 | + update_rows | |
| 1417 | + ( | |
| 1418 | + DB($MY_DB) the_data_base, | |
| 1419 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1420 | + $Row -> Bool which, | |
| 1421 | + DBRow($Row) -> Maybe($Row) how | |
| 1422 | + ) = | |
| 1423 | + if get_table(the_data_base,the_table) is | |
| 1424 | + { | |
| 1425 | + error(msg) then error(msg), | |
| 1426 | + ok(loaded_table) then if loaded_table is | |
| 1427 | + table(table_name,compare,store,changed_v,counter_v,rows_v) then protect | |
| 1428 | + changed_v <- true; | |
| 1429 | + if separ_list(*rows_v,(DBRow($Row) r) |-> | |
| 1430 | + if r is dbrow(row_id,ver,row) then which(row)) | |
| 1431 | + is (extracted_rows,other_rows) then | |
| 1432 | + with updated_rows = qsort(map((DBRow($Row) r) |-> | |
| 1433 | + if how(r) is | |
| 1434 | + { | |
| 1435 | + failure then not_updated(r), | |
| 1436 | + success(new_r) then updated(dbrow(row_id(r),version(r)+1,new_r)) | |
| 1437 | + }, | |
| 1438 | + extracted_rows), | |
| 1439 | + (DBUpdateResult($Row) ur1, DBUpdateResult($Row) ur2) |-> | |
| 1440 | + compare(the_row(ur1),the_row(ur2))), | |
| 1441 | + rows_v <- insert(map(the_row,updated_rows),other_rows,compare); | |
| 1442 | + if save_table(directory(the_data_base),loaded_table) is | |
| 1443 | + { | |
| 1444 | + error(msg) then error(msg), | |
| 1445 | + ok(_) then ok(updated_rows) | |
| 1446 | + } | |
| 1447 | + }. | |
| 1448 | + | |
| 1449 | + | |
| 1450 | + | |
| 1451 | + Deleting rows. | |
| 1452 | + | |
| 1453 | + | |
| 1454 | +define Result(DBError, | |
| 1455 | + ($Row, // the deleted row | |
| 1456 | + List(DBRow($Row))) // the remaining rows | |
| 1457 | + ) | |
| 1458 | + delete_row | |
| 1459 | + ( | |
| 1460 | + List(DBRow($Row)) l, | |
| 1461 | + DBRowId($Row) row_id | |
| 1462 | + ) = | |
| 1463 | + if l is | |
| 1464 | + { | |
| 1465 | + [ ] then error(record_not_found), | |
| 1466 | + [h . t] then if h is dbrow(i,v,r) then | |
| 1467 | + if i = row_id | |
| 1468 | + then ok((row(h),t)) | |
| 1469 | + else if delete_row(t,row_id) is | |
| 1470 | + { | |
| 1471 | + error(msg) then error(msg), | |
| 1472 | + ok(result1) then if result1 is (deleted,remaining) then | |
| 1473 | + ok((deleted,[h . remaining])) | |
| 1474 | + } | |
| 1475 | + }. | |
| 1476 | + | |
| 1477 | +public define Result(DBError,$Row) | |
| 1478 | + delete_row | |
| 1479 | + ( | |
| 1480 | + DB($MY_DB) the_data_base, | |
| 1481 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1482 | + DBRowId($Row) row_id | |
| 1483 | + ) = | |
| 1484 | + if get_table(the_data_base,the_table) is | |
| 1485 | + { | |
| 1486 | + error(msg) then error(msg), | |
| 1487 | + ok(loaded_table) then if loaded_table is | |
| 1488 | + table(table_name,compare,store,changed_v,counter_v,rows_v) then protect | |
| 1489 | + if delete_row(*rows_v,row_id) is | |
| 1490 | + { | |
| 1491 | + error(msg) then error(msg), | |
| 1492 | + ok(d_rows) then if d_rows is (deleted,rows) then | |
| 1493 | + changed_v <- true; | |
| 1494 | + rows_v <- rows; | |
| 1495 | + if save_table(directory(the_data_base),loaded_table) is | |
| 1496 | + { | |
| 1497 | + error(msg) then error(msg), | |
| 1498 | + ok(_) then ok(deleted) | |
| 1499 | + } | |
| 1500 | + } | |
| 1501 | + }. | |
| 1502 | + | |
| 1503 | +define (List($Row),List(DBRow($Row))) // (deleted rows, remaining rows) | |
| 1504 | + delete_rows | |
| 1505 | + ( | |
| 1506 | + List(DBRow($Row)) rows, | |
| 1507 | + $Row -> Bool which | |
| 1508 | + ) = | |
| 1509 | + if rows is | |
| 1510 | + { | |
| 1511 | + [ ] then ([ ],[ ]), | |
| 1512 | + [row1 . others] then | |
| 1513 | + if delete_rows(others,which) is (deleted_others,remaining_others) then | |
| 1514 | + if row1 is dbrow(id,ver,row) then | |
| 1515 | + if which(row) | |
| 1516 | + then ([row . deleted_others],remaining_others) | |
| 1517 | + else (deleted_others,[row1 . remaining_others]) | |
| 1518 | + }. | |
| 1519 | + | |
| 1520 | +public define Result(DBError,List($Row)) | |
| 1521 | + delete_rows | |
| 1522 | + ( | |
| 1523 | + DB($MY_DB) the_data_base, | |
| 1524 | + $MY_DB -> DBTable($Row,$HRow) the_table, | |
| 1525 | + $Row -> Bool which | |
| 1526 | + ) = | |
| 1527 | + if get_table(the_data_base,the_table) is | |
| 1528 | + { | |
| 1529 | + error(msg) then error(msg), | |
| 1530 | + ok(loaded_table) then if loaded_table is | |
| 1531 | + table(table_name,compare,store,changed_v,counter_v,rows_v) then protect | |
| 1532 | + if delete_rows(*rows_v,which) is (deleted,remaining) then | |
| 1533 | + changed_v <- true; | |
| 1534 | + rows_v <- remaining; | |
| 1535 | + if save_table(directory(the_data_base),loaded_table) is | |
| 1536 | + { | |
| 1537 | + error(msg) then error(msg), | |
| 1538 | + ok(_) then ok(deleted) | |
| 1539 | + } | |
| 1540 | + }. | |
| 1541 | + | |
| 1542 | + | |
| 1543 | + | |
| 1544 | + | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + Multi-tables queries. | |
| 1548 | + | |
| 1549 | + | |
| 1550 | +define List($Out) | |
| 1551 | + remove_repetitions | |
| 1552 | + ( | |
| 1553 | + List($Out) l | |
| 1554 | + ) = | |
| 1555 | + if l is | |
| 1556 | + { | |
| 1557 | + [ ] then [ ], | |
| 1558 | + [h . t] then | |
| 1559 | + if member(t,h) | |
| 1560 | + then remove_repetitions(t) | |
| 1561 | + else [h . remove_repetitions(t)] | |
| 1562 | + }. | |
| 1563 | + | |
| 1564 | + | |
| 1565 | +define List($T) | |
| 1566 | + flatten | |
| 1567 | + ( | |
| 1568 | + List(List($T)) l | |
| 1569 | + ) = | |
| 1570 | + if l is | |
| 1571 | + { | |
| 1572 | + [ ] then [ ], | |
| 1573 | + [h . t] then h + flatten(t) | |
| 1574 | + }. | |
| 1575 | + | |
| 1576 | +public define List($Out) | |
| 1577 | + query | |
| 1578 | + ( | |
| 1579 | + DB($MY_DB) the_data_base, | |
| 1580 | + $MY_DB -> DBTable($Row,$HRow) the_first_table, | |
| 1581 | + DBRow($Row) -> Bool the_first_condition, | |
| 1582 | + (DBRow($Row),$In) -> $Out the_first_selection, | |
| 1583 | + DBRow($Row) -> List($In) the_subquery | |
| 1584 | + ) = | |
| 1585 | + if get_rows(the_data_base,the_first_table,the_first_condition) is | |
| 1586 | + { | |
| 1587 | + error(msg) then [ ], | |
| 1588 | + ok(rows) then | |
| 1589 | + remove_repetitions(flatten( | |
| 1590 | + map((DBRow($Row) row) |-> | |
| 1591 | + map(($In i) |-> the_first_selection(row,i),the_subquery(row)), | |
| 1592 | + rows))) | |
| 1593 | + }. | |
| 1594 | + | |
| 1595 | + | |
| 1596 | + | |
| 1597 | + | |
| 1598 | + | |
| 1599 | + | ... | ... |
anubis_dev/library/tools/sdbms2.anubis
| ... | ... | @@ -49,9 +49,9 @@ |
| 49 | 49 | |
| 50 | 50 | *** (2) Data base and table structure. |
| 51 | 51 | *** (2.1) Data base roots. |
| 52 | - *** (2.2) Tables. | |
| 53 | - *** (2.3) Indexing. | |
| 54 | - *** (2.4) Errors. | |
| 52 | + *** (2.2) Errors and informations. | |
| 53 | + *** (2.3) Tables. | |
| 54 | + *** (2.4) Indexing. | |
| 55 | 55 | *** (2.5) Initializing a table. |
| 56 | 56 | *** (2.6) Initializing an index. |
| 57 | 57 | *** (2.7) Data bases. |
| ... | ... | @@ -118,11 +118,11 @@ public type DB2Info:... (see below) |
| 118 | 118 | In order to create a data base root, use the following tool: |
| 119 | 119 | |
| 120 | 120 | public define DB2Root |
| 121 | - root | |
| 121 | + make_root | |
| 122 | 122 | ( |
| 123 | 123 | String directory, // where the files will be located |
| 124 | 124 | Int32 kilo_bytes, // maximal number of kilo bytes in memory |
| 125 | - Int32 delay, // maximal synchronization delay between memory and files | |
| 125 | + Int32 delay, // maximal synchronisation delay between memory and files | |
| 126 | 126 | Var(Bool) shutdown_v, // shutdown flag |
| 127 | 127 | DB2Error -> One warn, // warning function for administrator |
| 128 | 128 | DB2Info -> One inform // information function for administrator |
| ... | ... | @@ -131,19 +131,19 @@ public define DB2Root |
| 131 | 131 | Create as many data base roots as you have data bases in your project. Choose distinct |
| 132 | 132 | directories for all data base roots. |
| 133 | 133 | |
| 134 | - 'kilo_bytes' determines the maximal number of kilo bytes the data base may occupy in | |
| 134 | + 'kilo_bytes' determines the maximal number of kilobytes the data base may occupy in | |
| 135 | 135 | memory (RAM). When the memory occupied by the data base becomes greater than this |
| 136 | 136 | value, those chunks and tables which have been used the less recently are unloaded from |
| 137 | 137 | memory. |
| 138 | 138 | |
| 139 | 139 | 'delay' is the maximal number of seconds which may elapse between a modification of a |
| 140 | - table in the memory and the synchronization with the data on the disk. | |
| 140 | + table in the memory and the synchronisation with the data on the disk. | |
| 141 | 141 | |
| 142 | 142 | The dynamic variable 'shutdown_v' is the 'shutdown flag'. When the tables are |
| 143 | 143 | initialized this variable receives the value 'false'. As soon as you put the value |
| 144 | 144 | 'true' in this variable, all the table which have been initialized with this root are |
| 145 | 145 | shutdown, which means that no more utilization command may work, and that the data on |
| 146 | - the disk are synchronized with the content of the memory. You should probably create | |
| 146 | + the disk are synchronised with the content of the memory. You should probably create | |
| 147 | 147 | only one such variable for all the data bases of your program, i.e. even if you create |
| 148 | 148 | several data base roots, you should provide the same shutdown flag to all these |
| 149 | 149 | roots. Nevertheless, if you want to shutdown your data bases at distinct times, use |
| ... | ... | @@ -184,16 +184,49 @@ public type DB2Info: |
| 184 | 184 | loading_chunk (String path), |
| 185 | 185 | unloading_chunk (String path), |
| 186 | 186 | beginning_chunk_synchronisation (String path), |
| 187 | - ending_chunk_synchronisation (String path), | |
| 188 | - beginning_table_move (String path, Int32 old_bits, Int32 new_bits), | |
| 189 | - ending_table_move (String path, Int32 old_bits, Int32 new_bits). | |
| 187 | + ending_chunk_synchronisation (String path). | |
| 190 | 188 | |
| 191 | 189 | |
| 192 | 190 | Data of these types are transmitted to the functions 'warn' and 'inform', that you must |
| 193 | 191 | provide when you create your data base root. |
| 192 | + | |
| 193 | + For your convenience we provide the following formating functions transforming data of | |
| 194 | + type DB2Error and DB2Info into English sentences: | |
| 194 | 195 | |
| 196 | +public define String | |
| 197 | + en_format | |
| 198 | + ( | |
| 199 | + DB2Error e | |
| 200 | + ) = | |
| 201 | + if e is | |
| 202 | + { | |
| 203 | + file_not_found(p) then "File not found: '"+p+"'", | |
| 204 | + file_reading_problem(p) then "Cannot read file: '"+p+"'", | |
| 205 | + file_type_problem(p) then "Incompatible type: '"+p+"'", | |
| 206 | + cannot_open_file(p) then "Cannot open file: '"+p+"'", | |
| 207 | + cannot_write_file(p) then "Cannot write into file: '"+p+"'", | |
| 208 | + cannot_find_index(d,t,i) then "Cannot find index: '"+d+"/t_"+t+"["+i+"]" | |
| 209 | + }. | |
| 195 | 210 | |
| 196 | 211 | |
| 212 | +public define String | |
| 213 | + en_format | |
| 214 | + ( | |
| 215 | + DB2Info i | |
| 216 | + ) = | |
| 217 | + if i is | |
| 218 | + { | |
| 219 | + creating_table(p) then "Creating table: '"+p+"'", | |
| 220 | + loading_table(p) then "Loading table: '"+p+"'", | |
| 221 | + unloading_table(p) then "Unloading table: '"+p+"'", | |
| 222 | + beginning_table_synchronisation(p) then "Beginning table synchronisation: '"+p+"'", | |
| 223 | + ending_table_synchronisation(p) then "Ending table synchronisation: '"+p+"'", | |
| 224 | + creating_chunk(p) then "Creating chunk: '"+p+"'", | |
| 225 | + loading_chunk(p) then "Loading chunk: '"+p+"'", | |
| 226 | + unloading_chunk(p) then "Unloading chunk: '"+p+"'", | |
| 227 | + beginning_chunk_synchronisation(p) then "Beginning chunk synchronisation: '"+p+"'", | |
| 228 | + ending_chunk_synchronisation(p) then "Ending chunk synchronisation: '"+p+"'" | |
| 229 | + }. | |
| 197 | 230 | |
| 198 | 231 | |
| 199 | 232 | *** (2.3) Tables. |
| ... | ... | @@ -749,41 +782,50 @@ public define List(Result(DB2Error,$Row)) |
| 749 | 782 | *** [1.1] Chunks. |
| 750 | 783 | *** [1.2] Secondary indexes. |
| 751 | 784 | *** [1.3] Tables. |
| 752 | - | |
| 753 | 785 | *** [2] Initializing. |
| 754 | 786 | *** [2.1] Roots. |
| 755 | 787 | *** [2.2] Tables. |
| 756 | 788 | *** [2.3] Indexes. |
| 757 | - | |
| 758 | 789 | *** [3] Tools for getting tables, chunks and indexes. |
| 790 | + *** [3.5] Loading a secondary index. | |
| 759 | 791 | *** [3.1] Loading a table. |
| 760 | 792 | *** [3.2] Getting a table. |
| 761 | 793 | *** [3.3] Loading a chunk. |
| 762 | 794 | *** [3.4] Getting a chunk. |
| 763 | - *** [3.5] Loading a secondary index. | |
| 764 | 795 | *** [3.6] Getting a secondary index. |
| 765 | - | |
| 766 | 796 | *** [4] Adding rows. |
| 767 | - *** [4.1] Computing the size of a row. | |
| 768 | 797 | *** [4.2] Adding a set of rows. |
| 769 | 798 | *** [4.3] The public tool 'add_rows'. |
| 770 | 799 | *** [4.4] The public tool 'add_row'. |
| 771 | - | |
| 772 | 800 | *** [5] Row selection. |
| 773 | - | |
| 774 | 801 | *** [6] Acting on rows. |
| 775 | 802 | *** [6.1] Acting on selected rows of a chunk. |
| 776 | - *** [6.2] Acting on a chunk. | |
| 777 | - *** [6.3] Acting by condition. | |
| 778 | - *** [6.4] Acting by primary index. | |
| 779 | - *** [6.5] Acting by secondary index. | |
| 780 | - | |
| 803 | + *** [6.2] Waiting for the end of chunk synchronisation. | |
| 804 | + *** [6.3] Acting on a chunk. | |
| 805 | + *** [6.4] Acting by condition. | |
| 806 | + *** [6.5] Acting by primary index. | |
| 807 | + *** [6.6] Acting by secondary index. | |
| 808 | + *** [6.7] Waiting for the end of table synchronisation. | |
| 809 | + *** [6.8] Acting in general. | |
| 781 | 810 | *** [7] Utilization commands. |
| 782 | 811 | *** [7.1] 'get_rows'. |
| 783 | 812 | *** [7.2] 'update_rows'. |
| 784 | 813 | *** [7.3] 'delete_rows'. |
| 785 | - | |
| 786 | - *** [8] Synchronizing memory with disk. | |
| 814 | + *** [8] Synchronising memory with disk. | |
| 815 | + *** [8.1] Synchronising a table file. | |
| 816 | + *** [8.2] Synchronising chunk files. | |
| 817 | + *** [8.2.1] One chunk. | |
| 818 | + *** [8.2.2] One 'new' chunks (moving table). | |
| 819 | + *** [8.2.2.1] 'Increasing' case. | |
| 820 | + *** [8.2.2.2] 'Decreasing' case. | |
| 821 | + *** [8.2.2.3] Both cases. | |
| 822 | + *** [8.2.3] All chunks. | |
| 823 | + *** [8.4] Synchronising everything. | |
| 824 | + *** [8.5] Asking for delayed synchronisation. | |
| 825 | + *** [9] Changing the number of bits of hash. | |
| 826 | + *** [9.1] Hashing. | |
| 827 | + *** [9.2] Deciding to change the number of bits of hash. | |
| 828 | + *** [9.3] Performing a change. | |
| 787 | 829 | |
| 788 | 830 | --------------------------------------------------------------------------------------- |
| 789 | 831 | |
| ... | ... | @@ -834,7 +876,7 @@ type Chunk($Row): |
| 834 | 876 | because, when memory becomes low, we need to unload some chunks. We unload those chunks |
| 835 | 877 | which have not been used since the longuest time. |
| 836 | 878 | |
| 837 | - The 'changed_v' flag means when 'true' that the chunk is not synchronized with its file | |
| 879 | + The 'changed_v' flag means when 'true' that the chunk is not synchronised with its file | |
| 838 | 880 | on the disk. The flag 'transfered_v' is used when the table is moving (see below). Of |
| 839 | 881 | course, the component 'rows_v' contains the list of all rows in this chunk. Normally a |
| 840 | 882 | very short list. |
| ... | ... | @@ -1213,7 +1255,7 @@ define Result(DB2Error,LoadedTable($Row,$HRow)) |
| 1213 | 1255 | store, |
| 1214 | 1256 | locked, |
| 1215 | 1257 | var(unchanged), // changed_v |
| 1216 | - 0, // bits_of_hash | |
| 1258 | + 10, // bits_of_hash | |
| 1217 | 1259 | mvar(1,not_loaded), // only 1 chunk |
| 1218 | 1260 | index_name(primary_index), |
| 1219 | 1261 | hash_row(primary_index), |
| ... | ... | @@ -1300,7 +1342,7 @@ define Result(DB2Error,LoadedChunk($Row)) |
| 1300 | 1342 | cannot_find_file then |
| 1301 | 1343 | with c = (LoadedChunk($Row))lchunk( |
| 1302 | 1344 | var(now), // last used |
| 1303 | - var(changed), // not synchronized with disk | |
| 1345 | + var(changed), // not synchronised with disk | |
| 1304 | 1346 | var(false), // transfered |
| 1305 | 1347 | var([])), // rows |
| 1306 | 1348 | chunks(hash) <- loaded(c); |
| ... | ... | @@ -1315,7 +1357,7 @@ define Result(DB2Error,LoadedChunk($Row)) |
| 1315 | 1357 | ok(cf) then if cf is chunk(rows) then |
| 1316 | 1358 | with c = (LoadedChunk($Row))lchunk( |
| 1317 | 1359 | var(now), // last used |
| 1318 | - var(unchanged), // synchronized with disk | |
| 1360 | + var(unchanged), // synchronised with disk | |
| 1319 | 1361 | var(false), // transfered |
| 1320 | 1362 | var(map(update,rows))), |
| 1321 | 1363 | chunks(hash) <- loaded(c); |
| ... | ... | @@ -1480,13 +1522,19 @@ public define Result(DB2Error,One) |
| 1480 | 1522 | |
| 1481 | 1523 | |
| 1482 | 1524 | *** [5] Row selection. |
| 1525 | + | |
| 1526 | + Rows in a table may be selected (regardless of the type of action) via several | |
| 1527 | + different methods. | |
| 1483 | 1528 | |
| 1484 | -public type DB2Select($Row): | |
| 1485 | - cond($Row -> Bool which), | |
| 1486 | - prim(ByteArray serialized_model), | |
| 1487 | - secd(String secondary_index_name, | |
| 1529 | +public type DB2Select($Row): // an opaque type | |
| 1530 | + cond($Row -> Bool which), // by condition | |
| 1531 | + prim(ByteArray serialized_model), // by primary index | |
| 1532 | + secd(String secondary_index_name, // by secondary index | |
| 1488 | 1533 | ByteArray serialized_model). |
| 1489 | 1534 | |
| 1535 | + | |
| 1536 | + Interface constructors for this opaque type. | |
| 1537 | + | |
| 1490 | 1538 | public define DB2Select($Row) |
| 1491 | 1539 | condition |
| 1492 | 1540 | ( |
| ... | ... | @@ -1495,6 +1543,9 @@ public define DB2Select($Row) |
| 1495 | 1543 | cond(which). |
| 1496 | 1544 | |
| 1497 | 1545 | |
| 1546 | + Of course, the types $Primary and $Secondary must disappear from the selection | |
| 1547 | + method. This is why we serialize the given model. | |
| 1548 | + | |
| 1498 | 1549 | public define DB2Select($Row) |
| 1499 | 1550 | primary |
| 1500 | 1551 | ( |
| ... | ... | @@ -1515,6 +1566,7 @@ public define DB2Select($Row) |
| 1515 | 1566 | |
| 1516 | 1567 | |
| 1517 | 1568 | |
| 1569 | + | |
| 1518 | 1570 | *** [6] Acting on rows. |
| 1519 | 1571 | |
| 1520 | 1572 | We need to be able to act in several different ways on a set of rows, selected by a |
| ... | ... | @@ -1525,16 +1577,18 @@ public define DB2Select($Row) |
| 1525 | 1577 | - deleting rows. |
| 1526 | 1578 | |
| 1527 | 1579 | |
| 1528 | - The type below records what can happen to a row: | |
| 1580 | + The type below records what can happen to a row after the action is performed: | |
| 1529 | 1581 | |
| 1530 | 1582 | type NewRow($Row): |
| 1531 | - deleted, | |
| 1532 | - unchanged, | |
| 1533 | - changed($Row new_row). | |
| 1583 | + deleted, // the row has been deleted | |
| 1584 | + unchanged, // the row did not change | |
| 1585 | + changed($Row new_row). // the value of the row has been changed, | |
| 1586 | + // and here is the new value | |
| 1587 | + | |
| 1534 | 1588 | |
| 1535 | 1589 | The function which acts on a row has type: |
| 1536 | 1590 | |
| 1537 | - $Row -> (NewRow($Row),Maybe($Result)) | |
| 1591 | + $Row -> (NewRow($Row),Maybe($Result)) | |
| 1538 | 1592 | |
| 1539 | 1593 | regardless of the sort of action performed. It returns eventually a new row (this is |
| 1540 | 1594 | considered as a change of value). |
| ... | ... | @@ -1545,9 +1599,19 @@ type NewRow($Row): |
| 1545 | 1599 | define One |
| 1546 | 1600 | ask_for_delayed_synchronisation // defined below in this file |
| 1547 | 1601 | ( |
| 1548 | - LoadedTable($Row,$HRow) the_table, | |
| 1602 | + LoadedTable($Row,$HRow) the_table | |
| 1549 | 1603 | ). |
| 1550 | 1604 | |
| 1605 | +define One | |
| 1606 | + ask_for_delayed_synchronisation // defined below in this file | |
| 1607 | + ( | |
| 1608 | + LoadedChunk($Row) the_chunk | |
| 1609 | + ). | |
| 1610 | + | |
| 1611 | + This function starts a virtual machine for delayed synchronisation, except if one is | |
| 1612 | + already started. | |
| 1613 | + | |
| 1614 | + | |
| 1551 | 1615 | |
| 1552 | 1616 | |
| 1553 | 1617 | |
| ... | ... | @@ -1603,8 +1667,30 @@ define (List($Row), // new rows of chunk |
| 1603 | 1667 | |
| 1604 | 1668 | |
| 1605 | 1669 | |
| 1670 | + *** [6.2] Waiting for the end of chunk synchronisation. | |
| 1606 | 1671 | |
| 1607 | - *** [6.2] Acting on a chunk. | |
| 1672 | + The next 'waiting' function is used to forbid operation on a chunk while it is | |
| 1673 | + synchronising. | |
| 1674 | + | |
| 1675 | +define One | |
| 1676 | + wait_for_end_of_synchronisation | |
| 1677 | + ( | |
| 1678 | + Var(ChunkSynState) st_v | |
| 1679 | + ) = | |
| 1680 | + if *st_v is | |
| 1681 | + { | |
| 1682 | + unchanged then unique, | |
| 1683 | + changed then unique, | |
| 1684 | + synchronising then | |
| 1685 | + checking every 1 millisecond, | |
| 1686 | + wait for *st_v /= synchronising then | |
| 1687 | + unique | |
| 1688 | + }. | |
| 1689 | + | |
| 1690 | + | |
| 1691 | + | |
| 1692 | + | |
| 1693 | + *** [6.3] Acting on a chunk. | |
| 1608 | 1694 | |
| 1609 | 1695 | This is the interface to the previous function. We are given a chunk and an action. The |
| 1610 | 1696 | chunk is updated. |
| ... | ... | @@ -1616,40 +1702,21 @@ define List($Result) |
| 1616 | 1702 | LoadedChunk($Row) c, |
| 1617 | 1703 | $Row -> (NewRow($Row),Maybe($Result)) act |
| 1618 | 1704 | ) = |
| 1705 | + protect | |
| 1619 | 1706 | if c is lchunk(lu_v,st_v,tr_v,rows_v) then |
| 1620 | - wait_for_end_of_synchronization(st_v); | |
| 1621 | - if act_on_chunk_rows(*rows_v,act) is (new_rows,result,changed) then | |
| 1707 | + wait_for_end_of_synchronisation(st_v); | |
| 1708 | + if act_on_chunk_rows(*rows_v,act) is (new_rows,result,ch) then | |
| 1622 | 1709 | rows_v <- new_rows; |
| 1623 | 1710 | lu_v <- now; |
| 1711 | + (if ch then st_v <- changed else unique); | |
| 1712 | + result. | |
| 1624 | 1713 | |
| 1625 | - | |
| 1626 | - if changed | |
| 1627 | - then | |
| 1628 | - ( | |
| 1629 | - | |
| 1630 | - ) | |
| 1631 | - else | |
| 1632 | - ( | |
| 1633 | - ) | |
| 1634 | - if *st_v is | |
| 1635 | - { | |
| 1636 | - unchanged then | |
| 1637 | - changed then | |
| 1638 | - synchronizing then | |
| 1639 | - }; | |
| 1640 | - result. | |
| 1641 | - | |
| 1642 | - | |
| 1643 | - then unique else | |
| 1644 | - (ch_v <- changed); | |
| 1645 | - ask_for_delayed_synchronisation(the_table)); | |
| 1646 | - result. | |
| 1647 | - | |
| 1714 | + | |
| 1648 | 1715 | |
| 1649 | 1716 | |
| 1650 | 1717 | |
| 1651 | 1718 | |
| 1652 | - *** [6.3] Acting by condition. | |
| 1719 | + *** [6.4] Acting by condition. | |
| 1653 | 1720 | |
| 1654 | 1721 | We want to act on all rows of a table (actually we apply 'act' to all rows, but 'act' |
| 1655 | 1722 | may not select some rows). We have to work on all chunks. Hence, the function is a loop |
| ... | ... | @@ -1708,7 +1775,7 @@ define List(Result(DB2Error,$Result)) |
| 1708 | 1775 | |
| 1709 | 1776 | |
| 1710 | 1777 | |
| 1711 | - *** [6.4] Acting by primary index. | |
| 1778 | + *** [6.5] Acting by primary index. | |
| 1712 | 1779 | |
| 1713 | 1780 | We are given the serialization 'serialized_model' of the primary datum to be searched |
| 1714 | 1781 | for. From this serialization and the number of bits of hash, we compute the hash of the |
| ... | ... | @@ -1741,7 +1808,7 @@ define List(Result(DB2Error,$Result)) |
| 1741 | 1808 | |
| 1742 | 1809 | |
| 1743 | 1810 | |
| 1744 | - *** [6.5] Acting by secondary index. | |
| 1811 | + *** [6.6] Acting by secondary index. | |
| 1745 | 1812 | |
| 1746 | 1813 | We are again given a serialization of a secondary datum to be searched for. We first |
| 1747 | 1814 | hash this datum so as to get a secondary hash 's_hash'. We are also given the name of |
| ... | ... | @@ -1788,9 +1855,9 @@ define List(Result(DB2Error,$Result)) |
| 1788 | 1855 | |
| 1789 | 1856 | |
| 1790 | 1857 | |
| 1791 | - *** [6.7] Waiting for the end of the synchronisation. | |
| 1858 | + *** [6.7] Waiting for the end of table synchronisation. | |
| 1792 | 1859 | |
| 1793 | - The newt 'waiting' function is used to forbid operations on a table while it is | |
| 1860 | + The next 'waiting' function is used to forbid operations on a table while it is | |
| 1794 | 1861 | synchronising. |
| 1795 | 1862 | |
| 1796 | 1863 | define One |
| ... | ... | @@ -1853,6 +1920,14 @@ define List(Result(DB2Error,$Result)) |
| 1853 | 1920 | |
| 1854 | 1921 | |
| 1855 | 1922 | |
| 1923 | + | |
| 1924 | + | |
| 1925 | + | |
| 1926 | + | |
| 1927 | + | |
| 1928 | + | |
| 1929 | + | |
| 1930 | + | |
| 1856 | 1931 | *** [7] Utilization commands. |
| 1857 | 1932 | |
| 1858 | 1933 | |
| ... | ... | @@ -1947,6 +2022,7 @@ public define List(Result(DB2Error,$Row)) |
| 1947 | 2022 | |
| 1948 | 2023 | *** [8.1] Synchronising a table file. |
| 1949 | 2024 | |
| 2025 | + Getting the list of all entries from a multiple variable. | |
| 1950 | 2026 | |
| 1951 | 2027 | define List($T) |
| 1952 | 2028 | to_list |
| ... | ... | @@ -1999,10 +2075,11 @@ define One |
| 1999 | 2075 | |
| 2000 | 2076 | |
| 2001 | 2077 | *** [8.2] Synchronising chunk files. |
| 2002 | - | |
| 2003 | - | |
| 2078 | + | |
| 2004 | 2079 | *** [8.2.1] One chunk. |
| 2005 | 2080 | |
| 2081 | + Synchronising a single chunk file. | |
| 2082 | + | |
| 2006 | 2083 | define One |
| 2007 | 2084 | synchronise_chunk_file |
| 2008 | 2085 | ( | ... | ... |