All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ru.curs.celesta.score.CelestaSerializer Maven / Gradle / Ivy

The newest version!
package ru.curs.celesta.score;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.stream.Collectors;

import ru.curs.celesta.score.SequenceElement.Argument;

/**
 * Serializes grain and its components to CelestaSQL.
 * 

* The class name reflects its counterpart - {@link CelestaParser} * * @author Pavel Perminov ([email protected]) * @since 2019-03-07 */ public final class CelestaSerializer { private final PrintWriter writer; public CelestaSerializer(PrintWriter writer) { this.writer = writer; } static String toString(MaterializedView mv) throws IOException { try (StringWriter sw = new StringWriter()) { new CelestaSerializer(new PrintWriter(sw)).save(mv); return sw.toString(); } } /** * Returns a query based on which the view is going to be created. * * @param v view * @return * @throws IOException if query creation fails */ public static String toQueryString(View v) throws IOException { try (StringWriter sw = new StringWriter()) { new CelestaSerializer(new PrintWriter(sw)).saveQuery(v); return sw.toString(); } } /** * Serializes grain part to its CelestaSQL representation. * * @param gp grain part * @throws IOException if serialization fails */ public void save(GrainPart gp) throws IOException { save(gp.getGrain(), gp); } /** * Serializes grain to its CelestaSQL representation. * * @param grain grain * @throws IOException if serialization fails */ public void save(Grain grain) throws IOException { save(grain, null); } private void save(Grain grain, GrainPart gp) throws IOException { writeCelestaDoc(grain); writer.printf("CREATE SCHEMA %s VERSION '%s'", grain.getName(), grain.getVersion()); if (!grain.isAutoupdate()) { writer.printf(" WITH NO AUTOUPDATE"); } writer.printf(";%n"); writer.println(); writer.println("-- *** SEQUENCES ***"); Collection sequences = grain.getElements(SequenceElement.class, gp); for (SequenceElement s : sequences) { save(s); } writer.println("-- *** TABLES ***"); Collection

tables = grain.getElements(Table.class, gp); for (Table t : tables) { save(t); } Collection roTables = grain.getElements(ReadOnlyTable.class, gp); for (ReadOnlyTable rot : roTables) { save(rot); } writer.println("-- *** FOREIGN KEYS ***"); for (BasicTable t : tables) { for (ForeignKey fk : t.getForeignKeys()) { save(fk); } } writer.println("-- *** INDICES ***"); Collection indices = grain.getElements(Index.class, gp); for (Index i : indices) { save(i); } writer.println("-- *** VIEWS ***"); Collection views = grain.getElements(View.class, gp); for (View v : views) { save(v); } writer.println("-- *** MATERIALIZED VIEWS ***"); Collection materializedViews = grain.getElements(MaterializedView.class, gp); for (MaterializedView mv : materializedViews) { save(mv); } writer.println("-- *** PARAMETERIZED VIEWS ***"); Collection parameterizedViews = grain.getElements(ParameterizedView.class, gp); for (ParameterizedView pv : parameterizedViews) { save(pv); } } private boolean writeCelestaDoc(NamedElement e) { String doc = e.getCelestaDoc(); if (doc == null) { return false; } else { writer.printf("/**%s*/%n", doc); return true; } } void save(SequenceElement s) { writeCelestaDoc(s); writer.printf("CREATE SEQUENCE %s ", s.getName()); if (s.hasArgument(Argument.START_WITH)) { writer.printf("START WITH %s ", s.getStartWith()); } if (s.hasArgument(Argument.INCREMENT_BY)) { writer.printf("INCREMENT BY %s ", s.getIncrementBy()); } if (s.hasArgument(Argument.MINVALUE)) { writer.printf("MINVALUE %s ", s.getMinValue()); } if (s.hasArgument(Argument.MAXVALUE)) { writer.printf("MAXVALUE %s ", s.getMaxValue()); } if (s.hasArgument(Argument.CYCLE) && s.isCycle()) { writer.write("CYCLE "); } writer.println(";"); writer.println(); } /** * Serializes table to its CelestaSQL representation. * * @param t table * @throws IOException if serialization fails */ void save(Table t) throws IOException { saveHead(t); if (!t.isVersioned()) { writer.write(" WITH NO VERSION CHECK"); saveTail(t, false); } else { saveTail(t, true); } } /** * Serializes read only table to its CelestaSQL representation. * * @param t table * @throws IOException if serialization fails */ void save(ReadOnlyTable t) throws IOException { saveHead(t); writer.write(" WITH READ ONLY"); saveTail(t, false); } private void saveHead(BasicTable t) throws IOException { writeCelestaDoc(t); writer.printf("CREATE TABLE %s(%n", t.getQuotedNameIfNeeded()); boolean comma = false; for (Column c : t.getColumns().values()) { if (comma) { writer.println(","); } save(c); comma = true; } // Here we write the PK if (!t.getPrimaryKey().isEmpty()) { if (comma) { writer.write(","); } writer.println(); writer.write(" CONSTRAINT "); writer.write(t.getPkConstraintName()); writer.write(" PRIMARY KEY ("); comma = false; for (Column c : t.getPrimaryKey().values()) { if (comma) { writer.write(", "); } writer.write(c.getQuotedNameIfNeeded()); comma = true; } writer.println(")"); } writer.write(")"); } private void saveTail(BasicTable t, boolean isWith) { if (!t.isAutoUpdate()) { if (isWith) { writer.write(" WITH"); } writer.write(" NO AUTOUPDATE"); } writer.println(";"); writer.println(); } /** * Serializes column to its CelestaSQL representation. * * @param c column * @throws IOException if serialization fails */ void save(Column c) throws IOException { writer.write(" "); if (writeCelestaDoc(c)) { writer.write(" "); } writer.write(c.getName()); switch (c.getCelestaType()) { case BinaryColumn.CELESTA_TYPE: saveColumn((BinaryColumn) c); break; case BooleanColumn.CELESTA_TYPE: saveColumn((BooleanColumn) c); break; case DateTimeColumn.CELESTA_TYPE: saveColumn((DateTimeColumn) c); break; case DecimalColumn.CELESTA_TYPE: saveColumn((DecimalColumn) c); break; case ZonedDateTimeColumn.CELESTA_TYPE: saveColumn((ZonedDateTimeColumn) c); break; case FloatingColumn.CELESTA_TYPE: saveColumn((FloatingColumn) c); break; case IntegerColumn.CELESTA_TYPE: saveColumn((IntegerColumn) c); break; case StringColumn.VARCHAR: case StringColumn.TEXT: saveColumn((StringColumn) c); break; default: throw new IOException(String.format("No serializer for column of type %s was found!", c.getCelestaType())); } } private void saveColumn(BinaryColumn c) { writer.write(" BLOB"); if (!c.isNullable()) { writer.write(" NOT NULL"); } String defaultVal = c.getDefaultValue(); if (defaultVal != null) { writer.write(" DEFAULT "); writer.write(defaultVal); } } private void saveColumn(BooleanColumn c) { writer.write(" BIT"); if (!c.isNullable()) { writer.write(" NOT NULL"); } Boolean defaultVal = c.getDefaultValue(); if (defaultVal != null) { writer.write(" DEFAULT '"); writer.write(defaultVal.toString().toUpperCase()); writer.write("'"); } } private void saveColumn(DateTimeColumn c) { writer.write(" DATETIME"); if (!c.isNullable()) { writer.write(" NOT NULL"); } if (c.isGetdate()) { writer.write(" DEFAULT GETDATE()"); } else { Date defaultVal = c.getDefaultValue(); if (defaultVal != null) { writer.write(" DEFAULT '"); DateFormat df = new SimpleDateFormat("yyyyMMdd"); writer.write(df.format(defaultVal)); writer.write("'"); } } } private void saveColumn(DecimalColumn c) { writer.write(" DECIMAL"); if (!c.isNullable()) { writer.write(" NOT NULL"); } BigDecimal defaultVal = c.getDefaultValue(); if (defaultVal != null) { writer.write(" DEFAULT "); writer.write(defaultVal.toString()); } } private void saveColumn(FloatingColumn c) { writer.write(" REAL"); if (!c.isNullable()) { writer.write(" NOT NULL"); } Double defaultVal = c.getDefaultValue(); if (defaultVal != null) { writer.write(" DEFAULT "); writer.write(defaultVal.toString()); } } private void saveColumn(IntegerColumn c) { writer.write(" INT"); if (!c.isNullable()) { writer.write(" NOT NULL"); } Integer defaultVal = c.getDefaultValue(); if (defaultVal != null) { writer.write(" DEFAULT "); writer.write(defaultVal.toString()); } } private void saveColumn(StringColumn c) { if (c.isMax()) { writer.write(" TEXT"); } else { writer.write(" VARCHAR("); writer.write(Integer.toString(c.getLength())); writer.write(")"); } if (!c.isNullable()) { writer.write(" NOT NULL"); } String defaultVal = c.getDefaultValue(); if (defaultVal != null) { writer.write(" DEFAULT "); writer.write(StringColumn.quoteString(defaultVal)); } } private void saveColumn(ZonedDateTimeColumn c) { writer.write(" " + ZonedDateTimeColumn.CELESTA_TYPE); if (!c.isNullable()) { writer.write(" NOT NULL"); } } /** * Serializes foreign key to its CelestaSQL representation. * * @param fk foreign key * @throws IOException if serialization fails */ void save(ForeignKey fk) { writer.write("ALTER TABLE "); writer.write(fk.getParentTable().getQuotedNameIfNeeded()); writer.write(" ADD CONSTRAINT "); String name = fk.getConstraintName(); writer.write(name); writer.write(" FOREIGN KEY ("); boolean comma = false; for (Column c : fk.getColumns().values()) { if (comma) { writer.write(", "); } writer.write(c.getQuotedNameIfNeeded()); comma = true; } writer.write(") REFERENCES "); writer.write(fk.getReferencedTable().getGrain().getQuotedNameIfNeeded()); writer.write("."); writer.write(fk.getReferencedTable().getQuotedNameIfNeeded()); writer.write("("); comma = false; for (Column c : fk.getReferencedTable().getPrimaryKey().values()) { if (comma) { writer.write(", "); } writer.write(c.getQuotedNameIfNeeded()); comma = true; } writer.write(")"); switch (fk.getUpdateRule()) { case CASCADE: writer.write(" ON UPDATE CASCADE"); break; case SET_NULL: writer.write(" ON UPDATE SET NULL"); break; case NO_ACTION: default: break; } switch (fk.getDeleteRule()) { case CASCADE: writer.write(" ON DELETE CASCADE"); break; case SET_NULL: writer.write(" ON DELETE SET NULL"); break; case NO_ACTION: default: break; } writer.println(";"); } /** * Serializes index to its CelestaSQL representation. * * @param i index * @throws IOException if serialization fails */ void save(Index i) { writeCelestaDoc(i); writer.write("CREATE INDEX "); writer.write(i.getQuotedNameIfNeeded()); writer.write(" ON "); writer.write(i.getTable().getQuotedNameIfNeeded()); writer.write("("); boolean comma = false; for (Column c : i.getColumns().values()) { if (comma) { writer.write(", "); } writer.write(c.getQuotedNameIfNeeded()); comma = true; } writer.println(");"); } /** * Serializes view to its CelestaSQL representation. * * @param v view * @throws IOException if serialization fails */ void save(View v) throws IOException { writeCelestaDoc(v); v.createViewScript(writer, new ViewCelestaSQLGen(v)); writer.println(";"); writer.println(); } private void saveQuery(View v) throws IOException { v.selectScript(writer, new ViewCelestaSQLGen(v)); } /** * Serializes materialized view to its CelestaSQL representation. * * @param mv materialized view * @throws IOException if serialization fails */ void save(MaterializedView mv) throws IOException { writeCelestaDoc(mv); SQLGenerator gen = new MaterializedViewCelestaSQLGen(mv); writer.println(gen.preamble(mv)); mv.selectScript(writer, gen); writer.println(";"); writer.println(); } /** * Serializes parameterized view to its CelestaSQL representation. * * @param pv parameterized view * @throws IOException if serialization fails */ void save(ParameterizedView pv) throws IOException { writeCelestaDoc(pv); pv.createViewScript(writer, new ParameterizedViewCelestaSQLGen(pv)); writer.println(";"); writer.println(); } private abstract static class AbstractViewCelestaSQLGen extends SQLGenerator { final V view; AbstractViewCelestaSQLGen(V view) { this.view = view; } @Override protected String preamble(AbstractView dummyView) { return String.format("create %s %s as", view.viewType(), viewName(view)); } @Override protected String viewName(AbstractView dummyView) { return view.getQuotedNameIfNeeded(); } @Override protected String tableName(TableRef tRef) { TableElement t = tRef.getTable(); if (t.getGrain() == view.getGrain()) { return String.format("%s as %s", t.getQuotedNameIfNeeded(), tRef.getAlias()); } else { return String.format("%s.%s as %s", t.getGrain().getQuotedNameIfNeeded(), t.getQuotedNameIfNeeded(), tRef.getAlias()); } } @Override protected boolean quoteNames() { return false; } } private static class ViewCelestaSQLGen extends AbstractViewCelestaSQLGen { ViewCelestaSQLGen(View view) { super(view); } } private static class MaterializedViewCelestaSQLGen extends AbstractViewCelestaSQLGen { MaterializedViewCelestaSQLGen(MaterializedView view) { super(view); } } private static class ParameterizedViewCelestaSQLGen extends AbstractViewCelestaSQLGen { ParameterizedViewCelestaSQLGen(ParameterizedView view) { super(view); } @Override protected String preamble(AbstractView dummyView) { return String.format("create %s %s (%s) as", view.viewType(), viewName(view), view.getParameters().values().stream() .map(p -> p.getName() + " " + p.getType().toString()) .collect(Collectors.joining(", "))); } } }