@linkup-ai/abap-ai 2.0.0
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/README.md +384 -0
- package/dist/adt-client.js +364 -0
- package/dist/cli/activate.js +113 -0
- package/dist/cli/init.js +333 -0
- package/dist/cli/remove.js +80 -0
- package/dist/cli/status.js +229 -0
- package/dist/cli/systems.js +68 -0
- package/dist/cli.js +81 -0
- package/dist/index.js +1318 -0
- package/dist/knowledge/abap/abap-dictionary.md +199 -0
- package/dist/knowledge/abap/abap-sql.md +296 -0
- package/dist/knowledge/abap/amdp.md +273 -0
- package/dist/knowledge/abap/clean-code.md +293 -0
- package/dist/knowledge/abap/cloud-background-processing.md +250 -0
- package/dist/knowledge/abap/cloud-communication.md +265 -0
- package/dist/knowledge/abap/cloud-development.md +176 -0
- package/dist/knowledge/abap/cloud-extensibility.md +252 -0
- package/dist/knowledge/abap/cloud-released-apis.md +261 -0
- package/dist/knowledge/abap/constructor-expressions.md +289 -0
- package/dist/knowledge/abap/enhancements.md +232 -0
- package/dist/knowledge/abap/exceptions.md +271 -0
- package/dist/knowledge/abap/internal-tables.md +205 -0
- package/dist/knowledge/abap/object-orientation.md +298 -0
- package/dist/knowledge/abap/performance.md +216 -0
- package/dist/knowledge/abap/rap-abstract-entities.md +206 -0
- package/dist/knowledge/abap/rap-business-events.md +216 -0
- package/dist/knowledge/abap/rap-draft.md +191 -0
- package/dist/knowledge/abap/rap-eml.md +453 -0
- package/dist/knowledge/abap/rap-end-to-end.md +486 -0
- package/dist/knowledge/abap/rap-feature-control.md +185 -0
- package/dist/knowledge/abap/rap-numbering.md +280 -0
- package/dist/knowledge/abap/rap-service-exposure.md +163 -0
- package/dist/knowledge/abap/rap-unmanaged.md +468 -0
- package/dist/knowledge/abap/string-processing.md +180 -0
- package/dist/knowledge/abap/unit-testing.md +303 -0
- package/dist/knowledge/abap-cds/access-control.md +241 -0
- package/dist/knowledge/abap-cds/annotations.md +331 -0
- package/dist/knowledge/abap-cds/associations.md +254 -0
- package/dist/knowledge/abap-cds/expressions.md +230 -0
- package/dist/knowledge/abap-cds/functions.md +245 -0
- package/dist/knowledge/abap-cds/metadata-extensions.md +294 -0
- package/dist/knowledge/cap/authentication.md +278 -0
- package/dist/knowledge/cap/cdl-syntax.md +247 -0
- package/dist/knowledge/cap/cql-queries.md +266 -0
- package/dist/knowledge/cap/deployment.md +343 -0
- package/dist/knowledge/cap/event-handlers.md +287 -0
- package/dist/knowledge/cap/fiori-integration.md +303 -0
- package/dist/knowledge/cap/service-definitions.md +287 -0
- package/dist/knowledge/fiori/annotations.md +347 -0
- package/dist/knowledge/fiori/deployment.md +340 -0
- package/dist/knowledge/fiori/fiori-elements.md +332 -0
- package/dist/knowledge/fiori/fiori-side-effects.md +107 -0
- package/dist/knowledge/fiori/fiori-valuelist.md +144 -0
- package/dist/knowledge/fiori/ui5-controllers.md +358 -0
- package/dist/knowledge/fiori/ui5-data-binding.md +311 -0
- package/dist/knowledge/fiori/ui5-fragments-dialogs.md +330 -0
- package/dist/knowledge/fiori/ui5-manifest.md +411 -0
- package/dist/knowledge/fiori/ui5-routing.md +303 -0
- package/dist/knowledge/fiori/ui5-xml-views.md +294 -0
- package/dist/logger.js +114 -0
- package/dist/system-profile.js +207 -0
- package/dist/tools/abap-doc.js +72 -0
- package/dist/tools/abapgit.js +161 -0
- package/dist/tools/activate.js +68 -0
- package/dist/tools/atc-check.js +117 -0
- package/dist/tools/auth-object.js +56 -0
- package/dist/tools/breakpoints.js +76 -0
- package/dist/tools/call-hierarchy.js +84 -0
- package/dist/tools/cds-annotations.js +98 -0
- package/dist/tools/cds-dependencies.js +65 -0
- package/dist/tools/check.js +47 -0
- package/dist/tools/code-completion.js +70 -0
- package/dist/tools/code-coverage.js +111 -0
- package/dist/tools/create-amdp.js +111 -0
- package/dist/tools/create-dcl.js +81 -0
- package/dist/tools/create-transport.js +38 -0
- package/dist/tools/create.js +285 -0
- package/dist/tools/data-preview.js +37 -0
- package/dist/tools/delete.js +45 -0
- package/dist/tools/deploy-bsp.js +298 -0
- package/dist/tools/discovery.js +59 -0
- package/dist/tools/element-info.js +93 -0
- package/dist/tools/enhancements.js +186 -0
- package/dist/tools/extract-method.js +44 -0
- package/dist/tools/function-group.js +59 -0
- package/dist/tools/knowledge.js +275 -0
- package/dist/tools/lock-object.js +75 -0
- package/dist/tools/message-class.js +67 -0
- package/dist/tools/navigate.js +80 -0
- package/dist/tools/number-range.js +57 -0
- package/dist/tools/object-documentation.js +43 -0
- package/dist/tools/object-structure.js +78 -0
- package/dist/tools/object-versions.js +57 -0
- package/dist/tools/package-contents.js +60 -0
- package/dist/tools/pretty-printer.js +35 -0
- package/dist/tools/publish-binding.js +49 -0
- package/dist/tools/quick-fix.js +69 -0
- package/dist/tools/read.js +167 -0
- package/dist/tools/refactor-rename.js +60 -0
- package/dist/tools/release-transport.js +24 -0
- package/dist/tools/released-apis.js +51 -0
- package/dist/tools/repository-tree.js +90 -0
- package/dist/tools/scaffold-rap.js +642 -0
- package/dist/tools/search.js +73 -0
- package/dist/tools/shared/data-format.js +101 -0
- package/dist/tools/sql-console.js +17 -0
- package/dist/tools/system-info.js +270 -0
- package/dist/tools/traces.js +66 -0
- package/dist/tools/transport-contents.js +83 -0
- package/dist/tools/transports.js +67 -0
- package/dist/tools/unit-test.js +135 -0
- package/dist/tools/where-used.js +59 -0
- package/dist/tools/write.js +101 -0
- package/package.json +49 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# CDS Expressions — Operators, CASE, Aggregates, Types
|
|
2
|
+
|
|
3
|
+
## Field References
|
|
4
|
+
|
|
5
|
+
```sql
|
|
6
|
+
{
|
|
7
|
+
key matnr, -- simple
|
|
8
|
+
key source.matnr, -- with alias prefix
|
|
9
|
+
matnr as MaterialNumber, -- with alias
|
|
10
|
+
'EUR' as DefaultCurrency, -- char literal (alias required)
|
|
11
|
+
100 as DefaultQty, -- integer literal
|
|
12
|
+
abap.dats'20241115' as FixedDate -- typed literal
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Session Variables
|
|
17
|
+
|
|
18
|
+
```sql
|
|
19
|
+
{
|
|
20
|
+
$session.user as CurrentUser, -- SY-UNAME
|
|
21
|
+
$session.client as ClientId, -- SY-MANDT
|
|
22
|
+
$session.system_language as Language, -- SY-LANGU
|
|
23
|
+
$session.system_date as Today -- SY-DATUM (7.51+)
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Comparison Operators
|
|
28
|
+
|
|
29
|
+
| Operator | Example |
|
|
30
|
+
|----------|---------|
|
|
31
|
+
| `=` | `status = 'A'` |
|
|
32
|
+
| `<>` | `status <> 'D'` |
|
|
33
|
+
| `<` `>` `<=` `>=` | `amount > 0` |
|
|
34
|
+
| `between ... and ...` | `date between '20240101' and '20241231'` |
|
|
35
|
+
| `in (...)` | `status in ('A','B','C')` |
|
|
36
|
+
| `is null` / `is not null` | `description is not null` |
|
|
37
|
+
| `like` | `name like 'SAP%'` |
|
|
38
|
+
|
|
39
|
+
### LIKE Patterns
|
|
40
|
+
|
|
41
|
+
```sql
|
|
42
|
+
where name like 'SAP%' -- starts with
|
|
43
|
+
where name like '%GmbH' -- ends with
|
|
44
|
+
where name like '%Partner%' -- contains
|
|
45
|
+
where code like 'A_B' -- single char wildcard
|
|
46
|
+
where name like '%10#%%' escape '#' -- literal % via escape
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Arithmetic
|
|
50
|
+
|
|
51
|
+
```sql
|
|
52
|
+
{
|
|
53
|
+
quantity * unit_price as LineTotal,
|
|
54
|
+
gross_amount - discount as NetAmount,
|
|
55
|
+
total / 100 as Percentage,
|
|
56
|
+
-balance as NegatedBalance,
|
|
57
|
+
(10 + 5) * 2 as WithParens -- = 30, not 20
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Precedence: `()` > `-`(unary) > `*` `/` > `+` `-`
|
|
62
|
+
|
|
63
|
+
## CASE — Simple
|
|
64
|
+
|
|
65
|
+
```sql
|
|
66
|
+
case status
|
|
67
|
+
when 'A' then 'Active'
|
|
68
|
+
when 'I' then 'Inactive'
|
|
69
|
+
when 'D' then 'Deleted'
|
|
70
|
+
else 'Unknown'
|
|
71
|
+
end as StatusText
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## CASE — Searched
|
|
75
|
+
|
|
76
|
+
```sql
|
|
77
|
+
case
|
|
78
|
+
when amount > 10000 then 'High'
|
|
79
|
+
when amount > 1000 then 'Medium'
|
|
80
|
+
when amount > 0 then 'Low'
|
|
81
|
+
else 'Zero'
|
|
82
|
+
end as AmountCategory
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## CASE — Nested
|
|
86
|
+
|
|
87
|
+
```sql
|
|
88
|
+
case type
|
|
89
|
+
when 'S' then
|
|
90
|
+
case status
|
|
91
|
+
when 'A' then 'Sales Active'
|
|
92
|
+
when 'C' then 'Sales Closed'
|
|
93
|
+
else 'Sales Other'
|
|
94
|
+
end
|
|
95
|
+
when 'P' then 'Purchase'
|
|
96
|
+
else 'Other'
|
|
97
|
+
end as TypeDescription
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## CASE — With Calculation
|
|
101
|
+
|
|
102
|
+
```sql
|
|
103
|
+
case indicator
|
|
104
|
+
when 'H' then amount
|
|
105
|
+
when 'S' then -amount
|
|
106
|
+
else 0
|
|
107
|
+
end as SignedAmount
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Logical Operators
|
|
111
|
+
|
|
112
|
+
```sql
|
|
113
|
+
-- AND / OR / NOT
|
|
114
|
+
where status = 'A' and type = 'S'
|
|
115
|
+
where status = 'A' or status = 'B'
|
|
116
|
+
where not status = 'D'
|
|
117
|
+
|
|
118
|
+
-- Precedence: NOT > AND > OR — use parentheses
|
|
119
|
+
where (status = 'A' and type = 'S')
|
|
120
|
+
or (status = 'B' and priority > 5)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Aggregate Functions
|
|
124
|
+
|
|
125
|
+
| Function | Usage |
|
|
126
|
+
|----------|-------|
|
|
127
|
+
| `sum(field)` | Sum |
|
|
128
|
+
| `avg(field)` | Average |
|
|
129
|
+
| `min(field)` | Minimum |
|
|
130
|
+
| `max(field)` | Maximum |
|
|
131
|
+
| `count(*)` | Row count |
|
|
132
|
+
| `count(distinct field)` | Distinct count |
|
|
133
|
+
|
|
134
|
+
## GROUP BY / HAVING
|
|
135
|
+
|
|
136
|
+
```sql
|
|
137
|
+
define view Z_CUST_SUMMARY as select from zvbak
|
|
138
|
+
{
|
|
139
|
+
kunnr,
|
|
140
|
+
sum(netwr) as TotalSales,
|
|
141
|
+
avg(netwr) as AvgOrder,
|
|
142
|
+
min(erdat) as FirstOrder,
|
|
143
|
+
max(erdat) as LastOrder,
|
|
144
|
+
count(*) as OrderCount,
|
|
145
|
+
count(distinct matnr) as UniqueProducts
|
|
146
|
+
}
|
|
147
|
+
group by kunnr
|
|
148
|
+
having count(*) >= 5
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Path Expressions
|
|
152
|
+
|
|
153
|
+
```sql
|
|
154
|
+
-- Single level
|
|
155
|
+
_Customer.name1 as CustomerName
|
|
156
|
+
|
|
157
|
+
-- Multi-level
|
|
158
|
+
_Order._Customer._Country.name as CountryName
|
|
159
|
+
|
|
160
|
+
-- Path with filter + cardinality indicator
|
|
161
|
+
_Items[1: ItemNumber = '000010'].Material as FirstMaterial
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Conditional Navigation
|
|
165
|
+
|
|
166
|
+
```sql
|
|
167
|
+
case
|
|
168
|
+
when type = 'C' then _Customer.name1
|
|
169
|
+
when type = 'V' then _Vendor.name1
|
|
170
|
+
else 'Unknown'
|
|
171
|
+
end as PartnerName
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## NULL Handling
|
|
175
|
+
|
|
176
|
+
```sql
|
|
177
|
+
-- COALESCE: first non-null
|
|
178
|
+
coalesce(override_price, standard_price, 0) as EffectivePrice
|
|
179
|
+
|
|
180
|
+
-- Arithmetic with NULL returns NULL
|
|
181
|
+
price - discount as NetPrice -- NULL if discount NULL
|
|
182
|
+
price - coalesce(discount, 0) as NetPrice -- safe
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## CAST
|
|
186
|
+
|
|
187
|
+
```sql
|
|
188
|
+
cast(numc_field as abap.char(10)) as TextField,
|
|
189
|
+
cast(char_field as abap.int4) as IntField,
|
|
190
|
+
cast(amount as abap.curr(15,2)) as FormattedAmount,
|
|
191
|
+
cast('EUR' as abap.cuky) as Currency
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Common ABAP Types for CAST
|
|
195
|
+
|
|
196
|
+
| Type | Syntax |
|
|
197
|
+
|------|--------|
|
|
198
|
+
| Character | `abap.char(n)` |
|
|
199
|
+
| Numeric text | `abap.numc(n)` |
|
|
200
|
+
| Integer | `abap.int4` |
|
|
201
|
+
| Date | `abap.dats` |
|
|
202
|
+
| Time | `abap.tims` |
|
|
203
|
+
| Currency key | `abap.cuky` |
|
|
204
|
+
| Currency amount | `abap.curr(n,d)` |
|
|
205
|
+
| Unit | `abap.unit(n)` |
|
|
206
|
+
| Quantity | `abap.quan(n,d)` |
|
|
207
|
+
| Decimal | `abap.dec(n,d)` |
|
|
208
|
+
| String | `abap.string` |
|
|
209
|
+
|
|
210
|
+
## Rules
|
|
211
|
+
|
|
212
|
+
- Literals always require an alias
|
|
213
|
+
- All CASE branches must return the same type
|
|
214
|
+
- Always use COALESCE or CASE for NULL-prone calculations
|
|
215
|
+
- Always alias calculated/expression fields
|
|
216
|
+
- Use parentheses in complex WHERE to clarify precedence
|
|
217
|
+
- GROUP BY must list all non-aggregated fields
|
|
218
|
+
- `$session.system_date` requires NW 7.51+
|
|
219
|
+
|
|
220
|
+
## Anti-Patterns
|
|
221
|
+
|
|
222
|
+
| Anti-Pattern | Correct |
|
|
223
|
+
|---|---|
|
|
224
|
+
| Arithmetic on nullable field without COALESCE | `coalesce(field, 0)` before math |
|
|
225
|
+
| CASE branches returning mixed types | Ensure all branches return same type |
|
|
226
|
+
| Missing GROUP BY field | List every non-aggregated field |
|
|
227
|
+
| `where a = 1 or b = 2 and c = 3` without parens | `where a = 1 or (b = 2 and c = 3)` |
|
|
228
|
+
| Unaliased expression in projection | Always alias: `expr as AliasName` |
|
|
229
|
+
| CASE in WHERE on large datasets | Use separate WHERE conditions for performance |
|
|
230
|
+
| Using `$session.system_date` on NW < 7.51 | Use parameter with `@Environment.systemField` |
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# CDS Built-in Functions — String, Numeric, Date, Conversion
|
|
2
|
+
|
|
3
|
+
## String Functions
|
|
4
|
+
|
|
5
|
+
```sql
|
|
6
|
+
-- concat / concat_with_space
|
|
7
|
+
concat(first_name, last_name) as Full -- 'JohnDoe'
|
|
8
|
+
concat_with_space(first_name, last_name, 1) as Full -- 'John Doe'
|
|
9
|
+
|
|
10
|
+
-- length
|
|
11
|
+
length(description) as Len -- 5
|
|
12
|
+
|
|
13
|
+
-- left / right / substring (1-based)
|
|
14
|
+
left(matnr, 4) as Prefix -- '1234'
|
|
15
|
+
right(matnr, 3) as Suffix -- '678'
|
|
16
|
+
substring(docnum, 3, 5) as Sub -- '34567'
|
|
17
|
+
|
|
18
|
+
-- upper / lower
|
|
19
|
+
upper(name) as Up -- 'HELLO'
|
|
20
|
+
lower(name) as Lo -- 'hello'
|
|
21
|
+
|
|
22
|
+
-- lpad / rpad
|
|
23
|
+
lpad(docnum, 10, '0') as Padded -- '0000012345'
|
|
24
|
+
rpad(name, 20, ' ') as PaddedR -- 'John '
|
|
25
|
+
|
|
26
|
+
-- ltrim / rtrim
|
|
27
|
+
ltrim(docnum, '0') as Trimmed -- '12345'
|
|
28
|
+
rtrim(name, ' ') as TrimmedR -- 'John'
|
|
29
|
+
|
|
30
|
+
-- replace
|
|
31
|
+
replace(phone, '-', '') as Clean -- '1234567890'
|
|
32
|
+
|
|
33
|
+
-- instr (0 if not found)
|
|
34
|
+
instr(email, '@') as AtPos -- 5
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Numeric Functions
|
|
38
|
+
|
|
39
|
+
```sql
|
|
40
|
+
-- abs
|
|
41
|
+
abs(-100) as Val -- 100
|
|
42
|
+
|
|
43
|
+
-- ceil / floor
|
|
44
|
+
ceil(5.1) as Up -- 6
|
|
45
|
+
floor(5.9) as Down -- 5
|
|
46
|
+
|
|
47
|
+
-- round
|
|
48
|
+
round(5.567, 2) as R -- 5.57
|
|
49
|
+
round(12345, -2) as R2 -- 12300
|
|
50
|
+
|
|
51
|
+
-- div / mod (integer)
|
|
52
|
+
div(125, 60) as Hours -- 2
|
|
53
|
+
mod(125, 60) as Mins -- 5
|
|
54
|
+
|
|
55
|
+
-- division (with decimal precision)
|
|
56
|
+
division(10, 3, 4) as R -- 3.3333
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Date Functions
|
|
60
|
+
|
|
61
|
+
```sql
|
|
62
|
+
-- dats_add_days
|
|
63
|
+
dats_add_days(order_date, 7) as Delivery -- +7 days
|
|
64
|
+
dats_add_days(order_date, -30) as PrevMonth -- -30 days
|
|
65
|
+
|
|
66
|
+
-- dats_add_months
|
|
67
|
+
dats_add_months(start_date, 1) as NextMonth -- +1 month
|
|
68
|
+
|
|
69
|
+
-- dats_days_between (negative if date1 > date2)
|
|
70
|
+
dats_days_between(order_date, delivery_date) as Lead -- 14
|
|
71
|
+
|
|
72
|
+
-- dats_is_valid (returns 1 or 0)
|
|
73
|
+
dats_is_valid(input_date) as IsValid -- 1 or 0
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Timestamp Functions
|
|
77
|
+
|
|
78
|
+
```sql
|
|
79
|
+
-- Add seconds
|
|
80
|
+
tstmp_add_seconds(created_at, 3600, 'FAIL') as PlusHour
|
|
81
|
+
|
|
82
|
+
-- Seconds between
|
|
83
|
+
tstmp_seconds_between(start_ts, end_ts, 'FAIL') as Duration
|
|
84
|
+
|
|
85
|
+
-- Current UTC
|
|
86
|
+
tstmp_current_utctimestamp() as Now
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Third param: `'FAIL'` to raise error, `'NULL'` to return null on invalid input.
|
|
90
|
+
|
|
91
|
+
## COALESCE
|
|
92
|
+
|
|
93
|
+
```sql
|
|
94
|
+
coalesce(override_price, standard_price, 0) as Price
|
|
95
|
+
coalesce(customer_name, 'Unknown') as Name
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## CAST
|
|
99
|
+
|
|
100
|
+
```sql
|
|
101
|
+
cast(numc_field as abap.char(10)) as Text,
|
|
102
|
+
cast(char_field as abap.int4) as Int,
|
|
103
|
+
cast(amount as abap.curr(15,2)) as Amt,
|
|
104
|
+
cast('EUR' as abap.cuky) as Cur,
|
|
105
|
+
cast(num as abap.dec(11,2)) as Dec
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Types
|
|
109
|
+
|
|
110
|
+
| Type | Syntax |
|
|
111
|
+
|------|--------|
|
|
112
|
+
| `abap.char(n)` | Character |
|
|
113
|
+
| `abap.numc(n)` | Numeric text |
|
|
114
|
+
| `abap.int4` | Integer |
|
|
115
|
+
| `abap.dats` | Date |
|
|
116
|
+
| `abap.tims` | Time |
|
|
117
|
+
| `abap.cuky` | Currency key |
|
|
118
|
+
| `abap.curr(n,d)` | Currency amount |
|
|
119
|
+
| `abap.unit(n)` | Unit of measure |
|
|
120
|
+
| `abap.quan(n,d)` | Quantity |
|
|
121
|
+
| `abap.dec(n,d)` | Decimal |
|
|
122
|
+
| `abap.string` | String |
|
|
123
|
+
|
|
124
|
+
## Aggregate Functions
|
|
125
|
+
|
|
126
|
+
```sql
|
|
127
|
+
define view Z_ORDER_AGG as select from vbap
|
|
128
|
+
{
|
|
129
|
+
vbeln,
|
|
130
|
+
sum(netwr) as Total,
|
|
131
|
+
count(*) as Items,
|
|
132
|
+
min(erdat) as FirstDate,
|
|
133
|
+
max(erdat) as LastDate,
|
|
134
|
+
avg(netwr) as AvgAmt,
|
|
135
|
+
count(distinct matnr) as UniqueMatnr
|
|
136
|
+
}
|
|
137
|
+
group by vbeln
|
|
138
|
+
having sum(netwr) > 1000
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Conversion Functions
|
|
142
|
+
|
|
143
|
+
```sql
|
|
144
|
+
-- Decimal shift by currency
|
|
145
|
+
decimal_shift(amount => netwr, currency => waers) as Shifted
|
|
146
|
+
|
|
147
|
+
-- Unit conversion (HANA, requires T006)
|
|
148
|
+
unit_conversion(
|
|
149
|
+
quantity => menge,
|
|
150
|
+
source_unit => meins,
|
|
151
|
+
target_unit => 'KG'
|
|
152
|
+
) as QtyKG
|
|
153
|
+
|
|
154
|
+
-- Currency conversion (HANA, requires TCURR)
|
|
155
|
+
currency_conversion(
|
|
156
|
+
amount => netwr,
|
|
157
|
+
source_currency => waers,
|
|
158
|
+
target_currency => 'EUR',
|
|
159
|
+
exchange_rate_date => erdat
|
|
160
|
+
) as AmtEUR
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Complex Examples
|
|
164
|
+
|
|
165
|
+
### Minutes to HH:MM
|
|
166
|
+
|
|
167
|
+
```sql
|
|
168
|
+
concat(
|
|
169
|
+
concat(
|
|
170
|
+
lpad(ltrim(cast(div(flight_time, 60) as abap.char(12)), '0'), 2, '0'),
|
|
171
|
+
':'
|
|
172
|
+
),
|
|
173
|
+
lpad(ltrim(cast(mod(flight_time, 60) as abap.char(12)), '0'), 2, '0')
|
|
174
|
+
) as FormattedTime
|
|
175
|
+
-- 125 => '02:05'
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Date Validation with Default
|
|
179
|
+
|
|
180
|
+
```sql
|
|
181
|
+
case
|
|
182
|
+
when dats_is_valid(input_date) = 1 then input_date
|
|
183
|
+
else '00000000'
|
|
184
|
+
end as ValidatedDate
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Conditional Concatenation
|
|
188
|
+
|
|
189
|
+
```sql
|
|
190
|
+
case
|
|
191
|
+
when last_name is not null
|
|
192
|
+
then concat_with_space(first_name, last_name, 1)
|
|
193
|
+
else first_name
|
|
194
|
+
end as DisplayName
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Safe Percentage
|
|
198
|
+
|
|
199
|
+
```sql
|
|
200
|
+
case
|
|
201
|
+
when total > 0
|
|
202
|
+
then division(part * 100, total, 2)
|
|
203
|
+
else cast(0 as abap.dec(5,2))
|
|
204
|
+
end as Percentage
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Nested Functions
|
|
208
|
+
|
|
209
|
+
```sql
|
|
210
|
+
upper(
|
|
211
|
+
replace(
|
|
212
|
+
ltrim(
|
|
213
|
+
concat_with_space(first_name, last_name, 1),
|
|
214
|
+
' '
|
|
215
|
+
),
|
|
216
|
+
' ',
|
|
217
|
+
'_'
|
|
218
|
+
)
|
|
219
|
+
) as NormalizedName
|
|
220
|
+
-- ' John Doe ' => 'JOHN_DOE'
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Rules
|
|
224
|
+
|
|
225
|
+
- `substring` position is 1-based, not 0-based
|
|
226
|
+
- `lpad` truncates if original exceeds target length
|
|
227
|
+
- `dats_days_between` returns negative if date1 > date2
|
|
228
|
+
- `division` third param = decimal places; `div` returns integer
|
|
229
|
+
- `unit_conversion` / `currency_conversion` require HANA + maintained tables
|
|
230
|
+
- Always validate dates with `dats_is_valid` before date arithmetic
|
|
231
|
+
- Use `coalesce` before arithmetic on nullable fields
|
|
232
|
+
- Aggregate functions require GROUP BY for all non-aggregated fields
|
|
233
|
+
|
|
234
|
+
## Anti-Patterns
|
|
235
|
+
|
|
236
|
+
| Anti-Pattern | Correct |
|
|
237
|
+
|---|---|
|
|
238
|
+
| `concat(concat(a, ' '), b)` for space join | `concat_with_space(a, b, 1)` |
|
|
239
|
+
| Date math without `dats_is_valid` check | Validate first, then calculate |
|
|
240
|
+
| `division(a, b, 2)` without zero check | Wrap in `case when b > 0` |
|
|
241
|
+
| `substring(f, 0, 5)` (0-based) | `substring(f, 1, 5)` — 1-based |
|
|
242
|
+
| Nested 5+ function calls | Break into intermediate views |
|
|
243
|
+
| `unit_conversion` on non-HANA DB | Check platform support first |
|
|
244
|
+
| Missing GROUP BY with aggregates | List every non-aggregated field |
|
|
245
|
+
| `ltrim(field, ' ')` expecting full trim | Only trims from left side |
|