Logica: a logic language that compiles down to SQL
Logica is a logic programming language that compiles to SQL. It runs on DuckDB, Google BigQuery, PostgreSQL and SQLite.
At a glance
- What is it?
- A declarative data language from the Yedalog line that turns logic programs into SQL, so rules run on BigQuery, Postgres, SQLite and DuckDB instead of a bespoke engine.
- Who is it for?
- Logica is a good fit when a rule is genuinely recursive and awkward to express as a hand written recursive CTE, and a poor fit when a plain window function or join would do. What the repository settles clearly is the install path, the engines, and the shape of a program: the command line tool, the engine directive and the head and body notation are all visible in the README and the examples.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 18 days ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A logic language that compiles down to SQL
Logica is a declarative language for manipulating data, and its defining move is that it does not ship its own runtime. A program written in Logica is compiled into a single SQL expression, which is then handed to an existing database engine. That engine can be Google BigQuery, PostgreSQL or SQLite, and the examples on the project page also drive DuckDB, which is the convenient choice when you want the whole thing to run on your own machine. The repository is Apache licensed, was started at Google, and is described as the successor to Yedalog, an earlier Google research language with the same ambition.
The name is a small clue to the design. The README expands Logica as Logic with aggregation, and it belongs to the Datalog family of logic programming languages rather than to the Prolog branch. That distinction matters for syntax. Datalog treats data as relations and describes manipulation as rules over those relations, which is why the language looks more like a set of equations about data than like a sequence of instructions. If you have written Prolog, the move is familiar. If you have only written SQL, the closest mental model is a rule that says a row exists when these other rows exist, and you can keep that analogy in your head while reading a Logica program.
Why bother compiling logic instead of writing the SQL
The short answer is that SQL engines have pulled far ahead of native logic programming engines in raw capability. BigQuery is a distributed warehouse, so a logic program can be spread across thousands of machines, and Postgres and SQLite will happily chew through large volumes of data on a laptop. Rather than compete with that, Logica borrows the syntax people already reason in and keeps the machinery underneath. The README is candid that among database researchers Datalog and SQL are considered equivalent, and that converting between the two is often straightforward, but that real programs trip over the details: how to treat disjunction, and how to treat negation.
Those two words are where the design effort went. A negative condition in a rule, written with a tilde, has to become something the SQL engine will actually evaluate correctly, and a disjunction has to expand without changing the meaning of the surrounding rules. The project's stated goal is that a person should be able to read the generated SQL and follow the structure of what they wrote. That is the right bar for a language meant for engineers who already know SQL and do not want to be locked out of the surrounding ecosystem. The trade is that you accept SQL's execution model, including its performance characteristics, in exchange for the rule notation.
Installing Logica and running a program from the terminal
Installation is a single pip command, and the package name matches the project name. After that the module can be invoked directly, which is the form the README uses for every example:
python3 -m pip install logica
python3 -m logica - print Greet <<<'@Engine("sqlite"); Greet(greeting: "Hello world!")'
python3 -m logica - run Greet <<<'@Engine("sqlite"); Greet(greeting: "Hello world!")'The two verbs are the whole command line story. The print form compiles the program and shows you the SQL it produced without touching a database, which is the fastest way to understand what the lowering does. The run form compiles and executes, returning rows. Between them sits a naming convention worth picking up immediately: you give a rule a name, here Greet, and you pass that name after run or print. If your Python installation puts its bin directory on your path you can shorten the invocation to just logica, and the README also shows running straight from a clone:
git clone https://github.com/evgskv/logica
cd logica
./logica - print Greet <<<'Greet(greeting: "Hello world!")'Running from the clone does not require the BigQuery tooling. That is only needed when the target engine is BigQuery, which additionally needs a Google Cloud project, the bq command line tool and the Google Cloud SDK. For everything else Python 3 is the only prerequisite the project lists.
Reading the prime number example line by line
The README's running example finds primes below thirty, and it is small enough to read in full. This is the entire program:
@Engine("sqlite");
Number(x + 1) :- x in Range(30);
Composite(a * b) distinct :- Number(a), Number(b), a > 1, b > 1;
Prime(n) distinct :- Number(n), n > 1, ~Composite(n);Four lines, four ideas. The engine directive picks the backend, here SQLite so the example needs nothing installed. The first rule builds the numbers one through thirty by adding one to each member of a range. The second rule defines a composite number as a product of two numbers greater than one, and the keyword distinct marks the output relation as one that should not keep duplicate rows. The last rule negates the composite relation with a leading tilde, so a prime is any number greater than one that is not composite. The documented run prints the primes under thirty as a result set with a single column. Once the program is named, you ask for it with the run verb and the rule name.
This is the shape most Logica programs take: generate a base relation, define derived relations from it, and finish with a negation or an aggregation to narrow the answer. The primes example is a good first program precisely because the recursion is obvious and the answer is checkable by eye.
Where the aggregation in the name shows up
The expansion Logic with aggregation promises a second pillar, and the repository's own primer and examples are where you would look for it. Aggregation is what lets a rule move from enumerating rows to summarising them, which is the step that turns a logic program into something that can answer the questions a table normally answers, such as counting or grouping. The primes program does not use it, so on the strength of that example alone you would not know what the second half of the name refers to. The examples directory is populated with notebooks that do, including one on clustering news articles, one on COVID analysis, one on life expectancy and one on drawing graphs, several of which run against DuckDB.
Two practical notes for someone starting out. The tutorial and the examples are written to be opened in Colab, and the README says that a Google Cloud project is the only thing you need to run Logica from a notebook. That makes the browser the path of least resistance, with no local install at all. If you prefer to run the second example locally, which uses a public beer dataset, the README notes that DuckDB installs easily:
python3 -m pip install duckdbThe distinction between running a rule from the terminal and running a notebook matters because they load the engine slightly differently: the terminal form inlines the engine directive in the program text, while a notebook generally sets the connection once and reuses it across cells.
The layout of the codebase and what is still growing
The tree tells you more about the project than the README does. There is a compiler directory, separate parser directories in C++ and Python, a type inference directory, and a syntax directory that presumably holds grammar definitions. Alongside them sit an integration tests directory, a run_all_tests.py harness, and the examples and tutorial folders already mentioned. That split, with two parsers and a dedicated type inference stage, is the shape of a project that has been built as a real compiler rather than a transpiler sketch, and it explains why the surface syntax is small: the effort went into the machinery underneath it.
The main open area is engine coverage. The project advertises BigQuery, Postgres and SQLite, the topic list also names Presto and Trino, and the README says support for more dialects and engines is coming. That last sentence is the honest signal that the set of backends is still expanding, so the choice of engine is not fully open the way it would be in plain SQL. The project is not archived and its last recorded push is in September 2026, so this is live work rather than a finished artifact, with 2141 stars, 113 forks and 42 open issues behind it. The most useful thing a new user can do is pick the backend they already run in production and see how much of their existing query logic survives the translation into rules.
Editorial conclusion
Logica is a good fit when a rule is genuinely recursive and awkward to express as a hand written recursive CTE, and a poor fit when a plain window function or join would do. What the repository settles clearly is the install path, the engines, and the shape of a program: the command line tool, the engine directive and the head and body notation are all visible in the README and the examples. What it does not settle is performance, because every query you write is really a query against whatever backend you point at, so the cost is the backend's cost. A sensible first step is to install the package, run the prime example on SQLite so nothing external is needed, then open the DuckDB tutorial in Colab before pointing it at a table you care about.
Frequently asked questions
What is Logica and what is it built on?
Logica is a declarative logic programming language for data manipulation that compiles to SQL. It is a successor to Yedalog, an earlier Google language, and belongs to the Datalog family rather than the Prolog family.
Which databases can Logica run against?
The README lists BigQuery, Postgres and SQLite as the main targets, and the examples also use DuckDB. Running against BigQuery additionally needs a Google Cloud project, the bq command line tool and the Google Cloud SDK, while the other engines only require Python 3.
How do I install Logica and see the SQL it generates?
Install it with pip, then use the print verb to compile a program and show the SQL without running it. Invoking the module directly as python3 -m logica works, and the print form takes the rule name after the verb and the program on standard input.
What does the name Logica stand for?
The README expands it as Logic with aggregation, pointing at the two halves of the design: declarative rules plus the ability to summarise results. The prime number example in the README shows the rule side but not the aggregation side.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/evgskv-logica)