awslabs.dynamodb-mcp-server 1.0.9__py3-none-any.whl → 2.0.2__py3-none-any.whl
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.
Potentially problematic release.
This version of awslabs.dynamodb-mcp-server might be problematic. Click here for more details.
- awslabs/__init__.py +20 -0
- awslabs/dynamodb_mcp_server/__init__.py +1 -1
- awslabs/dynamodb_mcp_server/common.py +1 -282
- awslabs/dynamodb_mcp_server/database_analysis_queries.py +210 -0
- awslabs/dynamodb_mcp_server/database_analyzers.py +383 -0
- awslabs/dynamodb_mcp_server/prompts/dynamodb_architect.md +13 -0
- awslabs/dynamodb_mcp_server/server.py +153 -858
- awslabs_dynamodb_mcp_server-2.0.2.dist-info/METADATA +256 -0
- awslabs_dynamodb_mcp_server-2.0.2.dist-info/RECORD +13 -0
- awslabs_dynamodb_mcp_server-1.0.9.dist-info/METADATA +0 -180
- awslabs_dynamodb_mcp_server-1.0.9.dist-info/RECORD +0 -11
- {awslabs_dynamodb_mcp_server-1.0.9.dist-info → awslabs_dynamodb_mcp_server-2.0.2.dist-info}/WHEEL +0 -0
- {awslabs_dynamodb_mcp_server-1.0.9.dist-info → awslabs_dynamodb_mcp_server-2.0.2.dist-info}/entry_points.txt +0 -0
- {awslabs_dynamodb_mcp_server-1.0.9.dist-info → awslabs_dynamodb_mcp_server-2.0.2.dist-info}/licenses/LICENSE +0 -0
- {awslabs_dynamodb_mcp_server-1.0.9.dist-info → awslabs_dynamodb_mcp_server-2.0.2.dist-info}/licenses/NOTICE +0 -0
awslabs/__init__.py
CHANGED
|
@@ -14,3 +14,23 @@
|
|
|
14
14
|
|
|
15
15
|
# This file is part of the awslabs namespace.
|
|
16
16
|
# It is intentionally minimal to support PEP 420 namespace packages.
|
|
17
|
+
|
|
18
|
+
# Namespace Package Configuration
|
|
19
|
+
#
|
|
20
|
+
# This line resolves namespace conflicts when multiple packages share the 'awslabs' namespace prefix.
|
|
21
|
+
# Without this configuration, test suites fail and build issues occur because Python cannot properly
|
|
22
|
+
# resolve which package owns the 'awslabs' namespace when both 'awslabs.dynamodb-mcp-server' and
|
|
23
|
+
# 'awslabs.mysql-mcp-server' are installed in the same environment.
|
|
24
|
+
#
|
|
25
|
+
# The extend_path() function implements PEP 420 namespace packages, allowing multiple distributions
|
|
26
|
+
# to contribute modules to the same namespace. This ensures that:
|
|
27
|
+
# 1. Both DynamoDB and MySQL MCP servers can coexist in the same Python environment
|
|
28
|
+
# 2. Import statements like 'from awslabs.dynamodb_mcp_server import ...' work correctly
|
|
29
|
+
# 3. Test discovery and execution functions properly across both packages
|
|
30
|
+
# 4. Build processes complete successfully without namespace collision errors
|
|
31
|
+
#
|
|
32
|
+
# This is the standard solution for namespace packages in Python and is required for proper
|
|
33
|
+
# multi-package namespace support in the awslabs ecosystem.
|
|
34
|
+
|
|
35
|
+
# Extend namespace to include installed packages
|
|
36
|
+
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
|
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import os
|
|
16
16
|
from functools import wraps
|
|
17
|
-
from typing import
|
|
18
|
-
from typing_extensions import TypedDict
|
|
17
|
+
from typing import Callable
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
def handle_exceptions(func: Callable) -> Callable:
|
|
@@ -52,283 +51,3 @@ def mutation_check(func):
|
|
|
52
51
|
return await func(*args, **kwargs)
|
|
53
52
|
|
|
54
53
|
return wrapper
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
# Type definitions
|
|
58
|
-
AttributeValue = Dict[Literal['S', 'N', 'B', 'BOOL', 'NULL', 'L', 'M', 'SS', 'NS', 'BS'], Any]
|
|
59
|
-
KeyAttributeValue = Dict[Literal['S', 'N', 'B'], Any]
|
|
60
|
-
|
|
61
|
-
# Return value enums
|
|
62
|
-
ReturnValue = Literal['NONE', 'ALL_OLD', 'UPDATED_OLD', 'ALL_NEW', 'UPDATED_NEW']
|
|
63
|
-
ReturnConsumedCapacity = Literal['INDEXES', 'TOTAL', 'NONE']
|
|
64
|
-
ReturnItemCollectionMetrics = Literal['SIZE', 'NONE']
|
|
65
|
-
Select = Literal['ALL_ATTRIBUTES', 'ALL_PROJECTED_ATTRIBUTES', 'SPECIFIC_ATTRIBUTES', 'COUNT']
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class ScanInput(TypedDict, total=False):
|
|
69
|
-
"""Parameters for Scan operation."""
|
|
70
|
-
|
|
71
|
-
TableName: str # required
|
|
72
|
-
IndexName: Optional[str]
|
|
73
|
-
AttributesToGet: Optional[List[str]] # Legacy parameter
|
|
74
|
-
Limit: Optional[int]
|
|
75
|
-
Select: Optional[Select]
|
|
76
|
-
ScanFilter: Optional[
|
|
77
|
-
Dict[str, AttributeValue]
|
|
78
|
-
] # Legacy parameter (must use AttributeValue format e.g. {'S': 'value'})
|
|
79
|
-
ConditionalOperator: Optional[Literal['AND', 'OR']] # Legacy parameter
|
|
80
|
-
ExclusiveStartKey: Optional[
|
|
81
|
-
Dict[str, KeyAttributeValue]
|
|
82
|
-
] # Primary key attributes in AttributeValue format e.g. {'S': 'value'}
|
|
83
|
-
ReturnConsumedCapacity: Optional[ReturnConsumedCapacity]
|
|
84
|
-
TotalSegments: Optional[int]
|
|
85
|
-
Segment: Optional[int]
|
|
86
|
-
ProjectionExpression: Optional[str]
|
|
87
|
-
FilterExpression: Optional[str]
|
|
88
|
-
ExpressionAttributeNames: Optional[Dict[str, str]]
|
|
89
|
-
ExpressionAttributeValues: Optional[
|
|
90
|
-
Dict[str, AttributeValue]
|
|
91
|
-
] # values must use AttributeValue format e.g. {'S': 'value'}
|
|
92
|
-
ConsistentRead: Optional[bool]
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
class QueryInput(TypedDict, total=False):
|
|
96
|
-
"""Parameters for Query operation."""
|
|
97
|
-
|
|
98
|
-
TableName: str # required
|
|
99
|
-
IndexName: Optional[str]
|
|
100
|
-
Select: Optional[Select]
|
|
101
|
-
AttributesToGet: Optional[List[str]] # Legacy parameter
|
|
102
|
-
Limit: Optional[int]
|
|
103
|
-
ConsistentRead: Optional[bool]
|
|
104
|
-
KeyConditionExpression: Optional[str]
|
|
105
|
-
FilterExpression: Optional[str]
|
|
106
|
-
ProjectionExpression: Optional[str]
|
|
107
|
-
ExpressionAttributeNames: Optional[Dict[str, str]]
|
|
108
|
-
ExpressionAttributeValues: Optional[
|
|
109
|
-
Dict[str, AttributeValue]
|
|
110
|
-
] # values must use AttributeValue format e.g. {'S': 'value'}
|
|
111
|
-
ScanIndexForward: Optional[bool]
|
|
112
|
-
ExclusiveStartKey: Optional[
|
|
113
|
-
Dict[str, KeyAttributeValue]
|
|
114
|
-
] # Primary key attributes in AttributeValue format e.g. {'S': 'value'}
|
|
115
|
-
ReturnConsumedCapacity: Optional[ReturnConsumedCapacity]
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
class DeleteItemInput(TypedDict, total=False):
|
|
119
|
-
"""Parameters for DeleteItem operation."""
|
|
120
|
-
|
|
121
|
-
TableName: str # required
|
|
122
|
-
Key: Dict[
|
|
123
|
-
str, KeyAttributeValue
|
|
124
|
-
] # required - primary key attributes in AttributeValue format e.g. {'S': 'value'}
|
|
125
|
-
ConditionExpression: Optional[str]
|
|
126
|
-
ExpressionAttributeNames: Optional[Dict[str, str]]
|
|
127
|
-
ExpressionAttributeValues: Optional[
|
|
128
|
-
Dict[str, AttributeValue]
|
|
129
|
-
] # values must use AttributeValue format e.g. {'S': 'value'}
|
|
130
|
-
ReturnConsumedCapacity: Optional[ReturnConsumedCapacity]
|
|
131
|
-
ReturnItemCollectionMetrics: Optional[ReturnItemCollectionMetrics]
|
|
132
|
-
ReturnValues: Optional[ReturnValue]
|
|
133
|
-
ReturnValuesOnConditionCheckFailure: Optional[Literal['ALL_OLD', 'NONE']]
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
class UpdateItemInput(TypedDict, total=False):
|
|
137
|
-
"""Parameters for UpdateItem operation."""
|
|
138
|
-
|
|
139
|
-
TableName: str # required
|
|
140
|
-
Key: Dict[
|
|
141
|
-
str, KeyAttributeValue
|
|
142
|
-
] # required - primary key attributes in AttributeValue format e.g. {'S': 'value'}
|
|
143
|
-
UpdateExpression: Optional[str]
|
|
144
|
-
ConditionExpression: Optional[str]
|
|
145
|
-
ExpressionAttributeNames: Optional[Dict[str, str]]
|
|
146
|
-
ExpressionAttributeValues: Optional[
|
|
147
|
-
Dict[str, AttributeValue]
|
|
148
|
-
] # values must use AttributeValue format e.g. {'S': 'value'}
|
|
149
|
-
ReturnConsumedCapacity: Optional[ReturnConsumedCapacity]
|
|
150
|
-
ReturnItemCollectionMetrics: Optional[ReturnItemCollectionMetrics]
|
|
151
|
-
ReturnValues: Optional[ReturnValue]
|
|
152
|
-
ReturnValuesOnConditionCheckFailure: Optional[Literal['ALL_OLD', 'NONE']]
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
class GetItemInput(TypedDict, total=False):
|
|
156
|
-
"""Parameters for GetItem operation."""
|
|
157
|
-
|
|
158
|
-
TableName: str # required
|
|
159
|
-
Key: Dict[
|
|
160
|
-
str, KeyAttributeValue
|
|
161
|
-
] # required - primary key attributes in AttributeValue format e.g. {'S': 'value'}
|
|
162
|
-
AttributesToGet: Optional[List[str]]
|
|
163
|
-
ConsistentRead: Optional[bool]
|
|
164
|
-
ExpressionAttributeNames: Optional[Dict[str, str]]
|
|
165
|
-
ProjectionExpression: Optional[str]
|
|
166
|
-
ReturnConsumedCapacity: Optional[ReturnConsumedCapacity]
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
class PutItemInput(TypedDict, total=False):
|
|
170
|
-
"""Parameters for PutItem operation."""
|
|
171
|
-
|
|
172
|
-
TableName: str # required
|
|
173
|
-
Item: Dict[
|
|
174
|
-
str, AttributeValue
|
|
175
|
-
] # required - maps attribute name to AttributeValue (must use AttributeValue format e.g. {'S': 'value'})
|
|
176
|
-
ConditionExpression: Optional[str]
|
|
177
|
-
ExpressionAttributeNames: Optional[Dict[str, str]]
|
|
178
|
-
ExpressionAttributeValues: Optional[
|
|
179
|
-
Dict[str, AttributeValue]
|
|
180
|
-
] # values must use AttributeValue format e.g. {'S': 'value'}
|
|
181
|
-
ReturnConsumedCapacity: Optional[ReturnConsumedCapacity]
|
|
182
|
-
ReturnItemCollectionMetrics: Optional[ReturnItemCollectionMetrics]
|
|
183
|
-
ReturnValues: Optional[ReturnValue]
|
|
184
|
-
ReturnValuesOnConditionCheckFailure: Optional[Literal['ALL_OLD', 'NONE']]
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
class AttributeDefinition(TypedDict):
|
|
188
|
-
AttributeName: str
|
|
189
|
-
AttributeType: Literal['S', 'N', 'B']
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
class KeySchemaElement(TypedDict):
|
|
193
|
-
AttributeName: str
|
|
194
|
-
KeyType: Literal['HASH', 'RANGE']
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
class ProvisionedThroughput(TypedDict):
|
|
198
|
-
ReadCapacityUnits: int
|
|
199
|
-
WriteCapacityUnits: int
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
class Projection(TypedDict, total=False):
|
|
203
|
-
ProjectionType: Literal['KEYS_ONLY', 'INCLUDE', 'ALL']
|
|
204
|
-
NonKeyAttributes: List[str]
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
class OnDemandThroughput(TypedDict, total=False):
|
|
208
|
-
MaxReadRequestUnits: int
|
|
209
|
-
MaxWriteRequestUnits: int
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
class WarmThroughput(TypedDict, total=False):
|
|
213
|
-
ReadUnitsPerSecond: int
|
|
214
|
-
WriteUnitsPerSecond: int
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
class GlobalSecondaryIndex(TypedDict, total=False):
|
|
218
|
-
IndexName: str # required
|
|
219
|
-
KeySchema: List[KeySchemaElement] # required
|
|
220
|
-
Projection: Projection # required
|
|
221
|
-
ProvisionedThroughput: ProvisionedThroughput
|
|
222
|
-
OnDemandThroughput: OnDemandThroughput
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
class GlobalSecondaryIndexUpdateAction(TypedDict, total=False):
|
|
226
|
-
IndexName: str
|
|
227
|
-
ProvisionedThroughput: ProvisionedThroughput
|
|
228
|
-
OnDemandThroughput: OnDemandThroughput
|
|
229
|
-
WarmThroughput: WarmThroughput
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
class GlobalSecondaryIndexDeleteAction(TypedDict):
|
|
233
|
-
IndexName: str
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
class GlobalSecondaryIndexUpdate(TypedDict, total=False):
|
|
237
|
-
Create: GlobalSecondaryIndex
|
|
238
|
-
Delete: GlobalSecondaryIndexDeleteAction
|
|
239
|
-
Update: GlobalSecondaryIndexUpdateAction
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
class StreamSpecification(TypedDict, total=False):
|
|
243
|
-
StreamEnabled: bool
|
|
244
|
-
StreamViewType: Literal['KEYS_ONLY', 'NEW_IMAGE', 'OLD_IMAGE', 'NEW_AND_OLD_IMAGES']
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
class Tag(TypedDict):
|
|
248
|
-
Key: str
|
|
249
|
-
Value: str
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
class SSESpecification(TypedDict, total=False):
|
|
253
|
-
"""Set Enabled to true for AWS managed key (KMS charges apply). set it to false for AWS owned key."""
|
|
254
|
-
|
|
255
|
-
Enabled: bool
|
|
256
|
-
SSEType: Literal['KMS']
|
|
257
|
-
KMSMasterKeyId: str
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
class TimeToLiveSpecification(TypedDict):
|
|
261
|
-
AttributeName: str # The name of the TTL attribute used to store the expiration time for items
|
|
262
|
-
Enabled: bool # Indicates whether TTL is enabled (true) or disabled (false) on the table
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
class GetResourcePolicyInput(TypedDict):
|
|
266
|
-
ResourceArn: str # The Amazon Resource Name (ARN) of the DynamoDB resource to which the policy is attached
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
class PutResourcePolicyInput(TypedDict, total=False):
|
|
270
|
-
Policy: str # An AWS resource-based policy document in JSON format
|
|
271
|
-
ResourceArn: str # The Amazon Resource Name (ARN) of the DynamoDB resource to which the policy will be attached
|
|
272
|
-
ConfirmRemoveSelfResourceAccess: (
|
|
273
|
-
bool # Set to true to confirm removing your permissions to change the policy in the future
|
|
274
|
-
)
|
|
275
|
-
ExpectedRevisionId: str # A string value for conditional updates of your policy
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
class OnDemandThroughputOverride(TypedDict):
|
|
279
|
-
MaxReadRequestUnits: int
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
class ProvisionedThroughputOverride(TypedDict):
|
|
283
|
-
ReadCapacityUnits: int
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
class ReplicaCreate(TypedDict, total=False):
|
|
287
|
-
RegionName: str
|
|
288
|
-
KMSMasterKeyId: str
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
class ReplicaDelete(TypedDict):
|
|
292
|
-
RegionName: str
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
class ReplicaUpdate(TypedDict, total=False):
|
|
296
|
-
KMSMasterKeyId: str
|
|
297
|
-
OnDemandThroughputOverride: OnDemandThroughputOverride
|
|
298
|
-
ProvisionedThroughputOverride: ProvisionedThroughputOverride
|
|
299
|
-
RegionName: str
|
|
300
|
-
TableClassOverride: Literal['STANDARD', 'STANDARD_INFREQUENT_ACCESS']
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
class ReplicationGroupUpdate(TypedDict, total=False):
|
|
304
|
-
Create: ReplicaCreate
|
|
305
|
-
Update: ReplicaUpdate
|
|
306
|
-
Delete: ReplicaDelete
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
class CreateTableInput(TypedDict, total=False):
|
|
310
|
-
"""Parameters for CreateTable operation."""
|
|
311
|
-
|
|
312
|
-
TableName: str # required
|
|
313
|
-
AttributeDefinitions: List[AttributeDefinition] # required
|
|
314
|
-
KeySchema: List[KeySchemaElement] # required
|
|
315
|
-
BillingMode: Literal['PROVISIONED', 'PAY_PER_REQUEST']
|
|
316
|
-
GlobalSecondaryIndexes: List[GlobalSecondaryIndex]
|
|
317
|
-
ProvisionedThroughput: ProvisionedThroughput
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
class UpdateTableInput(TypedDict, total=False):
|
|
321
|
-
"""Parameters for UpdateTable operation."""
|
|
322
|
-
|
|
323
|
-
TableName: str # required
|
|
324
|
-
AttributeDefinitions: List[AttributeDefinition]
|
|
325
|
-
BillingMode: Literal['PROVISIONED', 'PAY_PER_REQUEST']
|
|
326
|
-
DeletionProtectionEnabled: bool
|
|
327
|
-
GlobalSecondaryIndexUpdates: List[GlobalSecondaryIndexUpdate]
|
|
328
|
-
OnDemandThroughput: OnDemandThroughput
|
|
329
|
-
ProvisionedThroughput: ProvisionedThroughput
|
|
330
|
-
ReplicaUpdates: List[ReplicationGroupUpdate]
|
|
331
|
-
SSESpecification: SSESpecification
|
|
332
|
-
StreamSpecification: StreamSpecification
|
|
333
|
-
TableClass: Literal['STANDARD', 'STANDARD_INFREQUENT_ACCESS']
|
|
334
|
-
WarmThroughput: WarmThroughput
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
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
|
+
"""Source Database Analysis SQL Query Resources for DynamoDB Data Modeling."""
|
|
16
|
+
|
|
17
|
+
from typing import Any, Dict
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# SQL Query Templates for MySQL
|
|
21
|
+
mysql_analysis_queries = {
|
|
22
|
+
'performance_schema_check': {
|
|
23
|
+
'name': 'Performance Schema Status Check',
|
|
24
|
+
'description': 'Returns the status of the performance_schema system variable (ON/OFF)',
|
|
25
|
+
'sql': 'SELECT @@performance_schema;',
|
|
26
|
+
'parameters': [],
|
|
27
|
+
},
|
|
28
|
+
'query_pattern_analysis': {
|
|
29
|
+
'name': 'Query Pattern Analysis',
|
|
30
|
+
'description': 'Returns query patterns from Performance Schema with execution counts, calculated RPS, average execution time, average rows examined per execution, scan counts, execution timeframes, and SQL complexity classification',
|
|
31
|
+
'sql': """SELECT
|
|
32
|
+
-- Basic pattern information
|
|
33
|
+
DIGEST_TEXT as query_pattern,
|
|
34
|
+
COUNT_STAR as frequency,
|
|
35
|
+
-- Timing information
|
|
36
|
+
FIRST_SEEN as first_seen,
|
|
37
|
+
LAST_SEEN as last_seen
|
|
38
|
+
FROM performance_schema.events_statements_summary_by_digest
|
|
39
|
+
WHERE SCHEMA_NAME = '{target_database}'
|
|
40
|
+
AND COUNT_STAR > 0
|
|
41
|
+
AND LAST_SEEN >= DATE_SUB(NOW(), INTERVAL {pattern_analysis_days} DAY)
|
|
42
|
+
-- Exclude system and administrative queries
|
|
43
|
+
AND DIGEST_TEXT NOT LIKE 'SET%'
|
|
44
|
+
AND DIGEST_TEXT NOT LIKE 'USE %'
|
|
45
|
+
AND DIGEST_TEXT NOT LIKE 'SHOW%'
|
|
46
|
+
AND DIGEST_TEXT NOT LIKE '/* RDS Data API */%'
|
|
47
|
+
AND DIGEST_TEXT NOT LIKE '%information_schema%'
|
|
48
|
+
AND DIGEST_TEXT NOT LIKE '%performance_schema%'
|
|
49
|
+
AND DIGEST_TEXT NOT LIKE '%mysql.%'
|
|
50
|
+
AND DIGEST_TEXT NOT LIKE 'SELECT @@%'
|
|
51
|
+
AND DIGEST_TEXT NOT LIKE '%sys.%'
|
|
52
|
+
AND DIGEST_TEXT NOT LIKE 'select ?'
|
|
53
|
+
AND DIGEST_TEXT NOT LIKE '%mysql.general_log%'
|
|
54
|
+
AND DIGEST_TEXT NOT LIKE 'DESCRIBE %'
|
|
55
|
+
AND DIGEST_TEXT NOT LIKE 'EXPLAIN %'
|
|
56
|
+
AND DIGEST_TEXT NOT LIKE '%configured_database%'
|
|
57
|
+
AND DIGEST_TEXT NOT LIKE 'FLUSH %'
|
|
58
|
+
AND DIGEST_TEXT NOT LIKE 'RESET %'
|
|
59
|
+
AND DIGEST_TEXT NOT LIKE 'OPTIMIZE %'
|
|
60
|
+
AND DIGEST_TEXT NOT LIKE 'ANALYZE %'
|
|
61
|
+
AND DIGEST_TEXT NOT LIKE 'CHECK %'
|
|
62
|
+
AND DIGEST_TEXT NOT LIKE 'REPAIR %'
|
|
63
|
+
AND DIGEST_TEXT NOT LIKE '%@@default_storage_engine%'
|
|
64
|
+
AND DIGEST_TEXT NOT LIKE '%@%:=%'
|
|
65
|
+
AND DIGEST_TEXT NOT LIKE '%MD5%'
|
|
66
|
+
AND DIGEST_TEXT NOT LIKE '%SHA%'
|
|
67
|
+
AND DIGEST_TEXT NOT LIKE '%CONCAT_WS%'
|
|
68
|
+
ORDER BY frequency DESC;""",
|
|
69
|
+
'parameters': ['target_database', 'pattern_analysis_days'],
|
|
70
|
+
},
|
|
71
|
+
'table_analysis': {
|
|
72
|
+
'name': 'Table Structure Analysis',
|
|
73
|
+
'description': 'Returns table statistics including row counts, data size in MB, index size in MB, column counts, foreign key counts, and creation/modification timestamps',
|
|
74
|
+
'sql': """SELECT
|
|
75
|
+
TABLE_NAME,
|
|
76
|
+
TABLE_ROWS,
|
|
77
|
+
-- Storage sizes in MB
|
|
78
|
+
ROUND(DATA_LENGTH/1024/1024, 2) as datamb,
|
|
79
|
+
ROUND(INDEX_LENGTH/1024/1024, 2) as indexmb,
|
|
80
|
+
-- Count columns in this table
|
|
81
|
+
(SELECT COUNT(*) FROM information_schema.COLUMNS c
|
|
82
|
+
WHERE c.TABLE_SCHEMA = t.TABLE_SCHEMA AND c.TABLE_NAME = t.TABLE_NAME) as columncount,
|
|
83
|
+
-- Count foreign keys in this table
|
|
84
|
+
(SELECT COUNT(*) FROM information_schema.KEY_COLUMN_USAGE k
|
|
85
|
+
WHERE k.TABLE_SCHEMA = t.TABLE_SCHEMA AND k.TABLE_NAME = t.TABLE_NAME
|
|
86
|
+
AND k.REFERENCED_TABLE_NAME IS NOT NULL) as fkcount,
|
|
87
|
+
CREATE_TIME,
|
|
88
|
+
UPDATE_TIME
|
|
89
|
+
FROM information_schema.TABLES t
|
|
90
|
+
WHERE TABLE_SCHEMA = '{target_database}'
|
|
91
|
+
ORDER BY TABLE_ROWS DESC;""",
|
|
92
|
+
'parameters': ['target_database'],
|
|
93
|
+
},
|
|
94
|
+
'column_analysis': {
|
|
95
|
+
'name': 'Column Information Analysis',
|
|
96
|
+
'description': 'Returns all column definitions including table name, column name, data type, nullability, key type, default value, and extra attributes',
|
|
97
|
+
'sql': """SELECT
|
|
98
|
+
TABLE_NAME,
|
|
99
|
+
COLUMN_NAME,
|
|
100
|
+
COLUMN_TYPE,
|
|
101
|
+
IS_NULLABLE,
|
|
102
|
+
COLUMN_KEY,
|
|
103
|
+
COLUMN_DEFAULT,
|
|
104
|
+
EXTRA
|
|
105
|
+
FROM information_schema.COLUMNS
|
|
106
|
+
WHERE TABLE_SCHEMA = '{target_database}'
|
|
107
|
+
ORDER BY TABLE_NAME, ORDINAL_POSITION;""",
|
|
108
|
+
'parameters': ['target_database'],
|
|
109
|
+
},
|
|
110
|
+
'index_analysis': {
|
|
111
|
+
'name': 'Index Statistics Analysis',
|
|
112
|
+
'description': 'Returns index structure details including table name, index name, column name, uniqueness flag, and column position within each index',
|
|
113
|
+
'sql': """SELECT
|
|
114
|
+
TABLE_NAME,
|
|
115
|
+
INDEX_NAME,
|
|
116
|
+
COLUMN_NAME,
|
|
117
|
+
NON_UNIQUE,
|
|
118
|
+
SEQ_IN_INDEX
|
|
119
|
+
FROM information_schema.STATISTICS
|
|
120
|
+
WHERE TABLE_SCHEMA = '{target_database}'
|
|
121
|
+
ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;""",
|
|
122
|
+
'parameters': ['target_database'],
|
|
123
|
+
},
|
|
124
|
+
'foreign_key_analysis': {
|
|
125
|
+
'name': 'Foreign Key Relationship Analysis',
|
|
126
|
+
'description': 'Returns foreign key relationships including constraint names, child/parent table and column mappings, referential action rules, and estimated relationship cardinality',
|
|
127
|
+
'sql': """SELECT
|
|
128
|
+
kcu.CONSTRAINT_NAME,
|
|
129
|
+
kcu.TABLE_NAME as child_table,
|
|
130
|
+
kcu.COLUMN_NAME as child_column,
|
|
131
|
+
kcu.REFERENCED_TABLE_NAME as parent_table,
|
|
132
|
+
kcu.REFERENCED_COLUMN_NAME as parent_column,
|
|
133
|
+
rc.UPDATE_RULE,
|
|
134
|
+
rc.DELETE_RULE,
|
|
135
|
+
-- Estimate relationship cardinality based on unique constraints
|
|
136
|
+
CASE
|
|
137
|
+
WHEN EXISTS (
|
|
138
|
+
SELECT 1 FROM information_schema.STATISTICS s
|
|
139
|
+
WHERE s.TABLE_SCHEMA = '{target_database}'
|
|
140
|
+
AND s.TABLE_NAME = kcu.TABLE_NAME
|
|
141
|
+
AND s.COLUMN_NAME = kcu.COLUMN_NAME
|
|
142
|
+
AND s.NON_UNIQUE = 0 -- Unique constraint exists
|
|
143
|
+
AND (SELECT COUNT(*) FROM information_schema.KEY_COLUMN_USAGE kcu2
|
|
144
|
+
WHERE kcu2.CONSTRAINT_NAME = s.INDEX_NAME
|
|
145
|
+
AND kcu2.TABLE_SCHEMA = s.TABLE_SCHEMA) = 1 -- Single column constraint
|
|
146
|
+
) THEN '1:1 or 1:0..1'
|
|
147
|
+
ELSE '1:Many'
|
|
148
|
+
END as estimated_cardinality
|
|
149
|
+
FROM information_schema.KEY_COLUMN_USAGE kcu
|
|
150
|
+
LEFT JOIN information_schema.REFERENTIAL_CONSTRAINTS rc
|
|
151
|
+
ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
|
|
152
|
+
AND kcu.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA
|
|
153
|
+
WHERE kcu.TABLE_SCHEMA = '{target_database}'
|
|
154
|
+
AND kcu.REFERENCED_TABLE_NAME IS NOT NULL -- Only foreign key constraints
|
|
155
|
+
ORDER BY kcu.TABLE_NAME, kcu.COLUMN_NAME;""",
|
|
156
|
+
'parameters': ['target_database'],
|
|
157
|
+
},
|
|
158
|
+
'database_objects': {
|
|
159
|
+
'name': 'Database Objects Summary',
|
|
160
|
+
'description': 'Returns object counts and concatenated names grouped by object type: tables, triggers, stored procedures, and functions',
|
|
161
|
+
'sql': """SELECT
|
|
162
|
+
'Tables' as object_type,
|
|
163
|
+
COUNT(*) as count,
|
|
164
|
+
GROUP_CONCAT(TABLE_NAME) as names
|
|
165
|
+
FROM information_schema.TABLES
|
|
166
|
+
WHERE TABLE_SCHEMA = '{target_database}'
|
|
167
|
+
UNION ALL
|
|
168
|
+
SELECT
|
|
169
|
+
'Triggers' as object_type,
|
|
170
|
+
COUNT(*) as count,
|
|
171
|
+
COALESCE(GROUP_CONCAT(TRIGGER_NAME), 'None') as names
|
|
172
|
+
FROM information_schema.TRIGGERS
|
|
173
|
+
WHERE TRIGGER_SCHEMA = '{target_database}'
|
|
174
|
+
UNION ALL
|
|
175
|
+
SELECT
|
|
176
|
+
'Stored Procedures' as object_type,
|
|
177
|
+
COUNT(*) as count,
|
|
178
|
+
COALESCE(GROUP_CONCAT(ROUTINE_NAME), 'None') as names
|
|
179
|
+
FROM information_schema.ROUTINES
|
|
180
|
+
WHERE ROUTINE_SCHEMA = '{target_database}'
|
|
181
|
+
AND ROUTINE_TYPE = 'PROCEDURE'
|
|
182
|
+
UNION ALL
|
|
183
|
+
SELECT
|
|
184
|
+
'Functions' as object_type,
|
|
185
|
+
COUNT(*) as count,
|
|
186
|
+
COALESCE(GROUP_CONCAT(ROUTINE_NAME), 'None') as names
|
|
187
|
+
FROM information_schema.ROUTINES
|
|
188
|
+
WHERE ROUTINE_SCHEMA = '{target_database}'
|
|
189
|
+
AND ROUTINE_TYPE = 'FUNCTION';""",
|
|
190
|
+
'parameters': ['target_database'],
|
|
191
|
+
},
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def get_query_resource(query_name: str, max_query_results: int, **params) -> Dict[str, Any]:
|
|
196
|
+
"""Get a SQL query resource with parameters substituted."""
|
|
197
|
+
if query_name not in mysql_analysis_queries:
|
|
198
|
+
raise ValueError(f"Query '{query_name}' not found")
|
|
199
|
+
|
|
200
|
+
query_info = mysql_analysis_queries[query_name].copy()
|
|
201
|
+
|
|
202
|
+
# Substitute parameters in SQL
|
|
203
|
+
if params:
|
|
204
|
+
query_info['sql'] = query_info['sql'].format(**params)
|
|
205
|
+
|
|
206
|
+
# Apply LIMIT to all queries
|
|
207
|
+
sql = query_info['sql'].rstrip(';')
|
|
208
|
+
query_info['sql'] = f'{sql} LIMIT {max_query_results};'
|
|
209
|
+
|
|
210
|
+
return query_info
|