検索

お知らせ
· 2025年12月8日

Developer Community turns 10!

Hi Community,

On December 7, 2025, the InterSystems Developer Community officially celebrated its 10th anniversary! 🥳🎉

And now we honor this decade of learning, collaboration, problem-solving, and advancing InterSystems technologies. Whether you’ve been here since the beginning or joined recently, thank you for your contributions, questions, ideas, and support. This milestone belongs to all of you 💖 You’ve built this community into what it is today, and we’re truly grateful!

As part of the celebration, we invited you to participate in a special anniversary video. And boy, you delivered! Thank you to everyone who took the time to share their greetings, memories, and kind words.

Here’s to the next 10 years of innovation and collaboration! 💙

PS. Drop a line in the comments if you've spotted yourself in the brolls 😉


Stay tuned — this is just the beginning. More anniversary highlights and surprises are coming soon.

35 Comments
ディスカッション (35)20
続けるにはログインするか新規登録を行ってください
ダイジェスト
· 2025年12月8日

Publications des développeurs d'InterSystems, semaine Décembre 01 - 07, 2025, Résumé

Décembre 01 - 07, 2025Week at a GlanceInterSystems Developer Community
記事
· 2025年12月8日 8m read

When SQLancer Meets IRIS: What Happens When We Push a Database to Its Limits

Modern SQL engines are enormously complex pieces of software. Even when they appear stable and mature, subtle bugs can hide in their optimizers, type systems, predicate evaluation, or execution layers. These bugs rarely announce themselves loudly. Instead, they quietly produce incorrect results, behave inconsistently, or fail abruptly under specific combinations of SQL constructs.

This is precisely why tools like SQLancer exist. SQLancer automatically generates SQL queries and uses logical “oracles” to detect when a database behaves incorrectly. It has revealed hundreds of real bugs in widely used systems such as MySQL, PostgreSQL, SQLite, and DuckDB.

With this in mind, I attempted to bring SQLancer to InterSystems IRIS, starting with the NOREC oracle — a powerful method for detecting optimizer correctness issues. The journey, however, uncovered not just potential SQL correctness problems, but also a surprising number of driver-level and server-level failures that prevented SQLancer from running at full strength.

This article summarizes why SQLancer is important, how the NOREC oracle works, and what unexpected findings appeared while testing IRIS.

What is SQLancer?

SQLancer (SQL Testing via Differential Oracles) is a framework designed to uncover hidden correctness bugs in database systems — specifically bugs that cause a database to return wrong results without crashing or reporting an error. Instead of relying on handcrafted test cases or predefined expected outputs, SQLancer uses a powerful idea:

Generate random and syntactically valid SQL queries, run them against the database, and check whether different logically equivalent forms of the query produce the same results.

If they don’t, it indicates that the database engine evaluated the query incorrectly.

SQLancer has been remarkably successful in practice. It has found correctness bugs in virtually every major SQL system, including:

  • MySQL
  • PostgreSQL
  • SQLite
  • MariaDB
  • DuckDB
  • CockroachDB
  • TiDB
  • and many others

These bugs often involved query optimizers rewriting expressions incorrectly, mishandling NULLs, evaluating predicates inconsistently, or performing illegal simplifications.

Unlike typical fuzzers, SQLancer is not interested in simply causing crashes. Its primary goal is to reveal semantic defects — the hardest kind of bug to detect, and the most dangerous for real applications.

Bringing SQLancer to InterSystems IRIS means giving IRIS the same level of scrutiny that other major engines have already received.


How the NOREC Oracle Works

SQLancer supports multiple “oracles,” each representing a different strategy for detecting incorrect behavior. For the IRIS integration, the focus is on the NOREC oracle.

NOREC (short for “No Rewriting”) is based on a simple and elegant insight:

If you take a query and rewrite it into a form that prevents the optimizer from applying any complex transformations, then both versions should always return the same result.

In other words, NOREC compares:

  1. The original query, which the optimizer is free to rewrite, reorder, simplify, and transform.
  2. A rewritten version of the query, where all filtering is performed explicitly using a CASE expression inside the aggregate function.
    This version deliberately avoids giving the optimizer opportunities to change semantics.

For example:

Original query:

SELECT SUM(x) FROM t WHERE a > 10 AND (b IS NULL OR b < 5);

NOREC-rewritten query:

SELECT SUM(
         CASE WHEN a > 10 AND (b IS NULL OR b < 5)
              THEN x
              ELSE 0
         END
       )
FROM t;

Because the rewritten query forces evaluation to occur row-by-row without shortcuts, it serves as a correctness baseline.

If the results differ between the original and rewritten form, several things may be wrong:

  • the optimizer incorrectly simplified or reordered the predicate
  • NULL handling differed between expressions
  • type conversions were inconsistent
  • the executor incorrectly evaluated the condition
  • the optimizer applied an illegal rewrite

The power of NOREC is that it does not require any knowledge of the expected value. The comparison is enough.

For decades, the hardest bugs in SQL engines have come not from syntax or crashes, but from optimizers making incorrect assumptions. NOREC is specifically designed to expose such issues.


Why Correctness Testing Matters for IRIS

InterSystems IRIS is often deployed in environments where correctness is not optional:

  • healthcare
  • banking and payments
  • supply chain and logistics
  • government services
  • high-reliability global systems

In such domains, a silent incorrect query result is far more dangerous than a crash.

A crash is disruptive, but it is visible. Someone can notice, investigate, and repair the situation.

A silent wrong answer, however:

  • corrupts analytics
  • misleads business logic
  • propagates into reports
  • influences decisions
  • hides undetected for years

Even small inconsistencies — one row missing due to an incorrect rewrite, a predicate evaluated incorrectly, or a NULL handled in a non-standard way — can have large downstream effects.

This is why tools like SQLancer matter.

By generating a wide variety of SQL queries — including strange, unexpected combinations of predicates — it forces the database engine into corners that normal workloads rarely reach. If IRIS behaves inconsistently or incorrectly, SQLancer can reveal the problem long before it affects a real production system.

During the early experiments for this project, the unexpected driver and server errors that surfaced indicate that IRIS under random SQL generation may expose robustness issues even before correctness oracles come into play. This finding alone reinforces the importance of deeper testing.

Correctness testing isn’t about proving that the database is broken.
It’s about building confidence that it behaves correctly even in the most obscure corner cases — a goal that every SQL engine benefits from.


Hot to run it

It requires Java 17, and InterSystems IRIS Enterprise (it uses many connections).

Clone github repository

https://github.com/caretdev/sqlancer-iris.git

Build the project

cd sqlancer-iris
mvn package -DskipTests

Run with oracle NOREC

cd target
java -jar sqlancer-iris*.jar iris --oracle norec --connection-url IRIS://_SYSTEM:SYS@localhost:1972/USER

It is possible to use other oracles as well:

  • WHERE
  • Fuzzer

When running it, tool will print all the SQL queries executed, and issues found during the run

Run Tests using testcontainers

This way it will create container with IRIS will start it and run tests against it.

mvn -Dtest=TestIRISNOREC clean test 
mvn -Dtest=TestIRISWHERE clean test 
mvn -Dtest=TestIRISFuzzer clean test 

Findings so far

  • Invalid Message CountHappening quite often and for any query.
    java.sql.SQLException: Invalid Message Count (452); expected: 5 got: -1. Server returned: 406. Closing Connection
            at com.intersystems.jdbc.InStream.checkHeader(InStream.java:123)
            at com.intersystems.jdbc.InStream.readMessageInternal(InStream.java:241)
            at com.intersystems.jdbc.InStream.readMessage(InStream.java:173)
            at com.intersystems.jdbc.InStream.readMessage(InStream.java:148)
            at com.intersystems.jdbc.IRISStatement.sendDirectUpdateRequest(IRISStatement.java:458)
            at com.intersystems.jdbc.IRISStatement.Update(IRISStatement.java:439)
            at com.intersystems.jdbc.IRISStatement.execute(IRISStatement.java:740)
            at sqlancer.iris.IRISProvider.createDatabase(IRISProvider.java:123)
            at sqlancer.iris.IRISProvider.createDatabase(IRISProvider.java:1)
            at sqlancer.Main$DBMSExecutor.run(Main.java:450)
            at sqlancer.Main$2.run(Main.java:684)
            at sqlancer.Main$2.runThread(Main.java:666)
            at sqlancer.Main$2.run(Main.java:657)
            at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
            at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
            at java.base/java.lang.Thread.run(Thread.java:829)
     
  • Server closed communication device
    Caused by: java.sql.SQLException: Communication error:  Server closed communication device
            at com.intersystems.jdbc.InStream.read(InStream.java:62)
            at com.intersystems.jdbc.InStream.readBuffer(InStream.java:74)
            at com.intersystems.jdbc.InStream.checkHeader(InStream.java:101)
            at com.intersystems.jdbc.InStream.readMessageInternal(InStream.java:241)
            at com.intersystems.jdbc.InStream.readMessage(InStream.java:173)
            at com.intersystems.jdbc.InStream.readMessage(InStream.java:148)
            at com.intersystems.jdbc.IRISStatement.sendDirectQueryRequest(IRISStatement.java:351)
            at com.intersystems.jdbc.IRISStatement.Query(IRISStatement.java:269)
            at com.intersystems.jdbc.IRISStatement.executeQuery(IRISStatement.java:170)
  • Unable to obtain group command lock. Usually happens during table creation
    Caused by: java.sql.SQLException: [SQLCODE: <-400>:<Fatal error occurred>]
    [Location: <ServerLoop>]
    [%msg: <ERROR #7808: Unable to obtain group '8777833385654' command lock.>]
            at com.intersystems.jdbc.IRISConnection.getServerError(IRISConnection.java:1001)
            at com.intersystems.jdbc.IRISConnection.processError(IRISConnection.java:1146)
            at com.intersystems.jdbc.InStream.readMessageInternal(InStream.java:284)
            at com.intersystems.jdbc.InStream.readMessage(InStream.java:173)
            at com.intersystems.jdbc.InStream.readMessage(InStream.java:148)
            at com.intersystems.jdbc.IRISStatement.sendDirectUpdateRequest(IRISStatement.java:458)
            at com.intersystems.jdbc.IRISStatement.Update(IRISStatement.java:439)
            at com.intersystems.jdbc.IRISStatement.execute(IRISStatement.java:740)
            at sqlancer.common.query.SQLQueryAdapter.internalExecute(SQLQueryAdapter.java:140)
    
  • SQL: Property does not exists. looks like something unicode related
    SELECT 1 WHERE ('') = ('_㉸^');
    Totally fine SQL query, which gives strange error
    SQL Error [400] [S1000]: [SQLCODE: <-400>:<Fatal error occurred>]
    [Location: <ServerLoop - Query Open()>]
    [%msg: <Unexpected error occurred:  <PROPERTY DOES NOT EXIST>%C0o+7^%sqlcq.USER.cls592.1 *i%c㉸4,%sqlcq.USER.cls592>]
    How come, that literal value became a property

Unfortunately due to, too many errors that I have no control of quite difficult to continue any further development. 

If you think that this tool worth of existing, and we need all already found bugs fixing as well as a new ones, please vote on the contest.

3 Comments
ディスカッション (3)1
続けるにはログインするか新規登録を行ってください
お知らせ
· 2025年12月8日

Time to vote in InterSystems "Bringing Ideas to Reality" Contest 2025

Hi Community,

It's voting time! Cast your votes for the best applications in our InterSystems "Bringing Ideas to Reality" Contest:

🔥 VOTE FOR THE BEST APPS 🔥

How to vote? Details below.

Experts nomination:

An experienced jury from InterSystems will choose the best apps to nominate for the prizes in the Experts Nomination.

Community nomination:

All active members of the Developer Community with a “trusted” status in their profile are eligible to vote in the Community nomination. To check your status, please click on your profile picture at the top right, and you will see it under your picture. To become a trusted member, you need to participate in the Community at least once.

Blind vote!

The number of votes for each app will be hidden from everyone. We will publish the leaderboard in the comments section of this post daily. Experts may vote any time so it is possible that the places change dramatically at the last moment. The same applies to bonus points.

The order of projects on the contest page will be determined by the order in which applications were submitted to the competition, with the earliest submissions appearing higher on the list.

P.S. Don't forget to subscribe to this post (click on the bell icon) to be notified of new comments.

To take part in the voting, you need:

  1. Sign in to Open Exchange – DC credentials will work.
  2. Make any valid contribution to the Developer Community – answer or ask questions, write an article, contribute applications on Open Exchange – and you'll be able to vote. Check this post on the options to make helpful contributions to the Developer Community.

If you change your mind, cancel the choice and give your vote to another application!

Support the application you like!


Note: Contest participants are allowed to fix bugs and make improvements to their applications during the voting week, so be sure to subscribe to application releases!

5 Comments
ディスカッション (5)2
続けるにはログインするか新規登録を行ってください
記事
· 2025年12月8日 4m read

Intersystems IRIS provider for Apache Airflow


Apache Airflow is the leading open-source platform to programmatically author, schedule, and monitor data pipelines and workflows using Python. Workflows are defined as code (DAGs), making them version-controlled, testable, and reusable. With a rich UI, 100+ built-in operators, dynamic task generation, and native support for cloud providers, Airflow powers ETL/ELT, ML pipelines, and batch jobs at companies like Airbnb, Netflix, and Spotify.

Airflow Application Layout
Dag Details Page in light mode showing overview dashboard and failure diagnostics

 

Airflow-Provider-IRIS Package

Airflow-Provider-IRIS  enables seamless integration between Airflow workflows and the InterSystems IRIS data platform. It provides native connection support and operators for executing IRIS SQL and automating IRIS-driven tasks within modern ETL/ELT pipelines. Designed for reliability and ease of use, this provider helps data engineers and developers build scalable, production-ready workflows.

🚀 Features

  • ✔️ IrisHook – for managing IRIS connections
  • ✔️ IrisSQLOperator – for running SQL queries
  • ✔️ IrisSensor– Wait for IRIS data readiness (row counts, status flags, bulk load completion)
  • ✔️ Support for both SELECT/CTE and DML statements
  • ✔️ Native Airflow connection UI customization
  • ✔️ Examples for real-world ETL patterns

📦Installation

The airflow-provider-iris package can be installed separately in any Airflow environment using the following command:

pip install airflow-provider-iris

For detailed documentation, usage examples, and a complete list of operators/hooks, see the published provider package: 
PyPI Package

 

iris-airflow-provider Application

iris-airflow-provider  is an Open Exchange application that demonstrates the capabilities and usage of the airflow-provider-iris Python package through ready-to-run examples and sample DAGs. 

Navigate to http://localhost:8080/ to access the application [Credentials: airflow/airflow]

Add IRIS connection

Go to Admin → Connections and click on the Add Connection button

Fill in the fields and click the Save button at the bottom of the form to create the connection.

Use your InterSystems IRIS connection by setting the iris_conn_id parameter in any of the provided operators.

In the Airflow DAG example below, the IrisSQLOperator uses the iris_conn_id parameter to connect to the IRIS instance :

# New_Test_DAG.py
from datetime import datetime
from airflow import DAG
from airflow_provider_iris.operators.iris_operator import IrisSQLOperator

# Define the DAG for running a simple SQL command against InterSystems IRIS.
with DAG(
    dag_id="01_IRIS_Raw_SQL_Demo_Local",
    start_date=datetime(2025, 12, 1),
    schedule=None,               # Run manually; no automatic scheduling
    catchup=False,               # Do not backfill previous dates
    tags=["iris-contest"],       # Tag to group the DAG in Airflow UI
) as dag:

    # Create a demo table if it does not already exist.
    # This operator connects to the specified IRIS instance and executes the SQL.
    create_table = IrisSQLOperator(
        task_id="create_table",
        iris_conn_id="ContainerInstance",   # Airflow connection configured for IRIS
        sql="""
            CREATE TABLE IF NOT EXISTS Test.AirflowDemo (
                ID INTEGER IDENTITY PRIMARY KEY,
                Message VARCHAR(200),
                RunDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        """,
    )

A DAG (Directed Acyclic Graph) is a Python script that defines an Airflow workflow as a collection of tasks, their dependencies, and execution schedule. Airflow automatically discovers and loads any Python file placed in the designated DAGs folder.

View/Run Sample Dags

The application comes with three pre-loaded DAGs.

  1. Open the Airflow UI and click on the DAGs tab.
  2. Use the toggle button next to each DAG to enable or disable it.

To run a DAG manually, click the Trigger DAG button (▶ arrow) on the right side of the DAG row.
Click the name of DAG (e.g., 01_IRIS_Raw_SQL_Demo) to view its details, graph, and run history.

The 01_IRIS_Raw_SQL_Demo DAG consists of three tasks:

  1. Create Table
  2. Insert Data
  3. Retrieve Data

Select a task and click the task box to open its details. Click on the Details tab to see its details.

Click on the Code tab to see the task’s source code.

Click on the Log tab to see the Log details.


If the DAG runs successfully, verify the results in the InterSystems Management Portal.
Navigate to http://localhost:32783/csp/sys/exp/%25CSP.UI.Portal.SQL.Home.zen?$NAMESPACE=USER [Credentials: _SYSTEM/SYS]


IrisSensor – Wait for Data in InterSystems IRIS

The IrisSensor is a purpose-built Airflow sensor that repeatedly runs a SQL query against IRIS until a condition is satisfied.
It solves the most common real-world need when integrating Airflow with IRIS:
“Don’t start my downstream jobs until the data has actually landed in IRIS.”

Why you’ll use it every day

  • Wait for daily bulk loads (CSV, EDI, API, replication, etc.)
  • Wait for upstream systems to flip a status flag
  • Wait for a minimum number of rows in a staging table
  • Wait for a specific value (e.g., Status = 'COMPLETED')
  • Wait for stored procedures or class methods that write results to a table

irisSensor Example (04_IRIS_Daily_Sales_Report_Sensor.py)

This example DAG waits patiently until the daily bulk sales load is complete, safely creates the summary table if it doesn’t exist, replaces today’s report (making the pipeline fully
idempotent), and builds a clean regional summary ready for dashboards or downstream jobs.


For more details, please visit iris-provider-iris open exchange application page.

Thanks

7 Comments
ディスカッション (7)2
続けるにはログインするか新規登録を行ってください