prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  🪲 random appears to be evaluated once
  was seeing what happens for opteryx for https://buttondown.email/jaffray/archive/the-case-of-a-curious-sql-query/
  
  ~~~sql
  SELECT count(*) 
  FROM GENERATE_SERIES(1000) AS one_thousand 
  CROSS JOIN GENERATE_SERIES(1000) AS one_thousand_b 
  WHERE random() < 0.5
  ~~~
  
  ~~~
  AFTER COST OPTIMIZATION
  └─ EXIT
     └─ PROJECT (COUNT(*))
        └─ AGGREGATE (COUNT(*))
           └─ FILTER (False)
              └─ CROSS JOIN
                 ├─ GENERATE SERIES (1000) AS one_thousand
                 └─ GENERATE SERIES (1000) AS one_thousand_b
  ~~~
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `opteryx/components/cost_based_optimizer/strategies/constant_folding.py`
  Content:
  ```
  1 # Licensed under the Apache License, Version 2.0 (the "License");
  2 # you may not use this file except in compliance with the License.
  3 # You may obtain a copy of the License at
  4 #
  5 #     http://www.apache.org/licenses/LICENSE-2.0
  6 #
  7 # Unless required by applicable law or agreed to in writing, software
  8 # distributed under the License is distributed on an "AS IS" BASIS,
  9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10 # See the License for the specific language governing permissions and
  11 # limitations under the License.
  12 
  13 import datetime
  14 from typing import Any
  15 
  16 import numpy
  17 from orso.types import OrsoTypes
  18 
  19 from opteryx.components.logical_planner import LogicalPlan
  20 from opteryx.components.logical_planner import LogicalPlanNode
  21 from opteryx.components.logical_planner import LogicalPlanStepType
  22 from opteryx.managers.expression import NodeType
  23 from opteryx.managers.expression import evaluate
  24 from opteryx.managers.expression import get_all_nodes_of_type
  25 from opteryx.models import Node
  26 from opteryx.virtual_datasets import no_table_data
  27 
  28 from .optimization_strategy import OptimizationStrategy
  29 from .optimization_strategy import OptimizerContext
  30 
  31 
  32 def build_literal_node(value: Any, root: Node):
  33     # fmt:off
  34     if hasattr(value, "as_py"):
  35         value = value.as_py()
  36 
  37     root.value = value
  38     root.node_type = NodeType.LITERAL
  39     if value is None:
  40         root.type=OrsoTypes.NULL
  41     elif isinstance(value, (bool, numpy.bool_)):
  42         # boolean must be before numeric
  43         root.type=OrsoTypes.BOOLEAN
  44     elif isinstance(value, (str)):
  45         root.type=OrsoTypes.VARCHAR
  46     elif isinstance(value, (int, numpy.int64)):
  47         root.type=OrsoTypes.INTEGER
  48     elif isinstance(value, (numpy.datetime64, datetime.datetime)):
  49         root.type=OrsoTypes.TIMESTAMP
  50     elif isinstance(value, (datetime.date)):
  51         root.type=OrsoTypes.DATE
  52     else:
  53         raise Exception("Unable to fold expression")
  54     return root
  55     # fmt:on
  56 
  57 
  58 def fold_constants(root: Node) -> Node:
  59     identifiers = get_all_nodes_of_type(root, (NodeType.IDENTIFIER, NodeType.WILDCARD))
  60     if len(identifiers) == 0:
  61         table = no_table_data.read()
  62         try:
  63             result = evaluate(root, table, None)[0]
  64             return build_literal_node(result, root)
  65         except Exception as err:  # nosec
  66             # what ever the reason, just skip
  67             # DEBUG:log (err)
  68             pass
  69     return root
  70 
  71 
  72 class ConstantFoldingStrategy(OptimizationStrategy):
  73     def visit(self, node: LogicalPlanNode, context: OptimizerContext) -> OptimizerContext:
  74         """
  75         Constant Folding is when we precalculate expressions (or sub expressions)
  76         which contain only constant or literal values.
  77         """
  78         if not context.optimized_plan:
  79             context.optimized_plan = context.pre_optimized_tree.copy()  # type: ignore
  80 
  81         if node.node_type == LogicalPlanStepType.Filter:
  82             node.condition = fold_constants(node.condition)
  83             if node.condition.node_type == NodeType.LITERAL and node.condition.value:
  84                 context.optimized_plan.remove_node(context.node_id, heal=True)
  85             else:
  86                 context.optimized_plan[context.node_id] = node
  87 
  88         return context
  89 
  90     def complete(self, plan: LogicalPlan, context: OptimizerContext) -> LogicalPlan:
  91         # No finalization needed for this strategy
  92         return plan
  93
  ```
  
  Path: `opteryx/__version__.py`
  Content:
  ```
  1 __build__ = 430
  2 
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 #     http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 """
  16 Store the version here so:
  17 1) we don't load dependencies by storing it in __init__.py
  18 2) we can import it in setup.py for the same reason
  19 """
  20 from enum import Enum  # isort: skip
  21 
  22 
  23 class VersionStatus(Enum):
  24     ALPHA = "alpha"
  25     BETA = "beta"
  26     RELEASE = "release"
  27 
  28 
  29 _major = 0
  30 _minor = 14
  31 _revision = 2
  32 _status = VersionStatus.ALPHA
  33 
  34 __author__ = "@joocer"
  35 __version__ = f"{_major}.{_minor}.{_revision}" + (
  36     f"-{_status.value}.{__build__}" if _status != VersionStatus.RELEASE else ""
  37 )
  38
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/opteryx/__version__.py b/opteryx/__version__.py
  --- a/opteryx/__version__.py
  +++ b/opteryx/__version__.py
  @@ -1,4 +1,4 @@
  -__build__ = 430
  +__build__ = 432
   
   # Licensed under the Apache License, Version 2.0 (the "License");
   # you may not use this file except in compliance with the License.
  diff --git a/opteryx/components/cost_based_optimizer/strategies/constant_folding.py b/opteryx/components/cost_based_optimizer/strategies/constant_folding.py
  --- a/opteryx/components/cost_based_optimizer/strategies/constant_folding.py
  +++ b/opteryx/components/cost_based_optimizer/strategies/constant_folding.py
  @@ -57,6 +57,11 @@
   
   def fold_constants(root: Node) -> Node:
       identifiers = get_all_nodes_of_type(root, (NodeType.IDENTIFIER, NodeType.WILDCARD))
  +    functions = get_all_nodes_of_type(root, (NodeType.FUNCTION,))
  +
  +    if any(func.value in {"RANDOM", "RAND", "NORMAL", "RANDOM_STRING"} for func in functions):
  +        return root
  +
       if len(identifiers) == 0:
           table = no_table_data.read()
           try:
  
verification_info: {"golden_diff": "diff --git a/opteryx/__version__.py b/opteryx/__version__.py\n--- a/opteryx/__version__.py\n+++ b/opteryx/__version__.py\n@@ -1,4 +1,4 @@\n-__build__ = 430\n+__build__ = 432\n \n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\ndiff --git a/opteryx/components/cost_based_optimizer/strategies/constant_folding.py b/opteryx/components/cost_based_optimizer/strategies/constant_folding.py\n--- a/opteryx/components/cost_based_optimizer/strategies/constant_folding.py\n+++ b/opteryx/components/cost_based_optimizer/strategies/constant_folding.py\n@@ -57,6 +57,11 @@\n \n def fold_constants(root: Node) -> Node:\n     identifiers = get_all_nodes_of_type(root, (NodeType.IDENTIFIER, NodeType.WILDCARD))\n+    functions = get_all_nodes_of_type(root, (NodeType.FUNCTION,))\n+\n+    if any(func.value in {\"RANDOM\", \"RAND\", \"NORMAL\", \"RANDOM_STRING\"} for func in functions):\n+        return root\n+\n     if len(identifiers) == 0:\n         table = no_table_data.read()\n         try:\n", "issue": "\ud83e\udeb2 random appears to be evaluated once\nwas seeing what happens for opteryx for https://buttondown.email/jaffray/archive/the-case-of-a-curious-sql-query/\r\n\r\n~~~sql\r\nSELECT count(*) \r\nFROM GENERATE_SERIES(1000) AS one_thousand \r\nCROSS JOIN GENERATE_SERIES(1000) AS one_thousand_b \r\nWHERE random() < 0.5\r\n~~~\r\n\r\n~~~\r\nAFTER COST OPTIMIZATION\r\n\u2514\u2500 EXIT\r\n   \u2514\u2500 PROJECT (COUNT(*))\r\n      \u2514\u2500 AGGREGATE (COUNT(*))\r\n         \u2514\u2500 FILTER (False)\r\n            \u2514\u2500 CROSS JOIN\r\n               \u251c\u2500 GENERATE SERIES (1000) AS one_thousand\r\n               \u2514\u2500 GENERATE SERIES (1000) AS one_thousand_b\r\n~~~\n", "before_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport datetime\nfrom typing import Any\n\nimport numpy\nfrom orso.types import OrsoTypes\n\nfrom opteryx.components.logical_planner import LogicalPlan\nfrom opteryx.components.logical_planner import LogicalPlanNode\nfrom opteryx.components.logical_planner import LogicalPlanStepType\nfrom opteryx.managers.expression import NodeType\nfrom opteryx.managers.expression import evaluate\nfrom opteryx.managers.expression import get_all_nodes_of_type\nfrom opteryx.models import Node\nfrom opteryx.virtual_datasets import no_table_data\n\nfrom .optimization_strategy import OptimizationStrategy\nfrom .optimization_strategy import OptimizerContext\n\n\ndef build_literal_node(value: Any, root: Node):\n    # fmt:off\n    if hasattr(value, \"as_py\"):\n        value = value.as_py()\n\n    root.value = value\n    root.node_type = NodeType.LITERAL\n    if value is None:\n        root.type=OrsoTypes.NULL\n    elif isinstance(value, (bool, numpy.bool_)):\n        # boolean must be before numeric\n        root.type=OrsoTypes.BOOLEAN\n    elif isinstance(value, (str)):\n        root.type=OrsoTypes.VARCHAR\n    elif isinstance(value, (int, numpy.int64)):\n        root.type=OrsoTypes.INTEGER\n    elif isinstance(value, (numpy.datetime64, datetime.datetime)):\n        root.type=OrsoTypes.TIMESTAMP\n    elif isinstance(value, (datetime.date)):\n        root.type=OrsoTypes.DATE\n    else:\n        raise Exception(\"Unable to fold expression\")\n    return root\n    # fmt:on\n\n\ndef fold_constants(root: Node) -> Node:\n    identifiers = get_all_nodes_of_type(root, (NodeType.IDENTIFIER, NodeType.WILDCARD))\n    if len(identifiers) == 0:\n        table = no_table_data.read()\n        try:\n            result = evaluate(root, table, None)[0]\n            return build_literal_node(result, root)\n        except Exception as err:  # nosec\n            # what ever the reason, just skip\n            # DEBUG:log (err)\n            pass\n    return root\n\n\nclass ConstantFoldingStrategy(OptimizationStrategy):\n    def visit(self, node: LogicalPlanNode, context: OptimizerContext) -> OptimizerContext:\n        \"\"\"\n        Constant Folding is when we precalculate expressions (or sub expressions)\n        which contain only constant or literal values.\n        \"\"\"\n        if not context.optimized_plan:\n            context.optimized_plan = context.pre_optimized_tree.copy()  # type: ignore\n\n        if node.node_type == LogicalPlanStepType.Filter:\n            node.condition = fold_constants(node.condition)\n            if node.condition.node_type == NodeType.LITERAL and node.condition.value:\n                context.optimized_plan.remove_node(context.node_id, heal=True)\n            else:\n                context.optimized_plan[context.node_id] = node\n\n        return context\n\n    def complete(self, plan: LogicalPlan, context: OptimizerContext) -> LogicalPlan:\n        # No finalization needed for this strategy\n        return plan\n", "path": "opteryx/components/cost_based_optimizer/strategies/constant_folding.py"}, {"content": "__build__ = 430\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nStore the version here so:\n1) we don't load dependencies by storing it in __init__.py\n2) we can import it in setup.py for the same reason\n\"\"\"\nfrom enum import Enum  # isort: skip\n\n\nclass VersionStatus(Enum):\n    ALPHA = \"alpha\"\n    BETA = \"beta\"\n    RELEASE = \"release\"\n\n\n_major = 0\n_minor = 14\n_revision = 2\n_status = VersionStatus.ALPHA\n\n__author__ = \"@joocer\"\n__version__ = f\"{_major}.{_minor}.{_revision}\" + (\n    f\"-{_status.value}.{__build__}\" if _status != VersionStatus.RELEASE else \"\"\n)\n", "path": "opteryx/__version__.py"}], "after_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport datetime\nfrom typing import Any\n\nimport numpy\nfrom orso.types import OrsoTypes\n\nfrom opteryx.components.logical_planner import LogicalPlan\nfrom opteryx.components.logical_planner import LogicalPlanNode\nfrom opteryx.components.logical_planner import LogicalPlanStepType\nfrom opteryx.managers.expression import NodeType\nfrom opteryx.managers.expression import evaluate\nfrom opteryx.managers.expression import get_all_nodes_of_type\nfrom opteryx.models import Node\nfrom opteryx.virtual_datasets import no_table_data\n\nfrom .optimization_strategy import OptimizationStrategy\nfrom .optimization_strategy import OptimizerContext\n\n\ndef build_literal_node(value: Any, root: Node):\n    # fmt:off\n    if hasattr(value, \"as_py\"):\n        value = value.as_py()\n\n    root.value = value\n    root.node_type = NodeType.LITERAL\n    if value is None:\n        root.type=OrsoTypes.NULL\n    elif isinstance(value, (bool, numpy.bool_)):\n        # boolean must be before numeric\n        root.type=OrsoTypes.BOOLEAN\n    elif isinstance(value, (str)):\n        root.type=OrsoTypes.VARCHAR\n    elif isinstance(value, (int, numpy.int64)):\n        root.type=OrsoTypes.INTEGER\n    elif isinstance(value, (numpy.datetime64, datetime.datetime)):\n        root.type=OrsoTypes.TIMESTAMP\n    elif isinstance(value, (datetime.date)):\n        root.type=OrsoTypes.DATE\n    else:\n        raise Exception(\"Unable to fold expression\")\n    return root\n    # fmt:on\n\n\ndef fold_constants(root: Node) -> Node:\n    identifiers = get_all_nodes_of_type(root, (NodeType.IDENTIFIER, NodeType.WILDCARD))\n    functions = get_all_nodes_of_type(root, (NodeType.FUNCTION,))\n\n    if any(func.value in {\"RANDOM\", \"RAND\", \"NORMAL\", \"RANDOM_STRING\"} for func in functions):\n        return root\n\n    if len(identifiers) == 0:\n        table = no_table_data.read()\n        try:\n            result = evaluate(root, table, None)[0]\n            return build_literal_node(result, root)\n        except Exception as err:  # nosec\n            # what ever the reason, just skip\n            # DEBUG:log (err)\n            pass\n    return root\n\n\nclass ConstantFoldingStrategy(OptimizationStrategy):\n    def visit(self, node: LogicalPlanNode, context: OptimizerContext) -> OptimizerContext:\n        \"\"\"\n        Constant Folding is when we precalculate expressions (or sub expressions)\n        which contain only constant or literal values.\n        \"\"\"\n        if not context.optimized_plan:\n            context.optimized_plan = context.pre_optimized_tree.copy()  # type: ignore\n\n        if node.node_type == LogicalPlanStepType.Filter:\n            node.condition = fold_constants(node.condition)\n            if node.condition.node_type == NodeType.LITERAL and node.condition.value:\n                context.optimized_plan.remove_node(context.node_id, heal=True)\n            else:\n                context.optimized_plan[context.node_id] = node\n\n        return context\n\n    def complete(self, plan: LogicalPlan, context: OptimizerContext) -> LogicalPlan:\n        # No finalization needed for this strategy\n        return plan\n", "path": "opteryx/components/cost_based_optimizer/strategies/constant_folding.py"}, {"content": "__build__ = 432\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nStore the version here so:\n1) we don't load dependencies by storing it in __init__.py\n2) we can import it in setup.py for the same reason\n\"\"\"\nfrom enum import Enum  # isort: skip\n\n\nclass VersionStatus(Enum):\n    ALPHA = \"alpha\"\n    BETA = \"beta\"\n    RELEASE = \"release\"\n\n\n_major = 0\n_minor = 14\n_revision = 2\n_status = VersionStatus.ALPHA\n\n__author__ = \"@joocer\"\n__version__ = f\"{_major}.{_minor}.{_revision}\" + (\n    f\"-{_status.value}.{__build__}\" if _status != VersionStatus.RELEASE else \"\"\n)\n", "path": "opteryx/__version__.py"}]}