/* ALTERNATIVE APPROACHES  : 
 * 1. Multiple columns. (one implemented)
 * 2. Multiple rows using unions.
 * 3. Flag values as it is.
*/
/**
 * This system procedure is used to return the list  
 * of indexes defined in the current database.
 */
CREATE PROCEDURE psp_indexes
(   
	in :database_qual   VARCHAR(20) = DATABASE(), -- Name of the database
    in :table_name      VARCHAR(255) = NULL -- Name of the table
)

RETURNS
(
    TABLE_QUALIFIER     VARCHAR (20),  -- Name of the database that contains the table
    TABLE_OWNER         VARCHAR (20),  -- owner of the table
    TABLE_NAME          VARCHAR(255),  -- Name of the table
    INDEX_NAME          VARCHAR(255),  -- Name of the index
    INDEX_TYPE          CHAR(20), 	    -- Type of the index - Primary/Foreign 
    COLUMN_NAME         VARCHAR(255),  -- Name of the column
    ORDINAL_POSITION    USMALLINT,  -- Ordinal position of the index
    DUPLICATES_ALLOWED  CHAR(3), -- Duplicate Index
    UPDATABLE           CHAR(3), -- Modifiable Index
    CASE_SENSITIVE      CHAR(3), -- Case sensitive Index
    ASC_DESC		    CHAR(1), -- Asc or Desc index
    NAMED_INDEX		    CHAR(3)  -- Named or UnNamed Index
);

BEGIN

  declare :pkName VARCHAR(255);

  -- Check if the database qualifier specified is a blank string
  if (rtrim(:database_qual) = '') then
    SIGNAL 'S1000', 'Please enter a valid database name. Database name cannot be a blank string'; 
  end if;

  -- Check if the table_name specified is a blank string
  if (rtrim(:table_name) = '') then
    SIGNAL 'S1000', 'Table name cannot be a blank string'; 
  end if;

  -- If database qualifier is null, use current database
  SET :database_qual = IFNULL(:database_qual, DATABASE());

  /* If table name is not supplied or null value
     match all */	
  SET :table_name = IFNULL(:table_name,'%');

  SELECT B."PK_NAME" INTO :pkName FROM dbo.fSQLPrimaryKeys ( :database_qual, :table_name ) B;  -- For creating missing optional ddfs

  SELECT A."TABLE_QUALIFIER",
         A."TABLE_OWNER", 
         A."TABLE_NAME",
         A."INDEX_NAME",

       CASE
        WHEN ( SELECT COUNT(B."PK_NAME") FROM dbo.fSQLPrimaryKeys ( :database_qual, :table_name ) B WHERE B."PK_NAME" = A."INDEX_NAME" ) > 1 THEN 'PRIMARY KEY INDEX'
        WHEN ( SELECT COUNT(C."FK_NAME") FROM dbo.fSQLForeignKeys ( :database_qual, '%', :table_name ) C WHERE C."FK_NAME" = A."INDEX_NAME" ) > 1 THEN 'FOREIGN KEY INDEX'       
        ELSE 'NORMAL INDEX'
       END AS "INDEX_TYPE",

         A."COLUMN_NAME",
         A."SEQ_IN_INDEX" AS "ORDINAL_POSITION",

       CASE A."NON_UNIQUE"
        WHEN 0 THEN 'NO'
        ELSE 'YES'
       END AS "DUPLICATES_ALLOWED",

       CASE 
        WHEN ( SELECT TOP 1 I.Xi$Flags & 2 FROM X$File F, X$Index I, X$Field E
               WHERE F.Xf$Name = RTRIM(A."TABLE_NAME")
                 AND E.Xe$Name = RTRIM( A."COLUMN_NAME" )
                 AND I.Xi$File = Xf$Id
                 AND I.Xi$File = E.Xe$File
                 AND I.Xi$Field = E.Xe$Id
                 AND I.Xi$Part = A."SEQ_IN_INDEX" - 1 ) = 2 THEN 'YES'
        ELSE 'NO'
       END AS "UPDATABLE",

       CASE 
        WHEN ( SELECT TOP 1 I.Xi$Flags & 32 FROM X$File F, X$Index I, X$Field E
               WHERE F.Xf$Name = RTRIM(A."TABLE_NAME")
                 AND E.Xe$Name = RTRIM( A."COLUMN_NAME" )
                 AND I.Xi$File = Xf$Id
                 AND I.Xi$File = E.Xe$File
                 AND I.Xi$Field = E.Xe$Id
                 AND I.Xi$Part = A."SEQ_IN_INDEX" - 1 ) = 32 THEN 'NO'
        ELSE 'YES'
       END AS "CASE_SENSITIVE",

         A."COLLATION" AS "ASC_DESC",

       CASE 
        WHEN ( SELECT TOP 1 I.Xi$Flags & 128 FROM X$File F, X$Index I, X$Field E
               WHERE F.Xf$Name = RTRIM(A."TABLE_NAME")
                 AND E.Xe$Name = RTRIM( A."COLUMN_NAME" )
                 AND I.Xi$File = Xf$Id
                 AND I.Xi$File = E.Xe$File
                 AND I.Xi$Field = E.Xe$Id
                 AND I.Xi$Part = A."SEQ_IN_INDEX" - 1 ) = 128 THEN 'YES'
        ELSE 'NO'
       END AS "NAMED_INDEX"

  FROM dbo.fSQLStatistics ( :database_qual, :table_name, 1 ) A

  WHERE A."INDEX_NAME" IS NOT NULL

  ORDER BY A."INDEX_NAME", "ORDINAL_POSITION";

END; -- End of the stored procedure.

