driftdetect-core 0.4.1 → 0.4.3
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.
- package/LICENSE +21 -0
- package/dist/boundaries/boundary-scanner.d.ts +76 -0
- package/dist/boundaries/boundary-scanner.d.ts.map +1 -0
- package/dist/boundaries/boundary-scanner.js +801 -0
- package/dist/boundaries/boundary-scanner.js.map +1 -0
- package/dist/boundaries/data-access-learner.d.ts +126 -0
- package/dist/boundaries/data-access-learner.d.ts.map +1 -0
- package/dist/boundaries/data-access-learner.js +486 -0
- package/dist/boundaries/data-access-learner.js.map +1 -0
- package/dist/boundaries/index.d.ts +6 -0
- package/dist/boundaries/index.d.ts.map +1 -1
- package/dist/boundaries/index.js +6 -0
- package/dist/boundaries/index.js.map +1 -1
- package/dist/boundaries/security-prioritizer.d.ts +118 -0
- package/dist/boundaries/security-prioritizer.d.ts.map +1 -0
- package/dist/boundaries/security-prioritizer.js +316 -0
- package/dist/boundaries/security-prioritizer.js.map +1 -0
- package/dist/call-graph/analysis/coverage-analyzer.d.ts +201 -0
- package/dist/call-graph/analysis/coverage-analyzer.d.ts.map +1 -0
- package/dist/call-graph/analysis/coverage-analyzer.js +553 -0
- package/dist/call-graph/analysis/coverage-analyzer.js.map +1 -0
- package/dist/call-graph/analysis/dead-code-detector.d.ts +145 -0
- package/dist/call-graph/analysis/dead-code-detector.d.ts.map +1 -0
- package/dist/call-graph/analysis/dead-code-detector.js +391 -0
- package/dist/call-graph/analysis/dead-code-detector.js.map +1 -0
- package/dist/call-graph/analysis/graph-builder.d.ts +142 -0
- package/dist/call-graph/analysis/graph-builder.d.ts.map +1 -0
- package/dist/call-graph/analysis/graph-builder.js +624 -0
- package/dist/call-graph/analysis/graph-builder.js.map +1 -0
- package/dist/call-graph/analysis/impact-analyzer.d.ts +150 -0
- package/dist/call-graph/analysis/impact-analyzer.d.ts.map +1 -0
- package/dist/call-graph/analysis/impact-analyzer.js +329 -0
- package/dist/call-graph/analysis/impact-analyzer.js.map +1 -0
- package/dist/call-graph/analysis/index.d.ts +11 -0
- package/dist/call-graph/analysis/index.d.ts.map +1 -0
- package/dist/call-graph/analysis/index.js +9 -0
- package/dist/call-graph/analysis/index.js.map +1 -0
- package/dist/call-graph/analysis/path-finder.d.ts +117 -0
- package/dist/call-graph/analysis/path-finder.d.ts.map +1 -0
- package/dist/call-graph/analysis/path-finder.js +360 -0
- package/dist/call-graph/analysis/path-finder.js.map +1 -0
- package/dist/call-graph/analysis/reachability.d.ts +56 -0
- package/dist/call-graph/analysis/reachability.d.ts.map +1 -0
- package/dist/call-graph/analysis/reachability.js +357 -0
- package/dist/call-graph/analysis/reachability.js.map +1 -0
- package/dist/call-graph/demo.d.ts +11 -0
- package/dist/call-graph/demo.d.ts.map +1 -0
- package/dist/call-graph/demo.js +339 -0
- package/dist/call-graph/demo.js.map +1 -0
- package/dist/call-graph/enrichment/enrichment-engine.d.ts +126 -0
- package/dist/call-graph/enrichment/enrichment-engine.d.ts.map +1 -0
- package/dist/call-graph/enrichment/enrichment-engine.js +760 -0
- package/dist/call-graph/enrichment/enrichment-engine.js.map +1 -0
- package/dist/call-graph/enrichment/impact-scorer.d.ts +59 -0
- package/dist/call-graph/enrichment/impact-scorer.d.ts.map +1 -0
- package/dist/call-graph/enrichment/impact-scorer.js +328 -0
- package/dist/call-graph/enrichment/impact-scorer.js.map +1 -0
- package/dist/call-graph/enrichment/index.d.ts +12 -0
- package/dist/call-graph/enrichment/index.d.ts.map +1 -0
- package/dist/call-graph/enrichment/index.js +15 -0
- package/dist/call-graph/enrichment/index.js.map +1 -0
- package/dist/call-graph/enrichment/remediation-generator.d.ts +41 -0
- package/dist/call-graph/enrichment/remediation-generator.d.ts.map +1 -0
- package/dist/call-graph/enrichment/remediation-generator.js +609 -0
- package/dist/call-graph/enrichment/remediation-generator.js.map +1 -0
- package/dist/call-graph/enrichment/sensitivity-classifier.d.ts +71 -0
- package/dist/call-graph/enrichment/sensitivity-classifier.d.ts.map +1 -0
- package/dist/call-graph/enrichment/sensitivity-classifier.js +454 -0
- package/dist/call-graph/enrichment/sensitivity-classifier.js.map +1 -0
- package/dist/call-graph/enrichment/types.d.ts +402 -0
- package/dist/call-graph/enrichment/types.d.ts.map +1 -0
- package/dist/call-graph/enrichment/types.js +9 -0
- package/dist/call-graph/enrichment/types.js.map +1 -0
- package/dist/call-graph/extractors/base-extractor.d.ts +112 -0
- package/dist/call-graph/extractors/base-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/base-extractor.js +140 -0
- package/dist/call-graph/extractors/base-extractor.js.map +1 -0
- package/dist/call-graph/extractors/csharp-data-access-extractor.d.ts +76 -0
- package/dist/call-graph/extractors/csharp-data-access-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/csharp-data-access-extractor.js +387 -0
- package/dist/call-graph/extractors/csharp-data-access-extractor.js.map +1 -0
- package/dist/call-graph/extractors/csharp-extractor.d.ts +87 -0
- package/dist/call-graph/extractors/csharp-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/csharp-extractor.js +470 -0
- package/dist/call-graph/extractors/csharp-extractor.js.map +1 -0
- package/dist/call-graph/extractors/data-access-extractor.d.ts +76 -0
- package/dist/call-graph/extractors/data-access-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/data-access-extractor.js +234 -0
- package/dist/call-graph/extractors/data-access-extractor.js.map +1 -0
- package/dist/call-graph/extractors/index.d.ts +26 -0
- package/dist/call-graph/extractors/index.d.ts.map +1 -0
- package/dist/call-graph/extractors/index.js +36 -0
- package/dist/call-graph/extractors/index.js.map +1 -0
- package/dist/call-graph/extractors/java-data-access-extractor.d.ts +101 -0
- package/dist/call-graph/extractors/java-data-access-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/java-data-access-extractor.js +611 -0
- package/dist/call-graph/extractors/java-data-access-extractor.js.map +1 -0
- package/dist/call-graph/extractors/java-extractor.d.ts +87 -0
- package/dist/call-graph/extractors/java-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/java-extractor.js +510 -0
- package/dist/call-graph/extractors/java-extractor.js.map +1 -0
- package/dist/call-graph/extractors/php-data-access-extractor.d.ts +93 -0
- package/dist/call-graph/extractors/php-data-access-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/php-data-access-extractor.js +589 -0
- package/dist/call-graph/extractors/php-data-access-extractor.js.map +1 -0
- package/dist/call-graph/extractors/php-extractor.d.ts +104 -0
- package/dist/call-graph/extractors/php-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/php-extractor.js +619 -0
- package/dist/call-graph/extractors/php-extractor.js.map +1 -0
- package/dist/call-graph/extractors/python-data-access-extractor.d.ts +90 -0
- package/dist/call-graph/extractors/python-data-access-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/python-data-access-extractor.js +537 -0
- package/dist/call-graph/extractors/python-data-access-extractor.js.map +1 -0
- package/dist/call-graph/extractors/python-extractor.d.ts +98 -0
- package/dist/call-graph/extractors/python-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/python-extractor.js +681 -0
- package/dist/call-graph/extractors/python-extractor.js.map +1 -0
- package/dist/call-graph/extractors/semantic-data-access-scanner.d.ts +91 -0
- package/dist/call-graph/extractors/semantic-data-access-scanner.d.ts.map +1 -0
- package/dist/call-graph/extractors/semantic-data-access-scanner.js +498 -0
- package/dist/call-graph/extractors/semantic-data-access-scanner.js.map +1 -0
- package/dist/call-graph/extractors/typescript-data-access-extractor.d.ts +122 -0
- package/dist/call-graph/extractors/typescript-data-access-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/typescript-data-access-extractor.js +788 -0
- package/dist/call-graph/extractors/typescript-data-access-extractor.js.map +1 -0
- package/dist/call-graph/extractors/typescript-extractor.d.ts +145 -0
- package/dist/call-graph/extractors/typescript-extractor.d.ts.map +1 -0
- package/dist/call-graph/extractors/typescript-extractor.js +904 -0
- package/dist/call-graph/extractors/typescript-extractor.js.map +1 -0
- package/dist/call-graph/index.d.ts +127 -0
- package/dist/call-graph/index.d.ts.map +1 -0
- package/dist/call-graph/index.js +247 -0
- package/dist/call-graph/index.js.map +1 -0
- package/dist/call-graph/store/call-graph-store.d.ts +70 -0
- package/dist/call-graph/store/call-graph-store.d.ts.map +1 -0
- package/dist/call-graph/store/call-graph-store.js +210 -0
- package/dist/call-graph/store/call-graph-store.js.map +1 -0
- package/dist/call-graph/store/index.d.ts +7 -0
- package/dist/call-graph/store/index.d.ts.map +1 -0
- package/dist/call-graph/store/index.js +7 -0
- package/dist/call-graph/store/index.js.map +1 -0
- package/dist/call-graph/types.d.ts +376 -0
- package/dist/call-graph/types.d.ts.map +1 -0
- package/dist/call-graph/types.js +8 -0
- package/dist/call-graph/types.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/lake/callgraph-shard-store.d.ts +168 -0
- package/dist/lake/callgraph-shard-store.d.ts.map +1 -0
- package/dist/lake/callgraph-shard-store.js +466 -0
- package/dist/lake/callgraph-shard-store.js.map +1 -0
- package/dist/lake/examples-store.d.ts +127 -0
- package/dist/lake/examples-store.d.ts.map +1 -0
- package/dist/lake/examples-store.js +389 -0
- package/dist/lake/examples-store.js.map +1 -0
- package/dist/lake/index-store.d.ts +82 -0
- package/dist/lake/index-store.d.ts.map +1 -0
- package/dist/lake/index-store.js +359 -0
- package/dist/lake/index-store.js.map +1 -0
- package/dist/lake/index.d.ts +93 -0
- package/dist/lake/index.d.ts.map +1 -0
- package/dist/lake/index.js +138 -0
- package/dist/lake/index.js.map +1 -0
- package/dist/lake/lake.bak/index-store.d.ts +82 -0
- package/dist/lake/lake.bak/index-store.d.ts.map +1 -0
- package/dist/lake/lake.bak/index-store.js +357 -0
- package/dist/lake/lake.bak/index-store.js.map +1 -0
- package/dist/lake/lake.bak/index.d.ts +81 -0
- package/dist/lake/lake.bak/index.d.ts.map +1 -0
- package/dist/lake/lake.bak/index.js +114 -0
- package/dist/lake/lake.bak/index.js.map +1 -0
- package/dist/lake/lake.bak/manifest-store.d.ts +51 -0
- package/dist/lake/lake.bak/manifest-store.d.ts.map +1 -0
- package/dist/lake/lake.bak/manifest-store.js +347 -0
- package/dist/lake/lake.bak/manifest-store.js.map +1 -0
- package/dist/lake/lake.bak/query-engine.d.ts +112 -0
- package/dist/lake/lake.bak/query-engine.d.ts.map +1 -0
- package/dist/lake/lake.bak/query-engine.js +370 -0
- package/dist/lake/lake.bak/query-engine.js.map +1 -0
- package/dist/lake/lake.bak/types.d.ts +428 -0
- package/dist/lake/lake.bak/types.d.ts.map +1 -0
- package/dist/lake/lake.bak/types.js +46 -0
- package/dist/lake/lake.bak/types.js.map +1 -0
- package/dist/lake/lake.bak/view-materializer.d.ts +70 -0
- package/dist/lake/lake.bak/view-materializer.d.ts.map +1 -0
- package/dist/lake/lake.bak/view-materializer.js +314 -0
- package/dist/lake/lake.bak/view-materializer.js.map +1 -0
- package/dist/lake/lake.bak/view-store.d.ts +57 -0
- package/dist/lake/lake.bak/view-store.d.ts.map +1 -0
- package/dist/lake/lake.bak/view-store.js +348 -0
- package/dist/lake/lake.bak/view-store.js.map +1 -0
- package/dist/lake/manifest-store.d.ts +51 -0
- package/dist/lake/manifest-store.d.ts.map +1 -0
- package/dist/lake/manifest-store.js +348 -0
- package/dist/lake/manifest-store.js.map +1 -0
- package/dist/lake/pattern-shard-store.d.ts +87 -0
- package/dist/lake/pattern-shard-store.d.ts.map +1 -0
- package/dist/lake/pattern-shard-store.js +347 -0
- package/dist/lake/pattern-shard-store.js.map +1 -0
- package/dist/lake/query-engine.d.ts +124 -0
- package/dist/lake/query-engine.d.ts.map +1 -0
- package/dist/lake/query-engine.js +453 -0
- package/dist/lake/query-engine.js.map +1 -0
- package/dist/lake/security-shard-store.d.ts +156 -0
- package/dist/lake/security-shard-store.d.ts.map +1 -0
- package/dist/lake/security-shard-store.js +498 -0
- package/dist/lake/security-shard-store.js.map +1 -0
- package/dist/lake/types.d.ts +428 -0
- package/dist/lake/types.d.ts.map +1 -0
- package/dist/lake/types.js +46 -0
- package/dist/lake/types.js.map +1 -0
- package/dist/lake/view-materializer.d.ts +70 -0
- package/dist/lake/view-materializer.d.ts.map +1 -0
- package/dist/lake/view-materializer.js +314 -0
- package/dist/lake/view-materializer.js.map +1 -0
- package/dist/lake/view-store.d.ts +57 -0
- package/dist/lake/view-store.d.ts.map +1 -0
- package/dist/lake/view-store.js +348 -0
- package/dist/lake/view-store.js.map +1 -0
- package/dist/parsers/tree-sitter/index.d.ts +1 -0
- package/dist/parsers/tree-sitter/index.d.ts.map +1 -1
- package/dist/parsers/tree-sitter/index.js +4 -0
- package/dist/parsers/tree-sitter/index.js.map +1 -1
- package/dist/parsers/tree-sitter/typescript-loader.d.ts +58 -0
- package/dist/parsers/tree-sitter/typescript-loader.d.ts.map +1 -0
- package/dist/parsers/tree-sitter/typescript-loader.js +250 -0
- package/dist/parsers/tree-sitter/typescript-loader.js.map +1 -0
- package/dist/store/project-config.d.ts +154 -0
- package/dist/store/project-config.d.ts.map +1 -0
- package/dist/store/project-config.js +235 -0
- package/dist/store/project-config.js.map +1 -0
- package/dist/store/project-registry.d.ts +241 -0
- package/dist/store/project-registry.d.ts.map +1 -0
- package/dist/store/project-registry.js +557 -0
- package/dist/store/project-registry.js.map +1 -0
- package/package.json +16 -14
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python Semantic Data Access Extractor
|
|
3
|
+
*
|
|
4
|
+
* Extracts data access points from Python using tree-sitter.
|
|
5
|
+
* Provides accurate, semantic-aware detection of database operations.
|
|
6
|
+
*
|
|
7
|
+
* Supports:
|
|
8
|
+
* - Django ORM: User.objects.filter()
|
|
9
|
+
* - SQLAlchemy: session.query(User).filter()
|
|
10
|
+
* - Supabase Python: supabase.table('users').select()
|
|
11
|
+
* - Raw SQL: cursor.execute('SELECT * FROM users')
|
|
12
|
+
* - Tortoise ORM: await User.filter()
|
|
13
|
+
* - Peewee: User.select()
|
|
14
|
+
*/
|
|
15
|
+
import { BaseDataAccessExtractor, type DataAccessExtractionResult } from './data-access-extractor.js';
|
|
16
|
+
import type { CallGraphLanguage } from '../types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Python data access extractor using tree-sitter
|
|
19
|
+
*/
|
|
20
|
+
export declare class PythonDataAccessExtractor extends BaseDataAccessExtractor {
|
|
21
|
+
readonly language: CallGraphLanguage;
|
|
22
|
+
readonly extensions: string[];
|
|
23
|
+
private parser;
|
|
24
|
+
/**
|
|
25
|
+
* Check if tree-sitter is available
|
|
26
|
+
*/
|
|
27
|
+
static isAvailable(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Extract data access points from Python source
|
|
30
|
+
*/
|
|
31
|
+
extract(source: string, filePath: string): DataAccessExtractionResult;
|
|
32
|
+
/**
|
|
33
|
+
* Visit AST nodes to find data access patterns
|
|
34
|
+
*/
|
|
35
|
+
private visitNode;
|
|
36
|
+
/**
|
|
37
|
+
* Analyze a call expression for data access patterns
|
|
38
|
+
*/
|
|
39
|
+
private analyzeCallExpression;
|
|
40
|
+
/**
|
|
41
|
+
* Get the call chain from a call expression
|
|
42
|
+
* e.g., User.objects.filter() -> ['User', 'objects', 'filter']
|
|
43
|
+
*/
|
|
44
|
+
private getCallChain;
|
|
45
|
+
/**
|
|
46
|
+
* Try to match Django ORM pattern: Model.objects.filter()
|
|
47
|
+
*/
|
|
48
|
+
private tryDjangoPattern;
|
|
49
|
+
/**
|
|
50
|
+
* Try to match SQLAlchemy pattern: session.query(Model).filter()
|
|
51
|
+
*/
|
|
52
|
+
private trySQLAlchemyPattern;
|
|
53
|
+
/**
|
|
54
|
+
* Try to match Supabase Python pattern: supabase.table('users').select()
|
|
55
|
+
*/
|
|
56
|
+
private trySupabasePythonPattern;
|
|
57
|
+
/**
|
|
58
|
+
* Check if a method name is a where clause method
|
|
59
|
+
*/
|
|
60
|
+
private isWhereClauseMethod;
|
|
61
|
+
/**
|
|
62
|
+
* Extract field name from a where clause method call
|
|
63
|
+
*/
|
|
64
|
+
private extractWhereClauseField;
|
|
65
|
+
/**
|
|
66
|
+
* Try to match Tortoise ORM pattern: await Model.filter()
|
|
67
|
+
*/
|
|
68
|
+
private tryTortoisePattern;
|
|
69
|
+
/**
|
|
70
|
+
* Try to match Peewee pattern: Model.select()
|
|
71
|
+
*/
|
|
72
|
+
private tryPeeweePattern;
|
|
73
|
+
/**
|
|
74
|
+
* Try to match raw SQL pattern: cursor.execute('SELECT * FROM users')
|
|
75
|
+
*/
|
|
76
|
+
private tryRawSQLPattern;
|
|
77
|
+
/**
|
|
78
|
+
* Parse a SQL statement to extract table, operation, and fields
|
|
79
|
+
*/
|
|
80
|
+
private parseSQLStatement;
|
|
81
|
+
/**
|
|
82
|
+
* Extract string arguments from a list of nodes
|
|
83
|
+
*/
|
|
84
|
+
private extractStringArgs;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Create a Python data access extractor
|
|
88
|
+
*/
|
|
89
|
+
export declare function createPythonDataAccessExtractor(): PythonDataAccessExtractor;
|
|
90
|
+
//# sourceMappingURL=python-data-access-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-data-access-extractor.d.ts","sourceRoot":"","sources":["../../../src/call-graph/extractors/python-data-access-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,uBAAuB,EAAE,KAAK,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACtG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKrD;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,uBAAuB;IACpE,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAY;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAA2B;IAExD,OAAO,CAAC,MAAM,CAAiC;IAE/C;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,OAAO;IAI7B;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,0BAA0B;IAuBrE;;OAEG;IACH,OAAO,CAAC,SAAS;IAiBjB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA2B7B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAwDpB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuExB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAmD5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAsEhC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAgB3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA2B/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAoC1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAoCxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA6CxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA2CzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAS1B;AAED;;GAEG;AACH,wBAAgB,+BAA+B,IAAI,yBAAyB,CAE3E"}
|
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python Semantic Data Access Extractor
|
|
3
|
+
*
|
|
4
|
+
* Extracts data access points from Python using tree-sitter.
|
|
5
|
+
* Provides accurate, semantic-aware detection of database operations.
|
|
6
|
+
*
|
|
7
|
+
* Supports:
|
|
8
|
+
* - Django ORM: User.objects.filter()
|
|
9
|
+
* - SQLAlchemy: session.query(User).filter()
|
|
10
|
+
* - Supabase Python: supabase.table('users').select()
|
|
11
|
+
* - Raw SQL: cursor.execute('SELECT * FROM users')
|
|
12
|
+
* - Tortoise ORM: await User.filter()
|
|
13
|
+
* - Peewee: User.select()
|
|
14
|
+
*/
|
|
15
|
+
import { BaseDataAccessExtractor } from './data-access-extractor.js';
|
|
16
|
+
import { isTreeSitterAvailable, createPythonParser } from '../../parsers/tree-sitter/loader.js';
|
|
17
|
+
/**
|
|
18
|
+
* Python data access extractor using tree-sitter
|
|
19
|
+
*/
|
|
20
|
+
export class PythonDataAccessExtractor extends BaseDataAccessExtractor {
|
|
21
|
+
language = 'python';
|
|
22
|
+
extensions = ['.py', '.pyw', '.pyi'];
|
|
23
|
+
parser = null;
|
|
24
|
+
/**
|
|
25
|
+
* Check if tree-sitter is available
|
|
26
|
+
*/
|
|
27
|
+
static isAvailable() {
|
|
28
|
+
return isTreeSitterAvailable();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Extract data access points from Python source
|
|
32
|
+
*/
|
|
33
|
+
extract(source, filePath) {
|
|
34
|
+
const result = this.createEmptyResult(filePath);
|
|
35
|
+
if (!isTreeSitterAvailable()) {
|
|
36
|
+
result.errors.push('Tree-sitter not available for Python parsing');
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
if (!this.parser) {
|
|
41
|
+
this.parser = createPythonParser();
|
|
42
|
+
}
|
|
43
|
+
const tree = this.parser.parse(source);
|
|
44
|
+
this.visitNode(tree.rootNode, result, filePath, source);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
result.errors.push(error instanceof Error ? error.message : 'Unknown parse error');
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Visit AST nodes to find data access patterns
|
|
53
|
+
*/
|
|
54
|
+
visitNode(node, result, filePath, source) {
|
|
55
|
+
// Check for call expressions
|
|
56
|
+
if (node.type === 'call') {
|
|
57
|
+
this.analyzeCallExpression(node, result, filePath, source);
|
|
58
|
+
}
|
|
59
|
+
// Recurse into children
|
|
60
|
+
for (const child of node.children) {
|
|
61
|
+
this.visitNode(child, result, filePath, source);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Analyze a call expression for data access patterns
|
|
66
|
+
*/
|
|
67
|
+
analyzeCallExpression(node, result, filePath, source) {
|
|
68
|
+
// Get the full call chain
|
|
69
|
+
const chain = this.getCallChain(node);
|
|
70
|
+
// Try each pattern
|
|
71
|
+
const accessPoint = this.tryDjangoPattern(chain, node, filePath, source) ||
|
|
72
|
+
this.trySQLAlchemyPattern(chain, node, filePath, source) ||
|
|
73
|
+
this.trySupabasePythonPattern(chain, node, filePath, source) ||
|
|
74
|
+
this.tryTortoisePattern(chain, node, filePath, source) ||
|
|
75
|
+
this.tryPeeweePattern(chain, node, filePath, source) ||
|
|
76
|
+
this.tryRawSQLPattern(chain, node, filePath, source);
|
|
77
|
+
if (accessPoint) {
|
|
78
|
+
// Avoid duplicates
|
|
79
|
+
const exists = result.accessPoints.some(ap => ap.id === accessPoint.id);
|
|
80
|
+
if (!exists) {
|
|
81
|
+
result.accessPoints.push(accessPoint);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get the call chain from a call expression
|
|
87
|
+
* e.g., User.objects.filter() -> ['User', 'objects', 'filter']
|
|
88
|
+
*/
|
|
89
|
+
getCallChain(node) {
|
|
90
|
+
const names = [];
|
|
91
|
+
const args = [];
|
|
92
|
+
let current = node;
|
|
93
|
+
while (current) {
|
|
94
|
+
if (current.type === 'call') {
|
|
95
|
+
// Get arguments
|
|
96
|
+
const argsNode = current.childForFieldName('arguments');
|
|
97
|
+
if (argsNode) {
|
|
98
|
+
const argList = [];
|
|
99
|
+
for (const child of argsNode.children) {
|
|
100
|
+
if (child.type !== '(' && child.type !== ')' && child.type !== ',') {
|
|
101
|
+
argList.push(child);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
args.unshift(argList);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
args.unshift([]);
|
|
108
|
+
}
|
|
109
|
+
const funcNode = current.childForFieldName('function');
|
|
110
|
+
if (!funcNode)
|
|
111
|
+
break;
|
|
112
|
+
if (funcNode.type === 'attribute') {
|
|
113
|
+
const attrNode = funcNode.childForFieldName('attribute');
|
|
114
|
+
if (attrNode) {
|
|
115
|
+
names.unshift(attrNode.text);
|
|
116
|
+
}
|
|
117
|
+
const objNode = funcNode.childForFieldName('object');
|
|
118
|
+
current = objNode;
|
|
119
|
+
}
|
|
120
|
+
else if (funcNode.type === 'identifier') {
|
|
121
|
+
names.unshift(funcNode.text);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else if (current.type === 'attribute') {
|
|
129
|
+
const attrNode = current.childForFieldName('attribute');
|
|
130
|
+
if (attrNode) {
|
|
131
|
+
names.unshift(attrNode.text);
|
|
132
|
+
}
|
|
133
|
+
const objNode = current.childForFieldName('object');
|
|
134
|
+
current = objNode;
|
|
135
|
+
}
|
|
136
|
+
else if (current.type === 'identifier') {
|
|
137
|
+
names.unshift(current.text);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return { names, args };
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Try to match Django ORM pattern: Model.objects.filter()
|
|
148
|
+
*/
|
|
149
|
+
tryDjangoPattern(chain, node, filePath, _source) {
|
|
150
|
+
// Look for .objects. in the chain
|
|
151
|
+
const objectsIndex = chain.names.indexOf('objects');
|
|
152
|
+
if (objectsIndex === -1 || objectsIndex === 0)
|
|
153
|
+
return null;
|
|
154
|
+
// Model name is before 'objects'
|
|
155
|
+
const modelName = chain.names[objectsIndex - 1];
|
|
156
|
+
if (!modelName || !/^[A-Z]/.test(modelName))
|
|
157
|
+
return null;
|
|
158
|
+
// Method is after 'objects'
|
|
159
|
+
const methodName = chain.names[objectsIndex + 1];
|
|
160
|
+
if (!methodName)
|
|
161
|
+
return null;
|
|
162
|
+
const djangoMethods = ['get', 'filter', 'exclude', 'all', 'first', 'last', 'create', 'update', 'delete',
|
|
163
|
+
'get_or_create', 'update_or_create', 'bulk_create', 'bulk_update', 'count', 'exists',
|
|
164
|
+
'values', 'values_list', 'annotate', 'aggregate', 'order_by', 'distinct'];
|
|
165
|
+
if (!djangoMethods.includes(methodName))
|
|
166
|
+
return null;
|
|
167
|
+
const operation = this.detectOperation(methodName);
|
|
168
|
+
if (!operation)
|
|
169
|
+
return null;
|
|
170
|
+
// Extract fields from values() or values_list()
|
|
171
|
+
let fields = [];
|
|
172
|
+
const whereFields = [];
|
|
173
|
+
if (methodName === 'values' || methodName === 'values_list') {
|
|
174
|
+
const methodArgs = chain.args[objectsIndex + 1];
|
|
175
|
+
if (methodArgs) {
|
|
176
|
+
fields = this.extractStringArgs(methodArgs);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Extract fields from filter/exclude/get kwargs
|
|
180
|
+
if (methodName === 'filter' || methodName === 'exclude' || methodName === 'get') {
|
|
181
|
+
const methodArgs = chain.args[objectsIndex + 1];
|
|
182
|
+
if (methodArgs) {
|
|
183
|
+
for (const arg of methodArgs) {
|
|
184
|
+
if (arg.type === 'keyword_argument') {
|
|
185
|
+
const nameNode = arg.childForFieldName('name');
|
|
186
|
+
if (nameNode) {
|
|
187
|
+
// Django uses field__lookup syntax, extract base field
|
|
188
|
+
const fieldName = nameNode.text.split('__')[0];
|
|
189
|
+
if (fieldName) {
|
|
190
|
+
whereFields.push(fieldName);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Merge fields
|
|
198
|
+
const allFields = [...new Set([...fields, ...whereFields])];
|
|
199
|
+
return this.createAccessPoint({
|
|
200
|
+
table: this.inferTableFromName(modelName),
|
|
201
|
+
fields: allFields,
|
|
202
|
+
operation,
|
|
203
|
+
file: filePath,
|
|
204
|
+
line: node.startPosition.row + 1,
|
|
205
|
+
column: node.startPosition.column,
|
|
206
|
+
context: node.text.slice(0, 200),
|
|
207
|
+
confidence: 0.95,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Try to match SQLAlchemy pattern: session.query(Model).filter()
|
|
212
|
+
*/
|
|
213
|
+
trySQLAlchemyPattern(chain, node, filePath, _source) {
|
|
214
|
+
// Look for .query() in the chain
|
|
215
|
+
const queryIndex = chain.names.indexOf('query');
|
|
216
|
+
if (queryIndex === -1)
|
|
217
|
+
return null;
|
|
218
|
+
// Get model from query(Model) argument
|
|
219
|
+
const queryArgs = chain.args[queryIndex];
|
|
220
|
+
if (!queryArgs || queryArgs.length === 0)
|
|
221
|
+
return null;
|
|
222
|
+
const modelArg = queryArgs[0];
|
|
223
|
+
if (!modelArg || modelArg.type !== 'identifier')
|
|
224
|
+
return null;
|
|
225
|
+
const modelName = modelArg.text;
|
|
226
|
+
if (!/^[A-Z]/.test(modelName))
|
|
227
|
+
return null;
|
|
228
|
+
// Determine operation from chain
|
|
229
|
+
let operation = 'read';
|
|
230
|
+
for (let i = queryIndex + 1; i < chain.names.length; i++) {
|
|
231
|
+
const method = chain.names[i];
|
|
232
|
+
if (method === 'delete') {
|
|
233
|
+
operation = 'delete';
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
if (method === 'update') {
|
|
237
|
+
operation = 'write';
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Check for session.add/delete patterns
|
|
242
|
+
if (chain.names.includes('add') || chain.names.includes('add_all') || chain.names.includes('merge')) {
|
|
243
|
+
operation = 'write';
|
|
244
|
+
}
|
|
245
|
+
return this.createAccessPoint({
|
|
246
|
+
table: this.inferTableFromName(modelName),
|
|
247
|
+
fields: [],
|
|
248
|
+
operation,
|
|
249
|
+
file: filePath,
|
|
250
|
+
line: node.startPosition.row + 1,
|
|
251
|
+
column: node.startPosition.column,
|
|
252
|
+
context: node.text.slice(0, 200),
|
|
253
|
+
confidence: 0.9,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Try to match Supabase Python pattern: supabase.table('users').select()
|
|
258
|
+
*/
|
|
259
|
+
trySupabasePythonPattern(chain, node, filePath, _source) {
|
|
260
|
+
// Look for .table() or .from() in the chain
|
|
261
|
+
const tableIndex = chain.names.findIndex(n => n === 'table' || n === 'from');
|
|
262
|
+
if (tableIndex === -1)
|
|
263
|
+
return null;
|
|
264
|
+
// Check if it looks like supabase
|
|
265
|
+
const firstPart = chain.names[0]?.toLowerCase();
|
|
266
|
+
if (!firstPart?.includes('supabase') && !firstPart?.includes('client'))
|
|
267
|
+
return null;
|
|
268
|
+
// Get table name from .table('name') or .from('name')
|
|
269
|
+
const tableArgs = chain.args[tableIndex];
|
|
270
|
+
if (!tableArgs || tableArgs.length === 0)
|
|
271
|
+
return null;
|
|
272
|
+
const tableArg = tableArgs[0];
|
|
273
|
+
if (!tableArg || tableArg.type !== 'string')
|
|
274
|
+
return null;
|
|
275
|
+
// Extract string content (remove quotes)
|
|
276
|
+
const table = tableArg.text.replace(/^['"]|['"]$/g, '');
|
|
277
|
+
// Determine operation
|
|
278
|
+
let operation = 'read';
|
|
279
|
+
let fields = [];
|
|
280
|
+
const whereFields = [];
|
|
281
|
+
for (let i = tableIndex + 1; i < chain.names.length; i++) {
|
|
282
|
+
const method = chain.names[i];
|
|
283
|
+
const methodArgs = chain.args[i];
|
|
284
|
+
if (method === 'select' && methodArgs && methodArgs.length > 0) {
|
|
285
|
+
const selectArg = methodArgs[0];
|
|
286
|
+
if (selectArg?.type === 'string') {
|
|
287
|
+
fields = this.extractFieldsFromString(selectArg.text.replace(/^['"]|['"]$/g, ''));
|
|
288
|
+
}
|
|
289
|
+
operation = 'read';
|
|
290
|
+
}
|
|
291
|
+
else if (method === 'insert' || method === 'upsert') {
|
|
292
|
+
operation = 'write';
|
|
293
|
+
}
|
|
294
|
+
else if (method === 'update') {
|
|
295
|
+
operation = 'write';
|
|
296
|
+
}
|
|
297
|
+
else if (method === 'delete') {
|
|
298
|
+
operation = 'delete';
|
|
299
|
+
}
|
|
300
|
+
// Extract fields from where clause methods
|
|
301
|
+
else if (method && this.isWhereClauseMethod(method) && methodArgs && methodArgs.length > 0) {
|
|
302
|
+
const fieldName = this.extractWhereClauseField(methodArgs);
|
|
303
|
+
if (fieldName) {
|
|
304
|
+
whereFields.push(fieldName);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// Merge select fields with where clause fields (deduplicated)
|
|
309
|
+
const allFields = [...new Set([...fields, ...whereFields])];
|
|
310
|
+
return this.createAccessPoint({
|
|
311
|
+
table,
|
|
312
|
+
fields: allFields,
|
|
313
|
+
operation,
|
|
314
|
+
file: filePath,
|
|
315
|
+
line: node.startPosition.row + 1,
|
|
316
|
+
column: node.startPosition.column,
|
|
317
|
+
context: node.text.slice(0, 200),
|
|
318
|
+
confidence: 0.95,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Check if a method name is a where clause method
|
|
323
|
+
*/
|
|
324
|
+
isWhereClauseMethod(method) {
|
|
325
|
+
const whereClauseMethods = [
|
|
326
|
+
// Supabase/PostgREST
|
|
327
|
+
'eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'like', 'ilike', 'is_', 'in_',
|
|
328
|
+
'contains', 'contained_by', 'range_gt', 'range_gte', 'range_lt', 'range_lte',
|
|
329
|
+
'range_adjacent', 'overlaps', 'text_search', 'match', 'not_', 'or_', 'filter',
|
|
330
|
+
// Django ORM
|
|
331
|
+
'filter', 'exclude', 'get',
|
|
332
|
+
// SQLAlchemy
|
|
333
|
+
'filter', 'filter_by', 'where',
|
|
334
|
+
// Peewee
|
|
335
|
+
'where',
|
|
336
|
+
];
|
|
337
|
+
return whereClauseMethods.includes(method);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Extract field name from a where clause method call
|
|
341
|
+
*/
|
|
342
|
+
extractWhereClauseField(args) {
|
|
343
|
+
if (args.length === 0)
|
|
344
|
+
return null;
|
|
345
|
+
const firstArg = args[0];
|
|
346
|
+
if (!firstArg)
|
|
347
|
+
return null;
|
|
348
|
+
// String argument: .eq('email', value)
|
|
349
|
+
if (firstArg.type === 'string') {
|
|
350
|
+
return firstArg.text.replace(/^['"]|['"]$/g, '');
|
|
351
|
+
}
|
|
352
|
+
// Keyword argument: filter(email=value) - extract from keyword_argument
|
|
353
|
+
if (firstArg.type === 'keyword_argument') {
|
|
354
|
+
const nameNode = firstArg.childForFieldName('name');
|
|
355
|
+
if (nameNode) {
|
|
356
|
+
return nameNode.text;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
// Identifier
|
|
360
|
+
if (firstArg.type === 'identifier') {
|
|
361
|
+
return firstArg.text;
|
|
362
|
+
}
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Try to match Tortoise ORM pattern: await Model.filter()
|
|
367
|
+
*/
|
|
368
|
+
tryTortoisePattern(chain, node, filePath, _source) {
|
|
369
|
+
if (chain.names.length < 2)
|
|
370
|
+
return null;
|
|
371
|
+
const modelName = chain.names[0];
|
|
372
|
+
const methodName = chain.names[1];
|
|
373
|
+
if (!modelName || !methodName)
|
|
374
|
+
return null;
|
|
375
|
+
if (!/^[A-Z]/.test(modelName))
|
|
376
|
+
return null;
|
|
377
|
+
const tortoiseMethods = ['filter', 'get', 'get_or_none', 'all', 'first', 'create', 'update', 'delete',
|
|
378
|
+
'get_or_create', 'update_or_create', 'bulk_create', 'bulk_update', 'count', 'exists'];
|
|
379
|
+
if (!tortoiseMethods.includes(methodName))
|
|
380
|
+
return null;
|
|
381
|
+
// Skip if it looks like Django (has .objects)
|
|
382
|
+
if (chain.names.includes('objects'))
|
|
383
|
+
return null;
|
|
384
|
+
const operation = this.detectOperation(methodName);
|
|
385
|
+
if (!operation)
|
|
386
|
+
return null;
|
|
387
|
+
return this.createAccessPoint({
|
|
388
|
+
table: this.inferTableFromName(modelName),
|
|
389
|
+
fields: [],
|
|
390
|
+
operation,
|
|
391
|
+
file: filePath,
|
|
392
|
+
line: node.startPosition.row + 1,
|
|
393
|
+
column: node.startPosition.column,
|
|
394
|
+
context: node.text.slice(0, 200),
|
|
395
|
+
confidence: 0.8,
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Try to match Peewee pattern: Model.select()
|
|
400
|
+
*/
|
|
401
|
+
tryPeeweePattern(chain, node, filePath, _source) {
|
|
402
|
+
if (chain.names.length < 2)
|
|
403
|
+
return null;
|
|
404
|
+
const modelName = chain.names[0];
|
|
405
|
+
const methodName = chain.names[1];
|
|
406
|
+
if (!modelName || !methodName)
|
|
407
|
+
return null;
|
|
408
|
+
if (!/^[A-Z]/.test(modelName))
|
|
409
|
+
return null;
|
|
410
|
+
const peeweeMethods = ['select', 'get', 'get_or_none', 'get_or_create', 'create', 'insert', 'insert_many',
|
|
411
|
+
'update', 'delete', 'delete_instance'];
|
|
412
|
+
if (!peeweeMethods.includes(methodName))
|
|
413
|
+
return null;
|
|
414
|
+
// Skip if it looks like Django (has .objects)
|
|
415
|
+
if (chain.names.includes('objects'))
|
|
416
|
+
return null;
|
|
417
|
+
const operation = this.detectOperation(methodName);
|
|
418
|
+
if (!operation)
|
|
419
|
+
return null;
|
|
420
|
+
return this.createAccessPoint({
|
|
421
|
+
table: this.inferTableFromName(modelName),
|
|
422
|
+
fields: [],
|
|
423
|
+
operation,
|
|
424
|
+
file: filePath,
|
|
425
|
+
line: node.startPosition.row + 1,
|
|
426
|
+
column: node.startPosition.column,
|
|
427
|
+
context: node.text.slice(0, 200),
|
|
428
|
+
confidence: 0.8,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Try to match raw SQL pattern: cursor.execute('SELECT * FROM users')
|
|
433
|
+
*/
|
|
434
|
+
tryRawSQLPattern(chain, node, filePath, _source) {
|
|
435
|
+
// Look for execute/executemany/raw methods
|
|
436
|
+
const sqlMethods = ['execute', 'executemany', 'raw', 'executescript', 'mogrify'];
|
|
437
|
+
const methodIndex = chain.names.findIndex(n => sqlMethods.includes(n));
|
|
438
|
+
if (methodIndex === -1)
|
|
439
|
+
return null;
|
|
440
|
+
const methodArgs = chain.args[methodIndex];
|
|
441
|
+
if (!methodArgs || methodArgs.length === 0)
|
|
442
|
+
return null;
|
|
443
|
+
const sqlArg = methodArgs[0];
|
|
444
|
+
if (!sqlArg)
|
|
445
|
+
return null;
|
|
446
|
+
let sqlText = '';
|
|
447
|
+
if (sqlArg.type === 'string') {
|
|
448
|
+
sqlText = sqlArg.text.replace(/^['"]|['"]$/g, '').replace(/^f['"]|['"]$/g, '');
|
|
449
|
+
}
|
|
450
|
+
else if (sqlArg.type === 'concatenated_string') {
|
|
451
|
+
// Handle multi-line strings
|
|
452
|
+
sqlText = sqlArg.text;
|
|
453
|
+
}
|
|
454
|
+
if (!sqlText)
|
|
455
|
+
return null;
|
|
456
|
+
// Parse SQL to extract table and operation
|
|
457
|
+
const { table, operation, fields } = this.parseSQLStatement(sqlText);
|
|
458
|
+
if (!table || table === 'unknown')
|
|
459
|
+
return null;
|
|
460
|
+
return this.createAccessPoint({
|
|
461
|
+
table,
|
|
462
|
+
fields,
|
|
463
|
+
operation,
|
|
464
|
+
file: filePath,
|
|
465
|
+
line: node.startPosition.row + 1,
|
|
466
|
+
column: node.startPosition.column,
|
|
467
|
+
context: node.text.slice(0, 200),
|
|
468
|
+
isRawSql: true,
|
|
469
|
+
confidence: 0.8,
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Parse a SQL statement to extract table, operation, and fields
|
|
474
|
+
*/
|
|
475
|
+
parseSQLStatement(sql) {
|
|
476
|
+
const upperSql = sql.toUpperCase().trim();
|
|
477
|
+
let operation = 'unknown';
|
|
478
|
+
let table = 'unknown';
|
|
479
|
+
const fields = [];
|
|
480
|
+
// Determine operation
|
|
481
|
+
if (upperSql.startsWith('SELECT')) {
|
|
482
|
+
operation = 'read';
|
|
483
|
+
}
|
|
484
|
+
else if (upperSql.startsWith('INSERT')) {
|
|
485
|
+
operation = 'write';
|
|
486
|
+
}
|
|
487
|
+
else if (upperSql.startsWith('UPDATE')) {
|
|
488
|
+
operation = 'write';
|
|
489
|
+
}
|
|
490
|
+
else if (upperSql.startsWith('DELETE')) {
|
|
491
|
+
operation = 'delete';
|
|
492
|
+
}
|
|
493
|
+
// Extract table name
|
|
494
|
+
const fromMatch = sql.match(/FROM\s+["'`]?(\w+)["'`]?/i);
|
|
495
|
+
const intoMatch = sql.match(/INTO\s+["'`]?(\w+)["'`]?/i);
|
|
496
|
+
const updateMatch = sql.match(/UPDATE\s+["'`]?(\w+)["'`]?/i);
|
|
497
|
+
if (fromMatch?.[1])
|
|
498
|
+
table = fromMatch[1];
|
|
499
|
+
else if (intoMatch?.[1])
|
|
500
|
+
table = intoMatch[1];
|
|
501
|
+
else if (updateMatch?.[1])
|
|
502
|
+
table = updateMatch[1];
|
|
503
|
+
// Extract fields from SELECT
|
|
504
|
+
if (operation === 'read') {
|
|
505
|
+
const selectMatch = sql.match(/SELECT\s+(.+?)\s+FROM/i);
|
|
506
|
+
if (selectMatch?.[1] && selectMatch[1] !== '*') {
|
|
507
|
+
const fieldList = selectMatch[1].split(',').map(f => f.trim());
|
|
508
|
+
for (const field of fieldList) {
|
|
509
|
+
const fieldName = field.split(/\s+as\s+/i)[0]?.trim();
|
|
510
|
+
if (fieldName && !fieldName.includes('(')) {
|
|
511
|
+
fields.push(fieldName.replace(/["'`]/g, ''));
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return { table, operation, fields };
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Extract string arguments from a list of nodes
|
|
520
|
+
*/
|
|
521
|
+
extractStringArgs(args) {
|
|
522
|
+
const strings = [];
|
|
523
|
+
for (const arg of args) {
|
|
524
|
+
if (arg.type === 'string') {
|
|
525
|
+
strings.push(arg.text.replace(/^['"]|['"]$/g, ''));
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return strings;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Create a Python data access extractor
|
|
533
|
+
*/
|
|
534
|
+
export function createPythonDataAccessExtractor() {
|
|
535
|
+
return new PythonDataAccessExtractor();
|
|
536
|
+
}
|
|
537
|
+
//# sourceMappingURL=python-data-access-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-data-access-extractor.js","sourceRoot":"","sources":["../../../src/call-graph/extractors/python-data-access-extractor.ts"],"names":[],"mappings":"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"}
|