{"record":{"id":"0bdb1820f07bf5a7","repo":"apache/beam","slug":"tablefunctionqueryconfig-must-provide-where-clause-value-fn","errorCode":null,"errorMessage":"TableFunctionQueryConfig must provide where_clause_value_fn","messagePattern":"TableFunctionQueryConfig must provide where_clause_value_fn","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/transforms/enrichment_handlers/cloudsql.py","lineNumber":88,"sourceCode":"          \"TableFieldsQueryConfig must provide non-empty \" +\n          \"where_clause_fields\")\n\n\n@dataclass\nclass TableFunctionQueryConfig:\n  \"\"\"Configuration for using table name, where clause, and a value function.\"\"\"\n  table_id: str\n  where_clause_template: str\n  where_clause_value_fn: ConditionValueFn\n\n  def __post_init__(self):\n    if not self.table_id or not self.where_clause_template:\n      raise ValueError(\n          \"TableFunctionQueryConfig must provide table_id and \" +\n          \"where_clause_template\")\n\n    if not self.where_clause_value_fn:\n      raise ValueError(\n          \"TableFunctionQueryConfig must provide \" + \"where_clause_value_fn\")\n\n\nclass DatabaseTypeAdapter(Enum):\n  POSTGRESQL = \"pg8000\"\n  MYSQL = \"pymysql\"\n  SQLSERVER = \"pytds\"\n\n  def to_sqlalchemy_dialect(self):\n    \"\"\"Map the adapter type to its corresponding SQLAlchemy dialect.\n\n    Returns:\n        str: SQLAlchemy dialect string.\n    \"\"\"\n    if self == DatabaseTypeAdapter.POSTGRESQL:\n      return f\"postgresql+{self.value}\"\n    elif self == DatabaseTypeAdapter.MYSQL:\n      return f\"mysql+{self.value}\"","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/transforms/enrichment_handlers/cloudsql.py#L70-L106","documentation":"TableFunctionQueryConfig.__post_init__ validates its three required fields; where_clause_value_fn is falsy (None or an empty callable reference), so the config has no way to extract WHERE-clause values from input rows.","triggerScenarios":"TableFunctionQueryConfig(table_id='t', where_clause_template='WHERE x = :x', where_clause_value_fn=None) or omitting the field.","commonSituations":"Forgetting the callable when copying the constructor signature; the function reference is defined later/further away and None is passed by default.","solutions":["Pass a callable where_clause_value_fn that computes condition values from the input row","Verify the callable is defined/imported before constructing the config","Switch to TableFieldsQueryConfig (field-based values) if a custom function is not needed"],"exampleFix":"// before\nTableFunctionQueryConfig(table_id='users', where_clause_template='WHERE id = :id', where_clause_value_fn=None)\n// after\nTableFunctionQueryConfig(table_id='users', where_clause_template='WHERE id = :id', where_clause_value_fn=lambda row: {'id': row['user_id']})","handlingStrategy":"validation","validationCode":"def make_table_fn_config(table_id, tmpl, fn):\n    if not callable(fn):\n        raise ValueError('where_clause_value_fn must be a callable')\n    return TableFunctionQueryConfig(table_id, tmpl, fn)","typeGuard":"def is_condition_value_fn(v) -> bool:\n    return callable(v)","tryCatchPattern":"try:\n    cfg = TableFunctionQueryConfig(**raw)\nexcept ValueError as e:\n    raise ValueError('where_clause_value_fn is mandatory for TableFunctionQueryConfig') from e","preventionTips":["Define and import the value fn before constructing config","Use TableFieldsQueryConfig when field-based values suffice","Make the parameter keyword-only to avoid positional None slips"],"tags":["python","apache-beam","cloudsql","dataclass","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}