/*
CLASS {NATIVE_DB|_Java}, NATIVE, UNTESTED:

NATIVE: NATIVE_DB_import .

FUN Check_blobs_are_supported ==> BOOL,
    UNSUPPORTED('BLOBS ARE NOT IMPLEMENED FOR JAVA') : .

TEST of_supported:
     ASSERT !Check_blobs_are_supported .

*/
import java.sql.*;
import java.util.Date;
import java.util.ArrayList;

public class NATIVE_DB {
    
    public static ArrayList<NATIVE_DB> All_db = new ArrayList<NATIVE_DB>();
    

    //public boolean use_OleDb;
    public String Connection_String;
    public Connection S_c;
    public PreparedStatement Sql;
    public ResultSet D_r;
	public String User_name;

    public static int DB_Create_connection(String Connection, String User,
        int Provider) throws Exception
    {
		Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        if (All_db.size() == 0)
            All_db.add(new NATIVE_DB("", User));
        int i = All_db.indexOf(null);
        if (i < 0)
        {
            i = All_db.size();
            All_db.add(null);
        }
        All_db.set(i, new NATIVE_DB(Connection, User));
        return i;
    }

    public static boolean DB_Connect(int Handle, String Password)
    {
        NATIVE_DB db = All_db.get(Handle);
        try
        {
            String Connection = db.Connection_String;
            
            //System.console().printf("* * * connecting %s|%s|%s\n",
            //    Connection, db.User_name, Password);
            
            db.S_c = DriverManager.getConnection(Connection,
				db.User_name, Password);
            //db.S_c.Open();
            return !db.S_c.isClosed();
        }
        catch(Exception E)
        {
            AL4_system.Any_exception(E);
        }
        return false;
    }

    public NATIVE_DB(String Connection, String User)
    {
        Connection_String = Connection;
		User_name = User;
    }

    public static void DB_Disconnect(int Handle)
    {
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            db.S_c.close();
			All_db.set(Handle, null);
        }
        catch(Exception E)
        {
            AL4_system.Any_exception(E);
        }
    }
    
	public static boolean DB_Is_connected(int Handle)
    {
    	try
        {
	        NATIVE_DB db = All_db.get(Handle);
	        return db.S_c != null && !db.S_c.isClosed();
        }
        catch(Exception E)
        {
            AL4_system.Any_exception(E);
        }
        return false;
    }
    
    public static void DB_Destroy_connection(int Handle)
    {
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.S_c != null)
            {
                if (!db.S_c.isClosed())
                    db.S_c.close();
                db.S_c = null;
            }
            All_db.set(Handle, null);
        }
        catch(Exception E)
        {
            AL4_system.Any_exception(E);
        }
    }
    
    public static int DB_Begin_transaction(int Handle)
    {
        try
        {
            NATIVE_DB db = All_db.get(Handle);
			db.S_c.setAutoCommit(false);
        }
        catch(Exception E)
        {
            AL4_system.Any_exception(E);
        }
		return 0;
    }
    
    public static void DB_End_transaction(int Handle, int Transaction_handle,
        boolean Commited)
    {
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (Commited) db.S_c.commit();
            else          db.S_c.rollback();
        }
        catch(Exception E)
        {
            AL4_system.Any_exception(E);
        }
    }
    
    public static int DB_Execute(int Handle, String Sql_text)
    {
        int RESULT = 0;
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            db.Sql = db.S_c.prepareStatement(Sql_text);
            RESULT = db.Sql.executeUpdate();
        }
        catch(Exception E)
        {
            AL4_system.Any_exception(E);
        }
        return RESULT;
    }
    
    public static boolean DB_Open(int Handle, String Sql_text)
    {
        boolean RESULT = false;
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            
            //System.console().printf("@ @ @ opening: %s\n", Sql_text);
            
            //db.Sql = db.S_c.prepareStatement(Sql_text, 
            //    ResultSet.TYPE_SCROLL_SENSITIVE, 
            //    ResultSet.CONCUR_UPDATABLE);
            //
            //System.console().printf("@ @ @ prepared\n");
            
            db.Sql = db.S_c.prepareStatement(Sql_text);
            
            //System.console().printf("@ @ @ prepared\n");
            
            db.D_r = db.Sql.executeQuery();
            //System.console().printf("@ @ @ executed\n");
            
            //RESULT = db.D_r.first();
            RESULT = db.D_r.next();
            
            //System.console().printf("@ @ @ opened: %s\n", RESULT ? "ok" : "not ok");
        }
        catch(Exception E)
        {
            System.console().printf("@ @ @ exception: %s\n", E.getMessage());
            AL4_system.Any_exception(E);
            E.printStackTrace();
            RESULT = false;
        }
        return RESULT;
    }
    
    public static void DB_Close(int Handle)
    {
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.D_r != null)
            {
               db.D_r.close();
               db.D_r = null;
            }
        }
        catch(Exception E)
        {
            AL4_system.Any_exception(E);
        }
    }
    
    public static boolean DB_Next(int Handle)
    {
        boolean RESULT = false;
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.D_r == null) return false;
            RESULT = db.D_r.next();
        }
        catch(Exception E)
        {
            AL4_system.Any_exception(E);
            RESULT = false;
        }
        return RESULT;
    }
    
    public static int DB_Count_fields(int Handle)
    {
        int RESULT = 0;
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.D_r == null) return 0;
            RESULT = db.D_r.getMetaData().getColumnCount();
            
            //System.console().printf("* * * count fields: %d\n", RESULT);
        }
        catch(Exception E)
        {
            AL4_system.Any_exception(E);
            RESULT = 0;
        }
        return RESULT;
    }
    
    public static String DB_Field_name_by_index(int Handle, int Indx)
    {
        String RESULT = "";
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.D_r == null) return "";
            if (Indx >= 0 && Indx < db.D_r.getMetaData().getColumnCount())
                RESULT = db.D_r.getMetaData().getColumnName(Indx+1);
            
            //System.console().printf("* * * field name by index(%d): %s\n",
            //    Indx, RESULT);
        }
        catch(Exception E)
        {
            //AL4_system.Any_exception(E);
            RESULT = "";
        }
        return RESULT;
    }
    
    public static int DB_Integer(int Handle, int Indx)
    {
        int RESULT = 0;
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.D_r == null) return RESULT;
            //System.console().printf("* * * column_count=%d DB_Integer(%d) = ",
            //    db.D_r.getMetaData().getColumnCount(), Indx);
            if (Indx >= 0 && Indx < db.D_r.getMetaData().getColumnCount())
            {
                //System.console().printf("* * * DB_Integer(%d) = ", Indx);
                RESULT = (int)db.D_r.getLong(Indx+1);
                //System.console().printf("= %d", RESULT);
            }
        }
        catch(Exception E)
        {
            //System.console().printf("@ @ @i exception: %s\n", E.getMessage());
            //AL4_system.Any_exception(E);
            RESULT = 0;
        }
        return RESULT;
    }
    
    public static double DB_Real(int Handle, int Indx)
    {
        double RESULT = 0;
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.D_r == null) return RESULT;
            //System.console().printf("* * *R column_count=%d DB_Integer(%d) = ",
            //    db.D_r.getMetaData().getColumnCount(), Indx);
            if (Indx >= 0 && Indx < db.D_r.getMetaData().getColumnCount())
            {
                //System.console().printf("* * * DB_Real(%d) = ", Indx);
                RESULT = db.D_r.getDouble(Indx+1);
                //System.console().printf("= %f", RESULT);
            }
        }
        catch(Exception E)
        {
            //System.console().printf("@ @ @R exception: %s\n", E.getMessage());
            //AL4_system.Any_exception(E);
            RESULT = 0;
        }
        return RESULT;
    }
    
    public static double DB_Date_time(int Handle, int Indx)
    {
        double RESULT = new java.util.Date(1899, 12, 31).getTime();
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.D_r == null) return RESULT;
            if (Indx >= 0 && Indx < db.D_r.getMetaData().getColumnCount())
            {
                RESULT = db.D_r.getDate(Indx+1).getTime();
            }
        }
        catch(Exception E)
        {
            //AL4_system.Any_exception(E);
        }
        return RESULT;
    }
    
    public static boolean DB_boolean(int Handle, int Indx)
    {
        boolean RESULT = false;
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.D_r == null) return RESULT;
            if (Indx >= 0 && Indx < db.D_r.getMetaData().getColumnCount())
            {
                 RESULT = db.D_r.getBoolean(Indx+1);
            }
        }
        catch(Exception E)
        {
            //AL4_system.Any_exception(E);
        }
        return RESULT;
    }
    
    public static boolean DB_Is_null(int Handle, int Indx)
    {
        boolean RESULT = true;
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.D_r == null) return RESULT;
            if (Indx >= 0 && Indx < db.D_r.getMetaData().getColumnCount())
            {
                db.D_r.getObject(Indx+1);
				RESULT = db.D_r.wasNull();
            }
        }
        catch(Exception E)
        {
            //AL4_system.Any_exception(E);
        }
        return RESULT;
    }
    
    public static String DB_String(int Handle, int Indx)
    {
        String RESULT = "";
        try
        {
            NATIVE_DB db = All_db.get(Handle);
            if (db.D_r == null) return RESULT;
            if (Indx >= 0 && Indx < db.D_r.getMetaData().getColumnCount())
            {
                RESULT = db.D_r.getString(Indx+1);
				 if (RESULT == null)  RESULT = "";
            }
        }
        catch(Exception E)
        {
            //AL4_system.Any_exception(E);
        }
        return RESULT;
    }
    
}
/*
    
CONST STR:
    NATIVE_DB_import = ""
    
    NATIVE_DB_Create_connection = @
    "   RESULT = NATIVE_DB.DB_Create_connection(X_Connection, X_User, "
    "       X_Provider);"

    NATIVE_DB_Destroy_connection = @
    "   NATIVE_DB.DB_Destroy_connection(X_Handle);"

    NATIVE_DB_Connect = @
    "   RESULT = NATIVE_DB.DB_Connect(X_Handle, X_Password);"
    
    NATIVE_DB_Disconnect = @
    "   NATIVE_DB.DB_Disconnect(X_Handle);"
    
	NATIVE_DB_Is_connected = @
    "   RESULT = NATIVE_DB.DB_Is_connected(X_Handle);"

    NATIVE_DB_Begin_transaction = @
    "   RESULT = NATIVE_DB.DB_Begin_transaction(X_Handle);"

    NATIVE_DB_End_transaction = @
    "   NATIVE_DB.DB_End_transaction(X_Handle, X_Transaction,"
    "       X_Commited);"

    NATIVE_DB_Commit_transaction = @
    ""

    NATIVE_DB_Rollback_transaction = @
    ""

    NATIVE_DB_Execute = @
    "   RESULT = NATIVE_DB.DB_Execute(X_Handle, X_SQL);"

    NATIVE_DB_Open = @
    "   RESULT = !NATIVE_DB.DB_Open(X_Handle, X_SQL);"

    NATIVE_DB_Close = @
    "   NATIVE_DB.DB_Close(X_Handle);"

    NATIVE_DB_Next = @
    "   RESULT = NATIVE_DB.DB_Next(X_Handle);"

    NATIVE_DB_Count_fields = @
    "   RESULT = NATIVE_DB.DB_Count_fields(X_Handle);"

    NATIVE_DB_Field_by_index = @
    "   RESULT = NATIVE_DB.DB_Field_name_by_index(X_Handle, X_Ind);"

    NATIVE_DB_Integer = @
    "   RESULT = NATIVE_DB.DB_Integer(X_Handle, X_Ind);"

    NATIVE_DB_Real = @
    "   RESULT = NATIVE_DB.DB_Real(X_Handle, X_Ind);"

    NATIVE_DB_Date_time = @
    "   RESULT = NATIVE_DB.DB_Date_time(X_Handle, X_Ind);"

    NATIVE_DB_Boolean = @
    "   RESULT = NATIVE_DB.DB_boolean(X_Handle, X_Ind);"

    NATIVE_DB_Is_null = @
    "   RESULT = NATIVE_DB.DB_Is_null(X_Handle, X_Ind);"

    NATIVE_DB_String = @
    "   RESULT = NATIVE_DB.DB_String(X_Handle, X_Ind);"
    
    NATIVE_Load_from_blob = ""

    NATIVE_Read_blob = ""

    .
        
END
*/

