FB/IB'de SQLDialect'e göre alanların DataType tanımı nedir ?
Bunun nedeni FB NUMERIC gibi float alanları tutarken temel tipler olan SMALLINT, INTEGER, INT64 gibi veri yapılarını kullanıyor. Yani 1,1 numeric için SMALLINT yetiyor ve içinde SMALLINT bir alanda bunu tutuyor. Yani NUMERIC, DECIMAL gibi alanlar aslında sanal alanlar.
Buna göre kodun Dialect 3 ve 1 için yeniden düzenlenmesi gerekecek.
Buna göre kodun Dialect 3 ve 1 için yeniden düzenlenmesi gerekecek.
- Böylece adım adım tüm kodu açık hale getireceksin bak anladım...
- Tüm fonksiyonu yazayım... Ben sadece 8 ve 27 ile ilgilendiğimden kod karmaşasına girmemek için sadeleştirmiştim...



- Tüm fonksiyonu yazayım... Ben sadece 8 ve 27 ile ilgilendiğimden kod karmaşasına girmemek için sadeleştirmiştim...
Kod: Tümünü seç
Function TForm1.TipDetayi(Field_Type, Field_Sub_Type, Field_Length, Field_Precision, Field_Scale : Integer ) : String;
begin
Result := '';
Case Field_Type OF
8 : // 'INTEGER';
If IBDataBase1.SQLDialect = 3 then
begin
case Field_Sub_Type of
0 : Result := 'INTEGER';
1 : Result := Format('NUMERIC (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
2 : Result := Format('DECIMAL (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
end; // Case
end
else // Dialect 3 değilse
if Field_Scale <> 0 then
begin
If IBDataBase1.SQLDialect = 1
then Result := Format('NUMERIC (%d, %d)',[9, Abs(Field_Scale)] ) // EMS, IBExpert, SQLHammer'den feyz alıyoruz Dial1 ise NUMERIC olsun
else Result := Format('DECIMAL (%d, %d)',[9, Abs(Field_Scale)] );
end
else Result := 'INTEGER';
27: // 'DOUBLE';
If Abs(Field_Scale) <> 0 then
begin
If IBDataBase1.SQLDialect = 1 // Yeni Dialect çıkarsa şimdiden uyumlu olduk :)))))
then Result := Format('NUMERIC (%d, %d)',[15, Abs(Field_Scale)] ) // EMS, IBExpert, SQLHammer'den feyz alıyoruz Dial1 ise NUMERIC olsun
else Result := Format('DECIMAL (%d, %d)',[15, Abs(Field_Scale)] );
end
else Result := 'DOUBLE PRECISION';
7 : // 'SMALLINT'
If IBDataBase1.SQLDialect = 3 then
begin
case Field_Sub_Type of
0 : Result := 'SMALLINT';
1 : Result := Format('NUMERIC (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
2 : Result := Format('DECIMAL (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
end; // Case
end
else // Dialect 3 değilse
if Field_Scale <> 0
then Result := Format('DECIMAL (%d, %d)',[4, Abs(Field_Scale)] )
else Result := 'SMALLINT';
16: // 'INT64';
If IBDataBase1.SQLDialect = 3 then
case Field_Sub_Type of
0 : Result := 'DECIMAL (18, 0)';
1 : Result := Format('NUMERIC (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
2 : Result := Format('DECIMAL (%d, %d)',[Field_Precision, Abs(Field_Scale)] );
end;
10: // 'FLOAT';
Result := 'FLOAT';
14: // 'CHAR';
Result := Format('CHAR (%d)',[Field_Length] );
35: // 'TIMESTAMP';
If IBDataBase1.SQLDialect = 3
then Result := 'TIMESTAMP'
else Result := 'DATE';
13: // 'TIME';
Result := 'TIME';
12: // 'DATE';
Result := 'DATE';
37: // 'VARCHAR';
Result := Format('VARCHAR (%d)',[Field_Length] );
40: // 'CSTRING';
Result := Format('CSTRING (%d)',[Field_Length] );
261: // 'BLOB';
Result := 'BLOB';
9: Result := 'QUAD';
11: Result := 'D_FLOAT (Double Precision)';
end; // Case
Result := Format('%s /* (Tip:%d, SubType:%d) */',[Result, Field_Type, Field_Sub_Type] );
end;
Evet eminim. Dialect 1 de tablo yaratıp denedim. SQL ile bu bilgiyi almanın daha esnek olduğunu düşünerek bir SQL yazdım. İleride güncellemesi de kolay olur ve yükü server çeker. Henüz tamamlanmadı ama bir fikir olması açısından vereyim. Bu kod sadece Dialect 1 VT'lerin tiplerini almak için, dialect 3 e genişletilebilir ve optimize edilebilir:
-- Uyum problemi için yeniden düzenledim --
Kod: Tümünü seç
/* Dialect 1 için tablo alanları bilgisi */
SELECT b.RDB$FIELD_NAME, c.RDB$FIELD_TYPE, c.RDB$FIELD_SUB_TYPE, b.RDB$FIELD_ID,
c.RDB$FIELD_LENGTH, c.RDB$FIELD_SCALE,
case
when c.RDB$FIELD_TYPE = 07 then /* SMALLINT */
case
when (c.RDB$FIELD_SUB_TYPE = 0 or c.RDB$FIELD_SUB_TYPE is null) then
case when c.RDB$FIELD_SCALE = 0 then 'SMALLINT'
else 'NUMERIC'
end
when c.RDB$FIELD_SUB_TYPE = 1 then 'NUMERIC'
when c.RDB$FIELD_SUB_TYPE = 2 then 'DECIMAL'
end
when c.RDB$FIELD_TYPE = 08 then /* INTEGER */
case
when (c.RDB$FIELD_SUB_TYPE = 0 or c.RDB$FIELD_SUB_TYPE is null) then
case when c.RDB$FIELD_SCALE = 0 then 'INTEGER'
else 'NUMERIC'
end
when c.RDB$FIELD_SUB_TYPE = 1 then 'NUMERIC'
when c.RDB$FIELD_SUB_TYPE = 2 then 'DECIMAL'
end
when c.RDB$FIELD_TYPE = 09 then 'QUAD'
when c.RDB$FIELD_TYPE = 10 then 'FLOAT'
when c.RDB$FIELD_TYPE = 11 then 'D_FLOAT'
when c.RDB$FIELD_TYPE = 14 then 'CHAR'
when c.RDB$FIELD_TYPE = 27 then /* DOUBLE PRECISION */
case
when (c.RDB$FIELD_SUB_TYPE = 0 or c.RDB$FIELD_SUB_TYPE is null) then
case when c.RDB$FIELD_SCALE = 0 then 'DOUBLE PRECISION'
else 'NUMERIC'
end
when c.RDB$FIELD_SUB_TYPE = 1 then 'NUMERIC'
when c.RDB$FIELD_SUB_TYPE = 2 then 'DECIMAL'
end
when c.RDB$FIELD_TYPE = 35 then 'DATE'
when c.RDB$FIELD_TYPE = 37 then 'VARCHAR'
when c.RDB$FIELD_TYPE = 40 then 'CSTRING'
when c.RDB$FIELD_TYPE = 261 then 'BLOB'
end
FROM RDB$RELATIONS a
INNER JOIN RDB$RELATION_FIELDS b
ON a.RDB$RELATION_NAME = b.RDB$RELATION_NAME
INNER JOIN RDB$FIELDS c
ON b.RDB$FIELD_SOURCE = c.RDB$FIELD_NAME
INNER JOIN RDB$TYPES d
ON c.RDB$FIELD_TYPE = d.RDB$TYPE
WHERE a.RDB$SYSTEM_FLAG = 0
AND d.RDB$FIELD_NAME = 'RDB$FIELD_TYPE'
ORDER BY b.RDB$FIELD_ID
En son fduman tarafından 08 Haz 2005 05:12 tarihinde düzenlendi, toplamda 2 kere düzenlendi.
Bu kodu sen mi yazdın.
Bu yazdığın SQL dialect 1 içinse

Employee.GDB
SQLDialect 1
Type 8
SubType 0
Table : SALES
Field : TOTAL_VALUE
görünüyor ki, Bahsettiğim alan INTEGER çıkacak...

Kod: Tümünü seç
when c.RDB$FIELD_TYPE = 08 then
case
when (c.RDB$FIELD_SUB_TYPE = 0 or c.RDB$FIELD_SUB_TYPE is null) then
'INTEGER'
when c.RDB$FIELD_SUB_TYPE = 1 then 'NUMERIC'
when c.RDB$FIELD_SUB_TYPE = 2 then 'DECIMAL'
end

Employee.GDB
SQLDialect 1
Type 8
SubType 0
Table : SALES
Field : TOTAL_VALUE
görünüyor ki, Bahsettiğim alan INTEGER çıkacak...
Employee tablosunda bir anormallik var.
Dialect 3 için:
SALES AGED alanı tip 16, subtype 0, scale -9 ve IBExpert bunu NUMERIC olarak tanıyor. Bu alan NUMERIC (18, 9) tipinde.
IBExpert ile aynı tipte bir alan yarattığımda :
tip 16, subtype 1, scale -9. IBExpert bunu da NUMERIC tanımlıyor. Zannedersem IB/FB 'ün önceki sürümlerinden gelen bir uyum problemi mevcut veya backup restore aracı ile bu tablo IB 6 dan FB 1.5 e aktarılırken bir hata yapmış. Ancak IBExpert bu hatayı kendi içinde scale kontrolü yaparak düzeltiyor.
Dialect 3 için:
SALES AGED alanı tip 16, subtype 0, scale -9 ve IBExpert bunu NUMERIC olarak tanıyor. Bu alan NUMERIC (18, 9) tipinde.
IBExpert ile aynı tipte bir alan yarattığımda :
tip 16, subtype 1, scale -9. IBExpert bunu da NUMERIC tanımlıyor. Zannedersem IB/FB 'ün önceki sürümlerinden gelen bir uyum problemi mevcut veya backup restore aracı ile bu tablo IB 6 dan FB 1.5 e aktarılırken bir hata yapmış. Ancak IBExpert bu hatayı kendi içinde scale kontrolü yaparak düzeltiyor.
Sanırım Dialect 1 yaratıldığında Dialect 3 olarak açamıyordun. Tip uyuşmazlığı söz konusu olduğundan herhalde.
Dialect 3 için yazdığım SQL aşağıda. Bu da Dialect 1 de hatalı sonuç verir. Dialect 1 için yukardakini 3 için bunu kullanmalısınız.
-- Yukarıda bahsettiğim uyum sorunu için yeniden düzenledim --
Dialect 3 için yazdığım SQL aşağıda. Bu da Dialect 1 de hatalı sonuç verir. Dialect 1 için yukardakini 3 için bunu kullanmalısınız.
Kod: Tümünü seç
/* Dialect 3 için tablo alanları bilgisi */
SELECT b.RDB$FIELD_NAME, c.RDB$FIELD_TYPE, c.RDB$FIELD_SUB_TYPE, b.RDB$FIELD_ID,
c.RDB$FIELD_LENGTH, c.RDB$FIELD_SCALE,
case
when c.RDB$FIELD_TYPE = 07 then /* SMALLINT */
case
when (c.RDB$FIELD_SUB_TYPE = 0 or c.RDB$FIELD_SUB_TYPE is null) then
case when c.RDB$FIELD_SCALE = 0 then 'SMALLINT'
else 'NUMERIC'
end
when c.RDB$FIELD_SUB_TYPE = 1 then 'NUMERIC'
when c.RDB$FIELD_SUB_TYPE = 2 then 'DECIMAL'
end
when c.RDB$FIELD_TYPE = 08 then /* INTEGER */
case
when (c.RDB$FIELD_SUB_TYPE = 0 or c.RDB$FIELD_SUB_TYPE is null) then
case when c.RDB$FIELD_SCALE = 0 then 'INTEGER'
else 'NUMERIC'
end
when c.RDB$FIELD_SUB_TYPE = 1 then 'NUMERIC'
when c.RDB$FIELD_SUB_TYPE = 2 then 'DECIMAL'
end
when c.RDB$FIELD_TYPE = 09 then 'QUAD'
when c.RDB$FIELD_TYPE = 10 then 'FLOAT'
when c.RDB$FIELD_TYPE = 11 then 'D_FLOAT'
when c.RDB$FIELD_TYPE = 12 then 'DATE'
when c.RDB$FIELD_TYPE = 13 then 'TIME'
when c.RDB$FIELD_TYPE = 14 then 'CHAR'
when c.RDB$FIELD_TYPE = 16 then /* INT64 */
case
when (c.RDB$FIELD_SUB_TYPE = 0 or c.RDB$FIELD_SUB_TYPE is null) then
case when c.RDB$FIELD_SCALE = 0 then 'INT64'
else 'NUMERIC'
end
when c.RDB$FIELD_SUB_TYPE = 1 then 'NUMERIC'
when c.RDB$FIELD_SUB_TYPE = 2 then 'DECIMAL'
end
when c.RDB$FIELD_TYPE = 27 then /* DOUBLE PRECISION */
case
when (c.RDB$FIELD_SUB_TYPE = 0 or c.RDB$FIELD_SUB_TYPE is null) then
case when c.RDB$FIELD_SCALE = 0 then 'DOUBLE PRECISION'
else 'NUMERIC'
end
when c.RDB$FIELD_SUB_TYPE = 1 then 'NUMERIC'
when c.RDB$FIELD_SUB_TYPE = 2 then 'DECIMAL'
end
when c.RDB$FIELD_TYPE = 35 then 'TIMESTAMP'
when c.RDB$FIELD_TYPE = 37 then 'VARCHAR'
when c.RDB$FIELD_TYPE = 40 then 'CSTRING'
when c.RDB$FIELD_TYPE = 261 then 'BLOB'
end
FROM RDB$RELATIONS a
INNER JOIN RDB$RELATION_FIELDS b
ON a.RDB$RELATION_NAME = b.RDB$RELATION_NAME
INNER JOIN RDB$FIELDS c
ON b.RDB$FIELD_SOURCE = c.RDB$FIELD_NAME
INNER JOIN RDB$TYPES d
ON c.RDB$FIELD_TYPE = d.RDB$TYPE
WHERE a.RDB$SYSTEM_FLAG = 0
AND d.RDB$FIELD_NAME = 'RDB$FIELD_TYPE'
ORDER BY a.RDB$RELATION_NAME, b.RDB$FIELD_ID