/******************************************************************************* ** ** Source File Name = tbconstr.c ** ** Licensed Materials - Property of IBM ** ** (C) COPYRIGHT International Business Machines Corp. 1995, 2000 ** All Rights Reserved. ** ** US Government Users Restricted Rights - Use, duplication or ** disclosure restricted by GSA ADP Schedule Contract with IBM Corp. ** ** ** PURPOSE : ** Shows how to work with constraints associated with tables. ** ** For more information about these samples see the README file. ** ** For more information on programming in CLI see the: ** - "Building CLI Applications" section of the Application Building Guide, and the ** - CLI Guide and Reference. ** ** For more information on the SQL language see the SQL Reference. ** *******************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sqlcli1.h> #include "utilcli.h" /* Header file for CLI sample code */ int CnDefine( SQLHANDLE) ; int CnListPrimaryKeys( SQLHANDLE) ; int CnListForeignKeys( SQLHANDLE) ; int CnListSpecialColumns( SQLHANDLE) ; int CnListIndexColumns( SQLHANDLE) ; int CnCleanUp( SQLHANDLE); /******************************************************************* ** main *******************************************************************/ int main( int argc, char * argv[] ) { SQLRETURN sqlrc = SQL_SUCCESS; int rc = 0; SQLHANDLE henv; /* environment handle */ SQLHANDLE hdbc; /* connection handles */ char dbAlias[SQL_MAX_DSN_LENGTH + 1] ; char user[MAX_UID_LENGTH + 1] ; char pswd[MAX_PWD_LENGTH + 1] ; /* checks the command line arguments */ rc = CmdLineArgsCheck1( argc, argv, dbAlias, user, pswd ); if ( rc != 0 ) return( rc ) ; printf("\n\nTABLES: HOW TO WORK WITH CONSTRAINTS.\n"); /* initialize the CLI application */ rc = CLIAppInit( dbAlias, user, pswd, &henv, &hdbc, (SQLPOINTER)SQL_AUTOCOMMIT_ON); if ( rc != 0 ) return( rc ) ; rc = CnDefine( hdbc) ; rc = CnListPrimaryKeys( hdbc) ; rc = CnListForeignKeys( hdbc) ; rc = CnListSpecialColumns( hdbc) ; rc = CnListIndexColumns( hdbc) ; rc = CnCleanUp( hdbc) ; /* terminate the CLI application */ rc = CLIAppTerm( &henv, &hdbc, dbAlias); return( rc ) ; } /* end main */ /****************************************************************************** ** CnDefine ******************************************************************************/ int CnDefine( SQLHANDLE hdbc) { SQLRETURN sqlrc = SQL_SUCCESS; int rc = 0; SQLHANDLE hstmt ; /* statement handle */ SQLCHAR * stmt1 = ( SQLCHAR *) "CREATE TABLE sch.dept ( " "deptno CHAR(3) NOT NULL PRIMARY KEY, " "deptname VARCHAR(32) )" ; SQLCHAR * stmt2 = ( SQLCHAR *) "CREATE TABLE sch.emp ( " "empno CHAR(7) NOT NULL PRIMARY KEY, " "deptno CHAR(3) NOT NULL," "sex CHAR(1) WITH DEFAULT 'M', " "salary DECIMAL(7,2) WITH DEFAULT, " "CONSTRAINT check1 " " CHECK( sex IN ( 'M', 'F')), " "CONSTRAINT check2" " CHECK( salary < 70000.00), " "CONSTRAINT fk1" " FOREIGN KEY (deptno) REFERENCES sch.dept(deptno) )" ; printf("\nUSE THE CLI FUNCTIONS\n"); printf("-SQLSetConnectAttr\n-SQLAllocHandle\n"); printf("-SQLExecDirect\n-SQLFreeHandle\n"); printf("TO CREATE TABLES WITH CONSTRAINTS:\n"); /* set AUTOCOMMIT on */ sqlrc = SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* allocate a statement handle */ sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* create first table */ printf("\n Execute directly the statement\n"); printf(" CREATE TABLE sch.dept ( \n"); printf(" deptno CHAR(3) NOT NULL PRIMARY KEY, \n"); printf(" deptname VARCHAR(32) )\n"); sqlrc = SQLExecDirect( hstmt, stmt1, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* create second table */ printf(" Execute directly the statement\n"); printf(" CREATE TABLE sch.emp ( \n"); printf(" empno CHAR(7) NOT NULL PRIMARY KEY,\n"); printf(" deptno CHAR(3) NOT NULL,\n"); printf(" sex CHAR(1) WITH DEFAULT 'M', \n"); printf(" salary DECIMAL(7,2) WITH DEFAULT, \n"); printf(" CONSTRAINT check1 \n"); printf(" CHECK( sex IN ( 'M', 'F')), \n"); printf(" CONSTRAINT check2\n"); printf(" CHECK( salary < 70000.00), \n"); printf(" CONSTRAINT fk1\n"); printf(" FOREIGN KEY (deptno) REFERENCES sch.dept(deptno))\n"); sqlrc = SQLExecDirect( hstmt, stmt2, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* free the statement handle */ sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); return(rc); } /****************************************************************************** ** CnCleanUp - drop the tables created in CnDefine ******************************************************************************/ int CnCleanUp( SQLHANDLE hdbc) { SQLRETURN sqlrc = SQL_SUCCESS; int rc = 0; SQLHANDLE hstmt ; /* statement handle */ SQLCHAR * stmt1 = ( SQLCHAR *) "DROP TABLE sch.dept" ; SQLCHAR * stmt2 = ( SQLCHAR *) "DROP TABLE sch.emp" ; printf("\nDrop the tables created in CnDefine.\n"); /* set AUTOCOMMIT on */ sqlrc = SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* allocate a statement handle */ sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* drop the first table */ sqlrc = SQLExecDirect( hstmt, stmt1, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* drop the second table */ sqlrc = SQLExecDirect( hstmt, stmt2, SQL_NTS ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* free the statement handle */ sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); return(rc); } /****************************************************************************** ** CnListPrimaryKeys ******************************************************************************/ int CnListPrimaryKeys( SQLHANDLE hdbc) { SQLRETURN sqlrc = SQL_SUCCESS; int rc = 0; SQLHANDLE hstmt ; /* statement handle */ SQLCHAR tbSchema[] = "SCH"; SQLCHAR tbName[] = "DEPT"; struct { SQLINTEGER ind; SQLCHAR val[129]; } pkColumnName, pkName; struct { SQLINTEGER ind; SQLSMALLINT val; } pkColumnPos ; SQLINTEGER rowNb = 0; printf("\nUSE THE CLI FUNCTIONS\n"); printf("-SQLSetConnectAttr\n-SQLAllocHandle\n"); printf("-SQLPrimaryKeys\n-SQLBindCol\n"); printf("-SQLFetch\n-SQLFreeHandle\n"); printf("TO LIST THE PRIMARY KEYS FOR A SPECIFIED TABLE:\n"); /* set AUTOCOMMIT on */ sqlrc = SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* allocate a statement handle */ sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /*--> 00003366.snippet */ /* call SQLPrimaryKeys */ printf("\n Call SQLPrimaryKeys for the table %s.%s\n", tbSchema, tbName); sqlrc = SQLPrimaryKeys(hstmt, NULL, 0, tbSchema, SQL_NTS, tbName, SQL_NTS); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; /* 00003366.snippet <--*/ /* bind columns to variables */ sqlrc = SQLBindCol(hstmt, 4, SQL_C_CHAR, (SQLPOINTER) pkColumnName.val, 129, &pkColumnName.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 5, SQL_C_SHORT, (SQLPOINTER) &pkColumnPos.val, 0, &pkColumnPos.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 6, SQL_C_CHAR, (SQLPOINTER) pkName.val, 129, &pkName.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; /*-->00000595.snippet */ /* fetch each row, and display */ printf(" Fetch each row and display.\n"); sqlrc = SQLFetch( hstmt ); /* 00000595.snippet <--*/ STMT_HANDLE_CHECK( hstmt, sqlrc ); if (sqlrc == SQL_NO_DATA_FOUND) { printf("\nData not found.\n"); } while( sqlrc != SQL_NO_DATA_FOUND ) { rowNb = rowNb + 1; printf(" -------row nb. %lu --------\n", rowNb); printf(" Primary Key Name: %s\n", pkName.val); printf(" Primary Key Column Name: %s\n", pkColumnName.val); printf(" Primary Key Column Position: %d\n", pkColumnPos.val); sqlrc = SQLFetch( hstmt ); STMT_HANDLE_CHECK( hstmt, sqlrc ); } /* free the statement handle */ sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); return(rc); } /****************************************************************************** ** CnListForeignKeys ******************************************************************************/ int CnListForeignKeys( SQLHANDLE hdbc) { SQLRETURN sqlrc = SQL_SUCCESS; int rc = 0; SQLHANDLE hstmt ; /* statement handle */ SQLCHAR tbSchema[] = "SCH"; SQLCHAR tbName[] = "DEPT"; struct { SQLINTEGER ind; SQLCHAR val[129]; } pkTableSch, pkTableName, pkColumnName, pkName; struct { SQLINTEGER ind; SQLCHAR val[129]; } fkTableSch, fkTableName, fkColumnName, fkName; struct { SQLINTEGER ind; SQLSMALLINT val; } deleteRule, updateRule ; SQLINTEGER rowNb = 0; printf("\nUSE THE CLI FUNCTIONS\n"); printf("-SQLSetConnectAttr\n-SQLAllocHandle\n"); printf("-SQLForeignKeys\n-SQLBindCol\n"); printf("-SQLFetch\n-SQLFreeHandle\n"); printf("TO LIST THE FOREIGN KEYS FOR A SPECIFIED TABLE:\n"); /* set AUTOCOMMIT on */ sqlrc = SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* allocate a statement handle */ sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* call SQLForeignKeys */ printf("\n Call SQLForeignKeys for the table %s.%s\n", tbSchema, tbName); sqlrc = SQLForeignKeys(hstmt, NULL, 0, tbSchema, SQL_NTS, tbName, SQL_NTS, NULL, 0, NULL, SQL_NTS, NULL, SQL_NTS); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; /* bind columns to variables */ sqlrc = SQLBindCol(hstmt, 2, SQL_C_CHAR, (SQLPOINTER) pkTableSch.val, 129, &pkTableSch.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 3, SQL_C_CHAR, (SQLPOINTER) pkTableName.val, 129, &pkTableName.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 4, SQL_C_CHAR, (SQLPOINTER) pkColumnName.val, 129, &pkColumnName.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 6, SQL_C_CHAR, (SQLPOINTER) fkTableSch.val, 129, &fkTableSch.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 7, SQL_C_CHAR, (SQLPOINTER) fkTableName.val, 129, &fkTableName.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 8, SQL_C_CHAR, (SQLPOINTER) fkColumnName.val, 129, &fkColumnName.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 10, SQL_C_SHORT, (SQLPOINTER) &updateRule.val, 0, &updateRule.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 11, SQL_C_SHORT, (SQLPOINTER) &deleteRule.val, 0, &deleteRule.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 12, SQL_C_CHAR, (SQLPOINTER) fkName.val, 129, &fkName.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 13, SQL_C_CHAR, (SQLPOINTER) pkName.val, 129, &pkName.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; /* fetch each row, and display */ printf(" Fetch each row and dispaly.\n"); sqlrc = SQLFetch( hstmt ); STMT_HANDLE_CHECK( hstmt, sqlrc ); if (sqlrc == SQL_NO_DATA_FOUND) { printf("\nData not found.\n"); } while( sqlrc != SQL_NO_DATA_FOUND ) { rowNb = rowNb + 1; printf(" -------row nb. %lu --------\n", rowNb); printf(" Foreign Key Name: %s\n", fkName.val); printf(" Primary Key Name: %s\n", pkName.val); printf(" Foreign Key Column: %s.%s.%s\n", fkTableSch.val, fkTableName.val, fkColumnName.val); printf(" Primary Key Column: %s.%s.%s\n", pkTableSch.val, pkTableName.val, pkColumnName.val); printf(" Update Rule: "); switch( updateRule.val) { case SQL_RESTRICT: printf("RESTRICT\n"); /* always for IBM DBMSs */ break; case SQL_CASCADE: printf("CASCADE\n"); /* non-IBM only */ break; default: printf("SET NULL\n"); break; } printf(" Delete Rule: "); switch( deleteRule.val) { case SQL_RESTRICT: printf("RESTRICT\n"); /* always for IBM DBMSs */ break; case SQL_CASCADE: printf("CASCADE\n"); /* non-IBM only */ break; case SQL_NO_ACTION: printf("NO ACTION\n"); /* non-IBM only */ break; default: printf("SET NULL\n"); break; } sqlrc = SQLFetch( hstmt ); STMT_HANDLE_CHECK( hstmt, sqlrc ); } /* free the statement handle */ sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); return(rc); } /****************************************************************************** ** CnListSpecialColumns - list the columns included in ** Foreign Key or Unique Indexes ******************************************************************************/ int CnListSpecialColumns( SQLHANDLE hdbc) { SQLRETURN sqlrc = SQL_SUCCESS; int rc = 0; SQLHANDLE hstmt ; /* statement handle */ struct { SQLINTEGER ind ; SQLCHAR val[129] ; } colName, colType; struct { SQLINTEGER ind ; SQLCHAR val[255] ; } colRemarks; struct { SQLINTEGER ind ; SQLINTEGER val; } colPrecision; struct { SQLINTEGER ind ; SQLSMALLINT val; } colScale; SQLCHAR tbSchema[] = "SCH"; SQLCHAR tbName[] = "DEPT"; printf("\nUSE THE CLI FUNCTIONS\n"); printf("-SQLSetConnectAttr\n-SQLAllocHandle\n"); printf("-SQLSpecialColumns\n-SQLBindCol\n"); printf("-SQLFetch\n-SQLFreeHandle\n"); printf("TO LIST SPECIAL COLUMNS FOR A SPECIFIED TABLE:\n"); /* set AUTOCOMMIT on */ sqlrc = SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* allocate a statement handle */ sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /*--> 00000660.snippet */ /* call SQLSpecialColumns */ printf("\n Call SQLSpecialColumns for the table %s.%s\n", tbSchema, tbName); sqlrc = SQLSpecialColumns(hstmt, SQL_BEST_ROWID, NULL, 0, tbSchema, SQL_NTS, tbName, SQL_NTS, SQL_SCOPE_CURROW, SQL_NULLABLE); /* 00000660.snippet <--*/ STMT_HANDLE_CHECK( hstmt, sqlrc ) ; /* bind columns to variables */ sqlrc = SQLBindCol( hstmt, 2, SQL_C_CHAR, colName.val, 129, &colName.ind ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); sqlrc = SQLBindCol( hstmt, 4, SQL_C_CHAR, colType.val, 129, &colType.ind ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); sqlrc = SQLBindCol( hstmt, 5, SQL_C_LONG, (SQLPOINTER)&colPrecision.val, sizeof(colPrecision.val), &colPrecision.ind ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); sqlrc = SQLBindCol( hstmt, 7, SQL_C_SHORT, (SQLPOINTER)&colScale.val, sizeof(colScale.ind), &colScale.ind ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); /* fetch each row, and display */ printf(" Fetch each row and dispaly.\n"); sqlrc = SQLFetch( hstmt ); STMT_HANDLE_CHECK( hstmt, sqlrc); if (sqlrc == SQL_NO_DATA_FOUND) { printf("\n Data not found.\n"); } while( sqlrc != SQL_NO_DATA_FOUND ) { printf(" %-10.10s", colName.val); printf(", %s", colType.val); if ( colPrecision.ind != SQL_NULL_DATA) { printf(" (%ld", colPrecision.val); } else { printf("(\n"); } if (colScale.ind != SQL_NULL_DATA) { printf(", %d)\n", colScale.val); } else { printf(")\n"); } sqlrc = SQLFetch( hstmt ); STMT_HANDLE_CHECK( hstmt, sqlrc ); } /* endwhile */ /* free the statement handle */ sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); return(rc); } /****************************************************************************** ** CnListIndexColumns ******************************************************************************/ int CnListIndexColumns( SQLHANDLE hdbc) { SQLRETURN sqlrc = SQL_SUCCESS; int rc = 0; SQLHANDLE hstmt ; /* statement handle */ SQLCHAR tbSchema[] = "SCH"; SQLCHAR tbName[] = "DEPT"; struct { SQLINTEGER ind; SQLCHAR val[129]; } columnName, indexName; struct { SQLINTEGER ind; SQLSMALLINT val; } type ; printf("\nUSE THE CLI FUNCTIONS\n"); printf("-SQLSetConnectAttr\n-SQLAllocHandle\n"); printf("-SQLStatistics\n-SQLBindCol\n"); printf("-SQLFetch\n-SQLFreeHandle\n"); printf("TO LIST INDEX COLUMNS FOR A SPECIFIED TABLE:\n"); /* set AUTOCOMMIT on */ sqlrc = SQLSetConnectAttr( hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* allocate a statement handle */ sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ; DBC_HANDLE_CHECK( hdbc, sqlrc); /* call SQLStatistics */ printf("\n Call SQLStatistics for the table %s.%s\n", tbSchema, tbName); sqlrc = SQLStatistics(hstmt, NULL, 0, tbSchema, SQL_NTS, tbName, SQL_NTS, SQL_INDEX_UNIQUE, SQL_QUICK); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; /* bind columns to variables */ sqlrc = SQLBindCol(hstmt, 6, SQL_C_CHAR, (SQLPOINTER) indexName.val, 129, &indexName.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 7, SQL_C_SHORT, (SQLPOINTER) &type.val, 0, &type.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; sqlrc = SQLBindCol(hstmt, 9, SQL_C_CHAR, (SQLPOINTER) columnName.val, 129, &columnName.ind); STMT_HANDLE_CHECK( hstmt, sqlrc ) ; /* fetch each row, and display */ printf(" Fetch each row and dispaly.\n"); sqlrc = SQLFetch( hstmt ); STMT_HANDLE_CHECK( hstmt, sqlrc ); if (sqlrc == SQL_NO_DATA_FOUND) { printf("\nData not found.\n"); } while( sqlrc != SQL_NO_DATA_FOUND ) { if ( type.val != SQL_TABLE_STAT) { printf(" Column: %-10s Index Name: %s\n", columnName.val, indexName.val); } sqlrc = SQLFetch( hstmt ); STMT_HANDLE_CHECK( hstmt, sqlrc ); } /* free the statement handle */ sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ; STMT_HANDLE_CHECK( hstmt, sqlrc); return(rc); }