Quantcast
Channel: IQ – Jason L. Froebe – Tech tips and How Tos for Fellow Techies
Viewing all 56 articles
Browse latest View live

UPDATED: HOWTO: Extract Permissions from SAP Sybase IQ

$
0
0

Back in 2013 I posted a method of extracting the table/view permissions from SAP IQ. With later 15.4 patches and v16 the USER_NAME() function would fail on the grantee column of sys.systableperm. An easy way to extract the users is to simply join the grantee column with sys.sysuser. I broke up the case statement to we don’t have a leading comma in the grant statement: “grant , insert on “. Since we’re dealing with tiny tables, there shouldn’t be any undue harm in simply running each grant generation statement separately and union them (to make dbisql happy for those of you that don’t have multiple results enabled).


    SELECT 'GRANT SELECT ON ' + USER_NAME(st.creator) + '.' + st.table_name + ' TO ' + su.user_name + ';'
    FROM
        sys.systable st,
        sys.systableperm stp,
        sys.sysuser su
    WHERE stp.stable_id = st.table_id
        and su.user_id = stp.grantee
        and stp.selectauth = 'Y'
        and lower(su.user_name) not in ('dba', 'public', 'sys', 'dbo', 'diagnostics', 'rs_systabgroup', 'sa_debug', 'extenv_main', 'extenv_worker', 'sys_spatial_admin_role')
    
    UNION ALL 
    
    SELECT 'GRANT DELETE ON ' + USER_NAME(st.creator) + '.' + st.table_name + ' TO ' + su.user_name + ';'
    FROM
        sys.systable st,
        sys.systableperm stp,
        sys.sysuser su
    WHERE stp.stable_id = st.table_id
        and su.user_id = stp.grantee
        and stp.deleteauth = 'Y'
        and lower(su.user_name) not in ('dba', 'public', 'sys', 'dbo', 'diagnostics', 'rs_systabgroup', 'sa_debug', 'extenv_main', 'extenv_worker', 'sys_spatial_admin_role')
    
    UNION ALL 
    
    SELECT 'GRANT UPDATE ON ' + USER_NAME(st.creator) + '.' + st.table_name + ' TO ' + su.user_name + ';'
    FROM
        sys.systable st,
        sys.systableperm stp,
        sys.sysuser su
    WHERE stp.stable_id = st.table_id
        and su.user_id = stp.grantee
        and stp.updateauth = 'Y'
        and lower(su.user_name) not in ('dba', 'public', 'sys', 'dbo', 'diagnostics', 'rs_systabgroup', 'sa_debug', 'extenv_main', 'extenv_worker', 'sys_spatial_admin_role')
    
    UNION ALL
    
    SELECT 'GRANT ALTER ON ' + USER_NAME(st.creator) + '.' + st.table_name + ' TO ' + su.user_name + ';'
    FROM
        sys.systable st,
        sys.systableperm stp,
        sys.sysuser su
    WHERE stp.stable_id = st.table_id
        and su.user_id = stp.grantee
        and stp.alterauth = 'Y'
        and lower(su.user_name) not in ('dba', 'public', 'sys', 'dbo', 'diagnostics', 'rs_systabgroup', 'sa_debug', 'extenv_main', 'extenv_worker', 'sys_spatial_admin_role')
    
    UNION ALL 
    
    SELECT 'GRANT REFERENCE ON ' + USER_NAME(st.creator) + '.' + st.table_name + ' TO ' + su.user_name + ';'
    FROM
        sys.systable st,
        sys.systableperm stp,
        sys.sysuser su
    WHERE stp.stable_id = st.table_id
        and su.user_id = stp.grantee
        and stp.referenceauth = 'Y'
        and lower(su.user_name) not in ('dba', 'public', 'sys', 'dbo', 'diagnostics', 'rs_systabgroup', 'sa_debug', 'extenv_main', 'extenv_worker', 'sys_spatial_admin_role')
    
    UNION ALL
    
    SELECT 'GRANT INSERT ON ' + USER_NAME(st.creator) + '.' + st.table_name + ' TO ' + su.user_name + ';'
    FROM
        sys.systable st,
        sys.systableperm stp,
        sys.sysuser su
    WHERE stp.stable_id = st.table_id
        and su.user_id = stp.grantee
        and stp.insertauth = 'Y'
        and lower(su.user_name) not in ('dba', 'public', 'sys', 'dbo', 'diagnostics', 'rs_systabgroup', 'sa_debug', 'extenv_main', 'extenv_worker', 'sys_spatial_admin_role')

SAP Sybase IQ and ODBC (Linux/UNIX)

$
0
0

Connecting to SAP SAP_IQSybase’s IQ server shouldn’t be scary but the documentation leaves a lot to be desired. Log on to your favorite Linux or Unix box and make sure you source the IQ.sh file wherever you installed the software.

Let’s use the following hypothetical server:

IQ Server:  MyIQboxOfDoom
Port:  5000
Hostname: myiqboxofdoom

If you want a single odbc.ini file for all users, you’ll need to create the file and store it somewhere. Make sure you set the ODBCINI environment variable somewhere (NOT the IQ.sh file as it will but overwritten anytime you patch IQ) to the file. For example: export ODBCINI=/opt/databases/odbc.ini

If you want each user to have their own odbc.ini file, they will need to create the file named as ${HOME}/.odbc.ini The format will be the same as odbc.ini
odbc.ini / .odbc.ini contents:

[MyIQboxOfDoom]
CommLinks=tcpip(ip=myiqboxofdoom;port=5000;DOBROADCAST=NONE;VERIFY=NO)
AutoStop=no

Connecting is a simple matter of:

dbisql -c "dsn=MyIQboxOfDoom;uid=myuser;pwd=mypass" -nogui

Of course you could embed the user in the odbc.ini file like so:

[MyIQboxOfDoom]
CommLinks=tcpip(ip=myiqboxofdoom;port=5000;DOBROADCAST=NONE;VERIFY=NO)
AutoStop=no
uid=myuser

UPDATED: HOWTO: Extract Permissions from SAP Sybase IQ using the LIST() function

$
0
0

Back in August I provided an updated method to extract the permissions for tables in a SAP IQ server. This provided SAP_IQquite a few GRANT statements to execute. If you have thousands of tables and/or thousands of users, the created a large file that can take a while to execute. We can reduce the number of GRANT statements by combining the SELECT, DELETE, UPDATE, ALTER, REFERENCE and INSERT grants into a single GRANT statement with the LIST() function.

The LIST() function joins a value from a set of rows with a specified delimiter. Think of this as the equivalent of the Perl JOIN() command.

Take for example the following strings:

VALUE1
VALUE2 
VALUE3

In Perl if you wanted a single string with a comma as the delimiter you would write the following:

my $STRING = join(', ', 'VALUE1', 'VALUE2', 'VALUE3');
print "$STRING\n";
VALUE1, VALUE2, VALUE3

In IQ we can do the equivalent with the LIST() function:

CREATE TABLE #test (column_a CHAR(6));
INSERT INTO #test VALUES ('VALUE1');
INSERT INTO #test VALUES ('VALUE2');
INSERT INTO #test VALUES ('VALUE3');

SELECT LIST(column_a, ', ') FROM #test;
VALUE1, VALUE2, VALUE3

The extract permissions for IQ tables code as updated to use the LIST() function:

SELECT 'GRANT ' 
    + LIST ( stp.auth, ', ' )
    + ' ON '
    + USER_NAME(st.creator)
    + '.'
    + st.table_name
    + ' TO '
    + su.user_name + ';'
FROM
    ( SELECT grantee, stable_id, 'SELECT' as auth FROM sys.systableperm WHERE selectauth = 'Y'
      UNION ALL
      SELECT grantee, stable_id, 'DELETE' as auth FROM sys.systableperm WHERE deleteauth = 'Y'
      UNION ALL
      SELECT grantee, stable_id, 'UPDATE' as auth FROM sys.systableperm WHERE updateauth = 'Y'
      UNION ALL
      SELECT grantee, stable_id, 'ALTER' as auth FROM sys.systableperm WHERE alterauth = 'Y'
      UNION ALL
      SELECT grantee, stable_id, 'REFERENCE' as auth FROM sys.systableperm WHERE referenceauth = 'Y'
      UNION ALL
      SELECT grantee, stable_id, 'INSERT' as auth FROM sys.systableperm WHERE insertauth = 'Y'
    ) stp,
    sys.systable st,
    sys.sysuser su
WHERE stp.stable_id = st.table_id
    and su.user_id = stp.grantee
    and lower(su.user_name) not in ('dba', 'public', 'sys', 'dbo', 'diagnostics', 'rs_systabgroup', 'sa_debug', 'extenv_main', 'extenv_worker', 'sys_spatial_admin_role')
GROUP BY su.user_name, st.table_name, st.creator

Produces the following SQL output:

GRANT SELECT ON MYUSER.my_table TO otheruser_i;
GRANT DELETE, UPDATE, INSERT, SELECT ON MYUSER.my_table TO otheruser_u;
GRANT DELETE, UPDATE, INSERT, SELECT ON MYUSER.my_table TO otheruser_e;

SAP IQ: Error: server ‘iq_mpx_1’ was started on an incorrect host ‘myhost1’: this server was created with this connection string ‘host=myhost11:5535’ SOLVED

$
0
0

Recently I built a SAP_IQSAP IQ Multiplex cluster and ran into a self inflicted issue. After I configured the secondary nodes I updated the coordinator node (primary node) with the private (interconnect) and public (what you connect to with an application) connection information. Problem was, I made a small typo and didn’t catch it until after I tried starting the coordinator node.

I configured the coordinator node as such:

alter multiplex server ip_mpx_1 database '/dba/syb/iq_mpx.db' PRIVATE HOST 'node1-clu' PORT 5535 HOST 'myhost11' port 5535;

Upon attempting to start the coordinator node it failed to start with the following message:

MPX: startup failure message: server 'iq_mpx_1' was started on an incorrect host 'myhost1': this server was created with this connection string 'host=myhost11:5535
-- (stcxtlib/st_database.cxx 9455)
Database server shutdown due to startup error

As soon as I saw the message I swore but the fix is quite simple. First, shutdown any secondary nodes. Update your IQ configuration file (or start command line options) so it starts in single node mode and overrides the multiplex configuration:

# single node mode
-iqmpx_sn 1

#For use starting multiplex databases only. Starts the server with override to acknowledge that the write server is starting (1) on a different host, (2) with a different server name, or (3) using a different path to its catalog (.db) file. Do not start two write servers against the same database.
-iqmpx_ov 1

Start the IQ coordinator and reissue the alter multiplex command:

alter multiplex server ip_mpx_1 database '/dba/syb/iq_mpx.db' PRIVATE HOST 'node1-clu' PORT 5535 HOST 'myhost1' port 5535;

Update your IQ configuration file to either remove or comment out the lines we added earlier.

Start up your coordinator. It should now start fine. Please note you will need to resync your secondary nodes before starting them.

HOWTO: SAP Sybase IQ Loading Tables with AutoIncrement/Identity with Zero as a value SOLVED

$
0
0

If the source table has an identity or autoincrement field AND the value starts at zero “0” then load table either server -> server or from file will not work.  IQ is hard coded to reject the rows with the zero value for identity/autoincrement using load table.  Creating a staging table with a numeric field instead of identity/autoincrement will not work with the export file because the export file has the field flagged as an identity/autoincrement field.
 
This isn’t documented anywhere.
 
Workaround/resolution:
1. Extract out the source table
2. Create a staging table using the same DDL as the destination table, swapping the identity/autoincrement field with numeric(10,0)
3. Load the table into the staging table
4. Turn on identity_insert for the destination table

Set temporary option identity_insert= 'destination_table';

5. Insert into destination table from staging table

Insert into destination_table select * from staging_table;

6. Turn off identity_insert for the destination table

Set temporary option identity_insert = '';

7. Drop staging table
8. Rebuild any views that are invalid
FW Howto: List Invalid Views and fix the views in SAP Sybase IQ

HOWTO: SAP IQ Drop Device File from DBSpace

$
0
0

Sometimes when we build an IQ Data Warehouse, our initial space/growth estimate is off significantly enough to warrant reducing the size of the dbspace(s). The process is quite easy put there are a few steps to perform:

Determine how much space is used by the data/indexes. The usage field is the percentage of the totalsize that is being used. For example, the below shows 38% of 4.99TB being used. (4.99 TB * 1024 GB/TB) * 0.38 = 1941.70 GB used:

select convert(varchar(20), DBSpaceName), Usage, TotalSize from sp_iqdbspace() where DBSpaceName = 'IQ_USER_MAIN';
DBSpaceName          Usage TotalSize
------------------------------------
IQ_USER_MAIN         38    4.99T

Determine which device files are part of a dbspace

select convert(varchar(20), DBSpaceName), convert(varchar(20), DBFileName), convert(varchar(70), Path), DBFileSize, Usage from sp_iqfile() where DBSpaceName = 'IQ_USER_MAIN';
DBSpaceName          DBFileName           Path                                                                   DBFileSize Usage
---------------------------------------------------------------------------------------------------------------------------------
IQ_USER_MAIN         IQ_USER_MAIN_FILE_01 /sap/iq/devices/test_usermain001.iq                                    1024G      38
IQ_USER_MAIN         IQ_USER_MAIN_FILE_02 /sap/iq/devices/test_usermain002.iq                                    1024G      38
IQ_USER_MAIN         IQ_USER_MAIN_FILE_03 /sap/iq/devices/test_usermain003.iq                                    1024G      38
IQ_USER_MAIN         IQ_USER_MAIN_FILE_04 /sap/iq/devices/test_usermain004.iq                                    1024G      38
IQ_USER_MAIN         IQ_USER_MAIN_FILE_05 /sap/iq/devices/test_usermain005.iq                                    1024G      34

Verify that the used data will fit in the new allocation

sp_iqdbspace IQ_USER_MAIN

BACKUP DATABASE

backup database FULL to '/backups/test_FULL.dmp';

Alter the file to be dropped to be read only

alter dbspace IQ_USER_MAIN ALTER FILE IQ_USER_MAIN_FILE_05 readonly

Empty the device file (raw device) to be dropped (if dropping more than one file, drop the device file *LEAST* used first)

sp_iqemptyfile 'IQ_USER_MAIN_FILE_05'

Drop the device file (you may need to restart before IQ will let you do this)

ALTER DBSPACE IQ_USER_MAIN DROP FILE IQ_USER_MAIN_FILE_05

Verify the device was dropped

select convert(varchar(20), DBSpaceName), convert(varchar(20), DBFileName), convert(varchar(70), Path), DBFileSize, Usage from sp_iqfile() where DBSpaceName = 'IQ_USER_MAIN';
DBSpaceName          DBFileName           Path                                                                   DBFileSize Usage
---------------------------------------------------------------------------------------------------------------------------------
IQ_USER_MAIN         IQ_USER_MAIN_FILE_01 /sap/iq/devices/test_usermain001.iq                                    1024G      48
IQ_USER_MAIN         IQ_USER_MAIN_FILE_02 /sap/iq/devices/test_usermain002.iq                                    1024G      48
IQ_USER_MAIN         IQ_USER_MAIN_FILE_03 /sap/iq/devices/test_usermain003.iq                                    1024G      45
IQ_USER_MAIN         IQ_USER_MAIN_FILE_04 /sap/iq/devices/test_usermain004.iq                                    1024G      47

SAP IQ: Uptime

$
0
0

At some point you will be asked how long your IQ server has been up.

To determine when the IQ server was started issue:

SELECT PROPERTY('StartTime')

Output:

2015-08-14 18:04:53.918

For the number of days, hours, and minutes we can slice and dice like so:

-- Declarations
DECLARE @UPTIME_DAYS INTEGER
DECLARE @UPTIME_HOURS INTEGER
DECLARE @UPTIME_MINUTES INTEGER

-- Populate variables
SELECT DATEDIFF(day, PROPERTY('StartTime'), CURRENT TIMESTAMP) into @UPTIME_DAYS
SELECT DATEDIFF(hour, PROPERTY('StartTime'), CURRENT TIMESTAMP) % 24 into @UPTIME_HOURS
SELECT DATEDIFF(minute, PROPERTY('StartTime'), CURRENT TIMESTAMP) % 60 into @UPTIME_MINUTES

-- OUTPUT
SELECT @UPTIME_DAYS || ' days ' || @UPTIME_HOURS || ' hours ' || @UPTIME_MINUTES || ' minutes '

Output:

132 days 15 hours 40 minutes

SAP IQ: iqinit error SQLCode: -1000338, SQLState: ‘QDD38’, Severity: 14: Insufficient cache to allocate free list SOLVED

$
0
0

When you create a new IQ v16 instance, you need to use the iqinit program for initial creation of the database.

iqinit -iqpath '/siq/devices/main001.iq' -iqpgsize 131072 -iqblksize 16384 -p 4096 -iqtmppath '/siq/devices/temp001.iqtmp' -dba DBA,SUPER_PASSWORD  -m '/siq/devices/myiq.mir' -o '/siq/log/myiq.iqmsg' -t '/siq/devices/myiq.log' -b -c '/siq/devices/myiq.db'

Occasionally you may run into the SQLCode: -1000338, SQLState: ‘QDD38’, Severity: 14: Insufficient cache to allocate free list error message which basically states the IQ temp cache is too small to start the maintenance IQ instance. The iqinit program is a compiled program that calls the $SYBASE/IQ-16_0/bin64/iqsrv16 program.

SQL Anywhere Initialization Utility Version 16.0.0.809
=============================================================
IQ server starting with:
     10 connections         (       -gm )
    106 cmd resources       ( -iqgovern )
   2459 threads             (     -iqmt )
    512 Kb thread stack size   (   -iqtss  )
  1259008 Kb thread memory size ( -iqmt * -iqtss )
     48 IQ number of cpus  ( -iqnumbercpus )
      0 MB maximum size of IQMSG file ( -iqmsgsz )
      0 copies of IQMSG file archives ( -iqmsgnum )
=============================================================

CHAR collation sequence:  ISO_BINENG(CaseSensitivity=Respect)
CHAR character set encoding:  ISO_8859-1:1987
NCHAR collation sequence:  UCA(CaseSensitivity=UpperFirst;AccentSensitivity=Respect;PunctuationSensitivity=Primary)
NCHAR character set encoding:  UTF-8
Database is not encrypted
Creating system tables
Creating system views
Setting option values
Exception Thrown from stcxtlib/st_database.cxx:1938, Err# 49, tid 2 origtid 2
   O/S Err#: 0, ErrID: 5120 (st_databaseException); SQLCode: -1000338, SQLState: 'QDD38', Severity: 14
[21221]: Insufficient cache to allocate free list. Temp buffers required: 132; temp buffers avaliable: 63.
-- (stcxtlib/st_database.cxx 1938) .
SQL error (-1000338) -- Insufficient cache to allocate free list. Temp buffers required: 132; temp buffers avaliable: 63.
-- (stcxtlib/st_database.cxx 1938) .
Database "/siq/devices/myiq.db" not created

Unfortunately there is no way to specify the IQ temp cache size via the iqinit program:

Usage: iqinit [options] database
        @data expands data from environment variable data or file data

Options (use specified case, as shown):
        -a             accent sensitivity on all UCA string comparisons
        -af            accent sensitivity (French rules) on all
                       UCA string comparisons
        -b             blank padding of strings for comparisons
        -c             case sensitivity on all string comparisons
        -dba uid,pwd set dba username and password
        -dbs size    set initial database size
        -ea alg      encryption algorithm (default none)
        -ek key      specify encryption key
        -ep            prompt for encryption key
        -et            enable encrypted tables
        -i             do not install jConnect support
        -k             SYS.SYSCOLUMNS and SYS.SYSINDEXES views not created
        -l             list available collation sequences
                       (use -l+ to list older collations)
        -le            list available character set encoding labels
                       (use -le+ to list more encoding label aliases)
        -m name      set transaction log mirror name
        -n             no transaction log
        -o file      log output messages to file
        -p size      set page size (must be power of 2 = 2048 and = 32768)
        -pd            legacy system stored procedure behavior
        -q             quiet: do not display messages
        -s             add checksum to database pages
                       (by default checksums are added to database pages,
                       use '-s-' to turn off adding checksums to database pages)
        -t name      transaction log file name (default is database.log)
        -z coll      specify collation sequence for CHAR data type (defaults
                       to server platform's codepage and ordering)
        -ze encoding specify character set encoding for CHAR data type
        -zn coll     specify collation sequence for NCHAR data type
                       (use '-zn UTF8BIN' if the ICU libraries are not
                       available on the server that will load the database. ICU
                       libraries might not be installed on some platforms, such
                       as Windows CE.)
        -iqpath        The path name of the main segment file containing the
                       IQ data.
        -iqsize        The size in MB of either raw partition or OS file with
                       the -iqpath.
        -iqpgsize      The page size in bytes for the Sybase IQ segment of the
                       database.
        -iqblksize     The I/O transfer block size in bytes..
        -iqreservesize Specifies the size in MB of the space to reserve for
                       the Main IQ store.
        -iqmsgpath     The path name of the segment containing the Sybase IQ
                       message trace file.
        -iqtmppath     The path name of of the temporary segment file.
        -iqtmpsize     The size in MB of either the raw partition or OS file
                       for the -iqtmppath.
        -iqtmpreservesize     The size in MB of space to reserve for the
                        temporary IQ store.

Since iqinit calls the iqsrv16 program, we can rename the iqsrv16 to iqsrv16.orig and wrap it with the following iqsrv16 shell script:

#!/bin/ksh

$SYBASE/IQ-16_0/bin64/iqsrv16.orig -iqtc 200 -iqmc 200 $*

Note that I’m allocating 200mb of both main and temporary cache. The IQ instance is now able to start and once the database is created, we can simply replace the iqsrv16 wrapper with the iqsrv16.orig program.


IQ Error: The multiplex server ‘iq_node_3’ is not included in the multiplex – SOLVED

$
0
0

When you run SAP’s IQ Multiplex cluster for a while you start finding little gotchas that will just drive you to drink. If you don’t drink, you will wish you do. (Just like with any other cluster system)

In my latest foray into the murky waters of IQ Multiplex (v16), if one of the nodes if offline for a while, the coodinator node will mark the node as excluded so the cluster carries on. Not really a big deal until you try to bring up the problem node:

I. 02/09 10:31:45. Database server stopped at Tue Feb 09 2016 10:31
DBSPAWN ERROR:  -82
Unable to start specified database: autostarting database failed
Exception Thrown from stcxtlib/st_database.cxx:10050, Err# 21, tid 2 origtid 2
   O/S Err#: 0, ErrID: 5120 (st_databaseException); SQLCode: -1013113, SQLState: 'QNA49', Severity: 14
[22016]: The multiplex server 'iq_node_3' is not included in the multiplex.
-- (stcxtlib/st_database.cxx 10050)

Error: The multiplex server 'iq_node_3' is not included in the multiplex. The multiplex server 'iq_node_3' is not included in the multiplex.
Server failed to start

JNLERROR 2016-02-09-10:31:46 Start of IQ instance iq_mpx_cluster1 failed

Log into the coordinator node, in my case iq_node_1, and run

select server_name, status, mpx_mode, inc_state from sp_iqmpxinfo();"
server_name        status   mpx_mode         inc_state
---------------------------------------------------------------
iq_node_1          included coordinator      N/A
iq_node_2          included writer           active
iq_node_3          excluded unknown           timed_out

As you can see, the iq_node_3 node is excluded due to the connection to it from the coordinator timed out. What to do? Simple, first we re-include the node (on the coordinator):

alter multiplex server iq_node_3 status included;

Next we need to resync iq_node_3:

Resync IQ secondary node

The problem node should start up just fine now.

HOWTO: Connect to SAP Sybase IQ Multiplex using JDBC and the SQL Anywhere driver: “Connection error: TCPIP requires a server name”

$
0
0

SAP’s documentation, like other vendors, often sucks. In today’s wonderful documentation sucky-ness the examples from SAP to connect to IQ using a JDBC connection string like so:

“jdbc:sqlanywhere:UID=***;ENG=MyIQ;PWD=***;links=tcpip(Host=MyIQ;PORT=40000)”

This is fine except when you connect to IQ multiplex and you have logical servers set up. You won’t know which IQ node you will be on and since each IQ node has an unique name (eng=), this won’t work. Alright, let’s drop the eng=MyIQ.

“jdbc:sqlanywhere:UID=***;PWD=***;links=tcpip(Host=MyIQ;PORT=40000)”

This will result in an immediate error of “Connection error: TCPIP requires a server name”. Don’t panic, there is a fix. Drop the ENG=MyIQ and links=tcpip(Host=MyIQ;PORT=40000) replacing it with the HOST=MyIQ:40000.

“jdbc:sqlanywhere:UID=***;PWD=***;HOST=MyIQ:40000)”

That works. That is so much more simple than the demented links=tcpip(Host=MyIQ;PORT=40000) nonsense.

Now the fun bit of working code. The following “IQConnect” program accepts four parameters host port username password and spits out the names of the tables on the IQ server:

import java.io.*;
import java.sql.*;

public class IQConnect {
    public static void main(String[] args) {
        if (args.length == 4) {
            String HostName;
            int Port = 0;
            String UserName;
            String Password;

            try {
                Port = Integer.parseInt(args[1]);
            } catch (NumberFormatException e) {
                System.err.println("Port # must be an integer");
                System.exit(1);
            }

            HostName = args[0];
            UserName = args[2];
            Password = args[3];

            String arg;
            Connection con;

            try {
                String ConnectionParams = String.format("jdbc:sqlanywhere:uid=%s;pwd=%s;host=%s:%d", UserName, Password, HostName, Port);
                con = DriverManager.getConnection(ConnectionParams);

                Statement stmt = con.createStatement();
                ResultSet rs = stmt.executeQuery("select table_name from sys.systable;");

                while (rs.next()) {
                    String TableName = rs.getString(1);
                    System.out.println(TableName);
                }

                stmt.close();
                con.close();
            }
            catch (SQLException sqe)
            {
                System.out.println("Unexpected exception : " +
                  sqe.toString() + ", sqlstate = " +
                  sqe.getSQLState());
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        } else {
            System.out.println("Requires Host Port# User Password");
        }
    }
}

Compile it with:

javac -cp $IQ16/java/sajdbc4.jar:. IQConnect.java

Execute it with

java -cp $IQ16/java/sajdbc4.jar:. IQConnect MyIQ 40000 dba sql

Of course, if you have $IQ16/java as part of your $CLASSPATH you don’t need to include “-cp $IQ16/java/sajdbc4.jar:.” to execute the program.

HowTo: SAP IQ What is running right now (active transactions) hogging resources?

$
0
0

Every once in a while you need to determine what connections in SAP IQ are actively executing. In other words, list the open transactions along with connection information. This is handly to determine what is hogging the cpu or blocking other connections.

select
    siqc.ConnHandle,
    ISNULL(siqc.MPXServerName, siqc.LSName) "Server",
    siqc.Name,
    siqc.Userid,
    siqc.ConnCreateTime,
    siqc.LastReqTime,
    siqc.NodeAddr "Connect From",
    siqc.LastIdle,
    saci.BlockedOn,
    saci.LockTable,
    sacp_ProcName.Value "Proc Name",
    sacp_ProcLineNumber.Value "Proc Line Number",
    siqt.TxnID,
    siqt.TxnCreateTime,
    CAST(siqc.TempTableSpaceKB / 1024 AS Integer) "TempTableSpaceMB",
    CAST(siqc.TempWorkSpaceKB / 1024 AS Integer) "TempWorkSpaceMB",
    siqc.IQthreads,
    siqc.ReqType,
    sac.LastStatement
FROM 
    sp_iqconnection() siqc 
    JOIN sa_conn_activity() sac ON sac.Number = siqc.ConnHandle
    JOIN sa_conn_info() saci on saci.Number = sac.Number
    JOIN sa_conn_properties() sacp_ProcLineNumber on sacp_ProcLineNumber.Number = saci.Number
    JOIN sa_conn_properties() sacp_ProcName on sacp_ProcName.Number = saci.Number
    JOIN sp_iqtransaction() siqt on siqt.TxnID = siqc.TxnID
WHERE 
    siqc.TxnID > 0
    AND siqc.ConnHandle != @@spid
    AND siqc.Userid != 'dbo'
    AND sacp_ProcLineNumber.PropName = 'CurrentLineNumber'
    AND sacp_ProcName.PropName = 'CurrentProcedure'
ORDER BY
    siqc.ConnCreateTime asc,
    siqc.LastReqTime desc

result

SAP IQ and SQL Anywhere: Locking and blocking only for a maximum specified time

$
0
0

Usually in IQ, you will lock a table for a short time (dml operations) or longer when performing a data load, table/index maintenance or issuing a holdlock within your transaction. These locks can cause other processes to block or even abort with an error “SQL Anywhere Error – 210: User ‘another user’ has the row in (some table)”. It can become problematic if you have an application that doesn’t close the transaction in a reasonable timeframe.

Consider the following scenario: A process that retrieves and loads dozens of data files to load into a single table every few minutes.
Issue: Occasionally the “SQL Anywhere Error – 210: User ‘another user’ has the row in (some table)” error will occur causing the load to fail for that file(s).

What can be done? Several things really:

  1. Trap/ignore the error
  2. Retry loading the file. How many times do we attempt this before we collide with the next set of files to load?
  3. Issue holdlock (not sure if it works with load table – I haven’t tried it) causing write access to block. If the load table is stalled, it will hold the lock indefinitely
  4. Combine all the files and load that monolithic file. Potentially faster as setting up a load table connection is very expensive, but if the file fails, the entire set fails. Do we retry?
  5. Issue temporary locks, but block only for X time and only allow itself to be blocked for Y time before rolling back, erroring.

Using the temporary locks/blocking seems to be the best option for this particular scenario to me. It allows for the load tables to run in succession without me having to set up the queue and if it does error out, I can decide in the outside code whether or not to retry the load table. Basically it gives me more control over the locking/blocking.

set temporary option date_order = 'YMD';
set temporary option timestamp_format = 'yyyy/mm/dd hh:nn:ss.sss';

-- "If the blocking option is set to “On”, any transaction attempting to obtain a lock that conflicts with an existing lock held by another transaction waits until every conflicting lock is released or until the blocking_timeout is reached. If the lock is not released within blocking_timeout milliseconds, then an error is returned for the waiting transaction. If the blocking option is set to “Off”, the transaction that attempts to obtain a conflicting lock receives an error." - https://wiki.scn.sap.com/wiki/display/SQLANY/How+to+Debug+Blocking+in+SQL+Anywhere
SET TEMPORARY OPTION "blocking" = 'ON';

-- we will wait up to 10 seconds to obtain a lock before rolling back
SET TEMPORARY OPTION "blocking_timeout" = '10000';

-- allow blocking of other transactions to maximum 5 sec before rolling back
SET TEMPORARY OPTION blocking_others_timeout = '5000';

LOAD TABLE ${REPOSITORY_SCHEMA}.activity (
    ConnHandle,
    LSServer,
    Name,
    Userid
)
USING CLIENT FILE '${OUT_CSV_FILE}'
NOTIFY 1000
QUOTES ON ESCAPES OFF
FORMAT bcp
DELIMITED BY '|'
ROW DELIMITED BY '\n';

COMMIT;

SAP Sybase IQ: Do not use LF indexes in IQ v16

$
0
0

Really, there isn’t a good reason to use LF indexes in version 16 and higher of IQ. Use HG indexes instead. From Mark Mumy of SAP fame:

Mumy, Mark mark.mumy at sap.com
Mon Aug 17 11:31:37 MST 2015

There is no need with IQ 16 SP08.20 and beyond to use an LF. The HG index has been augmented over the past few years to take on the same characteristics for low cardinality data while adding parallelism and other join/sort features that just don’t exist in the LF.

Remove all LF indexes and replace them with HGs, if they don’t have one. There is no need for an HNG as the LF (don’t use) and HG have many of those features and can cost less.

Mark

Mark Mumy
Director, Enterprise Architecture, Global HANA CoE | SAP
M +1 347-820-2136 | E mark.mumy at sap.com
My Blogs: http://scn.sap.com/people/markmumy/blog

Connect SAP IQ to SAP IQ using ODBC the easy way

$
0
0

The documentation on setting up a linked server is overly complex in SAP’s documentation and doesn’t actually tell you what you need to do. This is rather typical of SAP’s IQ documentation unfortunately. Setting up the linked server is easy and only takes about 20 seconds.

First add an entry into the $SYBASE/interfaces file. Seriously. There shouldn’t be any reason for this because we specify the ip/port in the server definition. Chock it up to SAP not cleaning up ancient code.

iq_02
    query tcp ether siq02 50000
    master tcp ether siq02 50000

Next we add the server entry into the local IQ server. Yes, you really do want to use the ASA (SQL Anywhere) driver here. You don’t have to do anything special for multiplex unlike the IQ driver which really doesn’t give you anything more than a raging headache and the urge to excessively partake in your least favorite poison.

CREATE SERVER iq_02 CLASS 'ASAODBC' USING 'siq02:50000'

Finally we add the remote login mapping. In this case, I’m mapping the remote user “k2k23” to the local dba account:

CREATE EXTERNLOGIN "dba" to "iq_02" REMOTE LOGIN "k2k23" IDENTIFIED BY klj3haq345as56t

You are now free to set up your proxy tables and load from (remote) location without issue.

SAP IQ and SQL Anywhere UnixODBC UserDSN and SystemDSN issues: WORKAROUND

$
0
0

SAP’s IQ / SQLAnywhere ODBC driver on Linux/*nix doesn’t work with a system that has both UserDSNs (~/.odbc.ini) and SystemDSNs (/etc/odbc.ini).

Currently when the driver looks for a DSN (db instance), the resolution is:

  1. $ODBCINI – must contain the exact full path name of the .odbc.ini file.
  2. $HOME
  3. Current directory
  4. $PATH

Notice that /etc/odbc.ini is not processed. A workaround to use SystemDSNs is to set the ODBCINI variable to /etc/odbc.ini but it doesn’t help if you have a mix of SystemDSNs and UserDSNs.

I’ve requested SAP to fix this. They’ve opened KBA2571931 CR812127. Unfortunately, SAP requires a support contract to view the KBA 🙁

CR812127 order of resolution:

  1. $ODBCINI – must contain the exact full path name of the .odbc.ini file.
  2. $HOME
  3. Current directory
  4. $PATH
  5. /etc/odbc.ini

HOWTO: SAP Sybase IQ, SQLAnywhere, ADO.net and Powershell

$
0
0

Connecting to IQ can be a rather pain in the tuckus.

In the v16 IQ client for Microsoft Windows, the .net assembly changed to “Sap.Data.SQLAnywhere” from “iAnywhere.Data.SQLAnywhere”.

Another annoyance is the loading of the assembly where SAP recommends loading it via

Add-Type -AssemblyName ("Sap.Data.SQLAnywhere.v4.5, Version=17.0.0.10624, Culture=neutral, PublicKeyToken=f222fc4333e0d400")

This forces you to remember the exact version of the assembly as well as the public key token. If you’re worried about a nefarious individual gaining access to your machine and infecting your ado.net assemblies, continue to use the recommended method.

A simpler mechanism is using “LoadWithPartialName” where powershell will load the v4.5 ado.net driver for SQLAnywhere if it is in the Global Assembly Cache (GAC):

[void][System.Reflection.Assembly]::LoadWithPartialName("Sap.Data.SQLAnywhere.v4.5")

Working example of connecting to IQ from PowerShell with a v16.1 IQ client (v17 SQLAnywhere client under the covers):

$HostName = "127.0.0.1"
$Port = 20001
$User = "DBA"
$Password = "password"

[void][System.Reflection.Assembly]::LoadWithPartialName("Sap.Data.SQLAnywhere.v4.5")

# Connection string
$connectionString = "Host=$HostName`:$Port;UserID=$User;Password=$Password"

# Create SAConnection object
$conn = New-Object Sap.Data.SQLAnywhere.SAConnection($connectionString)

# Connect to remote IQ server
$conn.Open()

# simple query
$Query = 'select 1 as col1 from dummy'

# Create a SACommand object and feed it the simple $Query
$command = New-Object Sap.Data.SQLAnywhere.SACommand($Query, $conn)

# Execute the query on the remote IQ server
$reader = $command.ExecuteReader()

# create a DataTable object 
$Datatable = New-Object System.Data.DataTable

# Load the results into the $DataTable object
$DataTable.Load($reader)

# Send the results to the screen in a formatted table
$DataTable | Format-Table -Auto

Output:

col1
----
   1
Viewing all 56 articles
Browse latest View live