LINUX.ORG.RU

Derby SQL - обновить view от которой зависят другие

 , , ,


0

2

День добрый, ЛОР.

Есть view в derby, от которой зависит как минимум ещё одна view. В то же время в derby нет create or replace view. Т.е. надо вручную дропнуть и создать. Но дропнуть нельзя, т.к.

java.sql.SQLException: Operation 'DROP VIEW' cannot be performed on object 'VIEW_NAME' because VIEW 'OTHER_VIEW_NAME' is dependent on that object.
И что же делать в такой ситуации? set constraints all deferred не помогает.

PS Тег java, т.к. derby на java.

★★★★★

Последнее исправление: orm-i-auga (всего исправлений: 2)


Statement Dependency System

Any statements referencing the view are invalidated on a DROP VIEW statement. DROP VIEW is disallowed if there are any views or open cursors dependent on the view. The view must be dropped before any objects that it is dependent on can be dropped.

SevikL ★★★★★
()
Ответ на: комментарий от SevikL

Да, я это читал. И какой же вывод? Неужто они предлагают пересоздавать по зависимостям всё дерево представлений каждый раз, когда надо заменить лишь одно представление?

orm-i-auga ★★★★★
() автор топика
Ответ на: комментарий от SevikL

А alter на view работает в derby? В Postgresql, например, нельзя с помощью alter изменить запрос, которым строится view.

А drop cascade в derby есть?

grondek
()
Ответ на: комментарий от SevikL

В доках я не нашёл никакого alter view.

orm-i-auga ★★★★★
() автор топика
Ответ на: комментарий от grondek

В общем, проверил, ни alter view, ни drop cascade в derby нет. Мда, похоже плохо дело. Банальное обновление представления превращается в нетривиальную задачу. Обычным sql-скриптом этого не сделать, надо либо заранее знать все зависимости представлений и все их пересоздавать, либо делать это в рантайме через метаданные.

orm-i-auga ★★★★★
() автор топика

Выяснилось, что каскадное удаление никто делать не будет:

https://issues.apache.org/jira/browse/DERBY-1631

Ну что же, пришлось сделать велосипед. Обрабатываю зависимости представлений вручную, если на drop ловлю соответствующий эхэпшон:

	Pattern messagePattern = Pattern.compile(
			"Operation 'DROP VIEW' cannot be performed on object '\\w+' because VIEW '(\\w+)' is dependent on that object.");

	class ViewDefinition {
		String name;
		String definition;
	}

	public void replaceView(ViewDefinition view, Connection conn) throws SQLException {
		Deque<ViewDefinition> viewsToDrop = new LinkedList<ViewDefinition>();
		Deque<ViewDefinition> viewsToAdd = new LinkedList<ViewDefinition>();
		viewsToDrop.push(view);
		viewsToAdd.push(view);

		Statement st = conn.createStatement();

		try {
			while (!viewsToDrop.isEmpty()) {
				ViewDefinition nextView = viewsToDrop.getFirst();
				try {
					st.execute("drop view " + nextView.name);
				} catch (SQLException e) {
					if ("X0Y23".equals(e.getSQLState())) {
						// dependency error
						String message = e.getMessage();
						Matcher matcher = messagePattern.matcher(message);
						if (matcher.matches()) {
							ViewDefinition dependentView = new ViewDefinition();
							dependentView.name = matcher.group(1);
							dependentView.definition = getViewDefinition(dependentView.name, conn);
							viewsToDrop.addFirst(dependentView);
							viewsToAdd.addFirst(dependentView);
							continue;
						} else {
							throw new RuntimeException(
									String.format("Can't detect dependent view name for view %s", nextView.name));
						}
					} else {
						throw e;
					}
				}
				// view dropped
				viewsToDrop.removeFirst();
			}
			while (!viewsToAdd.isEmpty()) {
				ViewDefinition nextView = viewsToAdd.pollLast();
				st.execute(nextView.definition);
			}
		} finally {
			if (!st.isClosed())
				st.close();
		}
	}

	private String getViewDefinition(String viewName, Connection conn) throws SQLException {
		String definition = null;
		PreparedStatement ps = conn.prepareStatement(
				"select v.viewdefinition from sys.sysviews v inner join sys.systables t on t.tableid = v.tableid where lower(t.tablename) = lower(?) and t.tabletype = ?");
		ps.setString(1, viewName);
		ps.setString(2, "V");
		ResultSet rs = ps.executeQuery();
		if (rs.next()) {
			definition = rs.getString("viewdefinition");
		}
		rs.close();
		ps.close();
		return definition;
	}

orm-i-auga ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.