flagsmith-sql-flag-engine 0.1.1__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flagsmith-sql-flag-engine
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: SQL translator for Flagsmith segment predicates.
5
5
  Author: Flagsmith
6
6
  Author-email: Flagsmith <engineering@flagsmith.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "flagsmith-sql-flag-engine"
3
- version = "0.1.1"
3
+ version = "0.1.3"
4
4
  description = "SQL translator for Flagsmith segment predicates."
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Flagsmith", email = "engineering@flagsmith.com" }]
@@ -432,22 +432,15 @@ def translate_condition(cond: SegmentCondition, ctx: TranslateContext) -> str |
432
432
  # Engine: float() on the threshold raises → returns False.
433
433
  return "FALSE"
434
434
  threshold = float(threshold_lit)
435
- identity: dict[str, object] = ctx.evaluation_context.get("identity") or {} # type: ignore[assignment]
436
435
  kind = classification.kind
437
436
  if not prop:
438
- # Implicit `$.identity.key` — engine returns False when no
439
- # identity, or when the identity lacks `key`. The engine
440
- # never synthesises one from env+identifier.
441
- if not identity.get("key"):
442
- return "FALSE"
437
+ # In traditional engine implementations, this branch implies
438
+ # an identity-less context, which makes no sense for the SQL engine.
439
+ # Assume identity key.
443
440
  value_expr = ctx.dialect.cast_string(ctx.identity_key_expr)
444
441
  elif kind == "key":
445
- if not identity.get("key"):
446
- return "FALSE"
447
442
  value_expr = ctx.dialect.cast_string(ctx.jsonpath_expr("$.identity.key"))
448
443
  elif kind == "identifier":
449
- if not identity.get("identifier"):
450
- return "FALSE"
451
444
  value_expr = ctx.dialect.cast_string(ctx.jsonpath_expr("$.identity.identifier"))
452
445
  elif kind == "identity_object":
453
446
  # PERCENTAGE_SPLIT on `$.identity` — the whole dict. Engine
@@ -463,13 +456,18 @@ def translate_condition(cond: SegmentCondition, ctx: TranslateContext) -> str |
463
456
  # future work and let the caller fall back to the engine.
464
457
  return None
465
458
  else:
466
- # Plain trait key, or `$.identity.traits.<X>` rewritten to
467
- # the bare key. Hash subject pulls from `i.traits:"<key>"`
468
- # per row.
469
- traits = identity.get("traits") or {}
470
- if not isinstance(traits, dict) or prop not in traits:
471
- return "FALSE"
472
- value_expr = ctx.dialect.cast_string(ctx.trait_path(prop))
459
+ # Plain trait key, or `$.identity.traits.<X>` rewritten to the
460
+ # bare key. Hash the per-row trait value from `i.traits:"<key>"`.
461
+ # A row missing the trait has no value to bucket, so it cannot
462
+ # match — mirroring the engine's `context_value is None -> False`.
463
+ trait_sql = ctx.trait_path(prop)
464
+ split = _percentage_split_expr(
465
+ ctx,
466
+ ctx.segment_key,
467
+ ctx.dialect.cast_string(trait_sql),
468
+ threshold,
469
+ )
470
+ return f"({trait_sql} IS NOT NULL AND {split})"
473
471
  return _percentage_split_expr(ctx, ctx.segment_key, value_expr, threshold)
474
472
 
475
473
  if not prop: