Firebird 2.1 What's New by Vladislav Khorsun (English)
Upcoming SlideShare
Loading in...5
×
 

Firebird 2.1 What's New by Vladislav Khorsun (English)

on

  • 4,545 views

Detailed presentation devoted to new features of Firebird 2.1 by Vladislav Khorsun, core Firebird Developer. Main features are covered, including tips and tricks and often usage scenarios.

Detailed presentation devoted to new features of Firebird 2.1 by Vladislav Khorsun, core Firebird Developer. Main features are covered, including tips and tricks and often usage scenarios.

Statistics

Views

Total Views
4,545
Views on SlideShare
4,287
Embed Views
258

Actions

Likes
1
Downloads
41
Comments
0

3 Embeds 258

http://firebird-pl.blogspot.com 176
http://www.developpez.net 72
http://www.slideshare.net 10

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • - CONNECT <br /> Database connection established <br /> A transaction is started <br /> Triggers are fired - uncaught exceptions rollback the transaction, disconnect the attachment and are returned to the client <br /> The transaction is committed <br /> - DISCONNECT <br /> A transaction is started <br /> Triggers are fired - uncaught exceptions rollback the transaction, disconnect the attachment and are swallowed <br /> The transaction is committed <br /> The attachment is disconnected <br /> - TRANSACTION START <br /> Triggers are fired in the newly user created transaction – uncaught exceptions are returned to the client and the transaction is rolled-back. <br /> - TRANSACTION COMMIT <br /> Triggers are fired in the committing transaction (before actual commit) - uncaught exceptions rollback the triggers savepoint, the commit command is aborted and the exception is returned to the client. <br /> Note: for two-phase transactions the triggers are fired in &quot;prepare&quot; and not in commit. <br /> - TRANSACTION ROLLBACK <br /> Triggers are fired in the rolling-back transaction (before actual rollback) - changes done will be rolled-back togheter with the transaction and exceptions are swallowed <br /> <br /> gfix and gstat connections does not fire database triggers
  • - CONNECT <br /> Database connection established <br /> A transaction is started <br /> Triggers are fired - uncaught exceptions rollback the transaction, disconnect the attachment and are returned to the client <br /> The transaction is committed <br /> - DISCONNECT <br /> A transaction is started <br /> Triggers are fired - uncaught exceptions rollback the transaction, disconnect the attachment and are swallowed <br /> The transaction is committed <br /> The attachment is disconnected <br /> - TRANSACTION START <br /> Triggers are fired in the newly user created transaction – uncaught exceptions are returned to the client and the transaction is rolled-back. <br /> - TRANSACTION COMMIT <br /> Triggers are fired in the committing transaction (before actual commit) - uncaught exceptions rollback the triggers savepoint, the commit command is aborted and the exception is returned to the client. <br /> Note: for two-phase transactions the triggers are fired in &quot;prepare&quot; and not in commit. <br /> - TRANSACTION ROLLBACK <br /> Triggers are fired in the rolling-back transaction (before actual rollback) - changes done will be rolled-back togheter with the transaction and exceptions are swallowed <br /> <br /> gfix and gstat connections does not fire database triggers
  • - CONNECT <br /> Database connection established <br /> A transaction is started <br /> Triggers are fired - uncaught exceptions rollback the transaction, disconnect the attachment and are returned to the client <br /> The transaction is committed <br /> - DISCONNECT <br /> A transaction is started <br /> Triggers are fired - uncaught exceptions rollback the transaction, disconnect the attachment and are swallowed <br /> The transaction is committed <br /> The attachment is disconnected <br /> - TRANSACTION START <br /> Triggers are fired in the newly user created transaction – uncaught exceptions are returned to the client and the transaction is rolled-back. <br /> - TRANSACTION COMMIT <br /> Triggers are fired in the committing transaction (before actual commit) - uncaught exceptions rollback the triggers savepoint, the commit command is aborted and the exception is returned to the client. <br /> Note: for two-phase transactions the triggers are fired in &quot;prepare&quot; and not in commit. <br /> - TRANSACTION ROLLBACK <br /> Triggers are fired in the rolling-back transaction (before actual rollback) - changes done will be rolled-back togheter with the transaction and exceptions are swallowed <br /> <br /> gfix and gstat connections does not fire database triggers
  • Intro <br /> Sometimes programmers have necessity for the data with temporary nature. For example - create a data set, work with it and remove it. If it is necessity is seldom or in general once then it is possible to create and drop the table. But what to do if such tasks arises frequently ? Constant creation and dropping of tables at first is not good from the security point of view (end users usual have no such rights), at second it is extremely not recommended to perform DDL on production database and, at third, productivity of such approach is far from perfect. Besides if the own set of temporary data are needed for several users simultaneously, they will be compelled to assign them unique names, and it means that stored procedures can&apos;t work with such tables. <br /> <br /> One of the widespread approaches to get rid of these problems is to create the permanent table with an additional service field populated with CURRENT_USER or with the private value of generator used during data sets lifetime. In spite of the fact that this approach is free from lacks of previous one it also has its own lacks. In particular because of frequent deletions many record versions will be accumulated which then should be removed from database. Since usually additional field is indexed and included in all queries to such tables the removed records are never visited again and this garbage will sit in DB until the sweep runs. <br /> <br /> Fortunately the SQL standard has the solution of such problems (yes it not always prevents quiet life of the ordinary programmer :). This solution is a various kinds of temporary tables. Today we consider global temporary tables as they were implemented in IB 7.5 first, then it was included in Fyracle and now they are in Firebird also <br /> <br /> Definition <br /> Global temporary tables (GTTs) are tables with permanent metadata, stored in the system catalogue, but with the temporary data. GTT&apos;s may be of two kinds - with the data, persistent within lifetime of connection in which the given GTT was referenced, and with the data, persistent within only during lifetime of referencing transaction. The data from different connections (transactions) are isolated from each other, but metadata of the global temporary table are shared between all connections and transactions.
  • All kinds of constraints between temporary and persistent tables follow the rule below: <br /> a) references between persistent and temporary tables are forbidden <br /> b) GTT with ON COMMIT PRESERVE ROWS can&apos;t have reference on GTT with ON COMMIT DELETE ROWS <br /> c) Domain constraints can&apos;t have reference on GTT. <br /> <br /> This is a table for easier understanding of which references are allowed
  • Implementation details: <br /> GTT instance (set of data rows created by and visible within given connection or transaction) created when it first referenced, usually at statement prepare time. Each instance has its own private set of pages on which data and indexes are stored. Data rows and indexes have the same physical storage layout as permanent tables. <br /> <br /> When connection or transaction ends all pages of an GTT instance are released immediately (this is similar as when you do DROP TABLE but metatada remains in database of course). This is much quicker than traditional row by row delete + garbage collection of deleted record versions. Each data (index) page contains rows (keys) from the same GTT instance therefore connection ransaction should readwrite less pages than if an GTT instances were isolated by the service field. Note that with “service field” design data pages will contain rows also from old dead connections or transactions until it will be garbage collected. <br /> <br /> Sometimes our design required more space than “service field” design. For example 10 instances of GTT each with one row occupied 10 data pages, while “service field” design needs only one page (if it can fit 10 rows). But this difference visible only with big amount of small tables and we assume it reasonable price for benefits (speed and near instant cleanup). <br /> <br /> In Fyracle data pages of all of the GTT’s instances placed in the database file. In Firebird 2.1 this pages placed in separate temporary file’s – this allows to put temporary data into another hard disk and reach more performance level. Each connection have its own temporary file created when this connection first referenced some GTT. Also this temporary files always opened with “Forced writes = OFF” settings despite of database setting. <br /> <br /> There are no limit on number of GTT instances. If you have N transactions active simultaneously and each transaction have referenced some GTT then you’ll have N GTT’s instances.
  • CTE is standard feature. It is supported in modern versions of DB2, ORACLE, MSSQL, ASA. In FB history it was first implemented in Fyracle by Paul Ruizendaal to support Oracles non standart syntax of recursive queries. <br /> CTE allows to write very complex queries in simple, natural manner. All you need is just decompose complex query by simple parts (as you often do with complex procedures in such programming language as C, PASCAL etc), assign names to this parts and use it in near any possible combinations. <br /> CTE is like view’s, locally defined within main query. Or we can compare it with local procedures in pascal language. From the engine POV CTE is a derived table so no intermediate materialization is performed
  • WITH can’t be nested but this is not a strict limitation as you always can reference one CTE from another
  • Here the simple example of how we can build cross-tab report about per year budget of each department using one CTE several times in the same query. Our standard “employee” database is used in this example (someone can even remember it :) <br /> <br /> We defined CTE DEPT_YEAR_BUDGET which sums per-year budget of each department. Then we join it four times with DEPARTMENT table to build our simple cross-tab. Also we exclude from report departments which have no budget at all <br /> <br /> This example shows that we can reuse same CTE several times in query
  • here the results of query above.
  • Well, CTE is a powerful mechanism to create complex, powerful query. But that’s not all. <br /> With recursive CTE we can create even recursive queries now. <br /> <br /> How it work: <br /> engine start execution from non-recursive members <br /> for each evaluated row engine start execution of each recursive member using current row values as parameters <br /> if current instance of recursive member produced no rows engine returns one step back and get next row from previous resultset <br /> <br /> Memory and CPU overhead of recursive CTE is much less than overhead of recursive stored procedures <br /> <br /> currently recursion depth is limited by hardcoded value of 1024 <br /> <br /> it will be discussed later about implement non standard optional syntax enhancement to allow user specify maximum recursion level immediately in query
  • Aggregates limitation come from standard. I have no clear explanation of it
  • This example shows how to solve several classical tasks when working with recursive data structures <br /> <br /> <br /> <br /> <br /> query returns tree-like table in order of tree walk. it is very useful if client application can’t itself show tree-like structure <br /> <br /> <br /> <br /> <br /> we see how easy nesting level can be evaluated <br /> <br /> <br /> <br /> <br /> we see how we can limit number of processed levels of tree <br /> <br /> <br /> <br /> <br /> we also return full path from the root to the current tree node – it can be used by client application as a hint to end-user
  • this example is more complex. it shows how two recursive members is used to return two recursion path <br /> very simple table PEOPLE contains ID of people, his name and ID’s of his parents <br /> query returns whole genealogical tree of given people - i.e. his parents, parents of his parents and so on <br /> also we see that parameters can be used inside of CTE also (if someone think it is allowed in main query only)
  • return to the our example of use of simple CTE and include department’s as a tree into that cross-tab report <br /> let define CTE DEPT_TREE which shows departments in tree-like style and replace in main query plain table DEPARTMENT by this recursive CTE <br /> To let our report looks as real tree I included INDENT field into our recursive CTE DEPT_TREE. More nesting level – more indentation of name
  • Easy is not is ?
  • Note - error message contains variable name and linecolumn numbers

Firebird 2.1 What's New by Vladislav Khorsun (English) Firebird 2.1 What's New by Vladislav Khorsun (English) Presentation Transcript

  • FIREBIRD 2. 1
      • What's new
    Vladyslav Khorsun hvlad @users. sourceforge .net
  • FIREBIRD 2. 1
    • BETTER ADMINISTRATION
        • Monitoring and Windows trusted authentication
    • IMPROVED PERFORMANCE
        • Less roundtrpis, faster large sorts and other...
    • SQL LANGUAGE ENHANCEMENTS
        • GTT, CTE, Database Triggers and more...
    • BUGS FIXED
        • Many bugs was fixed
    • Monitoring tables
      • Activity snapshot retained till the end of transaction
      • Works with both Super and Classic Server
      • Regular users restricted to see own attachment
      • Kill long running query
    ADMINISTRATION
  • MONITORING TABLES Databases and objects MON$DATABASE MON$DATABASE_NAME ... MON$ATTACHMENTS MON$ATTACHMENT_ID MON$ATTACHMENT_NAME ... MON$TRANSACTIONS MON$TRANSACTION_ID MON$ATTACHMENT_ID ... MON$STATEMENTS MON$STATEMENT_ID MON$ATTACHMENT_ID MON$TRANSACTION_ID ... MON$CALL_STACK MON$CALL_ID MON$STATEMENT_ID MON$CALLER_ID ...
  • MONITORING TABLES Objects and statistics MON$DATABASE ... MON$STAT_ID MON$ATTACHMENTS ... MON$STAT_ID MON$TRANSACTIONS ... MON$STAT_ID MON$STATEMENTS ... MON$STAT_ID MON$CALL_STACK ... MON$STAT_ID MON$IO_STATS MON$STAT_ID MON$STAT_GROUP ... MON$RECORD_STATS MON$STAT_ID MON$STAT_GROUP ...
    • Trusted Windows authentication
      • Used built-in Windows security
      • New SYSTEM_USER context variable (?)
      • New Authentication parameter in firebird.conf :
        • Native
        • Trusted
        • Mixed
      • New DPB tag isc_dpb_trusted_auth
      • New command line switch -trusted in utilities
    ADMINISTRATION
    • Network protocol improvements
    • Flush of large page cache
    • Huge on-disk sorts
    • External tables readwrite performance
    PERFORMANCE
    • Less roundtrips and traffic saving
      • Some type of packets are delayed
        • (require both client and server v2.1)
      • Cached statement information
        • (client v2.1 with any server version)
      • No trailing zeros in information response
        • (any client with server v2.1)
    • Full backward compatibility
    NETWORK PROTOCOL IMPROVED
  • SQL LANGUAGE
    • DATABASE TRIGGERS
        • Attachment and transaction level triggers
    • GLOBAL TEMPORARY TABLE
        • New kind of tables
    • COMMON TABLE EXPRESSIONS
    • Complex and recursive queries ? It is simple !
    • DOMAINS EVERYWHERE
    • Domains in procedures , triggers and CAST
    • INSERT OR UPDATE, MERGE
    • Insert or update ? Let Firebird decide ;)
    • A LOT OF NEW BUILT-IN FUNCTIONS
  • DATABASE TRIGGERS
    • Database-wide triggers fired on :
      • CONNECT
      • DISCONNECT
      • TRANSACTION START
      • TRANSACTION COMMIT
      • TRANSACTION ROLLBACK
    • Only SYSDBA or database owner can :
      • define database triggers
      • switch it off for new connection by :
        • new isc_dpb_no_db_triggers tag
        • new -no_dbtriggers switch in utilities
  • DATABASE TRIGGERS Example of ON CONNECT trigger isql temp.fdb -user SYSDBA -pass masterkey Database: temp .fdb, User: SYSDBA SQL> SET TERM ^ ; SQL> CREATE EXCEPTION EX_CONNECT 'Forbidden !' ^ SQL> CREATE OR ALTER TRIGGER TRG_CONN ON CONNECT CON> AS CON> BEGIN CON> IF (<bad user>) CON> THEN EXCEPTION EX_CONNECT USER || ' not allowed !'; CON> END ^ SQL> EXIT ^ isql temp.fdb -user BAD_USER -pass ... Statement failed, SQLCODE = -836 exception 217 -EX_CONNECT - BAD_USER not allowed ! -At trigger 'TRG_CONN' line: 5, col: 3 Use CONNECT or CREATE DATABASE to specify a database SQL> EXIT;
  • DATABASE TRIGGERS
      • Help ! My ON CONNECT trigger deny all users and even SYSDBA ! Nobody can log in anymore :(
      • What can i do ???
      • Don't panic :) Use -no_dbtriggers switch in utilities :
    Example of ON CONNECT trigger isql temp.fdb -user SYSDBA -pass masterkey -nodbtriggers Database: temp .fdb, User: SYSDBA SQL> ALTER TRIGGER TRG_CONN INACTIVE; SQL> EXIT;
  • GLOBAL TEMPORARY TABLES
    • Standard properties
      • Common metadata and private data
      • Indices , triggers , uniqueness check and referential integrity
      • Lifetime : attachment or transaction
      • DELETE triggers are not fired on cleanup
    • Firebird’s specific
      • No problem with garbage collection
      • Storage is in temporary files, forced writes off
      • Instant cleanup
    • Syntax
      • CREATE GLOBAL TEMPORARY TABLE
      • [ON COMMIT <DELETE | PRESERVE> ROWS]
      • ON COMMIT DELETE ROWS
      • data lifetime - transaction
      • ON COMMIT PRESERVE ROWS
      • data lifetime - attachment
      • By default - DELETE ROWS
    GLOBAL TEMPORARY TABLES
  • GLOBAL TEMPORARY TABLES Referential integrity rules   on commit delete rows  on commit preserve rows  persistent on commit delete rows on commit preserve rows persistent master detail
  • GLOBAL TEMPORARY TABLES database CREATE GLOBAL TEMPORARY TABLE T1 attachment 1 attachment 2 pages not allocated pages not allocated pages allocated ( temporary file 1, FW = OFF ) pages freed ( temporary file deleted ) INSERT INTO T1 SELECT FROM T1 pages allocated disconnect pages freed ( temporary file deleted ) INSERT INTO T1 SELECT FROM T1 pages allocated ( temporary file 2, FW = OFF ) disconnect pages not allocated Common metadata Private data
  • COMMON TABLE EXPRESSIONS
    • Syntax
      • WITH [RECURSIVE] -- new keywords
        • CTE_A -- first table expression’s name
        • [(a1, a2, …)] -- fields aliases , optional
        • AS ( SELECT … ), -- table expression’s definition
        • CTE_B -- second table expression
        • [(b1, b2, …)]
        • AS ( SELECT … ),
      • SELECT … -- main query , used both
      • FROM CTE _ A , CTE_B , -- table expressions
      • TAB1, TAB2 -- and regular tables
      • WHERE …
  • COMMON TABLE EXPRESSIONS Rules of simple ( non recursive ) table expressions
    • Several table expressions can be defined at one query
    • Any SELECT’s clause can be used in table expressions
    • Table expressions can reference each other
    • Table expressions can be used within any part of main query or another table expression
    • The same table expression can be used several times in main query
  • COMMON TABLE EXPRESSIONS Rules of simple ( non recursive ) table expressions
    • Table expressions can be used in INSERT, UPDATE and DELETE statements (as subqueries of course)
    • Table expressions can be used in procedure language also :
    • for with … select … into …
    • WITH statements can not be nested
    • References between expressions should not have a loops
  • COMMON TABLE EXPRESSIONS Example of simple ( non recursive ) table expressions WITH DEPT_YEAR_BUDGET AS ( SELECT FISCAL_YEAR, DEPT_NO, SUM(PROJECTED_BUDGET) AS BUDGET FROM PROJ_DEPT_BUDGET GROUP BY FISCAL_YEAR, DEPT_NO ) SELECT D.DEPT_NO, D.DEPARTMENT, B_1993.BUDGET AS B_1993, B_1994.BUDGET AS B_1994, B_1995.BUDGET AS B_1995, B_1996.BUDGET AS B_1996 FROM DEPARTMENT D LEFT JOIN DEPT_YEAR_BUDGET B_1993 ON D.DEPT_NO = B_1993.DEPT_NO AND B_1993.FISCAL_YEAR = 1993 LEFT JOIN DEPT_YEAR_BUDGET B_1994 ON D.DEPT_NO = B_1994.DEPT_NO AND B_1994.FISCAL_YEAR = 1994 LEFT JOIN DEPT_YEAR_BUDGET B_1995 ON D.DEPT_NO = B_1995.DEPT_NO AND B_1995.FISCAL_YEAR = 1995 LEFT JOIN DEPT_YEAR_BUDGET B_1996 ON D.DEPT_NO = B_1996.DEPT_NO AND B_1996.FISCAL_YEAR = 1996 WHERE EXISTS (SELECT * FROM PROJ_DEPT_BUDGET B WHERE D.DEPT_NO = B.DEPT_NO)
  • COMMON TABLE EXPRESSIONS Example of simple ( non recursive ) table expressions
  • COMMON TABLE EXPRESSIONS Recursive table expressions
    • WITH RECURSIVE -- mandatory keyword RECURSIVE
      • CTE_R AS ( -- recursive table expression
        • SELECT … -- non recursive query (anchor member)
    • FROM T1
        • UNION ALL -- mandatory UNION ALL
        • SELECT … -- recursive query
    • FROM CTE_R -- recursive reference
    • )
      • … -- another table expressions
      • SELECT … -- main query
    • FROM CTE_R …
    • WHERE …
  • COMMON TABLE EXPRESSIONS Recursive table expressions
    • Recursive CTE have reference to itself
    • Recursive CTE is an UNION of recursive and non-recursive members
    • At least one non-recursive member (anchor) must be present
    • Non-recursive members are placed first in UNION
    • Recursive members are separated from an anchor members and from each other with UNION ALL
  • COMMON TABLE EXPRESSIONS Recursive table expressions
    • References between CTE’s still should not have a loops
    • Aggregates (DISTINCT, GROUP BY, HAVING) and aggregate functions (SUM, COUNT, MAX etc) are not allowed in recursive members
    • Recursive member can have only one reference to itself and only in FROM clause
    • Recursive reference can not participate in outer joins
  • COMMON TABLE EXPRESSIONS WITH RECURSIVE R_TREE (ID, LEVEL, PATH) AS ( SELECT ID, 0, CAST(ID AS VARCHAR(255)) FROM TREE WHERE PARENT_ID IS NULL UNION ALL SELECT TREE.ID, R_TREE.LEVEL + 1, R_TREE.PATH || ‘.’ || CAST(TREE.ID AS VARCHAR(8)) FROM TREE, R_TREE WHERE TREE.PARENT_ID = R_TREE.ID AND R_TREE.LEVEL < 10 ) SELECT TREE.*, R_TREE.LEVEL, R_TREE.PATH FROM TREE, R_TREE WHERE TREE.ID = R_TREE.ID Examples of recursive table expressions
  • COMMON TABLE EXPRESSIONS WITH RECURSIVE FAMILY AS ( SELECT PEOPLE, FATHER, MOTHER FROM PEOPLES WHERE NAME = :CHILD UNION ALL SELECT F.PEOPLE_ID, F.FATHER, F.MOTHER FROM PEOPLES F, FAMILY WHERE F.PEOPLE_ID = FAMILY .FATHER UNION ALL SELECT M.PEOPLE_ID, M.FATHER, M.MOTHER FROM PEOPLES M, FAMILY WHERE M.PEOPLE_ID = FAMILY .MOTHER ) SELECT * FROM FAMILY CREATE TABLE PEOPLES ( PEOPLE_ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(255), FATHER INT REFERENCES PEOPLES, MOTHER INT REFERENCES PEOPLES ) Examples of recursive table expressions
  • COMMON TABLE EXPRESSIONS WITH RECURSIVE DEPT_YEAR_BUDGET AS ( SELECT FISCAL_YEAR, DEPT_NO, SUM(PROJECTED_BUDGET) AS BUDGET FROM PROJ_DEPT_BUDGET GROUP BY FISCAL_YEAR, DEPT_NO ), DEPT_TREE AS ( SELECT DEPT_NO, HEAD_DEPT, DEPARTMENT, CAST('' AS VARCHAR(255)) AS INDENT FROM DEPARTMENT WHERE HEAD_DEPT IS NULL UNION ALL SELECT D.DEPT_NO, D.HEAD_DEPT, D.DEPARTMENT, H.INDENT || ' ' FROM DEPARTMENT D JOIN DEPT_TREE H ON D.HEAD_DEPT = H.DEPT_NO ) Examples of recursive table expressions SELECT D.DEPT_NO, D.INDENT || D.DEPARTMENT AS DEPARTMENT, B_1993.BUDGET AS B_1993, B_1994.BUDGET AS B_1994, B_1995.BUDGET AS B_1995, B_1996.BUDGET AS B_1996 FROM DEPT_TREE D LEFT JOIN DEPT_YEAR_BUDGET B_1993 ON D.DEPT_NO = B_1993.DEPT_NO AND B_1993.FISCAL_YEAR = 1993 LEFT JOIN DEPT_YEAR_BUDGET B_1994 ON D.DEPT_NO = B_1994.DEPT_NO AND B_1994.FISCAL_YEAR = 1994 LEFT JOIN DEPT_YEAR_BUDGET B_1995 ON D.DEPT_NO = B_1995.DEPT_NO AND B_1995.FISCAL_YEAR = 1995 LEFT JOIN DEPT_YEAR_BUDGET B_1996 ON D.DEPT_NO = B_1996.DEPT_NO AND B_1996.FISCAL_YEAR = 1996
  • COMMON TABLE EXPRESSIONS Examples of recursive table expressions
  • DOMAINS EVERYWHERE
    • Syntax
      • data_type ::= <builtin_data_type>
      • | <domain_name>
      • | TYPE OF <domain_name>
    • Usage
      • Domains in input and output parameters
        • CREATE PROCEDURE MY_PROC(IN_PARAM [ TYPE OF ] DOMAIN_A)
          • RETURNS (OUT_PARAM [ TYPE OF ] DOMAIN_B)
      • Domains in variable declaration
        • DECLARE VARIABLE VAR1 [ TYPE OF ] DOMAIN_A
      • Domains in CAST statement
        • OUT_PARAM = CAST(VAR1 AS [ TYPE OF ] DOMAIN_B)
  • DOMAINS EVERYWHERE
    • Using plain <domain_name> data type inherits domain constraints (CHECK, NOT NULL) and default value
    • Using new keyword TYPE OF only data type from domain definition is inherited.
    • Engine tracked dependency between domain and stored procedure or trigger where its used and not allows to drop such domains
    • When domain altered engine don’t recompile dependent objects
    • Dependent objects will take up new domain definition only after reload into metadata cache
  • DOMAINS EVERYWHERE SQL> SET TERM ^ ; SQL> SQL> CREATE DOMAIN COLOUR VARCHAR(8) CON> DEFAULT 'RED' CON> CHECK (VALUE IN ('RED', 'GREEN', 'BLUE'))^ SQL> SQL> EXECUTE BLOCK CON> RETURNS (C1 COLOUR, C2 TYPE OF COLOUR) CON> AS CON> BEGIN CON> SUSPEND; CON> END ^ C1 C2 ======== ======== RED <null> Example : domain's DEFAULT value
  • DOMAINS EVERYWHERE SQL> CREATE OR ALTER PROCEDURE COLOUR_USING CON> AS CON> DECLARE C1 COLOUR; CON> DECLARE C2 TYPE OF COLOUR; CON> BEGIN CON> C2 = 'BLACK'; CON> C1 = 'WHITE'; CON> END ^ SQL> SQL> EXECUTE PROCEDURE COLOUR_USING ^ Statement failed, SQLCODE = -625 validation error for variable C1, value &quot;WHITE&quot; -At procedure 'COLOUR_USING' line: 7, col: 3 SQL> Example : domain's CHECK CONSTRAINT
  • UPDATE OR INSERT
    • Syntax
      • UPDATE OR INSERT INTO <table> [(col1, …, colN)]
        • VALUES (val1, …, valN)
      • [ MATCHING (mc1, …, mcM)] -- new keyword MATCHING , optional
      • [RETURNING (ret1, …, retR) -- optional RETURNING ... INTO
        • [INTO :var1, …, :varR]] -- clause (introduced in FB 2.0)
    UPDATE <table> SET col1 = val1, … colN = valN WHERE mc1 = val1 AND … AND mcM = valM); IF (ROWCOUNT = 0) THEN INSERT INTO <table> [(col1, …, colN)] VALUES (val1, …, valN) UPDATE OR INSERT statement is close equivalent of construction below but easier to write and understand
  • UPDATE OR INSERT UPDATE OR INSERT rules
    • If optional clause MATCHING is omitted then primary key is used to match table rows against replaced values
    • If RETURNING clause is used then no more than one row must correspond to MATCHING criteria
    • “ IF (ROWCOUNT = 0) …” construction can be used in PSQL only while UPDATE OR INSERT can be used directly as it is usual SQL statement
    • User must have both INSERT and UPDATE privileges on table
    • If row was inserted then INSERT trigger fired else fired UPDATE trigger
  • MERGE
    • Syntax
      • MERGE INTO <table> -- new keyword MERGE
        • USING <table_or_join> -- source of data for merging
          • ON <search_condition> -- how to find target row
        • [WHEN MATCHED THEN -- UPDATE query specification
          • UPDATE SET col1 = val1, …, colN = valN]
        • [WHEN NOT MATCHED THEN -- INSERT query specification
          • INSERT [(col1, …, colN)] VALUES (val1, …, valN)]
    • Both INSERT and UPDATE query specifications are optional but at least one of them must be defined
  • MERGE FOR SELECT <table>.RDB$DBKEY FROM <table_or_join> LEFT JOIN <table> ON <search_condition> INTO :table_dbkey DO IF (:table_dbkey IS NULL ) THEN INSERT INTO <table> … ELSE UPDATE <table> SET … WHERE RDB$DBKEY = :table_dbkey;
    • MERGE statement is handled by the engine like a more complex construction below :
    • As UPDATE OR INSERT statement MERGE is regular SQL statement and can be used directly anywhere (not only inside procedures)
  • MERGE CREATE TABLE AMOUNTS ( GOODID INT, SUMMA NUMERIC(18, 4), CONSTRAINT PK_AMOUNTS PRIMARY KEY (GOODID) ) ; CREATE TABLE ENTRIES ( GOODID INT, DT DATE, DBT NUMERIC(18, 4), CRD NUMERIC(18, 4), CONSTRAINT PK_ENTRIES PRIMARY KEY (GOODID, DT) ) ; MERGE INTO AMOUNTS USING ENTRIES E ON GOODID = E.GOODID WHEN MATCHED THEN UPDATE SET SUMMA = SUMMA + E.DBT - E.CRD WHEN NOT MATCHED THEN INSERT (GOODID, SUMMA) VALUES (E.GOODID, E.DBT - E.CRD) MERGE example
  • NEW BUILT-IN FUNCTIONS
    • Mathematical
      • ABS, MOD, SIGN, CEIL, CEILING, FLOOR, ROUND, TRUNC, PI
      • LOG, LOG10, LN, POWER, EXP, SQRT
      • COS, COSH, ACOS, SIN, SINH, ASIN, TAN, TANH, ATAN, ATAN2, COT
    • Bit logic
      • BIN_AND, BIN_OR, BIN_SHL, BIN_SHR, BIN_XOR
    • Datetime arithmetics
      • DATEADD, DATEDIFF
    • String manipulations
      • ASCII_CHAR, ASCII_VAL
      • LEFT, RIGHT, LPAD, RPAD, POSITION, REPLACE, OVERLAY, REVERSE
    • Other
      • DECODE, MAXVALUE, MINVALUE
      • GEN_UUID, HASH, RAND
  • Questions ?