Question

I have a temp-table called tt. I want to create a database table with the same field names and types using my temp-table.

I can't figure out how to do in Progress-4gl. Is this possible ?

Thanks.

Was it helpful?

Solution

Short answer: yes

The safest way is to do this by code is to create an incremental df and then load this. Here is a very partial start that should get you going:

DEFINE TEMP-TABLE tt NO-UNDO
   FIELD ii AS INT
   FIELD cc AS CHAR
INDEX ttix IS UNIQUE PRIMARY ii.

DEF VAR hb     AS HANDLE NO-UNDO.
DEF VAR hf     AS HANDLE NO-UNDO.
DEF VAR ifield AS INT NO-UNDO.

hb = TEMP-TABLE tt:DEFAULT-BUFFER-HANDLE.

OUTPUT TO "tt.df".

PUT UNFORMATTED SUBSTITUTE( "ADD TABLE &1", QUOTER( hb:NAME ) ) SKIP.

DO  ifield = 1 TO hb:NUM-FIELDS:

   hf = hb:BUFFER-FIELD( ifield ).

   PUT UNFORMATTED 
      SUBSTITUTE( 
         "ADD FIELD &1 OF &2 AS &3", 
         QUOTER( hf:NAME ), 
         QUOTER( hb:NAME ), 
         hf:DATA-TYPE 
      ) SKIP.

   /* to do: add other field attributes like label, initial value, decimals, format */

END.         

/* to do: add indices */

OUTPUT CLOSE.

The resulting df can be loaded with:

RUN prodict/load_df.p ( "tt.df" ).

OTHER TIPS

While this might be possible it's not a very good idea. Chances are you will corrupt your database. This might lead to data loss. You are much better off sticking to the provided tools even if they might have some problems.

Backup first

Always back up before applying any changes!

Single Use Database

You can modify a single usage database (if you're locally connected) online directly in the Data Dictionary. This is quite straight forward. Just use the GUI to add the table, it's fields and indices. Make sure you commit your changes.

Multi User Database

A multi user database can be changed offline or (a little bit more limited) online. Adding a new table with corresponding fields and indices is a change that can be made online. Adding the changes offline is done exactly in the same way as the "Single Use Database".

Online changes requires more work:

First of all you need two connected databases. I'll call them "live" and "development" in this case. "Development" will consist of a perfect copy of "live" when it comes to the schema. It doesn't have to have any data in it. The databases can have the same name - then you'll use a "logical name" alias when connecting to one of them.

  1. Make the changes in "development" just like you would in an offline database or single usage database (use Data Dictionary). Make sure you commit your changes.

  2. Enter the Data Administration Tool. Make sure you have "development" selected as default database. Go to the Admin -> Dump Data and Definitions -> Create Incremental .df file. Select your "live" database as comparative database and select a good file name (delta.df is default).

    The file created is a diff-file between your "live" and "development" databases. It's wise to check it to make sure you're not dropping any tables or anything like that by mistake.

  3. Now select the "live" database as default and go to Admin -> Load Data and Definitions. Here you can choose to add the changes offline (default) or online (check 'Add new objects on-line').

Some schema changes will require you to compile your source code again!

Load Data and Definitions

Using the example of @Stefan Drissen, and done some modification.

{temp-tables.i}

def input param table-handle tt.

def var hb     as handle no-undo.
def var hf     as handle no-undo.
def var ifield as int no-undo.
def var vindex as char no-undo.
def var vi as int. 

hb = tt:default-buffer-handle.

output to value("/home/user/teste.df") append.

    put unformatted substitute( "ADD TABLE &1", quoter(hb:name)) skip.

    DO  ifield = 1 to hb:num-fields:

        hf = hb:buffer-field( ifield ).

       put unformatted
          substitute( 
             "ADD FIELD &1 OF &2 AS &3", 
             quoter( hf:name ), 
             quoter( hb:name ), 
             hf:data-type 
          ) skip.

       put unformatted 
           substitute(
               "FORMAT &1",
                   quoter(hf:format)
                   ) skip.

       put unformatted 
            substitute (
                "LABEL &1",
                    quoter( hf:name )
                    ) skip.

        put unformatted "ORDER " + string(ifield * 10) skip.

        if ifield < hb:num-fields then put unformatted skip (1).   

    end. 

    put unformatted skip(1).

    /*=== INDEX CREATION ===*/
    assign vindex = hb:index-information(1).

    if lookup("default",vindex) <= 0 
    then do:    
        put unformatted(
            substitute(
                "ADD INDEX &1 ON &2",
                    quoter(entry(01,vindex,",")),
                    quoter( hb:name ))) skip.

        if entry(02,vindex,",") = "1" 
        then put unformatted "UNIQUE" skip.

        if entry(03,vindex,",") = "1" 
        then put unformatted "PRIMARY" skip.

        do vi = 5 to 20 by 2:
            if num-entries(vindex,",") > vi 
            then put unformatted "INDEX-FIELD " entry(vi,vindex,",") " " (if entry(vi + 1,vindex,",") = "0" then "ASCENDING" else "DESCENDING") skip.
        end.   
    end.
    /*=== INDEX CREATION ===*/

    put unformatted skip(1).
output close.

To make it work, just call this code on a program.p.

run createDF.p(input table nameOfYourTempTable).

CREATE TABLE new_table AS (SELECT * FROM tt);

Just replace the new_table with the table name you want to give

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top