{"id":14063365,"url":"https://github.com/pgspider/odbc_fdw","last_synced_at":"2025-07-29T15:32:45.818Z","repository":{"id":39753582,"uuid":"441097623","full_name":"pgspider/odbc_fdw","owner":"pgspider","description":"PostgreSQL Foreign-data Wrapper for ODBC","archived":false,"fork":true,"pushed_at":"2023-12-26T06:48:19.000Z","size":1576,"stargazers_count":2,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-08-13T07:04:46.096Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PLpgSQL","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"CartoDB/odbc_fdw","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pgspider.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-23T07:23:27.000Z","updated_at":"2023-05-15T08:39:24.000Z","dependencies_parsed_at":"2023-02-10T12:45:19.203Z","dependency_job_id":null,"html_url":"https://github.com/pgspider/odbc_fdw","commit_stats":null,"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgspider%2Fodbc_fdw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgspider%2Fodbc_fdw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgspider%2Fodbc_fdw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgspider%2Fodbc_fdw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pgspider","download_url":"https://codeload.github.com/pgspider/odbc_fdw/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228028322,"owners_count":17858313,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-13T07:03:18.108Z","updated_at":"2024-12-04T01:30:40.392Z","avatar_url":"https://github.com/pgspider.png","language":"PLpgSQL","funding_links":[],"categories":["PLpgSQL"],"sub_categories":[],"readme":"ODBC FDW for PostgreSQL 9.5+ \n============================\nThis PostgreSQL extension implements a Foreign Data Wrapper (FDW) for\nremote databases using Open Database Connectivity [ODBC](http://msdn.microsoft.com/en-us/library/ms714562(v=VS.85).aspx).\n\nThis code is based on [`odbc_fdw`][1]created by CARTO, Gunnar \"Nick\" Bluth and Zheng Yang.\n\nRequirements\n------------\n\nTo compile and install this extension, assuming a Linux OS,\nthe libraries and header files for ODBC and PostgreSQL are needed,\ne.g. in Ubuntu this can be provided by the `unixodbc-dev`\nand `postgresql-server-dev-9.5` system packages.\n\nTo make use of the extension ODBC drivers for the data sources to\nbe used must be installed in the system and reflected\nin the `/etc/odbcinst.ini` file.\n\nDriver requirements\n--------------------\n\n- odbc-postgresql: \u003e= 9.x\n- libmyodbc: \u003e=  5.1\n- FreeTDS: \u003e= 1.0\n- hive-odbc-native: \u003e= 2.1\n\nBuilding and Installing\n-----------------------\n\nThe extension can be built and installed with:\n\n```sh\nmake\nsudo make install\n```\n\nFeature\n-------\n#### Write-able FDW\nThe existing odbc FDWs are only read-only, this version provides the write capability.  \nThe user can now issue an insert, update, and delete statement for the foreign tables using the odbc_fdw. \n\n#### WHERE clause push-down\nThe odbc_fdw will push-down the foreign table where clause to the foreign server.  \nThe where condition on the foreign table will be executed on the foreign server,   \nhence there will be fewer rows to bring across to PostgreSQL.  \nThis is a performance feature.\n\n#### Column push-down\nThe existing odbc FDWs are fetching all the columns from the target foreign table.  \nThe latest version does the column push-down and only brings back the columns   \nthat are part of the select target list.  \nThis is a performance feature.\n\n#### Aggregate function push-down\nList of aggregate functions push-down:\n```\n  avg, bit_and, bit_or, count, max, min, stddev_pop, stddev_samp, sum, var_pop, var_samp,\n  sum(DISTINCT), avg(DISTINCT), max(DISTINCT), min(DISTINCT), count(DISTINCT)\n```\n\n#### Function push-down\nThe function can be push-down in WHERE clauses.\nList of builtin functions of PostgreSQL can be pushed-down:\n - Flow Control Functions:\n   ```\n   nullif\n   ```\n - Numeric functions:\n   ```\n   abs, acos, asin, atan, atan2, ceil, ceiling, cos, cot, degrees, div, exp, floor, ln, log, log10, mod,   \n   pow, power, radians, round, sign, sin, sqrt, tan,\n   ```\n - String functions:\n   ```\n   ascii, bit_length, char_length, character_length, concat, concat_ws, left, length, lower, lpad,   \n   octet_length, repeat, replace, reverse, right, rpad, position, regexp_replace, substr, substring,   \n   upper,\n   ```\n   - For `bit_length`: postgre's core will optimize `bit_length(str)` to `octet_length(str) * 8` and push it down to remote server.\n - Date and Time functions\n   ```\n   date\n   ```\n - Explicit cast functions:   \n   | Postgres explicit cast  |      ODBC coressponding syntax      |\n   |----------|:-------------|\n   |col::float4|CAST(col AS real)|\n   |col::date|CAST(col AS date)|\n   |col::time|CAST(col AS time)|\n\nUsage\n-----\n\nThe `OPTION` clause of the `CREATE SERVER`, `CREATE FOREIGN TABLE`\nand  `IMPORT FOREIGN SCHEMA` commands is used to define both\nthe ODBC attributes to define a connection to an ODBC data source\nand some additional parameters to specify the table or query that\nwill be accessed as a foreign table.\n\nThe following options to define ODBC attributes should be defined in\nthe server definition (`CREATE SERVER`).\n\noption   | description\n-------- | -----------\n`dsn`    | The Database Source Name of the foreign database system you're connecting to.\n`driver` | The name of the ODBC driver to use (needed if no dsn is used)\n\nAny other ODBC connection attribute is driver-dependent, and should be defined by\nan option named as the attribute prepended by the prefix `odbc_`.\nFor example `odbc_server`,   `odbc_port`, `odbc_uid`, `odbc_pwd`, etc.\n\nThe DSN and Driver can also be defined by the prefixed options\n`odbc_DSN`  and `odbc_DRIVER` repectively.\n\nThe odbc_ prefixed options can be defined either in the server, user mapping\nor foreign table statements.\n\nIf the ODBC driver requires case-sensitive attribute names, the\n`odbc_` option names will have to be quoted with double quotes (`\"\"`),\nfor example `OPTIONS ( \"odbc_SERVER\" '127.0.0.1' )`.\nAttributes `DSN`, `DRIVER`, `UID` and `PWD` are automatically uppercased\nand don't need quoting.\n\nIf an ODBC attribute value contains special characters such as `=` or `;`\nit will require quoting with curly braces (`{}`), for example:\nfor example `OPTIONS ( \"odbc_PWD\" '{xyz=abc}' )`.\n\nodbc_ option names may need to be quoted with \"\" if the driver\nrequires case-sensitive names (otherwise the names are passed as lowercase,\nexcept for UID \u0026 PWD)\nodbc_ option values may need to be quoted with {} if they contain\ncharacters such as =; ...\n(but PG driver doesn't seem to support them)\n(the driver name and DNS should always support this quoting, since they aren't\nhandled by the driver)\n\n\nUsually you'll want to define authentication-related attributes\nin a `CREATE USER MAPPING` statement, so that they are determined by\nthe connected PostgreSQL role, but that's not a requirement: any attribute\ncan be define in any of the statements; when a foreign table is access\nthe SERVER, USER MAPPING and FOREIGN TABLE options will be combined\nto produce an ODBC connection string.\n\nThe next options are used to define the table or query to connect a\nforeign table to. They should be defined either in `CREATE FOREIGN TABLE`\nor `IMPORT FOREIGN SCHEMA` statements:\n\noption     | description\n---------- | -----------\n`schema`   | The schema of the database to query.\n`table`    | The name of the table to query. Also the name of the foreign table to create in the case of queries.\n`sql_query`| Optional: User defined SQL statement for querying the foreign table(s). This overrides the `table` parameters. This should use the syntax of ODBC driver used.\n`sql_count`| Optional: User defined SQL statement for counting number of records in the foreign table(s). This should use the syntax of ODBC driver used.\n`prefix`   | For IMPORT FOREIGN SCHEMA: a prefix for foreign table names. This can be used to prepend a prefix to the names of tables imported from an external database.\n\nNote that if the `prefix` option is used and only one specific foreign table is to be imported,\nthe `table` option is necessary (to specify the unprefixed, remote table name). In this case\nit is better not to include a `LIMIT TO` clause (otherwise it has to reference the *prefixed* table name).\n\nThe below options are used with a column in `CREATE FOREIGN TABLE` or `IMPORT FOREIGN SCHEMA` statements:\n\noption     | description\n---------- | -----------\n`column`   | The name of column to query. If this option is omitted, same name with the foreign table's is used.\n`key`      | The column with this option identifies each record in a table like primary keys.\n\nExample\n-------\n\nAssuming that the `odbc_fdw` is installed and available\nin your database (`CREATE EXTENSION odbc_fdw`), and that\nyou have a DNS `test` defined for some ODBC datasource which\nhas a table named `dblist` in a schema named `test`:\n\n```sql\nCREATE SERVER odbc_server\n  FOREIGN DATA WRAPPER odbc_fdw\n  OPTIONS (dsn 'test');\n\nCREATE FOREIGN TABLE\n  odbc_table (\n    id integer,\n    name varchar(255),\n    desc text,\n    users float4,\n    createdtime timestamp\n  )\n  SERVER odbc_server\n  OPTIONS (\n    odbc_DATABASE 'myplace',\n    schema 'test',\n    sql_query 'select description,id,name,created_datetime,sd,users from `test`.`dblist`',\n    sql_count 'select count(id) from `test`.`dblist`'\n  );\n\nCREATE USER MAPPING FOR postgres\n  SERVER odbc_server\n  OPTIONS (odbc_UID 'root', odbc_PWD '');\n```\n\nNote that no DSN is required; we can define connection attributes,\nincluding the name of the ODBC driver, individually:\n\n```sql\nCREATE SERVER odbc_server\n  FOREIGN DATA WRAPPER odbc_fdw\n  OPTIONS (\n    odbc_DRIVER 'MySQL',\n\todbc_SERVER '192.168.1.17',\n\tencoding 'iso88591'\n  );\n```\n\nThe need to know about the columns of the table(s) to be queried\nad its types can be obviated by using the `IMPORT FOREIGN SCHEMA`\nstatement. By using the same OPTIONS as for `CREATE FOREIGN TABLE`\nwe can import as a foreign table the results of an arbitrary\nquery performed through the ODBC driver:\n\n```sql\nIMPORT FOREIGN SCHEMA test\n  FROM SERVER odbc_server\n  INTO public\n  OPTIONS (\n    odbc_DATABASE 'myplace',\n    table 'odbc_table', -- this will be the name of the created foreign table\n    sql_query 'select description,id,name,created_datetime,sd,users from `test`.`dblist`'\n  );\n```\n\nIf you want to update tables, please add OPTIONS (key 'true') to a primary key or unique key like the following:\n\n```sql\nCREATE FOREIGN TABLE\n  odbc_table (\n    id integer OPTIONS (key 'true'),\n    name varchar(255),\n    desc text,\n    users float4,\n    createdtime timestamp\n  )\n  SERVER odbc_server\n  OPTIONS (\n    odbc_DATABASE 'myplace',\n    schema 'test',\n  );\n```\n\nLIMITATIONS\n-----------\n\n* Column, schema, table names should not be longer than the limit stablished by\n  PostgreSQL ([NAMEDATALEN](https://www.postgresql.org/docs/9.5/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS))\n* Only the following column types are currently fully suported:\n\n   type             | select | insert/update/delete\n   -----------------|--------|-------\n   SQL_CHAR         | x      | -\n   SQL_WCHAR        | x      | -\n   SQL_VARCHAR      | x      | x\n   SQL_WVARCHAR     | x      | -\n   SQL_LONGVARCHAR  | x      | -\n   SQL_WLONGVARCHAR | x      | -\n   SQL_DECIMAL      | x      | -\n   SQL_NUMERIC      | x      | x\n   SQL_INTEGER      | x      | x\n   SQL_REAL         | x      | -\n   SQL_FLOAT        | x      | -\n   SQL_DOUBLE       | x      | x\n   SQL_SMALLINT     | x      | x\n   SQL_TINYINT      | x      | -\n   SQL_BIGINT       | x      | x\n   SQL_DATE         | x      | x\n   SQL_TYPE_TIME    | x      | -\n   SQL_TIME         | x      | x\n   SQL_TIMESTAMP    | x      | x\n   SQL_GUID         | x      | -\n\n* Foreign encodings are supported with the  `encoding` option\n  for any enconding supported by PostgreSQL and compatible with the\n  local database. The encoding must be identified with the\n  name used by [PostgreSQL](https://www.postgresql.org/docs/9.5/static/multibyte.html).\n\n* Concatenation Operator\nThe `||` operator as a concatenation operator is standard SQL, however in MySQL, it represents the OR operator (logical operator)\nIf the PIPES_AS_CONCAT SQL mode is enabled, || signifies the SQL-standard string concatenation operator (like CONCAT()).\nUser needs to enable PIPES_AS_CONCAT mode in MySQL for concatenation.\n\n* Floating-point value comparison\nFloating-point numbers are approximate and not stored as exact values. A floating-point value as written in an SQL statement may not be the same as the value represented internally.\n\n   For example:\n\n   ```\n   SELECT float4.f1 FROM FLOAT4_TBL tbl06 WHERE float4.f1 \u003c\u003e '1004.3';\n        f1      \n   -------------\n              0\n         1004.3\n         -34.84\n    1.23457e+20\n    1.23457e-20\n   (5 rows)\n   ```\n   In order to get correct result, can decide on an acceptable tolerance for differences between the numbers and then do the comparison against the tolerance value to that can get the correct result.\n   ```\n   SELECT float4.f1 FROM tbl06 float4 WHERE float4.f1 \u003c\u003e '1004.3' GROUP BY float4.id, float4.f1 HAVING abs(f1 - 1004.3) \u003e 0.001 ORDER BY float4.id;\n        f1      \n   -------------\n              0\n         -34.84\n    1.23457e+20\n    1.23457e-20\n   (4 rows)\n   ```\n * Functions push-down:\n   * For `log`: Just push down `log(b, x)`, the `log(x)` does not push-down to remote server because of different functionality in the remote side (Mysql ODBC datasource)\n   * For `regexp_replace`: Just push-down `regexp_replace(source, pattern, eplacement_string)`, does not push-down the other signature of `regexp_replace` (these signatures is not support by Mysql ODBC datasource)\n\n* COPY and foreign partition routing not supported in odbc_fdw.\n\nNOTES\n-----------\n- ODBC FDW does not support \"infinity\" or \"-infinity\" values. Error message \"TIMESTAMP_NOT_FINITE\" will be shown.\n- For date or date time which has \"BC\" or \"AD\", ODBC FDW can not display the \"BC\" and \"AD\", only the date or date time part is displayed.\n- ODBC FDW does not accept NULL value as key column when UPDATE or DELETE. Error \"Value of key column is NULL\" will be shown.\n\n[1]:https://github.com/CartoDB/odbc_fdw\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpgspider%2Fodbc_fdw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpgspider%2Fodbc_fdw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpgspider%2Fodbc_fdw/lists"}