Repository: cloud-custodian/cloud-custodian

Issue:
sqlkvcache errors: AttributeError: __enter__ and sqlite3.InterfaceError: Error binding parameter 1 - probably unsupported type.
### Describe the bug

```AttributeError: __enter__```

### What did you expect to happen?

I expected 2 + 2 to equal 4, but instead 2 + 2 equaled 6!

### Cloud Provider

Amazon Web Services (AWS)

### Cloud Custodian version and dependency information

_No response_

### Policy

```shell
- name: rds-invalid-param-unmark
  resource: aws.rds
  filters:
    - type: db-parameter
```


### Relevant log/traceback output

```
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/c7n/policy.py", line 302, in run
    resources = self.policy.resource_manager.resources()
  File "/usr/local/lib/python3.7/dist-packages/c7n/query.py", line 535, in resources
    resources = self.filter_resources(resources)
  File "/usr/local/lib/python3.7/dist-packages/c7n/manager.py", line 111, in filter_resources
    resources = f.process(resources, event)
  File "/usr/local/lib/python3.7/dist-packages/c7n/filters/core.py", line 378, in process
    return self.process_set(resources, event)
  File "/usr/local/lib/python3.7/dist-packages/c7n/filters/core.py", line 397, in process_set
    resources = f.process(resources, event)
  File "/usr/local/lib/python3.7/dist-packages/c7n/filters/core.py", line 337, in process
    return self.process_set(resources, event)
  File "/usr/local/lib/python3.7/dist-packages/c7n/filters/core.py", line 353, in process_set
    r[rtype_id] for r in f.process(resources, event)])
  File "/usr/local/lib/python3.7/dist-packages/c7n/filters/core.py", line 364, in process
    resources = f.process(resources, events)
  File "/usr/local/lib/python3.7/dist-packages/c7n/filters/core.py", line 337, in process
    return self.process_set(resources, event)
  File "/usr/local/lib/python3.7/dist-packages/c7n/filters/core.py", line 353, in process_set
    r[rtype_id] for r in f.process(resources, event)])
  File "/usr/local/lib/python3.7/dist-packages/c7n/resources/rds.py", line 1650, in process
    pg_values = self.manager._cache.get(cache_key)
  File "/usr/local/lib/python3.7/dist-packages/c7n/cache.py", line 143, in get
    with self.conn as cursor:
AttributeError: __enter__
```


### Extra information or context

Another policy that ran for more than a day re: ecs-task-definition

```
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/c7n/commands.py", line 302, in run
    policy()
  File "/usr/local/lib/python3.7/dist-packages/c7n/policy.py", line 1296, in __call__
    resources = mode.run()
  File "/usr/local/lib/python3.7/dist-packages/c7n/policy.py", line 302, in run
    resources = self.policy.resource_manager.resources()
  File "/usr/local/lib/python3.7/dist-packages/c7n/query.py", line 531, in resources
    self._cache.save(cache_key, resources)
  File "/usr/local/lib/python3.7/dist-packages/c7n/cache.py", line 162, in save
    (sqlite3.Binary(encode(key)), sqlite3.Binary(encode(data)), timestamp))
sqlite3.InterfaceError: Error binding parameter 1 - probably unsupported type.
```


Discussion:

Resolving patch:
diff --git a/c7n/resources/rds.py b/c7n/resources/rds.py
--- a/c7n/resources/rds.py
+++ b/c7n/resources/rds.py
@@ -1632,31 +1632,35 @@ def recast(val, datatype):
 
         return ret_val
 
+    def handle_paramgroup_cache(self, client, paginator, param_groups):
+        pgcache = {}
+        cache = self.manager._cache
+
+        with cache:
+            for pg in param_groups:
+                cache_key = {
+                    'region': self.manager.config.region,
+                    'account_id': self.manager.config.account_id,
+                    'rds-pg': pg}
+                pg_values = cache.get(cache_key)
+                if pg_values is not None:
+                    pgcache[pg] = pg_values
+                    continue
+                param_list = list(itertools.chain(*[p['Parameters']
+                    for p in paginator.paginate(DBParameterGroupName=pg)]))
+                pgcache[pg] = {
+                    p['ParameterName']: self.recast(p['ParameterValue'], p['DataType'])
+                    for p in param_list if 'ParameterValue' in p}
+                cache.save(cache_key, pgcache[pg])
+        return pgcache
+
     def process(self, resources, event=None):
         results = []
-        paramcache = {}
-
         client = local_session(self.manager.session_factory).client('rds')
         paginator = client.get_paginator('describe_db_parameters')
-
         param_groups = {db['DBParameterGroups'][0]['DBParameterGroupName']
                         for db in resources}
-
-        for pg in param_groups:
-            cache_key = {
-                'region': self.manager.config.region,
-                'account_id': self.manager.config.account_id,
-                'rds-pg': pg}
-            pg_values = self.manager._cache.get(cache_key)
-            if pg_values is not None:
-                paramcache[pg] = pg_values
-                continue
-            param_list = list(itertools.chain(*[p['Parameters']
-                for p in paginator.paginate(DBParameterGroupName=pg)]))
-            paramcache[pg] = {
-                p['ParameterName']: self.recast(p['ParameterValue'], p['DataType'])
-                for p in param_list if 'ParameterValue' in p}
-            self.manager._cache.save(cache_key, paramcache[pg])
+        paramcache = self.handle_paramgroup_cache(client, paginator, param_groups)
 
         for resource in resources:
             for pg in resource['DBParameterGroups']:


Test patch:
diff --git a/tests/data/placebo/test_rds_param_value/rds.DescribeDBInstances_1.json b/tests/data/placebo/test_rds_param_value/rds.DescribeDBInstances_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_rds_param_value/rds.DescribeDBInstances_1.json
@@ -0,0 +1,122 @@
+{
+    "status_code": 200,
+    "data": {
+        "DBInstances": [
+            {
+                "DBInstanceIdentifier": "c7n-test",
+                "DBInstanceClass": "db.t3.micro",
+                "Engine": "postgres",
+                "DBInstanceStatus": "available",
+                "MasterUsername": "postgres",
+                "Endpoint": {
+                    "Address": "c7n-test.cz6wy8cci3uf.us-east-1.rds.amazonaws.com",
+                    "Port": 5432,
+                    "HostedZoneId": "Z2R2ITUGPM61AM"
+                },
+                "AllocatedStorage": 20,
+                "InstanceCreateTime": {
+                    "__class__": "datetime",
+                    "year": 2022,
+                    "month": 9,
+                    "day": 26,
+                    "hour": 2,
+                    "minute": 50,
+                    "second": 32,
+                    "microsecond": 719000
+                },
+                "PreferredBackupWindow": "06:25-06:55",
+                "BackupRetentionPeriod": 0,
+                "DBSecurityGroups": [],
+                "VpcSecurityGroups": [
+                    {
+                        "VpcSecurityGroupId": "sg-01f406cb65070f20b",
+                        "Status": "active"
+                    }
+                ],
+                "DBParameterGroups": [
+                    {
+                        "DBParameterGroupName": "test",
+                        "ParameterApplyStatus": "in-sync"
+                    }
+                ],
+                "AvailabilityZone": "us-east-1a",
+                "DBSubnetGroup": {
+                    "DBSubnetGroupName": "default",
+                    "DBSubnetGroupDescription": "default",
+                    "VpcId": "vpc-d2d616b5",
+                    "SubnetGroupStatus": "Complete",
+                    "Subnets": [
+                        {
+                            "SubnetIdentifier": "subnet-914763e7",
+                            "SubnetAvailabilityZone": {
+                                "Name": "us-east-1a"
+                            },
+                            "SubnetOutpost": {},
+                            "SubnetStatus": "Active"
+                        },
+                        {
+                            "SubnetIdentifier": "subnet-e3b194de",
+                            "SubnetAvailabilityZone": {
+                                "Name": "us-east-1e"
+                            },
+                            "SubnetOutpost": {},
+                            "SubnetStatus": "Active"
+                        },
+                        {
+                            "SubnetIdentifier": "subnet-efbcccb7",
+                            "SubnetAvailabilityZone": {
+                                "Name": "us-east-1b"
+                            },
+                            "SubnetOutpost": {},
+                            "SubnetStatus": "Active"
+                        },
+                        {
+                            "SubnetIdentifier": "subnet-3a334610",
+                            "SubnetAvailabilityZone": {
+                                "Name": "us-east-1d"
+                            },
+                            "SubnetOutpost": {},
+                            "SubnetStatus": "Active"
+                        }
+                    ]
+                },
+                "PreferredMaintenanceWindow": "sat:05:03-sat:05:33",
+                "PendingModifiedValues": {},
+                "MultiAZ": false,
+                "EngineVersion": "12.10",
+                "AutoMinorVersionUpgrade": true,
+                "ReadReplicaDBInstanceIdentifiers": [],
+                "LicenseModel": "postgresql-license",
+                "OptionGroupMemberships": [
+                    {
+                        "OptionGroupName": "default:postgres-12",
+                        "Status": "in-sync"
+                    }
+                ],
+                "PubliclyAccessible": false,
+                "StorageType": "gp2",
+                "DbInstancePort": 0,
+                "StorageEncrypted": true,
+                "KmsKeyId": "arn:aws:kms:us-east-1:644160558196:key/b10f842a-feb7-4318-92d5-0640a75b7688",
+                "DbiResourceId": "db-AAVMVUJ3FAZEE2FALGHBHZUCJU",
+                "CACertificateIdentifier": "rds-ca-2019",
+                "DomainMemberships": [],
+                "CopyTagsToSnapshot": true,
+                "MonitoringInterval": 60,
+                "EnhancedMonitoringResourceArn": "arn:aws:logs:us-east-1:644160558196:log-group:RDSOSMetrics:log-stream:db-AAVMVUJ3FAZEE2FALGHBHZUCJU",
+                "MonitoringRoleArn": "arn:aws:iam::644160558196:role/rds-monitoring-role",
+                "DBInstanceArn": "arn:aws:rds:us-east-1:644160558196:db:c7n-test",
+                "IAMDatabaseAuthenticationEnabled": false,
+                "PerformanceInsightsEnabled": false,
+                "DeletionProtection": false,
+                "AssociatedRoles": [],
+                "TagList": [],
+                "CustomerOwnedIpEnabled": false,
+                "ActivityStreamStatus": "stopped",
+                "BackupTarget": "region",
+                "NetworkType": "IPV4"
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_1.json b/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_1.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200,
+    "data": {
+        "Parameters": [
+            {
+                "ParameterName": "application_name",
+                "Description": "Sets the application name to be reported in statistics and logs.",
+                "Source": "engine-default",
+                "ApplyType": "dynamic",
+                "DataType": "string",
+                "IsModifiable": true,
+                "ApplyMethod": "pending-reboot"
+            }
+        ],
+        "Marker": "Z2luX2Z1enp5X3NlYXJjaF9saW1pdA==",
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_2.json b/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_2.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_2.json
@@ -0,0 +1,19 @@
+{
+    "status_code": 200,
+    "data": {
+        "Parameters": [
+            {
+                "ParameterName": "gin_pending_list_limit",
+                "Description": "(kB) Sets the maximum size of the pending list for GIN index.",
+                "Source": "engine-default",
+                "ApplyType": "dynamic",
+                "DataType": "integer",
+                "AllowedValues": "64-2147483647",
+                "IsModifiable": true,
+                "ApplyMethod": "pending-reboot"
+            }
+        ],
+        "Marker": "cGdsb2dpY2FsLnVzZV9zcGk=",
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_3.json b/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_3.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_3.json
@@ -0,0 +1,20 @@
+{
+    "status_code": 200,
+    "data": {
+        "Parameters": [
+            {
+                "ParameterName": "rds.force_admin_logging_level",
+                "ParameterValue": "info",
+                "Description": "See log messages for RDS admin user actions in customer databases.",
+                "Source": "user",
+                "ApplyType": "dynamic",
+                "DataType": "string",
+                "AllowedValues": "disabled,debug5,debug4,debug3,debug2,debug1,info,notice,warning,error,log,fatal,panic",
+                "IsModifiable": true,
+                "ApplyMethod": "immediate"
+            }
+        ],
+        "Marker": "dGltZXpvbmU=",
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_4.json b/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_4.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_rds_param_value/rds.DescribeDBParameters_4.json
@@ -0,0 +1,18 @@
+{
+    "status_code": 200,
+    "data": {
+        "Parameters": [
+            {
+                "ParameterName": "track_activities",
+                "Description": "Collects information about executing commands.",
+                "Source": "engine-default",
+                "ApplyType": "dynamic",
+                "DataType": "boolean",
+                "AllowedValues": "0,1",
+                "IsModifiable": true,
+                "ApplyMethod": "pending-reboot"
+            }
+        ],
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/test_rds.py b/tests/test_rds.py
--- a/tests/test_rds.py
+++ b/tests/test_rds.py
@@ -1633,6 +1633,32 @@ def test_param_value_cases(self):
                 print(len(f_resources), fdata, assertion)
                 self.fail(err_msg)
 
+    def test_rds_param_value(self):
+        session_factory = self.replay_flight_data("test_rds_param_value")
+        p = self.load_policy(
+            {
+                "name": "rds-param-value",
+                "resource": "aws.rds",
+                "filters": [
+                    {
+                        "type": "db-parameter",
+                        "key": "rds.force_admin_logging_level",
+                        "value": "info",
+                        "value_type": "normalize",
+                        "op": "eq",
+                    },
+                ],
+            },
+            session_factory=session_factory, cache=True,
+        )
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        self.assertEqual(resources[0].get('DBInstanceIdentifier'), 'c7n-test')
+        self.assertEqual(resources[0].get(
+            'c7n:MatchedDBParameter')[0], 'rds.force_admin_logging_level')
+        self.assertIn(('DBParameterGroupName', 'test'), resources[0].get(
+            'DBParameterGroups')[0].items())
+
 
 class Resize(BaseTest):