Table TemelleriBasics of Table

This page is part of an incremental translation project. Body text not yet translated to Turkish falls back to English even in TR mode.

Önceki bölümlerde tartışıldığı gibi, table, genişletilmiş feature'ları nedeniyle TROIA'nın en önemli data type'larından biridir. Bu bölüm, table'lar hakkındaki temel kavramları ve en çok kullanılan table command ve function'larını tanıtmayı amaçlar.As discussed in previous sections, table is most important data types of TROIA, because of the its extended features. This section aims to introduce basic concepts about tables and most used table command and functions.

GirişIntroduction

Table, string, integer veya double gibi TROIA'nın built-in bir data type'ıdır. Basit bir data type olmasının yanında, table, programcıların database application'ları kolayca implement etmesine olanak tanıyan çok fazla feature'a sahiptir.Table is a built-in data type of TROIA like string, integer or double. In addition to being a simple data type, table has too many features that allow programmers to implement database applications with easily.

Table data type'a dayanan çok sayıda yapı ve kavram vardır, hatta chart, diagram vb. de dahildir. Ayrıca database query'leri ve etkileşimleri de table'lara dayanır. Table'ları ve feature'larını tartışmadan önce, "table" kelimesiyle neyi kastettiğimize odaklanmalıyız.Thera are too many structures and concepts which are based on table data type, even charts, diagrams etc. Also database queries and interactions are based on tables. Before discussing tables and its features we must focus what we mean with the word : “table”.

Database Table / Data Type / Table ControlDatabase Table/Data Type/Table Control

TROIA Platformu, database table'larını yalnızca data saklamak için kullanır, bu yüzden bu bölümde table'lardan bahsederken database table'larını kastetmiyoruz. Database table'ları tanımlama ve data manipulation command'ları kullanma, sonraki bölümlerde tartışılacaktır.TROIA Platform, uses database tables just for storing data, so when we discuss tables in this section we don’t mean database tables. Defining database tables and using data manipulation commands will be discussed in next sections.

TROIA'da iki ana table kavramı vardır; birincisi table data type, ikincisi dialog'larda kullanılan "table control"dür. Table control'ün bir user interface'i ve bu user interface üzerinde conditional formatting gibi bazı function'ları vardır. Table control'lerin ayrıca server memory'de table type'ında bir variable'ı vardır, başka bir deyişle "table control" bir user interface object'idir ve table bir tür değerdir (textfield'ın background color'ı & değeri gibi). Bu yüzden bu bölümde tartışılan tüm feature'ları ve operation'ları bir table control'ün değerine uygulamak mümkündür.In TROIA, there are two main table concepts, first one is table data type and second one is “table control” that is used on dialogs. Table control has a user interface and some functions on its user interface such as conditional formatting etc. Table controls have also a table typed variable in server memory, in other words “table control” is user interface object and table is a kind of value (like textfield’s background color & its value). So its possible to apply all features and operations discussed in this section, to value of a table control.

Bu bölümde "table" kelimesini, type'ı table olan bir variable'ı kastetmek için kullanıyoruz. Table control'lerle ilgili feature'lar sonraki bölümlerde tartışılacaktır.In this section we use the word table “table” to mean a variable whose type is table. Features related with table controls will be discussed in next sections.

Table Tanımlama/DoldurmaDefining/Filling Tables

Diğer data type'lar gibi, bir table tanımlamak için data definition command'ları kullanılır ve bir integer variable tanımlamaktan çok farklı değildir. İşte bir integer ve bir table tanımlayan tek bir object command'ı.Like other data types, data definition commands are used to define a table and it is not so much different defining an integer variable. Here is a single object command that defines an integer and a table.

OBJECT:OBJECT:

TABLE TABLEVAR, TABLE TABLEVAR,

INTEGER INTVAR; INTEGER INTVAR;

Primitive data type'lardan (int, double vb.) farklı olarak, table iki boyutlu bir data type'tır. Bu yüzden, table'lar için yalnızca variable tanımlamak pek kullanışlı değildir. Table instance'ını tanımlamaya ek olarak, data saklamak için yapısını/column'larını da tanımlamalıyız. Column eklemek için, column ismi, column type'ı ve column uzunluğu alan ve table variable'a bir column ekleyen bir command vardır. Bu command "APPEND COLUMN" olarak adlandırılır, işte syntax'ı ve örnek kullanımı:Unlike primitive data types (int, double etc), table is a two dimensional data type. Therefore, only variable definition is not so much useful for tables.In addition to defining table instance, also we must define its structure/columns to store data. To add columns, there is a command which gets column name, column type and colcumn length and adds a column to table variable. This command is called “APPEND COLUMN”, here is its syntax and sample usage:

APPEND COLUMN {columnname}, {columntype}, {columnlength} TO {table};APPEND COLUMN {columnname}, {columntype}, {columnlength} TO {table};

/* add a 100 char length string column named COL1 to TABLEVAR *//* add a 100 char length string column named COL1 to TABLEVAR */

APPEND COLUMN COL1, STRING, 100 TO TABLEVAR;APPEND COLUMN COL1, STRING, 100 TO TABLEVAR;

APPEND COLUMN COL2, INTEGER, 10 TO TABLEVAR;APPEND COLUMN COL2, INTEGER, 10 TO TABLEVAR;

/* now table is able to store data *//* now table is able to store data */

APPEND COLUMN command'ı kullanılarak STRING, INTEGER, TEXT, DATE, DATETIME, DECIMAL, LONG, TIME ve TIMES column'ları eklemek mümkündür ve TABLE veya VECTOR type'larını table column'u olarak eklemeye izin verilmez. Column isimleri benzersiz olmalıdır, bu yüzden aynı isme sahip iki column eklemeye izin verilmez. Command hakkında daha fazla detay için lütfen help dokümanlarına bakın.It is possible to add STRING, INTEGER,TEXT,DATE,DATETIME,DECIMAL,LONG, TIME and TIMES columns using APPEND COLUMN command and it is not allowed to add TABLE or VECTOR types as table column. Column names must be unique, so it is not allowed to add two columns that has same name. For more details about the command please see help documents.

Table tanımlamanın başka bir seçeneği, bir dialog üzerinde table control kullanmaktır. Her ui table'ın data model'i olarak global bir table variable'ı vardır ve programcılar table data'sına bu model üzerinden erişebilir. Model table, table control ile aynı isme sahiptir ve bir textfield ile değerinden (string variable olarak) çok farklı değildir. APPEND COLUMN, ui table'lar için de çalışır, ancak yeni column'ları ekleme ve user interface'te gösterme sonraki bölümde tartışılacaktır.Another option to define table is using a table control on a dialog. Every ui table has a global table variable as its data model and programmers can access table data over this model. Model table has same name with table control and its not too much different from a textfield and its value (as a string variable). APPEND COLUMN also works for ui tables, but appending and showing new columns on user interface will be discussed in next section.

Ayrıca, SELECT command'ı bir table variable'ı column'larıyla birlikte tanımlar, bu yüzden programcıların command'dan önce table'ı ve column'larını tanımlamasına gerek yoktur. SELECT command'ı ayrıca query sonucuna bağlı olarak row ekler. SELECT command'ı ilgili bölümlerde tartışılacaktır, ancak şimdilik SELECT command'ının var olan bir table variable'ın column model'ini değiştirdiğini veya table'ı column model'iyle birlikte tanımladığını bilmeliyiz. İşte örnek bir kod:Additionally, SELECT command defines a table variable with its columns, so programmers do not need to define table and its columns before the command. SELECT command also adds rows depending to query result. SELECT command will be discussed in related sections, but for now we must know that, SELECT command changes the column model of an existing table variable or defines table with its column model. Here is a sample code:

OBJECT:OBJECT:

TABLE T1; TABLE T1;

/* change column-model and data of an existing variable *//* change column-model and data of an existing variable */

SELECT USERNAME, CREATEDBY, CREATEDAT FROM IASUSERS WHERE 1 = 2 INTO T1;SELECT USERNAME, CREATEDBY, CREATEDAT FROM IASUSERS WHERE 1 = 2 INTO T1;

/* define a table variable with its column-model *//* define a table variable with its column-model */

SELECT USERNAME, CREATEDBY, CREATEDAT FROM IASUSERS WHERE 1 = 2 INTO T2;SELECT USERNAME, CREATEDBY, CREATEDAT FROM IASUSERS WHERE 1 = 2 INTO T2;

Başka bir seçenek olarak, table'ı tanımlayan ve column bilgisini oluşturan bir CONSTRUCT command'ı vardır. Bu command, table tanımlamak için nadiren kullanılır; daha fazla bilgi için lütfen help dokümanına bakın.As another option, there is a CONSTRUCT command that defines table and creates it’s column information. This command is rarely used to define tables, for more information please see it’s help document.

Table'lara Row EklemeAdding Rows To Tables

Açık olduğu üzere, row'lar bir table variable'ının data'sıdır. TROIA'da bir table'a row eklemenin birden fazla yolu vardır. Bir table variable'a programatik olarak yeni bir row eklemek için APPEND ROW command'ı kullanılır. Bu command, ilk row'a, table'ın sonuna veya belirli bir row'dan sonraya yeni bir row ekleyebilir. İşte syntax ve örnek, daha fazla detay için lütfen TROIA Help'e bakın.As its obvious, rows are the data of a table variable. In TROIA there are multiple ways of adding rows to a table. To add a new row to a table variable programmatically, APPEND ROW command is used.This command is able to add a new row to first row, end of the table or after a specific row. Here is the syntax and example, for more detail please see TROIA Help.

APPEND ROW TO {table} [ATHEAD | ATBETWEEN];APPEND ROW TO {table} [ATHEAD | ATBETWEEN];

OBJECT:OBJECT:

TABLE T1; TABLE T1;

SELECT USERNAME, CREATEDBY, CREATEDAT FROM IASUSERS WHERE 1 = 2 INTO T1;SELECT USERNAME, CREATEDBY, CREATEDAT FROM IASUSERS WHERE 1 = 2 INTO T1;

APPEND ROW TO T1;APPEND ROW TO T1;

Ayrıca table'ı database'den seçilen data ile doldurmak da mümkündür. SELECT command'ının başka bir feature'ı da table'a yeni row'lar eklemesidir. İşte bir örnek:Also it is possible to fill table with data which is selected from database. Another feature of SELECT command is adding new rows to table. Here is an example:

OBJECT:OBJECT:

TABLE T1; TABLE T1;

SELECT USERNAME, CREATEDBY, CREATEDAT FROM IASUSERS INTO T1;SELECT USERNAME, CREATEDBY, CREATEDAT FROM IASUSERS INTO T1;

Ayrıca kullanıcılar tarafından user interface'ten table'lara row eklemek de mümkündür. Bir ui table'a yeni bir row eklemek için INSERT tuşu kullanılır. Bu, sonraki bölümlerde detaylı olarak tartışılacaktır.Also it is possible to add rows to tables from user interface by users. To add a new row to a ui table, INSERT key is used. It will be discussed detailly in next sections.

Table Data'sına ErişmeAccessing Table Data

Bir table cell'ine erişmek için "_" operator'ü kullanılır. Bu operator, en azından table ismi & column ismi veya ek bir row numarası bilgisine ihtiyaç duyar.To access data on a table cell, “_” operator is used. This operator needs at least two information table name & column name or an additional row number.

Row Index KullanmaUsing Row Index

Diğer programlama dillerindeki array'ler gibi, cell değeri erişiminde row index belirtilebilir. TROIA'da row index'ler 1'den başlar, işte örnek:Like arrays on other programming languages, row index can be specified on cell value access. In TROIA row indexes starts from 1, here is the example:

OBJECT:OBJECT:

TABLE T1, TABLE T1,

INTEGER ROWINDEX, INTEGER ROWINDEX,

STRING RESULT; STRING RESULT;

ROWINDEX = 1;ROWINDEX = 1;

RESULT = '';RESULT = '';

SELECT USERNAME, CREATEDBY, CREATEDAT FROM IASUSERS INTO T1;SELECT USERNAME, CREATEDBY, CREATEDAT FROM IASUSERS INTO T1;

WHILE ROWINDEX < T1_ROWCOUNTWHILE ROWINDEX < T1_ROWCOUNT

BEGINBEGIN

RESULT = RESULT + T1[ROWINDEX]_USERNAME + ' created by '; RESULT = RESULT + T1[ROWINDEX]_USERNAME + ' created by ';

RESULT = RESULT + T1[ROWINDEX]_CREATEDBY + ' at '; RESULT = RESULT + T1[ROWINDEX]_CREATEDBY + ' at ';

RESULT = RESULT + T1[ROWINDEX]_CREATEDAT + TOCHAR(10); RESULT = RESULT + T1[ROWINDEX]_CREATEDAT + TOCHAR(10);

ROWINDEX = ROWINDEX + 1; ROWINDEX = ROWINDEX + 1;

ENDWHILE;ENDWHILE;

Table cell'lerine row index kullanarak erişmek, en çok kullanılan yöntem değildir; çünkü bu yöntemde programcı her cell erişiminde row index sağlamalıdır.Accessing table cells using row indexes is not mostly used method, because in this method programmer must provice row index at each cell access.

Active Row: Internal Row CursorActive Row: Internal Row Cursor

Development efforunu azaltmak için, table variable'ın active row'u gösteren internal bir cursor'ı vardır, bu yüzden programcıların aynı row'daki her cell erişimi için row numarasına işaret etmesine gerek yoktur. İşte aynı bilgiyi yazdıran, ancak row index yerine active row kullanan TROIA kodu:To reduce development efford, table variable have an internal cursor that shows active row,so programmers need to point row number for each cell access on same row.Here is the TROIA code that prints same information, but using active row instead of row index:

OBJECT:OBJECT:

TABLE T1, TABLE T1,

INTEGER ROWINDEX, INTEGER ROWINDEX,

STRING RESULT; STRING RESULT;

ROWINDEX = 1;ROWINDEX = 1;

RESULT = '';RESULT = '';

SELECT USERNAME, CREATEDBY, CREATEDATSELECT USERNAME, CREATEDBY, CREATEDAT

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

WHILE ROWINDEX < T1_ROWCOUNTWHILE ROWINDEX < T1_ROWCOUNT

BEGINBEGIN

T1_ACTIVEROW = ROWINDEX; T1_ACTIVEROW = ROWINDEX;

RESULT = RESULT + T1_USERNAME + ' created by '; RESULT = RESULT + T1_USERNAME + ' created by ';

RESULT = RESULT + T1_CREATEDBY + ' at '; RESULT = RESULT + T1_CREATEDBY + ' at ';

RESULT = RESULT + T1_CREATEDAT + TOCHAR(10); RESULT = RESULT + T1_CREATEDAT + TOCHAR(10);

ROWINDEX = ROWINDEX + 1; ROWINDEX = ROWINDEX + 1;

ENDWHILE;ENDWHILE;

Active row, table'larla çalışmanın en çok kullanılan ve en önemli kavramıdır. Table command'larının çoğu, looping veya locating gibi active row'a dayanır.Active row is the most used and important concept of working with tables. Most of table commands are based on active row, such as looping or locating.

"Active Row", "Selected Row" ile aynı değildir; her zaman tek bir row'a işaret eder. Bu cursor değeri, user interface veya farklı TROIA command'ları tarafından ayarlanır. Active row'u etkileyen command'ları ilgili bölümlerde tartışacağız. Ancak bu bölümde, active row'un doğrudan iki ana yöntemle ayarlanabileceğini bilmeliyiz.“Active Row” is not same with “Selected Row”, it always points a single row. This curser value is set by user interface or different TROIA commands. We will discuss commands which effects active row in related sections. But in this section we must know that it is possible to set active row directly, by two main method.

Birincisi, READ command'ının INDEX varyasyonuyla değeri doğrudan ayarlamaktır, işte read command'ının temel syntax'ı:First one is directly setting the value with READ command’s INDEX variation, here is the basic syntax of read command:

/* to a given index *//* to a given index */

READ {table} WITH INDEX {activerowindex};READ {table} WITH INDEX {activerowindex};

/* to an index related with current *//* to an index related with current */

READ {table} WITH FIRST | LAST | NEXT | PREV;READ {table} WITH FIRST | LAST | NEXT | PREV;

Diğer yöntem, table'ın ACTIVEROW flag'iyle active row değerini ayarlamaktır.Another method is setting active row value with ACTIVEROW flag of table.

Table Flag'leriTable Flags

Row count, active row gibi table'lar hakkında belirli bilgiler döndüren bazı özel field'lar vardır. Bu field'ların isimleri reserved'dir ve column ismi olarak kullanılamaz. Ve table column'ları gibi _ operator'ü ile erişilebilir.There are some special fields that returns specific information about tables like row count, active row etc. Names of these fields are reserved and can not be used as column names. And can be accessed by _ operator like table columns.

Table Hakkındaki Flag'lerFlags about Table

İşte table'ın kendisi hakkında data döndüren flag'ler (active row'dan bağımsız). Bu flag'lerin bazıları ilgili bölümlerde detaylı olarak tartışılacaktır (w.b.d.).Here are flags that returns data about table’s itself (independent from active row). Some of this flags will be discussed (w.b.d.) detailly, in related sections.

FlagTypeR-OnlyDescription
ACTIVEROWINTEGERNOReturns active row index between 1-row count
ROWCOUNTINTEGERYESReturns number of rows in table
DBTABLENAMESTRINGYESDb table whose data is set to table (w.b.d.)
HASSELECTEDROWINTEGERYESReturns whether given table has a selected row
ACTIVECOLINTEGERYESActive column index of ui table
ACTIVECOLNAMESTRINGYESActive column name of ui table (w.b.d.)
ARROWSTATEINTEGERYESFor the ArrowClick Event of ui table (w.b.d.)

UI Table Row'ları Hakkındaki Flag'lerFlags about UI Table Rows

Ayrıca, table'ın row ile ilgili flag'leri vardır, her row her flag için farklı değerler saklayabilir. Bu flag'lere de row index ile veya row index olmadan erişilir. Row index belirtilmezse sistem active row'un flag değerini döndürür. Bu flag'ler ui table'lar için ilgili/anlamlı olsa da, herhangi bir table variable için de kullanılabilir. Ancak bu flag'leri ana amaçları dışında başka amaçlar için kullanmak önerilmez.Additionally, table has row releated flags, each row is able to store different values for each flag. This flags also accessed by with and without row index. If row index is not specified system returns active row’s flag value. Although this flags are related/meaningful for ui tables, they are also available for any table variable. But it is not recommended to use this flags for other purposes except their main purpose.

FlagTypeDescription
SELECTEDINTEGERis set to 1 when user selects row on ui, otherwise 0
HIDEINTEGERif it is set to 1, row is not visible on ui table
BKCOLORINTEGERto change row color on ui
ROWTOOLTIPSTRINGtooltip text which gets visible when user mouse stops on row
FYISTRINGanother alias for ROWTOOLTIP
FILTEREDINTEGERis set to 1 when row is invisible by a ui filter
SUMMARYROWINTEGERmust be set to 1, for subtotal/summary rows to avoid miscalculations
CHECKEDINTEGERonly set and read by TROIA applications

Bazı başka ui table flag'leri de vardır, bunlar ilgili bölümlerde tartışılacaktır.There are some other ui table flags, they will be discussed in related sections.

Persistency Flag'leriPersistency Flags

TROIA table'ları ayrıca object/relational persistency'yi destekler, bu yüzden programcıların data'yı database'e saklamak için uygun data manipulation statement'ını seçmek amacıyla ekstra bilgi saklamasına gerek yoktur. Row'un database'deki ilgili record'a kıyasla durumunu gösteren persistency state, persistency flag'lerinde saklanır. Bir cell değeri değiştiğinde veya interpreter tarafından database'den data okunduğunda otomatik olarak ayarlanırlar. İşte persistency flag'lerinin kısa ve basit bir listesi, her flag ve state geçişleri database bölümünde detaylı olarak tartışılacaktır.TROIA tables also support object/relational persistency, so programmers don’t need to store extra information to select appropriate data manimulation statement for storing data on database. Persistency state which indicates row’s state compared to releated record on database, is stored on persistency flags. They are set automatically when a cell value changed or when data is read from database by interpreter. Here is a short and simple list of persistency flags, each flag and its state transitions will be discussed detailly on database section.

FlagDescription
DELETEDReturns whether row is deleted by user, programmer
INSERTEDReturns whether row is a new row.
READReturns whether row read from database.
UPDATEDReturns whether row is updated after db read.

Table'larda LoopingLooping on Tables

TROIA'da, bir table'ın her row'u için bir şey yapmak için, bir index tanımlayıp while statement'ıyla loop yapmaya ve her iterasyonda index'i artırmaya gerek yoktur. Diğer seçenek, bazı diğer programlama dillerindeki for-each statement'larına çok benzeyen LOOP command'ıdır. Ayrıca bazı condition'lar eklemeyi de destekler, bu yüzden programcıların loop block'una bir if statement'ı eklemesine gerek yoktur. İşte en basit syntax:In TROIA, to do something for each row of a table, there is no need to define an index and loop with a while statement and increase index at each iteration. Other option is LOOP command which is very similer to for-each statements on some other programming languages. Also it supports to add some conditions so programmers don’t need to add an if statement to loop block. Here is the simplest syntax:

LOOP AT table [WHERE {condition}]LOOP AT table [WHERE {condition}]

BEGINBEGIN

block block

ENDLOOP;ENDLOOP;

Görüldüğü gibi LOOP command'ı, active row'u artırır ve yeni active row'da condition'ı çalıştırır; condition true dönerse inner block'unu çalıştırır, bu yüzden active row'un loop'tan önce ve sonra aynı olmadığını bilmeliyiz. İşte WHILE yerine LOOP command'ı kullanan aynı örnek.As it is obvious LOOP command, increases active row and executes condition new active row and if condition is returns true runs its inner block, so we must know that active row is not same at before the loop and after the loop. Here is the same example that uses LOOP command instead of WHILE.

OBJECT:OBJECT:

TABLE T1, TABLE T1,

STRING RESULT; STRING RESULT;

RESULT = '';RESULT = '';

SELECT USERNAME, CREATEDBY, CREATEDATSELECT USERNAME, CREATEDBY, CREATEDAT

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

LOOP AT T1LOOP AT T1

BEGINBEGIN

RESULT = RESULT + T1_USERNAME + ' created by '; RESULT = RESULT + T1_USERNAME + ' created by ';

RESULT = RESULT + T1_CREATEDBY + ' at '; RESULT = RESULT + T1_CREATEDBY + ' at ';

RESULT = RESULT + T1_CREATEDAT + TOCHAR(10); RESULT = RESULT + T1_CREATEDAT + TOCHAR(10);

ENDLOOP;ENDLOOP;

Ve where condition kullanan başka bir örnek. Bu örnekte, yalnızca 'btan' tarafından oluşturulan kullanıcılar yazdırılır.And another example that uses where condition. In this example, it prints users only created by ‘btan’.

OBJECT:OBJECT:

TABLE T1, TABLE T1,

STRING RESULT; STRING RESULT;

RESULT = '';RESULT = '';

SELECT USERNAME, CREATEDBY, CREATEDATSELECT USERNAME, CREATEDBY, CREATEDAT

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

LOOP AT T1 WHERE T1_CREATEDBY == 'btan'LOOP AT T1 WHERE T1_CREATEDBY == 'btan'

BEGINBEGIN

RESULT = RESULT + T1_USERNAME + ' created by '; RESULT = RESULT + T1_USERNAME + ' created by ';

RESULT = RESULT + T1_CREATEDBY + ' at '; RESULT = RESULT + T1_CREATEDBY + ' at ';

RESULT = RESULT + T1_CREATEDAT + TOCHAR(10); RESULT = RESULT + T1_CREATEDAT + TOCHAR(10);

ENDLOOP;ENDLOOP;

Hem WHERE condition ile hem de WHERE condition olmadan bu yöntem tüm table'ı tarar. Where condition sağlanırsa LOOP command'ı her row için condition expression'ını çalıştırır.Both with and without WHERE condition this method scans whole table. If where condition provided LOOP command executes condition expression for each row.

Daha Hızlı Looping: CRITERIA COLUMNS VaryasyonuLooping Faster: CRITERIA COLUMNS Variation

Where condition expression'ı olmadan başka bir seçenek, LOOP Command'ının CRITERIA COLUMNS varyasyonunu kullanmaktır. Bu varyasyonda sistem, condition expression'ını TROIA interpreter katmanında değil, java katmanında çalıştırır. Bu varyasyon, tüm table'ı TROIA katmanında taramaktan daha hızlı çalışır.Another option without a where condition expression is using CRITERIA COLUMNS variation of LOOP Command. In this variation system does not execute condition expression on TROIA interpereter layer, but in java layer. This variation works faster than scanning whole table on TROIA layer

LOOP AT {table} CRITERIA COLUMNS {columns} VALUES {values} [NOTCASESENSITIVE]LOOP AT {table} CRITERIA COLUMNS {columns} VALUES {values} [NOTCASESENSITIVE]

BEGINBEGIN

block block

ENDLOOPENDLOOP

/* {columns} & {values} are comma separated list. *//* {columns} & {values} are comma separated list. */

İşte CRITERIA COLUMNS ile looping'i gösteren bir örnek. Bu örnek, BTAN tarafından oluşturulan ve password validity'si 2000 olan kullanıcıları yazdırır:Here is an example, that shows looping with CRITERIA COLUMNS. This examle prints users that is created by BTAN and password validity is 2000:

OBJECT:OBJECT:

TABLE T1, TABLE T1,

STRING RESULT, STRING RESULT,

STRING STRCREATEDBY; STRING STRCREATEDBY;

SELECT USERNAME, CREATEDBY, PWDVALIDITYSELECT USERNAME, CREATEDBY, PWDVALIDITY

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

STRCREATEDBY = 'BTAN';STRCREATEDBY = 'BTAN';

RESULT = '';RESULT = '';

LOOP AT T1 CRITERIA COLUMNS CREATEDBY,PWDVALIDITY VALUES STRCREATEDBY,2000LOOP AT T1 CRITERIA COLUMNS CREATEDBY,PWDVALIDITY VALUES STRCREATEDBY,2000

BEGINBEGIN

RESULT = RESULT + T1_USERNAME + ':'; RESULT = RESULT + T1_USERNAME + ':';

RESULT = RESULT + T1_PWDVALIDITY + TOCHAR(10); RESULT = RESULT + T1_PWDVALIDITY + TOCHAR(10);

ENDLOOP;ENDLOOP;

Lütfen STRCREATEDBY'nin değerini değiştirin ve hem case sensitive hem de insensitive seçeneklerle, tek ve çoklu parametrelerle test edin. Ayrıca row'larla ilgili table flag'lerini condition olarak kullanmak da mümkündür. İşte INSERTED flag'ini CRITERIA COLUMNS condition'ı olarak kullanan basit bir örnek:Please change value of STRCREATEDBY and test with both case sensitive and insensitive options, with single and multiple parameters. Also it is possible to use table flags which are related with rows, as condition. Here is a simple example than uses INSERTED flag as CRITERIA COLUMNS condition:

OBJECT:OBJECT:

TABLE T1, TABLE T1,

STRING RESULT, STRING RESULT,

STRING STRCREATEDBY; STRING STRCREATEDBY;

SELECT USERNAME, CREATEDBY, PWDVALIDITYSELECT USERNAME, CREATEDBY, PWDVALIDITY

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

STRCREATEDBY = 'BTAN';STRCREATEDBY = 'BTAN';

RESULT = '';RESULT = '';

APPEND ROW TO T1;APPEND ROW TO T1;

T1_USERNAME = 'NewUser';T1_USERNAME = 'NewUser';

T1_CREATEDBY = 'BTAN';T1_CREATEDBY = 'BTAN';

T1_CREATEDBY = 30;T1_CREATEDBY = 30;

LOOP AT T1 CRITERIA COLUMNS CREATEDBY,INSERTED VALUES STRCREATEDBY,1LOOP AT T1 CRITERIA COLUMNS CREATEDBY,INSERTED VALUES STRCREATEDBY,1

BEGINBEGIN

RESULT = RESULT + T1_USERNAME + ':'; RESULT = RESULT + T1_USERNAME + ':';

RESULT = RESULT + T1_PWDVALIDITY + TOCHAR(10); RESULT = RESULT + T1_PWDVALIDITY + TOCHAR(10);

ENDLOOP;ENDLOOP;

Daha Hızlı Looping: Hash Index Üzerinde LoopLooping Faster: Loop on Hash Index

Ayrıca indekslenmiş column'ların farklı değerleri üzerinde loop yapmak için bir table variable üzerinde virtual index'ler oluşturmak da mümkündür. Bir index oluştururken, sistem indekslenmiş row'ların her değer kombinasyonu için row index'lerini bulur/hesaplar. Bu yüzden aynı column'lar için birden fazla loop ve farklı criteria değerlerine ihtiyacınız varsa, index'leri bir kez hesaplamak yüksek performanslı looping için kullanışlı olabilir.Also it is possible to create virtual indexes on a table variable to loop on different values of indexed columns. While creating an index, system finds/calculates indexes of rows for each value combination of indexed rows. So if you need multiple loops and different criteria values for same columns, calculating indexes for once may be useful for high performance looping.

Bir table üzerinde virtual hash oluşturmak için BUILDHASHINDEX command'ı kullanılır, işte syntax:To create virtual hashes on a table BUILDHASHINDEX command is used, here is the syntax:

BUILDHASHINDEX {indexname} COLUMNS {columns} ON {table} [FORCE];BUILDHASHINDEX {indexname} COLUMNS {columns} ON {table} [FORCE];

BUILDHASHINDEX command'ı, verilen index ismiyle zaten bir index varsa index'i yeniden oluşturmaz. Var olan bir index'in üzerine yazmak isterseniz opsiyonel FORCE parametresini kullanmalısınız. Ayrıca HASHASHINDEX() function'ı, aynı isimde bir index'in var olup olmadığını kontrol etmek için kullanışlıdır. Hash index'ler ve ilgili function'lar hakkında daha fazla bilgi için lütfen help dokümanlarına bakın. İşte hash index'ler üzerinde looping için basit bir örnek.BUILDHASHINDEX command does not recreate index if there is already an index with given index name. If you want to overwrite an existing index you must use optional FORCE parameter. Also HASHASHINDEX() function is useful to check whether an index exists with same name. For more information about hash indexes and related functions please see help documents. Here is a simple example for looping over hash indexes.

OBJECT:OBJECT:

TABLE T1, TABLE T1,

STRING RESULT, STRING RESULT,

STRING INDEXNAME; STRING INDEXNAME;

SELECT USERNAME, CREATEDBY,PWDVALIDITYSELECT USERNAME, CREATEDBY,PWDVALIDITY

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

INDEXNAME = 'myindex';INDEXNAME = 'myindex';

RESULT = '';RESULT = '';

BUILDHASHINDEX INDEXNAME COLUMNS PWDVALIDITY,CREATEDBY ON T1;BUILDHASHINDEX INDEXNAME COLUMNS PWDVALIDITY,CREATEDBY ON T1;

LOOP AT T1 CRITERIA INDEXED INDEX INDEXNAME VALUES 2000, 'BTAN'LOOP AT T1 CRITERIA INDEXED INDEX INDEXNAME VALUES 2000, 'BTAN'

BEGINBEGIN

RESULT = RESULT + T1_USERNAME + ':'; RESULT = RESULT + T1_USERNAME + ':';

RESULT = RESULT + T1_PWDVALIDITY + TOCHAR(10); RESULT = RESULT + T1_PWDVALIDITY + TOCHAR(10);

ENDLOOP;ENDLOOP;

RESULT = RESULT + '----------------' + TOCHAR(10);RESULT = RESULT + '----------------' + TOCHAR(10);

LOOP AT T1 CRITERIA INDEXED INDEX INDEXNAME VALUES 60, 'kkizir'LOOP AT T1 CRITERIA INDEXED INDEX INDEXNAME VALUES 60, 'kkizir'

BEGINBEGIN

RESULT = RESULT + T1_USERNAME + ':'; RESULT = RESULT + T1_USERNAME + ':';

RESULT = RESULT + T1_PWDVALIDITY + TOCHAR(10); RESULT = RESULT + T1_PWDVALIDITY + TOCHAR(10);

ENDLOOP;ENDLOOP;

Hangi Looping Yöntemi En İyisidir?Which Looping Method is the Best?

Önceki bölümlerde belirtildiği gibi, table'lar TROIA programlama dilinin ana ve en çok kullanılan data type'ıdır. Table'lar, doğası gereği bulk data saklar, bu yüzden table'larla çalışırken performans konularını göz önünde bulundurmak zorunludur. Looping, yüksek performanslı application'lar için de çok önemli bir süreçtir, bu yüzden programcılar data yapılarını ve search criteria'larını göz önünde bulundurarak doğru looping seçeneğini seçmelidir.As mentioned in previous sections, tables are the main and most used data type of TROIA programming language. Tables store bulk data because of its nature, so considering performance issues while working with tables is a must. Looping is also very important process for high performance applications, so programmers must select correct looping option considering their data structure, search criterias.

Önemli bir nokta olarak, programcılar table'larda loop yapmak için LOOP command'ını kullanmalıdır. Başka bir deyişle WHILE command'ı kullanmak ÖNERİLMEZ. Ayrıca table'ın data yapısını, search criteria'larını, criteria'lardaki expression'ları, loop sayısını vb. göz önünde bulundurarak doğru LOOP command seçeneğini seçmek çok önemlidir.As an important point, programmers must use LOOP command to loop on tables. In other words using WHILE command is NOT recommended. Also it is very important to select correct LOOP command option considering data structure of table, search criterias, expressions on criterias, number of loops etc.

Her looping seçeneğinin farklı artıları ve eksileri vardır. Programcının göz önünde bulundurması gereken ana kural, "TROIA command'ları yerine mümkün olduğunca java katmanını kullanmak"tır. Örneğin, mümkünse CRITERIA columns kullanmak WHERE condition'dan daha hızlıdır.Each looping option has different pros & cons. The main rule that programmer must consider is “using java layer as much as possible instead of TROIA commands”. For example, if it is possible using CRITERIA columns is faster than WHERE condition.

İkinci kural "aynı expression'ları bir kez hesaplamak"tır. Expression sonucu active row'un ilgili cell'iyle ilgili değilse, karşılaştırma değerlerini loop'tan önce hesaplamak kullanışlı olacaktır. İşte bir örnek:The second rule is “calculating same expressions once”. If expression result is not related cell of active row, calculating comparison values before the loop will be useful. Here is an example:

OBJECT:OBJECT:

TABLE T1, TABLE T1,

STRING RESULT; STRING RESULT;

RESULT = '';RESULT = '';

SELECT USERNAME, PWDVALIDITYSELECT USERNAME, PWDVALIDITY

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

/* calculate value for each row *//* calculate value for each row */

LOOP AT T1 WHERE T1_PWDVALIDITY == THIS.CALCMAXVALIDITY() * 4 + 40LOOP AT T1 WHERE T1_PWDVALIDITY == THIS.CALCMAXVALIDITY() * 4 + 40

BEGINBEGIN

RESULT = RESULT + T1_USERNAME + '-> max validity ' + TOCHAR(10); RESULT = RESULT + T1_USERNAME + '-> max validity ' + TOCHAR(10);

ENDLOOP;ENDLOOP;

İşte değeri looping'den önce hesaplayan daha hızlı bir alternatif:Here is faster alternative which calculate value before looping:

OBJECT:OBJECT:

TABLE T1, TABLE T1,

STRING RESULT, STRING RESULT,

INTEGER MAXVALIDITY; INTEGER MAXVALIDITY;

RESULT = '';RESULT = '';

SELECT USERNAME, PWDVALIDITYSELECT USERNAME, PWDVALIDITY

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

MAXVALIDITY = THIS.CALCMAXVALIDITY() * 4 + 40;MAXVALIDITY = THIS.CALCMAXVALIDITY() * 4 + 40;

LOOP AT T1 WHERE T1_PWDVALIDITY == MAXVALIDITYLOOP AT T1 WHERE T1_PWDVALIDITY == MAXVALIDITY

BEGINBEGIN

RESULT = RESULT + T1_USERNAME + '-> max validity ' + TOCHAR(10); RESULT = RESULT + T1_USERNAME + '-> max validity ' + TOCHAR(10);

ENDLOOP;ENDLOOP;

İşte karşılaştırma expression'ını CRITERIA COLUMNS ile java katmanına taşıyan daha hızlı bir alternatif:Here is faster alternative which moves comparison expression to java layer with CRITERIA COLUMNS:

OBJECT:OBJECT:

TABLE T1, TABLE T1,

STRING RESULT, STRING RESULT,

INTEGER MAXVALIDITY; INTEGER MAXVALIDITY;

RESULT = '';RESULT = '';

SELECT USERNAME, PWDVALIDITYSELECT USERNAME, PWDVALIDITY

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

MAXVALIDITY = THIS.CALCMAXVALIDITY() * 4 + 40;MAXVALIDITY = THIS.CALCMAXVALIDITY() * 4 + 40;

LOOP AT T1 CRITERIA COLUMNS PWDVALIDITY VALUES MAXVALIDITYLOOP AT T1 CRITERIA COLUMNS PWDVALIDITY VALUES MAXVALIDITY

BEGINBEGIN

RESULT = RESULT + T1_USERNAME + '-> max validity ' + TOCHAR(10); RESULT = RESULT + T1_USERNAME + '-> max validity ' + TOCHAR(10);

ENDLOOP;ENDLOOP;

Table'da LocatingLocating on Table

Bazı durumlarda, programcılar belirli bir row bulmak ve yalnızca bu row için bir şey yapmak amacıyla table'da loop yapar. TROIA'da, LOCATERECORD command'ı sayesinde programcıların bir row bulmak için loop yapmasına gerek yoktur. Bu command, verilen parametrelere göre doğru row'u bulur ve table'daki active row cursor'ını değiştirir. LOCATERECORD command'ı verilen parametrelerle doğru row'u bulamazsa active row'u değiştirmez ve SYS_STATUS'u 1'e ayarlar, bu yüzden programcı verilen parametrelerle bir row olup olmadığını kontrol etmek için bunu kullanır. İşte LOCATERECORD command'ının temel ve en çok kullanılan varyasyonu:In some cases, programmers loops on table to find a specific row and do something for this row only. In TROIA, programmers do not need to loop to find a row, thanks to LOCATERECORD command. This command finds the correct row due to given parameters and changes the active row cursor on table. If LOCATERECORD command can not find correct row with given parameters it does not changes the active row and sets SYS_STATUS to 1, so programmer use check whether there is a row with given parameters. Here is the basic and most used variation of LOCATERECORD command:

LOCATERECORD SEQUENTIAL COLUMNS {columns} VALUES {values}LOCATERECORD SEQUENTIAL COLUMNS {columns} VALUES {values}

ON {table} [NOTCASESENSITIVE] [NEXT] [LAST]; ON {table} [NOTCASESENSITIVE] [NEXT] [LAST];

'BTAN' tarafından oluşturulan iki kullanıcıyı yazdıran bir örnek; lütfen değeri değiştirin ve farklı parametreler ve varyasyonlarla test edin/çalıştırın.An example that prints two users which is created by ‘BTAN’, please change the value and test/run with different parameters and variations.

OBJECT:OBJECT:

TABLE T1; TABLE T1;

SELECT USERNAME, CREATEDBY,CHANGEDBYSELECT USERNAME, CREATEDBY,CHANGEDBY

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

SET TMPTABLE TO TABLE TMPTABLE;SET TMPTABLE TO TABLE TMPTABLE;

LOCATERECORD SEQUENTIAL COLUMNS CREATEDBY VALUES 'BTAN' ON T1;LOCATERECORD SEQUENTIAL COLUMNS CREATEDBY VALUES 'BTAN' ON T1;

STRINGVAR3 = T1_ACTIVEROW + '-'+ T1_USERNAME;STRINGVAR3 = T1_ACTIVEROW + '-'+ T1_USERNAME;

STRINGVAR3 = STRINGVAR3 + ' ('+ SYS_STATUS + ')';STRINGVAR3 = STRINGVAR3 + ' ('+ SYS_STATUS + ')';

LOCATERECORD SEQUENTIAL COLUMNS CREATEDBY VALUES 'BTAN' ON T1 NEXT;LOCATERECORD SEQUENTIAL COLUMNS CREATEDBY VALUES 'BTAN' ON T1 NEXT;

STRINGVAR3 = STRINGVAR3 + TOCHAR(10) +T1_ACTIVEROW + '-'+ T1_USERNAME;STRINGVAR3 = STRINGVAR3 + TOCHAR(10) +T1_ACTIVEROW + '-'+ T1_USERNAME;

STRINGVAR3 = STRINGVAR3 + ' ('+ SYS_STATUS + ')';STRINGVAR3 = STRINGVAR3 + ' ('+ SYS_STATUS + ')';

LOCATERECORD command'ının SEQUENTIAL varyasyonu, LOOP command'ının CRITERIA COLUMNS varyasyonuna çok benzer ve table'ı java katmanında tarar. Table'ı taramaya alternatif olarak, command'ın sıralı bir table üzerinde daha hızlı arama yapan bir BINARYSEARCH varyasyonu vardır. BINARYSEARCH varyasyonu yalnızca verilen column'larda sıralanmış (artan) table'larda çalışır. İşte syntax ve basit bir column örneği:SEQUENTIAL variation of LOCATERECORD command is very similar to CRITERIA COLUMNS variation of LOOP command and scans table on java layer. As an alternative to scanning table, command has an BINARYSEARCH variation which searches faster on as sorted table. BINARYSEARCH variation only works on sorted tables on given columns (ascending). Here is the syntax and a simple column example:

LOCATERECORD BINARYSEARCH COLUMNS {columns} VALUES {values}LOCATERECORD BINARYSEARCH COLUMNS {columns} VALUES {values}

ON {table} [NOTCASESENSITIVE]; ON {table} [NOTCASESENSITIVE];

OBJECT:OBJECT:

TABLE T1; TABLE T1;

SELECT USERNAME, CREATEDBY,CHANGEDBYSELECT USERNAME, CREATEDBY,CHANGEDBY

FROM IASUSERS FROM IASUSERS

ORDERBY CREATEDBY ORDERBY CREATEDBY

INTO T1; INTO T1;

LOCATERECORD BINARYSEARCH COLUMNS CREATEDBY VALUES 'BTAN' ON T1;LOCATERECORD BINARYSEARCH COLUMNS CREATEDBY VALUES 'BTAN' ON T1;

STRINGVAR3 = T1_ACTIVEROW + '-'+ T1_USERNAME;STRINGVAR3 = T1_ACTIVEROW + '-'+ T1_USERNAME;

STRINGVAR3 = STRINGVAR3 + ' ('+ SYS_STATUS + ')';STRINGVAR3 = STRINGVAR3 + ' ('+ SYS_STATUS + ')';

Ayrıca table'ın active row'unu bir hashindex üzerinden locate etmek de mümkündür. Bu seçenekle, programcılar index'i bir kez oluşturabilir ve bu index'i kullanarak farklı row değerleriyle row'ları locate edebilir. Bu varyasyon, her locate'te table'ı taramaya kıyasla işlem süresini azaltır. İşte syntax ve örnek:Also it is possible to locate table’s active row over an hashindex. With this option, programmers can create index once and locate rows with different row values using this index. This variations reduces to process time compared to scanning table on each locate. Here is the syntax and example:

LOCATERECORD INDEXED INDEX {indexname} VALUES {values}LOCATERECORD INDEXED INDEX {indexname} VALUES {values}

ON {table} [NEXT] [LAST]; ON {table} [NEXT] [LAST];

OBJECT:OBJECT:

TABLE T1; TABLE T1;

SELECT USERNAME, CREATEDBY,CHANGEDBYSELECT USERNAME, CREATEDBY,CHANGEDBY

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

BUILDHASHINDEX 'MyIndex' COLUMNS CREATEDBY ON T1;BUILDHASHINDEX 'MyIndex' COLUMNS CREATEDBY ON T1;

LOCATERECORD INDEXED INDEX 'MyIndex' VALUES 'BTAN' ON T1;LOCATERECORD INDEXED INDEX 'MyIndex' VALUES 'BTAN' ON T1;

STRINGVAR3 = T1_ACTIVEROW + '-'+ T1_USERNAME;STRINGVAR3 = T1_ACTIVEROW + '-'+ T1_USERNAME;

STRINGVAR3 = STRINGVAR3 + ' ('+ SYS_STATUS + ')';STRINGVAR3 = STRINGVAR3 + ' ('+ SYS_STATUS + ')';

LOCATERECORD INDEXED INDEX 'MyIndex' VALUES 'BTAN' ON T1 LAST;LOCATERECORD INDEXED INDEX 'MyIndex' VALUES 'BTAN' ON T1 LAST;

STRINGVAR3 = STRINGVAR3 + TOCHAR(10) + T1_ACTIVEROW + '-'+ T1_USERNAME;STRINGVAR3 = STRINGVAR3 + TOCHAR(10) + T1_ACTIVEROW + '-'+ T1_USERNAME;

STRINGVAR3 = STRINGVAR3 + ' ('+ SYS_STATUS + ')';STRINGVAR3 = STRINGVAR3 + ' ('+ SYS_STATUS + ')';

Görüldüğü gibi, LOCATERECORD varyasyonları LOOP command'ının varyasyonlarına benzer. Her varyasyonun farklı artıları ve eksileri vardır. Yüksek performanslı application'lar oluşturmak için programcılar, data yapısını, locate sayısını vb. göz önünde bulundurarak doğru varyasyonu belirlemelidir. Table'larda locating hakkında daha fazla detay için lütfen LOCATERECORD command'ının help dokümanlarına bakın.As it is obvious, LOCATERECORD variations are similar to LOOP command’s. Each variation has different pros and cons. To create high performance applications, programmers must decide correct variation due to data structure, locate count etc. For more details about locating on tables please see help documents of LOCATERECORD command.

Table Data'sını SıralamaSorting Table Data

Database'den sıralı row data'sı seçmek mümkündür, ancak bazı durumlarda programcıların table'ları application katmanında sıralaması gerekebilir. Verilen column'lara göre table variable'larını sıralamak için SORT command'ı kullanılır. Bir veya daha fazla column'a göre row'ları azalan ve artan sırada sıralamak mümkündür. Default sıralama artan ve case sensitive değildir. Temel syntax aşağıdadır:It is possible to select sorted row data from database but in some cases programmers may need sorting tables on application layer. To sort table variables due to given columns, SORT command is used. Its possible to sort rows descending and ascending order due to one or more columns. Default sorting is ascending and not case sensitive. Basic syntax is below:

SORT {tablename} [CASESENSITIVE] ON [DESC] {column1}, [DESC] {column2};SORT {tablename} [CASESENSITIVE] ON [DESC] {column1}, [DESC] {column2};

İşte kullanıcıları, onları kim tanımladığına ve tanımlama zamanına göre sıralayan basit bir örnek.Here is a simple example that sorts users due to who defined them and definition time.

OBJECT:OBJECT:

TABLE TMPTABLE; TABLE TMPTABLE;

SELECT USERNAME, CREATEDBY, CREATEDATSELECT USERNAME, CREATEDBY, CREATEDAT

FROM IASUSERSFROM IASUSERS

INTO TMPTABLE;INTO TMPTABLE;

SORT TMPTABLE ON CREATEDBY, DESC CREATEDAT;SORT TMPTABLE ON CREATEDBY, DESC CREATEDAT;

/* this command will be discussed later *//* this command will be discussed later */

SET TMPTABLE TO TABLE TMPTABLE;SET TMPTABLE TO TABLE TMPTABLE;

Ayrıca sort column'larını dinamik olarak sağlamak da mümkündür, aşağıdaki syntax ile:Also its possible to provide sort colums dynamically, with the syntax below:

SORT {tablename} [CASESENSITIVE] ON @{columnsastext};SORT {tablename} [CASESENSITIVE] ON @{columnsastext};

Bu syntax, programcıların runtime interpretation olmadan (runtime interpretation daha sonra tartışılacaktır) dinamik olarak sıralama yapmasına olanak tanır. İşte dinamik syntax kullanan aynı örnek:This syntax allows programmers to sort dynamically, without runtime interpretation (runtime interpretation will be discussed later). Here is the same example that uses dynamic syntax:

OBJECT:OBJECT:

TABLE TMPTABLE, TABLE TMPTABLE,

STRING STRINGVAR3; STRING STRINGVAR3;

SELECT USERNAME, CREATEDBY, CREATEDATSELECT USERNAME, CREATEDBY, CREATEDAT

FROM IASUSERSFROM IASUSERS

INTO TMPTABLE;INTO TMPTABLE;

STRINGVAR3 = 'CREATEDBY, DESC CREATEDAT';STRINGVAR3 = 'CREATEDBY, DESC CREATEDAT';

SORT TMPTABLE ON @STRINGVAR3;SORT TMPTABLE ON @STRINGVAR3;

/* this command will be discussed later *//* this command will be discussed later */

SET TMPTABLE TO TABLE TMPTABLE;SET TMPTABLE TO TABLE TMPTABLE;

Hiyerarşik Sırada SıralamaSort in Hierarchical Order

Bazı durumlarda, programcıların row'ları ilişkisel bir şekilde sıralaması gerekebilir. Table'ın bir id column'u ve parent id column'u varsa, TROIA bu tür table'lar için gelişmiş bir sıralama seçeneğine sahiptir. İşte iki ülke ve şehir saklayan örnek bir data modeli.In some cases, programmers may need to sort rows in a relational manner. If table has an id column and parent id column, TROIA has an advanced sorting option such tables. Here is a sample data mode that stores two countries and cities.

COUNTRYNAME
GERMANYKARLSRUHE
GERMANYBERLIN
TURKEYIZMIR
TURKEYISTANBUL
TURKEY
GERMANY

Ve hiyerarşik sıralamadan sonra ihtiyacınız olan data modeli:And you need data model after hierarchical sort:

COUNTRYNAME
GERMANY
GERMANYKARLSRUHE
GERMANYBERLIN
TURKEY
TURKEYIZMIR
TURKEYISTANBUL

Table'ları hiyerarşik bir şekilde ağaç benzeri bir table elde etmek üzere sıralamak için SORT HIERARCHICAL varyasyonu kullanılır. İşte syntax:To sort tables in hierarchical manner to get tree like table, SORT HIERARCHICAL variation is used. Here is the syntax:

SORT {table} HIERARCHICAL IDCOLUMN {idcolumn} PARENTIDCOLUMN {parentidcolumn}SORT {table} HIERARCHICAL IDCOLUMN {idcolumn} PARENTIDCOLUMN {parentidcolumn}

[ROOTINDICATOR {indicatorvalue}] [MARKLEAFSASNODE]; [ROOTINDICATOR {indicatorvalue}] [MARKLEAFSASNODE];

Id column'larındaki değerler benzersiz olmalıdır. Ve hem id hem de parentid column'ları tek bir row olmalıdır; data'nın id ve parentid için birden fazla column'u varsa, SORT HIERARCHICAL command'ından önce konsolide edilmelidir. İşte örnek data modelini oluşturan ve sıralayan örnek TROIA kodu:Values on id columns must be unique. And both for id and parentid columns must be single row, if data has multiple colums for id and parentid they must be consolidated before SORT HIERARCHICAL command. Here is sample TROIA code that creates and sorts sample data model:

SELECT USERNAME AS COUNTRY, CREATEDBY AS NAMESELECT USERNAME AS COUNTRY, CREATEDBY AS NAME

FROM IASUSERS FROM IASUSERS

WHERE 1=2 WHERE 1=2

INTO TMPTABLE; INTO TMPTABLE;

APPEND ROW TO TMPTABLE;APPEND ROW TO TMPTABLE;

TMPTABLE_COUNTRY = 'TURKEY';TMPTABLE_COUNTRY = 'TURKEY';

TMPTABLE_NAME = 'IZMIR';TMPTABLE_NAME = 'IZMIR';

APPEND ROW TO TMPTABLE;APPEND ROW TO TMPTABLE;

TMPTABLE_NAME = 'TURKEY';TMPTABLE_NAME = 'TURKEY';

APPEND ROW TO TMPTABLE;APPEND ROW TO TMPTABLE;

TMPTABLE_COUNTRY = 'GERMANY';TMPTABLE_COUNTRY = 'GERMANY';

TMPTABLE_NAME = 'KARLSRUHE';TMPTABLE_NAME = 'KARLSRUHE';

APPEND ROW TO TMPTABLE;APPEND ROW TO TMPTABLE;

TMPTABLE_NAME = 'GERMANY';TMPTABLE_NAME = 'GERMANY';

APPEND ROW TO TMPTABLE;APPEND ROW TO TMPTABLE;

TMPTABLE_COUNTRY = 'GERMANY';TMPTABLE_COUNTRY = 'GERMANY';

TMPTABLE_NAME = 'BERLIN';TMPTABLE_NAME = 'BERLIN';

APPEND ROW TO TMPTABLE;APPEND ROW TO TMPTABLE;

TMPTABLE_COUNTRY = 'TURKEY';TMPTABLE_COUNTRY = 'TURKEY';

TMPTABLE_NAME = 'IZMIR';TMPTABLE_NAME = 'IZMIR';

/* to sort same level items *//* to sort same level items */

SORT TMPTABLE ON NAME;SORT TMPTABLE ON NAME;

SORT TMPTABLE HIERARCHICAL IDCOLUMN 'NAME' PARENTIDCOLUMN 'COUNTRY';SORT TMPTABLE HIERARCHICAL IDCOLUMN 'NAME' PARENTIDCOLUMN 'COUNTRY';

/* this command will be discussed later *//* this command will be discussed later */

SET TMPTABLE TO TABLE TMPTABLE;SET TMPTABLE TO TABLE TMPTABLE;

Hiyerarşik sıralama, table control'ün ağaç temsili olan tree table'lar için çok daha kullanışlıdır. Tree table'lar sonraki bölümlerde detaylı olarak tartışılacaktır, ancak şimdilik hiyerarşik sıralama seçeneği hakkında bilgi sahibi olmalıyız, çünkü bu, her tür table için gelişmiş bir sıralama seçeneğidir.Hierarchical sorting is much more useful fo tree tables which is a tree representation of table control. Tree tables will be discussed detailly in next sections, but for now we must know about hierarchical sorting option, because it is an advanced sorting option for all kind of tables.

Herhangi bir tür sıralama operation'ı için, tüm row'ları sort operation'ından önceki konumlarına geri taşımanın bir yolu yoktur. Çünkü TROIA interpreter, herhangi bir variable type'ı için variable'ın değer geçmişini takip etmez.For any kind of sorting operation, there is no way to relocate all rows to their positions before sort operation. Because TROIA interpreter does not track variable’s value history for any type of variable.

Table'larda ÇalışmaWorking on Tables

Row SilmeRemoving Rows

Bir table variable'dan row silmek için CLEAR command'ı kullanılır. Clear command'ın tüm row'ları veya active row'u temizlemek için farklı varyasyonları vardır. CLEAR command'ının farklı varyasyonları vardır ancak çoğunlukla table için kullanılır. İşte row silmeyle ilgili syntax:To remove rows from a table variable, CLEAR command is used. Clear command has different variations to clear all rows or active row. CLEAR command has different variations but mostly used for table. Here is the syntax which is related with removing rows:

CLEAR ROW | ALL {table};CLEAR ROW | ALL {table};

CLEAR command'ının ROW varyasyonu, active row cursor'ını değiştirmeden active row'u kaldırır, bu yüzden command'dan sonra active row aynı index'teki yeni row'dur. Kaldırılan row, çok row'lu bir table'ın son row'uysa, yeni active row yeni son row'dur. İşte CLEAR ROW'dan önce ve sonra row numarasını ve active row'u yazdıran örnek kod, lütfen farklı varyasyonları test edin ve sonuçları karşılaştırın. Clear row'dan sonra başka row kalmazsa active row, geçersiz bir active row index'i olan 0'a ayarlanır.ROW variation of CLEAR command removes the active row without changing the active row cursor, so after the command active row is the new row on same index. If removed row is the last row of a multi row table, new active row is the new last row. Here is the sample code that prints row number and active row before and after the CLEAR ROW, please test different variatins and compare the results. It there is no more rows after clear row active row is set to 0 which is an invalid active row index.

OBJECT:OBJECT:

TABLE T1, TABLE T1,

STRING STRINGVAR3; STRING STRINGVAR3;

SELECT USERNAME, PASSWSELECT USERNAME, PASSW

FROM IASUSERS WHERE USERNAME LIKE 'L%' FROM IASUSERS WHERE USERNAME LIKE 'L%'

INTO T1; INTO T1;

STRINGVAR3 = 'Before: ' + T1_ROWCOUNT + TOCHAR(10);STRINGVAR3 = 'Before: ' + T1_ROWCOUNT + TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'ActiveRow: ' + T1_ACTIVEROW + TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'ActiveRow: ' + T1_ACTIVEROW + TOCHAR(10);

CLEAR ROW T1;CLEAR ROW T1;

STRINGVAR3 = STRINGVAR3 + 'After: ' + T1_ROWCOUNT + TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'After: ' + T1_ROWCOUNT + TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'ActiveRow: ' + T1_ACTIVEROW + TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'ActiveRow: ' + T1_ACTIVEROW + TOCHAR(10);

ALL varyasyonuyla, table'dan tüm row'ları kaldırmak mümkündür. Tüm row'lar temizlendikten sonra active row 0'a ayarlanır.With ALL variation, it is possible to remove all rows from table. After clearing all rows active row is set to 0.

OBJECT:OBJECT:

TABLE T1, TABLE T1,

STRING STRINGVAR3; STRING STRINGVAR3;

SELECT USERNAME, PASSWSELECT USERNAME, PASSW

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

STRINGVAR3 = 'Before: ' + T1_ROWCOUNT + TOCHAR(10);STRINGVAR3 = 'Before: ' + T1_ROWCOUNT + TOCHAR(10);

CLEAR ALL T1;CLEAR ALL T1;

STRINGVAR3 = STRINGVAR3 + 'After: ' + T1_ROWCOUNT + TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'After: ' + T1_ROWCOUNT + TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'ActiveRow: ' + T1_ACTIVEROW + TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'ActiveRow: ' + T1_ACTIVEROW + TOCHAR(10);

Başka bir command olan CLEARTABLE, programcıların loop yapmadan verilen parametrelerle row'ları bulmasına ve kaldırmasına olanak tanır. Command, LOOP command'ı gibi WHERE condition ve CRITERIA COLUMNS varyasyonlarını destekler. Hash index varyasyonu CLEARTABLE command'ında desteklenmez, çünkü row'ları kaldırmak hash bilgisini yok eder. İşte iki varyasyonun syntax'ı ve örneği.Another command; CLEARTABLE allows programmers to find rows with given parameters and remove without looping. Command supports WHERE condition and CRITERIA COLUMNS variations like LOOP command. Hash index variation is not supported CLEARTABLE command, because removing rows destroys hash information. Here is the syntax and example of two variations.

CLEARTABLE {table} WHERE {condition};CLEARTABLE {table} WHERE {condition};

CLEARTABLE {table} CRITERIA COLUMNS {columns}CLEARTABLE {table} CRITERIA COLUMNS {columns}

VALUES {values} [NOTCASESENSITIVE]; VALUES {values} [NOTCASESENSITIVE];

SELECT USERNAME, CREATEDBYSELECT USERNAME, CREATEDBY

FROM IASUSERS FROM IASUSERS

WHERE CREATEDBY LIKE 'B%' WHERE CREATEDBY LIKE 'B%'

ORDERBY CREATEDBY ORDERBY CREATEDBY

INTO TMPTABLE; INTO TMPTABLE;

CLEARTABLE TMPTABLE WHERE TMPTABLE_CREATEDBY == 'BTAN';CLEARTABLE TMPTABLE WHERE TMPTABLE_CREATEDBY == 'BTAN';

/* or *//* or */

CLEARTABLE TMPTABLE CRITERIA COLUMNS CREATEDBY VALUES 'BTAN';CLEARTABLE TMPTABLE CRITERIA COLUMNS CREATEDBY VALUES 'BTAN';

SET TMPTABLE TO TABLE TMPTABLE;SET TMPTABLE TO TABLE TMPTABLE;

CLEARTABLE command'ı ayrıca LOOP Command'ı gibi CRITERIA COLUMNS condition'ında row tabanlı flag'ler kullanmayı da destekler.CLEARTABLE command is also supports using row based flags on CRITERIA COLUMNS condition like LOOP Command.

Column SilmeRemoving Columns

Bazı durumlarda programcıların tüm column'ları ve data'yı kaldırıp table'ı APPEND command'larını kullanarak yeniden oluşturması gerekebilir (Bir column'u kaldırmak, her row'un ilgili cell'ini de kaldırmak anlamına gelir, bu yüzden tüm column'ları kaldırmak tüm data'yı da kaldırır). Tüm column'ları kaldırmak için DESTROYTABLE command'ı kullanılır ve DESTROYTABLE command'ından sonra table, bir variable tanımlama command'ı (OBJECT, LOCAL ..) tarafından yeni oluşturulmuş bir table ile aynı duruma geçer, işte DESTROYTABLE command'ının syntax'ı:In some cases programmers may need remove all columns and data and reconstruct table using APPEND commands (Removing a column also means removing corresponding cell of each row, so removing all columns also removes whole data). To remove all columns DESTROYTABLE command is used and after the DESTROYTABLE command table goes to same state with a table that is newly created by a variable definition command (OBJECT, LOCAL ..), here is the syntax of DESTROYTABLE command:

DESTROYTABLE {table};DESTROYTABLE {table};

Bir table variable'dan tek bir column'u kaldırmak için REMOVECOLUMN kullanılır. İşte command'ın syntax'ı:To remove a single column from a table variable, REMOVECOLUMN is used. Here is the syntax of the command:

REMOVE COLUMN {columnname} [PERMANENT] FROM {table};REMOVE COLUMN {columnname} [PERMANENT] FROM {table};

{columnname} parametresi bir variable değildir, başka bir deyişle column'un ismi olarak kabul edilir. İsmi bir variable'da olan bir column'u kaldırmak isterseniz, variable isminden önce @ önekini kullanın. Default olarak REMOVECOLUMN command'ı column'u kaldırmaz, yalnızca removed flag'ini true'ya ayarlar. Bir column'un removed flag'i true'ya ayarlanmışsa, sistem database query'leri hazırlarken bu column'daki cell'leri yok sayar. Bu davranış, database select'lerinden sonra eklenen ve database'de var olmayan ekstra column'larla çalışmak için kullanışlıdır. Bir column'u kalıcı olarak kaldırmak için PERMANENT varyasyonunu kullanmalısınız. Bu varyasyon, column'u ve tüm row'lardaki ilgili cell'leri geri döndürülemez bir şekilde kaldırır.{columnname} parameter is not a variable, in other words is considered as name of the column. If you want to remove a column whose name is in a variable use @ prefix, before the variable name. As default REMOVECOLUMN command does not remove column, just sets removed flag to true. If removed flag of a column is set to true, system ignores cells on this column while preparing database queries.This behaviour is useful to work on extra columns which is appended after database selects and does not exists in database. To remove a column permanently, you must use PERMANENT variation. This variation removes column and related cells on all rows in an unreturnable manner.

OBJECT:OBJECT:

TABLE TMPTABLE; TABLE TMPTABLE;

SELECT CLIENT, USERNAME, CREATEDBY, CREATEDATSELECT CLIENT, USERNAME, CREATEDBY, CREATEDAT

FROM IASUSERS FROM IASUSERS

WHERE USERNAME LIKE 'B%' WHERE USERNAME LIKE 'B%'

INTO TMPTABLE; INTO TMPTABLE;

REMOVE COLUMN CREATEDBY FROM TMPTABLE;REMOVE COLUMN CREATEDBY FROM TMPTABLE;

REMOVE COLUMN CREATEDAT PERMANENT FROM TMPTABLE;REMOVE COLUMN CREATEDAT PERMANENT FROM TMPTABLE;

SET TMPTABLE TO TABLE TMPTABLE;SET TMPTABLE TO TABLE TMPTABLE;

Bu örnekte, CREATEDAT column'u kalıcı olarak kaldırıldığı için bu column'u ekranda görmeyeceksiniz, ancak CREATEDBY hâlâ görünürdür çünkü yalnızca db query'lerine bu column'u eklemekten kaçınmak için removed olarak işaretlenmiştir (sonraki bölümlerde tartışılacaktır).In this example, CREATEAT at column is removed permanently so you will not see this column on the screen, but CREATEDBY button is still visible because its just signed as removed to avoid adding this column to db queries (will be discussed in next sections).

Table Yapısını OkumaReading Table Structure

Bazı durumlarda, programcıların table & column'ları hakkında metadata'ya ihtiyacı olabilir. COPY STRUCTURE command'ı, bir table variable'ının yapısını okumak için kullanılır. İşte SELECT command'ı tarafından tanımlanan table yapısını yazdıran örnek kod:In some cases, programmers may need metadata about table & it’s columns. COPY STRUCTURE command is used to read structure of a table variable. Here is the sample code that prints table structure which is defined by SELECT command:

OBJECT:OBJECT:

TABLE T1; TABLE T1;

SELECT USERNAME, PASSWSELECT USERNAME, PASSW

FROM IASUSERS FROM IASUSERS

INTO T1; INTO T1;

DESTROYTABLE TMPTABLE;DESTROYTABLE TMPTABLE;

COPY STRUCTURE T1 INTO TMPTABLE;COPY STRUCTURE T1 INTO TMPTABLE;

SET TMPTABLE TO TABLE TMPTABLE;SET TMPTABLE TO TABLE TMPTABLE;

COPY STRUCTURE command'ı, hedef table'a COLNAME (column ismi), COLTYPE (column type'ı), COLLEN (column uzunluğu), COLPRE (column precision'ı), COLNOT olmak üzere beş column ekler. COLNOT deprecated/kullanılmayan bir field'dır.COPY STRUCTURE command, adds five column to destiation table named COLNAME (column name), COLTYPE (column type), COLLEN (column length), COLPRE (column presicion), COLNOT. COLNOT is a deprecated/unused field.

Bazı Kullanışlı Function'larSome Useful Functions

Daha önce belirtildiği gibi SELECTED flag'i, kullanıcının user interface'te bir row seçip seçmediğini gösterir. Seçilen row sayısını almak için, programcılar table'da loop yapıp seçilen row'ları saymalıdır. Bu tür gereksiz loop'lardan kurtulmak için, table'ın seçilen row sayısını döndüren bir SELECTEDROWCOUNT() system function'ı vardır. Başka bir kullanışlı function, verilen table'ın column sayısını okumak için GETCOLUMNCOUNT()'tur. İşte iki function için bir örnek:As mentioned before SELECTED flag shows whether user selected a row on user interface. To get selected row count, programmers must loop on table and count selected rows. To get rid of this kind of useless loops, there is an SELECTEDROWCOUNT() system function that returns selected row count of table. Another useful function is GETCOLUMNCOUNT() for reading column count of given table. Here is an example for two functions:

OBJECT:OBJECT:

TABLE TMPTABLE, TABLE TMPTABLE,

STRING STRINGVAR3; STRING STRINGVAR3;

SELECT USERNAME, PASSW, CREATEDBYSELECT USERNAME, PASSW, CREATEDBY

FROM IASUSERS FROM IASUSERS

WHERE USERNAME LIKE 'B%' WHERE USERNAME LIKE 'B%'

INTO TMPTABLE; INTO TMPTABLE;

LOOP AT TMPTABLELOOP AT TMPTABLE

BEGINBEGIN

IF TMPTABLE_ACTIVEROW % 2 == 0 THEN IF TMPTABLE_ACTIVEROW % 2 == 0 THEN

TMPTABLE_SELECTED = 1; TMPTABLE_SELECTED = 1;

ENDIF; ENDIF;

ENDLOOP;ENDLOOP;

STRINGVAR3 = 'Selected Row Count:' + SELECTEDROWCOUNT(TMPTABLE) + TOCHAR(10);STRINGVAR3 = 'Selected Row Count:' + SELECTEDROWCOUNT(TMPTABLE) + TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'Column Count:' + GETCOLUMNCOUNT(TMPTABLE);STRINGVAR3 = STRINGVAR3 + 'Column Count:' + GETCOLUMNCOUNT(TMPTABLE);

Table'lar Arasında Data AktarımıData Transfer Between Tables

Table'ları KopyalamaCopying Tables

Bir table'ın tüm yapısını ve data'sını kopyalamak için COPY TABLE command'ı kullanılır. COPY TABLE command'ı, default olarak row flag'lerini aktarmaz. Table flag'lerini aktarmak için bir WITHFLAGS varyasyonu vardır. İşte syntax:To copy whole structure and data of a table COPY TABLE command is used. COPY TABLE command does not transfer row flags, as default. To transfer table flags there is a WITHFLAGS variation. Here is the syntax:

COPY TABLE {sourcetable} INTO {destinationtable} [WITHFLAGS];COPY TABLE {sourcetable} INTO {destinationtable} [WITHFLAGS];

Ve bir source table'ı destination table'a aktaran bir örnek. Lütfen örnek kodu "DEVT11 - Runcode Test Transaction" üzerinde çalıştırın ve farklı data varyasyonlarını ve row flag aktarımını test edin.And an example that transfers a source table to destination table. Please run sample code on “DEVT11 - Runcode Test Transaction” and test different data variations and row flags transfer.

OBJECT:OBJECT:

TABLE SOURCE,TABLE SOURCE,

TABLE TMPTABLE,TABLE TMPTABLE,

STRING STRINGVAR3;STRING STRINGVAR3;

/* prepare source table & flags *//* prepare source table & flags */

SELECT CLIENT,USERNAME,CREATEDBY, CREATEDATSELECT CLIENT,USERNAME,CREATEDBY, CREATEDAT

FROM IASUSERS FROM IASUSERS

WHERE USERNAME LIKE 'BTAN%' WHERE USERNAME LIKE 'BTAN%'

INTO SOURCE; INTO SOURCE;

SOURCE_UPDATED = 1;SOURCE_UPDATED = 1;

SOURCE_READ = 1;SOURCE_READ = 1;

SOURCE_DELETED = 1;SOURCE_DELETED = 1;

SOURCE_HIDE = 1;SOURCE_HIDE = 1;

COPY TABLE SOURCE INTO TMPTABLE;COPY TABLE SOURCE INTO TMPTABLE;

STRINGVAR3 = 'UPDATED:' + TMPTABLE_UPDATED + TOCHAR(10);STRINGVAR3 = 'UPDATED:' + TMPTABLE_UPDATED + TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'READ:' + TMPTABLE_READ+ TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'READ:' + TMPTABLE_READ+ TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'DELETED:' + TMPTABLE_DELETED+ TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'DELETED:' + TMPTABLE_DELETED+ TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'HIDE:' + TMPTABLE_HIDE+ TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'HIDE:' + TMPTABLE_HIDE+ TOCHAR(10);

WITHFLAGS varyasyonu ayrıca her row için CHECKED, DELETED, INSERTED, CHANGE, READ, UPDATED, ROWTOOLTIP (FYI), SUMMARYROW flag'lerini aktarır; HIDE, SELECTED gibi diğer flag'ler WITHFLAGS varyasyonunda bile aktarılmaz. İşte örnek kod, lütfen STRINGVAR3 üzerindeki aktarılan flag değerlerine odaklanın:WITHFLAGS variation also transfers CHECKED, DELETED, INSERTED, CHANGE, READ, UPDATED, ROWTOOLTIP (FYI), SUMMARYROW flags for each row, other flags such as HIDE, SELECTED are not transferred even on WITHFLAGS variation. Here is the sample code, please focus on transferred flag values on STRINGVAR3:

OBJECT:OBJECT:

TABLE SOURCE, TABLE SOURCE,

TABLE TMPTABLE, TABLE TMPTABLE,

STRING STRINGVAR3; STRING STRINGVAR3;

/* prepare source table & flags *//* prepare source table & flags */

SELECT CLIENT,USERNAME,CREATEDBY, CREATEDATSELECT CLIENT,USERNAME,CREATEDBY, CREATEDAT

FROM IASUSERS FROM IASUSERS

WHERE USERNAME LIKE 'BTAN%' WHERE USERNAME LIKE 'BTAN%'

INTO SOURCE; INTO SOURCE;

SOURCE_UPDATED = 1;SOURCE_UPDATED = 1;

SOURCE_READ = 1;SOURCE_READ = 1;

SOURCE_DELETED = 1;SOURCE_DELETED = 1;

SOURCE_HIDE = 1;SOURCE_HIDE = 1;

SELECT CLIENT,USERNAME,CREATEDBY, PWDVALIDITYSELECT CLIENT,USERNAME,CREATEDBY, PWDVALIDITY

FROM IASUSERS FROM IASUSERS

WHERE 1=2 WHERE 1=2

INTO TMPTABLE; INTO TMPTABLE;

COPY TABLE SOURCE INTO TMPTABLE WITHFLAGS;COPY TABLE SOURCE INTO TMPTABLE WITHFLAGS;

STRINGVAR3 = 'UPDATED:' + TMPTABLE_UPDATED + TOCHAR(10);STRINGVAR3 = 'UPDATED:' + TMPTABLE_UPDATED + TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'READ:' + TMPTABLE_READ+ TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'READ:' + TMPTABLE_READ+ TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'DELETED:' + TMPTABLE_DELETED+ TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'DELETED:' + TMPTABLE_DELETED+ TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'HIDE:' + TMPTABLE_HIDE+ TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'HIDE:' + TMPTABLE_HIDE+ TOCHAR(10);

Cell/Row Data'sı KopyalamaCopying Cell/Row Data

Bir row'u başka bir table'a kopyalamak, tüm table'ı kopyalamaktan biraz daha karmaşıktır. Çünkü bir row'u doğrudan kopyalamak için table yapılarının aynı olması gerekir, aksi halde yalnızca karşılık gelen cell'ler aktarılabilir. Örneğin, source table'ın COL1, COL2 olmak üzere iki column'u varsa ve destination table'ın yalnızca COL1 column'u varsa, yalnızca COL1 destination table'a aktarılabilir. Aslında, aşağıdaki gibi assignment veya MOVE command'ıyla bir row'u kopyalamak mümkündür:Copying a row to another table is a little bit complicated than copying whole table. Because table structures must be identical to copy a row directly, otherwise only corresponding cells can be transferred. For example, if source table has two columns COL1, COL2 and destination table has only one column COL1, only COL1 can be transferred to destination table. Actually, copying a row with assignment or MOVE command is possible like below:

OBJECT:OBJECT:

TABLE SOURCE, TABLE SOURCE,

TABLE TMPTABLE; TABLE TMPTABLE;

/* source table with 4 columns *//* source table with 4 columns */

SELECT CLIENT,USERNAME,CREATEDBY, CREATEDATSELECT CLIENT,USERNAME,CREATEDBY, CREATEDAT

FROM IASUSERS FROM IASUSERS

WHERE USERNAME LIKE 'BTAN%' WHERE USERNAME LIKE 'BTAN%'

INTO SOURCE; INTO SOURCE;

/* destination table with 4 columns, 3 corresponding*//* destination table with 4 columns, 3 corresponding*/

SELECT CLIENT,USERNAME,CREATEDBY, PWDVALIDITYSELECT CLIENT,USERNAME,CREATEDBY, PWDVALIDITY

FROM IASUSERS FROM IASUSERS

WHERE 1=2 WHERE 1=2

INTO TMPTABLE; INTO TMPTABLE;

APPEND ROW TO TMPTABLE;APPEND ROW TO TMPTABLE;

/* move each column *//* move each column */

TMPTABLE_CLIENT = SOURCE_CLIENT;TMPTABLE_CLIENT = SOURCE_CLIENT;

TMPTABLE_USERNAME = SOURCE_USERNAME;TMPTABLE_USERNAME = SOURCE_USERNAME;

TMPTABLE_CREATEDBY = SOURCE_CREATEDBY;TMPTABLE_CREATEDBY = SOURCE_CREATEDBY;

Ancak source ve destination table arasında çok fazla karşılık gelen column varsa, her column'u manuel olarak atamak çok zorlaşır. TROIA, source ve destination table'ın active row'ları arasında tüm karşılık gelen column değerlerini aktarmak için MOVE-CORRESPONDING adlı bir command'a sahiptir. İşte MOVE-CORRESPONDING command'ının syntax'ı ve tek bir row'u aktaran bir örnek:But if there are too many corresponding columns between source and destination table, it becomes very hard to assign each column manually. TROIA has command named MOVE-CORRESPONDING to transfer all corresponding column values between active rows of source and destination table. Here is the syntax of MOVE-CORRESPONDING command and a sample that transfers a single row:

MOVE-CORRESPONDING {sourcetable} TO {destinationtable} [WITHFLAGS];MOVE-CORRESPONDING {sourcetable} TO {destinationtable} [WITHFLAGS];

OBJECT:OBJECT:

TABLE SOURCE, TABLE SOURCE,

TABLE TMPTABLE; TABLE TMPTABLE;

/* source table with 3 columns *//* source table with 3 columns */

SELECT CLIENT,USERNAME,CREATEDBY, CREATEDATSELECT CLIENT,USERNAME,CREATEDBY, CREATEDAT

FROM IASUSERS FROM IASUSERS

WHERE USERNAME LIKE 'BTAN%' WHERE USERNAME LIKE 'BTAN%'

INTO SOURCE; INTO SOURCE;

/* destination table with 5 columns*//* destination table with 5 columns*/

SELECT CLIENT,USERNAME,CREATEDBY, PWDVALIDITYSELECT CLIENT,USERNAME,CREATEDBY, PWDVALIDITY

FROM IASUSERS FROM IASUSERS

WHERE 1=2 WHERE 1=2

INTO TMPTABLE; INTO TMPTABLE;

APPEND ROW TO TMPTABLE;APPEND ROW TO TMPTABLE;

/* move all corresponding columns *//* move all corresponding columns */

MOVE-CORRESPONDING SOURCE TO TMPTABLE;MOVE-CORRESPONDING SOURCE TO TMPTABLE;

Ayrıca tüm row tabanlı flag'ler hem source hem de destination row'larda mevcuttur, bu yüzden bir row'u destination table'a aktarırken flag değerleri de göz önünde bulundurulmalıdır. Default olarak, MOVE-CORRESPONDING command'ı flag değerlerini aktarmaz; row flag'lerini de aktarmanız gerekiyorsa COPY TABLE command'ı gibi WITHFLAGS varyasyonunu kullanmalısınız. Lütfen aşağıdaki örnek kodu farklı flag değerleriyle ve WITHFLAGS keyword'ü ile/olmadan çalıştırın:Additionally all row based flags exist both on source and destination rows so when transferring a row to destionation table, also flag values must be considered. As default, MOVE-CORRESPONDIG command does not transfer flag values, if you need to transfer also row flags you must use WITHFLAGS variation like COPY TABLE command. Please run sample code below, with different flag values, and with/withoud WITHFLAGS keyword:

OBJECT:OBJECT:

TABLE SOURCE, TABLE SOURCE,

TABLE TMPTABLE TABLE TMPTABLE

STRING STRINGVAR3; STRING STRINGVAR3;

/* prepare source table & flags *//* prepare source table & flags */

SELECT CLIENT,USERNAME,CREATEDBY, CREATEDATSELECT CLIENT,USERNAME,CREATEDBY, CREATEDAT

FROM IASUSERS FROM IASUSERS

WHERE USERNAME LIKE 'BTAN%' WHERE USERNAME LIKE 'BTAN%'

INTO SOURCE; INTO SOURCE;

SOURCE_UPDATED = 1;SOURCE_UPDATED = 1;

SOURCE_READ = 1;SOURCE_READ = 1;

SOURCE_DELETED = 1;SOURCE_DELETED = 1;

SELECT CLIENT,USERNAME,CREATEDBY, PWDVALIDITYSELECT CLIENT,USERNAME,CREATEDBY, PWDVALIDITY

FROM IASUSERS FROM IASUSERS

WHERE 1=2 WHERE 1=2

INTO TMPTABLE; INTO TMPTABLE;

APPEND ROW TO TMPTABLE;APPEND ROW TO TMPTABLE;

/* move all corresponding columns *//* move all corresponding columns */

MOVE-CORRESPONDING SOURCE TO TMPTABLE WITHFLAGS;MOVE-CORRESPONDING SOURCE TO TMPTABLE WITHFLAGS;

STRINGVAR3 = 'UPDATED:' + TMPTABLE_UPDATED + TOCHAR(10);STRINGVAR3 = 'UPDATED:' + TMPTABLE_UPDATED + TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'READ:' + TMPTABLE_READ+ TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'READ:' + TMPTABLE_READ+ TOCHAR(10);

STRINGVAR3 = STRINGVAR3 + 'DELETED:' + TMPTABLE_DELETED+ TOCHAR(10);STRINGVAR3 = STRINGVAR3 + 'DELETED:' + TMPTABLE_DELETED+ TOCHAR(10);

MOVE-CORRESPONDING command'ı, CREATEDBY, CREATEDAT, CHANGEDBY, CHANGEDAT gibi default column'lar dahil tüm karşılık gelen column değerlerini doğrudan aktarır. Ancak source table, database configuration'da (ODBA) bir check table ise, default column'lar aktarılmaz. Default column'lar ve ODBA, sonraki bölümlerde detaylı olarak tartışılacaktır.MOVE-CORRESPONDING command directly transfers all corresponding column values even default columns such as CREATEDBY, CREATEDAT, CHANGEDBY, CHANGEDAT. But if source table is a check table on database configuration (ODBA). Default columns are not transferred. Default columns and ODBA will be discussed detailly in next sections.

Genellikle, MOVE-CORRESPONDING command'ı bir LOOP statement'ı içinde kullanılır ve source table'daki her row için, destination table'a yeni bir row eklenir veya row'lar bir conditional statement'a bağlı olarak source table'a aktarılır. Bu tür durumları kolaylaştırmak için, verilen condition'a bağlı olarak source table'ın row'larını aktaran MERGETABLE command'ı kullanılır. MERGETABLE command'ı, LOOP statement'ları gibi ek bir hash index varyasyonuna sahip CLEARTABLE command'ına benzer bir command'dır. İşte MERGETABLE command'ının üç varyasyonunun syntax'ları:Usually, MOVE-CORRESPONDING command is used in a LOOP statement and for each row in source table, a new row inserted to destination table or rows transferred to source table due to a conditional statement. To ease such cases MERGETABLE command is used, which transfers rows of source table due to given condition. MERGETABLE command is a similar command to CLEARTABLE command with an additional hash index variation like LOOP staments. Here is the syntaxes of three variation of MERGETABLE command:

MERGETABLE {source} INTO {destination} [WITHFLAGS] WHERE {condition};MERGETABLE {source} INTO {destination} [WITHFLAGS] WHERE {condition};

MERGETABLE {source} INTO {destination} [WITHFLAGS]MERGETABLE {source} INTO {destination} [WITHFLAGS]

CRITERIA COLUMNS {cols} VALUES {vals} [NOTCASESENSITIVE]; CRITERIA COLUMNS {cols} VALUES {vals} [NOTCASESENSITIVE];

MERGETABLE {source} INTO {destination} [WITHFLAGS]MERGETABLE {source} INTO {destination} [WITHFLAGS]

CRITERIA INDEXED {index} VALUES {vals}; CRITERIA INDEXED {index} VALUES {vals};

MERGETABLE'ın ayrıca davranışı COPY TABLE'ın WITHFLAGS varyasyonuyla aynı olan opsiyonel bir WITHFLAGS varyasyonu vardır. İşte üç varyasyonun tümünü kullanan bir örnek. Lütfen row flag değerlerini aktarmak için source kodu değiştirin ve çalıştırın.MERGETABLE has also optional WITHFLAGS variation whose behaviour is same with COPY TABLE’s WITHFLAGS variation. Here is an example that uses all three variation. Please modify and run source code to transfer row flag values.

SELECT 1 AS ORD, USERNAME, 'sv' AS PASSW, CREATEDBYSELECT 1 AS ORD, USERNAME, 'sv' AS PASSW, CREATEDBY

FROM IASUSERS FROM IASUSERS

WHERE CREATEDBY = 'BTAN' WHERE CREATEDBY = 'BTAN'

ORDERBY USERNAME ORDERBY USERNAME

INTO SOURCE; INTO SOURCE;

SELECT 1 AS ORD, USERNAME, 'dv' AS PASSW, CREATEDBYSELECT 1 AS ORD, USERNAME, 'dv' AS PASSW, CREATEDBY

FROM IASUSERS FROM IASUSERS

WHERE 1 = 2 WHERE 1 = 2

INTO TMPTABLE; INTO TMPTABLE;

LOOP AT SOURCELOOP AT SOURCE

BEGINBEGIN

IF SOURCETABLE_ACTIVEROW % 2 == 0 THEN IF SOURCETABLE_ACTIVEROW % 2 == 0 THEN

SOURCETABLE_INSERTED = 1; SOURCETABLE_INSERTED = 1;

ENDIF; ENDIF;

SOURCETABLE_ORD = SOURCETABLE_ACTIVEROW; SOURCETABLE_ORD = SOURCETABLE_ACTIVEROW;

ENDLOOP;ENDLOOP;

BUILDHASHINDEX 'INDX' COLUMNS PASSW, INSERTED ON SOURCE FORCE;BUILDHASHINDEX 'INDX' COLUMNS PASSW, INSERTED ON SOURCE FORCE;

MERGETABLE SOURCE INTO TMPTABLE WITHFLAGS WHERE SOURCETABLE_INSERTED == 1;MERGETABLE SOURCE INTO TMPTABLE WITHFLAGS WHERE SOURCETABLE_INSERTED == 1;

APPEND ROW TO TMPTABLE; /* as separator */APPEND ROW TO TMPTABLE; /* as separator */

MERGETABLE SOURCE INTO TMPTABLE CRITERIA COLUMNS PASSW,INSERTED VALUES 'sv',1;MERGETABLE SOURCE INTO TMPTABLE CRITERIA COLUMNS PASSW,INSERTED VALUES 'sv',1;

APPEND ROW TO TMPTABLE; /* as separator */APPEND ROW TO TMPTABLE; /* as separator */

MERGETABLE SOURCE INTO TMPTABLE CRITERIA INDEXED INDEX 'INDX' VALUES 'sv',0;MERGETABLE SOURCE INTO TMPTABLE CRITERIA INDEXED INDEX 'INDX' VALUES 'sv',0;

SET TMPTABLE TO TABLE TMPTABLE;SET TMPTABLE TO TABLE TMPTABLE;

Alıştırma 1: LOOP Seçeneklerini KarşılaştırmaExercise 1: Compare LOOP Options

Bir table tanımlayın ve PWDVALIDITY'si 0'dan büyük olan kullanıcılarla doldurun. Üç LOOP statement'ı yazın:Define a table and fill table with users whose PWDVALIDITY is more than 0. Write three LOOP statements :

veand

Alıştırma 2: Hash Index Kullanarak LocatingExercise 2: Locating Using Hash Index

Bir table tanımlayın ve IASUSERS table'ındaki tüm kullanıcılarla doldurun.Define a table and fill table with all users in IASUSERS table.

Alıştırma 3: Kullanıcıları Ağaç Gibi SıralamaExercise 3: Sort Users Like a Tree

Alıştırma 2 için yazdığınız kodu değiştirin.Modify code that you write for Exercise 2.

Alıştırma 4: Row'ları KopyalamaExercise 4: Copying Rows

Yeni bir table variable oluşturun ve en az bir kullanıcı oluşturmuş kullanıcıları yeni table variable'a kopyalayın. Önceki örnekte yazdığınız kodu kullanın.Create a new table variable and copy users who created at least one users to new table variable. Use the code that you write in previous example.