|
21 | 21 | import com.google.common.base.Preconditions; |
22 | 22 | import java.io.IOException; |
23 | 23 | import java.time.Instant; |
24 | | -import java.util.ArrayList; |
25 | 24 | import java.util.Arrays; |
26 | 25 | import java.util.HashSet; |
27 | 26 | import java.util.List; |
|
41 | 40 | import org.apache.gravitino.function.FunctionChange; |
42 | 41 | import org.apache.gravitino.function.FunctionColumn; |
43 | 42 | import org.apache.gravitino.function.FunctionDefinition; |
44 | | -import org.apache.gravitino.function.FunctionDefinitions; |
45 | | -import org.apache.gravitino.function.FunctionImpl; |
46 | 43 | import org.apache.gravitino.function.FunctionParam; |
47 | 44 | import org.apache.gravitino.function.FunctionType; |
48 | 45 | import org.apache.gravitino.meta.AuditInfo; |
@@ -167,20 +164,8 @@ public Function registerFunction( |
167 | 164 | @Override |
168 | 165 | public Function alterFunction(NameIdentifier ident, FunctionChange... changes) |
169 | 166 | throws NoSuchFunctionException, IllegalArgumentException { |
170 | | - try { |
171 | | - return store.update( |
172 | | - ident, |
173 | | - FunctionEntity.class, |
174 | | - Entity.EntityType.FUNCTION, |
175 | | - oldEntity -> applyChanges(oldEntity, changes)); |
176 | | - |
177 | | - } catch (NoSuchEntityException e) { |
178 | | - throw new NoSuchFunctionException(e, "Function %s does not exist", ident); |
179 | | - } catch (EntityAlreadyExistsException e) { |
180 | | - throw new IllegalArgumentException("Failed to alter function " + ident, e); |
181 | | - } catch (IOException e) { |
182 | | - throw new RuntimeException("Failed to alter function " + ident, e); |
183 | | - } |
| 167 | + // TODO: Implement when FunctionEntity is available |
| 168 | + throw new UnsupportedOperationException("alterFunction: FunctionEntity not yet implemented"); |
184 | 169 | } |
185 | 170 |
|
186 | 171 | @Override |
@@ -257,74 +242,6 @@ private Function doRegisterFunction( |
257 | 242 | } |
258 | 243 | } |
259 | 244 |
|
260 | | - private FunctionEntity applyChanges(FunctionEntity oldEntity, FunctionChange... changes) { |
261 | | - String newComment = oldEntity.comment(); |
262 | | - List<FunctionDefinition> newDefinitions = |
263 | | - new ArrayList<>(Arrays.asList(oldEntity.definitions())); |
264 | | - |
265 | | - for (FunctionChange change : changes) { |
266 | | - if (change instanceof FunctionChange.UpdateComment) { |
267 | | - newComment = ((FunctionChange.UpdateComment) change).newComment(); |
268 | | - |
269 | | - } else if (change instanceof FunctionChange.AddDefinition) { |
270 | | - FunctionDefinition defToAdd = ((FunctionChange.AddDefinition) change).definition(); |
271 | | - validateNoArityOverlap(newDefinitions, defToAdd); |
272 | | - newDefinitions.add(defToAdd); |
273 | | - |
274 | | - } else if (change instanceof FunctionChange.RemoveDefinition) { |
275 | | - FunctionParam[] paramsToRemove = ((FunctionChange.RemoveDefinition) change).parameters(); |
276 | | - validateRemoveDefinition(newDefinitions, paramsToRemove); |
277 | | - newDefinitions.removeIf(def -> parametersMatch(def.parameters(), paramsToRemove)); |
278 | | - |
279 | | - } else if (change instanceof FunctionChange.AddImpl) { |
280 | | - FunctionChange.AddImpl addImpl = (FunctionChange.AddImpl) change; |
281 | | - FunctionParam[] targetParams = addImpl.parameters(); |
282 | | - FunctionImpl implToAdd = addImpl.implementation(); |
283 | | - newDefinitions = addImplToDefinition(newDefinitions, targetParams, implToAdd); |
284 | | - |
285 | | - } else if (change instanceof FunctionChange.UpdateImpl) { |
286 | | - FunctionChange.UpdateImpl updateImpl = (FunctionChange.UpdateImpl) change; |
287 | | - FunctionParam[] targetParams = updateImpl.parameters(); |
288 | | - FunctionImpl.RuntimeType runtime = updateImpl.runtime(); |
289 | | - FunctionImpl newImpl = updateImpl.implementation(); |
290 | | - newDefinitions = updateImplInDefinition(newDefinitions, targetParams, runtime, newImpl); |
291 | | - |
292 | | - } else if (change instanceof FunctionChange.RemoveImpl) { |
293 | | - FunctionChange.RemoveImpl removeImpl = (FunctionChange.RemoveImpl) change; |
294 | | - FunctionParam[] targetParams = removeImpl.parameters(); |
295 | | - FunctionImpl.RuntimeType runtime = removeImpl.runtime(); |
296 | | - newDefinitions = removeImplFromDefinition(newDefinitions, targetParams, runtime); |
297 | | - |
298 | | - } else { |
299 | | - throw new IllegalArgumentException("Unknown function change: " + change); |
300 | | - } |
301 | | - } |
302 | | - |
303 | | - String currentUser = PrincipalUtils.getCurrentUserName(); |
304 | | - Instant now = Instant.now(); |
305 | | - AuditInfo newAuditInfo = |
306 | | - AuditInfo.builder() |
307 | | - .withCreator(oldEntity.auditInfo().creator()) |
308 | | - .withCreateTime(oldEntity.auditInfo().createTime()) |
309 | | - .withLastModifier(currentUser) |
310 | | - .withLastModifiedTime(now) |
311 | | - .build(); |
312 | | - |
313 | | - return FunctionEntity.builder() |
314 | | - .withId(oldEntity.id()) |
315 | | - .withName(oldEntity.name()) |
316 | | - .withNamespace(oldEntity.namespace()) |
317 | | - .withComment(newComment) |
318 | | - .withFunctionType(oldEntity.functionType()) |
319 | | - .withDeterministic(oldEntity.deterministic()) |
320 | | - .withReturnType(oldEntity.returnType()) |
321 | | - .withReturnColumns(oldEntity.returnColumns()) |
322 | | - .withDefinitions(newDefinitions.toArray(new FunctionDefinition[0])) |
323 | | - .withVersion(oldEntity.version() + 1) |
324 | | - .withAuditInfo(newAuditInfo) |
325 | | - .build(); |
326 | | - } |
327 | | - |
328 | 245 | /** |
329 | 246 | * Validates that all definitions in the array do not have overlapping arities. This is used when |
330 | 247 | * registering a function with multiple definitions. |
@@ -357,40 +274,6 @@ private void validateDefinitionsNoArityOverlap(FunctionDefinition[] definitions) |
357 | 274 | } |
358 | 275 | } |
359 | 276 |
|
360 | | - /** |
361 | | - * Validates that a new definition does not create ambiguous function arities with existing |
362 | | - * definitions. Each definition can support multiple arities based on parameters with default |
363 | | - * values. |
364 | | - * |
365 | | - * <p>Gravitino enforces strict validation to prevent ambiguity. Operations MUST fail if a new |
366 | | - * definition's invocation arities overlap with existing ones. For example, if an existing |
367 | | - * definition {@code foo(int, float default 1.0)} supports arities {@code (int)} and {@code (int, |
368 | | - * float)}, adding a new definition {@code foo(int, string default 'x')} (which supports {@code |
369 | | - * (int)} and {@code (int, string)}) will be REJECTED because both support the call {@code |
370 | | - * foo(1)}. This ensures every function invocation deterministically maps to a single definition. |
371 | | - * |
372 | | - * @param existingDefinitions The current definitions. |
373 | | - * @param newDefinition The definition to add. |
374 | | - * @throws IllegalArgumentException If the new definition creates overlapping arities. |
375 | | - */ |
376 | | - private void validateNoArityOverlap( |
377 | | - List<FunctionDefinition> existingDefinitions, FunctionDefinition newDefinition) { |
378 | | - Set<String> newArities = computeArities(newDefinition); |
379 | | - |
380 | | - for (FunctionDefinition existing : existingDefinitions) { |
381 | | - Set<String> existingArities = computeArities(existing); |
382 | | - for (String arity : newArities) { |
383 | | - if (existingArities.contains(arity)) { |
384 | | - throw new IllegalArgumentException( |
385 | | - String.format( |
386 | | - "Cannot add definition: arity '%s' overlaps with an existing definition. " |
387 | | - + "This would create ambiguous function invocations.", |
388 | | - arity)); |
389 | | - } |
390 | | - } |
391 | | - } |
392 | | - } |
393 | | - |
394 | 277 | /** |
395 | 278 | * Computes all possible invocation arities for a function definition. A definition with N |
396 | 279 | * parameters where the last M have default values supports arities from (N-M) to N parameters. |
@@ -456,168 +339,4 @@ private Set<String> computeArities(FunctionDefinition definition) { |
456 | 339 |
|
457 | 340 | return arities; |
458 | 341 | } |
459 | | - |
460 | | - /** |
461 | | - * Validates that a definition can be removed. |
462 | | - * |
463 | | - * @param definitions The current definitions. |
464 | | - * @param paramsToRemove The parameters identifying the definition to remove. |
465 | | - * @throws IllegalArgumentException If the definition doesn't exist or is the only one. |
466 | | - */ |
467 | | - private void validateRemoveDefinition( |
468 | | - List<FunctionDefinition> definitions, FunctionParam[] paramsToRemove) { |
469 | | - boolean found = false; |
470 | | - for (FunctionDefinition def : definitions) { |
471 | | - if (parametersMatch(def.parameters(), paramsToRemove)) { |
472 | | - found = true; |
473 | | - break; |
474 | | - } |
475 | | - } |
476 | | - |
477 | | - if (!found) { |
478 | | - throw new IllegalArgumentException( |
479 | | - "Cannot remove definition: no definition found with the specified parameters"); |
480 | | - } |
481 | | - |
482 | | - if (definitions.size() == 1) { |
483 | | - throw new IllegalArgumentException( |
484 | | - "Cannot remove the only definition. Use dropFunction to remove the entire function."); |
485 | | - } |
486 | | - } |
487 | | - |
488 | | - private boolean parametersMatch(FunctionParam[] params1, FunctionParam[] params2) { |
489 | | - if (params1.length != params2.length) { |
490 | | - return false; |
491 | | - } |
492 | | - for (int i = 0; i < params1.length; i++) { |
493 | | - if (!params1[i].name().equals(params2[i].name()) |
494 | | - || !params1[i].dataType().equals(params2[i].dataType())) { |
495 | | - return false; |
496 | | - } |
497 | | - } |
498 | | - return true; |
499 | | - } |
500 | | - |
501 | | - private List<FunctionDefinition> addImplToDefinition( |
502 | | - List<FunctionDefinition> definitions, FunctionParam[] targetParams, FunctionImpl implToAdd) { |
503 | | - List<FunctionDefinition> result = new ArrayList<>(); |
504 | | - boolean found = false; |
505 | | - |
506 | | - for (FunctionDefinition def : definitions) { |
507 | | - if (parametersMatch(def.parameters(), targetParams)) { |
508 | | - found = true; |
509 | | - // Check if runtime already exists |
510 | | - for (FunctionImpl existingImpl : def.impls()) { |
511 | | - if (existingImpl.runtime() == implToAdd.runtime()) { |
512 | | - throw new IllegalArgumentException( |
513 | | - String.format( |
514 | | - "Cannot add implementation: runtime '%s' already exists in this definition. " |
515 | | - + "Use updateImpl to replace it.", |
516 | | - implToAdd.runtime())); |
517 | | - } |
518 | | - } |
519 | | - List<FunctionImpl> impls = new ArrayList<>(Arrays.asList(def.impls())); |
520 | | - impls.add(implToAdd); |
521 | | - result.add(FunctionDefinitions.of(def.parameters(), impls.toArray(new FunctionImpl[0]))); |
522 | | - } else { |
523 | | - result.add(def); |
524 | | - } |
525 | | - } |
526 | | - |
527 | | - if (!found) { |
528 | | - throw new IllegalArgumentException( |
529 | | - "Cannot add implementation: no definition found with the specified parameters"); |
530 | | - } |
531 | | - |
532 | | - return result; |
533 | | - } |
534 | | - |
535 | | - private List<FunctionDefinition> updateImplInDefinition( |
536 | | - List<FunctionDefinition> definitions, |
537 | | - FunctionParam[] targetParams, |
538 | | - FunctionImpl.RuntimeType runtime, |
539 | | - FunctionImpl newImpl) { |
540 | | - List<FunctionDefinition> result = new ArrayList<>(); |
541 | | - boolean definitionFound = false; |
542 | | - boolean runtimeFound = false; |
543 | | - |
544 | | - for (FunctionDefinition def : definitions) { |
545 | | - if (parametersMatch(def.parameters(), targetParams)) { |
546 | | - definitionFound = true; |
547 | | - List<FunctionImpl> impls = new ArrayList<>(); |
548 | | - for (FunctionImpl impl : def.impls()) { |
549 | | - if (impl.runtime() == runtime) { |
550 | | - runtimeFound = true; |
551 | | - impls.add(newImpl); |
552 | | - } else { |
553 | | - impls.add(impl); |
554 | | - } |
555 | | - } |
556 | | - result.add(FunctionDefinitions.of(def.parameters(), impls.toArray(new FunctionImpl[0]))); |
557 | | - } else { |
558 | | - result.add(def); |
559 | | - } |
560 | | - } |
561 | | - |
562 | | - if (!definitionFound) { |
563 | | - throw new IllegalArgumentException( |
564 | | - "Cannot update implementation: no definition found with the specified parameters"); |
565 | | - } |
566 | | - |
567 | | - if (!runtimeFound) { |
568 | | - throw new IllegalArgumentException( |
569 | | - String.format( |
570 | | - "Cannot update implementation: runtime '%s' not found in the definition", runtime)); |
571 | | - } |
572 | | - |
573 | | - return result; |
574 | | - } |
575 | | - |
576 | | - private List<FunctionDefinition> removeImplFromDefinition( |
577 | | - List<FunctionDefinition> definitions, |
578 | | - FunctionParam[] targetParams, |
579 | | - FunctionImpl.RuntimeType runtime) { |
580 | | - List<FunctionDefinition> result = new ArrayList<>(); |
581 | | - boolean definitionFound = false; |
582 | | - boolean runtimeFound = false; |
583 | | - |
584 | | - for (FunctionDefinition def : definitions) { |
585 | | - if (parametersMatch(def.parameters(), targetParams)) { |
586 | | - definitionFound = true; |
587 | | - |
588 | | - // Check if this is the only implementation |
589 | | - if (def.impls().length == 1) { |
590 | | - if (def.impls()[0].runtime() == runtime) { |
591 | | - throw new IllegalArgumentException( |
592 | | - "Cannot remove the only implementation. Use removeDefinition to remove the entire definition."); |
593 | | - } |
594 | | - } |
595 | | - |
596 | | - List<FunctionImpl> impls = new ArrayList<>(); |
597 | | - for (FunctionImpl impl : def.impls()) { |
598 | | - if (impl.runtime() == runtime) { |
599 | | - runtimeFound = true; |
600 | | - } else { |
601 | | - impls.add(impl); |
602 | | - } |
603 | | - } |
604 | | - result.add(FunctionDefinitions.of(def.parameters(), impls.toArray(new FunctionImpl[0]))); |
605 | | - } else { |
606 | | - result.add(def); |
607 | | - } |
608 | | - } |
609 | | - |
610 | | - if (!definitionFound) { |
611 | | - throw new IllegalArgumentException( |
612 | | - "Cannot remove implementation: no definition found with the specified parameters"); |
613 | | - } |
614 | | - |
615 | | - if (!runtimeFound) { |
616 | | - throw new IllegalArgumentException( |
617 | | - String.format( |
618 | | - "Cannot remove implementation: runtime '%s' not found in the definition", runtime)); |
619 | | - } |
620 | | - |
621 | | - return result; |
622 | | - } |
623 | 342 | } |
0 commit comments