Metadata for Numeric Columns

Forum related to PostgreSQL

Moderators: gto, cipto_kh, EgonHugeist, olehs

Post Reply
sandeep_c24
Expert Boarder
Expert Boarder
Posts: 158
Joined: 06.11.2005, 01:43

Metadata for Numeric Columns

Post by sandeep_c24 »

I have changed GetColumns to return numeric and decimal column Size and Decimal digits correctly. It didn't work with Postgres 8.xx. I am not sure whether this fix will work for older versions or not.

Code: Select all

function TZPostgreSQLDatabaseMetadata.GetColumns(const Catalog: string;
  const SchemaPattern: string; const TableNamePattern: string;
  const ColumnNamePattern: string): IZResultSet;
{const
  VARHDRSZ = 4;
}var
  TypeOid, AttTypMod: Integer;
  Key, SQL, PgType: string;
begin
  Key := Format('get-columns:%s:%s:%s:%s',
    [Catalog, SchemaPattern, TableNamePattern, ColumnNamePattern]);

  Result := GetResultSetFromCache(Key);
  if Result = nil then
  begin
    Result := ConstructVirtualResultSet(TableColColumnsDynArray);

    if HaveMinimumServerVersion(7, 3) then
    begin
      SQL := 'SELECT n.nspname,c.relname,a.attname,a.atttypid,a.attnotnull,'
        + 'a.atttypmod,a.attlen,a.attnum,pg_get_expr(def.adbin, def.adrelid) as adsrc,dsc.description '
        + ' FROM pg_catalog.pg_namespace n '
        + ' JOIN pg_catalog.pg_class c ON (c.relnamespace = n.oid) '
        + ' JOIN pg_catalog.pg_attribute a ON (a.attrelid=c.oid) '
        + ' LEFT JOIN pg_catalog.pg_attrdef def ON (a.attrelid=def.adrelid'
        + ' AND a.attnum = def.adnum) LEFT JOIN pg_catalog.pg_description dsc'
        + ' ON (c.oid=dsc.objoid AND a.attnum = dsc.objsubid) '
        + ' LEFT JOIN pg_catalog.pg_class dc ON (dc.oid=dsc.classoid'
        + ' AND dc.relname=''pg_class'') LEFT JOIN pg_catalog.pg_namespace dn'
        + ' ON (dc.relnamespace=dn.oid AND dn.nspname=''pg_catalog'') '
        + ' WHERE a.attnum > 0 AND NOT a.attisdropped';
      if SchemaPattern <> '' then
      begin
        SQL := SQL + ' AND n.nspname LIKE '
          + EscapeString(SchemaPattern);
      end;
    end
    else
    begin
      SQL := 'SELECT NULL::text AS nspname,c.relname,a.attname,a.atttypid,'
        + 'a.attnotnull,a.atttypmod,a.attlen,a.attnum,NULL AS adsrc,'
        + 'NULL AS description FROM pg_class c, pg_attribute a '
        + ' WHERE a.attrelid=c.oid AND a.attnum > 0 ';
    end;

    SQL := SQL + ' AND c.relname LIKE ' + EscapeString(ToLikeString(TableNamePattern))
      + ' AND a.attname LIKE ' + EscapeString(ToLikeString(ColumnNamePattern))
      + ' ORDER BY nspname,relname,attnum';

    with GetConnection.CreateStatement.ExecuteQuery(SQL) do
    begin
      while Next do
      begin
        AttTypMod := GetIntByName('atttypmod');
        TypeOid := StrToInt(GetStringByName('atttypid'));
        PgType := GetPostgreSQLType(TypeOid);

        Result.MoveToInsertRow;
        Result.UpdateNull(1);
        Result.UpdateString(2, GetStringByName('nspname'));
        Result.UpdateString(3, GetStringByName('relname'));
        Result.UpdateString(4, GetStringByName('attname'));
        Result.UpdateInt(5, Ord(GetSQLTypeByOid(TypeOid)));
        Result.UpdateString(6, PgType);
        Result.UpdateInt(8, 0);

        if (PgType = 'bpchar') or (PgType = 'varchar') then
        begin
          if AttTypMod <> -1 then
            Result.UpdateInt(7, AttTypMod - 4)
          else Result.UpdateInt(7, 0);
        end
        else if (PgType = 'numeric') or (PgType = 'decimal') then
        begin
          AttTypMod := AttTypMod - 4;
          Result.UpdateInt(7, AttTypMod shr 16);
          Result.UpdateInt(9, AttTypMod and $FFFF);
          Result.UpdateInt(10, 10);
        end
        else if (PgType = 'bit') or (PgType = 'varbit') then
        begin
          Result.UpdateInt(7, AttTypMod);
          Result.UpdateInt(10, 2);
        end
        else
        begin
          Result.UpdateInt(7, GetIntByName('attlen'));
          Result.UpdateInt(10, 2);
        end;

        Result.UpdateNull(8);
        if GetBooleanByName('attnotnull') then
        begin
          Result.UpdateString(18, 'NO');
          Result.UpdateInt(11, Ord(ntNoNulls));
        end
        else
        begin
          Result.UpdateString(18, 'YES');
          Result.UpdateInt(11, Ord(ntNullable));
        end;
        Result.UpdateString(12, GetStringByName('description'));
        Result.UpdateString(13, GetStringByName('adsrc'));
        Result.UpdateNull(14);
        Result.UpdateNull(15);
        Result.UpdateInt(16, Result.GetInt(7));
        Result.UpdateInt(17, GetIntByName('attnum'));

        Result.UpdateNullByName('AUTO_INCREMENT');
        Result.UpdateBooleanByName('CASE_SENSITIVE',
          GetIdentifierConvertor.IsCaseSensitive(
          GetStringByName('attname')));
        Result.UpdateBooleanByName('SEARCHABLE', True);
        Result.UpdateBooleanByName('WRITABLE', True);
        Result.UpdateBooleanByName('DEFINITELYWRITABLE', True);
        Result.UpdateBooleanByName('READONLY', False);

        Result.InsertRow;
      end;
      Close;
    end;

    AddResultSetToCache(Key, Result);
  end;
end;
Mark there are other changes that I have made should I post them here so that you can look at them when you have time or do you want me to hold them until after current version is released.

Sandeep
User avatar
mdaems
Zeos Project Manager
Zeos Project Manager
Posts: 2766
Joined: 20.09.2005, 15:28
Location: Brussels, Belgium
Contact:

Post by mdaems »

I'm a little scared as it didn't pass the test suite yet and it's not tested with older versions. Don't these changes change how field properties are set when retrieving a dataset? Or does it change this the good way?

I would say... hold them till after current release, but on the other hand, maybe it's better to put them in the user patches forum. That way it's at least somewhere we don't forget about it.

Mark
Image
sandeep_c24
Expert Boarder
Expert Boarder
Posts: 158
Joined: 06.11.2005, 01:43

Post by sandeep_c24 »

The only change is to the following lines

Code: Select all

          AttTypMod := AttTypMod - 4;
          Result.UpdateInt(7, AttTypMod shr 16);
Could you please tell what error you got.

Sandeep
User avatar
mdaems
Zeos Project Manager
Zeos Project Manager
Posts: 2766
Joined: 20.09.2005, 15:28
Location: Brussels, Belgium
Contact:

Post by mdaems »

Maybe I did express myself wrongly... I didn't get an error as I never ran the test suite using postgres and know nobody who does. So if I would merge the change I would have no idea if the basic functions still work after the change.
And as you are not certain about the older versions it's like diving into water without knowing how deep it is.
Did you ever run the test suite? It's not that difficult...Just compile and configure...
And if you could install an older PG version next to your currrent one (maybe a very old version?), that would be even better.

Mark
Image
sandeep_c24
Expert Boarder
Expert Boarder
Posts: 158
Joined: 06.11.2005, 01:43

Post by sandeep_c24 »

Hi Mark

I think it might be a good idea for me to setup these tests on my machine so that I can run them before sending the updates. Can I find some instruction on how to setup these tests. I tried running some tests yesterday but the database related tests didn't work as there was no database on my machine.

Sandeep
User avatar
mdaems
Zeos Project Manager
Zeos Project Manager
Posts: 2766
Joined: 20.09.2005, 15:28
Location: Brussels, Belgium
Contact:

Post by mdaems »

Hi Sandeep,

There's a documentation file in the zeoslib package. See : {zeoslib root}/documentation/articles_generated/output/buildingtests/html/buildingtests.html

Mainly chapter 3 will be of your interest. The other chapters talk about the automated build+test procedure. I use it and it works nice now. But as a first start I think it may be easier to build everything manually.
- Build TestFramework+Install
- Build Test projects in packages/{compiler}/build directory
- Make sure a db server is available and get the connection information
- Adjust {zeoslib root}/database/test.properties file
- Run Test projects in packages/{compiler}/build directory

If you have Java+Ant available on your machine you could also use the build scripts in {zeoslib root}/build directory.

Mark
Image
Post Reply