{"record":{"id":"003e2ebe2670ef7c","repo":"apache/cassandra","slug":"unsupported-restriction-relation","errorCode":null,"errorMessage":"Unsupported restriction: <relation>","messagePattern":"Unsupported restriction: <relation>","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java","lineNumber":230,"sourceCode":"         *   - IN relation are restricted to row keys (for now) and conflicts with anything else (we could\n         *     allow two IN for the same entity but that doesn't seem very useful)\n         *   - The value_alias cannot be restricted in any way (we don't support wide rows with indexed value\n         *     in CQL so far)\n         *   - CONTAINS and CONTAINS_KEY cannot be used with UPDATE or DELETE\n         */\n        for (Relation relation : whereClause.relations)\n        {\n\n            Operator operator = relation.operator();\n            if (operator.requiresFilteringOrIndexingFor(ColumnMetadata.Kind.CLUSTERING) && (type.isUpdate() || type.isDelete()))\n            {\n                throw invalidRequest(\"Cannot use %s with %s\", type, operator);\n            }\n\n            if (operator == Operator.IS_NOT)\n            {\n                if (!forView)\n                    throw new InvalidRequestException(\"Unsupported restriction: \" + relation);\n\n                this.notNullColumns.addAll(relation.toRestriction(table, boundNames, owner, allowFiltering).columns());\n            }\n            else if (operator.requiresIndexing())\n            {\n                Restriction restriction = relation.toRestriction(table, boundNames, owner, allowFiltering);\n\n                if (!type.allowUseOfSecondaryIndices() || !restriction.hasSupportingIndex(indexRegistry, indexHints))\n                    throw invalidRequest(\"%s restriction is only supported on properly \" +\n                                                        \"indexed columns. %s is not valid.\", operator, relation);\n\n                addRestriction(restriction, indexRegistry, indexHints);\n            }\n            else\n            {\n                addRestriction(relation.toRestriction(table, boundNames, owner, allowFiltering), indexRegistry, indexHints);\n            }\n        }","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java#L212-L248","documentation":"The IS NOT operator in a WHERE clause is only supported when building the statement for a Materialized View (forView == true); ordinary CQL statements cannot use 'column IS NOT NULL' as a restriction. StatementRestrictions throws Unsupported restriction when an IS_NOT relation appears in a regular query.","triggerScenarios":"Issuing a SELECT/INSERT WHERE clause containing 'col IS NOT NULL' against a normal table via CQL or the driver, rather than inside a CREATE MATERIALIZED VIEW filter.","commonSituations":"Developers coming from SQL try to filter out nulls with IS NOT NULL in Cassandra queries; Cassandra instead requires filtering on non-null values or redesigning the model.","solutions":["Remove the IS NOT NULL restriction from the CQL statement.","Filter on a concrete value (e.g. col = ?) or use ALLOW FILTERING with a comparison if applicable.","If null exclusion is essential, use a materialized view whose filter includes IS NOT NULL, or model nulls as an empty/sentinel value."],"exampleFix":"// before\nSELECT * FROM users WHERE email IS NOT NULL;\n// after\nSELECT * FROM users WHERE email = 'specific@example.com'; // or query by key / use a secondary table for indexed emails","handlingStrategy":"validation","validationCode":"if (cql.matches(\"(?i).*\\\\bIS\\\\s+NOT\\\\b.*\") && !isMaterializedViewDefinition)\n    throw new IllegalArgumentException(\"IS NOT NULL restrictions are only valid in materialized view filters\");","typeGuard":null,"tryCatchPattern":"try { session.execute(stmt); }\ncatch (InvalidRequestException e) {\n    if (e.getMessage().startsWith(\"Unsupported restriction\")) { /* rewrite query without IS NOT */ }\n    else throw e;\n}","preventionTips":["Remember Cassandra CQL has no IS NOT NULL filter in normal queries.","Use concrete value predicates or a query table designed for the lookup.","Use materialized views when null-exclusion filtering is required."],"tags":["cassandra","cql","unsupported-restriction"],"backgroundTag":"unsupported-operation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}