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

sql.create_entity_manager.xslt Maven / Gradle / Ivy

The newest version!












package ;

import ch.epfl.labos.iu.orm.DBSet;
import ch.epfl.labos.iu.orm.LazySet;
import ch.epfl.labos.iu.orm.VectorSet;
import org.jinq.tuples.Pair;
import org.jinq.tuples.Tuple3;
import org.jinq.tuples.Tuple4;
import org.jinq.tuples.Tuple5;
import ch.epfl.labos.iu.orm.QueryList;
import ch.epfl.labos.iu.orm.query.RowReader;
import ch.epfl.labos.iu.orm.query.SelectFromWhere;
import ch.epfl.labos.iu.orm.query2.JDBCConnectionInfo;
import ch.epfl.labos.iu.orm.query2.SQLQueryComposer;
import ch.epfl.labos.iu.orm.query2.SQLReader;
import ch.epfl.labos.iu.orm.query2.SQLReaderColumnDescription;
import ch.epfl.labos.iu.orm.query2.EntityManagerBackdoor;
import org.jinq.orm.annotations.EntitySupplier;
import org.jinq.orm.annotations.NoSideEffects;
import org.jinq.orm.stream.JinqStream;
import org.jinq.orm.stream.QueryJinqStream;
import java.io.Serializable;
import java.util.List;
import java.util.Vector;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;
import java.util.WeakHashMap;
import java.util.stream.Stream;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.lang.ref.WeakReference;


public class EntityManager implements EntityManagerBackdoor, Serializable
{
	// Note: The EntityManager is not properly serializable, but some queries do access the
	// entity manager. Those Java 8 lambdas need to be serialized to be decoded, so 
	// there needs to be a way to record some sort of placeholder entity manager when
	// serializing the lambda.

	transient DBManager db;
	public int timeout = 0;
	boolean cacheQueries = true;
	boolean partialCacheQueries = true;
	

	public EntityManager(DBManager db)
	{
		this.db = db;
		this.timeout = db.timeout;
		this.cacheQueries = db.useFullQueryCaching;
		this.partialCacheQueries = db.usePartialQueryCaching;

	}

	void flushDirty()
	{
		// TODO: this
		// TODO: Flushing of objects with references to other non-persisted objects that later become persisted

	}

	public abstract static class EntityReader<T> extends SQLReader <T>
	{
		EntityManager em;
		String entityInternalClassName;
		List<SQLReaderColumnDescription> columns = new Vector<SQLReaderColumnDescription>();
		public EntityReader(EntityManager em, String entityInternalClassName)
		{
			this.em = em;
			this.entityInternalClassName = entityInternalClassName;
		}
		public int getNumColumns()
		{
			// Currently assumes that each entry in the columns list takes
			// up one column
			//
			return columns.size();
		}
		public int getColumnForField(String field)
		{
			for (int n = 0; n < columns.size(); n++)
			{
				if (field.equals(columns.get(n).field))
					return n;
			}
			return -1;
		}
		public int getColumnIndexForColumnName(String col)
		{
			for (int n = 0; n < columns.size(); n++)
			{
				if (col.equals(columns.get(n).columnName))
					return n;
			}
			return -1;
		}
		
		String [] getColumnNames()
		{
			String [] columnNames = new String[columns.size()];
			for (int n = 0; n < columnNames.length; n++)
				columnNames[n] = columns.get(n).columnName;
			return columnNames;
		}
		SQLReader readerForType(String type)
		{
			if (type.equals("int"))
				return new SQLReader.IntegerSQLReader();
			else if (type.equals("float"))
				return new SQLReader.FloatSQLReader();
			else if (type.equals("double"))
				return new SQLReader.DoubleSQLReader();
			else if (type.equals("String"))
				return new SQLReader.StringSQLReader();
			else if (type.equals("Date"))
				return new SQLReader.DateSQLReader();
			return null;
		}
		public SQLReader getReaderForField(String field)
		{
			for (int n = 0; n < columns.size(); n++)
			{
				if (field.equals(columns.get(n).field))
				{
					String type = columns.get(n).type;
					if (type != null)
						return readerForType(type);
					return null;
				}
			}
			return null;
		}
		public boolean isCastConsistent(String internalName)
		{
			return entityInternalClassName.equals(internalName);
		}
		
	}



   public SQLReader getReaderForEntity(String entity)
   {
		
			
				
					
				
			
		if ("".equals(entity))
		{
			return new SQLReader(this);			
		}
		
		return null;
   }
   public String[] getEntityColumnNames(String entity)
   {
		
			
				
					
				
			
		if ("".equals(entity))
		{
			return new SQLReader(this).getColumnNames();			
		}
		
		return null;
   }
   public String getTableForEntity(String entity)
   {
		
		if ("".equals(entity))
		{
			return ""; 
		}
		
		return null;
   }
   
	static class QueryCacheKey
	{
		QueryCacheKey(String context, Object baseQuery, Object lambda)
		{
			this.context = context;
			this.baseQuery = baseQuery;
			this.lambda = lambda;
		}
		public int hashCode()
		{
			return context.hashCode() ^ baseQuery.hashCode() ^ lambda.hashCode();
		}
		public boolean equals(Object o)
		{
			if (!(o instanceof QueryCacheKey)) return false;
			QueryCacheKey other = (QueryCacheKey)o;
			return other.context.equals(context)
				&& other.baseQuery.equals(baseQuery)
				&& other.lambda.equals(lambda);
		}
		String context;
		Object baseQuery;
		Object lambda;
	}
	static class QueryCacheValue
	{
		QueryCacheValue(QueryCacheKey key, Object cachedQuery)
		{
			this.key = key;
			this.cachedQuery = cachedQuery;
		}
		QueryCacheKey key;
		Object cachedQuery;
		QueryCacheValue prev = null;
		QueryCacheValue next = null;
	}
	transient Map<QueryCacheKey, QueryCacheValue> queryCache = new HashMap<QueryCacheKey, QueryCacheValue>();
	final static int QUERY_CACHE_LIMIT = 500;
	transient QueryCacheValue queryCacheLRU_head = null;
	transient QueryCacheValue queryCacheLRU_tail = null;
	int queryCacheSize = 0;
   private void dequeueQueryCacheLRU(QueryCacheValue val)
   {
		queryCacheSize--;
		if (val.next == null)
			queryCacheLRU_tail = val.prev;
		else
			val.next.prev = val.prev;
		if (val.prev == null)
			queryCacheLRU_head = val.next;
		else
			val.prev.next = val.next;
		val.prev = null;
		val.next = null;
   }
   private void enqueueQueryCacheLRU(QueryCacheValue val)
   {
		// Add it to the end of the queue
		if (queryCacheLRU_tail == null)
		{
			queryCacheLRU_tail = val;
			queryCacheLRU_head = val;
		}
		else
		{
			val.prev = queryCacheLRU_tail;
			queryCacheLRU_tail.next = val;
			queryCacheLRU_tail = val;
		}
		// Check if we've overflowed
		queryCacheSize++;
		if (queryCacheSize > QUERY_CACHE_LIMIT)
		{
			QueryCacheValue toRemove = queryCacheLRU_head;
			dequeueQueryCacheLRU(toRemove);
			queryCache.remove(toRemove.key);
		}
   }
   public Object getQueryCacheEntry(String context, Object baseQuery, Object lambda)
   {
		QueryCacheKey key = new QueryCacheKey(context, baseQuery, lambda);
		QueryCacheValue cached = queryCache.get(key);
		if (cached == null)
			return null;
		// Move it to the end of the queue
		dequeueQueryCacheLRU(cached);
		enqueueQueryCacheLRU(cached);
		return cached.cachedQuery;
   }
   public void putQueryCacheEntry(String context, Object baseQuery, Object lambda, Object cachedQuery)
   {
		QueryCacheKey key = new QueryCacheKey(context, baseQuery, lambda);
		QueryCacheValue cached = new QueryCacheValue(key, cachedQuery);
		queryCache.put(key, cached);
		enqueueQueryCacheLRU(cached);
   }
	static class GeneratedCachedQuery
	{
		GeneratedCachedQuery(Object key, Object cachedQuery)
		{
			this.key = key;
			this.cachedQuery = cachedQuery;
		}
		Object key;
		Object cachedQuery;
		GeneratedCachedQuery prev = null;
		GeneratedCachedQuery next = null;
	}
	transient Map<Object, GeneratedCachedQuery> generatedQueryCache = new HashMap<Object, GeneratedCachedQuery>();
	final static int GENERATED_QUERY_CACHE_LIMIT = 500;
	transient GeneratedCachedQuery generatedQueryCacheLRU_head = null;
	transient GeneratedCachedQuery generatedQueryCacheLRU_tail = null;
	int generatedQueryCacheSize = 0;
   private void dequeueGeneratedQueryCacheLRU(GeneratedCachedQuery val)
   {
		generatedQueryCacheSize--;
		if (val.next == null)
			generatedQueryCacheLRU_tail = val.prev;
		else
			val.next.prev = val.prev;
		if (val.prev == null)
			generatedQueryCacheLRU_head = val.next;
		else
			val.prev.next = val.next;
		val.prev = null;
		val.next = null;
   }
   private void enqueueGeneratedQueryCacheLRU(GeneratedCachedQuery val)
   {
		// Add it to the end of the queue
		if (generatedQueryCacheLRU_tail == null)
		{
			generatedQueryCacheLRU_tail = val;
			generatedQueryCacheLRU_head = val;
		}
		else
		{
			val.prev = generatedQueryCacheLRU_tail;
			generatedQueryCacheLRU_tail.next = val;
			generatedQueryCacheLRU_tail = val;
		}
		// Check if we've overflowed
		generatedQueryCacheSize++;
		if (generatedQueryCacheSize > GENERATED_QUERY_CACHE_LIMIT)
		{
			GeneratedCachedQuery toRemove = generatedQueryCacheLRU_head;
			dequeueGeneratedQueryCacheLRU(toRemove);
			generatedQueryCache.remove(toRemove.key);
		}
   }
	public Object getGeneratedQueryCacheEntry(Object queryRepresentation)
	{
		GeneratedCachedQuery cached = generatedQueryCache.get(queryRepresentation);
		if (cached == null)
			return null;
		// Move it to the end of the queue
		dequeueGeneratedQueryCacheLRU(cached);
		enqueueGeneratedQueryCacheLRU(cached);
		return cached.cachedQuery;
	}
	public void putGeneratedQueryCacheEntry(Object queryRepresentation, Object generatedQuery)
	{
		GeneratedCachedQuery cached = new GeneratedCachedQuery(queryRepresentation, generatedQuery);
		generatedQueryCache.put(queryRepresentation, cached);
		enqueueGeneratedQueryCacheLRU(cached);
	}
   
   public boolean isQueriesCached()
   {
		return cacheQueries || partialCacheQueries;
   }
   
   public boolean isPreparedStatementCached()
   {
   		return cacheQueries;
   }
   
}




	
		
			
		
	
	
	
	
		
			
		
	

	// TODO: add plural forms of entity names
	transient SQLQueryComposer<> Query;
	transient DBSet<> ;
	public DBSet<> all()
	{
		return ;
	}
	@EntitySupplier(entityClass=".") 
	public JinqStream<> Stream()
	{
	   return new QueryJinqStream<>(Query);
	}

	void dispose( obj)
	{
		flushDirty();
		.remove(obj);
		// delete from db immediately
		String sql = "DELETE FROM  "
			+ " WHERE 1=1"
	
			+ " AND  = ? ";
		if (db.testOut != null) db.testOut.println(sql);
		if (db.con != null)
		{
			try {
				PreparedStatement stmt = db.con.prepareStatement(sql);
				int idx = 0;
	
				++idx;
				stmt.setObject(idx, obj.get());
	
				stmt.executeUpdate();
				stmt.close();
			} catch (SQLException e)
			{
				e.printStackTrace();
			}
		}
	}

	void dirtyInstance( obj)
	{
		dirty.add(obj);
	}
	
	void newInstance( obj)
	{
		// TODO: Add handling of objects with auto-generated keys
		// TODO: Add handling of objects whose keys are references to other objects

		assert(obj.em == null);
		obj.em = this;
		// Fix references to other objects that happen to be keys

  
  
    
    
    
    
    
        
	      
		obj.set( 
		    obj.get().get());
	      
        
  
  
    
    
    
    
    
		
		  
		obj.set(
		    obj.get().get());
		  
		
  
		flushDirty();
		// Add to DB immediately
		.add(obj);

		String sql = "INSERT INTO  (";
		boolean isFirst = true;
		for (Map.Entry entry : map.entrySet())
		{
			if (!isFirst) sql = sql + ", ";
			isFirst = false;
			sql = sql + entry.getKey();
		}
		sql = sql + ") VALUES (";
		for (int n = 0; n < map.size(); n++)
		{
			if (n != 0) sql = sql + ", ";
			sql = sql + "?";
		}
        sql = sql + ")";
        if (db.testOut != null) db.testOut.println(sql);
        if (db.con != null)
        {
			try {
				PreparedStatement stmt = db.con.prepareStatement(sql);
				int idx = 1;
				for (Map.Entry entry : map.entrySet())
				{
					stmt.setObject(idx, entry.getValue());
					idx++;
				}
				stmt.executeUpdate();
				stmt.close();
			} catch (SQLException e)
			{
				e.printStackTrace();
			}
        }
		known.put(obj.idKey(), new WeakReference<>(obj));
		original.put(obj, ()obj.copyForComparison());
	}

	 create(ResultSet rs, int column) throws SQLException
	{
		 obj = null;

		 key = 
				
			;
		WeakReference<> ref = known.get(key);
		if (ref != null) {
			obj = ref.get();
			if (obj != null)
			{
				// I'm not sure if this is necessary, but it's better to be safe
				if (original.get(obj) == null)
					original.put(obj, ()obj.copyForComparison());
				return obj;
			}
		}

		obj = new (this, rs, column);
		known.put(obj.idKey(), new WeakReference<>(obj));
		original.put(obj, ()obj.copyForComparison());

		// TODO: this
		return obj;
	}
	
	 create(ResultSet rs, String prefix) throws SQLException
	{
		 obj = null;

		 key = 
				
			;
		WeakReference<> ref = known.get(key);
		if (ref != null) {
			obj = ref.get();
			if (obj != null)
			{
				// I'm not sure if this is necessary, but it's better to be safe
				if (original.get(obj) == null)
					original.put(obj, ()obj.copyForComparison());
				return obj;
			}
		}

		obj = new (this, rs, prefix);
		known.put(obj.idKey(), new WeakReference<>(obj));
		original.put(obj, ()obj.copyForComparison());

		// TODO: this
		return obj;
	}
	
	transient HashSet<> dirty = new HashSet<>();	
	transient WeakHashMap<, > original = new WeakHashMap<, >();	
	transient WeakHashMap<, WeakReference<>> known = new WeakHashMap<, WeakReference<>>();	

	public static class SQLReader extends EntityReader<>
	{
		public SQLReader(EntityManager em)
		{
			super(em, "");
		
			columns.add(new SQLReaderColumnDescription("", "", ""));
		
		
			
				
			columns.add(new SQLReaderColumnDescription(null, "", null));
				
				
			columns.add(new SQLReaderColumnDescription(null, "", null));
				
				
				
			
		
		
			
				
			columns.add(new SQLReaderColumnDescription(null, "", null));
				
				
			columns.add(new SQLReaderColumnDescription(null, "", null));
				
				
				
			
		
		}
		public  readData(ResultSet result, int column)
		{
			try {
				if (em.db.isQueryOnly)
					return new (em, result, column);
				else
					return em.create(result, column);
			} catch (SQLException e)
			{
				e.printStackTrace();
				return null;
			}
		}
	}

	public class RowReader implements RowReader <>
	{
		public int column;
		public String prefix;
		public RowReader(String prefix)
		{
			this.prefix = prefix;
		}
		protected RowReader(String prefix, int column)
		{
			this.prefix = prefix;
			this.column = column;
		}
		public  readSqlRow(ResultSet rs)
		{
			try {
				return create(rs, column);
			} catch (SQLException e)
			{
				e.printStackTrace();
			}
			return null;
		}
		public void configureQuery(SelectFromWhere query)
		{
			int firstColumn =  -1;
			int col;

		
			col = query.addSelection(prefix + ".", prefix + "_");
			if (firstColumn == -1) firstColumn = col;
		
		
			col = query.addSelection(prefix + ".", "LINK_" + prefix + "_");
			if (firstColumn == -1) firstColumn = col;
		
		
			col = query.addSelection(prefix + ".", "LINK_" + prefix + "_");
			if (firstColumn == -1) firstColumn = col;
		
		
			col = query.addSelection(prefix + ".", "LINK_" + prefix + "_");
			if (firstColumn == -1) firstColumn = col;
		
		
			col = query.addSelection(prefix + ".", "LINK_" + prefix + "_");
			if (firstColumn == -1) firstColumn = col;
		
			column = firstColumn;
		}
		public RowReader <> copy()
		{
			return new RowReader(prefix, column);
		}
		public String queryString()
		{
			return prefix;
		}
	
		
		
		
			
				
			
		

		String Prefix;
		public String materializeJoinString(SelectFromWhere query)
		{
			if (Prefix == null)
			{
			
				String middlePrefix = query.addTable("");
			
				Prefix = query.addTable("");
			
				query.addWhereClause(Prefix + ". = " + prefix + ".");
			
			
				query.addWhereClause(Prefix + ". = " + middlePrefix + ".");
			
			
				query.addWhereClause(middlePrefix + ". = " + prefix + ".");
			
			}
			return Prefix;
		}
		public RowReader materializeJoinRowReader(SelectFromWhere query)
		{
			return new RowReader(materializeJoinString(query));
		}
	
	
		
		
		
			
				
			
		

		String Prefix;
		public String materializeJoinString(SelectFromWhere query)
		{
			if (Prefix == null)
			{
			
				String middlePrefix = query.addTable("");
			
				Prefix = query.addTable("");
			
				query.addWhereClause(prefix + ". = " + Prefix + ".");
			
			
				query.addWhereClause(prefix + ". = " + middlePrefix + ".");
			
			
				query.addWhereClause(middlePrefix + ". = " + Prefix + ".");
			
			}
			return Prefix;
		}
		public RowReader materializeJoinRowReader(SelectFromWhere query)
		{
			return new RowReader(materializeJoinString(query));
		}
	
	}








	
		
			
		
	
	
		
			
		
	

		{
		
//			SelectFromWhere query = new SelectFromWhere();
//			String prefix = query.addTable("");
//			RowReader <> reader = new RowReader(prefix);
//			// TODO: Use of db con connection here that needs to be removed
//			 = new QueryLazySet<>(db.con, query, reader);
			JDBCConnectionInfo jdbc = new JDBCConnectionInfo();
			jdbc.connection = db.con;
			jdbc.timeout = db.timeout;
			jdbc.testOut = db.testOut;
			SQLReader reader = new SQLReader(this); 
			SQLQueryComposer<> query =
				new SQLQueryComposer<>(
						this,
						jdbc,
						db.queryll,
						reader,
						reader.getColumnNames(),
						""
					);
			Query = query;
			 = new QueryList<>(query);
		}







	
		
			
		
	
	
		
			
		
	

		for ( obj : dirty)
		{

			String sql = "UPDATE  SET ";
			boolean isFirst = true;
			for (Map.Entry entry : map.entrySet())
			{
				if (!isFirst) sql = sql + ", ";
				isFirst = false;
				sql = sql + entry.getKey() + "= ?";
			}
			sql = sql + " WHERE 1=1"
	
			+ " AND  = ? ";
			if (db.testOut != null) db.testOut.println(sql);
			if (sql != null)
			{
				try {
					PreparedStatement stmt = db.con.prepareStatement(sql);
					int idx = 0;
					for (Map.Entry entry : map.entrySet())
					{
						idx++;
						stmt.setObject(idx, entry.getValue());
					}
	
					idx++;
					stmt.setObject(idx, obj.get());
	
					stmt.executeUpdate();
					stmt.close();
				} catch (SQLException e)
				{
					e.printStackTrace();
				}
			}
	
			DBSet<> added = obj.get().comparisonClone();
			added.removeAll(original.get(obj).get());
			DBSet<> removed = original.get(obj).get().comparisonClone();
			removed.removeAll(obj.get());
			for ( toobj: added)
			{
				HashMap<String, Object> linkmap = new HashMap<String, Object>();
	
	    
				linkmap.put("", obj.get());
	
	
	    
	    
	    
	    
				linkmap.put("", toobj.get());
	
				String linksql = "INSERT INTO  (";
				isFirst = true;
				for (Map.Entry entry : linkmap.entrySet())
				{
					if (!isFirst) linksql = linksql + ", ";
					isFirst = false;
					linksql = linksql + entry.getKey();
				}
				linksql = linksql + ") VALUES (";
				for (int n = 0; n < linkmap.size(); n++)
				{
					if (n != 0) linksql = linksql + ", ";
					linksql = linksql + "?";
				}
		        linksql = linksql + ")";
		        if (db.testOut != null) db.testOut.println(linksql);
		        if (db.con != null)
		        {
					try {
						PreparedStatement stmt = db.con.prepareStatement(linksql);
						int idx = 0;
						for (Map.Entry entry : linkmap.entrySet())
						{
							idx++;
							stmt.setObject(idx, entry.getValue());
						}
						stmt.executeUpdate();
						stmt.close();
					} catch (SQLException e)
					{
						e.printStackTrace();
					}
		        }
			}
			for ( toobj: removed)
			{
				HashMap<String, Object> linkmap = new HashMap<String, Object>();
	
	    
				linkmap.put("", obj.get());
	
	
	    
	    
	    
	    
				linkmap.put("", toobj.get());
	
				String linksql = "DELETE FROM  "
					+ " WHERE 1=1";
				for (Map.Entry entry : linkmap.entrySet())
				{
					linksql = linksql + " AND " + entry.getKey() + " = ?";
				}
				if (db.testOut != null) db.testOut.println(linksql);
				if (db.con != null)
				{
					try {
						PreparedStatement stmt = db.con.prepareStatement(linksql);
						int idx = 0;
						for (Map.Entry entry : linkmap.entrySet())
						{
							idx++;
							stmt.setObject(idx, entry.getValue());
						}
						stmt.executeUpdate();
						stmt.close();
					} catch (SQLException e)
					{
						e.printStackTrace();
					}
				}
			}
	

		}
		dirty.clear();



















  
  
  
	
		
	
  
  
  
    NoKey
    rs.(prefix + "_")
    new <
      
        
        , 
      >(
      
        rs.(prefix + "_")
        , rs.(prefix + "_")
      )
  
    






  
  
  
	
		
	
  
  
  
    NoKey
    rs.(column + )
    new <
      
        
        , 
      >(
      
        rs.(column + )
        , rs.(column + )
      )
  
    





  
  
    
    
    
    
    
  







© 2015 - 2025 Weber Informatics LLC | Privacy Policy