You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Decimal precision lost in some columns after upgrade to sling==1.4.12 #636
Description
After upgrading to sling==1.4.12, some numeric columns from Oracle sources lose decimal precision and are rounded to whole numbers. This only affects certain columns, while others keep the correct precision.
Impact
Downstream tools (e.g., reports, Excel extracts) show incorrect rounded values.
Business reporting accuracy is compromised for affected datasets.
Steps to Reproduce
Upgrade to sling==1.4.12.
Ingest Oracle data containing decimal fields (expected NUMBER(24,6)).
Observe that some columns are rounded to whole numbers instead of keeping decimals.
Expected Behavior
Decimal fields should retain their defined precision from the Oracle source.
Observed Behavior
Some columns lose decimals and display only whole numbers.
Issue appears inconsistent across columns.
Notes
Likely related to auto-profiling of data types not enforcing source definitions.
It would be useful to allow disabling auto-profiling so that source-defined types are applied consistently.
@SIVERTKRISTIANSEN thanks for reporting, this version is a bit old now (latest is 1.4.19).
Can you try with the latest version to see if you face the same issue?
Also, I will need some debug logs and the replication config. Can you give example of original values which are losing precision? What is the column type DDL in the target database?
There is a test specifically for this (created after your last issue: #584), which runs and need to pass before a new release. Here is the log for a new run:
84 | sling run -r cmd/sling/tests/replications/r.28.oracle_number_scale.yaml
2025-08-29 07:54:28 INF Sling CLI | https://slingdata.io
2025-08-29 07:54:28 DBG executing hook "start-01" (type: query)
2025-08-29 07:54:29 DBG CLI Pro token validated
2025-08-29 07:54:29 DBG opened "oracle" connection (conn-oracle-Jk9)
2025-08-29 07:54:29 DBG BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ORACLE.TEST_NUMBER_PRECISION PURGE';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END
2025-08-29 07:54:29 DBG successfully executed hook "start-01" (type: query)
2025-08-29 07:54:29 DBG executing hook "start-02" (type: query)
2025-08-29 07:54:29 DBG CREATE TABLE ORACLE.TEST_NUMBER_PRECISION (
id NUMBER,
-- NUMBER without precision/scale can store decimals
value_decimal NUMBER,
-- NUMBER(10,2) has explicit scale
value_explicit NUMBER(10,2),
-- NUMBER(10) has scale of 0
value_integer NUMBER(10)
)
2025-08-29 07:54:29 DBG successfully executed hook "start-02" (type: query)
2025-08-29 07:54:29 DBG executing hook "start-03" (type: query)
2025-08-29 07:54:29 DBG INSERT INTO ORACLE.TEST_NUMBER_PRECISION (id, value_decimal, value_explicit, value_integer)
VALUES (1, 0.01233, 0.01, 10)
2025-08-29 07:54:29 DBG successfully executed hook "start-03" (type: query)
2025-08-29 07:54:29 DBG executing hook "start-04" (type: query)
2025-08-29 07:54:29 DBG INSERT INTO ORACLE.TEST_NUMBER_PRECISION (id, value_decimal, value_explicit, value_integer)
VALUES (2, 123.456789, 123.45, 123)
2025-08-29 07:54:29 DBG successfully executed hook "start-04" (type: query)
2025-08-29 07:54:29 DBG executing hook "start-05" (type: query)
2025-08-29 07:54:29 DBG select column_name, data_type, data_precision, data_scale
from all_tab_columns
where owner = 'ORACLE'
and table_name = 'TEST_NUMBER_PRECISION'
and column_name = 'VALUE_DECIMAL'
2025-08-29 07:54:30 DBG successfully executed hook "start-05" (type: query)
2025-08-29 07:54:30 INF Checking Oracle metadata for VALUE_DECIMAL column:
metadata_check => [{"column_name":"VALUE_DECIMAL","data_precision":null,"data_scale":null,"data_type":"NUMBER"}]
data_scale =>
2025-08-29 07:54:30 DBG executing hook "start-07" (type: check)
2025-08-29 07:54:30 DBG successfully executed hook "start-07" (type: check)
2025-08-29 07:54:30 DBG executing hook "start-08" (type: query)
2025-08-29 07:54:32 DBG opened "snowflake" connection (conn-snowflake-lqa)
2025-08-29 07:54:34 DBG drop table if exists public.test_number_precision
2025-08-29 07:54:34 DBG successfully executed hook "start-08" (type: query)
2025-08-29 07:54:34 INF Sling Replication | ORACLE -> SNOWFLAKE | ORACLE.TEST_NUMBER_PRECISION
2025-08-29 07:54:34 DBG Sling version: dev (darwin arm64)
2025-08-29 07:54:34 DBG type is db-db
2025-08-29 07:54:34 DBG using: {"columns":null,"mode":"full-refresh","select":null,"transforms":null}
2025-08-29 07:54:34 DBG using source options: {"empty_as_null":false,"datetime_format":"AUTO","max_decimals":-1}
2025-08-29 07:54:34 DBG using target options: {"datetime_format":"auto","file_max_rows":0,"max_decimals":-1,"use_bulk":true,"add_new_columns":true,"adjust_column_type":false,"column_casing":"normalize"}
2025-08-29 07:54:34 INF connecting to source database (oracle)
2025-08-29 07:54:34 DBG opened "oracle" connection (conn-oracle-2nR)
2025-08-29 07:54:34 INF connecting to target database (snowflake)
2025-08-29 07:54:35 DBG opened "snowflake" connection (conn-snowflake-Vo6)
2025-08-29 07:54:38 INF reading from source database
2025-08-29 07:54:38 DBG select * from "ORACLE"."TEST_NUMBER_PRECISION"
2025-08-29 07:54:38 DBG applying column casing (normalize) for target type (snowflake)
2025-08-29 07:54:38 INF writing to target database [mode: full-refresh]
2025-08-29 07:54:39 DBG drop table if exists "PUBLIC"."TEST_NUMBER_PRECISION_TMP"
2025-08-29 07:54:39 DBG table "PUBLIC"."TEST_NUMBER_PRECISION_TMP" dropped
2025-08-29 07:54:40 DBG create transient table "PUBLIC"."TEST_NUMBER_PRECISION_TMP" ("ID" integer,
"VALUE_DECIMAL" decimal(24,6),
"VALUE_EXPLICIT" decimal(10,2),
"VALUE_INTEGER" integer)
2025-08-29 07:54:41 INF created table "PUBLIC"."TEST_NUMBER_PRECISION_TMP"
2025-08-29 07:54:41 INF streaming data
2025-08-29 07:54:42 DBG CREATE STAGE IF NOT EXISTS "PUBLIC"."SLING_STAGING"
2025-08-29 07:54:43 DBG USE SCHEMA PUBLIC
2025-08-29 07:54:43 DBG opened "file" connection (conn-file-tW6)
2025-08-29 07:54:43 DBG writing to file:///var/folders/49/1zc24t595j79t5mw7_t9gtxr0000gn/T/snowflake/put/public.test_number_precision_tmp/2025-08-29T075443.753/part.01 [fileRowLimit=500000 fileBytesLimit=300000000 compression=zstd concurrency=7 useBufferedStream=false fileFormat=csv singleFile=false]
2025-08-29 07:54:43 DBG REMOVE @"PUBLIC"."SLING_STAGING"/public.test_number_precision_tmp/2025-08-29T075443.753
2025-08-29 07:54:44 DBG PUT 'file:///var/folders/49/1zc24t595j79t5mw7_t9gtxr0000gn/T/snowflake/put/public.test_number_precision_tmp/2025-08-29T075443.753/part.01.0001.csv.zst' @"PUBLIC"."SLING_STAGING"/public.test_number_precision_tmp/2025-08-29T075443.753 PARALLEL=10 AUTO_COMPRESS=FALSE
2025-08-29 07:54:46 DBG COPY INTO "PUBLIC"."TEST_NUMBER_PRECISION_TMP" ("ID", "VALUE_DECIMAL", "VALUE_EXPLICIT", "VALUE_INTEGER")
from (
select T.$1, T.$2, T.$3, T.$4
from @"PUBLIC"."SLING_STAGING"/public.test_number_precision_tmp/2025-08-29T075443.753 as T
)
FILE_FORMAT = (
TYPE = CSV
RECORD_DELIMITER = '\n'
ESCAPE_UNENCLOSED_FIELD = NONE
FIELD_OPTIONALLY_ENCLOSED_BY = '0x22'
EMPTY_FIELD_AS_NULL = FALSE
NULL_IF = '\\N'
SKIP_HEADER = 1
REPLACE_INVALID_CHARACTERS = TRUE
)
ON_ERROR = ABORT_STATEMENT
2025-08-29 07:54:48 DBG
+-------------------------------------------------------------------------------------------+--------+-------------+-------------+
| FILE | STATUS | ROWS_LOADED | ERRORS_SEEN |
+-------------------------------------------------------------------------------------------+--------+-------------+-------------+
| sling_staging/public.test_number_precision_tmp/2025-08-29T075443.753/part.01.0001.csv.zst | LOADED | 2 | 0 |
+-------------------------------------------------------------------------------------------+--------+-------------+-------------+
2025-08-29 07:54:48 DBG REMOVE @"PUBLIC"."SLING_STAGING"/public.test_number_precision_tmp/2025-08-29T075443.753
2025-08-29 07:54:49 DBG select count(*) cnt from "PUBLIC"."TEST_NUMBER_PRECISION_TMP"
2025-08-29 07:54:50 DBG drop table if exists "PUBLIC"."TEST_NUMBER_PRECISION"
2025-08-29 07:54:50 DBG table "PUBLIC"."TEST_NUMBER_PRECISION" dropped
2025-08-29 07:54:50 DBG create table "PUBLIC"."TEST_NUMBER_PRECISION" ("ID" integer,
"VALUE_DECIMAL" decimal(24,6),
"VALUE_EXPLICIT" decimal(10,2),
"VALUE_INTEGER" integer)
2025-08-29 07:54:51 INF created table "PUBLIC"."TEST_NUMBER_PRECISION"
2025-08-29 07:54:51 DBG insert into "PUBLIC"."TEST_NUMBER_PRECISION" ("ID", "VALUE_DECIMAL", "VALUE_EXPLICIT", "VALUE_INTEGER") select "ID" as "ID", "VALUE_DECIMAL" as "VALUE_DECIMAL", "VALUE_EXPLICIT" as "VALUE_EXPLICIT", "VALUE_INTEGER" as "VALUE_INTEGER" from "PUBLIC"."TEST_NUMBER_PRECISION_TMP"
2025-08-29 07:54:52 DBG inserted rows into "PUBLIC"."TEST_NUMBER_PRECISION" from temp table "PUBLIC"."TEST_NUMBER_PRECISION_TMP"
2025-08-29 07:54:52 INF inserted 2 rows into "PUBLIC"."TEST_NUMBER_PRECISION" in 18 secs [0 r/s] [63 B]
2025-08-29 07:54:52 DBG drop table if exists "PUBLIC"."TEST_NUMBER_PRECISION_TMP"
2025-08-29 07:54:53 DBG table "PUBLIC"."TEST_NUMBER_PRECISION_TMP" dropped
2025-08-29 07:54:54 DBG closed "snowflake" connection (conn-snowflake-Vo6)
2025-08-29 07:54:54 DBG closed "oracle" connection (conn-oracle-2nR)
2025-08-29 07:54:54 INF execution succeeded
2025-08-29 07:54:54 DBG executing hook "end-01" (type: query)
2025-08-29 07:54:54 DBG select * from public.test_number_precision order by id
2025-08-29 07:54:54 DBG successfully executed hook "end-01" (type: query)
2025-08-29 07:54:54 INF store.result =>
+----+---------------+----------------+---------------+
| ID | VALUE_DECIMAL | VALUE_EXPLICIT | VALUE_INTEGER |
+----+---------------+----------------+---------------+
| 1 | 0.012330 | 0.01 | 10 |
| 2 | 123.456789 | 123.45 | 123 |
+----+---------------+----------------+---------------+
store.result[0] => {"id":1,"value_decimal":"0.012330","value_explicit":"0.01","value_integer":10}
store.result[0].value_decimal => 0.012330
store.result[1] => {"id":2,"value_decimal":"123.456789","value_explicit":"123.45","value_integer":123}
store.result[1].value_decimal => 123.456789
2025-08-29 07:54:54 DBG executing hook "end-03" (type: check)
2025-08-29 07:54:54 DBG successfully executed hook "end-03" (type: check)
2025-08-29 07:54:54 DBG executing hook "end-04" (type: check)
2025-08-29 07:54:54 DBG successfully executed hook "end-04" (type: check)
2025-08-29 07:54:54 DBG executing hook "end-05" (type: check)
2025-08-29 07:54:54 DBG successfully executed hook "end-05" (type: check)
2025-08-29 07:54:54 DBG executing hook "end-06" (type: query)
2025-08-29 07:54:54 DBG BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ORACLE.TEST_NUMBER_PRECISION PURGE';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END
2025-08-29 07:54:54 DBG successfully executed hook "end-06" (type: query)
2025-08-29 07:54:54 DBG executing hook "end-07" (type: query)
2025-08-29 07:54:54 DBG drop table if exists public.test_number_precision
2025-08-29 07:54:55 DBG successfully executed hook "end-07" (type: query)
2025-08-29 07:54:55 DBG closed "snowflake" connection (conn-snowflake-lqa)
2025-08-29 07:54:55 DBG closed "oracle" connection (conn-oracle-Jk9)
Upgraded and re-tested on sling==1.4.19 — the issue persists: several Oracle numeric columns that should carry scale end up created/handled without scale at some stage, and decimals are effectively lost/rounded in downstream use. Now we have tested with version 1.4.4 and the newer versions. The 1.4.4 works perfectly fine.
Sling then logs type changes “integer → decimal” for those same columns (even though adjust_column_type: false):
column type change for SALE_DOM_AMOUNT (integer to decimal)
column type change for SALE_CURR_AMOUNT (integer to decimal)
column type change for DOM_OUTST_INTERVAL_0 (integer to decimal)
column type change for CURR_OUTST_INTERVAL_0 (integer to decimal)
... for _1/_2/_3/_4, etc.
Final target table DDL — many columns end up as NUMBER(38,10) (not the expected source scale like NUMBER(24,6)), and timestamps are also normalized:
Within a single run, the TMP table is created with inconsistent numeric types (some NUMBER(38,0) and some NUMBER(24,6)), and then Sling emits multiple “integer → decimal” adjustments despite adjust_column_type:false.
The final table types consolidate to NUMBER(38,10) for many fields, which differs from the Oracle column definitions (e.g., NUMBER(24,6)), and this mismatch appears to be the root of decimal handling issues we’re seeing in downstream tools.
What we can additionally provide (say the word and we’ll attach):
Full debug log from this run.
Oracle column metadata for affected columns (data_type, data_precision, data_scale).
SHOW CREATE TABLE / DESC TABLE for target (TMP and final) before/after run.
A few concrete source→target value examples illustrating decimal loss/rounding (sanitized).
Questions for guidance
Why does the TMP DDL assign NUMBER(38,0) to several fields that have scale at the Oracle source, while other fields in the same table become NUMBER(24,6)?
With max_decimals=38 and adjust_column_type=false, what is the expected type selection path? Should we ever see “integer → decimal” transitions logged?
Is there a recommended way to force strict preservation of source scale/precision from Oracle (e.g., a setting to bypass any auto-profiling/inference for numeric types)?
Hey @SIVERTKRISTIANSEN , can you try with the dev build for upcoming 1.4.20? There were some changes pushed to improve decimal logic. If you're using python, set the env var SLING_BINARY to the path of the binary so it can use it.
Furthermore, you should use column typing instead of max_decimals (that will give you more control over the DDL generated):
Activity
flarco commentedon Aug 29, 2025
@SIVERTKRISTIANSEN thanks for reporting, this version is a bit old now (latest is 1.4.19).
Can you try with the latest version to see if you face the same issue?
Also, I will need some debug logs and the replication config. Can you give example of original values which are losing precision? What is the column type DDL in the target database?
There is a test specifically for this (created after your last issue: #584), which runs and need to pass before a new release. Here is the log for a new run:
SIVERTKRISTIANSEN commentedon Sep 1, 2025
Thanks for the quick reply!
Status:
Upgraded and re-tested on sling==1.4.19 — the issue persists: several Oracle numeric columns that should carry scale end up created/handled without scale at some stage, and decimals are effectively lost/rounded in downstream use. Now we have tested with version 1.4.4 and the newer versions. The 1.4.4 works perfectly fine.
Replication config:
Run details (from --log-level=debug)
Sling: 1.4.19 (linux amd64)
Source options: {"empty_as_null":false,"datetime_format":"AUTO","max_decimals":38}
Target options: {"datetime_format":"auto","file_max_rows":0,"max_decimals":38,"use_bulk":true,"add_new_columns":true,"adjust_column_type":false,"column_casing":"normalize"}
Source query: select * from "IFSO"."TM_CREDIT_REP_MONTH"
Evidence from the same execution
Sling then logs type changes “integer → decimal” for those same columns (even though adjust_column_type: false):
Final target table DDL — many columns end up as NUMBER(38,10) (not the expected source scale like NUMBER(24,6)), and timestamps are also normalized:
What we believe is happening
Within a single run, the TMP table is created with inconsistent numeric types (some NUMBER(38,0) and some NUMBER(24,6)), and then Sling emits multiple “integer → decimal” adjustments despite adjust_column_type:false.
The final table types consolidate to NUMBER(38,10) for many fields, which differs from the Oracle column definitions (e.g., NUMBER(24,6)), and this mismatch appears to be the root of decimal handling issues we’re seeing in downstream tools.
What we can additionally provide (say the word and we’ll attach):
Full debug log from this run.
Oracle column metadata for affected columns (data_type, data_precision, data_scale).
SHOW CREATE TABLE / DESC TABLE for target (TMP and final) before/after run.
A few concrete source→target value examples illustrating decimal loss/rounding (sanitized).
Questions for guidance
Why does the TMP DDL assign NUMBER(38,0) to several fields that have scale at the Oracle source, while other fields in the same table become NUMBER(24,6)?
With max_decimals=38 and adjust_column_type=false, what is the expected type selection path? Should we ever see “integer → decimal” transitions logged?
Is there a recommended way to force strict preservation of source scale/precision from Oracle (e.g., a setting to bypass any auto-profiling/inference for numeric types)?
flarco commentedon Sep 1, 2025
Hey @SIVERTKRISTIANSEN , can you try with the dev build for upcoming 1.4.20? There were some changes pushed to improve decimal logic. If you're using python, set the env var
SLING_BINARYto the path of the binary so it can use it.Furthermore, you should use column typing instead of
max_decimals(that will give you more control over the DDL generated):flarco commentedon Sep 3, 2025
1.4.20 was released which should have fixed this. Closing, if the issue persists, feel free to re-open this issue.