From b4449553e642b8ffd8b418f05ec882158ed4b35e Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Wed, 22 Apr 2020 16:53:39 -0400 Subject: [PATCH 01/10] Add extension, mime_type and drive_letter --- auditbeat/module/file_integrity/event.go | 21 ++++++ auditbeat/module/file_integrity/event_test.go | 20 +++++- auditbeat/module/file_integrity/mime.go | 53 +++++++++++++++ auditbeat/module/file_integrity/mime_test.go | 68 +++++++++++++++++++ go.mod | 1 + go.sum | 2 + 6 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 auditbeat/module/file_integrity/mime.go create mode 100644 auditbeat/module/file_integrity/mime_test.go diff --git a/auditbeat/module/file_integrity/event.go b/auditbeat/module/file_integrity/event.go index 61e9b214819..72c2c8db640 100644 --- a/auditbeat/module/file_integrity/event.go +++ b/auditbeat/module/file_integrity/event.go @@ -31,6 +31,7 @@ import ( "path/filepath" "runtime" "strconv" + "strings" "time" "github.com/cespare/xxhash/v2" @@ -214,6 +215,17 @@ func NewEvent( return NewEventFromFileInfo(path, info, err, action, source, maxFileSize, hashTypes) } +func getDriveLetter(path string) string { + volume := filepath.VolumeName(path) + if len(volume) == 2 && volume[1] == ':' { + letter := path[0] + if (letter >= 'a' && letter <= 'z') || (letter >= 'A' && letter <= 'Z') { + return strings.ToUpper(volume[:1]) + } + } + return "" +} + func buildMetricbeatEvent(e *Event, existedBefore bool) mb.Event { file := common.MapStr{ "path": e.Path, @@ -237,6 +249,12 @@ func buildMetricbeatEvent(e *Event, existedBefore bool) mb.Event { file["ctime"] = info.CTime if e.Info.Type == FileType { + if extension := filepath.Ext(e.Path); extension != "" { + file["extension"] = extension + } + if mimeType := getMimeType(e.Path); mimeType != "" { + file["mime_type"] = mimeType + } file["size"] = info.Size } @@ -245,6 +263,9 @@ func buildMetricbeatEvent(e *Event, existedBefore bool) mb.Event { } if runtime.GOOS == "windows" { + if drive := getDriveLetter(e.Path); drive != "" { + file["drive_letter"] = drive + } if info.SID != "" { file["uid"] = info.SID } diff --git a/auditbeat/module/file_integrity/event_test.go b/auditbeat/module/file_integrity/event_test.go index 1d20f1b3965..48831f5ac1e 100644 --- a/auditbeat/module/file_integrity/event_test.go +++ b/auditbeat/module/file_integrity/event_test.go @@ -37,7 +37,7 @@ var testEventTime = time.Now().UTC() func testEvent() *Event { return &Event{ Timestamp: testEventTime, - Path: "/home/user", + Path: "/home/user/file.txt", Source: SourceScan, Action: ConfigChange, Info: &Metadata{ @@ -292,6 +292,7 @@ func TestBuildEvent(t *testing.T) { assertHasKey(t, fields, "event.action") assertHasKey(t, fields, "file.path") + assertHasKey(t, fields, "file.extension") assertHasKey(t, fields, "file.target_path") assertHasKey(t, fields, "file.inode") assertHasKey(t, fields, "file.uid") @@ -312,6 +313,23 @@ func TestBuildEvent(t *testing.T) { assertHasKey(t, fields, "hash.sha1") assertHasKey(t, fields, "hash.sha256") }) + if runtime.GOOS == "windows" { + t.Run("drive letter", func(t *testing.T) { + e := testEvent() + e.Path = "c:\\Documents" + fields := buildMetricbeatEvent(e, false).MetricSetFields + value, err := fields.GetValue("file.drive_letter") + assert.NoError(t, err) + assert.Equal(t, "C", value) + }) + t.Run("no drive letter", func(t *testing.T) { + e := testEvent() + e.Path = "\\\\remote\\Documents" + fields := buildMetricbeatEvent(e, false).MetricSetFields + _, err := fields.GetValue("file.drive_letter") + assert.Error(t, err) + }) + } t.Run("no setuid/setgid", func(t *testing.T) { e := testEvent() e.Info.SetGID = false diff --git a/auditbeat/module/file_integrity/mime.go b/auditbeat/module/file_integrity/mime.go new file mode 100644 index 00000000000..7c07138e00f --- /dev/null +++ b/auditbeat/module/file_integrity/mime.go @@ -0,0 +1,53 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package file_integrity + +import ( + "github.com/h2non/filetype" + + "github.com/elastic/beats/v7/libbeat/common/file" +) + +const ( + // Size for mime detection, office file + // detection requires ~8kb to detect properly + headerSize = 8192 +) + +// this does a best-effort to get the file type, if no +// filetype can be determined, it just returns an empty +// string +func getMimeType(path string) string { + f, err := file.ReadOpen(path) + if err != nil { + return "" + } + defer f.Close() + + head := make([]byte, headerSize) + n, err := f.Read(head) + if err != nil { + return "" + } + + kind, err := filetype.Match(head[:n]) + if err != nil { + return "" + } + return kind.MIME.Value +} diff --git a/auditbeat/module/file_integrity/mime_test.go b/auditbeat/module/file_integrity/mime_test.go new file mode 100644 index 00000000000..a4779c96fe8 --- /dev/null +++ b/auditbeat/module/file_integrity/mime_test.go @@ -0,0 +1,68 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package file_integrity + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +var mimeSamples = map[string][]byte{ + "docx": []byte("PK\x03\x04\x14\x00\b\b\b\x00\x13b\x96P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00word/numbering.xml\xa5\x93MN\xc30\x10\x85O\xc0\x1d\"\xef\xdb$\x15 \x145\xed\x82\n6\xec\x80\x03\xb8\x8e\x93X\xb5=\xd6\xd8I\xe8\xedq\x9b\xbfR$\x94\x86U\xe4\x8c\xdf\xf7\xc6\xe3\xe7\xf5\xf6K\u0260\xe6h\x05\xe8\x94\xc4\u02c8\x04\\3\u0204.R\xf2\xf9\xf1\xb2x\"\x81uTgT\x82\xe6)9rK\xb6\x9b\xbbu\x93\xe8J\xed9\xfa}\x81Gh\x9b(\x96\x92\xd29\x93\x84\xa1e%W\xd4.\xc1p\xed\x8b9\xa0\xa2\xce/\xb1\b\x15\xc5Ce\x16\f\x94\xa1N\xec\x85\x14\xee\x18\xae\xa2\xe8\x91t\x18HI\x85:\xe9\x10\v%\x18\x82\x85\u071d$\t\xe4\xb9`\xbc\xfb\xf4\n\x9c\xe2\xdbJv\xc0*\u0175;;\x86\u0225\xef\x01\xb4-\x85\xb1=M\u0365\xf9b\xd9C\xea\xbf\x0eQ+\xd9\xefk\xcc\x14\xb7\fi\xe3\xe7\xacdk\xd4\x00f\x06\x81qk\xfd\xdf][\x1c\x88q4a\x80'\u0120\x98\xd2\xc2O\u03fe\x13E\x85\x1e0\xa7t\\\x81\x06\xef\xa5\xf7\xee\x86vF\x8d\a\x19ga\xe5\x94F\xda\u049b\xd8#\xc5\xe3\xef.\xe8\x8cy^\ua358\x94\xe2+\x82W\xb9\n\x87@\xceA\xb0\x92\xa2\xeb\x01r\x0eA\x02;\xf0\xec\x99\xea\x9a\x0ea\u038aIq\xbe\"e\x82\x16H\xd5\x18R{\xd3\xcd\xc6\xd1U\\\xdeKj\xf8H+\xfeG{E\xa8\xcc\x18\xf7\xfb9\xb4\x8b\x17\x18?\xdc\x06X\xf5\x80p\xf3\rPK\a\bI\x13C\u007fh\x01\x00\x00=\x05\x00\x00PK\x03\x04\x14\x00\b\b\b\x00\x13b\x96P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00word/settings.xml\xa5\x95\xcdn\xdb0\f\u01df`\xef\x10\xe8\x9e\xf8\xa3I6\x18uzX\xb1\xed\xb0\x9e\xd2=\x00#\u0276\x10}A\x92\xe3\xe5\xed'\u01d6\u0564@\xe1f\xa7H\u007f\x92?\xd2\fM?>\xfd\x15|q\xa2\xc62%K\x94\xadR\xb4\xa0\x12+\xc2d]\xa2?\xaf?\x96\xdf\xd0\xc2:\x90\x04\xb8\x92\xb4Dgj\xd1\xd3\xee\xcbcWX\xea\x9c\xf7\xb2\vO\x90\xb6\x10\xb8D\x8ds\xbaH\x12\x8b\x1b*\xc0\xae\x94\xa6\xd2\x1b+e\x048\u007f5u\"\xc0\x1c[\xbd\xc4Jhp\xec\xc08s\xe7$O\xd3-\x1a1\xaaD\xad\x91\u0148X\n\x86\x8d\xb2\xaar}H\xa1\xaa\x8aa:\xfe\x84\b3'\xef\x10\xf2\xacp+\xa8t\x97\x8c\x89\xa1\xdc\u05e0\xa4m\x98\xb6\x81&\xee\xa5yc\x13 \xa7\x8f\x1e\xe2$x\xf0\xeb\xf4\x9cl\xc4@\xe7\x1b-\xf8\x90\xa8S\x86h\xa30\xb5\u05ab\u03c3q\"f\xe9\x8c\x06\xf6\x88)bN\t\xd79C%\x02\x98\x9c0\xfdp\u0700\xa6\xdc+\x9f{l\xda\x05\x15\x1f$\xf6\xc2\xf29\x85\f\xa6\xdf\xec`\xc0\x9c\xdfW\x01w\xf4\xf3m\xbcf\xb3\xa6\xf8\x86\xe0\xa3\\k\xa6\x81\xbc\a\x81\x1b0.\x00\xf8=\x04\xae\xf0\x91\x92\xef O0\r3\xa9g\x8d\xf3\r\x890\xa8\r\x888\xa4\xf6S\xffl\x96\u078c\u02fe\x01M#\xad\xfe?\xdaO\xa3Z\x1d\xc7}}\x0f\xed\xcd\x1b\x98m>\a\xc8\x03`\xe7W \xa1\x15\xb4\u073d\xc2a\xef\x94^t\xc5\t\xfc\x14\u007f\xcdS\x94\xf4\xe6a\xcb\xc5\xd3~\u0618\xc1/\xdb \u007f\x94 \xfc\x9bs\xb5\x10_\x14\xa1\xbd\xa95l~q}\xca\xe4*'7\xfb>\x88\xbe\x80\xd6C\xdaC\x9d\x95\x88\xb3\xbaqY\xcfw\xfeF\xfcB\xbe\\\x0eu>\xda\xf2\x8b-\x1fl\x97\v`\xec\xf7\x9c\xf7\x1e\x0fQ\u02c3\xf6\xc6\xef!h\x0fQ[\am\x1d\xb5M\xd06Q\xdb\x06m\xdbk\xcdYS\u00d9<\xfa6\x84c\xafW\x8as\xd5Q\xf2+\xda\xdfIc?\xc2Wj\xf7\x0fPK\a\b\x8e\xb3\u00e4\x05\x02\x00\x00\xea\x06\x00\x00PK\x03\x04\x14\x00\b\b\b\x00\x13b\x96P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00word/fontTable.xml\xa5\x94MN\xc30\x10\x85O\xc0\x1d\"\xef\u06e4\b\x10\x8a\x9aT\b\x04\x1bv\xc0\x01\x06\xc7I\xac\xda\x1ek\xec4\xf4\xf6\xb84?P$\x94\x86U\x94\x8c\xdf\xf7\xc6\xe3\x17\xaf7\x1fZE;AN\xa2\xc9\xd8j\x99\xb0H\x18\x8e\x854U\xc6\xde^\x1f\x17\xb7,r\x1eL\x01\n\x8d\xc8\xd8^8\xb6\xc9/\xd6mZ\xa2\xf1.\nr\xe3R\xcd3V{o\xd38v\xbc\x16\x1a\xdc\x12\xad0\xa1X\"i\xf0\u156aX\x03m\x1b\xbb\xe0\xa8-x\xf9.\x95\xf4\xfb\xf82InX\x87\xc1\x8c5d\xd2\x0e\xb1\u0412\x13:,\xfdA\x92bYJ.\xbaG\xaf\xa0)\xbeG\xc9\x03\xf2F\v\xe3\xbf\x1cc\x12*\xf4\x80\xc6\xd5\u04ba\x9e\xa6\xe7\xd2B\xb1\xee!\xbb\xbf6\xb1\u04ea_\xd7\xda)n\x05A\x1b\xceB\xab\xa3Q\x8bTXB.\x9c\v_\x1f\x8e\u0141\xb8J&\f\xf0\x80\x18\x14SZ\xf8\xe9\xd9w\xa2A\x9a\x01sH\xc6\th\xf0^\x06\xefnh_\xa8q#\xe3,\x9c\x9a\xd2\u0231\xf4,\xdf\th\xff\xbb\v\x981\xcf\xefz+'\xa5\xf8\x84\x10T\xbe\xa1!\x90s\x10\xbc\x06\xf2=@\xcd!(\xe4[Q\u0703\xd9\xc1\x10\u689a\x14\xe7\x13R!\xa1\"\xd0cH\xddY'\xbbJN\xe2\xf2R\x83\x15#\xad\xfa\x1f\ud270\xb1c\u072f\xe6\u043e\xfd\x81\xab\xeb\xf3\x00\x97= \xef\uefe8M\r\xe8\x10\xfe;\x92\xa0X\x9c\xaf\xe3\xeeb\xcc?\x01PK\a\b\xad\x87m\x00y\x01\x00\x00Z\x05\x00\x00PK\x03\x04\x14\x00\b\b\b\x00\x13b\x96P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00word/styles.xml\u0556\xedn\xda0\x14\x86\xaf`\xf7\x80\xf2\xbfMH\x02CQiU\xb5\xea6\xa9\ua9b5\xbb\x80\x83c\x88U\u01f6l\a\u02ae~\xce7$\xa1J\x03\x12\x1d\xfc\x00\x1f\xfb\xbc\xc7~\xfc:\xce\xd5\xcd[LGk,\x15\xe1ln\x8d/\x1dk\x84\x19\xe2!a\xab\xb9\xf5\xe7\xe5\xe1bf\x8d\x94\x06\x16\x02\xe5\f\u03ed-V\xd6\xcd\xf5\x97\xabM\xa0\xf4\x96b52\xf9L\x051\x9a[\x91\xd6\"\xb0m\x85\"\x1c\x83\xba\xe4\x023\u04f9\xe42\x06m\x9are\xc7 _\x13q\x81x,@\x93\x05\xa1Dom\xd7q\xa6V!\xc3\xe7V\"YPH\\\xc4\x04I\xae\xf8R\xa7)\x01_.\t\xc2\xc5O\x99!\xfb\xd4\xcdS\xee9Jb\xcctV\u0456\x98\x9a9p\xa6\"\"T\xa9\x16\x0fU3\x9dQ)\xb2~o\x11\ub616\xe36\xa2O\xb5P\xc2\xc6lFL\xf3B\x1b.C!9\xc2J\x99\xe8}\xdeY)\x8e\x9d\x1e\x00S\x89*\xa3\xcf\x14\xf6k\x963\x89\x81\xb0J&\xb5FC\xa8\xaa}ij\x17\xd02\xa9z!5\vE\xfbL$\xefz$\v\tr\u06de\x05\f\u0e5b/H/\x177\x14L\x96Nde\xc8!\x12(\x02\xa9K\x01:D\x81r\xf4\x8a\xc3;`k\xa8\xcc\x1c\xaez\u0679\xa1\x14\x12XI\x88k\x93\xaa\x0f\xed\xec\xd8i\xd8\xe59\x02\x81k\xb5\xd5qj\xdf$ODmw\u007f\x88\xda\xce\t\x1cO>&\xe0\x96\x02\xd7\xe6\x01\x18rt\x8f\x97\x90P\xad\u04a6\xfc%\x8bf\xd1\xca~\x1e8\xd3j\xb4\t@!B\xe6\u05ad$`\xcao\x02\xa4v\x1a\x18\x94\xbeU\x04vB\xd1-S\xd5x;\x95R\u007fMx\r\u6838n\x19\xb9S\xcd\x18\x05\xb6*c\x98\xa51\xbb\x98\x8c\u075c\xa2h\xb62M\x01\x88d\x12\x94\xa4\x87\xda\xfd:\xb5\x8a\xc6\uf11a\x00$\x9a\x17\xb2\xa2\x90\xdd\x15\xb2[\\\xb2{\xc2H\xe8\xad0\xe9\x02d\xea/\x11\xa5\xaaY\u05cfpn=\xa5~\xcc\xd6\x1d\xe6\x99\xe6*\xca\x183\x88q\xb9\x1c\x96\x0f\xcakg\xa9my\r\v\x8a\xf7\xa4_\xd2H/\xfdl\xe4\xe8\xa9G\x95\xeeE|\u01d0^\x9bm\xe1(\xef\x18\x8d\xf3-Z\x80\xc2\xe1OV\xf6\xd6\x05M\x16~\xd3]\xf1bs^1\x16O;C\n\xc14\xfch6H5\xe2\xf5^\xc2RcsS\x8e]'\x9d\xf1\x02\x9b\xf3o\x96\xe1;\xce\xfb{[\u0678\xf6\x9e\ufd3d\x97\xc7v|6\x04\x9b{\x10\x9b\xfb\u0270y\u04fe\xd8\x16\xa5\xb2\xd3<\xc2^\xc7\x11\xcecGb\xf4\x0eb\xf4\u038dq\xb6O\xd1\x1dJ\x11q\xcae\xe5=/\xfd\xb6\x9e\x90\xb3\x8e'\xe4\xec\x04x\xfd\x83x\xfd\u03c5\u05dd\xf5\u017b\x87s\x9a}Z8\xfd\x0e\x9c\xfe\tpN\x0e\xe2\x9c|2\x9c\xfe)q\x1e\xbc\xbf\x8f\xc49=\x88s\xfa\xbf\xe2$\r\xe1\xb3\xe0}!\u06bcU\xb4\xde\x17\xb2\u8679N\xf7\xb8~\xfc>\x9ft\xc0\x9a\x1c\x05\xeb9Y\xe8N^U\u01d9\x91y\xee f'|\x95\xafL\xddu\xa3u\x9b\xda\xebx\xef\xf2\x0e\xbcw\x95\xff\xd4\xf5?PK\a\b\x88\xceE\f\x1d\x03\x00\x00\xdf\x11\x00\x00PK\x03\x04\x14\x00\b\b\b\x00\x13b\x96P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00word/document.xml\xa5\x95Yn\xdb0\x10\x86O\xd0;\x18|\xb7%\x19N\x1b\b\x96\xf3P\xa3E\x81\xb60\xb2\x1c\x80&)\x89\b7\f)\xab\xee\xe9Kj\xf5\x12\x04\x8a\xeb\x17b\xb6o~\x91cr\xfd\xf0G\x8a\u0641\x81\xe5Ze(Y\xc4h\xc6\x14\u0454\xab\"C/\xcf\xdf\xe6\xf7hf\x1dV\x14\v\xadX\x86\x8e\u0322\x87\u0367u\x9dRM*\u0254\x9by\x82\xb2\xa9$\x19*\x9d3i\x14YR2\x89\xedB\x1b\xa6|0\xd7 \xb1\xf3&\x14\x91\xc4\xf0Z\x999\xd1\xd2`\xc7\xf7\\pw\x8c\x96q\xfc\x19u\x18\x9d\xa1\nT\xda!\xe6\x92\x13\xd0V\xe7.\x94\xa4:\xcf9a\xdd\xd2W\xc0\x94\xbem\u0276\x93\xdct\x8c\x80\t\xafA+[rc{\x9a\xbc\x95\xe6\x83e\x0f9\xbc\xf7\x11\a)\xfa\xbc\xdaL\xe9F\x01\xd7\xfe8\xa4h\x1b\xd5\x1a\xa8\x01M\x98\xb5\u07bbm\x83\x031\x89'l`@\f\x15S$\x9c\xf7\xec\x95H\xcc\u0540\t\xc3q\x01\x1az/|\xefn\xd3\x1a\xd4\xf8!\xe3^X1EH\x1b\xfa\xc9\xf7\x80\xe1x\xad\x02\u07f0\x9f\xa7\xf5\x86O\x9a\xe2\v\x82\xafr\x15\f\x03y\v\x82\x94\x18\\\x0f\x10\xb7\x10\x84&\xaf\x8c~\xc5\ua007a\xa6\u0164q\xbe Q\x8e\v\xc0r\x1cR\xfb\xa1\x93M\xe2\x8bqy*\xb1a#\xad\xf8?\xdaw\u0415\x19\xc7}u\v\xed\xe4\x1f\x98\xdc}\f\xb0\xec\x01\x1b\u007f\x05\xee5=\x86\xd5\xcc\xea\xd4\u07e0\xf41Cq\xf7C\x9dk\xcb\u0135sw\xedz\u0732\x1cW\u00bd\x11\xd9\xc1\x993Y\xa5\x06\x03\xfeA\ao\u04881;\b\v\xec \u06ac\xa3\xd1~O\xc8\x1b\x82\xcf\xdbu\xc4fq\u00a7\x1cp\xc0\xa0\xb6E\x13\tk\xdb0dYF\\\x9bo\x8a\xa7\xbf\xbe\xa0\xf4\xaf\xca\xdd\xfd\xaa\xe1\xfb\xbb&Y.WMyH\xf8\x85\x83\xba\xbdvN\xfbAMVm\x96\xd3f4\x04\xcb\xddh\x01/\xca\x13\xb3d\x982/\xf7\u02f21s\xad]ov\x1d~W\xf2\xf9h\x98\x0f\xfaG\fBi'\xbd\xd7\x19\xf5\xa7\x18\x8d/\xda\xe6\x1fPK\a\b@Z0\xeb\x17\x02\x00\x00\x16\a\x00\x00PK\x03\x04\x14\x00\b\b\b\x00\x13b\x96P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00word/_rels/document.xml.rels\xad\x92Mj\xc30\x10\x85O\xd0;\x88\xd9\u05f2\xd3\x1fJ\x89\x9cM\bd[\xdc\x03(\xf2\xf8\x87Z#!MJ}\xfb\x8a\x94$\x0e\x04\u04c5\x97\xef\x89y\xf3\u034c\u059b\x1f;\x88o\f\xb1w\xa4\xa0\xc8r\x10H\xc6\xd5=\xb5\n>\xab\xdd\xe3\x1b\x88\u021aj=8B\x05#F\u0614\x0f\xeb\x0f\x1c4\xa7\x9a\xd8\xf5>\x8a\x14BQA\xc7\xec\u07e5\x8c\xa6C\xabc\xe6\f\x93U\\\xac9\x88\xe7%!\xe8h\x0f\x18\xd2\xdcW\x88\x8b5\a\xf1\xb2\xe81x\x1cpz\x8a\x93>\xb7\x977\x9f\xbc\xfc\x05PK\a\b\x90\x00\xab\xeb\xf1\x00\x00\x00,\x03\x00\x00PK\x03\x04\x14\x00\b\b\b\x00\x13b\x96P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00_rels/.rels\x8d\xcf;\x0e\xc20\f\x06\xe0\x13p\x87\xc8;M\u02c0\x10j\xd2\x05!uE\xe5\x00Q\xe2\xa6\x11\xcdCIx\xf4\xf6d`\x00\xc4\xc0h\xfb\xf7g\xb9\xed\x1ev&7\x8c\xc9x\u01e0\xa9j \xe8\xa4W\xc6i\x06\xe7\xe1\xb8\xde\x01IY8%f\xef\x90\xc1\x82\t:\xbejO8\x8b\\v\xd2dB\"\x05q\x89\xc1\x94s\xd8S\x9a\xe4\x84V\xa4\xca\ate2\xfahE.e\xd44\by\x11\x1a\u99ae\xb74\xbe\x1b\xc0?L\xd2+\x06\xb1W\r\x90a\t\xf8\x8f\xed\xc7\xd1HV\xcbr-\xc2\xf7\xb8\xe8\x03 \v.V4Fj\x92\x90\x11\xf6\x00\xd7\u014c\x0e\x05M\x05\xe05\x82\xb5'\xf9\x92'\x17\x96RYHz\x82&\xaam}\x9c`\xa8\x88\x19\xe4\xe5\xb3\x1f_>{\x82\x8e\xee?=\xba\xff\xcb\u0443\aG\xf7\u007f6P]\xc3q\xa0S\xbd\xf8\xfe\x8b\xbf\x1f}\x8a\xfez\xf2\u074b\x87_\x99\xf1R\xc7\xff\xfe\xd3g\xbf\xfd\xfa\xa5\x19\xa8t\xe0\xf3\xaf\x1f\xff\xf1\xf4\xf1\xf3o>\xff\xf3\x87\x87\x06\xf8\x86\xc0C\x1d>\xa0\x11\x91\xe8&9@;<\x02\xc3\f\x02\xc8P\x9c\x8db\x10b\xaaSl\u0101\xc41Ni\f\xe8\x9e\n+\xe8\x9b\x13\u0330\x01\xd7!U\x0f\xde\x11\xd0\x02L\xc0\xab\xe3{\x15\x85wC1V\xd4\x00\xbc\x1eF\x15\xe0\x16\xe7\xac\u00c5\u0466\xeb\xa9,\xdd\v\xe380\v\x17c\x1d\xb7\x83\xf1\xbeIvw.\xbe\xbdq\x02\xb9LM,\xbb!\xa9\xa8\xb9\xcd \xe48 1Q(}\xc6\xf7\b1\x90\u0765\xb4\xe2\xd7-\xea\t.\xf9H\xa1\xbb\x14u05\xbad@\x87\xcaLt\x8dF\x10\x97\x89IA\x88w\xc57[wP\x873\x13\xfbM\xb2_EBU`fbIX\u014dW\xf1X\xe1\u02281\x8e\x98\x8e\xbc\x81UhRrw\"\xbc\x8a\u00e5\x82H\a\x84q\xd4\xf3\x89\x94&\x9a[bRQ\xf7:\xb4\x0es\u0637\xd8$\xaa\"\x85\xa2{&\xe4\r\u0339\x8e\xdc\xe4{\xdd\x10G\x89Qg\x1a\x87:\xf6#\xb9\a)\x8a\xd16WF%x\xb5B\xd29\xc4\x01\xc7K\xc3}\x87\x12u\xb6\u06beM\x83\u041c \u94f10\x95\x04\xe1\xd5z\x9c\xb0\x11&q\xd1\xe1+\xbd:\xa2\xf1q\x8d;\x82\xbe\x8d\u03fbqC\xab|\xfe\xed\xa3\xffQ\xcb\xde\x00'\x98jf\xbeQ/\xc3\u0377\xe7.\x17>}\xfb\xbb\xf3&\x1e\xc7\xdb\x04\n\xe2}s~\u07dc\xdf\xc5\u6f2c\x9e\u03ff%\u03fa\xb0\xad\x1f\xb436\xd1\xd2S\xf7\x882\xb6\xab&\x8c\u0710Y\xff\x96`\x9e\u07c7\xc5l\x92\x11\x95\x87\xfc$\x84a!\xae\x82\v\x04\xce\xc6Hp\xf5\tU\xe1n\x88\x13\x10\xe3d\x12\x02Y\xb0\x0e$J\xb8\x84\xab\x85\xb5\x94wv?\xa5`s\xb6\xe6N/\x95\x80\xc6j\x8b\xfb\xf9rC\xbfl\x96l\xb2Y uA\x8d\x94\xc1i\x855.\xbd\x9e0'\a\x9eR\x9a\u36a5\xb9\xc7J\xb35oB\xdd \x9c\xbeJpV\xea\xb9hH\x14\u0308\x9f\xfa=g0\r\xcb\x1b\f\x91S\xd3b\x14b\x9f\x18\x965\xfb\x9c\xc6\x1b\xf1\xa6{&%\xce\xc7\u0275\x05'\u06cb\xd5\xc4\xe2\xea\f\x1d\xb4\xadU\xb7\xeeZ\xc8\xc3I\xdb\x1a\xc1i\t\x86Q\x02\xfcd\xdai0\v\xe2\xb6\xe5\xa9\xdc\xc0\x93kq\xce\xe2UsV95w\x99\xc1\x15\x11\x89\x90j\x13\xcb0\xa7\xca\x1eM_\xa5\xc43\xfd\xebn3\xf5\xc3\xf9\x18`h&\xa7\u04e2\xd1r\xfeC-\xec\xf9\u0412\u0448xj\xc9\xcalZ<\xe3cE\xc4n\xe8\x1f\xa0!\x1b\x8b\x1d\fz7\xf3\xec\xf2\xa9\x84N_\x9fN\x04\xe4v\xb3H\xbcj\xe1\x16\xb51\xff\u02a6\xa8\x19\u0312\x10\x17\xd9\xde\xd2b\x9f\u00f3q\xa9C6\xd3\u0533\x97\xe8\xfe\x8a\xa64\xce\xd1\x14\xf7\xdd5%\xcd\\8\x9f6\xfc\xec\xd2\x04\xbb\xb8\xc0(\xcd\u0476\u0145\n9t\xa1$\xa4^_\xc0\xbe\x9f\xc9\x02\xbd\x10\x94E\xaa\x12b\xe9\v\xe8TW\xb2?\xeb[9\x8f\xbc\xc9\x05\xa1\u06a1\x01\x12\x14:\x9d\n\x05!\u06ea\xb0\xf3\x04fN]\xdf\x1e\xa7\x8c\x8a>S\xaa+\x93\xfcwH\xf6\t\x1b\xa4\u057b\x92\xdao\xa1p\xdaM\nGd\xb8\xf9\xa0\u0666\xea\x1a\x06\xfd\xb7\xf8\xe0\xd2|\xa5\x8dg&\xa8y\x96\u036f\xa95}m+X}=\x15N\xb3\x01k\xe2\xeaf\x8b\xeb\xee\u049dg~\xabM\xe0\x96\x81\xd2/h\xdcTxlv<\x1d\xf0\x1d\x88>*\xf7y\x04\x89x\xa1U\x94_\xb98\x04\x9d[\x9aq)\xab\u007f\xeb\x14\xd4Z\x12\xef\xf3<;j\xcen,q\xf6\xf1\xe2^\xdd\u066e\xc1\xd7\xee\xf1\xae\xb6\x17K\xd4\xd6\xee!\xd9l\xe1\x8f(>\xbc\a\xb27\xe1z3f\xf9\x8aL`\x96\x0f\xb6Ef\xf0\x90\xfb\x93b\xc8d\xde\x12rGL[:\x8bw\xc8\bQ\xffp\x1a\xd69\x8f\x16\xff\xf4\x94\x9b\xf9N. \xb5\xbd$l\x9cLX\xe0g\x9bHI\\?\x99\xb8\xa4\x98\xde\xf1J\xe2\xec\x16gb\xc0f\x92s|\x1e\xe5\xb2E\x96\x9eb\xf1\xeb\xb8\xec\x14\u029b]f\xcc\xde\u04fa\xec\x14\x81z\x05\x97\xa9\xc3\xe3]Vx\xca6%\x1e9T\x02w\xa7\u007f]A\xfe\u06b3\x94]\xff\aPK\a\b!Z\xa2\x84,\x06\x00\x00\xdb\x1d\x00\x00PK\x03\x04\x14\x00\b\b\b\x00\x13b\x96P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00[Content_Types].xml\xb5\x93Mn\xc20\x10\x85O\xd0;D\xdeV\xc4\xd0EUU\x04\x16\xfdY\xb6]\xd0\x03\f\xce\x04\xac\xfaO\x9e\x81\xc2\xed;\t\x90\x05\x02\xa9\x95\x9a\x8de\xfb\u037c\xf7y$O\xe7;\xef\x8a-f\xb21TjR\x8eU\x81\xc1\xc4\u0686U\xa5>\x17\xaf\xa3\aU\x10C\xa8\xc1\u0140\x95\xda#\xa9\xf9\xecf\xba\xd8'\xa4B\x9a\x03Uj\u035c\x1e\xb5&\xb3F\x0fT\u0184A\x94&f\x0f,\u01fc\xd2\t\xcc\x17\xacP\u07cd\xc7\xf7\xda\xc4\xc0\x18x\u012d\x87\x9aM\x9f\xb1\x81\x8d\xe3\xe2\xe9p\xdfZW\nRr\xd6\x00\v\x97\x163U\xbc\xecD<`\xb6g\xfd\x8b\xbem\xa8\xcf`FG\x902\xa3\xebjhm\x13\u075e\a\x88Jm\u00bbL&\xdb\x1a\xff\x14\x11\x9b\xc6\x1a\xac\xa3\xd9xi)\xbfc\xaeS\x8e\x06\x89d\xa8\u0795\x84\u0332;\xa6~@\xe67\xf0b\xab\xdbJ}R\xcb\xe3#\x87A\xe0\xbd\xc3k\x00\x9d6h|#^\vX:\xbcL\xd0\u02c3B\x84\x8d_b\x96\xfde\x88^\x1e\x14\xa2W<\xd8p\x19\xa4/\xf9G\x0e\x96\x8fze\xf8\x9dtX'\xa7H\xdd\xfd\xf6\xd9\x0fPK\a\b3\xaf\x0f\xb7,\x01\x00\x00-\x04\x00\x00PK\x01\x02\x14\x00\x14\x00\b\b\b\x00\x13b\x96PI\x13C\u007fh\x01\x00\x00=\x05\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00word/numbering.xmlPK\x01\x02\x14\x00\x14\x00\b\b\b\x00\x13b\x96P\x8e\xb3\u00e4\x05\x02\x00\x00\xea\x06\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa8\x01\x00\x00word/settings.xmlPK\x01\x02\x14\x00\x14\x00\b\b\b\x00\x13b\x96P\xad\x87m\x00y\x01\x00\x00Z\x05\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xec\x03\x00\x00word/fontTable.xmlPK\x01\x02\x14\x00\x14\x00\b\b\b\x00\x13b\x96P\x88\xceE\f\x1d\x03\x00\x00\xdf\x11\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa5\x05\x00\x00word/styles.xmlPK\x01\x02\x14\x00\x14\x00\b\b\b\x00\x13b\x96P@Z0\xeb\x17\x02\x00\x00\x16\a\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\b\x00\x00word/document.xmlPK\x01\x02\x14\x00\x14\x00\b\b\b\x00\x13b\x96P\x90\x00\xab\xeb\xf1\x00\x00\x00,\x03\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00U\v\x00\x00word/_rels/document.xml.relsPK\x01\x02\x14\x00\x14\x00\b\b\b\x00\x13b\x96P-h\xcf\"\xb1\x00\x00\x00*\x01\x00\x00\v\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\f\x00\x00_rels/.relsPK\x01\x02\x14\x00\x14\x00\b\b\b\x00\x13b\x96P!Z\xa2\x84,\x06\x00\x00\xdb\x1d\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00z\r\x00\x00word/theme/theme1.xmlPK\x01\x02\x14\x00\x14\x00\b\b\b\x00\x13b\x96P3\xaf\x0f\xb7,\x01\x00\x00-\x04\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe9\x13\x00\x00[Content_Types].xmlPK\x05\x06\x00\x00\x00\x00\t\x00\t\x00B\x02\x00\x00V\x15\x00\x00\x00\x00"), + "elf": []byte("\u007fELF\x01\x01\x01\x00\x00\xb3*1\xc0@\u0340\x02\x00\x03\x00\x01\x00\x00\x00\t\x00 \x00 \x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x01\x00\x00\x00@\x00\x00\x00@\x00\x00\x00\x05\x00\x00\x00\x00\x10\x00\x00"), + "jpg": []byte("\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00`\x00`\x00\x00\xff\xdb\x00C\x00\b\x06\x06\a\x06\x05\b\a\a\a\t\t\b\n\f\x14\r\f\v\v\f\x19\x12\x13\x0f\x14\x1d\x1a\x1f\x1e\x1d\x1a\x1c\x1c $.' \",#\x1c\x1c(7),01444\x1f'9=82<.342\xff\xdb\x00C\x01\t\t\t\f\v\f\x18\r\r\x182!\x1c!22222222222222222222222222222222222222222222222222\xff\xc0\x00\x11\b\x00\x01\x00\x01\x03\x01\"\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\a\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\f\x03\x01\x00\x02\x11\x03\x11\x00?\x00\xbf\x80\x0f\xff\xd9"), + "gif": []byte("GIF89a\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\xff\xff\xff!\xf9\x04\x01\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x01D\x00;"), + "png": []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\b\x04\x00\x00\x00\xb5\x1c\f\x02\x00\x00\x00\vIDATx\xdacd`\x00\x00\x00\x06\x00\x020\x81\xd0/\x00\x00\x00\x00IEND\xaeB`\x82"), +} + +func TestGetMimeType(t *testing.T) { + tests := []struct { + extension string + expected string + }{ + {"docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, + {"elf", "application/x-executable"}, + {"jpg", "image/jpeg"}, + {"gif", "image/gif"}, + {"png", "image/png"}, + } + + dir, err := ioutil.TempDir("", "mime-samples") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + for extension, sample := range mimeSamples { + samplePath := filepath.Join(dir, "sample."+extension) + if err := ioutil.WriteFile(samplePath, sample, 0700); err != nil { + t.Fatal(err) + } + } + + for _, test := range tests { + t.Run(test.extension, func(t *testing.T) { + samplePath := filepath.Join(dir, "sample."+test.extension) + assert.Equal(t, test.expected, getMimeType(samplePath)) + }) + } +} diff --git a/go.mod b/go.mod index 8c593491feb..92e086c40ad 100644 --- a/go.mod +++ b/go.mod @@ -93,6 +93,7 @@ require ( github.com/gorilla/mux v1.7.2 // indirect github.com/gorilla/websocket v1.4.1 // indirect github.com/grpc-ecosystem/grpc-gateway v1.13.0 // indirect + github.com/h2non/filetype v1.0.12 github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874 github.com/hashicorp/golang-lru v0.5.2-0.20190520140433-59383c442f7d // indirect github.com/insomniacslk/dhcp v0.0.0-20180716145214-633285ba52b2 diff --git a/go.sum b/go.sum index 5c8338626cc..1d13f1a6c16 100644 --- a/go.sum +++ b/go.sum @@ -383,6 +383,8 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.13.0 h1:sBDQoHXrOlfPobnKw69FIKa1wg9qsLLvvQ/Y19WtFgI= github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= +github.com/h2non/filetype v1.0.12 h1:yHCsIe0y2cvbDARtJhGBTD2ecvqMSTvlIcph9En/Zao= +github.com/h2non/filetype v1.0.12/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce h1:prjrVgOk2Yg6w+PflHoszQNLTUh4kaByUcEWM/9uin4= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874 h1:cAv7ZbSmyb1wjn6T4TIiyFCkpcfgpbcNNC3bM2srLaI= From 666a21893be8f5e5c36b93f1ec5d2fab99d9ba4b Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Mon, 27 Apr 2020 09:36:31 -0400 Subject: [PATCH 02/10] run go mod vendor --- .../godror/godror/odpi/CONTRIBUTING.md | 1 - .../github.com/godror/godror/odpi/LICENSE.md | 217 - .../github.com/godror/godror/odpi/README.md | 63 - .../godror/godror/odpi/embed/README.md | 3 - .../github.com/godror/godror/odpi/embed/dpi.c | 50 - .../godror/godror/odpi/include/dpi.h | 1814 -------- .../godror/godror/odpi/src/dpiConn.c | 2249 ---------- .../godror/godror/odpi/src/dpiContext.c | 329 -- .../godror/godror/odpi/src/dpiData.c | 899 ---- .../godror/godror/odpi/src/dpiDebug.c | 183 - .../godror/godror/odpi/src/dpiDeqOptions.c | 369 -- .../godror/godror/odpi/src/dpiEnqOptions.c | 173 - .../godror/godror/odpi/src/dpiEnv.c | 180 - .../godror/godror/odpi/src/dpiError.c | 222 - .../godror/godror/odpi/src/dpiErrorMessages.h | 90 - .../godror/godror/odpi/src/dpiGen.c | 307 -- .../godror/godror/odpi/src/dpiGlobal.c | 291 -- .../godror/godror/odpi/src/dpiHandleList.c | 116 - .../godror/godror/odpi/src/dpiHandlePool.c | 119 - .../godror/godror/odpi/src/dpiImpl.h | 1905 -------- .../godror/godror/odpi/src/dpiLob.c | 504 --- .../godror/godror/odpi/src/dpiMsgProps.c | 487 --- .../godror/godror/odpi/src/dpiObject.c | 966 ----- .../godror/godror/odpi/src/dpiObjectAttr.c | 114 - .../godror/godror/odpi/src/dpiObjectType.c | 344 -- .../godror/godror/odpi/src/dpiOci.c | 3823 ----------------- .../godror/godror/odpi/src/dpiOracleType.c | 504 --- .../godror/godror/odpi/src/dpiPool.c | 586 --- .../godror/godror/odpi/src/dpiQueue.c | 560 --- .../godror/godror/odpi/src/dpiRowid.c | 134 - .../godror/godror/odpi/src/dpiSodaColl.c | 812 ---- .../godror/odpi/src/dpiSodaCollCursor.c | 144 - .../godror/godror/odpi/src/dpiSodaDb.c | 431 -- .../godror/godror/odpi/src/dpiSodaDoc.c | 231 - .../godror/godror/odpi/src/dpiSodaDocCursor.c | 144 - .../godror/godror/odpi/src/dpiStmt.c | 1898 -------- .../godror/godror/odpi/src/dpiSubscr.c | 713 --- .../godror/godror/odpi/src/dpiUtils.c | 401 -- .../godror/godror/odpi/src/dpiVar.c | 1813 -------- .../github.com/h2non/filetype/.editorconfig | 12 + vendor/github.com/h2non/filetype/.gitignore | 2 + vendor/github.com/h2non/filetype/.travis.yml | 17 + vendor/github.com/h2non/filetype/History.md | 128 + vendor/github.com/h2non/filetype/LICENSE | 24 + vendor/github.com/h2non/filetype/README.md | 290 ++ vendor/github.com/h2non/filetype/filetype.go | 87 + vendor/github.com/h2non/filetype/go.mod | 3 + vendor/github.com/h2non/filetype/kind.go | 80 + vendor/github.com/h2non/filetype/match.go | 90 + .../h2non/filetype/matchers/application.go | 20 + .../h2non/filetype/matchers/archive.go | 234 + .../h2non/filetype/matchers/audio.go | 75 + .../h2non/filetype/matchers/document.go | 184 + .../h2non/filetype/matchers/font.go | 45 + .../h2non/filetype/matchers/image.go | 143 + .../filetype/matchers/isobmff/isobmff.go | 37 + .../h2non/filetype/matchers/matchers.go | 51 + .../h2non/filetype/matchers/video.go | 145 + .../h2non/filetype/types/defaults.go | 4 + .../github.com/h2non/filetype/types/mime.go | 14 + .../github.com/h2non/filetype/types/split.go | 11 + .../github.com/h2non/filetype/types/type.go | 16 + .../github.com/h2non/filetype/types/types.go | 18 + vendor/github.com/h2non/filetype/version.go | 4 + vendor/github.com/tsg/go-daemon/src/god.c | 313 -- .../github.com/yuin/gopher-lua/parse/Makefile | 4 + .../yuin/gopher-lua/parse/parser.go.y | 524 +++ vendor/modules.txt | 5 + 68 files changed, 2267 insertions(+), 24502 deletions(-) delete mode 100644 vendor/github.com/godror/godror/odpi/CONTRIBUTING.md delete mode 100644 vendor/github.com/godror/godror/odpi/LICENSE.md delete mode 100644 vendor/github.com/godror/godror/odpi/README.md delete mode 100644 vendor/github.com/godror/godror/odpi/embed/README.md delete mode 100644 vendor/github.com/godror/godror/odpi/embed/dpi.c delete mode 100644 vendor/github.com/godror/godror/odpi/include/dpi.h delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiConn.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiContext.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiData.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiDebug.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiDeqOptions.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiEnqOptions.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiEnv.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiError.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiErrorMessages.h delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiGen.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiGlobal.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiHandleList.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiHandlePool.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiImpl.h delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiLob.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiMsgProps.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiObject.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiObjectAttr.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiObjectType.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiOci.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiOracleType.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiPool.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiQueue.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiRowid.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSodaColl.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSodaCollCursor.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSodaDb.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSodaDoc.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSodaDocCursor.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiStmt.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSubscr.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiUtils.c delete mode 100644 vendor/github.com/godror/godror/odpi/src/dpiVar.c create mode 100644 vendor/github.com/h2non/filetype/.editorconfig create mode 100644 vendor/github.com/h2non/filetype/.gitignore create mode 100644 vendor/github.com/h2non/filetype/.travis.yml create mode 100644 vendor/github.com/h2non/filetype/History.md create mode 100644 vendor/github.com/h2non/filetype/LICENSE create mode 100644 vendor/github.com/h2non/filetype/README.md create mode 100644 vendor/github.com/h2non/filetype/filetype.go create mode 100644 vendor/github.com/h2non/filetype/go.mod create mode 100644 vendor/github.com/h2non/filetype/kind.go create mode 100644 vendor/github.com/h2non/filetype/match.go create mode 100644 vendor/github.com/h2non/filetype/matchers/application.go create mode 100644 vendor/github.com/h2non/filetype/matchers/archive.go create mode 100644 vendor/github.com/h2non/filetype/matchers/audio.go create mode 100644 vendor/github.com/h2non/filetype/matchers/document.go create mode 100644 vendor/github.com/h2non/filetype/matchers/font.go create mode 100644 vendor/github.com/h2non/filetype/matchers/image.go create mode 100644 vendor/github.com/h2non/filetype/matchers/isobmff/isobmff.go create mode 100644 vendor/github.com/h2non/filetype/matchers/matchers.go create mode 100644 vendor/github.com/h2non/filetype/matchers/video.go create mode 100644 vendor/github.com/h2non/filetype/types/defaults.go create mode 100644 vendor/github.com/h2non/filetype/types/mime.go create mode 100644 vendor/github.com/h2non/filetype/types/split.go create mode 100644 vendor/github.com/h2non/filetype/types/type.go create mode 100644 vendor/github.com/h2non/filetype/types/types.go create mode 100644 vendor/github.com/h2non/filetype/version.go delete mode 100644 vendor/github.com/tsg/go-daemon/src/god.c create mode 100644 vendor/github.com/yuin/gopher-lua/parse/Makefile create mode 100644 vendor/github.com/yuin/gopher-lua/parse/parser.go.y diff --git a/vendor/github.com/godror/godror/odpi/CONTRIBUTING.md b/vendor/github.com/godror/godror/odpi/CONTRIBUTING.md deleted file mode 100644 index 272ff94f74a..00000000000 --- a/vendor/github.com/godror/godror/odpi/CONTRIBUTING.md +++ /dev/null @@ -1 +0,0 @@ -Sorry, Pull Requests for ODPI-C cannot be accepted. Please report bugs and ask questions using [GitHub issues](https://github.com/oracle/odpi/issues) diff --git a/vendor/github.com/godror/godror/odpi/LICENSE.md b/vendor/github.com/godror/godror/odpi/LICENSE.md deleted file mode 100644 index cb344b76c16..00000000000 --- a/vendor/github.com/godror/godror/odpi/LICENSE.md +++ /dev/null @@ -1,217 +0,0 @@ -Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved. - -This program is free software: you can modify it and/or redistribute it under -the terms of: - -(i) the Universal Permissive License v 1.0 or at your option, any - later version (); and/or - -(ii) the Apache License v 2.0. () - - -The Universal Permissive License (UPL), Version 1.0 -=================================================== - -Subject to the condition set forth below, permission is hereby granted to any -person obtaining a copy of this software, associated documentation and/or data -(collectively the "Software"), free of charge and under any and all copyright -rights in the Software, and any and all patent rights owned or freely -licensable by each licensor hereunder covering either (i) the unmodified -Software as contributed to or provided by such licensor, or (ii) the Larger -Works (as defined below), to deal in both - -(a) the Software, and - -(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if - one is included with the Software (each a "Larger Work" to which the - Software is contributed by such licensors), - -without restriction, including without limitation the rights to copy, create -derivative works of, display, perform, and distribute the Software and make, -use, sell, offer for sale, import, export, have made, and have sold the -Software and the Larger Work(s), and to sublicense the foregoing rights on -either these or other terms. - -This license is subject to the following condition: - -The above copyright notice and either this complete permission notice or at a -minimum a reference to the UPL must be included in all copies or substantial -portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -Apache License -============== - -Version 2.0, January 2004 - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. **Definitions**. - - "License" shall mean the terms and conditions for use, reproduction, and - distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by the - copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all other - entities that control, are controlled by, or are under common control with - that entity. For the purposes of this definition, "control" means (i) the - power, direct or indirect, to cause the direction or management of such - entity, whether by contract or otherwise, or (ii) ownership of fifty - percent (50%) or more of the outstanding shares, or (iii) beneficial - ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity exercising - permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation source, - and configuration files. - - "Object" form shall mean any form resulting from mechanical transformation - or translation of a Source form, including but not limited to compiled - object code, generated documentation, and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or Object form, - made available under the License, as indicated by a copyright notice that - is included in or attached to the work (an example is provided in the - Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object form, - that is based on (or derived from) the Work and for which the editorial - revisions, annotations, elaborations, or other modifications represent, as - a whole, an original work of authorship. For the purposes of this License, - Derivative Works shall not include works that remain separable from, or - merely link (or bind by name) to the interfaces of, the Work and Derivative - Works thereof. - - "Contribution" shall mean any work of authorship, including the original - version of the Work and any modifications or additions to that Work or - Derivative Works thereof, that is intentionally submitted to Licensor for - inclusion in the Work by the copyright owner or by an individual or Legal - Entity authorized to submit on behalf of the copyright owner. For the - purposes of this definition, "submitted" means any form of electronic, - verbal, or written communication sent to the Licensor or its - representatives, including but not limited to communication on electronic - mailing lists, source code control systems, and issue tracking systems that - are managed by, or on behalf of, the Licensor for the purpose of discussing - and improving the Work, but excluding communication that is conspicuously - marked or otherwise designated in writing by the copyright owner as "Not a - Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity on - behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. **Grant of Copyright License.** Subject to the terms and conditions of this - License, each Contributor hereby grants to You a perpetual, worldwide, - non-exclusive, no-charge, royalty-free, irrevocable copyright license to - reproduce, prepare Derivative Works of, publicly display, publicly perform, - sublicense, and distribute the Work and such Derivative Works in Source or - Object form. - -3. **Grant of Patent License.** Subject to the terms and conditions of this - License, each Contributor hereby grants to You a perpetual, worldwide, - non-exclusive, no-charge, royalty-free, irrevocable (except as stated in - this section) patent license to make, have made, use, offer to sell, sell, - import, and otherwise transfer the Work, where such license applies only to - those patent claims licensable by such Contributor that are necessarily - infringed by their Contribution(s) alone or by combination of their - Contribution(s) with the Work to which such Contribution(s) was submitted. - If You institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work or a - Contribution incorporated within the Work constitutes direct or - contributory patent infringement, then any patent licenses granted to You - under this License for that Work shall terminate as of the date such - litigation is filed. - -4. **Redistribution.** You may reproduce and distribute copies of the Work or - Derivative Works thereof in any medium, with or without modifications, and - in Source or Object form, provided that You meet the following conditions: - - 1. You must give any other recipients of the Work or Derivative Works a - copy of this License; and - - 2. You must cause any modified files to carry prominent notices stating - that You changed the files; and - - 3. You must retain, in the Source form of any Derivative Works that You - distribute, all copyright, patent, trademark, and attribution notices - from the Source form of the Work, excluding those notices that do not - pertain to any part of the Derivative Works; and - - 4. If the Work includes a "NOTICE" text file as part of its distribution, - then any Derivative Works that You distribute must include a readable - copy of the attribution notices contained within such NOTICE file, - excluding those notices that do not pertain to any part of the - Derivative Works, in at least one of the following places: within a - NOTICE text file distributed as part of the Derivative Works; within - the Source form or documentation, if provided along with the Derivative - Works; or, within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents of the - NOTICE file are for informational purposes only and do not modify the - License. You may add Your own attribution notices within Derivative - Works that You distribute, alongside or as an addendum to the NOTICE - text from the Work, provided that such additional attribution notices - cannot be construed as modifying the License. - - You may add Your own copyright statement to Your modifications and may - provide additional or different license terms and conditions for use, - reproduction, or distribution of Your modifications, or for any such - Derivative Works as a whole, provided Your use, reproduction, and - distribution of the Work otherwise complies with the conditions stated - in this License. - -5. **Submission of Contributions.** Unless You explicitly state otherwise, any - Contribution intentionally submitted for inclusion in the Work by You to - the Licensor shall be under the terms and conditions of this License, - without any additional terms or conditions. Notwithstanding the above, - nothing herein shall supersede or modify the terms of any separate license - agreement you may have executed with Licensor regarding such Contributions. - -6. **Trademarks.** This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, except - as required for reasonable and customary use in describing the origin of - the Work and reproducing the content of the NOTICE file. - -7. **Disclaimer of Warranty.** Unless required by applicable law or agreed to - in writing, Licensor provides the Work (and each Contributor provides its - Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied, including, without limitation, any - warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or - FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for - determining the appropriateness of using or redistributing the Work and - assume any risks associated with Your exercise of permissions under this - License. - -8. **Limitation of Liability.** In no event and under no legal theory, whether - in tort (including negligence), contract, or otherwise, unless required by - applicable law (such as deliberate and grossly negligent acts) or agreed to - in writing, shall any Contributor be liable to You for damages, including - any direct, indirect, special, incidental, or consequential damages of any - character arising as a result of this License or out of the use or - inability to use the Work (including but not limited to damages for loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor has been - advised of the possibility of such damages. - -9. **Accepting Warranty or Additional Liability.** While redistributing the - Work or Derivative Works thereof, You may choose to offer, and charge a fee - for, acceptance of support, warranty, indemnity, or other liability - obligations and/or rights consistent with this License. However, in - accepting such obligations, You may act only on Your own behalf and on Your - sole responsibility, not on behalf of any other Contributor, and only if - You agree to indemnify, defend, and hold each Contributor harmless for any - liability incurred by, or claims asserted against, such Contributor by - reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS diff --git a/vendor/github.com/godror/godror/odpi/README.md b/vendor/github.com/godror/godror/odpi/README.md deleted file mode 100644 index fa911cc2130..00000000000 --- a/vendor/github.com/godror/godror/odpi/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# ODPI-C version 3.3 - -Oracle Database Programming Interface for C (ODPI-C) is an open source library -of C code that simplifies access to Oracle Database for applications written in -C or C++. It is a wrapper over [Oracle Call Interface -(OCI)](http://www.oracle.com/technetwork/database/features/oci/index.html) that -makes applications and language interfaces easier to develop. - -ODPI-C supports basic and advanced features of Oracle Database and -Oracle Client. See the [homepage](https://oracle.github.io/odpi/) for -a list. - -## Installation - -See [ODPI-C Installation](https://oracle.github.io/odpi/doc/installation.html). - -## Documentation - -See the [ODPI-C Documentation](https://oracle.github.io/odpi/doc/index.html) and -[Release Notes](https://oracle.github.io/odpi/doc/releasenotes.html). - -## Samples - -See [/samples](https://github.com/oracle/odpi/tree/master/samples). - -## Help - -Please report bugs and ask questions using [GitHub issues](https://github.com/oracle/odpi/issues). - -## Tests - -See [/test](https://github.com/oracle/odpi/tree/master/test). - -## Contributing - -See [CONTRIBUTING](https://github.com/oracle/odpi/blob/master/CONTRIBUTING.md). - -## Drivers Using ODPI-C - -Oracle Drivers: -* [cx_Oracle](https://oracle.github.io/python-cx_Oracle) Python interface. -* [node-oracledb](https://oracle.github.io/node-oracledb) Node.js module. - -Third-party Drivers: -* [go-goracle](https://gopkg.in/goracle.v2) Go Driver. -* [mirmir](https://github.com/rustyhorde/mimir) Rust Bindings. -* [odpic-raw](https://github.com/leptonyu/odpic-raw) Haskell Raw Bindings. -* [ruby-ODPI ](https://github.com/kubo/ruby-odpi) Ruby Interface. -* [rust-oracle ](https://github.com/kubo/rust-oracle) Driver for Rust. -* [Oracle.jl](https://github.com/felipenoris/Oracle.jl) Driver for Julia. -* [oranif](https://github.com/K2InformaticsGmbH/oranif) Driver for Erlang. - -## License - -Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. - -This program is free software: you can modify it and/or redistribute it under -the terms of: - -(i) the Universal Permissive License v 1.0 or at your option, any - later version (); and/or - -(ii) the Apache License v 2.0. () diff --git a/vendor/github.com/godror/godror/odpi/embed/README.md b/vendor/github.com/godror/godror/odpi/embed/README.md deleted file mode 100644 index dfe0b4524c0..00000000000 --- a/vendor/github.com/godror/godror/odpi/embed/README.md +++ /dev/null @@ -1,3 +0,0 @@ -This directory contains the file dpi.c which can be used to embed ODPI-C -within your project without having to manage the individual files that make up -the library. The files can also be compiled independently if that is preferred. diff --git a/vendor/github.com/godror/godror/odpi/embed/dpi.c b/vendor/github.com/godror/godror/odpi/embed/dpi.c deleted file mode 100644 index 7d0c6dc83bb..00000000000 --- a/vendor/github.com/godror/godror/odpi/embed/dpi.c +++ /dev/null @@ -1,50 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpi.c -// Include this file in your project in order to embed ODPI-C source without -// having to compile files individually. Only the definitions in the file -// include/dpi.h are intended to be used publicly. Each file can also be -// compiled independently if that is preferable. -//----------------------------------------------------------------------------- - -#include "../src/dpiConn.c" -#include "../src/dpiContext.c" -#include "../src/dpiData.c" -#include "../src/dpiDebug.c" -#include "../src/dpiDeqOptions.c" -#include "../src/dpiEnqOptions.c" -#include "../src/dpiEnv.c" -#include "../src/dpiError.c" -#include "../src/dpiGen.c" -#include "../src/dpiGlobal.c" -#include "../src/dpiHandleList.c" -#include "../src/dpiHandlePool.c" -#include "../src/dpiLob.c" -#include "../src/dpiMsgProps.c" -#include "../src/dpiObjectAttr.c" -#include "../src/dpiObject.c" -#include "../src/dpiObjectType.c" -#include "../src/dpiOci.c" -#include "../src/dpiOracleType.c" -#include "../src/dpiPool.c" -#include "../src/dpiQueue.c" -#include "../src/dpiRowid.c" -#include "../src/dpiSodaColl.c" -#include "../src/dpiSodaCollCursor.c" -#include "../src/dpiSodaDb.c" -#include "../src/dpiSodaDoc.c" -#include "../src/dpiSodaDocCursor.c" -#include "../src/dpiStmt.c" -#include "../src/dpiSubscr.c" -#include "../src/dpiUtils.c" -#include "../src/dpiVar.c" diff --git a/vendor/github.com/godror/godror/odpi/include/dpi.h b/vendor/github.com/godror/godror/odpi/include/dpi.h deleted file mode 100644 index 58b3a2d5867..00000000000 --- a/vendor/github.com/godror/godror/odpi/include/dpi.h +++ /dev/null @@ -1,1814 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpi.h -// Master include file for ODPI-C library. -//----------------------------------------------------------------------------- - -#ifndef DPI_PUBLIC -#define DPI_PUBLIC - -// define standard integer types for older versions of Microsoft Visual Studio -#ifdef _MSC_VER -#if _MSC_VER < 1600 -#define int8_t signed __int8 -#define int16_t signed __int16 -#define int32_t signed __int32 -#define int64_t signed __int64 -#define uint8_t unsigned __int8 -#define uint16_t unsigned __int16 -#define uint32_t unsigned __int32 -#define uint64_t unsigned __int64 -#endif -#endif - -#ifndef int8_t -#include -#endif - -// define __func__ for older versions of Microsoft Visual Studio -#ifdef _MSC_VER -#if _MSC_VER < 1900 -#define __func__ __FUNCTION__ -#endif -#endif - -// define ODPI-C version information -#define DPI_MAJOR_VERSION 3 -#define DPI_MINOR_VERSION 3 -#define DPI_PATCH_LEVEL 0 -#define DPI_VERSION_SUFFIX - -#define DPI_STR_HELPER(x) #x -#define DPI_STR(x) DPI_STR_HELPER(x) -#define DPI_VERSION_STRING \ - DPI_STR(DPI_MAJOR_VERSION) "." \ - DPI_STR(DPI_MINOR_VERSION) "." \ - DPI_STR(DPI_PATCH_LEVEL) \ - DPI_VERSION_SUFFIX -#define DPI_DEFAULT_DRIVER_NAME "ODPI-C : " DPI_VERSION_STRING - -#define DPI_VERSION_TO_NUMBER(major, minor, patch) \ - ((major * 10000) + (minor * 100) + patch) -#define DPI_VERSION_NUMBER \ - DPI_VERSION_TO_NUMBER(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, \ - DPI_PATCH_LEVEL) - -#define DPI_ORACLE_VERSION_TO_NUMBER(versionNum, releaseNum, updateNum, \ - portReleaseNum, portUpdateNum) \ - ((versionNum * 100000000) + (releaseNum * 1000000) + \ - (updateNum * 10000) + (portReleaseNum * 100) + (portUpdateNum)) - -// define default array size to use -#define DPI_DEFAULT_FETCH_ARRAY_SIZE 100 - -// define ping interval (in seconds) used when getting connections -#define DPI_DEFAULT_PING_INTERVAL 60 - -// define ping timeout (in milliseconds) used when getting connections -#define DPI_DEFAULT_PING_TIMEOUT 5000 - -// define constants for dequeue wait (AQ) -#define DPI_DEQ_WAIT_NO_WAIT 0 -#define DPI_DEQ_WAIT_FOREVER ((uint32_t) -1) - -// define maximum precision that can be supported by an int64_t value -#define DPI_MAX_INT64_PRECISION 18 - -// define constants for success and failure of methods -#define DPI_SUCCESS 0 -#define DPI_FAILURE -1 - -// set debug level (DPI_DEBUG_LEVEL) as a bitmask of desired flags -// reporting is to stderr -// 0x0001: reports errors during free -// 0x0002: reports on reference count changes -// 0x0004: reports on public function calls -// 0x0008: reports on all errors -// 0x0010: reports on all SQL statements -// 0x0020: reports on all memory allocations/frees -#define DPI_DEBUG_LEVEL_FREES 0x0001 -#define DPI_DEBUG_LEVEL_REFS 0x0002 -#define DPI_DEBUG_LEVEL_FNS 0x0004 -#define DPI_DEBUG_LEVEL_ERRORS 0x0008 -#define DPI_DEBUG_LEVEL_SQL 0x0010 -#define DPI_DEBUG_LEVEL_MEM 0x0020 - - -//----------------------------------------------------------------------------- -// Enumerations -//----------------------------------------------------------------------------- - - -// connection/pool authorization modes -typedef uint32_t dpiAuthMode; -#define DPI_MODE_AUTH_DEFAULT 0x00000000 -#define DPI_MODE_AUTH_SYSDBA 0x00000002 -#define DPI_MODE_AUTH_SYSOPER 0x00000004 -#define DPI_MODE_AUTH_PRELIM 0x00000008 -#define DPI_MODE_AUTH_SYSASM 0x00008000 -#define DPI_MODE_AUTH_SYSBKP 0x00020000 -#define DPI_MODE_AUTH_SYSDGD 0x00040000 -#define DPI_MODE_AUTH_SYSKMT 0x00080000 -#define DPI_MODE_AUTH_SYSRAC 0x00100000 - -// connection close modes -typedef uint32_t dpiConnCloseMode; -#define DPI_MODE_CONN_CLOSE_DEFAULT 0x0000 -#define DPI_MODE_CONN_CLOSE_DROP 0x0001 -#define DPI_MODE_CONN_CLOSE_RETAG 0x0002 - -// connection/pool creation modes -typedef uint32_t dpiCreateMode; -#define DPI_MODE_CREATE_DEFAULT 0x00000000 -#define DPI_MODE_CREATE_THREADED 0x00000001 -#define DPI_MODE_CREATE_EVENTS 0x00000004 - -// dequeue modes for advanced queuing -typedef uint32_t dpiDeqMode; -#define DPI_MODE_DEQ_BROWSE 1 -#define DPI_MODE_DEQ_LOCKED 2 -#define DPI_MODE_DEQ_REMOVE 3 -#define DPI_MODE_DEQ_REMOVE_NO_DATA 4 - -// dequeue navigation flags for advanced queuing -typedef uint32_t dpiDeqNavigation; -#define DPI_DEQ_NAV_FIRST_MSG 1 -#define DPI_DEQ_NAV_NEXT_TRANSACTION 2 -#define DPI_DEQ_NAV_NEXT_MSG 3 - -// event types -typedef uint32_t dpiEventType; -#define DPI_EVENT_NONE 0 -#define DPI_EVENT_STARTUP 1 -#define DPI_EVENT_SHUTDOWN 2 -#define DPI_EVENT_SHUTDOWN_ANY 3 -#define DPI_EVENT_DEREG 5 -#define DPI_EVENT_OBJCHANGE 6 -#define DPI_EVENT_QUERYCHANGE 7 -#define DPI_EVENT_AQ 100 - -// statement execution modes -typedef uint32_t dpiExecMode; -#define DPI_MODE_EXEC_DEFAULT 0x00000000 -#define DPI_MODE_EXEC_DESCRIBE_ONLY 0x00000010 -#define DPI_MODE_EXEC_COMMIT_ON_SUCCESS 0x00000020 -#define DPI_MODE_EXEC_BATCH_ERRORS 0x00000080 -#define DPI_MODE_EXEC_PARSE_ONLY 0x00000100 -#define DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS 0x00100000 - -// statement fetch modes -typedef uint16_t dpiFetchMode; -#define DPI_MODE_FETCH_NEXT 0x0002 -#define DPI_MODE_FETCH_FIRST 0x0004 -#define DPI_MODE_FETCH_LAST 0x0008 -#define DPI_MODE_FETCH_PRIOR 0x0010 -#define DPI_MODE_FETCH_ABSOLUTE 0x0020 -#define DPI_MODE_FETCH_RELATIVE 0x0040 - -// message delivery modes in advanced queuing -typedef uint16_t dpiMessageDeliveryMode; -#define DPI_MODE_MSG_PERSISTENT 1 -#define DPI_MODE_MSG_BUFFERED 2 -#define DPI_MODE_MSG_PERSISTENT_OR_BUFFERED 3 - -// message states in advanced queuing -typedef uint32_t dpiMessageState; -#define DPI_MSG_STATE_READY 0 -#define DPI_MSG_STATE_WAITING 1 -#define DPI_MSG_STATE_PROCESSED 2 -#define DPI_MSG_STATE_EXPIRED 3 - -// native C types -typedef uint32_t dpiNativeTypeNum; -#define DPI_NATIVE_TYPE_INT64 3000 -#define DPI_NATIVE_TYPE_UINT64 3001 -#define DPI_NATIVE_TYPE_FLOAT 3002 -#define DPI_NATIVE_TYPE_DOUBLE 3003 -#define DPI_NATIVE_TYPE_BYTES 3004 -#define DPI_NATIVE_TYPE_TIMESTAMP 3005 -#define DPI_NATIVE_TYPE_INTERVAL_DS 3006 -#define DPI_NATIVE_TYPE_INTERVAL_YM 3007 -#define DPI_NATIVE_TYPE_LOB 3008 -#define DPI_NATIVE_TYPE_OBJECT 3009 -#define DPI_NATIVE_TYPE_STMT 3010 -#define DPI_NATIVE_TYPE_BOOLEAN 3011 -#define DPI_NATIVE_TYPE_ROWID 3012 - -// operation codes (database change and continuous query notification) -typedef uint32_t dpiOpCode; -#define DPI_OPCODE_ALL_OPS 0x0 -#define DPI_OPCODE_ALL_ROWS 0x1 -#define DPI_OPCODE_INSERT 0x2 -#define DPI_OPCODE_UPDATE 0x4 -#define DPI_OPCODE_DELETE 0x8 -#define DPI_OPCODE_ALTER 0x10 -#define DPI_OPCODE_DROP 0x20 -#define DPI_OPCODE_UNKNOWN 0x40 - -// Oracle types -typedef uint32_t dpiOracleTypeNum; -#define DPI_ORACLE_TYPE_NONE 2000 -#define DPI_ORACLE_TYPE_VARCHAR 2001 -#define DPI_ORACLE_TYPE_NVARCHAR 2002 -#define DPI_ORACLE_TYPE_CHAR 2003 -#define DPI_ORACLE_TYPE_NCHAR 2004 -#define DPI_ORACLE_TYPE_ROWID 2005 -#define DPI_ORACLE_TYPE_RAW 2006 -#define DPI_ORACLE_TYPE_NATIVE_FLOAT 2007 -#define DPI_ORACLE_TYPE_NATIVE_DOUBLE 2008 -#define DPI_ORACLE_TYPE_NATIVE_INT 2009 -#define DPI_ORACLE_TYPE_NUMBER 2010 -#define DPI_ORACLE_TYPE_DATE 2011 -#define DPI_ORACLE_TYPE_TIMESTAMP 2012 -#define DPI_ORACLE_TYPE_TIMESTAMP_TZ 2013 -#define DPI_ORACLE_TYPE_TIMESTAMP_LTZ 2014 -#define DPI_ORACLE_TYPE_INTERVAL_DS 2015 -#define DPI_ORACLE_TYPE_INTERVAL_YM 2016 -#define DPI_ORACLE_TYPE_CLOB 2017 -#define DPI_ORACLE_TYPE_NCLOB 2018 -#define DPI_ORACLE_TYPE_BLOB 2019 -#define DPI_ORACLE_TYPE_BFILE 2020 -#define DPI_ORACLE_TYPE_STMT 2021 -#define DPI_ORACLE_TYPE_BOOLEAN 2022 -#define DPI_ORACLE_TYPE_OBJECT 2023 -#define DPI_ORACLE_TYPE_LONG_VARCHAR 2024 -#define DPI_ORACLE_TYPE_LONG_RAW 2025 -#define DPI_ORACLE_TYPE_NATIVE_UINT 2026 -#define DPI_ORACLE_TYPE_MAX 2027 - -// session pool close modes -typedef uint32_t dpiPoolCloseMode; -#define DPI_MODE_POOL_CLOSE_DEFAULT 0x0000 -#define DPI_MODE_POOL_CLOSE_FORCE 0x0001 - -// modes used when acquiring a connection from a session pool -typedef uint8_t dpiPoolGetMode; -#define DPI_MODE_POOL_GET_WAIT 0 -#define DPI_MODE_POOL_GET_NOWAIT 1 -#define DPI_MODE_POOL_GET_FORCEGET 2 -#define DPI_MODE_POOL_GET_TIMEDWAIT 3 - -// purity values when acquiring a connection from a pool -typedef uint32_t dpiPurity; -#define DPI_PURITY_DEFAULT 0 -#define DPI_PURITY_NEW 1 -#define DPI_PURITY_SELF 2 - -// database shutdown modes -typedef uint32_t dpiShutdownMode; -#define DPI_MODE_SHUTDOWN_DEFAULT 0 -#define DPI_MODE_SHUTDOWN_TRANSACTIONAL 1 -#define DPI_MODE_SHUTDOWN_TRANSACTIONAL_LOCAL 2 -#define DPI_MODE_SHUTDOWN_IMMEDIATE 3 -#define DPI_MODE_SHUTDOWN_ABORT 4 -#define DPI_MODE_SHUTDOWN_FINAL 5 - -// SODA flags -#define DPI_SODA_FLAGS_DEFAULT 0x00 -#define DPI_SODA_FLAGS_ATOMIC_COMMIT 0x01 -#define DPI_SODA_FLAGS_CREATE_COLL_MAP 0x02 -#define DPI_SODA_FLAGS_INDEX_DROP_FORCE 0x04 - -// database startup modes -typedef uint32_t dpiStartupMode; -#define DPI_MODE_STARTUP_DEFAULT 0 -#define DPI_MODE_STARTUP_FORCE 1 -#define DPI_MODE_STARTUP_RESTRICT 2 - -// statement types -typedef uint16_t dpiStatementType; -#define DPI_STMT_TYPE_UNKNOWN 0 -#define DPI_STMT_TYPE_SELECT 1 -#define DPI_STMT_TYPE_UPDATE 2 -#define DPI_STMT_TYPE_DELETE 3 -#define DPI_STMT_TYPE_INSERT 4 -#define DPI_STMT_TYPE_CREATE 5 -#define DPI_STMT_TYPE_DROP 6 -#define DPI_STMT_TYPE_ALTER 7 -#define DPI_STMT_TYPE_BEGIN 8 -#define DPI_STMT_TYPE_DECLARE 9 -#define DPI_STMT_TYPE_CALL 10 -#define DPI_STMT_TYPE_EXPLAIN_PLAN 15 -#define DPI_STMT_TYPE_MERGE 16 -#define DPI_STMT_TYPE_ROLLBACK 17 -#define DPI_STMT_TYPE_COMMIT 21 - -// subscription grouping classes -typedef uint8_t dpiSubscrGroupingClass; -#define DPI_SUBSCR_GROUPING_CLASS_TIME 1 - -// subscription grouping types -typedef uint8_t dpiSubscrGroupingType; -#define DPI_SUBSCR_GROUPING_TYPE_SUMMARY 1 -#define DPI_SUBSCR_GROUPING_TYPE_LAST 2 - -// subscription namespaces -typedef uint32_t dpiSubscrNamespace; -#define DPI_SUBSCR_NAMESPACE_AQ 1 -#define DPI_SUBSCR_NAMESPACE_DBCHANGE 2 - -// subscription protocols -typedef uint32_t dpiSubscrProtocol; -#define DPI_SUBSCR_PROTO_CALLBACK 0 -#define DPI_SUBSCR_PROTO_MAIL 1 -#define DPI_SUBSCR_PROTO_PLSQL 2 -#define DPI_SUBSCR_PROTO_HTTP 3 - -// subscription quality of service -typedef uint32_t dpiSubscrQOS; -#define DPI_SUBSCR_QOS_RELIABLE 0x01 -#define DPI_SUBSCR_QOS_DEREG_NFY 0x02 -#define DPI_SUBSCR_QOS_ROWIDS 0x04 -#define DPI_SUBSCR_QOS_QUERY 0x08 -#define DPI_SUBSCR_QOS_BEST_EFFORT 0x10 - -// visibility of messages in advanced queuing -typedef uint32_t dpiVisibility; -#define DPI_VISIBILITY_IMMEDIATE 1 -#define DPI_VISIBILITY_ON_COMMIT 2 - - -//----------------------------------------------------------------------------- -// Handle Types -//----------------------------------------------------------------------------- -typedef struct dpiConn dpiConn; -typedef struct dpiPool dpiPool; -typedef struct dpiStmt dpiStmt; -typedef struct dpiVar dpiVar; -typedef struct dpiLob dpiLob; -typedef struct dpiObject dpiObject; -typedef struct dpiObjectAttr dpiObjectAttr; -typedef struct dpiObjectType dpiObjectType; -typedef struct dpiRowid dpiRowid; -typedef struct dpiSubscr dpiSubscr; -typedef struct dpiDeqOptions dpiDeqOptions; -typedef struct dpiEnqOptions dpiEnqOptions; -typedef struct dpiMsgProps dpiMsgProps; - - -//----------------------------------------------------------------------------- -// Complex Native Data Types (used for transferring data to/from ODPI-C) -//----------------------------------------------------------------------------- - -// structure used for transferring byte strings to/from ODPI-C -typedef struct { - char *ptr; - uint32_t length; - const char *encoding; -} dpiBytes; - -// structure used for transferring day/seconds intervals to/from ODPI-C -typedef struct { - int32_t days; - int32_t hours; - int32_t minutes; - int32_t seconds; - int32_t fseconds; -} dpiIntervalDS; - -// structure used for transferring years/months intervals to/from ODPI-C -typedef struct { - int32_t years; - int32_t months; -} dpiIntervalYM; - -// structure used for transferring dates to/from ODPI-C -typedef struct { - int16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint32_t fsecond; - int8_t tzHourOffset; - int8_t tzMinuteOffset; -} dpiTimestamp; - - -//----------------------------------------------------------------------------- -// Other Types -//----------------------------------------------------------------------------- - -// forward declarations -typedef struct dpiAppContext dpiAppContext; -typedef struct dpiCommonCreateParams dpiCommonCreateParams; -typedef struct dpiConnCreateParams dpiConnCreateParams; -typedef struct dpiContext dpiContext; -typedef struct dpiData dpiData; -typedef struct dpiDataTypeInfo dpiDataTypeInfo; -typedef struct dpiEncodingInfo dpiEncodingInfo; -typedef struct dpiErrorInfo dpiErrorInfo; -typedef struct dpiObjectAttrInfo dpiObjectAttrInfo; -typedef struct dpiObjectTypeInfo dpiObjectTypeInfo; -typedef struct dpiPoolCreateParams dpiPoolCreateParams; -typedef struct dpiQueryInfo dpiQueryInfo; -typedef struct dpiQueue dpiQueue; -typedef struct dpiShardingKeyColumn dpiShardingKeyColumn; -typedef struct dpiSodaColl dpiSodaColl; -typedef struct dpiSodaCollNames dpiSodaCollNames; -typedef struct dpiSodaCollCursor dpiSodaCollCursor; -typedef struct dpiSodaDb dpiSodaDb; -typedef struct dpiSodaDoc dpiSodaDoc; -typedef struct dpiSodaDocCursor dpiSodaDocCursor; -typedef struct dpiSodaOperOptions dpiSodaOperOptions; -typedef struct dpiStmtInfo dpiStmtInfo; -typedef struct dpiSubscrCreateParams dpiSubscrCreateParams; -typedef struct dpiSubscrMessage dpiSubscrMessage; -typedef struct dpiSubscrMessageQuery dpiSubscrMessageQuery; -typedef struct dpiSubscrMessageRow dpiSubscrMessageRow; -typedef struct dpiSubscrMessageTable dpiSubscrMessageTable; -typedef struct dpiVersionInfo dpiVersionInfo; - -// union used for providing a buffer of any data type -typedef union { - int asBoolean; - int64_t asInt64; - uint64_t asUint64; - float asFloat; - double asDouble; - dpiBytes asBytes; - dpiTimestamp asTimestamp; - dpiIntervalDS asIntervalDS; - dpiIntervalYM asIntervalYM; - dpiLob *asLOB; - dpiObject *asObject; - dpiStmt *asStmt; - dpiRowid *asRowid; -} dpiDataBuffer; - -// structure used for application context -struct dpiAppContext { - const char *namespaceName; - uint32_t namespaceNameLength; - const char *name; - uint32_t nameLength; - const char *value; - uint32_t valueLength; -}; - -// structure used for common parameters used for creating standalone -// connections and session pools -struct dpiCommonCreateParams { - dpiCreateMode createMode; - const char *encoding; - const char *nencoding; - const char *edition; - uint32_t editionLength; - const char *driverName; - uint32_t driverNameLength; -}; - -// structure used for creating connections -struct dpiConnCreateParams { - dpiAuthMode authMode; - const char *connectionClass; - uint32_t connectionClassLength; - dpiPurity purity; - const char *newPassword; - uint32_t newPasswordLength; - dpiAppContext *appContext; - uint32_t numAppContext; - int externalAuth; - void *externalHandle; - dpiPool *pool; - const char *tag; - uint32_t tagLength; - int matchAnyTag; - const char *outTag; - uint32_t outTagLength; - int outTagFound; - dpiShardingKeyColumn *shardingKeyColumns; - uint8_t numShardingKeyColumns; - dpiShardingKeyColumn *superShardingKeyColumns; - uint8_t numSuperShardingKeyColumns; - int outNewSession; -}; - -// structure used for transferring data to/from ODPI-C -struct dpiData { - int isNull; - dpiDataBuffer value; -}; - -// structure used for providing metadata about data types -struct dpiDataTypeInfo { - dpiOracleTypeNum oracleTypeNum; - dpiNativeTypeNum defaultNativeTypeNum; - uint16_t ociTypeCode; - uint32_t dbSizeInBytes; - uint32_t clientSizeInBytes; - uint32_t sizeInChars; - int16_t precision; - int8_t scale; - uint8_t fsPrecision; - dpiObjectType *objectType; -}; - -// structure used for transferring encoding information from ODPI-C -struct dpiEncodingInfo { - const char *encoding; - int32_t maxBytesPerCharacter; - const char *nencoding; - int32_t nmaxBytesPerCharacter; -}; - -// structure used for transferring error information from ODPI-C -struct dpiErrorInfo { - int32_t code; - uint16_t offset; - const char *message; - uint32_t messageLength; - const char *encoding; - const char *fnName; - const char *action; - const char *sqlState; - int isRecoverable; -}; - -// structure used for transferring object attribute information from ODPI-C -struct dpiObjectAttrInfo { - const char *name; - uint32_t nameLength; - dpiDataTypeInfo typeInfo; -}; - -// structure used for transferring object type information from ODPI-C -struct dpiObjectTypeInfo { - const char *schema; - uint32_t schemaLength; - const char *name; - uint32_t nameLength; - int isCollection; - dpiDataTypeInfo elementTypeInfo; - uint16_t numAttributes; -}; - -// structure used for creating pools -struct dpiPoolCreateParams { - uint32_t minSessions; - uint32_t maxSessions; - uint32_t sessionIncrement; - int pingInterval; - int pingTimeout; - int homogeneous; - int externalAuth; - dpiPoolGetMode getMode; - const char *outPoolName; - uint32_t outPoolNameLength; - uint32_t timeout; - uint32_t waitTimeout; - uint32_t maxLifetimeSession; - const char *plsqlFixupCallback; - uint32_t plsqlFixupCallbackLength; - uint32_t maxSessionsPerShard; -}; - -// structure used for transferring query metadata from ODPI-C -struct dpiQueryInfo { - const char *name; - uint32_t nameLength; - dpiDataTypeInfo typeInfo; - int nullOk; -}; - -// structure used for sharding key columns -struct dpiShardingKeyColumn { - dpiOracleTypeNum oracleTypeNum; - dpiNativeTypeNum nativeTypeNum; - dpiDataBuffer value; -}; - -// structure used for getting collection names from the database -struct dpiSodaCollNames { - uint32_t numNames; - const char **names; - uint32_t *nameLengths; -}; - -// structure used for SODA operations (find/replace/remove) -struct dpiSodaOperOptions { - uint32_t numKeys; - const char **keys; - uint32_t *keyLengths; - const char *key; - uint32_t keyLength; - const char *version; - uint32_t versionLength; - const char *filter; - uint32_t filterLength; - uint32_t skip; - uint32_t limit; -}; - -// structure used for transferring statement information from ODPI-C -struct dpiStmtInfo { - int isQuery; - int isPLSQL; - int isDDL; - int isDML; - dpiStatementType statementType; - int isReturning; -}; - -// callback for subscriptions -typedef void (*dpiSubscrCallback)(void* context, dpiSubscrMessage *message); - -// structure used for creating subscriptions -struct dpiSubscrCreateParams { - dpiSubscrNamespace subscrNamespace; - dpiSubscrProtocol protocol; - dpiSubscrQOS qos; - dpiOpCode operations; - uint32_t portNumber; - uint32_t timeout; - const char *name; - uint32_t nameLength; - dpiSubscrCallback callback; - void *callbackContext; - const char *recipientName; - uint32_t recipientNameLength; - const char *ipAddress; - uint32_t ipAddressLength; - uint8_t groupingClass; - uint32_t groupingValue; - uint8_t groupingType; - uint64_t outRegId; - int clientInitiated; -}; - -// structure used for transferring messages in subscription callbacks -struct dpiSubscrMessage { - dpiEventType eventType; - const char *dbName; - uint32_t dbNameLength; - dpiSubscrMessageTable *tables; - uint32_t numTables; - dpiSubscrMessageQuery *queries; - uint32_t numQueries; - dpiErrorInfo *errorInfo; - const void *txId; - uint32_t txIdLength; - int registered; - const char *queueName; - uint32_t queueNameLength; - const char *consumerName; - uint32_t consumerNameLength; -}; - -// structure used for transferring query information in messages in -// subscription callbacks (continuous query notification) -struct dpiSubscrMessageQuery { - uint64_t id; - dpiOpCode operation; - dpiSubscrMessageTable *tables; - uint32_t numTables; -}; - -// structure used for transferring row information in messages in -// subscription callbacks -struct dpiSubscrMessageRow { - dpiOpCode operation; - const char *rowid; - uint32_t rowidLength; -}; - -// structure used for transferring table information in messages in -// subscription callbacks -struct dpiSubscrMessageTable { - dpiOpCode operation; - const char *name; - uint32_t nameLength; - dpiSubscrMessageRow *rows; - uint32_t numRows; -}; - -// structure used for transferring version information -struct dpiVersionInfo { - int versionNum; - int releaseNum; - int updateNum; - int portReleaseNum; - int portUpdateNum; - uint32_t fullVersionNum; -}; - - -//----------------------------------------------------------------------------- -// Context Methods (dpiContext) -//----------------------------------------------------------------------------- - -// create a context handle and validate the version information -int dpiContext_create(unsigned int majorVersion, unsigned int minorVersion, - dpiContext **context, dpiErrorInfo *errorInfo); - -// destroy context handle -int dpiContext_destroy(dpiContext *context); - -// return the OCI client version in use -int dpiContext_getClientVersion(const dpiContext *context, - dpiVersionInfo *versionInfo); - -// get error information -void dpiContext_getError(const dpiContext *context, dpiErrorInfo *errorInfo); - -// initialize context parameters to default values -int dpiContext_initCommonCreateParams(const dpiContext *context, - dpiCommonCreateParams *params); - -// initialize connection create parameters to default values -int dpiContext_initConnCreateParams(const dpiContext *context, - dpiConnCreateParams *params); - -// initialize pool create parameters to default values -int dpiContext_initPoolCreateParams(const dpiContext *context, - dpiPoolCreateParams *params); - -// initialize SODA operation options to default values -int dpiContext_initSodaOperOptions(const dpiContext *context, - dpiSodaOperOptions *options); - -// initialize subscription create parameters to default values -int dpiContext_initSubscrCreateParams(const dpiContext *context, - dpiSubscrCreateParams *params); - - -//----------------------------------------------------------------------------- -// Connection Methods (dpiConn) -//----------------------------------------------------------------------------- - -// add a reference to a connection -int dpiConn_addRef(dpiConn *conn); - -// begin a distributed transaction -int dpiConn_beginDistribTrans(dpiConn *conn, long formatId, - const char *transactionId, uint32_t transactionIdLength, - const char *branchId, uint32_t branchIdLength); - -// break execution of the statement running on the connection -int dpiConn_breakExecution(dpiConn *conn); - -// change the password for the specified user -int dpiConn_changePassword(dpiConn *conn, const char *userName, - uint32_t userNameLength, const char *oldPassword, - uint32_t oldPasswordLength, const char *newPassword, - uint32_t newPasswordLength); - -// close the connection now, not when the reference count reaches zero -int dpiConn_close(dpiConn *conn, dpiConnCloseMode mode, const char *tag, - uint32_t tagLength); - -// commits the current active transaction -int dpiConn_commit(dpiConn *conn); - -// create a connection and return a reference to it -int dpiConn_create(const dpiContext *context, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - const char *connectString, uint32_t connectStringLength, - const dpiCommonCreateParams *commonParams, - dpiConnCreateParams *createParams, dpiConn **conn); - -// dequeue a message from a queue -int dpiConn_deqObject(dpiConn *conn, const char *queueName, - uint32_t queueNameLength, dpiDeqOptions *options, dpiMsgProps *props, - dpiObject *payload, const char **msgId, uint32_t *msgIdLength); - -// enqueue a message to a queue -int dpiConn_enqObject(dpiConn *conn, const char *queueName, - uint32_t queueNameLength, dpiEnqOptions *options, dpiMsgProps *props, - dpiObject *payload, const char **msgId, uint32_t *msgIdLength); - -// get call timeout in place for round-trips with this connection -int dpiConn_getCallTimeout(dpiConn *conn, uint32_t *value); - -// get current schema associated with the connection -int dpiConn_getCurrentSchema(dpiConn *conn, const char **value, - uint32_t *valueLength); - -// get edition associated with the connection -int dpiConn_getEdition(dpiConn *conn, const char **value, - uint32_t *valueLength); - -// return the encoding information used by the connection -int dpiConn_getEncodingInfo(dpiConn *conn, dpiEncodingInfo *info); - -// get external name associated with the connection -int dpiConn_getExternalName(dpiConn *conn, const char **value, - uint32_t *valueLength); - -// get the OCI service context handle associated with the connection -int dpiConn_getHandle(dpiConn *conn, void **handle); - -// get internal name associated with the connection -int dpiConn_getInternalName(dpiConn *conn, const char **value, - uint32_t *valueLength); - -// get logical transaction id associated with the connection -int dpiConn_getLTXID(dpiConn *conn, const char **value, uint32_t *valueLength); - -// create a new object type and return it for subsequent object creation -int dpiConn_getObjectType(dpiConn *conn, const char *name, uint32_t nameLength, - dpiObjectType **objType); - -// return information about the server version in use -int dpiConn_getServerVersion(dpiConn *conn, const char **releaseString, - uint32_t *releaseStringLength, dpiVersionInfo *versionInfo); - -// get SODA interface object -int dpiConn_getSodaDb(dpiConn *conn, dpiSodaDb **db); - -// return the statement cache size -int dpiConn_getStmtCacheSize(dpiConn *conn, uint32_t *cacheSize); - -// create a new dequeue options object and return it -int dpiConn_newDeqOptions(dpiConn *conn, dpiDeqOptions **options); - -// create a new enqueue options object and return it -int dpiConn_newEnqOptions(dpiConn *conn, dpiEnqOptions **options); - -// create a new message properties object and return it -int dpiConn_newMsgProps(dpiConn *conn, dpiMsgProps **props); - -// create a new AQ queue -int dpiConn_newQueue(dpiConn *conn, const char *name, uint32_t nameLength, - dpiObjectType *payloadType, dpiQueue **queue); - -// create a new temporary LOB -int dpiConn_newTempLob(dpiConn *conn, dpiOracleTypeNum lobType, dpiLob **lob); - -// create a new variable and return it for subsequent binding/defining -int dpiConn_newVar(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, - dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, - int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, - dpiData **data); - -// ping the connection to see if it is still alive -int dpiConn_ping(dpiConn *conn); - -// prepare a distributed transaction for commit -int dpiConn_prepareDistribTrans(dpiConn *conn, int *commitNeeded); - -// prepare a statement and return it for subsequent execution/fetching -int dpiConn_prepareStmt(dpiConn *conn, int scrollable, const char *sql, - uint32_t sqlLength, const char *tag, uint32_t tagLength, - dpiStmt **stmt); - -// release a reference to the connection -int dpiConn_release(dpiConn *conn); - -// rolls back the current active transaction -int dpiConn_rollback(dpiConn *conn); - -// set action associated with the connection -int dpiConn_setAction(dpiConn *conn, const char *value, uint32_t valueLength); - -// set call timeout for subsequent round-trips with this connection -int dpiConn_setCallTimeout(dpiConn *conn, uint32_t value); - -// set client identifier associated with the connection -int dpiConn_setClientIdentifier(dpiConn *conn, const char *value, - uint32_t valueLength); - -// set client info associated with the connection -int dpiConn_setClientInfo(dpiConn *conn, const char *value, - uint32_t valueLength); - -// set current schema associated with the connection -int dpiConn_setCurrentSchema(dpiConn *conn, const char *value, - uint32_t valueLength); - -// set database operation associated with the connection -int dpiConn_setDbOp(dpiConn *conn, const char *value, uint32_t valueLength); - -// set external name associated with the connection -int dpiConn_setExternalName(dpiConn *conn, const char *value, - uint32_t valueLength); - -// set internal name associated with the connection -int dpiConn_setInternalName(dpiConn *conn, const char *value, - uint32_t valueLength); - -// set module associated with the connection -int dpiConn_setModule(dpiConn *conn, const char *value, uint32_t valueLength); - -// set the statement cache size -int dpiConn_setStmtCacheSize(dpiConn *conn, uint32_t cacheSize); - -// shutdown the database -int dpiConn_shutdownDatabase(dpiConn *conn, dpiShutdownMode mode); - -// startup the database -int dpiConn_startupDatabase(dpiConn *conn, dpiStartupMode mode); - -// subscribe to events in the database -int dpiConn_subscribe(dpiConn *conn, dpiSubscrCreateParams *params, - dpiSubscr **subscr); - -// unsubscribe from events in the database -int dpiConn_unsubscribe(dpiConn *conn, dpiSubscr *subscr); - - -//----------------------------------------------------------------------------- -// Data Methods (dpiData) -//----------------------------------------------------------------------------- - -// return the boolean portion of the data -int dpiData_getBool(dpiData *data); - -// return the bytes portion of the data -dpiBytes *dpiData_getBytes(dpiData *data); - -// return the double portion of the data -double dpiData_getDouble(dpiData *data); - -// return the float portion of the data -float dpiData_getFloat(dpiData *data); - -// return the integer portion of the data -int64_t dpiData_getInt64(dpiData *data); - -// return the interval (days/seconds) portion of the data -dpiIntervalDS *dpiData_getIntervalDS(dpiData *data); - -// return the interval (years/months) portion of the data -dpiIntervalYM *dpiData_getIntervalYM(dpiData *data); - -// return whether data value is null or not -int dpiData_getIsNull(dpiData *data); - -// return the LOB portion of the data -dpiLob *dpiData_getLOB(dpiData *data); - -// return the object portion of the data -dpiObject *dpiData_getObject(dpiData *data); - -// return the statement portion of the data -dpiStmt *dpiData_getStmt(dpiData *data); - -// return the timestamp portion of the data -dpiTimestamp *dpiData_getTimestamp(dpiData *data); - -// return the unsigned integer portion of the data -uint64_t dpiData_getUint64(dpiData *data); - -// set the boolean portion of the data -void dpiData_setBool(dpiData *data, int value); - -// set the bytes portion of the data -void dpiData_setBytes(dpiData *data, char *ptr, uint32_t length); - -// set the double portion of the data -void dpiData_setDouble(dpiData *data, double value); - -// set the float portion of the data -void dpiData_setFloat(dpiData *data, float value); - -// set the integer portion of the data -void dpiData_setInt64(dpiData *data, int64_t value); - -// set the interval (days/seconds) portion of the data -void dpiData_setIntervalDS(dpiData *data, int32_t days, int32_t hours, - int32_t minutes, int32_t seconds, int32_t fsceconds); - -// set the interval (years/months) portion of the data -void dpiData_setIntervalYM(dpiData *data, int32_t years, int32_t months); - -// set the LOB portion of the data -void dpiData_setLOB(dpiData *data, dpiLob *lob); - -// set data to the null value -void dpiData_setNull(dpiData *data); - -// set the object portion of the data -void dpiData_setObject(dpiData *data, dpiObject *obj); - -// set the statement portion of the data -void dpiData_setStmt(dpiData *data, dpiStmt *stmt); - -// set the timestamp portion of the data -void dpiData_setTimestamp(dpiData *data, int16_t year, uint8_t month, - uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, - uint32_t fsecond, int8_t tzHourOffset, int8_t tzMinuteOffset); - -// set the unsigned integer portion of the data -void dpiData_setUint64(dpiData *data, uint64_t value); - - -//----------------------------------------------------------------------------- -// Dequeue Option Methods (dpiDeqOptions) -//----------------------------------------------------------------------------- - -// add a reference to dequeue options -int dpiDeqOptions_addRef(dpiDeqOptions *options); - -// return condition associated with dequeue options -int dpiDeqOptions_getCondition(dpiDeqOptions *options, const char **value, - uint32_t *valueLength); - -// return consumer name associated with dequeue options -int dpiDeqOptions_getConsumerName(dpiDeqOptions *options, const char **value, - uint32_t *valueLength); - -// return correlation associated with dequeue options -int dpiDeqOptions_getCorrelation(dpiDeqOptions *options, const char **value, - uint32_t *valueLength); - -// return mode associated with dequeue options -int dpiDeqOptions_getMode(dpiDeqOptions *options, dpiDeqMode *value); - -// return message id associated with dequeue options -int dpiDeqOptions_getMsgId(dpiDeqOptions *options, const char **value, - uint32_t *valueLength); - -// return navigation associated with dequeue options -int dpiDeqOptions_getNavigation(dpiDeqOptions *options, - dpiDeqNavigation *value); - -// return transformation associated with dequeue options -int dpiDeqOptions_getTransformation(dpiDeqOptions *options, const char **value, - uint32_t *valueLength); - -// return visibility associated with dequeue options -int dpiDeqOptions_getVisibility(dpiDeqOptions *options, dpiVisibility *value); - -// return wait time associated with dequeue options -int dpiDeqOptions_getWait(dpiDeqOptions *options, uint32_t *value); - -// release a reference from dequeue options -int dpiDeqOptions_release(dpiDeqOptions *options); - -// set condition associated with dequeue options -int dpiDeqOptions_setCondition(dpiDeqOptions *options, const char *value, - uint32_t valueLength); - -// set consumer name associated with dequeue options -int dpiDeqOptions_setConsumerName(dpiDeqOptions *options, const char *value, - uint32_t valueLength); - -// set correlation associated with dequeue options -int dpiDeqOptions_setCorrelation(dpiDeqOptions *options, const char *value, - uint32_t valueLength); - -// set delivery mode associated with dequeue options -int dpiDeqOptions_setDeliveryMode(dpiDeqOptions *options, - dpiMessageDeliveryMode value); - -// set mode associated with dequeue options -int dpiDeqOptions_setMode(dpiDeqOptions *options, dpiDeqMode value); - -// set message id associated with dequeue options -int dpiDeqOptions_setMsgId(dpiDeqOptions *options, const char *value, - uint32_t valueLength); - -// set navigation associated with dequeue options -int dpiDeqOptions_setNavigation(dpiDeqOptions *options, - dpiDeqNavigation value); - -// set transformation associated with dequeue options -int dpiDeqOptions_setTransformation(dpiDeqOptions *options, const char *value, - uint32_t valueLength); - -// set visibility associated with dequeue options -int dpiDeqOptions_setVisibility(dpiDeqOptions *options, dpiVisibility value); - -// set wait time associated with dequeue options -int dpiDeqOptions_setWait(dpiDeqOptions *options, uint32_t value); - - -//----------------------------------------------------------------------------- -// Enqueue Option Methods (dpiEnqOptions) -//----------------------------------------------------------------------------- - -// add a reference to enqueue options -int dpiEnqOptions_addRef(dpiEnqOptions *options); - -// return transformation associated with enqueue options -int dpiEnqOptions_getTransformation(dpiEnqOptions *options, const char **value, - uint32_t *valueLength); - -// return visibility associated with enqueue options -int dpiEnqOptions_getVisibility(dpiEnqOptions *options, dpiVisibility *value); - -// release a reference from enqueue options -int dpiEnqOptions_release(dpiEnqOptions *options); - -// set delivery mode associated with enqueue options -int dpiEnqOptions_setDeliveryMode(dpiEnqOptions *options, - dpiMessageDeliveryMode value); - -// set transformation associated with enqueue options -int dpiEnqOptions_setTransformation(dpiEnqOptions *options, const char *value, - uint32_t valueLength); - -// set visibility associated with enqueue options -int dpiEnqOptions_setVisibility(dpiEnqOptions *options, dpiVisibility value); - - -//----------------------------------------------------------------------------- -// LOB Methods (dpiLob) -//----------------------------------------------------------------------------- - -// add a reference to the LOB -int dpiLob_addRef(dpiLob *lob); - -// close the LOB -int dpiLob_close(dpiLob *lob); - -// close the LOB's resources -int dpiLob_closeResource(dpiLob *lob); - -// create a copy of the LOB -int dpiLob_copy(dpiLob *lob, dpiLob **copiedLob); - -// get buffer size in bytes for a LOB -int dpiLob_getBufferSize(dpiLob *lob, uint64_t sizeInChars, - uint64_t *sizeInBytes); - -// return the chunk size for the LOB -int dpiLob_getChunkSize(dpiLob *lob, uint32_t *size); - -// return the directory alias name and file name of a BFILE LOB -int dpiLob_getDirectoryAndFileName(dpiLob *lob, const char **directoryAlias, - uint32_t *directoryAliasLength, const char **fileName, - uint32_t *fileNameLength); - -// return if the file associated with a BFILE LOB exists -int dpiLob_getFileExists(dpiLob *lob, int *exists); - -// return if the LOB's resources are currently open -int dpiLob_getIsResourceOpen(dpiLob *lob, int *isOpen); - -// return the current size of the LOB -int dpiLob_getSize(dpiLob *lob, uint64_t *size); - -// open the LOB's resources (used to improve performance of multiple -// read/writes operations) -int dpiLob_openResource(dpiLob *lob); - -// read bytes from the LOB at the specified offset -int dpiLob_readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, - char *value, uint64_t *valueLength); - -// release a reference to the LOB -int dpiLob_release(dpiLob *lob); - -// set the directory name and file name of the BFILE LOB -int dpiLob_setDirectoryAndFileName(dpiLob *lob, const char *directoryAlias, - uint32_t directoryAliasLength, const char *fileName, - uint32_t fileNameLength); - -// sets the contents of a LOB from a byte string -int dpiLob_setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength); - -// trim the LOB to the specified size -int dpiLob_trim(dpiLob *lob, uint64_t newSize); - -// write bytes to the LOB at the specified offset -int dpiLob_writeBytes(dpiLob *lob, uint64_t offset, const char *value, - uint64_t valueLength); - - -//----------------------------------------------------------------------------- -// Message Properties Methods (dpiMsgProps) -//----------------------------------------------------------------------------- - -// add a reference to message properties -int dpiMsgProps_addRef(dpiMsgProps *props); - -// return the number of attempts made to deliver the message -int dpiMsgProps_getNumAttempts(dpiMsgProps *props, int32_t *value); - -// return correlation associated with the message -int dpiMsgProps_getCorrelation(dpiMsgProps *props, const char **value, - uint32_t *valueLength); - -// return the number of seconds the message was delayed -int dpiMsgProps_getDelay(dpiMsgProps *props, int32_t *value); - -// return the mode used for delivering the message -int dpiMsgProps_getDeliveryMode(dpiMsgProps *props, - dpiMessageDeliveryMode *value); - -// return the time the message was enqueued -int dpiMsgProps_getEnqTime(dpiMsgProps *props, dpiTimestamp *value); - -// return the name of the exception queue associated with the message -int dpiMsgProps_getExceptionQ(dpiMsgProps *props, const char **value, - uint32_t *valueLength); - -// return the number of seconds until the message expires -int dpiMsgProps_getExpiration(dpiMsgProps *props, int32_t *value); - -// return the message id for the message (after enqueuing or dequeuing) -int dpiMsgProps_getMsgId(dpiMsgProps *props, const char **value, - uint32_t *valueLength); - -// return the original message id for the message -int dpiMsgProps_getOriginalMsgId(dpiMsgProps *props, const char **value, - uint32_t *valueLength); - -// return the payload of the message (object or bytes) -int dpiMsgProps_getPayload(dpiMsgProps *props, dpiObject **obj, - const char **value, uint32_t *valueLength); - -// return the priority of the message -int dpiMsgProps_getPriority(dpiMsgProps *props, int32_t *value); - -// return the state of the message -int dpiMsgProps_getState(dpiMsgProps *props, dpiMessageState *value); - -// release a reference from message properties -int dpiMsgProps_release(dpiMsgProps *props); - -// set correlation associated with the message -int dpiMsgProps_setCorrelation(dpiMsgProps *props, const char *value, - uint32_t valueLength); - -// set the number of seconds to delay the message -int dpiMsgProps_setDelay(dpiMsgProps *props, int32_t value); - -// set the name of the exception queue associated with the message -int dpiMsgProps_setExceptionQ(dpiMsgProps *props, const char *value, - uint32_t valueLength); - -// set the number of seconds until the message expires -int dpiMsgProps_setExpiration(dpiMsgProps *props, int32_t value); - -// set the original message id for the message -int dpiMsgProps_setOriginalMsgId(dpiMsgProps *props, const char *value, - uint32_t valueLength); - -// set the payload of the message (as a series of bytes) -int dpiMsgProps_setPayloadBytes(dpiMsgProps *props, const char *value, - uint32_t valueLength); - -// set the payload of the message (as an object) -int dpiMsgProps_setPayloadObject(dpiMsgProps *props, dpiObject *obj); - -// set the priority of the message -int dpiMsgProps_setPriority(dpiMsgProps *props, int32_t value); - - -//----------------------------------------------------------------------------- -// Object Methods (dpiObject) -//----------------------------------------------------------------------------- - -// add a reference to the object -int dpiObject_addRef(dpiObject *obj); - -// append an element to the collection -int dpiObject_appendElement(dpiObject *obj, dpiNativeTypeNum nativeTypeNum, - dpiData *value); - -// copy the object and return the copied object -int dpiObject_copy(dpiObject *obj, dpiObject **copiedObj); - -// delete an element from the collection -int dpiObject_deleteElementByIndex(dpiObject *obj, int32_t index); - -// get the value of the specified attribute -int dpiObject_getAttributeValue(dpiObject *obj, dpiObjectAttr *attr, - dpiNativeTypeNum nativeTypeNum, dpiData *value); - -// return whether an element exists in a collection at the specified index -int dpiObject_getElementExistsByIndex(dpiObject *obj, int32_t index, - int *exists); - -// get the value of the element in a collection at the specified index -int dpiObject_getElementValueByIndex(dpiObject *obj, int32_t index, - dpiNativeTypeNum nativeTypeNum, dpiData *value); - -// return the first index used in a collection -int dpiObject_getFirstIndex(dpiObject *obj, int32_t *index, int *exists); - -// return the last index used in a collection -int dpiObject_getLastIndex(dpiObject *obj, int32_t *index, int *exists); - -// return the next index used in a collection given an index -int dpiObject_getNextIndex(dpiObject *obj, int32_t index, int32_t *nextIndex, - int *exists); - -// return the previous index used in a collection given an index -int dpiObject_getPrevIndex(dpiObject *obj, int32_t index, int32_t *prevIndex, - int *exists); - -// return the number of elements in a collection -int dpiObject_getSize(dpiObject *obj, int32_t *size); - -// release a reference to the object -int dpiObject_release(dpiObject *obj); - -// set the value of the specified attribute -int dpiObject_setAttributeValue(dpiObject *obj, dpiObjectAttr *attr, - dpiNativeTypeNum nativeTypeNum, dpiData *value); - -// set the value of the element in a collection at the specified index -int dpiObject_setElementValueByIndex(dpiObject *obj, int32_t index, - dpiNativeTypeNum nativeTypeNum, dpiData *value); - -// trim a number of elements from the end of a collection -int dpiObject_trim(dpiObject *obj, uint32_t numToTrim); - - -//----------------------------------------------------------------------------- -// Object Type Attribute Methods (dpiObjectAttr) -//----------------------------------------------------------------------------- - -// add a reference to the attribute -int dpiObjectAttr_addRef(dpiObjectAttr *attr); - -// return the name of the attribute -int dpiObjectAttr_getInfo(dpiObjectAttr *attr, dpiObjectAttrInfo *info); - -// release a reference to the attribute -int dpiObjectAttr_release(dpiObjectAttr *attr); - - -//----------------------------------------------------------------------------- -// Object Type Methods (dpiObjectType) -//----------------------------------------------------------------------------- - -// add a reference to the object type -int dpiObjectType_addRef(dpiObjectType *objType); - -// create an object of the specified type and return it -int dpiObjectType_createObject(dpiObjectType *objType, dpiObject **obj); - -// return the attributes available on the object type -int dpiObjectType_getAttributes(dpiObjectType *objType, uint16_t numAttributes, - dpiObjectAttr **attributes); - -// return information about the object type -int dpiObjectType_getInfo(dpiObjectType *objType, dpiObjectTypeInfo *info); - -// release a reference to the object type -int dpiObjectType_release(dpiObjectType *objType); - - -//----------------------------------------------------------------------------- -// Session Pools Methods (dpiPool) -//----------------------------------------------------------------------------- - -// acquire a connection from the pool and return it -int dpiPool_acquireConnection(dpiPool *pool, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - dpiConnCreateParams *createParams, dpiConn **conn); - -// add a reference to a pool -int dpiPool_addRef(dpiPool *pool); - -// destroy the pool now, not when its reference count reaches zero -int dpiPool_close(dpiPool *pool, dpiPoolCloseMode closeMode); - -// create a session pool and return it -int dpiPool_create(const dpiContext *context, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - const char *connectString, uint32_t connectStringLength, - const dpiCommonCreateParams *commonParams, - dpiPoolCreateParams *createParams, dpiPool **pool); - -// get the pool's busy count -int dpiPool_getBusyCount(dpiPool *pool, uint32_t *value); - -// return the encoding information used by the session pool -int dpiPool_getEncodingInfo(dpiPool *pool, dpiEncodingInfo *info); - -// get the pool's "get" mode -int dpiPool_getGetMode(dpiPool *pool, dpiPoolGetMode *value); - -// get the pool's maximum lifetime session -int dpiPool_getMaxLifetimeSession(dpiPool *pool, uint32_t *value); - -// get the pool's open count -int dpiPool_getOpenCount(dpiPool *pool, uint32_t *value); - -// return the statement cache size -int dpiPool_getStmtCacheSize(dpiPool *pool, uint32_t *cacheSize); - -// get the pool's timeout value -int dpiPool_getTimeout(dpiPool *pool, uint32_t *value); - -// get the pool's wait timeout value -int dpiPool_getWaitTimeout(dpiPool *pool, uint32_t *value); - -// release a reference to the pool -int dpiPool_release(dpiPool *pool); - -// set the pool's "get" mode -int dpiPool_setGetMode(dpiPool *pool, dpiPoolGetMode value); - -// set the pool's maximum lifetime session -int dpiPool_setMaxLifetimeSession(dpiPool *pool, uint32_t value); - -// set the statement cache size -int dpiPool_setStmtCacheSize(dpiPool *pool, uint32_t cacheSize); - -// set the pool's timeout value -int dpiPool_setTimeout(dpiPool *pool, uint32_t value); - -// set the pool's wait timeout value -int dpiPool_setWaitTimeout(dpiPool *pool, uint32_t value); - - -//----------------------------------------------------------------------------- -// AQ Queue Methods (dpiQueue) -//----------------------------------------------------------------------------- - -// add a reference to the queue -int dpiQueue_addRef(dpiQueue *queue); - -// dequeue multiple messages from the queue -int dpiQueue_deqMany(dpiQueue *queue, uint32_t *numProps, dpiMsgProps **props); - -// dequeue a single message from the queue -int dpiQueue_deqOne(dpiQueue *queue, dpiMsgProps **props); - -// enqueue multiple message to the queue -int dpiQueue_enqMany(dpiQueue *queue, uint32_t numProps, dpiMsgProps **props); - -// enqueue a single message to the queue -int dpiQueue_enqOne(dpiQueue *queue, dpiMsgProps *props); - -// get a reference to the dequeue options associated with the queue -int dpiQueue_getDeqOptions(dpiQueue *queue, dpiDeqOptions **options); - -// get a reference to the enqueue options associated with the queue -int dpiQueue_getEnqOptions(dpiQueue *queue, dpiEnqOptions **options); - -// release a reference to the queue -int dpiQueue_release(dpiQueue *queue); - - -//----------------------------------------------------------------------------- -// SODA Collection Methods (dpiSodaColl) -//----------------------------------------------------------------------------- - -// add a reference to the SODA collection -int dpiSodaColl_addRef(dpiSodaColl *coll); - -// create an index on the collection -int dpiSodaColl_createIndex(dpiSodaColl *coll, const char *indexSpec, - uint32_t indexSpecLength, uint32_t flags); - -// drop a SODA collection -int dpiSodaColl_drop(dpiSodaColl *coll, uint32_t flags, int *isDropped); - -// drop an index on the collection -int dpiSodaColl_dropIndex(dpiSodaColl *coll, const char *name, - uint32_t nameLength, uint32_t flags, int *isDropped); - -// find documents in a SODA collection and return a cursor -int dpiSodaColl_find(dpiSodaColl *coll, const dpiSodaOperOptions *options, - uint32_t flags, dpiSodaDocCursor **cursor); - -// find a single document in a SODA collection -int dpiSodaColl_findOne(dpiSodaColl *coll, const dpiSodaOperOptions *options, - uint32_t flags, dpiSodaDoc **doc); - -// get the data guide for the collection -int dpiSodaColl_getDataGuide(dpiSodaColl *coll, uint32_t flags, - dpiSodaDoc **doc); - -// get the count of documents that match the criteria -int dpiSodaColl_getDocCount(dpiSodaColl *coll, - const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count); - -// get the metadata of the collection -int dpiSodaColl_getMetadata(dpiSodaColl *coll, const char **value, - uint32_t *valueLength); - -// get the name of the collection -int dpiSodaColl_getName(dpiSodaColl *coll, const char **value, - uint32_t *valueLength); - -// insert multiple documents into the SODA collection -int dpiSodaColl_insertMany(dpiSodaColl *coll, uint32_t numDocs, - dpiSodaDoc **docs, uint32_t flags, dpiSodaDoc **insertedDocs); - -// insert a document into the SODA collection -int dpiSodaColl_insertOne(dpiSodaColl *coll, dpiSodaDoc *doc, uint32_t flags, - dpiSodaDoc **insertedDoc); - -// release a reference to the SODA collection -int dpiSodaColl_release(dpiSodaColl *coll); - -// remove documents from a SODA collection (with operation options) -int dpiSodaColl_remove(dpiSodaColl *coll, const dpiSodaOperOptions *options, - uint32_t flags, uint64_t *count); - -// replace a document in a SODA collection (with operation options) -int dpiSodaColl_replaceOne(dpiSodaColl *coll, - const dpiSodaOperOptions *options, dpiSodaDoc *doc, uint32_t flags, - int *replaced, dpiSodaDoc **replacedDoc); - - -//----------------------------------------------------------------------------- -// SODA Collection Cursor Methods (dpiSodaCollCursor) -//----------------------------------------------------------------------------- - -// add a reference to the SODA collection cursor -int dpiSodaCollCursor_addRef(dpiSodaCollCursor *cursor); - -// close the SODA collection cursor -int dpiSodaCollCursor_close(dpiSodaCollCursor *cursor); - -// get the next collection from the cursor -int dpiSodaCollCursor_getNext(dpiSodaCollCursor *cursor, uint32_t flags, - dpiSodaColl **coll); - -// release a reference to the SODA collection cursor -int dpiSodaCollCursor_release(dpiSodaCollCursor *cursor); - - -//----------------------------------------------------------------------------- -// SODA Database Methods (dpiSodaDb) -//----------------------------------------------------------------------------- - -// add a reference to the SODA database -int dpiSodaDb_addRef(dpiSodaDb *db); - -// create a new SODA collection -int dpiSodaDb_createCollection(dpiSodaDb *db, const char *name, - uint32_t nameLength, const char *metadata, uint32_t metadataLength, - uint32_t flags, dpiSodaColl **coll); - -// create a new SODA document -int dpiSodaDb_createDocument(dpiSodaDb *db, const char *key, - uint32_t keyLength, const char *content, uint32_t contentLength, - const char *mediaType, uint32_t mediaTypeLength, uint32_t flags, - dpiSodaDoc **doc); - -// free the memory allocated when getting an array of SODA collection names -int dpiSodaDb_freeCollectionNames(dpiSodaDb *db, dpiSodaCollNames *names); - -// return a cursor to iterate over SODA collections -int dpiSodaDb_getCollections(dpiSodaDb *db, const char *startName, - uint32_t startNameLength, uint32_t flags, dpiSodaCollCursor **cursor); - -// return an array of SODA collection names -int dpiSodaDb_getCollectionNames(dpiSodaDb *db, const char *startName, - uint32_t startNameLength, uint32_t limit, uint32_t flags, - dpiSodaCollNames *names); - -// open an existing SODA collection -int dpiSodaDb_openCollection(dpiSodaDb *db, const char *name, - uint32_t nameLength, uint32_t flags, dpiSodaColl **coll); - -// release a reference to the SODA database -int dpiSodaDb_release(dpiSodaDb *db); - - -//----------------------------------------------------------------------------- -// SODA Document Methods (dpiSodaDoc) -//----------------------------------------------------------------------------- - -// add a reference to the SODA document -int dpiSodaDoc_addRef(dpiSodaDoc *cursor); - -// get the content of the document -int dpiSodaDoc_getContent(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength, const char **encoding); - -// get the created timestamp associated with the document -int dpiSodaDoc_getCreatedOn(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength); - -// get the key associated with the document -int dpiSodaDoc_getKey(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength); - -// get the last modified timestamp associated with the document -int dpiSodaDoc_getLastModified(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength); - -// get the media type of the document -int dpiSodaDoc_getMediaType(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength); - -// get the version of the document -int dpiSodaDoc_getVersion(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength); - -// release a reference to the SODA document -int dpiSodaDoc_release(dpiSodaDoc *cursor); - - -//----------------------------------------------------------------------------- -// SODA Document Cursor Methods (dpiSodaDocCursor) -//----------------------------------------------------------------------------- - -// add a reference to the SODA document cursor -int dpiSodaDocCursor_addRef(dpiSodaDocCursor *cursor); - -// close the SODA document cursor -int dpiSodaDocCursor_close(dpiSodaDocCursor *cursor); - -// get the next document from the cursor -int dpiSodaDocCursor_getNext(dpiSodaDocCursor *cursor, uint32_t flags, - dpiSodaDoc **doc); - -// release a reference to the SODA document cursor -int dpiSodaDocCursor_release(dpiSodaDocCursor *cursor); - - -//----------------------------------------------------------------------------- -// Statement Methods (dpiStmt) -//----------------------------------------------------------------------------- - -// add a reference to a statement -int dpiStmt_addRef(dpiStmt *stmt); - -// bind a variable to the statement using the given name -int dpiStmt_bindByName(dpiStmt *stmt, const char *name, uint32_t nameLength, - dpiVar *var); - -// bind a variable to the statement at the given position -// positions are determined by the order in which names are introduced -int dpiStmt_bindByPos(dpiStmt *stmt, uint32_t pos, dpiVar *var); - -// bind a value to the statement using the given name -// this creates the variable by looking at the type and then binds it -int dpiStmt_bindValueByName(dpiStmt *stmt, const char *name, - uint32_t nameLength, dpiNativeTypeNum nativeTypeNum, dpiData *data); - -// bind a value to the statement at the given position -// this creates the variable by looking at the type and then binds it -int dpiStmt_bindValueByPos(dpiStmt *stmt, uint32_t pos, - dpiNativeTypeNum nativeTypeNum, dpiData *data); - -// close the statement now, not when its reference count reaches zero -int dpiStmt_close(dpiStmt *stmt, const char *tag, uint32_t tagLength); - -// define a variable to accept the data for the specified column (1 based) -int dpiStmt_define(dpiStmt *stmt, uint32_t pos, dpiVar *var); - -// define type of data to use for the specified column (1 based) -int dpiStmt_defineValue(dpiStmt *stmt, uint32_t pos, - dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, - uint32_t size, int sizeIsBytes, dpiObjectType *objType); - -// execute the statement and return the number of query columns -// zero implies the statement is not a query -int dpiStmt_execute(dpiStmt *stmt, dpiExecMode mode, - uint32_t *numQueryColumns); - -// execute the statement multiple times (queries not supported) -int dpiStmt_executeMany(dpiStmt *stmt, dpiExecMode mode, uint32_t numIters); - -// fetch a single row and return the index into the defined variables -// this will internally perform any execute and array fetch as needed -int dpiStmt_fetch(dpiStmt *stmt, int *found, uint32_t *bufferRowIndex); - -// return the number of rows that are available in the defined variables -// up to the maximum specified; this will internally perform execute/array -// fetch only if no rows are available in the defined variables and there are -// more rows available to fetch -int dpiStmt_fetchRows(dpiStmt *stmt, uint32_t maxRows, - uint32_t *bufferRowIndex, uint32_t *numRowsFetched, int *moreRows); - -// get the number of batch errors that took place in the previous execution -int dpiStmt_getBatchErrorCount(dpiStmt *stmt, uint32_t *count); - -// get the batch errors that took place in the previous execution -int dpiStmt_getBatchErrors(dpiStmt *stmt, uint32_t numErrors, - dpiErrorInfo *errors); - -// get the number of bind variables that are in the prepared statement -int dpiStmt_getBindCount(dpiStmt *stmt, uint32_t *count); - -// get the names of the bind variables that are in the prepared statement -int dpiStmt_getBindNames(dpiStmt *stmt, uint32_t *numBindNames, - const char **bindNames, uint32_t *bindNameLengths); - -// get the number of rows to (internally) fetch at one time -int dpiStmt_getFetchArraySize(dpiStmt *stmt, uint32_t *arraySize); - -// get next implicit result from previous execution; NULL if no more exist -int dpiStmt_getImplicitResult(dpiStmt *stmt, dpiStmt **implicitResult); - -// return information about the statement -int dpiStmt_getInfo(dpiStmt *stmt, dpiStmtInfo *info); - -// get the rowid of the last row affected by a DML statement -int dpiStmt_getLastRowid(dpiStmt *stmt, dpiRowid **rowid); - -// get the number of query columns (zero implies the statement is not a query) -int dpiStmt_getNumQueryColumns(dpiStmt *stmt, uint32_t *numQueryColumns); - -// return metadata about the column at the specified position (1 based) -int dpiStmt_getQueryInfo(dpiStmt *stmt, uint32_t pos, dpiQueryInfo *info); - -// get the value for the specified column of the current row fetched -int dpiStmt_getQueryValue(dpiStmt *stmt, uint32_t pos, - dpiNativeTypeNum *nativeTypeNum, dpiData **data); - -// get the row count for the statement -// for queries, this is the number of rows that have been fetched so far -// for non-queries, this is the number of rows affected by the last execution -int dpiStmt_getRowCount(dpiStmt *stmt, uint64_t *count); - -// get the number of rows affected for each DML operation just executed -// using the mode DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS -int dpiStmt_getRowCounts(dpiStmt *stmt, uint32_t *numRowCounts, - uint64_t **rowCounts); - -// get subscription query id for continuous query notification -int dpiStmt_getSubscrQueryId(dpiStmt *stmt, uint64_t *queryId); - -// release a reference to the statement -int dpiStmt_release(dpiStmt *stmt); - -// scroll the statement to the desired row -// this is only valid for scrollable statements -int dpiStmt_scroll(dpiStmt *stmt, dpiFetchMode mode, int32_t offset, - int32_t rowCountOffset); - -// set the number of rows to (internally) fetch at one time -int dpiStmt_setFetchArraySize(dpiStmt *stmt, uint32_t arraySize); - - -//----------------------------------------------------------------------------- -// Rowid Methods (dpiRowid) -//----------------------------------------------------------------------------- - -// add a reference to the rowid -int dpiRowid_addRef(dpiRowid *rowid); - -// get string representation from rowid -int dpiRowid_getStringValue(dpiRowid *rowid, const char **value, - uint32_t *valueLength); - -// release a reference to the rowid -int dpiRowid_release(dpiRowid *subscr); - - -//----------------------------------------------------------------------------- -// Subscription Methods (dpiSubscr) -//----------------------------------------------------------------------------- - -// add a reference to the subscription -int dpiSubscr_addRef(dpiSubscr *subscr); - -// prepare statement for registration with subscription -int dpiSubscr_prepareStmt(dpiSubscr *subscr, const char *sql, - uint32_t sqlLength, dpiStmt **stmt); - -// release a reference to the subscription -int dpiSubscr_release(dpiSubscr *subscr); - - -//----------------------------------------------------------------------------- -// Variable Methods (dpiVar) -//----------------------------------------------------------------------------- - -// add a reference to the variable -int dpiVar_addRef(dpiVar *var); - -// copy the data from one variable to another variable -int dpiVar_copyData(dpiVar *var, uint32_t pos, dpiVar *sourceVar, - uint32_t sourcePos); - -// return the number of elements in a PL/SQL index-by table -int dpiVar_getNumElementsInArray(dpiVar *var, uint32_t *numElements); - -// return pointer to array of dpiData structures for transferring data -// this is needed for DML returning where the number of elements is modified -int dpiVar_getReturnedData(dpiVar *var, uint32_t pos, uint32_t *numElements, - dpiData **data); - -// return the size in bytes of the buffer used for fetching/binding -int dpiVar_getSizeInBytes(dpiVar *var, uint32_t *sizeInBytes); - -// release a reference to the variable -int dpiVar_release(dpiVar *var); - -// set the value of the variable from a byte string -int dpiVar_setFromBytes(dpiVar *var, uint32_t pos, const char *value, - uint32_t valueLength); - -// set the value of the variable from a LOB -int dpiVar_setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob); - -// set the value of the variable from an object -int dpiVar_setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj); - -// set the value of the variable from a rowid -int dpiVar_setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid); - -// set the value of the variable from a statement -int dpiVar_setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt); - -// set the number of elements in a PL/SQL index-by table -int dpiVar_setNumElementsInArray(dpiVar *var, uint32_t numElements); - -#endif diff --git a/vendor/github.com/godror/godror/odpi/src/dpiConn.c b/vendor/github.com/godror/godror/odpi/src/dpiConn.c deleted file mode 100644 index faa5dc5266b..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiConn.c +++ /dev/null @@ -1,2249 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiConn.c -// Implementation of connection. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" -#include - -// forward declarations of internal functions only used in this file -static int dpiConn__attachExternal(dpiConn *conn, void *externalHandle, - dpiError *error); -static int dpiConn__createStandalone(dpiConn *conn, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - const char *connectString, uint32_t connectStringLength, - const dpiCommonCreateParams *commonParams, - const dpiConnCreateParams *createParams, dpiError *error); -static int dpiConn__get(dpiConn *conn, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - const char *connectString, uint32_t connectStringLength, - dpiConnCreateParams *createParams, dpiPool *pool, dpiError *error); -static int dpiConn__getHandles(dpiConn *conn, dpiError *error); -static int dpiConn__getServerCharset(dpiConn *conn, dpiError *error); -static int dpiConn__getSession(dpiConn *conn, uint32_t mode, - const char *connectString, uint32_t connectStringLength, - dpiConnCreateParams *params, void *authInfo, dpiError *error); -static int dpiConn__setAttributesFromCreateParams(dpiConn *conn, void *handle, - uint32_t handleType, const char *userName, uint32_t userNameLength, - const char *password, uint32_t passwordLength, - const dpiConnCreateParams *params, dpiError *error); -static int dpiConn__setShardingKey(dpiConn *conn, void **shardingKey, - void *handle, uint32_t handleType, uint32_t attribute, - const char *action, dpiShardingKeyColumn *columns, uint8_t numColumns, - dpiError *error); -static int dpiConn__setShardingKeyValue(dpiConn *conn, void *shardingKey, - dpiShardingKeyColumn *column, dpiError *error); - - -//----------------------------------------------------------------------------- -// dpiConn__attachExternal() [INTERNAL] -// Attach to the server and session of an existing service context handle. -//----------------------------------------------------------------------------- -static int dpiConn__attachExternal(dpiConn *conn, void *externalHandle, - dpiError *error) -{ - // mark connection as using an external handle so that no attempts are - // made to close it - conn->externalHandle = 1; - - // acquire handles from existing service context handle - conn->handle = externalHandle; - if (dpiConn__getHandles(conn, error) < 0) { - conn->handle = NULL; - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiConn__check() [INTERNAL] -// Validate the connection handle and that it is still connected to the -// database. -//----------------------------------------------------------------------------- -static int dpiConn__check(dpiConn *conn, const char *fnName, dpiError *error) -{ - if (dpiGen__startPublicFn(conn, DPI_HTYPE_CONN, fnName, error) < 0) - return DPI_FAILURE; - return dpiConn__checkConnected(conn, error); -} - - -//----------------------------------------------------------------------------- -// dpiConn__checkConnected() [INTERNAL] -// Check to see if the connection is still open and raise an exception if it -// is not. -//----------------------------------------------------------------------------- -int dpiConn__checkConnected(dpiConn *conn, dpiError *error) -{ - if (!conn->handle || conn->closing || (conn->pool && !conn->pool->handle)) - return dpiError__set(error, "check connected", DPI_ERR_NOT_CONNECTED); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiConn__close() [INTERNAL] -// Internal method used for closing the connection. Any transaction is rolled -// back and any handles allocated are freed. For connections acquired from a -// pool and that aren't marked as needed to be dropped, the last time used is -// updated. This is called from dpiConn_close() where errors are expected to be -// propagated and from dpiConn__free() where errors are ignored. -//----------------------------------------------------------------------------- -static int dpiConn__close(dpiConn *conn, uint32_t mode, const char *tag, - uint32_t tagLength, int propagateErrors, dpiError *error) -{ - int status, txnInProgress; - uint32_t serverStatus, i; - time_t *lastTimeUsed; - dpiObject *obj; - dpiStmt *stmt; - dpiLob *lob; - - // rollback any outstanding transaction, if one is in progress; drop the - // session if any errors take place - txnInProgress = 0; - if (!conn->deadSession && !conn->externalHandle && conn->sessionHandle) { - txnInProgress = 1; - if (conn->env->versionInfo->versionNum >= 12) - dpiOci__attrGet(conn->sessionHandle, DPI_OCI_HTYPE_SESSION, - &txnInProgress, NULL, DPI_OCI_ATTR_TRANSACTION_IN_PROGRESS, - NULL, error); - } - if (txnInProgress && - dpiOci__transRollback(conn, propagateErrors, error) < 0) - conn->deadSession = 1; - - // close all objects; note that no references are retained by the - // handle list (otherwise all objects would be left until an explicit - // close of the connection was made) so a reference needs to be acquired - // first, as otherwise the object may be freed while the close is being - // performed! - if (conn->objects && !conn->externalHandle) { - for (i = 0; i < conn->objects->numSlots; i++) { - obj = (dpiObject*) conn->objects->handles[i]; - if (!obj) - continue; - if (conn->env->threaded) { - dpiMutex__acquire(conn->env->mutex); - status = dpiGen__checkHandle(obj, DPI_HTYPE_OBJECT, NULL, - NULL); - if (status == DPI_SUCCESS) - obj->refCount += 1; - dpiMutex__release(conn->env->mutex); - if (status < 0) - continue; - } - status = dpiObject__close(obj, propagateErrors, error); - if (conn->env->threaded) - dpiGen__setRefCount(obj, error, -1); - if (status < 0) - return DPI_FAILURE; - } - } - - // close all open statements; note that no references are retained by the - // handle list (otherwise all statements would be left open until an - // explicit close was made of either the statement or the connection) so - // a reference needs to be acquired first, as otherwise the statement may - // be freed while the close is being performed! - if (conn->openStmts && !conn->externalHandle) { - for (i = 0; i < conn->openStmts->numSlots; i++) { - stmt = (dpiStmt*) conn->openStmts->handles[i]; - if (!stmt) - continue; - if (conn->env->threaded) { - dpiMutex__acquire(conn->env->mutex); - status = dpiGen__checkHandle(stmt, DPI_HTYPE_STMT, NULL, NULL); - if (status == DPI_SUCCESS) - stmt->refCount += 1; - dpiMutex__release(conn->env->mutex); - if (status < 0) - continue; - } - status = dpiStmt__close(stmt, NULL, 0, propagateErrors, error); - if (conn->env->threaded) - dpiGen__setRefCount(stmt, error, -1); - if (status < 0) - return DPI_FAILURE; - } - } - - // close all open LOBs; the same comments apply as for statements - if (conn->openLobs && !conn->externalHandle) { - for (i = 0; i < conn->openLobs->numSlots; i++) { - lob = (dpiLob*) conn->openLobs->handles[i]; - if (!lob) - continue; - if (conn->env->threaded) { - dpiMutex__acquire(conn->env->mutex); - status = dpiGen__checkHandle(lob, DPI_HTYPE_LOB, NULL, NULL); - if (status == DPI_SUCCESS) - lob->refCount += 1; - dpiMutex__release(conn->env->mutex); - if (status < 0) - continue; - } - status = dpiLob__close(lob, propagateErrors, error); - if (conn->env->threaded) - dpiGen__setRefCount(lob, error, -1); - if (status < 0) - return DPI_FAILURE; - } - } - - // handle connections created with an external handle - if (conn->externalHandle) { - conn->sessionHandle = NULL; - - // handle standalone connections - } else if (conn->standalone) { - - // end session and free session handle - if (dpiOci__sessionEnd(conn, propagateErrors, error) < 0) - return DPI_FAILURE; - dpiOci__handleFree(conn->sessionHandle, DPI_OCI_HTYPE_SESSION); - conn->sessionHandle = NULL; - - // detach from server and free server handle - if (dpiOci__serverDetach(conn, propagateErrors, error) < 0) - return DPI_FAILURE; - dpiOci__handleFree(conn->serverHandle, DPI_OCI_HTYPE_SERVER); - - // free service context handle - dpiOci__handleFree(conn->handle, DPI_OCI_HTYPE_SVCCTX); - - // handle pooled connections - } else { - - // if session is to be dropped, mark it as a dead session - if (mode & DPI_OCI_SESSRLS_DROPSESS) - conn->deadSession = 1; - - // update last time used (if the session isn't going to be dropped) - // clear last time used (if the session is going to be dropped) - // do nothing, however, if not using a pool or the pool is being closed - if (conn->sessionHandle && conn->pool && conn->pool->handle) { - - // get the pointer from the context associated with the session - lastTimeUsed = NULL; - if (dpiOci__contextGetValue(conn, DPI_CONTEXT_LAST_TIME_USED, - (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), - (void**) &lastTimeUsed, propagateErrors, error) < 0) - return DPI_FAILURE; - - // if pointer available and session is going to be dropped, clear - // memory in order to avoid memory leak in OCI - if (lastTimeUsed && conn->deadSession) { - dpiOci__contextSetValue(conn, DPI_CONTEXT_LAST_TIME_USED, - (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), - NULL, 0, error); - dpiOci__memoryFree(conn, lastTimeUsed, error); - lastTimeUsed = NULL; - - // otherwise, if the pointer is not available, allocate a new - // pointer and set it - } else if (!lastTimeUsed && !conn->deadSession) { - if (dpiOci__memoryAlloc(conn, (void**) &lastTimeUsed, - sizeof(time_t), propagateErrors, error) < 0) - return DPI_FAILURE; - if (dpiOci__contextSetValue(conn, DPI_CONTEXT_LAST_TIME_USED, - (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), - lastTimeUsed, propagateErrors, error) < 0) { - dpiOci__memoryFree(conn, lastTimeUsed, error); - lastTimeUsed = NULL; - } - } - - // set last time used (used when acquiring a session to determine - // if ping is required) - if (lastTimeUsed) - *lastTimeUsed = time(NULL); - - } - - // check server status; if not connected, ensure session is dropped - if (conn->serverHandle) { - if (dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, - &serverStatus, NULL, DPI_OCI_ATTR_SERVER_STATUS, - "get server status", error) < 0 || - serverStatus != DPI_OCI_SERVER_NORMAL) - conn->deadSession = 1; - } - - // release session - if (conn->deadSession) - mode |= DPI_OCI_SESSRLS_DROPSESS; - else if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2, - NULL) == DPI_SUCCESS && (mode & DPI_MODE_CONN_CLOSE_RETAG) && - tag && tagLength > 0) - mode |= DPI_OCI_SESSRLS_MULTIPROPERTY_TAG; - if (dpiOci__sessionRelease(conn, tag, tagLength, mode, propagateErrors, - error) < 0) - return DPI_FAILURE; - conn->sessionHandle = NULL; - - } - conn->handle = NULL; - conn->serverHandle = NULL; - - // destroy sharding and super sharding key descriptors, if applicable - if (conn->shardingKey) { - dpiOci__descriptorFree(conn->shardingKey, DPI_OCI_DTYPE_SHARDING_KEY); - conn->shardingKey = NULL; - } - if (conn->superShardingKey) { - dpiOci__descriptorFree(conn->superShardingKey, - DPI_OCI_DTYPE_SHARDING_KEY); - conn->superShardingKey = NULL; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiConn__create() [PRIVATE] -// Perform internal initialization of the connection. -//----------------------------------------------------------------------------- -int dpiConn__create(dpiConn *conn, const dpiContext *context, - const char *userName, uint32_t userNameLength, const char *password, - uint32_t passwordLength, const char *connectString, - uint32_t connectStringLength, dpiPool *pool, - const dpiCommonCreateParams *commonParams, - dpiConnCreateParams *createParams, dpiError *error) -{ - void *envHandle = NULL; - - // allocate handle lists for statements, LOBs and objects - if (dpiHandleList__create(&conn->openStmts, error) < 0) - return DPI_FAILURE; - if (dpiHandleList__create(&conn->openLobs, error) < 0) - return DPI_FAILURE; - if (dpiHandleList__create(&conn->objects, error) < 0) - return DPI_FAILURE; - - // if an external service context handle is provided, acquire the - // environment handle from it; need a temporary environment handle in order - // to do so - if (createParams->externalHandle) { - error->env = conn->env; - if (dpiOci__envNlsCreate(&conn->env->handle, DPI_OCI_DEFAULT, 0, 0, - error) < 0) - return DPI_FAILURE; - if (dpiOci__handleAlloc(conn->env->handle, &error->handle, - DPI_OCI_HTYPE_ERROR, "allocate temp OCI error", error) < 0) - return DPI_FAILURE; - if (dpiOci__attrGet(createParams->externalHandle, DPI_OCI_HTYPE_SVCCTX, - &envHandle, NULL, DPI_OCI_ATTR_ENV, "get env handle", - error) < 0) - return DPI_FAILURE; - dpiOci__handleFree(conn->env->handle, DPI_OCI_HTYPE_ENV); - error->handle = NULL; - conn->env->handle = NULL; - } - - // initialize environment (for non-pooled connections) - if (!pool && dpiEnv__init(conn->env, context, commonParams, envHandle, - error) < 0) - return DPI_FAILURE; - - // if a handle is specified, use it - if (createParams->externalHandle) - return dpiConn__attachExternal(conn, createParams->externalHandle, - error); - - // connection class, sharding and the use of session pools require the use - // of the OCISessionGet() method; all other cases use the OCISessionBegin() - // method which is more capable - if (pool || (createParams->connectionClass && - createParams->connectionClassLength > 0) || - createParams->shardingKeyColumns || - createParams->superShardingKeyColumns) - return dpiConn__get(conn, userName, userNameLength, password, - passwordLength, connectString, connectStringLength, - createParams, pool, error); - return dpiConn__createStandalone(conn, userName, userNameLength, password, - passwordLength, connectString, connectStringLength, commonParams, - createParams, error); -} - - -//----------------------------------------------------------------------------- -// dpiConn__createStandalone() [PRIVATE] -// Create a standalone connection to the database using the parameters -// specified. -//----------------------------------------------------------------------------- -static int dpiConn__createStandalone(dpiConn *conn, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - const char *connectString, uint32_t connectStringLength, - const dpiCommonCreateParams *commonParams, - const dpiConnCreateParams *createParams, dpiError *error) -{ - uint32_t credentialType, authMode; - - // mark the connection as a standalone connection - conn->standalone = 1; - - // allocate the server handle - if (dpiOci__handleAlloc(conn->env->handle, &conn->serverHandle, - DPI_OCI_HTYPE_SERVER, "allocate server handle", error) < 0) - return DPI_FAILURE; - - // attach to the server - if (dpiOci__serverAttach(conn, connectString, connectStringLength, - error) < 0) - return DPI_FAILURE; - - // allocate the service context handle - if (dpiOci__handleAlloc(conn->env->handle, &conn->handle, - DPI_OCI_HTYPE_SVCCTX, "allocate service context handle", - error) < 0) - return DPI_FAILURE; - - // set attribute for server handle - if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, conn->serverHandle, - 0, DPI_OCI_ATTR_SERVER, "set server handle", error) < 0) - return DPI_FAILURE; - - // allocate the session handle - if (dpiOci__handleAlloc(conn->env->handle, &conn->sessionHandle, - DPI_OCI_HTYPE_SESSION, "allocate session handle", error) < 0) - return DPI_FAILURE; - - // driver name and edition are only relevant for standalone connections - if (dpiUtils__setAttributesFromCommonCreateParams(conn->sessionHandle, - DPI_OCI_HTYPE_SESSION, commonParams, error) < 0) - return DPI_FAILURE; - - // populate attributes on the session handle - if (dpiConn__setAttributesFromCreateParams(conn, conn->sessionHandle, - DPI_OCI_HTYPE_SESSION, userName, userNameLength, password, - passwordLength, createParams, error) < 0) - return DPI_FAILURE; - - // set the session handle on the service context handle - if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, - conn->sessionHandle, 0, DPI_OCI_ATTR_SESSION, "set session handle", - error) < 0) - return DPI_FAILURE; - - // if a new password is specified, change it (this also creates the session - // so a call to OCISessionBegin() is not needed) - if (createParams->newPassword && createParams->newPasswordLength > 0) { - authMode = DPI_OCI_AUTH; - if (createParams->authMode & DPI_MODE_AUTH_SYSDBA) - authMode |= DPI_OCI_CPW_SYSDBA; - if (createParams->authMode & DPI_MODE_AUTH_SYSOPER) - authMode |= DPI_OCI_CPW_SYSOPER; - if (createParams->authMode & DPI_MODE_AUTH_SYSASM) - authMode |= DPI_OCI_CPW_SYSASM; - if (createParams->authMode & DPI_MODE_AUTH_SYSBKP) - authMode |= DPI_OCI_CPW_SYSBKP; - if (createParams->authMode & DPI_MODE_AUTH_SYSDGD) - authMode |= DPI_OCI_CPW_SYSDGD; - if (createParams->authMode & DPI_MODE_AUTH_SYSKMT) - authMode |= DPI_OCI_CPW_SYSKMT; - return dpiOci__passwordChange(conn, userName, userNameLength, password, - passwordLength, createParams->newPassword, - createParams->newPasswordLength, authMode, error); - } - - // begin the session - credentialType = (createParams->externalAuth) ? DPI_OCI_CRED_EXT : - DPI_OCI_CRED_RDBMS; - authMode = createParams->authMode | DPI_OCI_STMT_CACHE; - if (dpiOci__sessionBegin(conn, credentialType, authMode, error) < 0) - return DPI_FAILURE; - return dpiConn__getServerCharset(conn, error); -} - - -//----------------------------------------------------------------------------- -// dpiConn__free() [INTERNAL] -// Free the memory and any resources associated with the connection. -//----------------------------------------------------------------------------- -void dpiConn__free(dpiConn *conn, dpiError *error) -{ - if (conn->handle) - dpiConn__close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0, 0, - error); - if (conn->pool) { - dpiGen__setRefCount(conn->pool, error, -1); - conn->pool = NULL; - conn->env = NULL; - } - if (conn->env) { - dpiEnv__free(conn->env, error); - conn->env = NULL; - } - if (conn->releaseString) { - dpiUtils__freeMemory((void*) conn->releaseString); - conn->releaseString = NULL; - } - if (conn->openStmts) { - dpiHandleList__free(conn->openStmts); - conn->openStmts = NULL; - } - if (conn->openLobs) { - dpiHandleList__free(conn->openLobs); - conn->openLobs = NULL; - } - if (conn->objects) { - dpiHandleList__free(conn->objects); - conn->objects = NULL; - } - dpiUtils__freeMemory(conn); -} - - -//----------------------------------------------------------------------------- -// dpiConn__get() [INTERNAL] -// Create a connection to the database using the parameters specified. This -// method uses the simplified OCI session creation protocol which is required -// when using pools and session tagging. -//----------------------------------------------------------------------------- -static int dpiConn__get(dpiConn *conn, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - const char *connectString, uint32_t connectStringLength, - dpiConnCreateParams *createParams, dpiPool *pool, dpiError *error) -{ - int externalAuth, status; - void *authInfo; - uint32_t mode; - - // clear pointers if length is 0 - if (userNameLength == 0) - userName = NULL; - if (passwordLength == 0) - password = NULL; - - // set things up for the call to acquire a session - if (pool) { - dpiGen__setRefCount(pool, error, 1); - conn->pool = pool; - mode = DPI_OCI_SESSGET_SPOOL; - externalAuth = pool->externalAuth; - if (userName && pool->homogeneous) - return dpiError__set(error, "check proxy", DPI_ERR_INVALID_PROXY); - - // if the userName is provided but no password is provided and external - // authentication is not being used, proxy authentication is taking - // place - if (userName && !password && !externalAuth) - mode |= DPI_OCI_SESSGET_CREDPROXY; - if (createParams->matchAnyTag) - mode |= DPI_OCI_SESSGET_SPOOL_MATCHANY; - if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2, - NULL) == DPI_SUCCESS && createParams->tag && - createParams->tagLength > 0) - mode |= DPI_OCI_SESSGET_MULTIPROPERTY_TAG; - } else { - mode = DPI_OCI_SESSGET_STMTCACHE; - externalAuth = createParams->externalAuth; - } - if (createParams->authMode & DPI_MODE_AUTH_SYSDBA) - mode |= DPI_OCI_SESSGET_SYSDBA; - if (externalAuth) - mode |= DPI_OCI_SESSGET_CREDEXT; - - // create authorization handle - if (dpiOci__handleAlloc(conn->env->handle, &authInfo, - DPI_OCI_HTYPE_AUTHINFO, "allocate authinfo handle", error) < 0) - return DPI_FAILURE; - - // set attributes for create parameters - if (dpiConn__setAttributesFromCreateParams(conn, authInfo, - DPI_OCI_HTYPE_AUTHINFO, userName, userNameLength, password, - passwordLength, createParams, error) < 0) { - dpiOci__handleFree(authInfo, DPI_OCI_HTYPE_AUTHINFO); - return DPI_FAILURE; - } - - // get a session from the pool - status = dpiConn__getSession(conn, mode, connectString, - connectStringLength, createParams, authInfo, error); - dpiOci__handleFree(authInfo, DPI_OCI_HTYPE_AUTHINFO); - if (status < 0) - return status; - return dpiConn__getServerCharset(conn, error); -} - - -//----------------------------------------------------------------------------- -// dpiConn__getAttributeText() [INTERNAL] -// Get the value of the OCI attribute from a text string. -//----------------------------------------------------------------------------- -static int dpiConn__getAttributeText(dpiConn *conn, uint32_t attribute, - const char **value, uint32_t *valueLength, const char *fnName) -{ - dpiError error; - int status; - - // validate parameters - if (dpiConn__check(conn, fnName, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, value) - DPI_CHECK_PTR_NOT_NULL(conn, valueLength) - - // determine pointer to pass (OCI uses different sizes) - switch (attribute) { - case DPI_OCI_ATTR_CURRENT_SCHEMA: - case DPI_OCI_ATTR_LTXID: - case DPI_OCI_ATTR_EDITION: - status = dpiOci__attrGet(conn->sessionHandle, - DPI_OCI_HTYPE_SESSION, (void*) value, valueLength, - attribute, "get session value", &error); - break; - case DPI_OCI_ATTR_INTERNAL_NAME: - case DPI_OCI_ATTR_EXTERNAL_NAME: - status = dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, - (void*) value, valueLength, attribute, "get server value", - &error); - break; - default: - status = dpiError__set(&error, "get attribute text", - DPI_ERR_NOT_SUPPORTED); - break; - } - - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn__getHandles() [INTERNAL] -// Get the server and session handle from the service context handle. -//----------------------------------------------------------------------------- -static int dpiConn__getHandles(dpiConn *conn, dpiError *error) -{ - if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, - (void*) &conn->sessionHandle, NULL, DPI_OCI_ATTR_SESSION, - "get session handle", error) < 0) - return DPI_FAILURE; - if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, - (void*) &conn->serverHandle, NULL, DPI_OCI_ATTR_SERVER, - "get server handle", error) < 0) - return DPI_FAILURE; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiConn__getRawTDO() [INTERNAL] -// Internal method used for ensuring that the RAW TDO has been cached on the -//connection. -//----------------------------------------------------------------------------- -int dpiConn__getRawTDO(dpiConn *conn, dpiError *error) -{ - if (conn->rawTDO) - return DPI_SUCCESS; - return dpiOci__typeByName(conn, "SYS", 3, "RAW", 3, &conn->rawTDO, error); -} - - -//----------------------------------------------------------------------------- -// dpiConn__getServerCharset() [INTERNAL] -// Internal method used for retrieving the server character set. This is used -// to determine if any conversion is required when transferring strings between -// the client and the server. -//----------------------------------------------------------------------------- -static int dpiConn__getServerCharset(dpiConn *conn, dpiError *error) -{ - return dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, - &conn->charsetId, NULL, DPI_OCI_ATTR_CHARSET_ID, - "get server charset id", error); -} - - -//----------------------------------------------------------------------------- -// dpiConn__getServerVersion() [INTERNAL] -// Internal method used for ensuring that the server version has been cached -// on the connection. -//----------------------------------------------------------------------------- -int dpiConn__getServerVersion(dpiConn *conn, dpiError *error) -{ - uint32_t serverRelease; - char buffer[512]; - - // nothing to do if the server version has been determined earlier - if (conn->releaseString) - return DPI_SUCCESS; - - // get server version - if (dpiOci__serverRelease(conn, buffer, sizeof(buffer), &serverRelease, - error) < 0) - return DPI_FAILURE; - conn->releaseStringLength = (uint32_t) strlen(buffer); - if (dpiUtils__allocateMemory(1, conn->releaseStringLength, 0, - "allocate release string", (void**) &conn->releaseString, - error) < 0) - return DPI_FAILURE; - strncpy( (char*) conn->releaseString, buffer, conn->releaseStringLength); - conn->versionInfo.versionNum = (int)((serverRelease >> 24) & 0xFF); - if (conn->versionInfo.versionNum >= 18) { - conn->versionInfo.releaseNum = (int)((serverRelease >> 16) & 0xFF); - conn->versionInfo.updateNum = (int)((serverRelease >> 12) & 0x0F); - conn->versionInfo.portReleaseNum = (int)((serverRelease >> 4) & 0xFF); - conn->versionInfo.portUpdateNum = (int)((serverRelease) & 0xF); - } else { - conn->versionInfo.releaseNum = (int)((serverRelease >> 20) & 0x0F); - conn->versionInfo.updateNum = (int)((serverRelease >> 12) & 0xFF); - conn->versionInfo.portReleaseNum = (int)((serverRelease >> 8) & 0x0F); - conn->versionInfo.portUpdateNum = (int)((serverRelease) & 0xFF); - } - conn->versionInfo.fullVersionNum = (uint32_t) - DPI_ORACLE_VERSION_TO_NUMBER(conn->versionInfo.versionNum, - conn->versionInfo.releaseNum, - conn->versionInfo.updateNum, - conn->versionInfo.portReleaseNum, - conn->versionInfo.portUpdateNum); - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiConn__getSession() [INTERNAL] -// Ping and loop until we get a good session. When a database instance goes -// down, it can leave several bad connections that need to be flushed out -// before a good connection can be acquired. If the connection is brand new -// (ping time context value has not been set) there is no need to do a ping. -// This also ensures that the loop cannot run forever! -//----------------------------------------------------------------------------- -static int dpiConn__getSession(dpiConn *conn, uint32_t mode, - const char *connectString, uint32_t connectStringLength, - dpiConnCreateParams *params, void *authInfo, dpiError *error) -{ - uint8_t savedBreakOnTimeout, breakOnTimeout; - uint32_t savedTimeout; - time_t *lastTimeUsed; - - while (1) { - - // acquire the new session - params->outNewSession = 0; - if (dpiOci__sessionGet(conn->env->handle, &conn->handle, authInfo, - connectString, connectStringLength, params->tag, - params->tagLength, ¶ms->outTag, ¶ms->outTagLength, - ¶ms->outTagFound, mode, error) < 0) - return DPI_FAILURE; - - // get session and server handles - if (dpiConn__getHandles(conn, error) < 0) - return DPI_FAILURE; - - // get last time used from session context - lastTimeUsed = NULL; - if (dpiOci__contextGetValue(conn, DPI_CONTEXT_LAST_TIME_USED, - (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), - (void**) &lastTimeUsed, 1, error) < 0) - return DPI_FAILURE; - - // if value is not found, a new connection has been created and there - // is no need to perform a ping; nor if we are creating a standalone - // connection - if (!lastTimeUsed || !conn->pool) { - params->outNewSession = 1; - break; - } - - // if ping interval is negative or the ping interval (in seconds) - // has not been exceeded yet, there is also no need to perform a ping - if (conn->pool->pingInterval < 0 || - *lastTimeUsed + conn->pool->pingInterval > time(NULL)) - break; - - // ping needs to be done at this point; set parameters to ensure that - // the ping does not take too long to complete; keep original values - dpiOci__attrGet(conn->serverHandle, - DPI_OCI_HTYPE_SERVER, &savedTimeout, NULL, - DPI_OCI_ATTR_RECEIVE_TIMEOUT, NULL, error); - dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, - &conn->pool->pingTimeout, 0, DPI_OCI_ATTR_RECEIVE_TIMEOUT, - NULL, error); - if (conn->env->versionInfo->versionNum >= 12) { - dpiOci__attrGet(conn->serverHandle, - DPI_OCI_HTYPE_SERVER, &savedBreakOnTimeout, NULL, - DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, NULL, error); - breakOnTimeout = 0; - dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, - &breakOnTimeout, 0, DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, - NULL, error); - } - - // if ping is successful, the connection is valid and can be returned - // restore original network parameters - if (dpiOci__ping(conn, error) == 0) { - dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, - &savedTimeout, 0, DPI_OCI_ATTR_RECEIVE_TIMEOUT, NULL, - error); - if (conn->env->versionInfo->versionNum >= 12) - dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, - &savedBreakOnTimeout, 0, - DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, NULL, error); - break; - } - - // session is bad, need to release and drop it - dpiOci__sessionRelease(conn, NULL, 0, DPI_OCI_SESSRLS_DROPSESS, 0, - error); - conn->handle = NULL; - conn->serverHandle = NULL; - conn->sessionHandle = NULL; - conn->deadSession = 0; - - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiConn__setAppContext() [INTERNAL] -// Populate the session handle with the application context. -//----------------------------------------------------------------------------- -static int dpiConn__setAppContext(void *handle, uint32_t handleType, - const dpiConnCreateParams *params, dpiError *error) -{ - void *listHandle, *entryHandle; - dpiAppContext *entry; - uint32_t i; - - // set the number of application context entries - if (dpiOci__attrSet(handle, handleType, (void*) ¶ms->numAppContext, - sizeof(params->numAppContext), DPI_OCI_ATTR_APPCTX_SIZE, - "set app context size", error) < 0) - return DPI_FAILURE; - - // get the application context list handle - if (dpiOci__attrGet(handle, handleType, &listHandle, NULL, - DPI_OCI_ATTR_APPCTX_LIST, "get context list handle", error) < 0) - return DPI_FAILURE; - - // set each application context entry - for (i = 0; i < params->numAppContext; i++) { - entry = ¶ms->appContext[i]; - - // retrieve the context element descriptor - if (dpiOci__paramGet(listHandle, DPI_OCI_DTYPE_PARAM, - &entryHandle, i + 1, "get context entry handle", error) < 0) - return DPI_FAILURE; - - // set the namespace name - if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM, - (void*) entry->namespaceName, entry->namespaceNameLength, - DPI_OCI_ATTR_APPCTX_NAME, "set namespace name", error) < 0) - return DPI_FAILURE; - - // set the name - if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM, - (void*) entry->name, entry->nameLength, - DPI_OCI_ATTR_APPCTX_ATTR, "set name", error) < 0) - return DPI_FAILURE; - - // set the value - if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM, - (void*) entry->value, entry->valueLength, - DPI_OCI_ATTR_APPCTX_VALUE, "set value", error) < 0) - return DPI_FAILURE; - - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiConn__setAttributesFromCreateParams() [INTERNAL] -// Populate the authorization info structure or session handle using the -// create parameters specified. -//----------------------------------------------------------------------------- -static int dpiConn__setAttributesFromCreateParams(dpiConn *conn, void *handle, - uint32_t handleType, const char *userName, uint32_t userNameLength, - const char *password, uint32_t passwordLength, - const dpiConnCreateParams *params, dpiError *error) -{ - uint32_t purity; - - // set credentials - if (userName && userNameLength > 0 && dpiOci__attrSet(handle, - handleType, (void*) userName, userNameLength, - DPI_OCI_ATTR_USERNAME, "set user name", error) < 0) - return DPI_FAILURE; - if (password && passwordLength > 0 && dpiOci__attrSet(handle, - handleType, (void*) password, passwordLength, - DPI_OCI_ATTR_PASSWORD, "set password", error) < 0) - return DPI_FAILURE; - - // set connection class and purity parameters - if (params->connectionClass && params->connectionClassLength > 0 && - dpiOci__attrSet(handle, handleType, - (void*) params->connectionClass, - params->connectionClassLength, - DPI_OCI_ATTR_CONNECTION_CLASS, "set connection class", - error) < 0) - return DPI_FAILURE; - if (params->purity != DPI_OCI_ATTR_PURITY_DEFAULT) { - purity = params->purity; - if (dpiOci__attrSet(handle, handleType, &purity, - sizeof(purity), DPI_OCI_ATTR_PURITY, "set purity", error) < 0) - return DPI_FAILURE; - } - - // set sharding key and super sharding key parameters - if (params->shardingKeyColumns && params->numShardingKeyColumns > 0) { - if (dpiConn__setShardingKey(conn, &conn->shardingKey, handle, - handleType, DPI_OCI_ATTR_SHARDING_KEY, "set sharding key", - params->shardingKeyColumns, params->numShardingKeyColumns, - error) < 0) - return DPI_FAILURE; - } - if (params->superShardingKeyColumns && - params->numSuperShardingKeyColumns > 0) { - if (params->numShardingKeyColumns == 0) - return dpiError__set(error, "ensure sharding key", - DPI_ERR_MISSING_SHARDING_KEY); - if (dpiConn__setShardingKey(conn, &conn->superShardingKey, handle, - handleType, DPI_OCI_ATTR_SUPER_SHARDING_KEY, - "set super sharding key", params->superShardingKeyColumns, - params->numSuperShardingKeyColumns, error) < 0) - return DPI_FAILURE; - } - - // set application context, if applicable - if (handleType == DPI_OCI_HTYPE_SESSION && params->numAppContext > 0) - return dpiConn__setAppContext(handle, handleType, params, error); - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiConn__setAttributeText() [INTERNAL] -// Set the value of the OCI attribute from a text string. -//----------------------------------------------------------------------------- -static int dpiConn__setAttributeText(dpiConn *conn, uint32_t attribute, - const char *value, uint32_t valueLength, const char *fnName) -{ - dpiError error; - int status; - - // validate parameters - if (dpiConn__check(conn, fnName, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(conn, value) - - // determine pointer to pass (OCI uses different sizes) - switch (attribute) { - case DPI_OCI_ATTR_ACTION: - case DPI_OCI_ATTR_CLIENT_IDENTIFIER: - case DPI_OCI_ATTR_CLIENT_INFO: - case DPI_OCI_ATTR_CURRENT_SCHEMA: - case DPI_OCI_ATTR_EDITION: - case DPI_OCI_ATTR_MODULE: - case DPI_OCI_ATTR_DBOP: - status = dpiOci__attrSet(conn->sessionHandle, - DPI_OCI_HTYPE_SESSION, (void*) value, valueLength, - attribute, "set session value", &error); - break; - case DPI_OCI_ATTR_INTERNAL_NAME: - case DPI_OCI_ATTR_EXTERNAL_NAME: - status = dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, - (void*) value, valueLength, attribute, "set server value", - &error); - break; - default: - status = dpiError__set(&error, "set attribute text", - DPI_ERR_NOT_SUPPORTED); - break; - } - - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn__setShardingKey() [INTERNAL] -// Using the specified columns, create a sharding key and set it on the given -// handle. -//----------------------------------------------------------------------------- -static int dpiConn__setShardingKey(dpiConn *conn, void **shardingKey, - void *handle, uint32_t handleType, uint32_t attribute, - const char *action, dpiShardingKeyColumn *columns, uint8_t numColumns, - dpiError *error) -{ - uint8_t i; - - // this is only supported on 12.2 and higher clients - if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2, - error) < 0) - return DPI_FAILURE; - - // create sharding key descriptor, if necessary - if (dpiOci__descriptorAlloc(conn->env->handle, shardingKey, - DPI_OCI_DTYPE_SHARDING_KEY, "allocate sharding key", error) < 0) - return DPI_FAILURE; - - // add each column to the sharding key - for (i = 0; i < numColumns; i++) { - if (dpiConn__setShardingKeyValue(conn, *shardingKey, &columns[i], - error) < 0) - return DPI_FAILURE; - } - - // add the sharding key to the handle - if (dpiOci__attrSet(handle, handleType, *shardingKey, 0, attribute, action, - error) < 0) - return DPI_FAILURE; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiConn__setShardingKeyValue() [INTERNAL] -// Using the specified columns, create a sharding key and set it on the given -// handle. -//----------------------------------------------------------------------------- -static int dpiConn__setShardingKeyValue(dpiConn *conn, void *shardingKey, - dpiShardingKeyColumn *column, dpiError *error) -{ - dpiShardingOciDate shardingDateValue; - uint32_t colLen = 0, descType = 0; - const dpiOracleType *oracleType; - dpiOciNumber numberValue; - int convertOk, status; - dpiOciDate dateValue; - void *col = NULL; - uint16_t colType; - - oracleType = dpiOracleType__getFromNum(column->oracleTypeNum, error); - if (!oracleType) - return DPI_FAILURE; - convertOk = 0; - colType = oracleType->oracleType; - switch (column->oracleTypeNum) { - case DPI_ORACLE_TYPE_VARCHAR: - case DPI_ORACLE_TYPE_CHAR: - case DPI_ORACLE_TYPE_RAW: - if (column->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { - col = column->value.asBytes.ptr; - colLen = column->value.asBytes.length; - convertOk = 1; - } - break; - case DPI_ORACLE_TYPE_NUMBER: - col = &numberValue; - colLen = sizeof(numberValue); - if (column->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { - if (dpiDataBuffer__toOracleNumberFromDouble(&column->value, - error, &numberValue) < 0) - return DPI_FAILURE; - convertOk = 1; - } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_INT64) { - if (dpiDataBuffer__toOracleNumberFromInteger(&column->value, - error, &numberValue) < 0) - return DPI_FAILURE; - convertOk = 1; - } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_UINT64) { - if (dpiDataBuffer__toOracleNumberFromUnsignedInteger( - &column->value, error, &numberValue) < 0) - return DPI_FAILURE; - convertOk = 1; - } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { - if (dpiDataBuffer__toOracleNumberFromText(&column->value, - conn->env, error, &numberValue) < 0) - return DPI_FAILURE; - convertOk = 1; - } - break; - case DPI_ORACLE_TYPE_DATE: - if (column->nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) { - if (dpiDataBuffer__toOracleDate(&column->value, - &dateValue) < 0) - return DPI_FAILURE; - convertOk = 1; - } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { - if (dpiDataBuffer__toOracleDateFromDouble(&column->value, - conn->env, error, &dateValue) < 0) - return DPI_FAILURE; - convertOk = 1; - } - - // for sharding only, the type must be SQLT_DAT, which uses a - // different format for storing the date values - if (convertOk) { - col = &shardingDateValue; - colLen = sizeof(shardingDateValue); - colType = DPI_SQLT_DAT; - shardingDateValue.century = - ((uint8_t) (dateValue.year / 100)) + 100; - shardingDateValue.year = (dateValue.year % 100) + 100; - shardingDateValue.month = dateValue.month; - shardingDateValue.day = dateValue.day; - shardingDateValue.hour = dateValue.hour + 1; - shardingDateValue.minute = dateValue.minute + 1; - shardingDateValue.second = dateValue.second + 1; - } - break; - case DPI_ORACLE_TYPE_TIMESTAMP: - case DPI_ORACLE_TYPE_TIMESTAMP_TZ: - case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: - colLen = sizeof(void*); - colType = DPI_SQLT_TIMESTAMP; - if (column->nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) { - descType = DPI_OCI_DTYPE_TIMESTAMP; - if (dpiOci__descriptorAlloc(conn->env->handle, &col, descType, - "alloc timestamp", error) < 0) - return DPI_FAILURE; - if (dpiDataBuffer__toOracleTimestamp(&column->value, conn->env, - error, col, 0) < 0) { - dpiOci__descriptorFree(col, descType); - return DPI_FAILURE; - } - convertOk = 1; - } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { - descType = DPI_OCI_DTYPE_TIMESTAMP_LTZ; - if (dpiOci__descriptorAlloc(conn->env->handle, &col, descType, - "alloc LTZ timestamp", error) < 0) - return DPI_FAILURE; - if (dpiDataBuffer__toOracleTimestampFromDouble(&column->value, - conn->env, error, col) < 0) { - dpiOci__descriptorFree(col, descType); - return DPI_FAILURE; - } - convertOk = 1; - } - break; - default: - break; - } - if (!convertOk) - return dpiError__set(error, "check type", DPI_ERR_NOT_SUPPORTED); - - status = dpiOci__shardingKeyColumnAdd(shardingKey, col, colLen, colType, - error); - if (descType) - dpiOci__descriptorFree(col, descType); - return status; -} - - -//----------------------------------------------------------------------------- -// dpiConn_addRef() [PUBLIC] -// Add a reference to the connection. -//----------------------------------------------------------------------------- -int dpiConn_addRef(dpiConn *conn) -{ - return dpiGen__addRef(conn, DPI_HTYPE_CONN, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_beginDistribTrans() [PUBLIC] -// Begin a distributed transaction. -//----------------------------------------------------------------------------- -int dpiConn_beginDistribTrans(dpiConn *conn, long formatId, - const char *transactionId, uint32_t transactionIdLength, - const char *branchId, uint32_t branchIdLength) -{ - void *transactionHandle; - dpiError error; - dpiOciXID xid; - int status; - - // validate parameters - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(conn, transactionId) - DPI_CHECK_PTR_AND_LENGTH(conn, branchId) - if (transactionIdLength > DPI_XA_MAXGTRIDSIZE) { - dpiError__set(&error, "check size of transaction id", - DPI_ERR_TRANS_ID_TOO_LARGE, transactionIdLength, - DPI_XA_MAXGTRIDSIZE); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - if (branchIdLength > DPI_XA_MAXBQUALSIZE) { - dpiError__set(&error, "check size of branch id", - DPI_ERR_BRANCH_ID_TOO_LARGE, branchIdLength, - DPI_XA_MAXBQUALSIZE); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - // determine if a transaction handle was previously allocated - if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, - (void*) &transactionHandle, NULL, DPI_OCI_ATTR_TRANS, - "get transaction handle", &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - - // if one was not found, create one and associate it with the connection - if (!transactionHandle) { - - // create new handle - if (dpiOci__handleAlloc(conn->env->handle, &transactionHandle, - DPI_OCI_HTYPE_TRANS, "create transaction handle", &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - - // associate the transaction with the connection - if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, - transactionHandle, 0, DPI_OCI_ATTR_TRANS, - "associate transaction", &error) < 0) { - dpiOci__handleFree(transactionHandle, DPI_OCI_HTYPE_TRANS); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - } - - // set the XID for the transaction, if applicable - if (formatId != -1) { - xid.formatID = formatId; - xid.gtrid_length = transactionIdLength; - xid.bqual_length = branchIdLength; - if (transactionIdLength > 0) - strncpy(xid.data, transactionId, transactionIdLength); - if (branchIdLength > 0) - strncpy(&xid.data[transactionIdLength], branchId, branchIdLength); - if (dpiOci__attrSet(transactionHandle, DPI_OCI_HTYPE_TRANS, &xid, - sizeof(dpiOciXID), DPI_OCI_ATTR_XID, "set XID", &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - // start the transaction - status = dpiOci__transStart(conn, &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_breakExecution() [PUBLIC] -// Break (interrupt) the currently executing operation. -//----------------------------------------------------------------------------- -int dpiConn_breakExecution(dpiConn *conn) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - status = dpiOci__break(conn, &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_changePassword() [PUBLIC] -// Change the password for the specified user. -//----------------------------------------------------------------------------- -int dpiConn_changePassword(dpiConn *conn, const char *userName, - uint32_t userNameLength, const char *oldPassword, - uint32_t oldPasswordLength, const char *newPassword, - uint32_t newPasswordLength) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(conn, userName) - DPI_CHECK_PTR_AND_LENGTH(conn, oldPassword) - DPI_CHECK_PTR_AND_LENGTH(conn, newPassword) - status = dpiOci__passwordChange(conn, userName, userNameLength, - oldPassword, oldPasswordLength, newPassword, newPasswordLength, - DPI_OCI_DEFAULT, &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_close() [PUBLIC] -// Close the connection and ensure it can no longer be used. -//----------------------------------------------------------------------------- -int dpiConn_close(dpiConn *conn, dpiConnCloseMode mode, const char *tag, - uint32_t tagLength) -{ - int propagateErrors = !(mode & DPI_MODE_CONN_CLOSE_DROP); - dpiError error; - int closing; - - // validate parameters - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(conn, tag) - if (mode && !conn->pool) { - dpiError__set(&error, "check in pool", DPI_ERR_CONN_NOT_IN_POOL); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - if (conn->externalHandle) { - dpiError__set(&error, "check external", DPI_ERR_CONN_IS_EXTERNAL); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - // determine whether connection is already being closed and if not, mark - // connection as being closed; this MUST be done while holding the lock - // (if in threaded mode) to avoid race conditions! - if (conn->env->threaded) - dpiMutex__acquire(conn->env->mutex); - closing = conn->closing; - conn->closing = 1; - if (conn->env->threaded) - dpiMutex__release(conn->env->mutex); - - // if connection is already being closed, raise an exception - if (closing) { - dpiError__set(&error, "check closing", DPI_ERR_NOT_CONNECTED); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - // if actual close fails, reset closing flag; again, this must be done - // while holding the lock (if in threaded mode) in order to avoid race - // conditions! - if (dpiConn__close(conn, mode, tag, tagLength, propagateErrors, - &error) < 0) { - if (conn->env->threaded) - dpiMutex__acquire(conn->env->mutex); - conn->closing = 0; - if (conn->env->threaded) - dpiMutex__release(conn->env->mutex); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_commit() [PUBLIC] -// Commit the transaction associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_commit(dpiConn *conn) -{ - dpiError error; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiOci__transCommit(conn, conn->commitMode, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - conn->commitMode = DPI_OCI_DEFAULT; - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_create() [PUBLIC] -// Create a standalone connection to the database using the parameters -// specified. -//----------------------------------------------------------------------------- -int dpiConn_create(const dpiContext *context, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - const char *connectString, uint32_t connectStringLength, - const dpiCommonCreateParams *commonParams, - dpiConnCreateParams *createParams, dpiConn **conn) -{ - dpiCommonCreateParams localCommonParams; - dpiConnCreateParams localCreateParams; - dpiConn *tempConn; - dpiError error; - int status; - - // validate parameters - if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, - &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(context, conn) - DPI_CHECK_PTR_AND_LENGTH(context, userName) - DPI_CHECK_PTR_AND_LENGTH(context, password) - DPI_CHECK_PTR_AND_LENGTH(context, connectString) - - // use default parameters if none provided - if (!commonParams) { - dpiContext__initCommonCreateParams(&localCommonParams); - commonParams = &localCommonParams; - } - - // size changed in 3.1; must use local variable until version 4 released - if (!createParams || context->dpiMinorVersion < 1) { - dpiContext__initConnCreateParams(&localCreateParams); - if (createParams) - memcpy(&localCreateParams, createParams, - sizeof(dpiConnCreateParams__v30)); - createParams = &localCreateParams; - } - - // password must not be specified if external authentication is desired - if (createParams->externalAuth && password && passwordLength > 0) { - dpiError__set(&error, "verify no password with external auth", - DPI_ERR_EXT_AUTH_WITH_CREDENTIALS); - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - } - - // the username must be enclosed within [] if external authentication - // with proxy is desired - if (createParams->externalAuth && userName && userNameLength > 0 && - (userName[0] != '[' || userName[userNameLength - 1] != ']')) { - dpiError__set(&error, "verify proxy user name with external auth", - DPI_ERR_EXT_AUTH_INVALID_PROXY); - return dpiGen__endPublicFn(context, DPI_FAILURE, &error ); - } - - // connectionClass and edition cannot be specified at the same time - if (createParams->connectionClass && - createParams->connectionClassLength > 0 && - commonParams->edition && commonParams->editionLength > 0) { - dpiError__set(&error, "check edition/conn class", - DPI_ERR_NO_EDITION_WITH_CONN_CLASS); - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - } - - // newPassword and edition cannot be specified at the same time - if (createParams->newPassword && createParams->newPasswordLength > 0 && - commonParams->edition && commonParams->editionLength > 0) { - dpiError__set(&error, "check edition/new password", - DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD); - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - } - - // handle case where pool is specified - if (createParams->pool) { - if (dpiGen__checkHandle(createParams->pool, DPI_HTYPE_POOL, - "verify pool", &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - if (!createParams->pool->handle) { - dpiError__set(&error, "check pool", DPI_ERR_NOT_CONNECTED); - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - } - status = dpiPool__acquireConnection(createParams->pool, userName, - userNameLength, password, passwordLength, createParams, conn, - &error); - return dpiGen__endPublicFn(context, status, &error); - } - - // create connection - if (dpiGen__allocate(DPI_HTYPE_CONN, NULL, (void**) &tempConn, &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - if (dpiConn__create(tempConn, context, userName, userNameLength, - password, passwordLength, connectString, connectStringLength, - NULL, commonParams, createParams, &error) < 0) { - dpiConn__free(tempConn, &error); - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - } - - *conn = tempConn; - dpiHandlePool__release(tempConn->env->errorHandles, &error.handle); - return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getSodaDb() [PUBLIC] -// Create a new SODA collection with the given name and metadata. -//----------------------------------------------------------------------------- -int dpiConn_getSodaDb(dpiConn *conn, dpiSodaDb **db) -{ - dpiError error; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 3, - &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiUtils__checkDatabaseVersion(conn, 18, 0, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiGen__allocate(DPI_HTYPE_SODA_DB, conn->env, (void**) db, - &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - dpiGen__setRefCount(conn, &error, 1); - (*db)->conn = conn; - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_deqObject() [PUBLIC] -// Dequeue a message from the specified queue. -//----------------------------------------------------------------------------- -int dpiConn_deqObject(dpiConn *conn, const char *queueName, - uint32_t queueNameLength, dpiDeqOptions *options, dpiMsgProps *props, - dpiObject *payload, const char **msgId, uint32_t *msgIdLength) -{ - dpiError error; - - // validate parameters - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiGen__checkHandle(options, DPI_HTYPE_DEQ_OPTIONS, "verify options", - &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS, - "verify message properties", &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiGen__checkHandle(payload, DPI_HTYPE_OBJECT, "verify payload", - &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(conn, queueName) - DPI_CHECK_PTR_NOT_NULL(conn, msgId) - DPI_CHECK_PTR_NOT_NULL(conn, msgIdLength) - - // dequeue message - if (dpiOci__aqDeq(conn, queueName, options->handle, props->handle, - payload->type->tdo, &payload->instance, &payload->indicator, - &props->msgIdRaw, &error) < 0) { - if (error.buffer->code == 25228) { - *msgId = NULL; - *msgIdLength = 0; - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); - } - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - dpiMsgProps__extractMsgId(props, msgId, msgIdLength); - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_enqObject() [PUBLIC] -// Enqueue a message to the specified queue. -//----------------------------------------------------------------------------- -int dpiConn_enqObject(dpiConn *conn, const char *queueName, - uint32_t queueNameLength, dpiEnqOptions *options, dpiMsgProps *props, - dpiObject *payload, const char **msgId, uint32_t *msgIdLength) -{ - dpiError error; - - // validate parameters - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiGen__checkHandle(options, DPI_HTYPE_ENQ_OPTIONS, "verify options", - &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS, - "verify message properties", &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiGen__checkHandle(payload, DPI_HTYPE_OBJECT, "verify payload", - &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(conn, queueName) - DPI_CHECK_PTR_NOT_NULL(conn, msgId) - DPI_CHECK_PTR_NOT_NULL(conn, msgIdLength) - - // enqueue message - if (dpiOci__aqEnq(conn, queueName, options->handle, props->handle, - payload->type->tdo, &payload->instance, &payload->indicator, - &props->msgIdRaw, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - dpiMsgProps__extractMsgId(props, msgId, msgIdLength); - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getCallTimeout() [PUBLIC] -// Return the call timeout (in milliseconds) used for round-trips to the -// database. This is only valid in Oracle Client 18c and higher. -//----------------------------------------------------------------------------- -int dpiConn_getCallTimeout(dpiConn *conn, uint32_t *value) -{ - dpiError error; - int status; - - // validate parameters - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, value) - if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 1, - &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - - // get call timeout - status = dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, - (void*) value, 0, DPI_OCI_ATTR_CALL_TIMEOUT, "get call timeout", - &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getCurrentSchema() [PUBLIC] -// Return the current schema associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_getCurrentSchema(dpiConn *conn, const char **value, - uint32_t *valueLength) -{ - return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_CURRENT_SCHEMA, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getEdition() [PUBLIC] -// Return the edition associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_getEdition(dpiConn *conn, const char **value, - uint32_t *valueLength) -{ - return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_EDITION, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getEncodingInfo() [PUBLIC] -// Get the encodings from the connection. -//----------------------------------------------------------------------------- -int dpiConn_getEncodingInfo(dpiConn *conn, dpiEncodingInfo *info) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - status = dpiEnv__getEncodingInfo(conn->env, info); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getExternalName() [PUBLIC] -// Return the external name associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_getExternalName(dpiConn *conn, const char **value, - uint32_t *valueLength) -{ - return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_EXTERNAL_NAME, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getHandle() [PUBLIC] -// Get the OCI service context handle associated with the connection. This is -// available in order to allow for extensions to the library using OCI -// directly. -//----------------------------------------------------------------------------- -int dpiConn_getHandle(dpiConn *conn, void **handle) -{ - dpiError error; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, handle) - *handle = conn->handle; - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getInternalName() [PUBLIC] -// Return the internal name associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_getInternalName(dpiConn *conn, const char **value, - uint32_t *valueLength) -{ - return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_INTERNAL_NAME, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getLTXID() [PUBLIC] -// Return the logical transaction id associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_getLTXID(dpiConn *conn, const char **value, uint32_t *valueLength) -{ - return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_LTXID, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getObjectType() [PUBLIC] -// Look up an object type given its name and return it. -//----------------------------------------------------------------------------- -int dpiConn_getObjectType(dpiConn *conn, const char *name, uint32_t nameLength, - dpiObjectType **objType) -{ - void *describeHandle, *param, *tdo; - int status, useTypeByFullName; - dpiError error; - - // validate parameters - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, name) - DPI_CHECK_PTR_NOT_NULL(conn, objType) - - // allocate describe handle - if (dpiOci__handleAlloc(conn->env->handle, &describeHandle, - DPI_OCI_HTYPE_DESCRIBE, "allocate describe handle", &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - - // Oracle Client 12.1 is capable of using OCITypeByFullName() but will - // fail if accessing an Oracle 11.2 database - useTypeByFullName = 1; - if (conn->env->versionInfo->versionNum < 12) - useTypeByFullName = 0; - else if (dpiConn__getServerVersion(conn, &error) < 0) - return DPI_FAILURE; - else if (conn->versionInfo.versionNum < 12) - useTypeByFullName = 0; - - // new API is supported so use it - if (useTypeByFullName) { - if (dpiOci__typeByFullName(conn, name, nameLength, &tdo, &error) < 0) { - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - if (dpiOci__describeAny(conn, tdo, 0, DPI_OCI_OTYPE_PTR, - describeHandle, &error) < 0) { - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - // use older API - } else { - if (dpiOci__describeAny(conn, (void*) name, nameLength, - DPI_OCI_OTYPE_NAME, describeHandle, &error) < 0) { - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - } - - // get the parameter handle - if (dpiOci__attrGet(describeHandle, - DPI_OCI_HTYPE_DESCRIBE, ¶m, 0, DPI_OCI_ATTR_PARAM, - "get param", &error) < 0) { - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - // create object type - status = dpiObjectType__allocate(conn, param, DPI_OCI_ATTR_NAME, objType, - &error); - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getServerVersion() [PUBLIC] -// Get the server version string from the database. -//----------------------------------------------------------------------------- -int dpiConn_getServerVersion(dpiConn *conn, const char **releaseString, - uint32_t *releaseStringLength, dpiVersionInfo *versionInfo) -{ - dpiError error; - - // validate parameters - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, versionInfo) - - // get server version - if (dpiConn__getServerVersion(conn, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (releaseString) - *releaseString = conn->releaseString; - if (releaseStringLength) - *releaseStringLength = conn->releaseStringLength; - memcpy(versionInfo, &conn->versionInfo, sizeof(dpiVersionInfo)); - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_getStmtCacheSize() [PUBLIC] -// Return the current size of the statement cache. -//----------------------------------------------------------------------------- -int dpiConn_getStmtCacheSize(dpiConn *conn, uint32_t *cacheSize) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, cacheSize) - status = dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, cacheSize, - NULL, DPI_OCI_ATTR_STMTCACHESIZE, "get stmt cache size", &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_newDeqOptions() [PUBLIC] -// Create a new dequeue options object and return it. -//----------------------------------------------------------------------------- -int dpiConn_newDeqOptions(dpiConn *conn, dpiDeqOptions **options) -{ - dpiDeqOptions *tempOptions; - dpiError error; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, options) - if (dpiGen__allocate(DPI_HTYPE_DEQ_OPTIONS, conn->env, - (void**) &tempOptions, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiDeqOptions__create(tempOptions, conn, &error) < 0) { - dpiDeqOptions__free(tempOptions, &error); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - *options = tempOptions; - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_newEnqOptions() [PUBLIC] -// Create a new enqueue options object and return it. -//----------------------------------------------------------------------------- -int dpiConn_newEnqOptions(dpiConn *conn, dpiEnqOptions **options) -{ - dpiEnqOptions *tempOptions; - dpiError error; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, options) - if (dpiGen__allocate(DPI_HTYPE_ENQ_OPTIONS, conn->env, - (void**) &tempOptions, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiEnqOptions__create(tempOptions, conn, &error) < 0) { - dpiEnqOptions__free(tempOptions, &error); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - *options = tempOptions; - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_newTempLob() [PUBLIC] -// Create a new temporary LOB and return it. -//----------------------------------------------------------------------------- -int dpiConn_newTempLob(dpiConn *conn, dpiOracleTypeNum lobType, dpiLob **lob) -{ - const dpiOracleType *type; - dpiLob *tempLob; - dpiError error; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, lob) - switch (lobType) { - case DPI_ORACLE_TYPE_CLOB: - case DPI_ORACLE_TYPE_BLOB: - case DPI_ORACLE_TYPE_NCLOB: - type = dpiOracleType__getFromNum(lobType, &error); - break; - default: - dpiError__set(&error, "check lob type", - DPI_ERR_INVALID_ORACLE_TYPE, lobType); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - if (dpiLob__allocate(conn, type, &tempLob, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiOci__lobCreateTemporary(tempLob, &error) < 0) { - dpiLob__free(tempLob, &error); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - *lob = tempLob; - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_newMsgProps() [PUBLIC] -// Create a new message properties object and return it. -//----------------------------------------------------------------------------- -int dpiConn_newMsgProps(dpiConn *conn, dpiMsgProps **props) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, props) - status = dpiMsgProps__allocate(conn, props, &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_newQueue() [PUBLIC] -// Create a new AQ queue object and return it. -//----------------------------------------------------------------------------- -int dpiConn_newQueue(dpiConn *conn, const char *name, uint32_t nameLength, - dpiObjectType *payloadType, dpiQueue **queue) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(conn, name) - DPI_CHECK_PTR_NOT_NULL(conn, queue) - status = dpiQueue__allocate(conn, name, nameLength, payloadType, queue, - &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_newVar() [PUBLIC] -// Create a new variable and return it. -//----------------------------------------------------------------------------- -int dpiConn_newVar(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, - dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, - int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, - dpiData **data) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, var) - DPI_CHECK_PTR_NOT_NULL(conn, data) - status = dpiVar__allocate(conn, oracleTypeNum, nativeTypeNum, maxArraySize, - size, sizeIsBytes, isArray, objType, var, data, &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_ping() [PUBLIC] -// Makes a round trip call to the server to confirm that the connection and -// server are still active. -//----------------------------------------------------------------------------- -int dpiConn_ping(dpiConn *conn) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - status = dpiOci__ping(conn, &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_prepareDistribTrans() [PUBLIC] -// Prepare a distributed transaction for commit. A boolean is returned -// indicating if a commit is actually needed as an attempt to perform a commit -// when nothing is actually prepared results in ORA-24756 (transaction does not -// exist). This is determined by the return value from OCITransPrepare() which -// is OCI_SUCCESS_WITH_INFO if there is no transaction requiring commit. -//----------------------------------------------------------------------------- -int dpiConn_prepareDistribTrans(dpiConn *conn, int *commitNeeded) -{ - dpiError error; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, commitNeeded) - if (dpiOci__transPrepare(conn, commitNeeded, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (*commitNeeded) - conn->commitMode = DPI_OCI_TRANS_TWOPHASE; - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_prepareStmt() [PUBLIC] -// Create a new statement and return it after preparing the specified SQL. -//----------------------------------------------------------------------------- -int dpiConn_prepareStmt(dpiConn *conn, int scrollable, const char *sql, - uint32_t sqlLength, const char *tag, uint32_t tagLength, - dpiStmt **stmt) -{ - dpiStmt *tempStmt; - dpiError error; - - *stmt = NULL; - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(conn, sql) - DPI_CHECK_PTR_AND_LENGTH(conn, tag) - DPI_CHECK_PTR_NOT_NULL(conn, stmt) - if (dpiStmt__allocate(conn, scrollable, &tempStmt, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiStmt__prepare(tempStmt, sql, sqlLength, tag, tagLength, - &error) < 0) { - dpiStmt__free(tempStmt, &error); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - *stmt = tempStmt; - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_release() [PUBLIC] -// Release a reference to the connection. -//----------------------------------------------------------------------------- -int dpiConn_release(dpiConn *conn) -{ - return dpiGen__release(conn, DPI_HTYPE_CONN, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_rollback() [PUBLIC] -// Rollback the transaction associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_rollback(dpiConn *conn) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - status = dpiOci__transRollback(conn, 1, &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_setAction() [PUBLIC] -// Set the action associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_setAction(dpiConn *conn, const char *value, uint32_t valueLength) -{ - return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_ACTION, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_setCallTimeout() [PUBLIC] -// Set the call timeout (in milliseconds) used for round-trips to the -// database. This is only valid in Oracle Client 18c and higher. -//----------------------------------------------------------------------------- -int dpiConn_setCallTimeout(dpiConn *conn, uint32_t value) -{ - dpiError error; - int status; - - // validate parameters - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 1, - &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - - // set call timeout - status = dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &value, - 0, DPI_OCI_ATTR_CALL_TIMEOUT, "set call timeout", &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_setClientIdentifier() [PUBLIC] -// Set the client identifier associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_setClientIdentifier(dpiConn *conn, const char *value, - uint32_t valueLength) -{ - return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CLIENT_IDENTIFIER, - value, valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_setClientInfo() [PUBLIC] -// Set the client info associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_setClientInfo(dpiConn *conn, const char *value, - uint32_t valueLength) -{ - return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CLIENT_INFO, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_setCurrentSchema() [PUBLIC] -// Set the current schema associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_setCurrentSchema(dpiConn *conn, const char *value, - uint32_t valueLength) -{ - return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CURRENT_SCHEMA, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_setDbOp() [PUBLIC] -// Set the database operation associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_setDbOp(dpiConn *conn, const char *value, uint32_t valueLength) -{ - return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_DBOP, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_setExternalName() [PUBLIC] -// Set the external name associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_setExternalName(dpiConn *conn, const char *value, - uint32_t valueLength) -{ - return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_EXTERNAL_NAME, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_setInternalName() [PUBLIC] -// Set the internal name associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_setInternalName(dpiConn *conn, const char *value, - uint32_t valueLength) -{ - return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_INTERNAL_NAME, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_setModule() [PUBLIC] -// Set the module associated with the connection. -//----------------------------------------------------------------------------- -int dpiConn_setModule(dpiConn *conn, const char *value, uint32_t valueLength) -{ - return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_MODULE, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiConn_setStmtCacheSize() [PUBLIC] -// Set the size of the statement cache. -//----------------------------------------------------------------------------- -int dpiConn_setStmtCacheSize(dpiConn *conn, uint32_t cacheSize) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - status = dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &cacheSize, 0, - DPI_OCI_ATTR_STMTCACHESIZE, "set stmt cache size", &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_shutdownDatabase() [PUBLIC] -// Shutdown the database. Note that this must be done in two phases except in -// the situation where the instance is being aborted. -//----------------------------------------------------------------------------- -int dpiConn_shutdownDatabase(dpiConn *conn, dpiShutdownMode mode) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - status = dpiOci__dbShutdown(conn, mode, &error); - return dpiGen__endPublicFn(conn, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_startupDatabase() [PUBLIC] -// Startup the database. This is equivalent to "startup nomount" in SQL*Plus. -//----------------------------------------------------------------------------- -int dpiConn_startupDatabase(dpiConn *conn, dpiStartupMode mode) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - status = dpiOci__dbStartup(conn, mode, &error); - return dpiGen__endPublicFn(conn, status, &error); -} - -//----------------------------------------------------------------------------- -// dpiConn_subscribe() [PUBLIC] -// Subscribe to events in the database. A subscription is created and -// returned. This replaces dpiConn_newSubscription(). -//----------------------------------------------------------------------------- -int dpiConn_subscribe(dpiConn *conn, dpiSubscrCreateParams *params, - dpiSubscr **subscr) -{ - dpiSubscr *tempSubscr; - dpiError error; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(conn, params) - DPI_CHECK_PTR_NOT_NULL(conn, subscr) - if (!conn->env->events) { - dpiError__set(&error, "subscribe", DPI_ERR_EVENTS_MODE_REQUIRED); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - if (dpiGen__allocate(DPI_HTYPE_SUBSCR, conn->env, (void**) &tempSubscr, - &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiSubscr__create(tempSubscr, conn, params, &error) < 0) { - dpiSubscr__free(tempSubscr, &error); - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - } - - *subscr = tempSubscr; - return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiConn_unsubscribe() [PUBLIC] -// Unsubscribe from events in the database. Once this call completes -// successfully no further notifications will be sent. -//----------------------------------------------------------------------------- -int dpiConn_unsubscribe(dpiConn *conn, dpiSubscr *subscr) -{ - dpiError error; - int status; - - if (dpiConn__check(conn, __func__, &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (dpiGen__checkHandle(subscr, DPI_HTYPE_SUBSCR, "check subscription", - &error) < 0) - return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); - if (subscr->registered) { - dpiMutex__acquire(subscr->mutex); - status = dpiOci__subscriptionUnRegister(conn, subscr, &error); - if (status == DPI_SUCCESS) - subscr->registered = 0; - dpiMutex__release(subscr->mutex); - if (status < 0) - return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); - } - - dpiGen__setRefCount(subscr, &error, -1); - return dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiContext.c b/vendor/github.com/godror/godror/odpi/src/dpiContext.c deleted file mode 100644 index e9adb18a33e..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiContext.c +++ /dev/null @@ -1,329 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiContext.c -// Implementation of context. Each context uses a specific version of the -// ODPI-C library, which is checked for compatibility before allowing its use. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -// maintain major and minor versions compiled into the library -static const unsigned int dpiMajorVersion = DPI_MAJOR_VERSION; -static const unsigned int dpiMinorVersion = DPI_MINOR_VERSION; - - -//----------------------------------------------------------------------------- -// dpiContext__create() [INTERNAL] -// Create a new context for interaction with the library. The major versions -// must match and the minor version of the caller must be less than or equal to -// the minor version compiled into the library. -//----------------------------------------------------------------------------- -static int dpiContext__create(const char *fnName, unsigned int majorVersion, - unsigned int minorVersion, dpiContext **context, dpiError *error) -{ - dpiContext *tempContext; - - // get error structure first (populates global environment if needed) - if (dpiGlobal__initError(fnName, error) < 0) - return DPI_FAILURE; - - // validate context handle - if (!context) - return dpiError__set(error, "check context handle", - DPI_ERR_NULL_POINTER_PARAMETER, "context"); - - // verify that the supplied version is supported by the library - if (dpiMajorVersion != majorVersion || minorVersion > dpiMinorVersion) - return dpiError__set(error, "check version", - DPI_ERR_VERSION_NOT_SUPPORTED, majorVersion, majorVersion, - minorVersion, dpiMajorVersion, dpiMinorVersion); - - // allocate context and initialize it - if (dpiGen__allocate(DPI_HTYPE_CONTEXT, NULL, (void**) &tempContext, - error) < 0) - return DPI_FAILURE; - tempContext->dpiMinorVersion = (uint8_t) minorVersion; - dpiOci__clientVersion(tempContext); - - *context = tempContext; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiContext__initCommonCreateParams() [INTERNAL] -// Initialize the common connection/pool creation parameters to default -// values. -//----------------------------------------------------------------------------- -void dpiContext__initCommonCreateParams(dpiCommonCreateParams *params) -{ - memset(params, 0, sizeof(dpiCommonCreateParams)); -} - - -//----------------------------------------------------------------------------- -// dpiContext__initConnCreateParams() [INTERNAL] -// Initialize the connection creation parameters to default values. Return -// the structure size as a convenience for calling functions which may have to -// differentiate between different ODPI-C application versions. -//----------------------------------------------------------------------------- -void dpiContext__initConnCreateParams(dpiConnCreateParams *params) -{ - memset(params, 0, sizeof(dpiConnCreateParams)); -} - - -//----------------------------------------------------------------------------- -// dpiContext__initPoolCreateParams() [INTERNAL] -// Initialize the pool creation parameters to default values. -//----------------------------------------------------------------------------- -void dpiContext__initPoolCreateParams(dpiPoolCreateParams *params) -{ - memset(params, 0, sizeof(dpiPoolCreateParams)); - params->minSessions = 1; - params->maxSessions = 1; - params->sessionIncrement = 0; - params->homogeneous = 1; - params->getMode = DPI_MODE_POOL_GET_NOWAIT; - params->pingInterval = DPI_DEFAULT_PING_INTERVAL; - params->pingTimeout = DPI_DEFAULT_PING_TIMEOUT; -} - - -//----------------------------------------------------------------------------- -// dpiContext__initSodaOperOptions() [INTERNAL] -// Initialize the SODA operation options to default values. -//----------------------------------------------------------------------------- -void dpiContext__initSodaOperOptions(dpiSodaOperOptions *options) -{ - memset(options, 0, sizeof(dpiSodaOperOptions)); -} - - -//----------------------------------------------------------------------------- -// dpiContext__initSubscrCreateParams() [INTERNAL] -// Initialize the subscription creation parameters to default values. -//----------------------------------------------------------------------------- -void dpiContext__initSubscrCreateParams(dpiSubscrCreateParams *params) -{ - memset(params, 0, sizeof(dpiSubscrCreateParams)); - params->subscrNamespace = DPI_SUBSCR_NAMESPACE_DBCHANGE; - params->groupingType = DPI_SUBSCR_GROUPING_TYPE_SUMMARY; -} - - -//----------------------------------------------------------------------------- -// dpiContext_create() [PUBLIC] -// Create a new context for interaction with the library. The major versions -// must match and the minor version of the caller must be less than or equal to -// the minor version compiled into the library. -//----------------------------------------------------------------------------- -int dpiContext_create(unsigned int majorVersion, unsigned int minorVersion, - dpiContext **context, dpiErrorInfo *errorInfo) -{ - dpiError error; - int status; - - if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) - dpiDebug__print("fn start %s\n", __func__); - status = dpiContext__create(__func__, majorVersion, minorVersion, context, - &error); - if (status < 0) - dpiError__getInfo(&error, errorInfo); - if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) - dpiDebug__print("fn end %s -> %d\n", __func__, status); - return status; -} - - -//----------------------------------------------------------------------------- -// dpiContext_destroy() [PUBLIC] -// Destroy an existing context. The structure will be checked for validity -// first. -//----------------------------------------------------------------------------- -int dpiContext_destroy(dpiContext *context) -{ - char message[80]; - dpiError error; - - if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, - &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - dpiUtils__clearMemory(&context->checkInt, sizeof(context->checkInt)); - if (dpiDebugLevel & DPI_DEBUG_LEVEL_REFS) - dpiDebug__print("ref %p (%s) -> 0\n", context, context->typeDef->name); - if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) - (void) sprintf(message, "fn end %s(%p) -> %d", __func__, context, - DPI_SUCCESS); - dpiUtils__freeMemory(context); - if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) - dpiDebug__print("%s\n", message); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiContext_getClientVersion() [PUBLIC] -// Return the version of the Oracle client that is in use. -//----------------------------------------------------------------------------- -int dpiContext_getClientVersion(const dpiContext *context, - dpiVersionInfo *versionInfo) -{ - dpiError error; - - if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, - &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(context, versionInfo) - memcpy(versionInfo, context->versionInfo, sizeof(dpiVersionInfo)); - return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiContext_getError() [PUBLIC] -// Return information about the error that was last populated. -//----------------------------------------------------------------------------- -void dpiContext_getError(const dpiContext *context, dpiErrorInfo *info) -{ - dpiError error; - - dpiGlobal__initError(NULL, &error); - dpiGen__checkHandle(context, DPI_HTYPE_CONTEXT, "check handle", &error); - dpiError__getInfo(&error, info); -} - - -//----------------------------------------------------------------------------- -// dpiContext_initCommonCreateParams() [PUBLIC] -// Initialize the common connection/pool creation parameters to default -// values. -//----------------------------------------------------------------------------- -int dpiContext_initCommonCreateParams(const dpiContext *context, - dpiCommonCreateParams *params) -{ - dpiError error; - - if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, - &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(context, params) - dpiContext__initCommonCreateParams(params); - return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiContext_initConnCreateParams() [PUBLIC] -// Initialize the connection creation parameters to default values. -//----------------------------------------------------------------------------- -int dpiContext_initConnCreateParams(const dpiContext *context, - dpiConnCreateParams *params) -{ - dpiConnCreateParams localParams; - dpiError error; - - if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, - &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(context, params) - - // size changed in version 3.1; can be dropped once version 4 released - if (context->dpiMinorVersion > 0) - dpiContext__initConnCreateParams(params); - else { - dpiContext__initConnCreateParams(&localParams); - memcpy(params, &localParams, sizeof(dpiConnCreateParams__v30)); - } - return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiContext_initPoolCreateParams() [PUBLIC] -// Initialize the pool creation parameters to default values. -//----------------------------------------------------------------------------- -int dpiContext_initPoolCreateParams(const dpiContext *context, - dpiPoolCreateParams *params) -{ - dpiPoolCreateParams localParams; - dpiError error; - - if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, - &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(context, params) - - // size changed in versions 3.1 and 3.3 - // changes can be dropped once version 4 released - if (context->dpiMinorVersion > 2) { - dpiContext__initPoolCreateParams(params); - } else { - dpiContext__initPoolCreateParams(&localParams); - if (context->dpiMinorVersion > 0) { - memcpy(params, &localParams, sizeof(dpiPoolCreateParams__v32)); - } else { - memcpy(params, &localParams, sizeof(dpiPoolCreateParams__v30)); - } - } - return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiContext_initSodaOperOptions() [PUBLIC] -// Initialize the SODA operation options to default values. -//----------------------------------------------------------------------------- -int dpiContext_initSodaOperOptions(const dpiContext *context, - dpiSodaOperOptions *options) -{ - dpiError error; - - if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, - &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(context, options) - dpiContext__initSodaOperOptions(options); - return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiContext_initSubscrCreateParams() [PUBLIC] -// Initialize the subscription creation parameters to default values. -//----------------------------------------------------------------------------- -int dpiContext_initSubscrCreateParams(const dpiContext *context, - dpiSubscrCreateParams *params) -{ - dpiSubscrCreateParams localParams; - dpiError error; - - if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, - &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(context, params) - - // size changed in versions 3.2 and 3.3 - // changes can be dropped once version 4 released - if (context->dpiMinorVersion > 2) { - dpiContext__initSubscrCreateParams(params); - } else { - dpiContext__initSubscrCreateParams(&localParams); - if (context->dpiMinorVersion > 1) { - memcpy(params, &localParams, sizeof(dpiSubscrCreateParams__v32)); - } else { - memcpy(params, &localParams, sizeof(dpiSubscrCreateParams__v30)); - } - } - return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiData.c b/vendor/github.com/godror/godror/odpi/src/dpiData.c deleted file mode 100644 index 57d3faac309..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiData.c +++ /dev/null @@ -1,899 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiData.c -// Implementation of transformation routines. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -// constants used for converting timestamps to/from an interval -#define DPI_MS_DAY 86400000 // 24 * 60 * 60 * 1000 -#define DPI_MS_HOUR 3600000 // 60 * 60 * 1000 -#define DPI_MS_MINUTE 60000 // 60 * 1000 -#define DPI_MS_SECOND 1000 // ms per sec -#define DPI_MS_FSECOND 1000000 // 1000 * 1000 - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__fromOracleDate() [INTERNAL] -// Populate the data from an dpiOciDate structure. -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleDate(dpiDataBuffer *data, - dpiOciDate *oracleValue) -{ - dpiTimestamp *timestamp = &data->asTimestamp; - - timestamp->year = oracleValue->year; - timestamp->month = oracleValue->month; - timestamp->day = oracleValue->day; - timestamp->hour = oracleValue->hour; - timestamp->minute = oracleValue->minute; - timestamp->second = oracleValue->second; - timestamp->fsecond = 0; - timestamp->tzHourOffset = 0; - timestamp->tzMinuteOffset = 0; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__fromOracleDateAsDouble() [INTERNAL] -// Populate the data from an dpiOciDate structure as a double value (number -// of milliseconds since January 1, 1970). -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleDateAsDouble(dpiDataBuffer *data, - dpiEnv *env, dpiError *error, dpiOciDate *oracleValue) -{ - void *timestamp; - int status; - - // allocate and populate a timestamp with the value of the date - if (dpiOci__descriptorAlloc(env->handle, ×tamp, - DPI_OCI_DTYPE_TIMESTAMP_LTZ, "alloc timestamp", error) < 0) - return DPI_FAILURE; - if (dpiOci__dateTimeConstruct(env->handle, timestamp, oracleValue->year, - oracleValue->month, oracleValue->day, oracleValue->hour, - oracleValue->minute, oracleValue->second, 0, NULL, 0, error) < 0) { - dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP_LTZ); - return DPI_FAILURE; - } - - // now calculate the number of milliseconds since January 1, 1970 - status = dpiDataBuffer__fromOracleTimestampAsDouble(data, env, error, - timestamp); - dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP_LTZ); - return status; -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__fromOracleIntervalDS() [INTERNAL] -// Populate the data from an OCIInterval structure (days/seconds). -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue) -{ - dpiIntervalDS *interval = &data->asIntervalDS; - - return dpiOci__intervalGetDaySecond(env->handle, &interval->days, - &interval->hours, &interval->minutes, &interval->seconds, - &interval->fseconds, oracleValue, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__fromOracleIntervalYM() [INTERNAL] -// Populate the data from an OCIInterval structure (years/months). -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue) -{ - dpiIntervalYM *interval = &data->asIntervalYM; - - return dpiOci__intervalGetYearMonth(env->handle, &interval->years, - &interval->months, oracleValue, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__fromOracleNumberAsDouble() [INTERNAL] -// Populate the data from an OCINumber structure as a double. -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleNumberAsDouble(dpiDataBuffer *data, - dpiError *error, void *oracleValue) -{ - return dpiOci__numberToReal(&data->asDouble, oracleValue, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__fromOracleNumberAsInteger() [INTERNAL] -// Populate the data from an OCINumber structure as an integer. -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleNumberAsInteger(dpiDataBuffer *data, - dpiError *error, void *oracleValue) -{ - return dpiOci__numberToInt(oracleValue, &data->asInt64, sizeof(int64_t), - DPI_OCI_NUMBER_SIGNED, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__fromOracleNumberAsUnsignedInteger() [INTERNAL] -// Populate the data from an OCINumber structure as an unsigned integer. -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleNumberAsUnsignedInteger(dpiDataBuffer *data, - dpiError *error, void *oracleValue) -{ - return dpiOci__numberToInt(oracleValue, &data->asUint64, sizeof(uint64_t), - DPI_OCI_NUMBER_UNSIGNED, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__fromOracleNumberAsText() [INTERNAL] -// Populate the data from an OCINumber structure as text. -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleNumberAsText(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue) -{ - uint8_t *target, numDigits, digits[DPI_NUMBER_MAX_DIGITS]; - int16_t decimalPointIndex, i; - uint16_t *targetUtf16; - uint32_t numBytes; - dpiBytes *bytes; - int isNegative; - - // parse the OCINumber structure - if (dpiUtils__parseOracleNumber(oracleValue, &isNegative, - &decimalPointIndex, &numDigits, digits, error) < 0) - return DPI_FAILURE; - - // calculate the number of bytes that will be required for the string - numBytes = numDigits; - if (isNegative) - numBytes++; - if (decimalPointIndex <= 0) - numBytes += -decimalPointIndex + 2; - else if (decimalPointIndex < numDigits) - numBytes++; - else if (decimalPointIndex > numDigits) - numBytes += decimalPointIndex - numDigits; - if (env->charsetId == DPI_CHARSET_ID_UTF16) - numBytes *= 2; - - // verify that the provided buffer is large enough - bytes = &data->asBytes; - if (numBytes > bytes->length) - return dpiError__set(error, "check number to text size", - DPI_ERR_BUFFER_SIZE_TOO_SMALL, bytes->length); - bytes->length = numBytes; - - // UTF-16 must be handled differently; the platform endianness is used in - // order to be compatible with OCI which has this restriction - if (env->charsetId == DPI_CHARSET_ID_UTF16) { - targetUtf16 = (uint16_t*) bytes->ptr; - - // if negative, include the sign - if (isNegative) - *targetUtf16++ = '-'; - - // if the decimal point index is 0 or less, add the decimal point and - // any leading zeroes that are needed - if (decimalPointIndex <= 0) { - *targetUtf16++ = '0'; - *targetUtf16++ = '.'; - for (; decimalPointIndex < 0; decimalPointIndex++) - *targetUtf16++ = '0'; - } - - // add each of the digits - for (i = 0; i < numDigits; i++) { - if (i > 0 && i == decimalPointIndex) - *targetUtf16++ = '.'; - *targetUtf16++ = '0' + digits[i]; - } - - // if the decimal point index exceeds the number of digits, add any - // trailing zeroes that are needed - if (decimalPointIndex > numDigits) { - for (i = numDigits; i < decimalPointIndex; i++) - *targetUtf16++ = '0'; - } - - // the following should be the same logic as the section above for UTF-16, - // simply with single byte encodings instead - } else { - target = (uint8_t*) bytes->ptr; - - // if negative, include the sign - if (isNegative) - *target++ = '-'; - - // if the decimal point index is 0 or less, add the decimal point and - // any leading zeroes that are needed - if (decimalPointIndex <= 0) { - *target++ = '0'; - *target++ = '.'; - for (; decimalPointIndex < 0; decimalPointIndex++) - *target++ = '0'; - } - - // add each of the digits - for (i = 0; i < numDigits; i++) { - if (i > 0 && i == decimalPointIndex) - *target++ = '.'; - *target++ = '0' + digits[i]; - } - - // if the decimal point index exceeds the number of digits, add any - // trailing zeroes that are needed - if (decimalPointIndex > numDigits) { - for (i = numDigits; i < decimalPointIndex; i++) - *target++ = '0'; - } - - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__fromOracleTimestamp() [INTERNAL] -// Populate the data from an OCIDateTime structure. -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue, int withTZ) -{ - dpiTimestamp *timestamp = &data->asTimestamp; - - if (dpiOci__dateTimeGetDate(env->handle, oracleValue, ×tamp->year, - ×tamp->month, ×tamp->day, error) < 0) - return DPI_FAILURE; - if (dpiOci__dateTimeGetTime(env->handle, oracleValue, ×tamp->hour, - ×tamp->minute, ×tamp->second, ×tamp->fsecond, - error) < 0) - return DPI_FAILURE; - if (withTZ) { - if (dpiOci__dateTimeGetTimeZoneOffset(env->handle, oracleValue, - ×tamp->tzHourOffset, ×tamp->tzMinuteOffset, - error) < 0) - return DPI_FAILURE; - } else { - timestamp->tzHourOffset = 0; - timestamp->tzMinuteOffset = 0; - } - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__fromOracleTimestampAsDouble() [INTERNAL] -// Populate the data from an OCIDateTime structure as a double value (number -// of milliseconds since January 1, 1970). -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleTimestampAsDouble(dpiDataBuffer *data, - dpiEnv *env, dpiError *error, void *oracleValue) -{ - int32_t day, hour, minute, second, fsecond; - void *interval; - int status; - - // allocate interval to use in calculation - if (dpiOci__descriptorAlloc(env->handle, &interval, - DPI_OCI_DTYPE_INTERVAL_DS, "alloc interval", error) < 0) - return DPI_FAILURE; - - // subtract dates to determine interval between date and base date - if (dpiOci__dateTimeSubtract(env->handle, oracleValue, env->baseDate, - interval, error) < 0) { - dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); - return DPI_FAILURE; - } - - // get the days, hours, minutes and seconds from the interval - status = dpiOci__intervalGetDaySecond(env->handle, &day, &hour, &minute, - &second, &fsecond, interval, error); - dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); - if (status < 0) - return DPI_FAILURE; - - // calculate milliseconds since January 1, 1970 - data->asDouble = ((double) day) * DPI_MS_DAY + hour * DPI_MS_HOUR + - minute * DPI_MS_MINUTE + second * DPI_MS_SECOND + - fsecond / DPI_MS_FSECOND; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__toOracleDate() [INTERNAL] -// Populate the data in an dpiOciDate structure. -//----------------------------------------------------------------------------- -int dpiDataBuffer__toOracleDate(dpiDataBuffer *data, dpiOciDate *oracleValue) -{ - dpiTimestamp *timestamp = &data->asTimestamp; - - oracleValue->year = timestamp->year; - oracleValue->month = timestamp->month; - oracleValue->day = timestamp->day; - oracleValue->hour = timestamp->hour; - oracleValue->minute = timestamp->minute; - oracleValue->second = timestamp->second; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__toOracleDateFromDouble() [INTERNAL] -// Populate the data in an dpiOciDate structure given a double (number of -// milliseconds since January 1, 1970). -//----------------------------------------------------------------------------- -int dpiDataBuffer__toOracleDateFromDouble(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, dpiOciDate *oracleValue) -{ - void *timestamp, *timestampLTZ; - uint32_t fsecond; - - // allocate a descriptor to acquire a timestamp - if (dpiOci__descriptorAlloc(env->handle, ×tampLTZ, - DPI_OCI_DTYPE_TIMESTAMP_LTZ, "alloc timestamp", error) < 0) - return DPI_FAILURE; - if (dpiDataBuffer__toOracleTimestampFromDouble(data, env, error, - timestampLTZ) < 0) { - dpiOci__descriptorFree(timestampLTZ, DPI_OCI_DTYPE_TIMESTAMP_LTZ); - return DPI_FAILURE; - } - - // allocate a plain timestamp and convert to it - if (dpiOci__descriptorAlloc(env->handle, ×tamp, - DPI_OCI_DTYPE_TIMESTAMP, "alloc plain timestamp", error) < 0) { - dpiOci__descriptorFree(timestampLTZ, DPI_OCI_DTYPE_TIMESTAMP_LTZ); - return DPI_FAILURE; - } - if (dpiOci__dateTimeConvert(env->handle, timestampLTZ, timestamp, - error) < 0) { - dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); - dpiOci__descriptorFree(timestampLTZ, DPI_OCI_DTYPE_TIMESTAMP_LTZ); - return DPI_FAILURE; - } - dpiOci__descriptorFree(timestampLTZ, DPI_OCI_DTYPE_TIMESTAMP_LTZ); - - // populate date structure - if (dpiOci__dateTimeGetDate(env->handle, timestamp, &oracleValue->year, - &oracleValue->month, &oracleValue->day, error) < 0) { - dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); - return DPI_FAILURE; - } - if (dpiOci__dateTimeGetTime(env->handle, timestamp, &oracleValue->hour, - &oracleValue->minute, &oracleValue->second, &fsecond, error) < 0) { - dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); - return DPI_FAILURE; - } - - dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__toOracleIntervalDS() [INTERNAL] -// Populate the data in an OCIInterval structure (days/seconds). -//----------------------------------------------------------------------------- -int dpiDataBuffer__toOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue) -{ - dpiIntervalDS *interval = &data->asIntervalDS; - - return dpiOci__intervalSetDaySecond(env->handle, interval->days, - interval->hours, interval->minutes, interval->seconds, - interval->fseconds, oracleValue, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__toOracleIntervalYM() [INTERNAL] -// Populate the data in an OCIInterval structure (years/months). -//----------------------------------------------------------------------------- -int dpiDataBuffer__toOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue) -{ - dpiIntervalYM *interval = &data->asIntervalYM; - - return dpiOci__intervalSetYearMonth(env->handle, interval->years, - interval->months, oracleValue, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__toOracleNumberFromDouble() [INTERNAL] -// Populate the data in an OCINumber structure from a double. -//----------------------------------------------------------------------------- -int dpiDataBuffer__toOracleNumberFromDouble(dpiDataBuffer *data, - dpiError *error, void *oracleValue) -{ - if (isnan(data->asDouble)) - return dpiError__set(error, "convert double to Oracle number", - DPI_ERR_NAN); - return dpiOci__numberFromReal(data->asDouble, oracleValue, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__toOracleNumberFromInteger() [INTERNAL] -// Populate the data in an OCINumber structure from an integer. -//----------------------------------------------------------------------------- -int dpiDataBuffer__toOracleNumberFromInteger(dpiDataBuffer *data, - dpiError *error, void *oracleValue) -{ - return dpiOci__numberFromInt(&data->asInt64, sizeof(int64_t), - DPI_OCI_NUMBER_SIGNED, oracleValue, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__toOracleNumberFromText() [INTERNAL] -// Populate the data in an OCINumber structure from text. -//----------------------------------------------------------------------------- -int dpiDataBuffer__toOracleNumberFromText(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue) -{ - uint8_t numDigits, digits[DPI_NUMBER_AS_TEXT_CHARS], *source, *target, i; - int isNegative, prependZero, appendSentinel; - dpiBytes *value = &data->asBytes; - int16_t decimalPointIndex; - uint8_t byte, numPairs; - int8_t ociExponent; - - // parse the string into its constituent components - if (dpiUtils__parseNumberString(value->ptr, value->length, env->charsetId, - &isNegative, &decimalPointIndex, &numDigits, digits, error) < 0) - return DPI_FAILURE; - - // if the exponent is odd, prepend a zero - prependZero = (decimalPointIndex > 0 && decimalPointIndex % 2 == 1) || - (decimalPointIndex < 0 && decimalPointIndex % 2 == -1); - if (prependZero && numDigits != 0) { - digits[numDigits++] = 0; - decimalPointIndex++; - } - - // determine the number of digit pairs; if the number of digits is odd, - // append a zero to make the number of digits even - if (numDigits % 2 == 1) - digits[numDigits++] = 0; - numPairs = numDigits / 2; - - // append a sentinel 102 byte for negative numbers if there is room - appendSentinel = (isNegative && numDigits > 0 && - numDigits < DPI_NUMBER_MAX_DIGITS); - - // initialize the OCINumber value - // the length is the number of pairs, plus one for the exponent - // include an extra byte for the sentinel if applicable - target = (uint8_t*) oracleValue; - *target++ = (uint8_t) (numPairs + 1 + appendSentinel); - - // if the number of digits is zero, the value is itself zero since all - // leading and trailing zeroes are removed from the digits string; the OCI - // value for zero is a special case - if (numDigits == 0) { - *target = 128; - return DPI_SUCCESS; - } - - // calculate the exponent - ociExponent = (int8_t) ((decimalPointIndex - 2) / 2 + 193); - if (isNegative) - ociExponent = ~ociExponent; - *target++ = (uint8_t) ociExponent; - - // calculate the mantissa bytes - source = digits; - for (i = 0; i < numPairs; i++) { - if (i == 0 && prependZero) - byte = *source++; - else { - byte = *source++ * 10; - byte += *source++; - } - if (isNegative) - byte = 101 - byte; - else byte++; - *target++ = byte; - } - - // append 102 byte for negative numbers if the number of digits is less - // than the maximum allowable - if (appendSentinel) - *target = 102; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__toOracleNumberFromUnsignedInteger() [INTERNAL] -// Populate the data in an OCINumber structure from an integer. -//----------------------------------------------------------------------------- -int dpiDataBuffer__toOracleNumberFromUnsignedInteger(dpiDataBuffer *data, - dpiError *error, void *oracleValue) -{ - return dpiOci__numberFromInt(&data->asUint64, sizeof(uint64_t), - DPI_OCI_NUMBER_UNSIGNED, oracleValue, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__toOracleTimestamp() [INTERNAL] -// Populate the data in an OCIDateTime structure. -//----------------------------------------------------------------------------- -int dpiDataBuffer__toOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue, int withTZ) -{ - dpiTimestamp *timestamp = &data->asTimestamp; - char tzOffsetBuffer[10], *tzOffset = NULL; - size_t tzOffsetLength = 0; - char sign; - - if (withTZ) { - sign = (timestamp->tzHourOffset < 0 || timestamp->tzMinuteOffset < 0) ? - '-' : '+'; - tzOffsetLength = (size_t) sprintf(tzOffsetBuffer, "%c%.2d:%.2d", sign, - abs(timestamp->tzHourOffset), abs(timestamp->tzMinuteOffset)); - tzOffset = tzOffsetBuffer; - } - return dpiOci__dateTimeConstruct(env->handle, oracleValue, timestamp->year, - timestamp->month, timestamp->day, timestamp->hour, - timestamp->minute, timestamp->second, timestamp->fsecond, tzOffset, - tzOffsetLength, error); -} - - -//----------------------------------------------------------------------------- -// dpiDataBuffer__toOracleTimestampFromDouble() [INTERNAL] -// Populate the data in an OCIDateTime structure, given the number of -// milliseconds since January 1, 1970. -//----------------------------------------------------------------------------- -int dpiDataBuffer__toOracleTimestampFromDouble(dpiDataBuffer *data, - dpiEnv *env, dpiError *error, void *oracleValue) -{ - int32_t day, hour, minute, second, fsecond; - void *interval; - int status; - double ms; - - // allocate interval to use in calculation - if (dpiOci__descriptorAlloc(env->handle, &interval, - DPI_OCI_DTYPE_INTERVAL_DS, "alloc interval", error) < 0) - return DPI_FAILURE; - - // determine the interval - ms = data->asDouble; - day = (int32_t) (ms / DPI_MS_DAY); - ms = ms - ((double) day) * DPI_MS_DAY; - hour = (int32_t) (ms / DPI_MS_HOUR); - ms = ms - (hour * DPI_MS_HOUR); - minute = (int32_t) (ms / DPI_MS_MINUTE); - ms = ms - (minute * DPI_MS_MINUTE); - second = (int32_t) (ms / DPI_MS_SECOND); - ms = ms - (second * DPI_MS_SECOND); - fsecond = (int32_t)(ms * DPI_MS_FSECOND); - if (dpiOci__intervalSetDaySecond(env->handle, day, hour, minute, second, - fsecond, interval, error) < 0) { - dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); - return DPI_FAILURE; - } - - // add the interval to the base date - status = dpiOci__dateTimeIntervalAdd(env->handle, env->baseDate, interval, - oracleValue, error); - dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); - return status; -} - - -//----------------------------------------------------------------------------- -// dpiData_getBool() [PUBLIC] -// Return the boolean portion of the data. -//----------------------------------------------------------------------------- -int dpiData_getBool(dpiData *data) -{ - return data->value.asBoolean; -} - - -//----------------------------------------------------------------------------- -// dpiData_getBytes() [PUBLIC] -// Return the bytes portion of the data. -//----------------------------------------------------------------------------- -dpiBytes *dpiData_getBytes(dpiData *data) -{ - return &data->value.asBytes; -} - - -//----------------------------------------------------------------------------- -// dpiData_getDouble() [PUBLIC] -// Return the double portion of the data. -//----------------------------------------------------------------------------- -double dpiData_getDouble(dpiData *data) -{ - return data->value.asDouble; -} - - -//----------------------------------------------------------------------------- -// dpiData_getFloat() [PUBLIC] -// Return the float portion of the data. -//----------------------------------------------------------------------------- -float dpiData_getFloat(dpiData *data) -{ - return data->value.asFloat; -} - - -//----------------------------------------------------------------------------- -// dpiData_getInt64() [PUBLIC] -// Return the integer portion of the data. -//----------------------------------------------------------------------------- -int64_t dpiData_getInt64(dpiData *data) -{ - return data->value.asInt64; -} - - -//----------------------------------------------------------------------------- -// dpiData_getIntervalDS() [PUBLIC] -// Return the interval (days/seconds) portion of the data. -//----------------------------------------------------------------------------- -dpiIntervalDS *dpiData_getIntervalDS(dpiData *data) -{ - return &data->value.asIntervalDS; -} - - -//----------------------------------------------------------------------------- -// dpiData_getIntervalYM() [PUBLIC] -// Return the interval (years/months) portion of the data. -//----------------------------------------------------------------------------- -dpiIntervalYM *dpiData_getIntervalYM(dpiData *data) -{ - return &data->value.asIntervalYM; -} - - -//----------------------------------------------------------------------------- -// dpiData_getIsNull() [PUBLIC] -// Return a boolean indicating if the value is null or not. -//----------------------------------------------------------------------------- -int dpiData_getIsNull(dpiData *data) -{ - return data->isNull; -} - - -//----------------------------------------------------------------------------- -// dpiData_getLOB() [PUBLIC] -// Return the LOB portion of the data. -//----------------------------------------------------------------------------- -dpiLob *dpiData_getLOB(dpiData *data) -{ - return data->value.asLOB; -} - - -//----------------------------------------------------------------------------- -// dpiData_getObject() [PUBLIC] -// Return the object portion of the data. -//----------------------------------------------------------------------------- -dpiObject *dpiData_getObject(dpiData *data) -{ - return data->value.asObject; -} - - -//----------------------------------------------------------------------------- -// dpiData_getStmt() [PUBLIC] -// Return the statement portion of the data. -//----------------------------------------------------------------------------- -dpiStmt *dpiData_getStmt(dpiData *data) -{ - return data->value.asStmt; -} - - -//----------------------------------------------------------------------------- -// dpiData_getTimestamp() [PUBLIC] -// Return the timestamp portion of the data. -//----------------------------------------------------------------------------- -dpiTimestamp *dpiData_getTimestamp(dpiData *data) -{ - return &data->value.asTimestamp; -} - - -//----------------------------------------------------------------------------- -// dpiData_getUint64() [PUBLIC] -// Return the unsigned integer portion of the data. -//----------------------------------------------------------------------------- -uint64_t dpiData_getUint64(dpiData *data) -{ - return data->value.asUint64; -} - - -//----------------------------------------------------------------------------- -// dpiData_setBool() [PUBLIC] -// Set the boolean portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setBool(dpiData *data, int value) -{ - data->isNull = 0; - data->value.asBoolean = value; -} - - -//----------------------------------------------------------------------------- -// dpiData_setBytes() [PUBLIC] -// Set the bytes portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setBytes(dpiData *data, char *ptr, uint32_t length) -{ - data->isNull = 0; - data->value.asBytes.ptr = ptr; - data->value.asBytes.length = length; -} - - -//----------------------------------------------------------------------------- -// dpiData_setDouble() [PUBLIC] -// Set the double portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setDouble(dpiData *data, double value) -{ - data->isNull = 0; - data->value.asDouble = value; -} - - -//----------------------------------------------------------------------------- -// dpiData_setFloat() [PUBLIC] -// Set the float portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setFloat(dpiData *data, float value) -{ - data->isNull = 0; - data->value.asFloat = value; -} - - -//----------------------------------------------------------------------------- -// dpiData_setInt64() [PUBLIC] -// Set the integer portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setInt64(dpiData *data, int64_t value) -{ - data->isNull = 0; - data->value.asInt64 = value; -} - - -//----------------------------------------------------------------------------- -// dpiData_setIntervalDS() [PUBLIC] -// Set the interval (days/seconds) portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setIntervalDS(dpiData *data, int32_t days, int32_t hours, - int32_t minutes, int32_t seconds, int32_t fseconds) -{ - dpiIntervalDS *interval = &data->value.asIntervalDS; - - data->isNull = 0; - interval->days = days; - interval->hours = hours; - interval->minutes = minutes; - interval->seconds = seconds; - interval->fseconds = fseconds; -} - - -//----------------------------------------------------------------------------- -// dpiData_setIntervalYM() [PUBLIC] -// Set the interval (years/months) portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setIntervalYM(dpiData *data, int32_t years, int32_t months) -{ - dpiIntervalYM *interval = &data->value.asIntervalYM; - - data->isNull = 0; - interval->years = years; - interval->months = months; -} - - -//----------------------------------------------------------------------------- -// dpiData_setLOB() [PUBLIC] -// Set the LOB portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setLOB(dpiData *data, dpiLob *lob) -{ - data->isNull = 0; - data->value.asLOB = lob; -} - - -//----------------------------------------------------------------------------- -// dpiData_setNull() [PUBLIC] -// Set the data to be treated as a null value. -//----------------------------------------------------------------------------- -void dpiData_setNull(dpiData *data) -{ - data->isNull = 1; -} - - -//----------------------------------------------------------------------------- -// dpiData_setObject() [PUBLIC] -// Set the object portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setObject(dpiData *data, dpiObject *obj) -{ - data->isNull = 0; - data->value.asObject = obj; -} - - -//----------------------------------------------------------------------------- -// dpiData_setStmt() [PUBLIC] -// Set the statement portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setStmt(dpiData *data, dpiStmt *obj) -{ - data->isNull = 0; - data->value.asStmt = obj; -} - - -//----------------------------------------------------------------------------- -// dpiData_setTimestamp() [PUBLIC] -// Set the timestamp portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setTimestamp(dpiData *data, int16_t year, uint8_t month, - uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, - uint32_t fsecond, int8_t tzHourOffset, int8_t tzMinuteOffset) -{ - dpiTimestamp *timestamp = &data->value.asTimestamp; - - data->isNull = 0; - timestamp->year = year; - timestamp->month = month; - timestamp->day = day; - timestamp->hour = hour; - timestamp->minute = minute; - timestamp->second = second; - timestamp->fsecond = fsecond; - timestamp->tzHourOffset = tzHourOffset; - timestamp->tzMinuteOffset = tzMinuteOffset; -} - - -//----------------------------------------------------------------------------- -// dpiData_setUint64() [PUBLIC] -// Set the unsigned integer portion of the data. -//----------------------------------------------------------------------------- -void dpiData_setUint64(dpiData *data, uint64_t value) -{ - data->isNull = 0; - data->value.asUint64 = value; -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiDebug.c b/vendor/github.com/godror/godror/odpi/src/dpiDebug.c deleted file mode 100644 index 28b8776475f..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiDebug.c +++ /dev/null @@ -1,183 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiDebug.c -// Methods used for debugging ODPI-C. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -#define DPI_DEBUG_THREAD_FORMAT "%.5" PRIu64 -#define DPI_DEBUG_DATE_FORMAT "%.4d-%.2d-%.2d" -#define DPI_DEBUG_TIME_FORMAT "%.2d:%.2d:%.2d.%.3d" - -// debug level (populated by environment variable DPI_DEBUG_LEVEL) -unsigned long dpiDebugLevel = 0; - -// debug prefix format (populated by environment variable DPI_DEBUG_PREFIX) -static char dpiDebugPrefixFormat[64] = "ODPI [%i] %d %t: "; - -// debug file for printing (currently unchangeable) -static FILE *dpiDebugStream = NULL; - - -//----------------------------------------------------------------------------- -// dpiDebug__getFormatWithPrefix() [INTERNAL] -// Adjust the provided format to include the prefix requested by the user. -// This method is not permitted to fail, so if there is not enough space, the -// prefix is truncated as needed -- although this is a very unlikely scenario. -//----------------------------------------------------------------------------- -static void dpiDebug__getFormatWithPrefix(const char *format, - char *formatWithPrefix, size_t maxFormatWithPrefixSize) -{ - char *sourcePtr, *targetPtr; - int gotTime, tempSize; - uint64_t threadId; - size_t size; -#ifdef _WIN32 - SYSTEMTIME time; -#else - struct timeval timeOfDay; - struct tm time; -#endif - - gotTime = 0; - sourcePtr = dpiDebugPrefixFormat; - targetPtr = formatWithPrefix; - size = maxFormatWithPrefixSize - strlen(format); - while (*sourcePtr && size > 20) { - - // all characters except '%' are copied verbatim to the target - if (*sourcePtr != '%') { - *targetPtr++ = *sourcePtr++; - maxFormatWithPrefixSize--; - continue; - } - - // handle the different directives - sourcePtr++; - switch (*sourcePtr) { - case 'i': -#ifdef _WIN32 - threadId = (uint64_t) GetCurrentThreadId(); -#elif defined __linux - threadId = (uint64_t) syscall(SYS_gettid); -#elif defined __APPLE__ - pthread_threadid_np(NULL, &threadId); -#else - threadId = (uint64_t) pthread_self(); -#endif - tempSize = sprintf(targetPtr, DPI_DEBUG_THREAD_FORMAT, - threadId); - size -= tempSize; - targetPtr += tempSize; - sourcePtr++; - break; - case 'd': - case 't': - if (!gotTime) { - gotTime = 1; -#ifdef _WIN32 - GetLocalTime(&time); -#else - gettimeofday(&timeOfDay, NULL); - localtime_r(&timeOfDay.tv_sec, &time); -#endif - } -#ifdef _WIN32 - if (*sourcePtr == 'd') - tempSize = sprintf(targetPtr, DPI_DEBUG_DATE_FORMAT, - time.wYear, time.wMonth, time.wDay); - else tempSize = sprintf(targetPtr, DPI_DEBUG_TIME_FORMAT, - time.wHour, time.wMinute, time.wSecond, - time.wMilliseconds); -#else - if (*sourcePtr == 'd') - tempSize = sprintf(targetPtr, DPI_DEBUG_DATE_FORMAT, - time.tm_year + 1900, time.tm_mon + 1, - time.tm_mday); - else tempSize = sprintf(targetPtr, DPI_DEBUG_TIME_FORMAT, - time.tm_hour, time.tm_min, time.tm_sec, - (int) (timeOfDay.tv_usec / 1000)); -#endif - size -= tempSize; - targetPtr += tempSize; - sourcePtr++; - break; - case '\0': - break; - default: - *targetPtr++ = '%'; - *targetPtr++ = *sourcePtr++; - break; - } - } - - // append original format - strcpy(targetPtr, format); -} - - -//----------------------------------------------------------------------------- -// dpiDebug__initialize() [INTERNAL] -// Initialize debugging infrastructure. This reads the environment variables -// and populates the global variables used for determining which messages to -// print and what prefix should be placed in front of each message. -//----------------------------------------------------------------------------- -void dpiDebug__initialize(void) -{ - char *envValue; - - // determine the value of the environment variable DPI_DEBUG_LEVEL and - // convert to an integer; if the value in the environment variable is not a - // valid integer, it is ignored - envValue = getenv("DPI_DEBUG_LEVEL"); - if (envValue) - dpiDebugLevel = (unsigned long) strtol(envValue, NULL, 10); - - // determine the value of the environment variable DPI_DEBUG_PREFIX and - // store it in the static buffer available for it; a static buffer is used - // since this runs during startup and may not fail; if the value of the - // environment variable is too large for the buffer, the value is ignored - // and the default value is used instead - envValue = getenv("DPI_DEBUG_PREFIX"); - if (envValue && strlen(envValue) < sizeof(dpiDebugPrefixFormat)) - strcpy(dpiDebugPrefixFormat, envValue); - - // messages are written to stderr - dpiDebugStream = stderr; - - // for any debugging level > 0 print a message indicating that tracing - // has started - if (dpiDebugLevel) { - dpiDebug__print("ODPI-C %s\n", DPI_VERSION_STRING); - dpiDebug__print("debugging messages initialized at level %lu\n", - dpiDebugLevel); - } -} - - -//----------------------------------------------------------------------------- -// dpiDebug__print() [INTERNAL] -// Print the specified debugging message with a newly calculated prefix. -//----------------------------------------------------------------------------- -void dpiDebug__print(const char *format, ...) -{ - char formatWithPrefix[512]; - va_list varArgs; - - dpiDebug__getFormatWithPrefix(format, formatWithPrefix, - sizeof(formatWithPrefix)); - va_start(varArgs, format); - (void) vfprintf(dpiDebugStream, formatWithPrefix, varArgs); - va_end(varArgs); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiDeqOptions.c b/vendor/github.com/godror/godror/odpi/src/dpiDeqOptions.c deleted file mode 100644 index 35cb84727ae..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiDeqOptions.c +++ /dev/null @@ -1,369 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiDeqOptions.c -// Implementation of AQ dequeue options. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiDeqOptions__create() [INTERNAL] -// Create a new subscription structure and return it. In case of error NULL -// is returned. -//----------------------------------------------------------------------------- -int dpiDeqOptions__create(dpiDeqOptions *options, dpiConn *conn, - dpiError *error) -{ - dpiGen__setRefCount(conn, error, 1); - options->conn = conn; - return dpiOci__descriptorAlloc(conn->env->handle, &options->handle, - DPI_OCI_DTYPE_AQDEQ_OPTIONS, "allocate descriptor", error); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions__free() [INTERNAL] -// Free the memory for a dequeue options structure. -//----------------------------------------------------------------------------- -void dpiDeqOptions__free(dpiDeqOptions *options, dpiError *error) -{ - if (options->handle) { - dpiOci__descriptorFree(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS); - options->handle = NULL; - } - if (options->conn) { - dpiGen__setRefCount(options->conn, error, -1); - options->conn = NULL; - } - dpiUtils__freeMemory(options); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions__getAttrValue() [INTERNAL] -// Get the attribute value in OCI. -//----------------------------------------------------------------------------- -static int dpiDeqOptions__getAttrValue(dpiDeqOptions *options, - uint32_t attribute, const char *fnName, void *value, - uint32_t *valueLength) -{ - dpiError error; - int status; - - if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, fnName, - &error) < 0) - return dpiGen__endPublicFn(options, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(options, value) - DPI_CHECK_PTR_NOT_NULL(options, valueLength) - status = dpiOci__attrGet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, - value, valueLength, attribute, "get attribute value", &error); - return dpiGen__endPublicFn(options, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions__setAttrValue() [INTERNAL] -// Set the attribute value in OCI. -//----------------------------------------------------------------------------- -static int dpiDeqOptions__setAttrValue(dpiDeqOptions *options, - uint32_t attribute, const char *fnName, const void *value, - uint32_t valueLength) -{ - dpiError error; - int status; - - if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, fnName, - &error) < 0) - return dpiGen__endPublicFn(options, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(options, value) - status = dpiOci__attrSet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, - (void*) value, valueLength, attribute, "set attribute value", - &error); - return dpiGen__endPublicFn(options, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_addRef() [PUBLIC] -// Add a reference to the dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_addRef(dpiDeqOptions *options) -{ - return dpiGen__addRef(options, DPI_HTYPE_DEQ_OPTIONS, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_getCondition() [PUBLIC] -// Return condition associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_getCondition(dpiDeqOptions *options, const char **value, - uint32_t *valueLength) -{ - return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_DEQCOND, __func__, - (void*) value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_getConsumerName() [PUBLIC] -// Return consumer name associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_getConsumerName(dpiDeqOptions *options, const char **value, - uint32_t *valueLength) -{ - return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_CONSUMER_NAME, - __func__, (void*) value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_getCorrelation() [PUBLIC] -// Return correlation associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_getCorrelation(dpiDeqOptions *options, const char **value, - uint32_t *valueLength) -{ - return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_CORRELATION, - __func__, (void*) value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_getMode() [PUBLIC] -// Return mode associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_getMode(dpiDeqOptions *options, dpiDeqMode *value) -{ - uint32_t valueLength = sizeof(uint32_t); - - return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_DEQ_MODE, - __func__, value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_getMsgId() [PUBLIC] -// Return message id associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_getMsgId(dpiDeqOptions *options, const char **value, - uint32_t *valueLength) -{ - dpiError error; - void *rawValue; - - if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, __func__, - &error) < 0) - return dpiGen__endPublicFn(options, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(options, value) - DPI_CHECK_PTR_NOT_NULL(options, valueLength) - if (dpiOci__attrGet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, - &rawValue, NULL, DPI_OCI_ATTR_DEQ_MSGID, "get attribute value", - &error) < 0) - return dpiGen__endPublicFn(options, DPI_FAILURE, &error); - dpiOci__rawPtr(options->env->handle, rawValue, (void**) value); - dpiOci__rawSize(options->env->handle, rawValue, valueLength); - return dpiGen__endPublicFn(options, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_getNavigation() [PUBLIC] -// Return navigation associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_getNavigation(dpiDeqOptions *options, - dpiDeqNavigation *value) -{ - uint32_t valueLength = sizeof(uint32_t); - - return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_NAVIGATION, - __func__, value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_getTransformation() [PUBLIC] -// Return transformation associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_getTransformation(dpiDeqOptions *options, const char **value, - uint32_t *valueLength) -{ - return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, - __func__, (void*) value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_getVisibility() [PUBLIC] -// Return visibility associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_getVisibility(dpiDeqOptions *options, dpiVisibility *value) -{ - uint32_t valueLength = sizeof(uint32_t); - - return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_VISIBILITY, - __func__, value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_getWait() [PUBLIC] -// Return the number of seconds to wait for a message when dequeuing. -//----------------------------------------------------------------------------- -int dpiDeqOptions_getWait(dpiDeqOptions *options, uint32_t *value) -{ - uint32_t valueLength = sizeof(uint32_t); - - return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_WAIT, __func__, - value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_release() [PUBLIC] -// Release a reference to the dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_release(dpiDeqOptions *options) -{ - return dpiGen__release(options, DPI_HTYPE_DEQ_OPTIONS, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_setCondition() [PUBLIC] -// Set condition associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_setCondition(dpiDeqOptions *options, const char *value, - uint32_t valueLength) -{ - return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_DEQCOND, __func__, - value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_setConsumerName() [PUBLIC] -// Set consumer name associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_setConsumerName(dpiDeqOptions *options, const char *value, - uint32_t valueLength) -{ - return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_CONSUMER_NAME, - __func__, value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_setCorrelation() [PUBLIC] -// Set correlation associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_setCorrelation(dpiDeqOptions *options, const char *value, - uint32_t valueLength) -{ - return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_CORRELATION, - __func__, value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_setDeliveryMode() [PUBLIC] -// Set the delivery mode associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_setDeliveryMode(dpiDeqOptions *options, - dpiMessageDeliveryMode value) -{ - return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_MSG_DELIVERY_MODE, - __func__, &value, 0); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_setMode() [PUBLIC] -// Set the mode associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_setMode(dpiDeqOptions *options, dpiDeqMode value) -{ - return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_DEQ_MODE, - __func__, &value, 0); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_setMsgId() [PUBLIC] -// Set the message id associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_setMsgId(dpiDeqOptions *options, const char *value, - uint32_t valueLength) -{ - void *rawValue = NULL; - dpiError error; - int status; - - if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, __func__, - &error) < 0) - return dpiGen__endPublicFn(options, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(options, value) - if (dpiOci__rawAssignBytes(options->env->handle, value, valueLength, - &rawValue, &error) < 0) - return dpiGen__endPublicFn(options, DPI_FAILURE, &error); - status = dpiOci__attrSet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, - (void*) &rawValue, valueLength, DPI_OCI_ATTR_DEQ_MSGID, - "set value", &error); - dpiOci__rawResize(options->env->handle, &rawValue, 0, &error); - return dpiGen__endPublicFn(options, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_setNavigation() [PUBLIC] -// Set navigation associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_setNavigation(dpiDeqOptions *options, dpiDeqNavigation value) -{ - return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_NAVIGATION, - __func__, &value, 0); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_setTransformation() [PUBLIC] -// Set transformation associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_setTransformation(dpiDeqOptions *options, const char *value, - uint32_t valueLength) -{ - return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, - __func__, value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_setVisibility() [PUBLIC] -// Set visibility associated with dequeue options. -//----------------------------------------------------------------------------- -int dpiDeqOptions_setVisibility(dpiDeqOptions *options, dpiVisibility value) -{ - return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_VISIBILITY, - __func__, &value, 0); -} - - -//----------------------------------------------------------------------------- -// dpiDeqOptions_setWait() [PUBLIC] -// Set the number of seconds to wait for a message when dequeuing. -//----------------------------------------------------------------------------- -int dpiDeqOptions_setWait(dpiDeqOptions *options, uint32_t value) -{ - return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_WAIT, __func__, - &value, 0); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiEnqOptions.c b/vendor/github.com/godror/godror/odpi/src/dpiEnqOptions.c deleted file mode 100644 index 24bf60a3229..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiEnqOptions.c +++ /dev/null @@ -1,173 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiEnqOptions.c -// Implementation of AQ enqueue options. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiEnqOptions__create() [INTERNAL] -// Create a new subscription structure and return it. In case of error NULL -// is returned. -//----------------------------------------------------------------------------- -int dpiEnqOptions__create(dpiEnqOptions *options, dpiConn *conn, - dpiError *error) -{ - dpiGen__setRefCount(conn, error, 1); - options->conn = conn; - return dpiOci__descriptorAlloc(conn->env->handle, &options->handle, - DPI_OCI_DTYPE_AQENQ_OPTIONS, "allocate descriptor", error); -} - - -//----------------------------------------------------------------------------- -// dpiEnqOptions__free() [INTERNAL] -// Free the memory for a enqueue options structure. -//----------------------------------------------------------------------------- -void dpiEnqOptions__free(dpiEnqOptions *options, dpiError *error) -{ - if (options->handle) { - dpiOci__descriptorFree(options->handle, DPI_OCI_DTYPE_AQENQ_OPTIONS); - options->handle = NULL; - } - if (options->conn) { - dpiGen__setRefCount(options->conn, error, -1); - options->conn = NULL; - } - dpiUtils__freeMemory(options); -} - - -//----------------------------------------------------------------------------- -// dpiEnqOptions__getAttrValue() [INTERNAL] -// Get the attribute value in OCI. -//----------------------------------------------------------------------------- -static int dpiEnqOptions__getAttrValue(dpiEnqOptions *options, - uint32_t attribute, const char *fnName, void *value, - uint32_t *valueLength) -{ - dpiError error; - int status; - - if (dpiGen__startPublicFn(options, DPI_HTYPE_ENQ_OPTIONS, fnName, - &error) < 0) - return dpiGen__endPublicFn(options, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(options, value) - DPI_CHECK_PTR_NOT_NULL(options, valueLength) - status = dpiOci__attrGet(options->handle, DPI_OCI_DTYPE_AQENQ_OPTIONS, - value, valueLength, attribute, "get attribute value", &error); - return dpiGen__endPublicFn(options, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiEnqOptions__setAttrValue() [INTERNAL] -// Set the attribute value in OCI. -//----------------------------------------------------------------------------- -static int dpiEnqOptions__setAttrValue(dpiEnqOptions *options, - uint32_t attribute, const char *fnName, const void *value, - uint32_t valueLength) -{ - dpiError error; - int status; - - if (dpiGen__startPublicFn(options, DPI_HTYPE_ENQ_OPTIONS, fnName, - &error) < 0) - return dpiGen__endPublicFn(options, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(options, value) - status = dpiOci__attrSet(options->handle, DPI_OCI_DTYPE_AQENQ_OPTIONS, - (void*) value, valueLength, attribute, "set attribute value", - &error); - return dpiGen__endPublicFn(options, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiEnqOptions_addRef() [PUBLIC] -// Add a reference to the enqueue options. -//----------------------------------------------------------------------------- -int dpiEnqOptions_addRef(dpiEnqOptions *options) -{ - return dpiGen__addRef(options, DPI_HTYPE_ENQ_OPTIONS, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiEnqOptions_getTransformation() [PUBLIC] -// Return transformation associated with enqueue options. -//----------------------------------------------------------------------------- -int dpiEnqOptions_getTransformation(dpiEnqOptions *options, const char **value, - uint32_t *valueLength) -{ - return dpiEnqOptions__getAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, - __func__, (void*) value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiEnqOptions_getVisibility() [PUBLIC] -// Return visibility associated with enqueue options. -//----------------------------------------------------------------------------- -int dpiEnqOptions_getVisibility(dpiEnqOptions *options, dpiVisibility *value) -{ - uint32_t valueLength = sizeof(uint32_t); - - return dpiEnqOptions__getAttrValue(options, DPI_OCI_ATTR_VISIBILITY, - __func__, value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiEnqOptions_release() [PUBLIC] -// Release a reference to the enqueue options. -//----------------------------------------------------------------------------- -int dpiEnqOptions_release(dpiEnqOptions *options) -{ - return dpiGen__release(options, DPI_HTYPE_ENQ_OPTIONS, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiEnqOptions_setDeliveryMode() [PUBLIC] -// Set the delivery mode associated with enqueue options. -//----------------------------------------------------------------------------- -int dpiEnqOptions_setDeliveryMode(dpiEnqOptions *options, - dpiMessageDeliveryMode value) -{ - return dpiEnqOptions__setAttrValue(options, DPI_OCI_ATTR_MSG_DELIVERY_MODE, - __func__, &value, 0); -} - - -//----------------------------------------------------------------------------- -// dpiEnqOptions_setTransformation() [PUBLIC] -// Set transformation associated with enqueue options. -//----------------------------------------------------------------------------- -int dpiEnqOptions_setTransformation(dpiEnqOptions *options, const char *value, - uint32_t valueLength) -{ - return dpiEnqOptions__setAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, - __func__, value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiEnqOptions_setVisibility() [PUBLIC] -// Set visibility associated with enqueue options. -//----------------------------------------------------------------------------- -int dpiEnqOptions_setVisibility(dpiEnqOptions *options, dpiVisibility value) -{ - return dpiEnqOptions__setAttrValue(options, DPI_OCI_ATTR_VISIBILITY, - __func__, &value, 0); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiEnv.c b/vendor/github.com/godror/godror/odpi/src/dpiEnv.c deleted file mode 100644 index c1a2c3f7d61..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiEnv.c +++ /dev/null @@ -1,180 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiEnv.c -// Implementation of environment. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiEnv__free() [INTERNAL] -// Free the memory associated with the environment. -//----------------------------------------------------------------------------- -void dpiEnv__free(dpiEnv *env, dpiError *error) -{ - if (env->threaded) - dpiMutex__destroy(env->mutex); - if (env->handle && !env->externalHandle) { - dpiOci__handleFree(env->handle, DPI_OCI_HTYPE_ENV); - env->handle = NULL; - } - if (env->errorHandles) { - dpiHandlePool__free(env->errorHandles); - env->errorHandles = NULL; - error->handle = NULL; - } - dpiUtils__freeMemory(env); -} - - -//----------------------------------------------------------------------------- -// dpiEnv__getCharacterSetIdAndName() [INTERNAL] -// Retrieve and store the IANA character set name for the attribute. -//----------------------------------------------------------------------------- -static int dpiEnv__getCharacterSetIdAndName(dpiEnv *env, uint16_t attribute, - uint16_t *charsetId, char *encoding, dpiError *error) -{ - *charsetId = 0; - dpiOci__attrGet(env->handle, DPI_OCI_HTYPE_ENV, charsetId, NULL, attribute, - "get environment", error); - return dpiGlobal__lookupEncoding(*charsetId, encoding, error); -} - - -//----------------------------------------------------------------------------- -// dpiEnv__getEncodingInfo() [INTERNAL] -// Populate the structure with the encoding info. -//----------------------------------------------------------------------------- -int dpiEnv__getEncodingInfo(dpiEnv *env, dpiEncodingInfo *info) -{ - info->encoding = env->encoding; - info->maxBytesPerCharacter = env->maxBytesPerCharacter; - info->nencoding = env->nencoding; - info->nmaxBytesPerCharacter = env->nmaxBytesPerCharacter; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiEnv__init() [INTERNAL] -// Initialize the environment structure. If an external handle is provided it -// is used directly; otherwise, a new OCI environment handle is created. In -// either case, information about the environment is stored for later use. -//----------------------------------------------------------------------------- -int dpiEnv__init(dpiEnv *env, const dpiContext *context, - const dpiCommonCreateParams *params, void *externalHandle, - dpiError *error) -{ - char timezoneBuffer[20]; - size_t timezoneLength; - - // store context and version information - env->context = context; - env->versionInfo = context->versionInfo; - - // an external handle is available, use it directly - if (externalHandle) { - env->handle = externalHandle; - env->externalHandle = 1; - - // otherwise, lookup encodings - } else { - - // lookup encoding - if (params->encoding && dpiGlobal__lookupCharSet(params->encoding, - &env->charsetId, error) < 0) - return DPI_FAILURE; - - // check for identical encoding before performing lookup of national - // character set encoding - if (params->nencoding && params->encoding && - strcmp(params->nencoding, params->encoding) == 0) - env->ncharsetId = env->charsetId; - else if (params->nencoding && - dpiGlobal__lookupCharSet(params->nencoding, - &env->ncharsetId, error) < 0) - return DPI_FAILURE; - - // both charsetId and ncharsetId must be zero or both must be non-zero - // use NLS routine to look up missing value, if needed - if (env->charsetId && !env->ncharsetId) { - if (dpiOci__nlsEnvironmentVariableGet(DPI_OCI_NLS_NCHARSET_ID, - &env->ncharsetId, error) < 0) - return DPI_FAILURE; - } else if (!env->charsetId && env->ncharsetId) { - if (dpiOci__nlsEnvironmentVariableGet(DPI_OCI_NLS_CHARSET_ID, - &env->charsetId, error) < 0) - return DPI_FAILURE; - } - - // create new environment handle - if (dpiOci__envNlsCreate(&env->handle, - params->createMode | DPI_OCI_OBJECT, - env->charsetId, env->ncharsetId, error) < 0) - return DPI_FAILURE; - - } - - // create the error handle pool - if (dpiHandlePool__create(&env->errorHandles, error) < 0) - return DPI_FAILURE; - error->env = env; - - // if threaded, create mutex for reference counts - if (params->createMode & DPI_OCI_THREADED) - dpiMutex__initialize(env->mutex); - - // determine encodings in use - if (dpiEnv__getCharacterSetIdAndName(env, DPI_OCI_ATTR_CHARSET_ID, - &env->charsetId, env->encoding, error) < 0) - return DPI_FAILURE; - if (dpiEnv__getCharacterSetIdAndName(env, DPI_OCI_ATTR_NCHARSET_ID, - &env->ncharsetId, env->nencoding, error) < 0) - return DPI_FAILURE; - - // acquire max bytes per character - if (dpiOci__nlsNumericInfoGet(env->handle, &env->maxBytesPerCharacter, - DPI_OCI_NLS_CHARSET_MAXBYTESZ, error) < 0) - return DPI_FAILURE; - - // for NCHAR we have no idea of how many so we simply take the worst case - // unless the charsets are identical - if (env->ncharsetId == env->charsetId) - env->nmaxBytesPerCharacter = env->maxBytesPerCharacter; - else env->nmaxBytesPerCharacter = 4; - - // allocate base date descriptor (for converting to/from time_t) - if (dpiOci__descriptorAlloc(env->handle, &env->baseDate, - DPI_OCI_DTYPE_TIMESTAMP_LTZ, "alloc base date descriptor", - error) < 0) - return DPI_FAILURE; - - // populate base date with January 1, 1970 - if (dpiOci__nlsCharSetConvert(env->handle, env->charsetId, timezoneBuffer, - sizeof(timezoneBuffer), DPI_CHARSET_ID_ASCII, "+00:00", 6, - &timezoneLength, error) < 0) - return DPI_FAILURE; - if (dpiOci__dateTimeConstruct(env->handle, env->baseDate, 1970, 1, 1, 0, 0, - 0, 0, timezoneBuffer, timezoneLength, error) < 0) - return DPI_FAILURE; - - // set whether or not we are threaded - if (params->createMode & DPI_MODE_CREATE_THREADED) - env->threaded = 1; - - // set whether or not events mode has been set - if (params->createMode & DPI_MODE_CREATE_EVENTS) - env->events = 1; - - return DPI_SUCCESS; -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiError.c b/vendor/github.com/godror/godror/odpi/src/dpiError.c deleted file mode 100644 index aac57b92f18..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiError.c +++ /dev/null @@ -1,222 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiError.c -// Implementation of error. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" -#include "dpiErrorMessages.h" - -//----------------------------------------------------------------------------- -// dpiError__getInfo() [INTERNAL] -// Get the error state from the error structure. Returns DPI_FAILURE as a -// convenience to the caller. -//----------------------------------------------------------------------------- -int dpiError__getInfo(dpiError *error, dpiErrorInfo *info) -{ - if (!info) - return DPI_FAILURE; - info->code = error->buffer->code; - info->offset = error->buffer->offset; - info->message = error->buffer->message; - info->messageLength = error->buffer->messageLength; - info->fnName = error->buffer->fnName; - info->action = error->buffer->action; - info->isRecoverable = error->buffer->isRecoverable; - info->encoding = error->buffer->encoding; - switch(info->code) { - case 12154: // TNS:could not resolve the connect identifier specified - info->sqlState = "42S02"; - break; - case 22: // invalid session ID; access denied - case 378: // buffer pools cannot be created as specified - case 602: // Internal programming exception - case 603: // ORACLE server session terminated by fatal error - case 604: // error occurred at recursive SQL level - case 609: // could not attach to incoming connection - case 1012: // not logged on - case 1033: // ORACLE initialization or shutdown in progress - case 1041: // internal error. hostdef extension doesn't exist - case 1043: // user side memory corruption - case 1089: // immediate shutdown or close in progress - case 1090: // shutdown in progress - case 1092: // ORACLE instance terminated. Disconnection forced - case 3113: // end-of-file on communication channel - case 3114: // not connected to ORACLE - case 3122: // attempt to close ORACLE-side window on user side - case 3135: // connection lost contact - case 12153: // TNS:not connected - case 27146: // post/wait initialization failed - case 28511: // lost RPC connection to heterogeneous remote agent - info->sqlState = "01002"; - break; - default: - if (error->buffer->code == 0 && - error->buffer->errorNum == (dpiErrorNum) 0) - info->sqlState = "00000"; - else info->sqlState = "HY000"; - break; - } - return DPI_FAILURE; -} - - -//----------------------------------------------------------------------------- -// dpiError__initHandle() [INTERNAL] -// Retrieve the OCI error handle to use for error handling, from a pool of -// error handles common to the environment handle stored on the error. This -// environment also controls the encoding of OCI errors (which uses the CHAR -// encoding of the environment). -//----------------------------------------------------------------------------- -int dpiError__initHandle(dpiError *error) -{ - if (dpiHandlePool__acquire(error->env->errorHandles, &error->handle, - error) < 0) - return DPI_FAILURE; - if (!error->handle) { - if (dpiOci__handleAlloc(error->env->handle, &error->handle, - DPI_OCI_HTYPE_ERROR, "allocate OCI error", error) < 0) - return DPI_FAILURE; - } - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiError__set() [INTERNAL] -// Set the error buffer to the specified DPI error. Returns DPI_FAILURE as a -// convenience to the caller. -//----------------------------------------------------------------------------- -int dpiError__set(dpiError *error, const char *action, dpiErrorNum errorNum, - ...) -{ - va_list varArgs; - - if (error) { - error->buffer->code = 0; - error->buffer->isRecoverable = 0; - error->buffer->offset = 0; - strcpy(error->buffer->encoding, DPI_CHARSET_NAME_UTF8); - error->buffer->action = action; - error->buffer->errorNum = errorNum; - va_start(varArgs, errorNum); - error->buffer->messageLength = - (uint32_t) vsnprintf(error->buffer->message, - sizeof(error->buffer->message), - dpiErrorMessages[errorNum - DPI_ERR_NO_ERR], varArgs); - va_end(varArgs); - if (dpiDebugLevel & DPI_DEBUG_LEVEL_ERRORS) - dpiDebug__print("internal error %.*s (%s / %s)\n", - error->buffer->messageLength, error->buffer->message, - error->buffer->fnName, action); - } - return DPI_FAILURE; -} - - -//----------------------------------------------------------------------------- -// dpiError__setFromOCI() [INTERNAL] -// Called when an OCI error has occurred and sets the error structure with -// the contents of that error. Note that trailing newlines and spaces are -// truncated from the message if they exist. If the connection is not NULL a -// check is made to see if the connection is no longer viable. The value -// DPI_FAILURE is returned as a convenience to the caller. -//----------------------------------------------------------------------------- -int dpiError__setFromOCI(dpiError *error, int status, dpiConn *conn, - const char *action) -{ - uint32_t callTimeout; - - // special error cases - if (status == DPI_OCI_INVALID_HANDLE) - return dpiError__set(error, action, DPI_ERR_INVALID_HANDLE, "OCI"); - else if (!error) - return DPI_FAILURE; - else if (!error->handle) - return dpiError__set(error, action, DPI_ERR_ERR_NOT_INITIALIZED); - else if (status != DPI_OCI_ERROR && status != DPI_OCI_NO_DATA) - return dpiError__set(error, action, - DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE, status, - error->buffer->fnName); - - // fetch OCI error - error->buffer->action = action; - strcpy(error->buffer->encoding, error->env->encoding); - if (dpiOci__errorGet(error->handle, DPI_OCI_HTYPE_ERROR, - error->env->charsetId, action, error) < 0) - return DPI_FAILURE; - if (dpiDebugLevel & DPI_DEBUG_LEVEL_ERRORS) - dpiDebug__print("OCI error %.*s (%s / %s)\n", - error->buffer->messageLength, error->buffer->message, - error->buffer->fnName, action); - - // determine if error is recoverable (Transaction Guard) - // if the attribute cannot be read properly, simply leave it as false; - // otherwise, that error will mask the one that we really want to see - error->buffer->isRecoverable = 0; - dpiOci__attrGet(error->handle, DPI_OCI_HTYPE_ERROR, - (void*) &error->buffer->isRecoverable, 0, - DPI_OCI_ATTR_ERROR_IS_RECOVERABLE, NULL, error); - - // check for certain errors which indicate that the session is dead and - // should be dropped from the session pool (if a session pool was used) - // also check for call timeout and raise unified message instead - if (conn && !conn->deadSession) { - switch (error->buffer->code) { - case 22: // invalid session ID; access denied - case 28: // your session has been killed - case 31: // your session has been marked for kill - case 45: // your session has been terminated with no replay - case 378: // buffer pools cannot be created as specified - case 602: // internal programming exception - case 603: // ORACLE server session terminated by fatal error - case 609: // could not attach to incoming connection - case 1012: // not logged on - case 1041: // internal error. hostdef extension doesn't exist - case 1043: // user side memory corruption - case 1089: // immediate shutdown or close in progress - case 1092: // ORACLE instance terminated. Disconnection forced - case 2396: // exceeded maximum idle time, please connect again - case 3113: // end-of-file on communication channel - case 3114: // not connected to ORACLE - case 3122: // attempt to close ORACLE-side window on user side - case 3135: // connection lost contact - case 12153: // TNS:not connected - case 12537: // TNS:connection closed - case 12547: // TNS:lost contact - case 12570: // TNS:packet reader failure - case 12583: // TNS:no reader - case 27146: // post/wait initialization failed - case 28511: // lost RPC connection - case 56600: // an illegal OCI function call was issued - conn->deadSession = 1; - break; - case 3136: // inbound connection timed out - case 3156: // OCI call timed out - case 12161: // TNS:internal error: partial data received - callTimeout = 0; - if (conn->env->versionInfo->versionNum >= 18) - dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, - (void*) &callTimeout, 0, DPI_OCI_ATTR_CALL_TIMEOUT, - NULL, error); - if (callTimeout > 0) { - dpiError__set(error, action, DPI_ERR_CALL_TIMEOUT, - callTimeout, error->buffer->code); - error->buffer->code = 0; - } - break; - } - } - - return DPI_FAILURE; -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiErrorMessages.h b/vendor/github.com/godror/godror/odpi/src/dpiErrorMessages.h deleted file mode 100644 index 1de52a2b17b..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiErrorMessages.h +++ /dev/null @@ -1,90 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiErrorMessages.h -// Definition of error messages used in ODPI-C. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -static const char* const dpiErrorMessages[DPI_ERR_MAX - DPI_ERR_NO_ERR] = { - "DPI-1000: no error", // DPI_ERR_NO_ERR - "DPI-1001: out of memory", // DPI_ERR_NO_MEMORY - "DPI-1002: invalid %s handle", // DPI_ERR_INVALID_HANDLE - "DPI-1003: OCI error handle is not initialized", // DPI_ERR_ERR_NOT_INITIALIZED - "DPI-1004: unable to get error message", // DPI_ERR_GET_FAILED - "DPI-1005: unable to acquire Oracle environment handle", // DPI_ERR_CREATE_ENV - "DPI-1006: unable to convert text to session character set", // DPI_ERR_CONVERT_TEXT - "DPI-1007: no query has been executed", // DPI_ERR_QUERY_NOT_EXECUTED - "DPI-1008: data type %d is not supported", // DPI_ERR_UNHANDLED_DATA_TYPE - "DPI-1009: zero-based position %u is not valid with max array size of %u", // DPI_ERR_INVALID_ARRAY_POSITION - "DPI-1010: not connected", // DPI_ERR_NOT_CONNECTED - "DPI-1011: connection was not acquired from a session pool", // DPI_ERR_CONN_NOT_IN_POOL - "DPI-1012: proxy authentication is not possible with homogeneous pools", // DPI_ERR_INVALID_PROXY - "DPI-1013: not supported", // DPI_ERR_NOT_SUPPORTED - "DPI-1014: conversion between Oracle type %d and native type %d is not implemented", // DPI_ERR_UNHANDLED_CONVERSION - "DPI-1015: array size of %u is too large", // DPI_ERR_ARRAY_SIZE_TOO_BIG - "DPI-1016: invalid date", // DPI_ERR_INVALID_DATE - "DPI-1017: value is null", // DPI_ERR_VALUE_IS_NULL - "DPI-1018: array size of %u is too small", // DPI_ERR_ARRAY_SIZE_TOO_SMALL - "DPI-1019: buffer size of %u is too small", // DPI_ERR_BUFFER_SIZE_TOO_SMALL - "DPI-1020: application requires ODPI-C %d (min %d.%d) but is using a shared library at version %d.%d", // DPI_ERR_VERSION_NOT_SUPPORTED - "DPI-1021: Oracle type %u is invalid", // DPI_ERR_INVALID_ORACLE_TYPE - "DPI-1022: attribute %.*s is not part of object type %.*s.%.*s", // DPI_ERR_WRONG_ATTR - "DPI-1023: object %.*s.%.*s is not a collection", // DPI_ERR_NOT_COLLECTION - "DPI-1024: element at index %d does not exist", // DPI_ERR_INVALID_INDEX - "DPI-1025: no object type specified for object variable", // DPI_ERR_NO_OBJECT_TYPE - "DPI-1026: invalid character set %s", // DPI_ERR_INVALID_CHARSET - "DPI-1027: scroll operation would go out of the result set", // DPI_ERR_SCROLL_OUT_OF_RS - "DPI-1028: query position %u is invalid", // DPI_ERR_QUERY_POSITION_INVALID - "DPI-1029: no row currently fetched", // DPI_ERR_NO_ROW_FETCHED - "DPI-1030: unable to get or set error structure for thread local storage", // DPI_ERR_TLS_ERROR - "DPI-1031: array size cannot be zero", // DPI_ERR_ARRAY_SIZE_ZERO - "DPI-1032: user name and password cannot be set when using external authentication", // DPI_ERR_EXT_AUTH_WITH_CREDENTIALS - "DPI-1033: unable to get row offset", // DPI_ERR_CANNOT_GET_ROW_OFFSET - "DPI-1034: connection created from external handle cannot be closed", // DPI_ERR_CONN_IS_EXTERNAL - "DPI-1035: size of the transaction ID is %u and cannot exceed %u", // DPI_ERR_TRANS_ID_TOO_LARGE - "DPI-1036: size of the branch ID is %u and cannot exceed %u", // DPI_ERR_BRANCH_ID_TOO_LARGE - "DPI-1037: column at array position %u fetched with error %u", // DPI_ERR_COLUMN_FETCH - "DPI-1039: statement was already closed", // DPI_ERR_STMT_CLOSED - "DPI-1040: LOB was already closed", // DPI_ERR_LOB_CLOSED - "DPI-1041: invalid character set id %d", // DPI_ERR_INVALID_CHARSET_ID - "DPI-1042: invalid OCI number", // DPI_ERR_INVALID_OCI_NUMBER - "DPI-1043: invalid number", // DPI_ERR_INVALID_NUMBER - "DPI-1044: value cannot be represented as an Oracle number", // DPI_ERR_NUMBER_NO_REPR - "DPI-1045: strings converted to numbers can only be up to 172 characters long", // DPI_ERR_NUMBER_STRING_TOO_LONG - "DPI-1046: parameter %s cannot be a NULL pointer", // DPI_ERR_NULL_POINTER_PARAMETER - "DPI-1047: Cannot locate a %s-bit Oracle Client library: \"%s\". See https://oracle.github.io/odpi/doc/installation.html#%s for help", // DPI_ERR_LOAD_LIBRARY - "DPI-1049: symbol %s not found in OCI library", // DPI_ERR_LOAD_SYMBOL - "DPI-1050: Oracle Client library is at version %d.%d but version %d.%d or higher is needed", // DPI_ERR_ORACLE_CLIENT_TOO_OLD - "DPI-1052: unable to get NLS environment variable", // DPI_ERR_NLS_ENV_VAR_GET, - "DPI-1053: parameter %s cannot be a NULL pointer while corresponding length parameter is non-zero", // DPI_ERR_PTR_LENGTH_MISMATCH - "DPI-1055: value is not a number (NaN) and cannot be used in Oracle numbers", // DPI_ERR_NAN - "DPI-1056: found object of type %.*s.%.*s when expecting object of type %.*s.%.*s", // DPI_ERR_WRONG_TYPE - "DPI-1057: buffer size of %u is too large (max %u)", // DPI_ERR_BUFFER_SIZE_TOO_LARGE - "DPI-1058: edition not supported with connection class", // DPI_ERR_NO_EDITION_WITH_CONN_CLASS - "DPI-1059: bind variables are not supported in DDL statements", // DPI_ERR_NO_BIND_VARS_IN_DDL - "DPI-1060: subscription was already closed", // DPI_ERR_SUBSCR_CLOSED - "DPI-1061: edition is not supported when a new password is specified", // DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD - "DPI-1062: unexpected OCI return value %d in function %s", // DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE - "DPI-1063: modes DPI_MODE_EXEC_BATCH_ERRORS and DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS can only be used with insert, update, delete and merge statements", // DPI_ERR_EXEC_MODE_ONLY_FOR_DML - "DPI-1064: array variables are not supported with dpiStmt_executeMany()", // DPI_ERR_ARRAY_VAR_NOT_SUPPORTED - "DPI-1065: events mode is required to subscribe to events in the database", // DPI_ERR_EVENTS_MODE_REQUIRED - "DPI-1066: Oracle Database is at version %d.%d but version %d.%d or higher is needed", // DPI_ERR_ORACLE_DB_TOO_OLD - "DPI-1067: call timeout of %u ms exceeded with ORA-%d", // DPI_ERR_CALL_TIMEOUT - "DPI-1068: SODA cursor was already closed", // DPI_ERR_SODA_CURSOR_CLOSED - "DPI-1069: proxy user name must be enclosed in [] when using external authentication", // DPI_ERR_EXT_AUTH_INVALID_PROXY - "DPI-1070: no payload provided in message properties", // DPI_ERR_QUEUE_NO_PAYLOAD - "DPI-1071: payload type in message properties must match the payload type of the queue", // DPI_ERR_QUEUE_WRONG_PAYLOAD_TYPE - "DPI-1072: the Oracle Client library version is unsupported", // DPI_ERR_ORACLE_CLIENT_UNSUPPORTED - "DPI-1073: sharding key is required when specifying a super sharding key", // DPI_ERR_MISSING_SHARDING_KEY -}; diff --git a/vendor/github.com/godror/godror/odpi/src/dpiGen.c b/vendor/github.com/godror/godror/odpi/src/dpiGen.c deleted file mode 100644 index f671adf2a21..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiGen.c +++ /dev/null @@ -1,307 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiGen.c -// Generic routines for managing the types available through public APIs. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// definition of handle types -//----------------------------------------------------------------------------- -static const dpiTypeDef dpiAllTypeDefs[DPI_HTYPE_MAX - DPI_HTYPE_NONE - 1] = { - { - "dpiConn", // name - sizeof(dpiConn), // size of structure - 0x49DC600C, // check integer - (dpiTypeFreeProc) dpiConn__free - }, - { - "dpiPool", // name - sizeof(dpiPool), // size of structure - 0x18E1AA4B, // check integer - (dpiTypeFreeProc) dpiPool__free - }, - { - "dpiStmt", // name - sizeof(dpiStmt), // size of structure - 0x31B02B2E, // check integer - (dpiTypeFreeProc) dpiStmt__free - }, - { - "dpiVar", // name - sizeof(dpiVar), // size of structure - 0x2AE8C6DC, // check integer - (dpiTypeFreeProc) dpiVar__free - }, - { - "dpiLob", // name - sizeof(dpiLob), // size of structure - 0xD8F31746, // check integer - (dpiTypeFreeProc) dpiLob__free - }, - { - "dpiObject", // name - sizeof(dpiObject), // size of structure - 0x38616080, // check integer - (dpiTypeFreeProc) dpiObject__free - }, - { - "dpiObjectType", // name - sizeof(dpiObjectType), // size of structure - 0x86036059, // check integer - (dpiTypeFreeProc) dpiObjectType__free - }, - { - "dpiObjectAttr", // name - sizeof(dpiObjectAttr), // size of structure - 0xea6d5dde, // check integer - (dpiTypeFreeProc) dpiObjectAttr__free - }, - { - "dpiSubscr", // name - sizeof(dpiSubscr), // size of structure - 0xa415a1c0, // check integer - (dpiTypeFreeProc) dpiSubscr__free - }, - { - "dpiDeqOptions", // name - sizeof(dpiDeqOptions), // size of structure - 0x70ee498d, // check integer - (dpiTypeFreeProc) dpiDeqOptions__free - }, - { - "dpiEnqOptions", // name - sizeof(dpiEnqOptions), // size of structure - 0x682f3946, // check integer - (dpiTypeFreeProc) dpiEnqOptions__free - }, - { - "dpiMsgProps", // name - sizeof(dpiMsgProps), // size of structure - 0xa2b75506, // check integer - (dpiTypeFreeProc) dpiMsgProps__free - }, - { - "dpiRowid", // name - sizeof(dpiRowid), // size of structure - 0x6204fa04, // check integer - (dpiTypeFreeProc) dpiRowid__free - }, - { - "dpiContext", // name - sizeof(dpiContext), // size of structure - 0xd81b9181, // check integer - NULL - }, - { - "dpiSodaColl", // name - sizeof(dpiSodaColl), // size of structure - 0x3684db22, // check integer - (dpiTypeFreeProc) dpiSodaColl__free - }, - { - "dpiSodaCollCursor", // name - sizeof(dpiSodaCollCursor), // size of structure - 0xcdc73b86, // check integer - (dpiTypeFreeProc) dpiSodaCollCursor__free - }, - { - "dpiSodaDb", // name - sizeof(dpiSodaDb), // size of structure - 0x1f386121, // check integer - (dpiTypeFreeProc) dpiSodaDb__free - }, - { - "dpiSodaDoc", // name - sizeof(dpiSodaDoc), // size of structure - 0xaffd950a, // check integer - (dpiTypeFreeProc) dpiSodaDoc__free - }, - { - "dpiSodaDocCursor", // name - sizeof(dpiSodaDocCursor), // size of structure - 0x80ceb83b, // check integer - (dpiTypeFreeProc) dpiSodaDocCursor__free - }, - { - "dpiQueue", // name - sizeof(dpiQueue), // size of structure - 0x54904ba2, // check integer - (dpiTypeFreeProc) dpiQueue__free - } -}; - - -//----------------------------------------------------------------------------- -// dpiGen__addRef() [INTERNAL] -// Add a reference to the specified handle. -//----------------------------------------------------------------------------- -int dpiGen__addRef(void *ptr, dpiHandleTypeNum typeNum, const char *fnName) -{ - dpiError error; - - if (dpiGen__startPublicFn(ptr, typeNum, fnName, &error) < 0) - return dpiGen__endPublicFn(ptr, DPI_FAILURE, &error); - dpiGen__setRefCount(ptr, &error, 1); - return dpiGen__endPublicFn(ptr, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiGen__allocate() [INTERNAL] -// Allocate memory for the specified type and initialize the base fields. The -// type specified is assumed to be valid. If the environment is specified, use -// it; otherwise, create a new one. No additional initialization is performed. -//----------------------------------------------------------------------------- -int dpiGen__allocate(dpiHandleTypeNum typeNum, dpiEnv *env, void **handle, - dpiError *error) -{ - const dpiTypeDef *typeDef; - dpiBaseType *value; - - typeDef = &dpiAllTypeDefs[typeNum - DPI_HTYPE_NONE - 1]; - if (dpiUtils__allocateMemory(1, typeDef->size, 1, "allocate handle", - (void**) &value, error) < 0) - return DPI_FAILURE; - value->typeDef = typeDef; - value->checkInt = typeDef->checkInt; - value->refCount = 1; - if (!env && typeNum != DPI_HTYPE_CONTEXT) { - if (dpiUtils__allocateMemory(1, sizeof(dpiEnv), 1, "allocate env", - (void**) &env, error) < 0) { - dpiUtils__freeMemory(value); - return DPI_FAILURE; - } - } - value->env = env; - if (dpiDebugLevel & DPI_DEBUG_LEVEL_REFS) - dpiDebug__print("ref %p (%s) -> 1 [NEW]\n", value, typeDef->name); - - *handle = value; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiGen__checkHandle() [INTERNAL] -// Check that the specific handle is valid, that it matches the type -// requested and that the check integer is still in place. -//----------------------------------------------------------------------------- -int dpiGen__checkHandle(const void *ptr, dpiHandleTypeNum typeNum, - const char *action, dpiError *error) -{ - dpiBaseType *value = (dpiBaseType*) ptr; - const dpiTypeDef *typeDef; - - typeDef = &dpiAllTypeDefs[typeNum - DPI_HTYPE_NONE - 1]; - if (!ptr || value->typeDef != typeDef || - value->checkInt != typeDef->checkInt) - return dpiError__set(error, action, DPI_ERR_INVALID_HANDLE, - typeDef->name); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiGen__endPublicFn() [INTERNAL] -// This method should be the last call made in any public method using an -// ODPI-C handle (other than dpiContext which is handled differently). -//----------------------------------------------------------------------------- -int dpiGen__endPublicFn(const void *ptr, int returnValue, dpiError *error) -{ - if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) - dpiDebug__print("fn end %s(%p) -> %d\n", error->buffer->fnName, ptr, - returnValue); - if (error->handle) - dpiHandlePool__release(error->env->errorHandles, &error->handle); - - return returnValue; -} - - -//----------------------------------------------------------------------------- -// dpiGen__release() [INTERNAL] -// Release a reference to the specified handle. If the reference count -// reaches zero, the resources associated with the handle are released and -// the memory associated with the handle is freed. Any internal references -// held to other handles are also released. -//----------------------------------------------------------------------------- -int dpiGen__release(void *ptr, dpiHandleTypeNum typeNum, const char *fnName) -{ - dpiError error; - - if (dpiGen__startPublicFn(ptr, typeNum, fnName, &error) < 0) - return dpiGen__endPublicFn(ptr, DPI_FAILURE, &error); - dpiGen__setRefCount(ptr, &error, -1); - return dpiGen__endPublicFn(ptr, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiGen__setRefCount() [INTERNAL] -// Increase or decrease the reference count by the given amount. The handle -// is assumed to be valid at this point. If the environment is in threaded -// mode, acquire the mutex first before making any adjustments to the reference -// count. If the operation sets the reference count to zero, release all -// resources and free the memory associated with the structure. -//----------------------------------------------------------------------------- -void dpiGen__setRefCount(void *ptr, dpiError *error, int increment) -{ - dpiBaseType *value = (dpiBaseType*) ptr; - unsigned localRefCount; - - // if threaded need to protect modification of the refCount with a mutex; - // also ensure that if the reference count reaches zero that it is - // immediately marked invalid in order to avoid race conditions - if (value->env->threaded) - dpiMutex__acquire(value->env->mutex); - value->refCount += increment; - localRefCount = value->refCount; - if (localRefCount == 0) - dpiUtils__clearMemory(&value->checkInt, sizeof(value->checkInt)); - if (value->env->threaded) - dpiMutex__release(value->env->mutex); - - // reference count debugging - if (dpiDebugLevel & DPI_DEBUG_LEVEL_REFS) - dpiDebug__print("ref %p (%s) -> %d\n", ptr, value->typeDef->name, - localRefCount); - - // if the refCount has reached zero, call the free routine - if (localRefCount == 0) - (*value->typeDef->freeProc)(value, error); -} - - -//----------------------------------------------------------------------------- -// dpiGen__startPublicFn() [INTERNAL] -// This method should be the first call made in any public method using an -// ODPI-C handle (other than dpiContext which is handled differently). The -// handle is checked for validity and an error handle is acquired for use in -// all subsequent calls. -//----------------------------------------------------------------------------- -int dpiGen__startPublicFn(const void *ptr, dpiHandleTypeNum typeNum, - const char *fnName, dpiError *error) -{ - dpiBaseType *value = (dpiBaseType*) ptr; - - if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) - dpiDebug__print("fn start %s(%p)\n", fnName, ptr); - if (dpiGlobal__initError(fnName, error) < 0) - return DPI_FAILURE; - if (dpiGen__checkHandle(ptr, typeNum, "check main handle", error) < 0) - return DPI_FAILURE; - error->env = value->env; - return DPI_SUCCESS; -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiGlobal.c b/vendor/github.com/godror/godror/odpi/src/dpiGlobal.c deleted file mode 100644 index 6599d870421..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiGlobal.c +++ /dev/null @@ -1,291 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiGlobal.c -// Global environment used for managing errors in a thread safe manner as -// well as for looking up encodings. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -// cross platform way of defining an initializer that runs at application -// startup (similar to what is done for the constructor calls for static C++ -// objects) -#if defined(_MSC_VER) - #pragma section(".CRT$XCU", read) - #define DPI_INITIALIZER_HELPER(f, p) \ - static void f(void); \ - __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \ - __pragma(comment(linker,"/include:" p #f "_")) \ - static void f(void) - #ifdef _WIN64 - #define DPI_INITIALIZER(f) DPI_INITIALIZER_HELPER(f, "") - #else - #define DPI_INITIALIZER(f) DPI_INITIALIZER_HELPER(f, "_") - #endif -#else - #define DPI_INITIALIZER(f) \ - static void f(void) __attribute__((constructor)); \ - static void f(void) -#endif - -// a global OCI environment is used for managing error buffers in a thread-safe -// manner; each thread is given its own error buffer; OCI error handles, -// though, must be created within the OCI environment created for use by -// standalone connections and session pools -static void *dpiGlobalEnvHandle = NULL; -static void *dpiGlobalErrorHandle = NULL; -static void *dpiGlobalThreadKey = NULL; -static dpiErrorBuffer dpiGlobalErrorBuffer; -static int dpiGlobalInitialized = 0; - -// a global mutex is used to ensure that only one thread is used to perform -// initialization of ODPI-C -static dpiMutexType dpiGlobalMutex; - -//----------------------------------------------------------------------------- -// dpiGlobal__extendedInitialize() [INTERNAL] -// Create the global environment used for managing error buffers in a -// thread-safe manner. This environment is solely used for implementing thread -// local storage for the error buffers and for looking up encodings given an -// IANA or Oracle character set name. -//----------------------------------------------------------------------------- -static int dpiGlobal__extendedInitialize(dpiError *error) -{ - int status; - - // create threaded OCI environment for storing error buffers and for - // looking up character sets; use character set AL32UTF8 solely to avoid - // the overhead of processing the environment variables; no error messages - // from this environment are ever used (ODPI-C specific error messages are - // used) - if (dpiOci__envNlsCreate(&dpiGlobalEnvHandle, DPI_OCI_THREADED, - DPI_CHARSET_ID_UTF8, DPI_CHARSET_ID_UTF8, error) < 0) - return DPI_FAILURE; - - // create global error handle - if (dpiOci__handleAlloc(dpiGlobalEnvHandle, &dpiGlobalErrorHandle, - DPI_OCI_HTYPE_ERROR, "create global error", error) < 0) { - dpiOci__handleFree(dpiGlobalEnvHandle, DPI_OCI_HTYPE_ENV); - return DPI_FAILURE; - } - - // create global thread key - status = dpiOci__threadKeyInit(dpiGlobalEnvHandle, dpiGlobalErrorHandle, - &dpiGlobalThreadKey, (void*) dpiUtils__freeMemory, error); - if (status < 0) { - dpiOci__handleFree(dpiGlobalEnvHandle, DPI_OCI_HTYPE_ENV); - return DPI_FAILURE; - } - - // mark library as fully initialized - dpiGlobalInitialized = 1; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiGlobal__finalize() [INTERNAL] -// Called when the process terminates and ensures that everything is cleaned -// up. -//----------------------------------------------------------------------------- -static void dpiGlobal__finalize(void) -{ - void *errorBuffer = NULL; - dpiError error; - - dpiMutex__acquire(dpiGlobalMutex); - dpiGlobalInitialized = 0; - error.buffer = &dpiGlobalErrorBuffer; - if (dpiGlobalThreadKey) { - dpiOci__threadKeyGet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, - dpiGlobalThreadKey, &errorBuffer, &error); - if (errorBuffer) { - dpiOci__threadKeySet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, - dpiGlobalThreadKey, NULL, &error); - dpiUtils__freeMemory(errorBuffer); - } - dpiOci__threadKeyDestroy(dpiGlobalEnvHandle, dpiGlobalErrorHandle, - &dpiGlobalThreadKey, &error); - dpiGlobalThreadKey = NULL; - } - if (dpiGlobalEnvHandle) { - dpiOci__handleFree(dpiGlobalEnvHandle, DPI_OCI_HTYPE_ENV); - dpiGlobalEnvHandle = NULL; - } - dpiMutex__release(dpiGlobalMutex); -} - - -//----------------------------------------------------------------------------- -// dpiGlobal__initError() [INTERNAL] -// Get the thread local error structure for use in all other functions. If -// an error structure cannot be determined for some reason, the global error -// buffer structure is returned instead. -//----------------------------------------------------------------------------- -int dpiGlobal__initError(const char *fnName, dpiError *error) -{ - dpiErrorBuffer *tempErrorBuffer; - - // initialize error buffer output to global error buffer structure; this is - // the value that is used if an error takes place before the thread local - // error structure can be returned - error->handle = NULL; - error->buffer = &dpiGlobalErrorBuffer; - if (fnName) - error->buffer->fnName = fnName; - - // initialize global environment, if necessary - // this should only ever be done once by the first thread to execute this - if (!dpiGlobalInitialized) { - dpiMutex__acquire(dpiGlobalMutex); - if (!dpiGlobalInitialized) - dpiGlobal__extendedInitialize(error); - dpiMutex__release(dpiGlobalMutex); - if (!dpiGlobalInitialized) - return DPI_FAILURE; - } - - // look up the error buffer specific to this thread - if (dpiOci__threadKeyGet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, - dpiGlobalThreadKey, (void**) &tempErrorBuffer, error) < 0) - return DPI_FAILURE; - - // if NULL, key has never been set for this thread, allocate new error - // and set it - if (!tempErrorBuffer) { - if (dpiUtils__allocateMemory(1, sizeof(dpiErrorBuffer), 1, - "allocate error buffer", (void**) &tempErrorBuffer, error) < 0) - return DPI_FAILURE; - if (dpiOci__threadKeySet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, - dpiGlobalThreadKey, tempErrorBuffer, error) < 0) { - dpiUtils__freeMemory(tempErrorBuffer); - return DPI_FAILURE; - } - } - - // if a function name has been specified, clear error - // the only time a function name is not specified is for - // dpiContext_getError() when the error information is being retrieved - if (fnName) { - tempErrorBuffer->code = 0; - tempErrorBuffer->offset = 0; - tempErrorBuffer->errorNum = (dpiErrorNum) 0; - tempErrorBuffer->isRecoverable = 0; - tempErrorBuffer->messageLength = 0; - tempErrorBuffer->fnName = fnName; - tempErrorBuffer->action = "start"; - strcpy(tempErrorBuffer->encoding, DPI_CHARSET_NAME_UTF8); - } - - error->buffer = tempErrorBuffer; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiGlobal__initialize() [INTERNAL] -// Initialization function that runs at process startup or when the library -// is first loaded. Some operating systems have limits on what can be run in -// this function, so most work is done in the dpiGlobal__extendedInitialize() -// function that runs when the first call to dpiContext_create() is made. -//----------------------------------------------------------------------------- -DPI_INITIALIZER(dpiGlobal__initialize) -{ - memset(&dpiGlobalErrorBuffer, 0, sizeof(dpiGlobalErrorBuffer)); - strcpy(dpiGlobalErrorBuffer.encoding, DPI_CHARSET_NAME_UTF8); - dpiMutex__initialize(dpiGlobalMutex); - dpiDebug__initialize(); - atexit(dpiGlobal__finalize); -} - - -//----------------------------------------------------------------------------- -// dpiGlobal__lookupCharSet() [INTERNAL] -// Lookup the character set id that can be used in the call to -// OCINlsEnvCreate(). -//----------------------------------------------------------------------------- -int dpiGlobal__lookupCharSet(const char *name, uint16_t *charsetId, - dpiError *error) -{ - char oraCharsetName[DPI_OCI_NLS_MAXBUFSZ]; - - // check for well-known encodings first - if (strcmp(name, DPI_CHARSET_NAME_UTF8) == 0) - *charsetId = DPI_CHARSET_ID_UTF8; - else if (strcmp(name, DPI_CHARSET_NAME_UTF16) == 0) - *charsetId = DPI_CHARSET_ID_UTF16; - else if (strcmp(name, DPI_CHARSET_NAME_ASCII) == 0) - *charsetId = DPI_CHARSET_ID_ASCII; - else if (strcmp(name, DPI_CHARSET_NAME_UTF16LE) == 0 || - strcmp(name, DPI_CHARSET_NAME_UTF16BE) == 0) - return dpiError__set(error, "check encoding", DPI_ERR_NOT_SUPPORTED); - - // perform lookup; check for the Oracle character set name first and if - // that fails, lookup using the IANA character set name - else { - if (dpiOci__nlsCharSetNameToId(dpiGlobalEnvHandle, name, charsetId, - error) < 0) - return DPI_FAILURE; - if (!*charsetId) { - if (dpiOci__nlsNameMap(dpiGlobalEnvHandle, oraCharsetName, - sizeof(oraCharsetName), name, DPI_OCI_NLS_CS_IANA_TO_ORA, - error) < 0) - return dpiError__set(error, "lookup charset", - DPI_ERR_INVALID_CHARSET, name); - dpiOci__nlsCharSetNameToId(dpiGlobalEnvHandle, oraCharsetName, - charsetId, error); - } - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiGlobal__lookupEncoding() [INTERNAL] -// Get the IANA character set name (encoding) given the Oracle character set -// id. -//----------------------------------------------------------------------------- -int dpiGlobal__lookupEncoding(uint16_t charsetId, char *encoding, - dpiError *error) -{ - char oracleName[DPI_OCI_NLS_MAXBUFSZ]; - - // check for well-known encodings first - switch (charsetId) { - case DPI_CHARSET_ID_UTF8: - strcpy(encoding, DPI_CHARSET_NAME_UTF8); - return DPI_SUCCESS; - case DPI_CHARSET_ID_UTF16: - strcpy(encoding, DPI_CHARSET_NAME_UTF16); - return DPI_SUCCESS; - case DPI_CHARSET_ID_ASCII: - strcpy(encoding, DPI_CHARSET_NAME_ASCII); - return DPI_SUCCESS; - } - - // get character set name - if (dpiOci__nlsCharSetIdToName(dpiGlobalEnvHandle, oracleName, - sizeof(oracleName), charsetId, error) < 0) - return dpiError__set(error, "lookup Oracle character set name", - DPI_ERR_INVALID_CHARSET_ID, charsetId); - - // get IANA character set name - if (dpiOci__nlsNameMap(dpiGlobalEnvHandle, encoding, DPI_OCI_NLS_MAXBUFSZ, - oracleName, DPI_OCI_NLS_CS_ORA_TO_IANA, error) < 0) - return dpiError__set(error, "lookup IANA name", - DPI_ERR_INVALID_CHARSET_ID, charsetId); - - return DPI_SUCCESS; -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiHandleList.c b/vendor/github.com/godror/godror/odpi/src/dpiHandleList.c deleted file mode 100644 index 2f3864067bb..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiHandleList.c +++ /dev/null @@ -1,116 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiHandleList.c -// Implementation of a list of handles which are managed in a thread-safe -// manner. The references to these handles are assumed to be held by other -// structures. No references are held by the list of handles defined here. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiHandleList__addHandle() [INTERNAL] -// Add a handle to the list. The list is expanded in sets of 8 handles as -// needed. A current position is maintained to reduce the number of scans of -// the list are required. An empty slot is designated by a NULL pointer. -//----------------------------------------------------------------------------- -int dpiHandleList__addHandle(dpiHandleList *list, void *handle, - uint32_t *slotNum, dpiError *error) -{ - uint32_t numSlots, i; - void **tempHandles; - - dpiMutex__acquire(list->mutex); - if (list->numUsedSlots == list->numSlots) { - numSlots = list->numSlots + 8; - if (dpiUtils__allocateMemory(numSlots, sizeof(void*), 1, - "allocate slots", (void**) &tempHandles, error) < 0) { - dpiMutex__release(list->mutex); - return DPI_FAILURE; - } - memcpy(tempHandles, list->handles, list->numSlots * sizeof(void*)); - dpiUtils__freeMemory(list->handles); - list->handles = tempHandles; - list->numSlots = numSlots; - *slotNum = list->numUsedSlots++; - list->currentPos = list->numUsedSlots; - } else { - for (i = 0; i < list->numSlots; i++) { - if (!list->handles[list->currentPos]) - break; - list->currentPos++; - if (list->currentPos == list->numSlots) - list->currentPos = 0; - } - list->numUsedSlots++; - *slotNum = list->currentPos++; - if (list->currentPos == list->numSlots) - list->currentPos = 0; - } - list->handles[*slotNum] = handle; - dpiMutex__release(list->mutex); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiHandleList__create() [INTERNAL] -// Create a new (empty) list of handles. -//----------------------------------------------------------------------------- -int dpiHandleList__create(dpiHandleList **list, dpiError *error) -{ - dpiHandleList *tempList; - - if (dpiUtils__allocateMemory(1, sizeof(dpiHandleList), 0, - "allocate handle list", (void**) &tempList, error) < 0) - return DPI_FAILURE; - tempList->numSlots = 8; - tempList->numUsedSlots = 0; - if (dpiUtils__allocateMemory(tempList->numSlots, sizeof(void*), 1, - "allocate handle list slots", (void**) &tempList->handles, - error) < 0) { - dpiUtils__freeMemory(tempList); - return DPI_FAILURE; - } - dpiMutex__initialize(tempList->mutex); - tempList->currentPos = 0; - *list = tempList; - return DPI_SUCCESS; -} - -//----------------------------------------------------------------------------- -// dpiHandleList__free() [INTERNAL] -// Free the memory associated with the handle list. -//----------------------------------------------------------------------------- -void dpiHandleList__free(dpiHandleList *list) -{ - if (list->handles) { - dpiUtils__freeMemory(list->handles); - list->handles = NULL; - } - dpiMutex__destroy(list->mutex); - dpiUtils__freeMemory(list); -} - - -//----------------------------------------------------------------------------- -// dpiHandleList__removeHandle() [INTERNAL] -// Remove the handle at the specified location from the list. -//----------------------------------------------------------------------------- -void dpiHandleList__removeHandle(dpiHandleList *list, uint32_t slotNum) -{ - dpiMutex__acquire(list->mutex); - list->handles[slotNum] = NULL; - list->numUsedSlots--; - dpiMutex__release(list->mutex); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiHandlePool.c b/vendor/github.com/godror/godror/odpi/src/dpiHandlePool.c deleted file mode 100644 index 456f094f136..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiHandlePool.c +++ /dev/null @@ -1,119 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiHandlePool.c -// Implementation of a pool of handles which can be acquired and released in -// a thread-safe manner. The pool is a circular queue where handles are -// acquired from the front and released to the back. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiHandlePool__acquire() [INTERNAL] -// Acquire a handle from the pool. If a handle is available, it will be -// cleared out of the pool and returned to the caller. It is the caller's -// responsibility to return the handle back to the pool when it is finished -// with it. If no handle is available, a NULL value is returned. The caller is -// expected to create a new handle and return it to the pool when it is -// finished with it. -//----------------------------------------------------------------------------- -int dpiHandlePool__acquire(dpiHandlePool *pool, void **handle, dpiError *error) -{ - void **tempHandles; - uint32_t numSlots; - - dpiMutex__acquire(pool->mutex); - if (pool->acquirePos != pool->releasePos) { - *handle = pool->handles[pool->acquirePos]; - pool->handles[pool->acquirePos++] = NULL; - if (pool->acquirePos == pool->numSlots) - pool->acquirePos = 0; - } else { - *handle = NULL; - pool->numUsedSlots++; - if (pool->numUsedSlots > pool->numSlots) { - numSlots = pool->numSlots + 8; - if (dpiUtils__allocateMemory(numSlots, sizeof(void*), 1, - "allocate slots", (void**) &tempHandles, error) < 0) { - dpiMutex__release(pool->mutex); - return DPI_FAILURE; - } - memcpy(tempHandles, pool->handles, pool->numSlots * sizeof(void*)); - dpiUtils__freeMemory(pool->handles); - pool->handles = tempHandles; - pool->numSlots = numSlots; - } - } - dpiMutex__release(pool->mutex); - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiHandlePool__create() [INTERNAL] -// Create a new handle pool. -//----------------------------------------------------------------------------- -int dpiHandlePool__create(dpiHandlePool **pool, dpiError *error) -{ - dpiHandlePool *tempPool; - - if (dpiUtils__allocateMemory(1, sizeof(dpiHandlePool), 0, - "allocate handle pool", (void**) &tempPool, error) < 0) - return DPI_FAILURE; - tempPool->numSlots = 8; - tempPool->numUsedSlots = 0; - if (dpiUtils__allocateMemory(tempPool->numSlots, sizeof(void*), 1, - "allocate handle pool slots", (void**) &tempPool->handles, - error) < 0) { - dpiUtils__freeMemory(tempPool); - return DPI_FAILURE; - } - dpiMutex__initialize(tempPool->mutex); - tempPool->acquirePos = 0; - tempPool->releasePos = 0; - *pool = tempPool; - return DPI_SUCCESS; -} - -//----------------------------------------------------------------------------- -// dpiHandlePool__free() [INTERNAL] -// Free the memory associated with the error pool. -//----------------------------------------------------------------------------- -void dpiHandlePool__free(dpiHandlePool *pool) -{ - if (pool->handles) { - dpiUtils__freeMemory(pool->handles); - pool->handles = NULL; - } - dpiMutex__destroy(pool->mutex); - dpiUtils__freeMemory(pool); -} - - -//----------------------------------------------------------------------------- -// dpiHandlePool__release() [INTERNAL] -// Release a handle back to the pool. No checks are performed on the handle -// that is being returned to the pool; It will simply be placed back in the -// pool. The handle is then NULLed in order to avoid multiple attempts to -// release the handle back to the pool. -//----------------------------------------------------------------------------- -void dpiHandlePool__release(dpiHandlePool *pool, void **handle) -{ - dpiMutex__acquire(pool->mutex); - pool->handles[pool->releasePos++] = *handle; - *handle = NULL; - if (pool->releasePos == pool->numSlots) - pool->releasePos = 0; - dpiMutex__release(pool->mutex); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiImpl.h b/vendor/github.com/godror/godror/odpi/src/dpiImpl.h deleted file mode 100644 index ec2ede13955..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiImpl.h +++ /dev/null @@ -1,1905 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiImpl.h -// Master include file for implementation of ODPI-C library. The definitions -// in this file are subject to change without warning. Only the definitions in -// the file dpi.h are intended to be used publicly. -//----------------------------------------------------------------------------- - -#ifndef DPI_IMPL -#define DPI_IMPL - -// Visual Studio 2005 introduced deprecation warnings for "insecure" and POSIX -// functions; silence these warnings -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS 1 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include "dpi.h" - -#ifdef _WIN32 -#include -#ifndef isnan -#define isnan _isnan -#endif -#else -#include -#include -#include -#endif -#ifdef __linux -#include -#include -#endif - -#ifdef _MSC_VER -#if _MSC_VER < 1900 -#define PRId64 "I64d" -#define PRIu64 "I64u" -#define snprintf _snprintf -#endif -#endif - -#ifndef PRIu64 -#include -#endif - -#ifdef __GNUC__ -#define UNUSED __attribute((unused)) -#else -#define UNUSED -#endif - -// define debugging level (defined in dpiGlobal.c) -extern unsigned long dpiDebugLevel; - -// define max error size -#define DPI_MAX_ERROR_SIZE 3072 - -// define context name for ping interval -#define DPI_CONTEXT_LAST_TIME_USED "DPI_LAST_TIME_USED" - -// define size of buffer used for numbers transferred to/from Oracle as text -#define DPI_NUMBER_AS_TEXT_CHARS 172 - -// define maximum number of digits possible in an Oracle number -#define DPI_NUMBER_MAX_DIGITS 38 - -// define maximum size in bytes supported by basic string handling -#define DPI_MAX_BASIC_BUFFER_SIZE 32767 - -// define internal chunk size used for dynamic binding/fetching -#define DPI_DYNAMIC_BYTES_CHUNK_SIZE 65536 - -// define maximum buffer size permitted in variables -#define DPI_MAX_VAR_BUFFER_SIZE (1024 * 1024 * 1024 - 2) - -// define subscription grouping repeat count -#define DPI_SUBSCR_GROUPING_FOREVER -1 - -// define number of rows to prefetch -#define DPI_PREFETCH_ROWS_DEFAULT 2 - -// define well-known character sets -#define DPI_CHARSET_ID_ASCII 1 -#define DPI_CHARSET_ID_UTF8 873 -#define DPI_CHARSET_ID_UTF16 1000 -#define DPI_CHARSET_ID_UTF16BE 2000 -#define DPI_CHARSET_ID_UTF16LE 2002 -#define DPI_CHARSET_NAME_ASCII "ASCII" -#define DPI_CHARSET_NAME_UTF8 "UTF-8" -#define DPI_CHARSET_NAME_UTF16 "UTF-16" -#define DPI_CHARSET_NAME_UTF16BE "UTF-16BE" -#define DPI_CHARSET_NAME_UTF16LE "UTF-16LE" - -// define handle types used for allocating OCI handles -#define DPI_OCI_HTYPE_ENV 1 -#define DPI_OCI_HTYPE_ERROR 2 -#define DPI_OCI_HTYPE_SVCCTX 3 -#define DPI_OCI_HTYPE_STMT 4 -#define DPI_OCI_HTYPE_BIND 5 -#define DPI_OCI_HTYPE_DEFINE 6 -#define DPI_OCI_HTYPE_DESCRIBE 7 -#define DPI_OCI_HTYPE_SERVER 8 -#define DPI_OCI_HTYPE_SESSION 9 -#define DPI_OCI_HTYPE_AUTHINFO 9 -#define DPI_OCI_HTYPE_TRANS 10 -#define DPI_OCI_HTYPE_SUBSCRIPTION 13 -#define DPI_OCI_HTYPE_SPOOL 27 -#define DPI_OCI_HTYPE_SODA_COLLECTION 30 -#define DPI_OCI_HTYPE_SODA_DOCUMENT 31 -#define DPI_OCI_HTYPE_SODA_COLL_CURSOR 32 -#define DPI_OCI_HTYPE_SODA_OPER_OPTIONS 33 -#define DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS 34 -#define DPI_OCI_HTYPE_SODA_DOC_CURSOR 36 - -// define OCI descriptor types -#define DPI_OCI_DTYPE_LOB 50 -#define DPI_OCI_DTYPE_PARAM 53 -#define DPI_OCI_DTYPE_ROWID 54 -#define DPI_OCI_DTYPE_AQENQ_OPTIONS 57 -#define DPI_OCI_DTYPE_AQDEQ_OPTIONS 58 -#define DPI_OCI_DTYPE_AQMSG_PROPERTIES 59 -#define DPI_OCI_DTYPE_INTERVAL_YM 62 -#define DPI_OCI_DTYPE_INTERVAL_DS 63 -#define DPI_OCI_DTYPE_AQNFY_DESCRIPTOR 64 -#define DPI_OCI_DTYPE_TIMESTAMP 68 -#define DPI_OCI_DTYPE_TIMESTAMP_TZ 69 -#define DPI_OCI_DTYPE_TIMESTAMP_LTZ 70 -#define DPI_OCI_DTYPE_CHDES 77 -#define DPI_OCI_DTYPE_TABLE_CHDES 78 -#define DPI_OCI_DTYPE_ROW_CHDES 79 -#define DPI_OCI_DTYPE_CQDES 80 -#define DPI_OCI_DTYPE_SHARDING_KEY 83 - -// define values used for getting/setting OCI attributes -#define DPI_OCI_ATTR_DATA_SIZE 1 -#define DPI_OCI_ATTR_DATA_TYPE 2 -#define DPI_OCI_ATTR_ENV 5 -#define DPI_OCI_ATTR_PRECISION 5 -#define DPI_OCI_ATTR_SCALE 6 -#define DPI_OCI_ATTR_NAME 4 -#define DPI_OCI_ATTR_SERVER 6 -#define DPI_OCI_ATTR_SESSION 7 -#define DPI_OCI_ATTR_IS_NULL 7 -#define DPI_OCI_ATTR_TRANS 8 -#define DPI_OCI_ATTR_TYPE_NAME 8 -#define DPI_OCI_ATTR_SCHEMA_NAME 9 -#define DPI_OCI_ATTR_ROW_COUNT 9 -#define DPI_OCI_ATTR_PREFETCH_ROWS 11 -#define DPI_OCI_ATTR_PARAM_COUNT 18 -#define DPI_OCI_ATTR_ROWID 19 -#define DPI_OCI_ATTR_USERNAME 22 -#define DPI_OCI_ATTR_PASSWORD 23 -#define DPI_OCI_ATTR_STMT_TYPE 24 -#define DPI_OCI_ATTR_INTERNAL_NAME 25 -#define DPI_OCI_ATTR_EXTERNAL_NAME 26 -#define DPI_OCI_ATTR_XID 27 -#define DPI_OCI_ATTR_CHARSET_ID 31 -#define DPI_OCI_ATTR_CHARSET_FORM 32 -#define DPI_OCI_ATTR_MAXDATA_SIZE 33 -#define DPI_OCI_ATTR_ROWS_RETURNED 42 -#define DPI_OCI_ATTR_VISIBILITY 47 -#define DPI_OCI_ATTR_CONSUMER_NAME 50 -#define DPI_OCI_ATTR_DEQ_MODE 51 -#define DPI_OCI_ATTR_NAVIGATION 52 -#define DPI_OCI_ATTR_WAIT 53 -#define DPI_OCI_ATTR_DEQ_MSGID 54 -#define DPI_OCI_ATTR_PRIORITY 55 -#define DPI_OCI_ATTR_DELAY 56 -#define DPI_OCI_ATTR_EXPIRATION 57 -#define DPI_OCI_ATTR_CORRELATION 58 -#define DPI_OCI_ATTR_ATTEMPTS 59 -#define DPI_OCI_ATTR_EXCEPTION_QUEUE 61 -#define DPI_OCI_ATTR_ENQ_TIME 62 -#define DPI_OCI_ATTR_MSG_STATE 63 -#define DPI_OCI_ATTR_ORIGINAL_MSGID 69 -#define DPI_OCI_ATTR_QUEUE_NAME 70 -#define DPI_OCI_ATTR_NUM_DML_ERRORS 73 -#define DPI_OCI_ATTR_DML_ROW_OFFSET 74 -#define DPI_OCI_ATTR_SUBSCR_NAME 94 -#define DPI_OCI_ATTR_SUBSCR_CALLBACK 95 -#define DPI_OCI_ATTR_SUBSCR_CTX 96 -#define DPI_OCI_ATTR_SUBSCR_NAMESPACE 98 -#define DPI_OCI_ATTR_REF_TDO 110 -#define DPI_OCI_ATTR_PARAM 124 -#define DPI_OCI_ATTR_PARSE_ERROR_OFFSET 129 -#define DPI_OCI_ATTR_SERVER_STATUS 143 -#define DPI_OCI_ATTR_STATEMENT 144 -#define DPI_OCI_ATTR_DEQCOND 146 -#define DPI_OCI_ATTR_SUBSCR_RECPTPROTO 149 -#define DPI_OCI_ATTR_CURRENT_POSITION 164 -#define DPI_OCI_ATTR_STMTCACHESIZE 176 -#define DPI_OCI_ATTR_BIND_COUNT 190 -#define DPI_OCI_ATTR_TRANSFORMATION 196 -#define DPI_OCI_ATTR_ROWS_FETCHED 197 -#define DPI_OCI_ATTR_SPOOL_STMTCACHESIZE 208 -#define DPI_OCI_ATTR_TYPECODE 216 -#define DPI_OCI_ATTR_STMT_IS_RETURNING 218 -#define DPI_OCI_ATTR_CURRENT_SCHEMA 224 -#define DPI_OCI_ATTR_SUBSCR_QOSFLAGS 225 -#define DPI_OCI_ATTR_COLLECTION_ELEMENT 227 -#define DPI_OCI_ATTR_SUBSCR_TIMEOUT 227 -#define DPI_OCI_ATTR_NUM_TYPE_ATTRS 228 -#define DPI_OCI_ATTR_SUBSCR_CQ_QOSFLAGS 229 -#define DPI_OCI_ATTR_LIST_TYPE_ATTRS 229 -#define DPI_OCI_ATTR_SUBSCR_CQ_REGID 230 -#define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_CLASS 231 -#define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_VALUE 232 -#define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_TYPE 233 -#define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_REPEAT_COUNT 235 -#define DPI_OCI_ATTR_NCHARSET_ID 262 -#define DPI_OCI_ATTR_APPCTX_SIZE 273 -#define DPI_OCI_ATTR_APPCTX_LIST 274 -#define DPI_OCI_ATTR_APPCTX_NAME 275 -#define DPI_OCI_ATTR_APPCTX_ATTR 276 -#define DPI_OCI_ATTR_APPCTX_VALUE 277 -#define DPI_OCI_ATTR_CLIENT_IDENTIFIER 278 -#define DPI_OCI_ATTR_CHAR_SIZE 286 -#define DPI_OCI_ATTR_EDITION 288 -#define DPI_OCI_ATTR_CQ_QUERYID 304 -#define DPI_OCI_ATTR_SPOOL_TIMEOUT 308 -#define DPI_OCI_ATTR_SPOOL_GETMODE 309 -#define DPI_OCI_ATTR_SPOOL_BUSY_COUNT 310 -#define DPI_OCI_ATTR_SPOOL_OPEN_COUNT 311 -#define DPI_OCI_ATTR_MODULE 366 -#define DPI_OCI_ATTR_ACTION 367 -#define DPI_OCI_ATTR_CLIENT_INFO 368 -#define DPI_OCI_ATTR_SUBSCR_PORTNO 390 -#define DPI_OCI_ATTR_CHNF_ROWIDS 402 -#define DPI_OCI_ATTR_CHNF_OPERATIONS 403 -#define DPI_OCI_ATTR_CHDES_DBNAME 405 -#define DPI_OCI_ATTR_CHDES_NFYTYPE 406 -#define DPI_OCI_ATTR_NFY_FLAGS 406 -#define DPI_OCI_ATTR_CHDES_XID 407 -#define DPI_OCI_ATTR_MSG_DELIVERY_MODE 407 -#define DPI_OCI_ATTR_CHDES_TABLE_CHANGES 408 -#define DPI_OCI_ATTR_CHDES_TABLE_NAME 409 -#define DPI_OCI_ATTR_CHDES_TABLE_OPFLAGS 410 -#define DPI_OCI_ATTR_CHDES_TABLE_ROW_CHANGES 411 -#define DPI_OCI_ATTR_CHDES_ROW_ROWID 412 -#define DPI_OCI_ATTR_CHDES_ROW_OPFLAGS 413 -#define DPI_OCI_ATTR_CHNF_REGHANDLE 414 -#define DPI_OCI_ATTR_CQDES_OPERATION 422 -#define DPI_OCI_ATTR_CQDES_TABLE_CHANGES 423 -#define DPI_OCI_ATTR_CQDES_QUERYID 424 -#define DPI_OCI_ATTR_DRIVER_NAME 424 -#define DPI_OCI_ATTR_CHDES_QUERIES 425 -#define DPI_OCI_ATTR_CONNECTION_CLASS 425 -#define DPI_OCI_ATTR_PURITY 426 -#define DPI_OCI_ATTR_RECEIVE_TIMEOUT 436 -#define DPI_OCI_ATTR_LOBPREFETCH_LENGTH 440 -#define DPI_OCI_ATTR_SUBSCR_IPADDR 452 -#define DPI_OCI_ATTR_UB8_ROW_COUNT 457 -#define DPI_OCI_ATTR_SPOOL_AUTH 460 -#define DPI_OCI_ATTR_LTXID 462 -#define DPI_OCI_ATTR_DML_ROW_COUNT_ARRAY 469 -#define DPI_OCI_ATTR_ERROR_IS_RECOVERABLE 472 -#define DPI_OCI_ATTR_TRANSACTION_IN_PROGRESS 484 -#define DPI_OCI_ATTR_DBOP 485 -#define DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION 490 -#define DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT 495 -#define DPI_OCI_ATTR_SHARDING_KEY 496 -#define DPI_OCI_ATTR_SUPER_SHARDING_KEY 497 -#define DPI_OCI_ATTR_FIXUP_CALLBACK 501 -#define DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT 506 -#define DPI_OCI_ATTR_CALL_TIMEOUT 531 -#define DPI_OCI_ATTR_SODA_COLL_NAME 535 -#define DPI_OCI_ATTR_SODA_COLL_DESCRIPTOR 536 -#define DPI_OCI_ATTR_SODA_CTNT_SQL_TYPE 549 -#define DPI_OCI_ATTR_SODA_KEY 563 -#define DPI_OCI_ATTR_SODA_LASTMOD_TIMESTAMP 564 -#define DPI_OCI_ATTR_SODA_CREATE_TIMESTAMP 565 -#define DPI_OCI_ATTR_SODA_VERSION 566 -#define DPI_OCI_ATTR_SODA_CONTENT 567 -#define DPI_OCI_ATTR_SODA_JSON_CHARSET_ID 568 -#define DPI_OCI_ATTR_SODA_DETECT_JSON_ENC 569 -#define DPI_OCI_ATTR_SODA_MEDIA_TYPE 571 -#define DPI_OCI_ATTR_SODA_CTNT_FORMAT 572 -#define DPI_OCI_ATTR_SODA_FILTER 576 -#define DPI_OCI_ATTR_SODA_SKIP 577 -#define DPI_OCI_ATTR_SODA_LIMIT 578 -#define DPI_OCI_ATTR_SODA_DOC_COUNT 593 -#define DPI_OCI_ATTR_SPOOL_MAX_PER_SHARD 602 - -// define OCI object type constants -#define DPI_OCI_OTYPE_NAME 1 -#define DPI_OCI_OTYPE_PTR 3 - -// define OCI data type constants -#define DPI_SQLT_CHR 1 -#define DPI_SQLT_NUM 2 -#define DPI_SQLT_INT 3 -#define DPI_SQLT_FLT 4 -#define DPI_SQLT_VNU 6 -#define DPI_SQLT_PDN 7 -#define DPI_SQLT_LNG 8 -#define DPI_SQLT_VCS 9 -#define DPI_SQLT_DAT 12 -#define DPI_SQLT_BFLOAT 21 -#define DPI_SQLT_BDOUBLE 22 -#define DPI_SQLT_BIN 23 -#define DPI_SQLT_LBI 24 -#define DPI_SQLT_UIN 68 -#define DPI_SQLT_LVB 95 -#define DPI_SQLT_AFC 96 -#define DPI_SQLT_IBFLOAT 100 -#define DPI_SQLT_IBDOUBLE 101 -#define DPI_SQLT_RDD 104 -#define DPI_SQLT_NTY 108 -#define DPI_SQLT_CLOB 112 -#define DPI_SQLT_BLOB 113 -#define DPI_SQLT_BFILE 114 -#define DPI_SQLT_RSET 116 -#define DPI_SQLT_NCO 122 -#define DPI_SQLT_ODT 156 -#define DPI_SQLT_DATE 184 -#define DPI_SQLT_TIMESTAMP 187 -#define DPI_SQLT_TIMESTAMP_TZ 188 -#define DPI_SQLT_INTERVAL_YM 189 -#define DPI_SQLT_INTERVAL_DS 190 -#define DPI_SQLT_TIMESTAMP_LTZ 232 -#define DPI_OCI_TYPECODE_SMALLINT 246 -#define DPI_SQLT_REC 250 -#define DPI_SQLT_BOL 252 -#define DPI_OCI_TYPECODE_ROWID 262 -#define DPI_OCI_TYPECODE_LONG 263 -#define DPI_OCI_TYPECODE_LONG_RAW 264 -#define DPI_OCI_TYPECODE_BINARY_INTEGER 265 -#define DPI_OCI_TYPECODE_PLS_INTEGER 266 - -// define session pool constants -#define DPI_OCI_SPD_FORCE 0x0001 -#define DPI_OCI_SPC_HOMOGENEOUS 0x0002 -#define DPI_OCI_SPC_STMTCACHE 0x0004 - -// define OCI session pool get constants -#define DPI_OCI_SESSGET_SPOOL 0x0001 -#define DPI_OCI_SESSGET_STMTCACHE 0x0004 -#define DPI_OCI_SESSGET_CREDPROXY 0x0008 -#define DPI_OCI_SESSGET_CREDEXT 0x0010 -#define DPI_OCI_SESSGET_SPOOL_MATCHANY 0x0020 -#define DPI_OCI_SESSGET_SYSDBA 0x0100 -#define DPI_OCI_SESSGET_MULTIPROPERTY_TAG 0x0400 - -// define OCI authentication constants -#define DPI_OCI_CPW_SYSDBA 0x00000010 -#define DPI_OCI_CPW_SYSOPER 0x00000020 -#define DPI_OCI_CPW_SYSASM 0x00800040 -#define DPI_OCI_CPW_SYSBKP 0x00000080 -#define DPI_OCI_CPW_SYSDGD 0x00000100 -#define DPI_OCI_CPW_SYSKMT 0x00000200 - -// define NLS constants -#define DPI_OCI_NLS_CS_IANA_TO_ORA 0 -#define DPI_OCI_NLS_CS_ORA_TO_IANA 1 -#define DPI_OCI_NLS_CHARSET_MAXBYTESZ 91 -#define DPI_OCI_NLS_CHARSET_ID 93 -#define DPI_OCI_NLS_NCHARSET_ID 94 -#define DPI_OCI_NLS_MAXBUFSZ 100 -#define DPI_SQLCS_IMPLICIT 1 -#define DPI_SQLCS_NCHAR 2 - -// define XA constants -#define DPI_XA_MAXGTRIDSIZE 64 -#define DPI_XA_MAXBQUALSIZE 64 -#define DPI_XA_XIDDATASIZE 128 - -// define null indicator values -#define DPI_OCI_IND_NULL -1 -#define DPI_OCI_IND_NOTNULL 0 - -// define subscription QOS values -#define DPI_OCI_SUBSCR_QOS_RELIABLE 0x01 -#define DPI_OCI_SUBSCR_QOS_PURGE_ON_NTFN 0x10 -#define DPI_OCI_SUBSCR_CQ_QOS_QUERY 0x01 -#define DPI_OCI_SUBSCR_CQ_QOS_BEST_EFFORT 0x02 - -// define miscellaneous OCI constants -#define DPI_OCI_CONTINUE -24200 -#define DPI_OCI_INVALID_HANDLE -2 -#define DPI_OCI_ERROR -1 -#define DPI_OCI_DEFAULT 0 -#define DPI_OCI_SUCCESS 0 -#define DPI_OCI_ONE_PIECE 0 -#define DPI_OCI_ATTR_PURITY_DEFAULT 0 -#define DPI_OCI_NUMBER_UNSIGNED 0 -#define DPI_OCI_SUCCESS_WITH_INFO 1 -#define DPI_OCI_NTV_SYNTAX 1 -#define DPI_OCI_MEMORY_CLEARED 1 -#define DPI_OCI_SESSRLS_DROPSESS 1 -#define DPI_OCI_SESSRLS_MULTIPROPERTY_TAG 4 -#define DPI_OCI_SERVER_NORMAL 1 -#define DPI_OCI_TYPEGET_ALL 1 -#define DPI_OCI_TRANS_NEW 1 -#define DPI_OCI_LOCK_NONE 1 -#define DPI_OCI_TEMP_BLOB 1 -#define DPI_OCI_CRED_RDBMS 1 -#define DPI_OCI_LOB_READONLY 1 -#define DPI_OCI_JSON_FORMAT_OSON 1 -#define DPI_OCI_TEMP_CLOB 2 -#define DPI_OCI_CRED_EXT 2 -#define DPI_OCI_LOB_READWRITE 2 -#define DPI_OCI_DATA_AT_EXEC 2 -#define DPI_OCI_DYNAMIC_FETCH 2 -#define DPI_OCI_NUMBER_SIGNED 2 -#define DPI_OCI_PIN_ANY 3 -#define DPI_OCI_PTYPE_TYPE 6 -#define DPI_OCI_AUTH 8 -#define DPI_OCI_DURATION_SESSION 10 -#define DPI_OCI_NUMBER_SIZE 22 -#define DPI_OCI_NO_DATA 100 -#define DPI_OCI_STRLS_CACHE_DELETE 0x0010 -#define DPI_OCI_THREADED 0x00000001 -#define DPI_OCI_OBJECT 0x00000002 -#define DPI_OCI_SODA_ATOMIC_COMMIT 0x00000001 -#define DPI_OCI_SODA_AS_STORED 0x00000002 -#define DPI_OCI_SODA_AS_AL32UTF8 0x00000004 -#define DPI_OCI_STMT_SCROLLABLE_READONLY 0x00000008 -#define DPI_OCI_STMT_CACHE 0x00000040 -#define DPI_OCI_SODA_COLL_CREATE_MAP 0x00010000 -#define DPI_OCI_SODA_INDEX_DROP_FORCE 0x00010000 -#define DPI_OCI_TRANS_TWOPHASE 0x01000000 -#define DPI_OCI_SECURE_NOTIFICATION 0x20000000 - -//----------------------------------------------------------------------------- -// Macros -//----------------------------------------------------------------------------- -#define DPI_CHECK_PTR_NOT_NULL(handle, parameter) \ - if (!parameter) { \ - dpiError__set(&error, "check parameter " #parameter, \ - DPI_ERR_NULL_POINTER_PARAMETER, #parameter); \ - return dpiGen__endPublicFn(handle, DPI_FAILURE, &error); \ - } - -#define DPI_CHECK_PTR_AND_LENGTH(handle, parameter) \ - if (!parameter && parameter ## Length > 0) { \ - dpiError__set(&error, "check parameter " #parameter, \ - DPI_ERR_PTR_LENGTH_MISMATCH, #parameter); \ - return dpiGen__endPublicFn(handle, DPI_FAILURE, &error); \ - } - - -//----------------------------------------------------------------------------- -// Enumerations -//----------------------------------------------------------------------------- - -// error numbers -typedef enum { - DPI_ERR_NO_ERR = 1000, - DPI_ERR_NO_MEMORY, - DPI_ERR_INVALID_HANDLE, - DPI_ERR_ERR_NOT_INITIALIZED, - DPI_ERR_GET_FAILED, - DPI_ERR_CREATE_ENV, - DPI_ERR_CONVERT_TEXT, - DPI_ERR_QUERY_NOT_EXECUTED, - DPI_ERR_UNHANDLED_DATA_TYPE, - DPI_ERR_INVALID_ARRAY_POSITION, - DPI_ERR_NOT_CONNECTED, - DPI_ERR_CONN_NOT_IN_POOL, - DPI_ERR_INVALID_PROXY, - DPI_ERR_NOT_SUPPORTED, - DPI_ERR_UNHANDLED_CONVERSION, - DPI_ERR_ARRAY_SIZE_TOO_BIG, - DPI_ERR_INVALID_DATE, - DPI_ERR_VALUE_IS_NULL, - DPI_ERR_ARRAY_SIZE_TOO_SMALL, - DPI_ERR_BUFFER_SIZE_TOO_SMALL, - DPI_ERR_VERSION_NOT_SUPPORTED, - DPI_ERR_INVALID_ORACLE_TYPE, - DPI_ERR_WRONG_ATTR, - DPI_ERR_NOT_COLLECTION, - DPI_ERR_INVALID_INDEX, - DPI_ERR_NO_OBJECT_TYPE, - DPI_ERR_INVALID_CHARSET, - DPI_ERR_SCROLL_OUT_OF_RS, - DPI_ERR_QUERY_POSITION_INVALID, - DPI_ERR_NO_ROW_FETCHED, - DPI_ERR_TLS_ERROR, - DPI_ERR_ARRAY_SIZE_ZERO, - DPI_ERR_EXT_AUTH_WITH_CREDENTIALS, - DPI_ERR_CANNOT_GET_ROW_OFFSET, - DPI_ERR_CONN_IS_EXTERNAL, - DPI_ERR_TRANS_ID_TOO_LARGE, - DPI_ERR_BRANCH_ID_TOO_LARGE, - DPI_ERR_COLUMN_FETCH, - DPI_ERR_STMT_CLOSED, - DPI_ERR_LOB_CLOSED, - DPI_ERR_INVALID_CHARSET_ID, - DPI_ERR_INVALID_OCI_NUMBER, - DPI_ERR_INVALID_NUMBER, - DPI_ERR_NUMBER_NO_REPR, - DPI_ERR_NUMBER_STRING_TOO_LONG, - DPI_ERR_NULL_POINTER_PARAMETER, - DPI_ERR_LOAD_LIBRARY, - DPI_ERR_LOAD_SYMBOL, - DPI_ERR_ORACLE_CLIENT_TOO_OLD, - DPI_ERR_NLS_ENV_VAR_GET, - DPI_ERR_PTR_LENGTH_MISMATCH, - DPI_ERR_NAN, - DPI_ERR_WRONG_TYPE, - DPI_ERR_BUFFER_SIZE_TOO_LARGE, - DPI_ERR_NO_EDITION_WITH_CONN_CLASS, - DPI_ERR_NO_BIND_VARS_IN_DDL, - DPI_ERR_SUBSCR_CLOSED, - DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD, - DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE, - DPI_ERR_EXEC_MODE_ONLY_FOR_DML, - DPI_ERR_ARRAY_VAR_NOT_SUPPORTED, - DPI_ERR_EVENTS_MODE_REQUIRED, - DPI_ERR_ORACLE_DB_TOO_OLD, - DPI_ERR_CALL_TIMEOUT, - DPI_ERR_SODA_CURSOR_CLOSED, - DPI_ERR_EXT_AUTH_INVALID_PROXY, - DPI_ERR_QUEUE_NO_PAYLOAD, - DPI_ERR_QUEUE_WRONG_PAYLOAD_TYPE, - DPI_ERR_ORACLE_CLIENT_UNSUPPORTED, - DPI_ERR_MISSING_SHARDING_KEY, - DPI_ERR_MAX -} dpiErrorNum; - -// handle types -typedef enum { - DPI_HTYPE_NONE = 4000, - DPI_HTYPE_CONN, - DPI_HTYPE_POOL, - DPI_HTYPE_STMT, - DPI_HTYPE_VAR, - DPI_HTYPE_LOB, - DPI_HTYPE_OBJECT, - DPI_HTYPE_OBJECT_TYPE, - DPI_HTYPE_OBJECT_ATTR, - DPI_HTYPE_SUBSCR, - DPI_HTYPE_DEQ_OPTIONS, - DPI_HTYPE_ENQ_OPTIONS, - DPI_HTYPE_MSG_PROPS, - DPI_HTYPE_ROWID, - DPI_HTYPE_CONTEXT, - DPI_HTYPE_SODA_COLL, - DPI_HTYPE_SODA_COLL_CURSOR, - DPI_HTYPE_SODA_DB, - DPI_HTYPE_SODA_DOC, - DPI_HTYPE_SODA_DOC_CURSOR, - DPI_HTYPE_QUEUE, - DPI_HTYPE_MAX -} dpiHandleTypeNum; - - -//----------------------------------------------------------------------------- -// Mutex definitions -//----------------------------------------------------------------------------- -#ifdef _WIN32 - typedef CRITICAL_SECTION dpiMutexType; - #define dpiMutex__initialize(m) InitializeCriticalSection(&m) - #define dpiMutex__destroy(m) DeleteCriticalSection(&m) - #define dpiMutex__acquire(m) EnterCriticalSection(&m) - #define dpiMutex__release(m) LeaveCriticalSection(&m) -#else - typedef pthread_mutex_t dpiMutexType; - #define dpiMutex__initialize(m) pthread_mutex_init(&m, NULL) - #define dpiMutex__destroy(m) pthread_mutex_destroy(&m) - #define dpiMutex__acquire(m) pthread_mutex_lock(&m) - #define dpiMutex__release(m) pthread_mutex_unlock(&m) -#endif - - -//----------------------------------------------------------------------------- -// old type definitions (to be dropped) -//----------------------------------------------------------------------------- - -// structure used for creating pools (3.0) -typedef struct { - uint32_t minSessions; - uint32_t maxSessions; - uint32_t sessionIncrement; - int pingInterval; - int pingTimeout; - int homogeneous; - int externalAuth; - dpiPoolGetMode getMode; - const char *outPoolName; - uint32_t outPoolNameLength; - uint32_t timeout; - uint32_t waitTimeout; - uint32_t maxLifetimeSession; -} dpiPoolCreateParams__v30; - -// structure used for creating pools (3.2) -typedef struct { - uint32_t minSessions; - uint32_t maxSessions; - uint32_t sessionIncrement; - int pingInterval; - int pingTimeout; - int homogeneous; - int externalAuth; - dpiPoolGetMode getMode; - const char *outPoolName; - uint32_t outPoolNameLength; - uint32_t timeout; - uint32_t waitTimeout; - uint32_t maxLifetimeSession; - const char *plsqlFixupCallback; - uint32_t plsqlFixupCallbackLength; -} dpiPoolCreateParams__v32; - -// structure used for creating connections (3.0) -typedef struct { - dpiAuthMode authMode; - const char *connectionClass; - uint32_t connectionClassLength; - dpiPurity purity; - const char *newPassword; - uint32_t newPasswordLength; - dpiAppContext *appContext; - uint32_t numAppContext; - int externalAuth; - void *externalHandle; - dpiPool *pool; - const char *tag; - uint32_t tagLength; - int matchAnyTag; - const char *outTag; - uint32_t outTagLength; - int outTagFound; - dpiShardingKeyColumn *shardingKeyColumns; - uint8_t numShardingKeyColumns; - dpiShardingKeyColumn *superShardingKeyColumns; - uint8_t numSuperShardingKeyColumns; -} dpiConnCreateParams__v30; - -// structure used for creating subscriptions (3.0 and 3.1) -typedef struct { - dpiSubscrNamespace subscrNamespace; - dpiSubscrProtocol protocol; - dpiSubscrQOS qos; - dpiOpCode operations; - uint32_t portNumber; - uint32_t timeout; - const char *name; - uint32_t nameLength; - dpiSubscrCallback callback; - void *callbackContext; - const char *recipientName; - uint32_t recipientNameLength; - const char *ipAddress; - uint32_t ipAddressLength; - uint8_t groupingClass; - uint32_t groupingValue; - uint8_t groupingType; -} dpiSubscrCreateParams__v30; - -// structure used for creating subscriptions (3.2) -typedef struct { - dpiSubscrNamespace subscrNamespace; - dpiSubscrProtocol protocol; - dpiSubscrQOS qos; - dpiOpCode operations; - uint32_t portNumber; - uint32_t timeout; - const char *name; - uint32_t nameLength; - dpiSubscrCallback callback; - void *callbackContext; - const char *recipientName; - uint32_t recipientNameLength; - const char *ipAddress; - uint32_t ipAddressLength; - uint8_t groupingClass; - uint32_t groupingValue; - uint8_t groupingType; - uint64_t outRegId; -} dpiSubscrCreateParams__v32; - - -//----------------------------------------------------------------------------- -// OCI type definitions -//----------------------------------------------------------------------------- - -// representation of OCI Number type -typedef struct { - unsigned char value[DPI_OCI_NUMBER_SIZE]; -} dpiOciNumber; - -// representation of OCI Date type -typedef struct { - int16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; -} dpiOciDate; - -// alternative representation of OCI Date type used for sharding -typedef struct { - uint8_t century; - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; -} dpiShardingOciDate; - -// representation of OCI XID type (two-phase commit) -typedef struct { - long formatID; - long gtrid_length; - long bqual_length; - char data[DPI_XA_XIDDATASIZE]; -} dpiOciXID; - - -//----------------------------------------------------------------------------- -// Internal implementation type definitions -//----------------------------------------------------------------------------- - -// used to manage a list of shared handles in a thread-safe manner; currently -// used for managing the list of open statements, LOBs and created objects for -// a connection (so that they can be closed before the connection itself is -// closed); the functions for managing this structure can be found in the file -// dpiHandleList.c; empty slots in the array are represented by a NULL handle -typedef struct { - void **handles; // array of handles managed by list - uint32_t numSlots; // length of handles array - uint32_t numUsedSlots; // actual number of managed handles - uint32_t currentPos; // next position to search - dpiMutexType mutex; // enables thread safety -} dpiHandleList; - -// used to manage a pool of shared handles in a thread-safe manner; currently -// used for managing the pool of error handles in the dpiEnv structure; the -// functions for managing this structure are found in the file dpiHandlePool.c -typedef struct { - void **handles; // array of handles managed by pool - uint32_t numSlots; // length of handles array - uint32_t numUsedSlots; // actual number of managed handles - uint32_t acquirePos; // position from which to acquire - uint32_t releasePos; // position to place released handles - dpiMutexType mutex; // enables thread safety -} dpiHandlePool; - -// used to save error information internally; one of these is stored for each -// thread using OCIThreadKeyGet() and OCIThreadKeySet() with a globally created -// OCI environment handle; it is also used when getting batch error information -// with the function dpiStmt_getBatchErrors() -typedef struct { - int32_t code; // Oracle error code or 0 - uint16_t offset; // parse error offset or row offset - dpiErrorNum errorNum; // OCPI-C error number - const char *fnName; // ODPI-C function name - const char *action; // internal action - char encoding[DPI_OCI_NLS_MAXBUFSZ]; // encoding (IANA name) - char message[DPI_MAX_ERROR_SIZE]; // buffer for storing messages - uint32_t messageLength; // length of message in buffer - int isRecoverable; // is recoverable? -} dpiErrorBuffer; - -// represents an OCI environment; a pointer to this structure is stored on each -// handle exposed publicly but it is created only when a pool is created or -// when a standalone connection is created; connections acquired from a pool -// shared the same environment as the pool; the functions for manipulating the -// environment are found in the file dpiEnv.c; all values are read-only after -// initialization of environment is complete -typedef struct { - const dpiContext *context; // context used to create environment - void *handle; // OCI environment handle - dpiMutexType mutex; // for reference count (threaded mode) - char encoding[DPI_OCI_NLS_MAXBUFSZ]; // CHAR encoding (IANA name) - int32_t maxBytesPerCharacter; // max bytes per CHAR character - uint16_t charsetId; // CHAR encoding (Oracle charset ID) - char nencoding[DPI_OCI_NLS_MAXBUFSZ]; // NCHAR encoding (IANA name) - int32_t nmaxBytesPerCharacter; // max bytes per NCHAR character - uint16_t ncharsetId; // NCHAR encoding (Oracle charset ID) - dpiHandlePool *errorHandles; // pool of OCI error handles - dpiVersionInfo *versionInfo; // OCI client version info - void *baseDate; // midnight, January 1, 1970 - int threaded; // threaded mode enabled? - int events; // events mode enabled? - int externalHandle; // external handle? -} dpiEnv; - -// used to manage all errors that take place in the library; the implementation -// for the functions that use this structure are found in dpiError.c; a pointer -// to this structure is passed to all internal functions and the first thing -// that takes place in every public function is a call to this this error -// structure -typedef struct { - dpiErrorBuffer *buffer; // buffer to store error information - void *handle; // OCI error handle or NULL - dpiEnv *env; // env which created OCI error handle -} dpiError; - -// function signature for all methods that free publicly exposed handles -typedef void (*dpiTypeFreeProc)(void*, dpiError*); - -// strcture used to provide metadata for the different types of handles exposed -// publicly; a list of these structures (defined as constants) can be found in -// the file dpiGen.c; the enumeration dpiHandleTypeNum is used to identify the -// structures instead of being used directly -typedef struct { - const char *name; // name (used in error messages) - size_t size; // size of structure, in bytes - uint32_t checkInt; // check integer (unique) - dpiTypeFreeProc freeProc; // procedure to call to free handle -} dpiTypeDef; - -// all structures exposed publicly by handle have these members -#define dpiType_HEAD \ - const dpiTypeDef *typeDef; \ - uint32_t checkInt; \ - unsigned refCount; \ - dpiEnv *env; - -// contains the base attributes that all handles exposed publicly have; generic -// functions for checking and manipulating handles are found in the file -// dpiGen.c; the check integer is used to verify the validity of the handle and -// is reset to zero when the handle is freed; the reference count is used to -// manage how many references (either publicly or internally) are held; when -// the reference count reaches zero the handle is freed -typedef struct { - dpiType_HEAD -} dpiBaseType; - -// represents the different types of Oracle data that the library supports; an -// array of these structures (defined as constants) can be found in the file -// dpiOracleType.c; the enumeration dpiOracleTypeNum is used to identify the -// structures -typedef struct dpiOracleType { - dpiOracleTypeNum oracleTypeNum; // enumeration value identifying type - dpiNativeTypeNum defaultNativeTypeNum; // default native (C) type - uint16_t oracleType; // OCI type code - uint8_t charsetForm; // specifies CHAR or NCHAR encoding - uint32_t sizeInBytes; // buffer size (fixed) or 0 (variable) - int isCharacterData; // is type character data? - int canBeInArray; // can type be in an index-by table? - int requiresPreFetch; // prefetch processing required? -} dpiOracleType; - -// represents a chunk of data that has been allocated dynamically for use in -// dynamic fetching of LONG or LONG RAW columns, or when the calling -// application wishes to use strings or raw byte strings instead of LOBs; an -// array of these chunks is found in the structure dpiDynamicBytes -typedef struct { - char *ptr; // pointer to buffer - uint32_t length; // actual length of buffer - uint32_t allocatedLength; // allocated length of buffer -} dpiDynamicBytesChunk; - -// represents a set of chunks allocated dynamically for use in dynamic fetching -// of LONG or LONG RAW columns, or when the calling application wishes to use -// strings or raw byte strings instead of LOBS -typedef struct { - uint32_t numChunks; // actual number of chunks - uint32_t allocatedChunks; // allocated number of chunks - dpiDynamicBytesChunk *chunks; // array of chunks -} dpiDynamicBytes; - -// represents a single bound variable; an array of these is retained in the -// dpiStmt structure in order to retain references to the variables that were -// bound to the statement, which ensures that the values remain valid while the -// statement is executed; the position is populated for bind by position -// (otherwise it is 0) and the name/nameLength are populated for bind by name -// (otherwise they are NULL/0) -typedef struct { - dpiVar *var; - uint32_t pos; - const char *name; - uint32_t nameLength; -} dpiBindVar; - -// intended to avoid the need for casts; contains references to LOBs, objects -// and statements (as part of dpiVar) -typedef union { - void *asHandle; - dpiObject *asObject; - dpiStmt *asStmt; - dpiLob *asLOB; - dpiRowid *asRowid; -} dpiReferenceBuffer; - -// intended to avoid the need for casts; contains the actual values that are -// bound or fetched (as part of dpiVar); it is also used for getting data into -// and out of Oracle object instances -typedef union { - void *asRaw; - char *asBytes; - float *asFloat; - double *asDouble; - int32_t *asInt32; - int64_t *asInt64; - uint64_t *asUint64; - dpiOciNumber *asNumber; - dpiOciDate *asDate; - void **asTimestamp; - void **asInterval; - void **asLobLocator; - void **asString; - void **asRawData; - void **asStmt; - void **asRowid; - int *asBoolean; - void **asObject; - void **asCollection; -} dpiOracleData; - -// intended to avoid the need for casts; contains the memory needed to supply -// buffers to Oracle when values are being transferred to or from the Oracle -// database -typedef union { - int32_t asInt32; - int64_t asInt64; - uint64_t asUint64; - float asFloat; - double asDouble; - dpiOciNumber asNumber; - dpiOciDate asDate; - int asBoolean; - void *asString; - void *asRawData; - void *asTimestamp; - void *asLobLocator; - void *asRaw; -} dpiOracleDataBuffer; - -// represents memory areas used for transferring data to and from the database -// and is used by the dpiVar structure; most statements only use one buffer, -// but DML returning statements can use multiple buffers since multiple rows -// can be returned for each execution of the statement -typedef struct { - uint32_t maxArraySize; // max number of rows in arrays - uint32_t actualArraySize; // actual number of rows in arrays - int16_t *indicator; // array of indicator values - uint16_t *returnCode; // array of return code values - uint16_t *actualLength16; // array of actual lengths (11.2 only) - uint32_t *actualLength32; // array of actual lengths (12.1+) - void **objectIndicator; // array of object indicator values - dpiReferenceBuffer *references; // array of references (specific types) - dpiDynamicBytes *dynamicBytes; // array of dynamically alloced chunks - char *tempBuffer; // buffer for numeric conversion - dpiData *externalData; // array of buffers (externally used) - dpiOracleData data; // Oracle data buffers (internal only) -} dpiVarBuffer; - -// represents memory areas used for enqueuing and dequeuing messages from -// queues -typedef struct { - uint32_t numElements; // number of elements in next arrays - dpiMsgProps **props; // array of dpiMsgProps handles - void **handles; // array of OCI msg prop handles - void **instances; // array of instances - void **indicators; // array of indicators - int16_t *rawIndicators; // array of indicators (RAW queues) - void **msgIds; // array of OCI message ids -} dpiQueueBuffer; - - -//----------------------------------------------------------------------------- -// External implementation type definitions -//----------------------------------------------------------------------------- - -// represents session pools and is exposed publicly as a handle of type -// DPI_HTYPE_POOL; the implementation for this is found in the file -// dpiPool.c -struct dpiPool { - dpiType_HEAD - void *handle; // OCI session pool handle - const char *name; // pool name (CHAR encoding) - uint32_t nameLength; // length of pool name - int pingInterval; // interval (seconds) between pings - int pingTimeout; // timeout (milliseconds) for ping - int homogeneous; // homogeneous pool? - int externalAuth; // use external authentication? -}; - -// represents connections to the database and is exposed publicly as a handle -// of type DPI_HTYPE_CONN; the implementation for this is found in the file -// dpiConn.c; the list of statement, LOB and object handles created by this -// connection is maintained and all of these are automatically closed when the -// connection itself is closed (in order to avoid memory leaks and segfaults if -// the correct order is not observed) -struct dpiConn { - dpiType_HEAD - dpiPool *pool; // pool acquired from or NULL - void *handle; // OCI service context handle - void *serverHandle; // OCI server handle - void *sessionHandle; // OCI session handle - void *shardingKey; // OCI sharding key descriptor - void *superShardingKey; // OCI supper sharding key descriptor - const char *releaseString; // cached release string or NULL - uint32_t releaseStringLength; // cached release string length or 0 - void *rawTDO; // cached RAW TDO - dpiVersionInfo versionInfo; // Oracle database version info - uint32_t commitMode; // commit mode (for two-phase commits) - uint16_t charsetId; // database character set ID - dpiHandleList *openStmts; // list of statements created - dpiHandleList *openLobs; // list of LOBs created - dpiHandleList *objects; // list of objects created - int externalHandle; // OCI handle provided directly? - int deadSession; // dead session (drop from pool)? - int standalone; // standalone connection (not pooled)? - int closing; // connection is being closed? -}; - -// represents the context in which all activity in the library takes place; the -// implementation for this is found in the file dpiContext.c; the minor -// version of the calling application is retained in order to adjust as needed -// for differing sizes of public structures -struct dpiContext { - dpiType_HEAD - dpiVersionInfo *versionInfo; // OCI client version info - uint8_t dpiMinorVersion; // ODPI-C minor version of application -}; - -// represents statements of all types (queries, DML, DDL, PL/SQL) and is -// exposed publicly as a handle of type DPI_HTYPE_STMT; the implementation for -// this is found in the file dpiStmt.c -struct dpiStmt { - dpiType_HEAD - dpiConn *conn; // connection which created this - uint32_t openSlotNum; // slot in connection handle list - void *handle; // OCI statement handle - dpiStmt *parentStmt; // parent statement (implicit results) - uint32_t fetchArraySize; // rows to fetch each time - uint32_t bufferRowCount; // number of rows in fetch buffers - uint32_t bufferRowIndex; // index into buffers for current row - uint32_t numQueryVars; // number of query variables - dpiVar **queryVars; // array of query variables - dpiQueryInfo *queryInfo; // array of query metadata - uint32_t allocatedBindVars; // number of allocated bind variables - uint32_t numBindVars; // actual nubmer of bind variables - dpiBindVar *bindVars; // array of bind variables - uint32_t numBatchErrors; // number of batch errors - dpiErrorBuffer *batchErrors; // array of batch errors - uint64_t rowCount; // rows affected or rows fetched so far - uint64_t bufferMinRow; // row num of first row in buffers - uint16_t statementType; // type of statement - dpiRowid *lastRowid; // rowid of last affected row - int isOwned; // owned by structure? - int hasRowsToFetch; // potentially more rows to fetch? - int scrollable; // scrollable cursor? - int isReturning; // statement has RETURNING clause? - int deleteFromCache; // drop from statement cache on close? - int closing; // statement is being closed? -}; - -// represents memory areas used for transferring data to and from the database -// and is exposed publicly as a handle of type DPI_HTYPE_VAR; the -// implementation for this is found in the file dpiVar.c; variables can be -// bound to a statement or fetched into by a statement -struct dpiVar { - dpiType_HEAD - dpiConn *conn; // connection which created this - const dpiOracleType *type; // type of data contained in variable - dpiNativeTypeNum nativeTypeNum; // native (C) type of data - int requiresPreFetch; // requires prefetch processing? - int isArray; // is an index-by table (array)? - uint32_t sizeInBytes; // size in bytes of each row - int isDynamic; // dynamically bound or defined? - dpiObjectType *objectType; // object type (or NULL) - dpiVarBuffer buffer; // main buffer for data - dpiVarBuffer *dynBindBuffers; // array of buffers (DML returning) - dpiError *error; // error (only for dynamic bind/define) -}; - -// represents large objects (CLOB, BLOB, NCLOB and BFILE) and is exposed -// publicly as a handle of type DPI_HTYPE_LOB; the implementation for this is -// found in the file dpiLob.c -struct dpiLob { - dpiType_HEAD - dpiConn *conn; // connection which created this - uint32_t openSlotNum; // slot in connection handle list - const dpiOracleType *type; // type of LOB - void *locator; // OCI LOB locator descriptor - char *buffer; // stores dir alias/name for BFILE - int closing; // is LOB being closed? -}; - -// represents object attributes of the types created by the SQL command CREATE -// OR REPLACE TYPE and is exposed publicly as a handle of type -// DPI_HTYPE_OBJECT_ATTR; the implementation for this is found in the file -// dpiObjectAttr.c -struct dpiObjectAttr { - dpiType_HEAD - dpiObjectType *belongsToType; // type attribute belongs to - const char *name; // name of attribute (CHAR encoding) - uint32_t nameLength; // length of name of attribute - dpiDataTypeInfo typeInfo; // attribute data type info -}; - -// represents types created by the SQL command CREATE OR REPLACE TYPE and is -// exposed publicly as a handle of type DPI_HTYPE_OBJECT_TYPE; the -// implementation for this is found in the file dpiObjectType.c -struct dpiObjectType { - dpiType_HEAD - dpiConn *conn; // connection which created this - void *tdo; // OCI type descriptor object - uint16_t typeCode; // OCI type code - const char *schema; // schema owning type (CHAR encoding) - uint32_t schemaLength; // length of schema owning type - const char *name; // name of type (CHAR encoding) - uint32_t nameLength; // length of name of type - dpiDataTypeInfo elementTypeInfo; // type info of elements of collection - int isCollection; // is type a collection? - uint16_t numAttributes; // number of attributes type has -}; - -// represents objects of the types created by the SQL command CREATE OR REPLACE -// TYPE and is exposed publicly as a handle of type DPI_HTYPE_OBJECT; the -// implementation for this is found in the file dpiObject.c -struct dpiObject { - dpiType_HEAD - dpiObjectType *type; // type of object - uint32_t openSlotNum; // slot in connection handle list - void *instance; // OCI instance - void *indicator; // OCI indicator - dpiObject *dependsOnObj; // extracted from parent obj, or NULL - int freeIndicator; // should indicator be freed? - int closing; // is object being closed? -}; - -// represents the unique identifier of a row in Oracle Database and is exposed -// publicly as a handle of type DPI_HTYPE_ROWID; the implementation for this is -// found in the file dpiRowid.c -struct dpiRowid { - dpiType_HEAD - void *handle; // OCI rowid descriptor - char *buffer; // cached string rep (or NULL) - uint16_t bufferLength; // length of string rep (or 0) -}; - -// represents a subscription to events such as continuous query notification -// (CQN) and object change notification and is exposed publicly as a handle of -// type DPI_HTYPE_SUBSCR; the implementation for this is found in the file -// dpiSubscr.c -struct dpiSubscr { - dpiType_HEAD - dpiConn *conn; // connection which created this - void *handle; // OCI subscription handle - dpiMutexType mutex; // enables thread safety - dpiSubscrNamespace subscrNamespace; // OCI namespace - dpiSubscrQOS qos; // quality of service flags - dpiSubscrCallback callback; // callback when event is propagated - void *callbackContext; // context pointer for callback - int clientInitiated; // client initiated? - int registered; // registered with database? -}; - -// represents the available options for dequeueing messages when using advanced -// queueing and is exposed publicly as a handle of type DPI_HTYPE_DEQ_OPTIONS; -// the implementation for this is found in dpiDeqOptions.c -struct dpiDeqOptions { - dpiType_HEAD - dpiConn *conn; // connection which created this - void *handle; // OCI dequeue options handle -}; - -// represents the available options for enqueueing messages when using advanced -// queueing and is exposed publicly as a handle of type DPI_HTYPE_ENQ_OPTIONS; -// the implementation for this is found in dpiEnqOptions.c -struct dpiEnqOptions { - dpiType_HEAD - dpiConn *conn; // connection which created this - void *handle; // OCI enqueue options handle -}; - -// represents the available properties for messages when using advanced queuing -// and is exposed publicly as a handle of type DPI_HTYPE_MSG_PROPS; the -// implementation for this is found in the file dpiMsgProps.c -struct dpiMsgProps { - dpiType_HEAD - dpiConn *conn; // connection which created this - void *handle; // OCI message properties handle - dpiObject *payloadObj; // payload (object) - void *payloadRaw; // payload (RAW) - void *msgIdRaw; // message ID (RAW) -}; - -// represents SODA collections and is exposed publicly as a handle of type -// DPI_HTYPE_SODA_COLL; the implementation for this is found in the file -// dpiSodaColl.c -struct dpiSodaColl { - dpiType_HEAD - dpiSodaDb *db; // database which created this - void *handle; // OCI SODA collection handle - int binaryContent; // content stored in BLOB? -}; - -// represents cursors that iterate over SODA collections and is exposed -// publicly as a handle of type DPI_HTYPE_SODA_COLL_CURSOR; the implementation -// for this is found in the file dpiSodaCollCursor.c -struct dpiSodaCollCursor { - dpiType_HEAD - dpiSodaDb *db; // database which created this - void *handle; // OCI SODA collection cursor handle -}; - -// represents a SODA database (contains SODA collections) and is exposed -// publicly as a handle of type DPI_HTYPE_SODA_DB; the implementation for this -// is found in the file dpiSodaDb.c -struct dpiSodaDb { - dpiType_HEAD - dpiConn *conn; // connection which created this -}; - -// represents a SODA document and is exposed publicly as a handle of type -// DPI_HTYPE_SODA_DOC; the implementation for this is found in the file -// dpiSodaDoc.c -struct dpiSodaDoc { - dpiType_HEAD - dpiSodaDb *db; // database which created this - void *handle; // OCI SODA document handle - int binaryContent; // binary content? -}; - -// represents a SODA document cursor and is exposed publicly as a handle of -// type DPI_HTYPE_SODA_DOC_CURSOR; the implementation for this is found in the -// file dpiSodaDocCursor.c -struct dpiSodaDocCursor { - dpiType_HEAD - dpiSodaColl *coll; // collection which created this - void *handle; // OCI SODA document cursor handle -}; - -// represents a queue used in AQ (advanced queuing) and is exposed publicly as -// a handle of type DPI_HTYPE_QUEUE; the implementation for this is found in -// the file dpiQueue.c -struct dpiQueue { - dpiType_HEAD - dpiConn *conn; // connection which created this - const char *name; // name of the queue (NULL-terminated) - dpiObjectType *payloadType; // object type (for object payloads) - dpiDeqOptions *deqOptions; // dequeue options - dpiEnqOptions *enqOptions; // enqueue options - dpiQueueBuffer buffer; // buffer area -}; - - -//----------------------------------------------------------------------------- -// definition of internal dpiContext methods -//----------------------------------------------------------------------------- -void dpiContext__initCommonCreateParams(dpiCommonCreateParams *params); -void dpiContext__initConnCreateParams(dpiConnCreateParams *params); -void dpiContext__initPoolCreateParams(dpiPoolCreateParams *params); -void dpiContext__initSodaOperOptions(dpiSodaOperOptions *options); -void dpiContext__initSubscrCreateParams(dpiSubscrCreateParams *params); - - -//----------------------------------------------------------------------------- -// definition of internal dpiDataBuffer methods -//----------------------------------------------------------------------------- -int dpiDataBuffer__fromOracleDate(dpiDataBuffer *data, - dpiOciDate *oracleValue); -int dpiDataBuffer__fromOracleDateAsDouble(dpiDataBuffer *data, - dpiEnv *env, dpiError *error, dpiOciDate *oracleValue); -int dpiDataBuffer__fromOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue); -int dpiDataBuffer__fromOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue); -int dpiDataBuffer__fromOracleNumberAsDouble(dpiDataBuffer *data, - dpiError *error, void *oracleValue); -int dpiDataBuffer__fromOracleNumberAsInteger(dpiDataBuffer *data, - dpiError *error, void *oracleValue); -int dpiDataBuffer__fromOracleNumberAsText(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue); -int dpiDataBuffer__fromOracleNumberAsUnsignedInteger(dpiDataBuffer *data, - dpiError *error, void *oracleValue); -int dpiDataBuffer__fromOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue, int withTZ); -int dpiDataBuffer__fromOracleTimestampAsDouble(dpiDataBuffer *data, - dpiEnv *env, dpiError *error, void *oracleValue); -int dpiDataBuffer__toOracleDate(dpiDataBuffer *data, dpiOciDate *oracleValue); -int dpiDataBuffer__toOracleDateFromDouble(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, dpiOciDate *oracleValue); -int dpiDataBuffer__toOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue); -int dpiDataBuffer__toOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue); -int dpiDataBuffer__toOracleNumberFromDouble(dpiDataBuffer *data, - dpiError *error, void *oracleValue); -int dpiDataBuffer__toOracleNumberFromInteger(dpiDataBuffer *data, - dpiError *error, void *oracleValue); -int dpiDataBuffer__toOracleNumberFromText(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue); -int dpiDataBuffer__toOracleNumberFromUnsignedInteger(dpiDataBuffer *data, - dpiError *error, void *oracleValue); -int dpiDataBuffer__toOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, - dpiError *error, void *oracleValue, int withTZ); -int dpiDataBuffer__toOracleTimestampFromDouble(dpiDataBuffer *data, - dpiEnv *env, dpiError *error, void *oracleValue); - - -//----------------------------------------------------------------------------- -// definition of internal dpiEnv methods -//----------------------------------------------------------------------------- -void dpiEnv__free(dpiEnv *env, dpiError *error); -int dpiEnv__init(dpiEnv *env, const dpiContext *context, - const dpiCommonCreateParams *params, void *externalHandle, - dpiError *error); -int dpiEnv__getEncodingInfo(dpiEnv *env, dpiEncodingInfo *info); - - -//----------------------------------------------------------------------------- -// definition of internal dpiError methods -//----------------------------------------------------------------------------- -int dpiError__getInfo(dpiError *error, dpiErrorInfo *info); -int dpiError__initHandle(dpiError *error); -int dpiError__set(dpiError *error, const char *context, dpiErrorNum errorNum, - ...); -int dpiError__setFromOCI(dpiError *error, int status, dpiConn *conn, - const char *action); - - -//----------------------------------------------------------------------------- -// definition of internal dpiGen methods -//----------------------------------------------------------------------------- -int dpiGen__addRef(void *ptr, dpiHandleTypeNum typeNum, const char *fnName); -int dpiGen__allocate(dpiHandleTypeNum typeNum, dpiEnv *env, void **handle, - dpiError *error); -int dpiGen__checkHandle(const void *ptr, dpiHandleTypeNum typeNum, - const char *context, dpiError *error); -int dpiGen__endPublicFn(const void *ptr, int returnValue, dpiError *error); -int dpiGen__release(void *ptr, dpiHandleTypeNum typeNum, const char *fnName); -void dpiGen__setRefCount(void *ptr, dpiError *error, int increment); -int dpiGen__startPublicFn(const void *ptr, dpiHandleTypeNum typeNum, - const char *fnName, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiGlobal methods -//----------------------------------------------------------------------------- -int dpiGlobal__initError(const char *fnName, dpiError *error); -int dpiGlobal__lookupCharSet(const char *name, uint16_t *charsetId, - dpiError *error); -int dpiGlobal__lookupEncoding(uint16_t charsetId, char *encoding, - dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiOracleType methods -//----------------------------------------------------------------------------- -const dpiOracleType *dpiOracleType__getFromNum(dpiOracleTypeNum oracleTypeNum, - dpiError *error); -int dpiOracleType__populateTypeInfo(dpiConn *conn, void *handle, - uint32_t handleType, dpiDataTypeInfo *info, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiConn methods -//----------------------------------------------------------------------------- -int dpiConn__checkConnected(dpiConn *conn, dpiError *error); -int dpiConn__create(dpiConn *conn, const dpiContext *context, - const char *userName, uint32_t userNameLength, const char *password, - uint32_t passwordLength, const char *connectString, - uint32_t connectStringLength, dpiPool *pool, - const dpiCommonCreateParams *commonParams, - dpiConnCreateParams *createParams, dpiError *error); -void dpiConn__free(dpiConn *conn, dpiError *error); -int dpiConn__getRawTDO(dpiConn *conn, dpiError *error); -int dpiConn__getServerVersion(dpiConn *conn, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiPool methods -//----------------------------------------------------------------------------- -int dpiPool__acquireConnection(dpiPool *pool, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - dpiConnCreateParams *params, dpiConn **conn, dpiError *error); -void dpiPool__free(dpiPool *pool, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiStmt methods -//----------------------------------------------------------------------------- -int dpiStmt__allocate(dpiConn *conn, int scrollable, dpiStmt **stmt, - dpiError *error); -int dpiStmt__close(dpiStmt *stmt, const char *tag, uint32_t tagLength, - int propagateErrors, dpiError *error); -void dpiStmt__free(dpiStmt *stmt, dpiError *error); -int dpiStmt__init(dpiStmt *stmt, dpiError *error); -int dpiStmt__prepare(dpiStmt *stmt, const char *sql, uint32_t sqlLength, - const char *tag, uint32_t tagLength, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiVar methods -//----------------------------------------------------------------------------- -int dpiVar__allocate(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, - dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, - int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, - dpiData **data, dpiError *error); -int dpiVar__convertToLob(dpiVar *var, dpiError *error); -int dpiVar__copyData(dpiVar *var, uint32_t pos, dpiData *sourceData, - dpiError *error); -int32_t dpiVar__defineCallback(dpiVar *var, void *defnp, uint32_t iter, - void **bufpp, uint32_t **alenpp, uint8_t *piecep, void **indpp, - uint16_t **rcodepp); -int dpiVar__extendedPreFetch(dpiVar *var, dpiVarBuffer *buffer, - dpiError *error); -void dpiVar__free(dpiVar *var, dpiError *error); -int32_t dpiVar__inBindCallback(dpiVar *var, void *bindp, uint32_t iter, - uint32_t index, void **bufpp, uint32_t *alenp, uint8_t *piecep, - void **indpp); -int dpiVar__getValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, - int inFetch, dpiError *error); -int dpiVar__setValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, - dpiData *data, dpiError *error); -int32_t dpiVar__outBindCallback(dpiVar *var, void *bindp, uint32_t iter, - uint32_t index, void **bufpp, uint32_t **alenpp, uint8_t *piecep, - void **indpp, uint16_t **rcodepp); - - -//----------------------------------------------------------------------------- -// definition of internal dpiLob methods -//----------------------------------------------------------------------------- -int dpiLob__allocate(dpiConn *conn, const dpiOracleType *type, dpiLob **lob, - dpiError *error); -int dpiLob__close(dpiLob *lob, int propagateErrors, dpiError *error); -void dpiLob__free(dpiLob *lob, dpiError *error); -int dpiLob__readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, - char *value, uint64_t *valueLength, dpiError *error); -int dpiLob__setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength, - dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiObject methods -//----------------------------------------------------------------------------- -int dpiObject__allocate(dpiObjectType *objType, void *instance, - void *indicator, dpiObject *dependsOnObj, dpiObject **obj, - dpiError *error); -int dpiObject__close(dpiObject *obj, int propagateErrors, dpiError *error); -void dpiObject__free(dpiObject *obj, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiObjectType methods -//----------------------------------------------------------------------------- -int dpiObjectType__allocate(dpiConn *conn, void *param, - uint32_t nameAttribute, dpiObjectType **objType, dpiError *error); -void dpiObjectType__free(dpiObjectType *objType, dpiError *error); -int dpiObjectType__isXmlType(dpiObjectType *objType); - - -//----------------------------------------------------------------------------- -// definition of internal dpiObjectAttr methods -//----------------------------------------------------------------------------- -int dpiObjectAttr__allocate(dpiObjectType *objType, void *param, - dpiObjectAttr **attr, dpiError *error); -int dpiObjectAttr__check(dpiObjectAttr *attr, dpiError *error); -void dpiObjectAttr__free(dpiObjectAttr *attr, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiRowid methods -//----------------------------------------------------------------------------- -int dpiRowid__allocate(dpiConn *conn, dpiRowid **rowid, dpiError *error); -void dpiRowid__free(dpiRowid *rowid, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiSubscr methods -//----------------------------------------------------------------------------- -void dpiSubscr__free(dpiSubscr *subscr, dpiError *error); -int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn, - dpiSubscrCreateParams *params, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiDeqOptions methods -//----------------------------------------------------------------------------- -int dpiDeqOptions__create(dpiDeqOptions *options, dpiConn *conn, - dpiError *error); -void dpiDeqOptions__free(dpiDeqOptions *options, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiEnqOptions methods -//----------------------------------------------------------------------------- -int dpiEnqOptions__create(dpiEnqOptions *options, dpiConn *conn, - dpiError *error); -void dpiEnqOptions__free(dpiEnqOptions *options, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiSodaColl methods -//----------------------------------------------------------------------------- -int dpiSodaColl__allocate(dpiSodaDb *db, void *handle, dpiSodaColl **coll, - dpiError *error); -void dpiSodaColl__free(dpiSodaColl *coll, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiSodaCollCursor methods -//----------------------------------------------------------------------------- -int dpiSodaCollCursor__allocate(dpiSodaDb *db, void *handle, - dpiSodaCollCursor **cursor, dpiError *error); -void dpiSodaCollCursor__free(dpiSodaCollCursor *cursor, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiSodaDb methods -//----------------------------------------------------------------------------- -void dpiSodaDb__free(dpiSodaDb *db, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiSodaDoc methods -//----------------------------------------------------------------------------- -int dpiSodaDoc__allocate(dpiSodaDb *db, void *handle, dpiSodaDoc **doc, - dpiError *error); -void dpiSodaDoc__free(dpiSodaDoc *doc, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiSodaDocCursor methods -//----------------------------------------------------------------------------- -int dpiSodaDocCursor__allocate(dpiSodaColl *coll, void *handle, - dpiSodaDocCursor **cursor, dpiError *error); -void dpiSodaDocCursor__free(dpiSodaDocCursor *cursor, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiQueue methods -//----------------------------------------------------------------------------- -int dpiQueue__allocate(dpiConn *conn, const char *name, uint32_t nameLength, - dpiObjectType *payloadType, dpiQueue **queue, dpiError *error); -void dpiQueue__free(dpiQueue *queue, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiOci methods -//----------------------------------------------------------------------------- -int dpiOci__aqDeq(dpiConn *conn, const char *queueName, void *options, - void *msgProps, void *payloadType, void **payload, void **payloadInd, - void **msgId, dpiError *error); -int dpiOci__aqDeqArray(dpiConn *conn, const char *queueName, void *options, - uint32_t *numIters, void **msgProps, void *payloadType, void **payload, void **payloadInd, void **msgId, dpiError *error); -int dpiOci__aqEnq(dpiConn *conn, const char *queueName, void *options, - void *msgProps, void *payloadType, void **payload, void **payloadInd, - void **msgId, dpiError *error); -int dpiOci__aqEnqArray(dpiConn *conn, const char *queueName, void *options, - uint32_t *numIters, void **msgProps, void *payloadType, void **payload, - void **payloadInd, void **msgId, dpiError *error); -int dpiOci__arrayDescriptorAlloc(void *envHandle, void **handle, - uint32_t handleType, uint32_t arraySize, dpiError *error); -int dpiOci__arrayDescriptorFree(void **handle, uint32_t handleType); -int dpiOci__attrGet(const void *handle, uint32_t handleType, void *ptr, - uint32_t *size, uint32_t attribute, const char *action, - dpiError *error); -int dpiOci__attrSet(void *handle, uint32_t handleType, void *ptr, - uint32_t size, uint32_t attribute, const char *action, - dpiError *error); -int dpiOci__bindByName(dpiStmt *stmt, void **bindHandle, const char *name, - int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error); -int dpiOci__bindByName2(dpiStmt *stmt, void **bindHandle, const char *name, - int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error); -int dpiOci__bindByPos(dpiStmt *stmt, void **bindHandle, uint32_t pos, - int dynamicBind, dpiVar *var, dpiError *error); -int dpiOci__bindByPos2(dpiStmt *stmt, void **bindHandle, uint32_t pos, - int dynamicBind, dpiVar *var, dpiError *error); -int dpiOci__bindDynamic(dpiVar *var, void *bindHandle, dpiError *error); -int dpiOci__bindObject(dpiVar *var, void *bindHandle, dpiError *error); -int dpiOci__break(dpiConn *conn, dpiError *error); -void dpiOci__clientVersion(dpiContext *context); -int dpiOci__collAppend(dpiConn *conn, const void *elem, const void *elemInd, - void *coll, dpiError *error); -int dpiOci__collAssignElem(dpiConn *conn, int32_t index, const void *elem, - const void *elemInd, void *coll, dpiError *error); -int dpiOci__collGetElem(dpiConn *conn, void *coll, int32_t index, int *exists, - void **elem, void **elemInd, dpiError *error); -int dpiOci__collSize(dpiConn *conn, void *coll, int32_t *size, - dpiError *error); -int dpiOci__collTrim(dpiConn *conn, uint32_t numToTrim, void *coll, - dpiError *error); -int dpiOci__contextGetValue(dpiConn *conn, const char *key, uint32_t keyLength, - void **value, int checkError, dpiError *error); -int dpiOci__contextSetValue(dpiConn *conn, const char *key, uint32_t keyLength, - void *value, int checkError, dpiError *error); -int dpiOci__dateTimeConstruct(void *envHandle, void *handle, int16_t year, - uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, - uint8_t second, uint32_t fsecond, const char *tz, size_t tzLength, - dpiError *error); -int dpiOci__dateTimeConvert(void *envHandle, void *inDate, void *outDate, - dpiError *error); -int dpiOci__dateTimeGetDate(void *envHandle, void *handle, int16_t *year, - uint8_t *month, uint8_t *day, dpiError *error); -int dpiOci__dateTimeGetTime(void *envHandle, void *handle, uint8_t *hour, - uint8_t *minute, uint8_t *second, uint32_t *fsecond, dpiError *error); -int dpiOci__dateTimeGetTimeZoneOffset(void *envHandle, void *handle, - int8_t *tzHourOffset, int8_t *tzMinuteOffset, dpiError *error); -int dpiOci__dateTimeIntervalAdd(void *envHandle, void *handle, void *interval, - void *outHandle, dpiError *error); -int dpiOci__dateTimeSubtract(void *envHandle, void *handle1, void *handle2, - void *interval, dpiError *error); -int dpiOci__dbShutdown(dpiConn *conn, uint32_t mode, dpiError *error); -int dpiOci__dbStartup(dpiConn *conn, uint32_t mode, dpiError *error); -int dpiOci__defineByPos(dpiStmt *stmt, void **defineHandle, uint32_t pos, - dpiVar *var, dpiError *error); -int dpiOci__defineByPos2(dpiStmt *stmt, void **defineHandle, uint32_t pos, - dpiVar *var, dpiError *error); -int dpiOci__defineDynamic(dpiVar *var, void *defineHandle, dpiError *error); -int dpiOci__defineObject(dpiVar *var, void *defineHandle, dpiError *error); -int dpiOci__describeAny(dpiConn *conn, void *obj, uint32_t objLength, - uint8_t objType, void *describeHandle, dpiError *error); -int dpiOci__descriptorAlloc(void *envHandle, void **handle, - const uint32_t handleType, const char *action, dpiError *error); -int dpiOci__descriptorFree(void *handle, uint32_t handleType); -int dpiOci__envNlsCreate(void **envHandle, uint32_t mode, uint16_t charsetId, - uint16_t ncharsetId, dpiError *error); -int dpiOci__errorGet(void *handle, uint32_t handleType, uint16_t charsetId, - const char *action, dpiError *error); -int dpiOci__handleAlloc(void *envHandle, void **handle, uint32_t handleType, - const char *action, dpiError *error); -int dpiOci__handleFree(void *handle, uint32_t handleType); -int dpiOci__intervalGetDaySecond(void *envHandle, int32_t *day, int32_t *hour, - int32_t *minute, int32_t *second, int32_t *fsecond, - const void *interval, dpiError *error); -int dpiOci__intervalGetYearMonth(void *envHandle, int32_t *year, - int32_t *month, const void *interval, dpiError *error); -int dpiOci__intervalSetDaySecond(void *envHandle, int32_t day, int32_t hour, - int32_t minute, int32_t second, int32_t fsecond, void *interval, - dpiError *error); -int dpiOci__intervalSetYearMonth(void *envHandle, int32_t year, int32_t month, - void *interval, dpiError *error); -int dpiOci__lobClose(dpiLob *lob, dpiError *error); -int dpiOci__lobCreateTemporary(dpiLob *lob, dpiError *error); -int dpiOci__lobFileExists(dpiLob *lob, int *exists, dpiError *error); -int dpiOci__lobFileGetName(dpiLob *lob, char *dirAlias, - uint16_t *dirAliasLength, char *name, uint16_t *nameLength, - dpiError *error); -int dpiOci__lobFileSetName(dpiLob *lob, const char *dirAlias, - uint16_t dirAliasLength, const char *name, uint16_t nameLength, - dpiError *error); -int dpiOci__lobFreeTemporary(dpiConn *conn, void *lobLocator, int checkError, - dpiError *error); -int dpiOci__lobGetChunkSize(dpiLob *lob, uint32_t *size, dpiError *error); -int dpiOci__lobGetLength2(dpiLob *lob, uint64_t *size, dpiError *error); -int dpiOci__lobIsOpen(dpiLob *lob, int *isOpen, dpiError *error); -int dpiOci__lobIsTemporary(dpiLob *lob, int *isTemporary, int checkError, - dpiError *error); -int dpiOci__lobLocatorAssign(dpiLob *lob, void **copiedHandle, - dpiError *error); -int dpiOci__lobOpen(dpiLob *lob, dpiError *error); -int dpiOci__lobRead2(dpiLob *lob, uint64_t offset, uint64_t *amountInBytes, - uint64_t *amountInChars, char *buffer, uint64_t bufferLength, - dpiError *error); -int dpiOci__lobTrim2(dpiLob *lob, uint64_t newLength, dpiError *error); -int dpiOci__lobWrite2(dpiLob *lob, uint64_t offset, const char *value, - uint64_t valueLength, dpiError *error); -int dpiOci__memoryAlloc(dpiConn *conn, void **ptr, uint32_t size, - int checkError, dpiError *error); -int dpiOci__memoryFree(dpiConn *conn, void *ptr, dpiError *error); -int dpiOci__nlsCharSetConvert(void *envHandle, uint16_t destCharsetId, - char *dest, size_t destLength, uint16_t sourceCharsetId, - const char *source, size_t sourceLength, size_t *resultSize, - dpiError *error); -int dpiOci__nlsCharSetIdToName(void *envHandle, char *buf, size_t bufLength, - uint16_t charsetId, dpiError *error); -int dpiOci__nlsCharSetNameToId(void *envHandle, const char *name, - uint16_t *charsetId, dpiError *error); -int dpiOci__nlsEnvironmentVariableGet(uint16_t item, void *value, - dpiError *error); -int dpiOci__nlsNameMap(void *envHandle, char *buf, size_t bufLength, - const char *source, uint32_t flag, dpiError *error); -int dpiOci__nlsNumericInfoGet(void *envHandle, int32_t *value, uint16_t item, - dpiError *error); -int dpiOci__numberFromInt(const void *value, unsigned int valueLength, - unsigned int flags, void *number, dpiError *error); -int dpiOci__numberFromReal(const double value, void *number, dpiError *error); -int dpiOci__numberToInt(void *number, void *value, unsigned int valueLength, - unsigned int flags, dpiError *error); -int dpiOci__numberToReal(double *value, void *number, dpiError *error); -int dpiOci__objectCopy(dpiObject *obj, void *sourceInstance, - void *sourceIndicator, dpiError *error); -int dpiOci__objectFree(void *envHandle, void *data, int checkError, - dpiError *error); -int dpiOci__objectGetAttr(dpiObject *obj, dpiObjectAttr *attr, - int16_t *scalarValueIndicator, void **valueIndicator, void **value, - void **tdo, dpiError *error); -int dpiOci__objectGetInd(dpiObject *obj, dpiError *error); -int dpiOci__objectNew(dpiObject *obj, dpiError *error); -int dpiOci__objectPin(void *envHandle, void *objRef, void **obj, - dpiError *error); -int dpiOci__objectSetAttr(dpiObject *obj, dpiObjectAttr *attr, - int16_t scalarValueIndicator, void *valueIndicator, const void *value, - dpiError *error); -int dpiOci__paramGet(const void *handle, uint32_t handleType, void **parameter, - uint32_t pos, const char *action, dpiError *error); -int dpiOci__passwordChange(dpiConn *conn, const char *userName, - uint32_t userNameLength, const char *oldPassword, - uint32_t oldPasswordLength, const char *newPassword, - uint32_t newPasswordLength, uint32_t mode, dpiError *error); -int dpiOci__ping(dpiConn *conn, dpiError *error); -int dpiOci__rawAssignBytes(void *envHandle, const char *value, - uint32_t valueLength, void **handle, dpiError *error); -int dpiOci__rawPtr(void *envHandle, void *handle, void **ptr); -int dpiOci__rawResize(void *envHandle, void **handle, uint32_t newSize, - dpiError *error); -int dpiOci__rawSize(void *envHandle, void *handle, uint32_t *size); -int dpiOci__rowidToChar(dpiRowid *rowid, char *buffer, uint16_t *bufferSize, - dpiError *error); -int dpiOci__serverAttach(dpiConn *conn, const char *connectString, - uint32_t connectStringLength, dpiError *error); -int dpiOci__serverDetach(dpiConn *conn, int checkError, dpiError *error); -int dpiOci__serverRelease(dpiConn *conn, char *buffer, uint32_t bufferSize, - uint32_t *version, dpiError *error); -int dpiOci__sessionBegin(dpiConn *conn, uint32_t credentialType, - uint32_t mode, dpiError *error); -int dpiOci__sessionEnd(dpiConn *conn, int checkError, dpiError *error); -int dpiOci__sessionGet(void *envHandle, void **handle, void *authInfo, - const char *connectString, uint32_t connectStringLength, - const char *tag, uint32_t tagLength, const char **outTag, - uint32_t *outTagLength, int *found, uint32_t mode, dpiError *error); -int dpiOci__sessionPoolCreate(dpiPool *pool, const char *connectString, - uint32_t connectStringLength, uint32_t minSessions, - uint32_t maxSessions, uint32_t sessionIncrement, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - uint32_t mode, dpiError *error); -int dpiOci__sessionPoolDestroy(dpiPool *pool, uint32_t mode, int checkError, - dpiError *error); -int dpiOci__sessionRelease(dpiConn *conn, const char *tag, uint32_t tagLength, - uint32_t mode, int checkError, dpiError *error); -int dpiOci__shardingKeyColumnAdd(void *shardingKey, void *col, uint32_t colLen, - uint16_t colType, dpiError *error); -int dpiOci__sodaBulkInsert(dpiSodaColl *coll, void **documents, - uint32_t numDocuments, void *outputOptions, uint32_t mode, - dpiError *error); -int dpiOci__sodaBulkInsertAndGet(dpiSodaColl *coll, void **documents, - uint32_t numDocuments, void *outputOptions, uint32_t mode, - dpiError *error); -int dpiOci__sodaCollCreateWithMetadata(dpiSodaDb *db, const char *name, - uint32_t nameLength, const char *metadata, uint32_t metadataLength, - uint32_t mode, void **handle, dpiError *error); -int dpiOci__sodaCollDrop(dpiSodaColl *coll, int *isDropped, uint32_t mode, - dpiError *error); -int dpiOci__sodaCollGetNext(dpiConn *conn, void *cursorHandle, - void **collectionHandle, uint32_t mode, dpiError *error); -int dpiOci__sodaCollList(dpiSodaDb *db, const char *startingName, - uint32_t startingNameLength, void **handle, uint32_t mode, - dpiError *error); -int dpiOci__sodaCollOpen(dpiSodaDb *db, const char *name, uint32_t nameLength, - uint32_t mode, void **handle, dpiError *error); -int dpiOci__sodaDataGuideGet(dpiSodaColl *coll, void **handle, uint32_t mode, - dpiError *error); -int dpiOci__sodaDocCount(dpiSodaColl *coll, void *options, uint32_t mode, - uint64_t *count, dpiError *error); -int dpiOci__sodaDocGetNext(dpiSodaDocCursor *cursor, void **handle, - uint32_t mode, dpiError *error); -int dpiOci__sodaFind(dpiSodaColl *coll, const void *options, uint32_t flags, - uint32_t mode, void **handle, dpiError *error); -int dpiOci__sodaFindOne(dpiSodaColl *coll, const void *options, uint32_t flags, - uint32_t mode, void **handle, dpiError *error); -int dpiOci__sodaIndexCreate(dpiSodaColl *coll, const char *indexSpec, - uint32_t indexSpecLength, uint32_t mode, dpiError *error); -int dpiOci__sodaIndexDrop(dpiSodaColl *coll, const char *name, - uint32_t nameLength, uint32_t mode, int *isDropped, dpiError *error); -int dpiOci__sodaInsert(dpiSodaColl *coll, void *handle, uint32_t mode, - dpiError *error); -int dpiOci__sodaInsertAndGet(dpiSodaColl *coll, void **handle, uint32_t mode, - dpiError *error); -int dpiOci__sodaOperKeysSet(const dpiSodaOperOptions *options, void *handle, - dpiError *error); -int dpiOci__sodaRemove(dpiSodaColl *coll, void *options, uint32_t mode, - uint64_t *count, dpiError *error); -int dpiOci__sodaReplOne(dpiSodaColl *coll, const void *options, void *handle, - uint32_t mode, int *isReplaced, dpiError *error); -int dpiOci__sodaReplOneAndGet(dpiSodaColl *coll, const void *options, - void **handle, uint32_t mode, int *isReplaced, dpiError *error); -int dpiOci__sodaSave(dpiSodaColl *coll, void *handle, uint32_t mode, - dpiError *error); -int dpiOci__sodaSaveAndGet(dpiSodaColl *coll, void **handle, uint32_t mode, - dpiError *error); -int dpiOci__stmtExecute(dpiStmt *stmt, uint32_t numIters, uint32_t mode, - dpiError *error); -int dpiOci__stmtFetch2(dpiStmt *stmt, uint32_t numRows, uint16_t fetchMode, - int32_t offset, dpiError *error); -int dpiOci__stmtGetBindInfo(dpiStmt *stmt, uint32_t size, uint32_t startLoc, - int32_t *numFound, char *names[], uint8_t nameLengths[], - char *indNames[], uint8_t indNameLengths[], uint8_t isDuplicate[], - void *bindHandles[], dpiError *error); -int dpiOci__stmtGetNextResult(dpiStmt *stmt, void **handle, dpiError *error); -int dpiOci__stmtPrepare2(dpiStmt *stmt, const char *sql, uint32_t sqlLength, - const char *tag, uint32_t tagLength, dpiError *error); -int dpiOci__stmtRelease(dpiStmt *stmt, const char *tag, uint32_t tagLength, - int checkError, dpiError *error); -int dpiOci__stringAssignText(void *envHandle, const char *value, - uint32_t valueLength, void **handle, dpiError *error); -int dpiOci__stringPtr(void *envHandle, void *handle, char **ptr); -int dpiOci__stringResize(void *envHandle, void **handle, uint32_t newSize, - dpiError *error); -int dpiOci__stringSize(void *envHandle, void *handle, uint32_t *size); -int dpiOci__subscriptionRegister(dpiConn *conn, void **handle, uint32_t mode, - dpiError *error); -int dpiOci__subscriptionUnRegister(dpiConn *conn, dpiSubscr *subscr, - dpiError *error); -int dpiOci__tableDelete(dpiObject *obj, int32_t index, dpiError *error); -int dpiOci__tableExists(dpiObject *obj, int32_t index, int *exists, - dpiError *error); -int dpiOci__tableFirst(dpiObject *obj, int32_t *index, dpiError *error); -int dpiOci__tableLast(dpiObject *obj, int32_t *index, dpiError *error); -int dpiOci__tableNext(dpiObject *obj, int32_t index, int32_t *nextIndex, - int *exists, dpiError *error); -int dpiOci__tablePrev(dpiObject *obj, int32_t index, int32_t *prevIndex, - int *exists, dpiError *error); -int dpiOci__tableSize(dpiObject *obj, int32_t *size, dpiError *error); -int dpiOci__threadKeyDestroy(void *envHandle, void *errorHandle, void **key, - dpiError *error); -int dpiOci__threadKeyGet(void *envHandle, void *errorHandle, void *key, - void **value, dpiError *error); -int dpiOci__threadKeyInit(void *envHandle, void *errorHandle, void **key, - void *destroyFunc, dpiError *error); -int dpiOci__threadKeySet(void *envHandle, void *errorHandle, void *key, - void *value, dpiError *error); -int dpiOci__transCommit(dpiConn *conn, uint32_t flags, dpiError *error); -int dpiOci__transPrepare(dpiConn *conn, int *commitNeeded, dpiError *error); -int dpiOci__transRollback(dpiConn *conn, int checkError, dpiError *error); -int dpiOci__transStart(dpiConn *conn, dpiError *error); -int dpiOci__typeByFullName(dpiConn *conn, const char *name, - uint32_t nameLength, void **tdo, dpiError *error); -int dpiOci__typeByName(dpiConn *conn, const char *schema, - uint32_t schemaLength, const char *name, uint32_t nameLength, - void **tdo, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiMsgProps methods -//----------------------------------------------------------------------------- -int dpiMsgProps__allocate(dpiConn *conn, dpiMsgProps **props, dpiError *error); -void dpiMsgProps__extractMsgId(dpiMsgProps *props, const char **msgId, - uint32_t *msgIdLength); -void dpiMsgProps__free(dpiMsgProps *props, dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiHandlePool methods -//----------------------------------------------------------------------------- -int dpiHandlePool__acquire(dpiHandlePool *pool, void **handle, - dpiError *error); -int dpiHandlePool__create(dpiHandlePool **pool, dpiError *error); -void dpiHandlePool__free(dpiHandlePool *pool); -void dpiHandlePool__release(dpiHandlePool *pool, void **handle); - - -//----------------------------------------------------------------------------- -// definition of internal dpiHandleList methods -//----------------------------------------------------------------------------- -int dpiHandleList__addHandle(dpiHandleList *list, void *handle, - uint32_t *slotNum, dpiError *error); -int dpiHandleList__create(dpiHandleList **list, dpiError *error); -void dpiHandleList__free(dpiHandleList *list); -void dpiHandleList__removeHandle(dpiHandleList *list, uint32_t slotNum); - - -//----------------------------------------------------------------------------- -// definition of internal dpiUtils methods -//----------------------------------------------------------------------------- -int dpiUtils__allocateMemory(size_t numMembers, size_t memberSize, - int clearMemory, const char *action, void **ptr, dpiError *error); -int dpiUtils__checkClientVersion(dpiVersionInfo *versionInfo, - int minVersionNum, int minReleaseNum, dpiError *error); -int dpiUtils__checkDatabaseVersion(dpiConn *conn, int minVersionNum, - int minReleaseNum, dpiError *error); -void dpiUtils__clearMemory(void *ptr, size_t length); -void dpiUtils__freeMemory(void *ptr); -int dpiUtils__getAttrStringWithDup(const char *action, const void *ociHandle, - uint32_t ociHandleType, uint32_t ociAttribute, const char **value, - uint32_t *valueLength, dpiError *error); -int dpiUtils__parseNumberString(const char *value, uint32_t valueLength, - uint16_t charsetId, int *isNegative, int16_t *decimalPointIndex, - uint8_t *numDigits, uint8_t *digits, dpiError *error); -int dpiUtils__parseOracleNumber(void *oracleValue, int *isNegative, - int16_t *decimalPointIndex, uint8_t *numDigits, uint8_t *digits, - dpiError *error); -int dpiUtils__setAttributesFromCommonCreateParams(void *handle, - uint32_t handleType, const dpiCommonCreateParams *params, - dpiError *error); - - -//----------------------------------------------------------------------------- -// definition of internal dpiDebug methods -//----------------------------------------------------------------------------- -void dpiDebug__initialize(void); -void dpiDebug__print(const char *format, ...); - -#endif diff --git a/vendor/github.com/godror/godror/odpi/src/dpiLob.c b/vendor/github.com/godror/godror/odpi/src/dpiLob.c deleted file mode 100644 index 55dfcebad6e..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiLob.c +++ /dev/null @@ -1,504 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiLob.c -// Implementation of LOB data. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiLob__allocate() [INTERNAL] -// Allocate and initialize LOB object. -//----------------------------------------------------------------------------- -int dpiLob__allocate(dpiConn *conn, const dpiOracleType *type, dpiLob **lob, - dpiError *error) -{ - dpiLob *tempLob; - - if (dpiGen__allocate(DPI_HTYPE_LOB, conn->env, (void**) &tempLob, - error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(conn, error, 1); - tempLob->conn = conn; - tempLob->type = type; - if (dpiOci__descriptorAlloc(conn->env->handle, &tempLob->locator, - DPI_OCI_DTYPE_LOB, "allocate descriptor", error) < 0) { - dpiLob__free(tempLob, error); - return DPI_FAILURE; - } - if (dpiHandleList__addHandle(conn->openLobs, tempLob, - &tempLob->openSlotNum, error) < 0) { - dpiOci__descriptorFree(tempLob->locator, DPI_OCI_DTYPE_LOB); - tempLob->locator = NULL; - dpiLob__free(tempLob, error); - return DPI_FAILURE; - } - - *lob = tempLob; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiLob__check() [INTERNAL] -// Check that the LOB is valid and get an error handle for subsequent calls. -//----------------------------------------------------------------------------- -static int dpiLob__check(dpiLob *lob, const char *fnName, dpiError *error) -{ - if (dpiGen__startPublicFn(lob, DPI_HTYPE_LOB, fnName, error) < 0) - return DPI_FAILURE; - if (!lob->locator) - return dpiError__set(error, "check closed", DPI_ERR_LOB_CLOSED); - return dpiConn__checkConnected(lob->conn, error); -} - - -//----------------------------------------------------------------------------- -// dpiLob__close() [INTERNAL] -// Internal method used for closing the LOB. -//----------------------------------------------------------------------------- -int dpiLob__close(dpiLob *lob, int propagateErrors, dpiError *error) -{ - int isTemporary, closing, status = DPI_SUCCESS; - - // determine whether LOB is already being closed and if not, mark LOB as - // being closed; this MUST be done while holding the lock (if in threaded - // mode) to avoid race conditions! - if (lob->env->threaded) - dpiMutex__acquire(lob->env->mutex); - closing = lob->closing; - lob->closing = 1; - if (lob->env->threaded) - dpiMutex__release(lob->env->mutex); - - // if LOB is already being closed, nothing needs to be done - if (closing) - return DPI_SUCCESS; - - // perform actual work of closing LOB - if (lob->locator) { - if (!lob->conn->deadSession && lob->conn->handle) { - status = dpiOci__lobIsTemporary(lob, &isTemporary, propagateErrors, - error); - if (isTemporary && status == DPI_SUCCESS) - status = dpiOci__lobFreeTemporary(lob->conn, - lob->locator, propagateErrors, error); - } - dpiOci__descriptorFree(lob->locator, DPI_OCI_DTYPE_LOB); - if (!lob->conn->closing) - dpiHandleList__removeHandle(lob->conn->openLobs, lob->openSlotNum); - lob->locator = NULL; - } - if (lob->buffer) { - dpiUtils__freeMemory(lob->buffer); - lob->buffer = NULL; - } - - // if actual close fails, reset closing flag; again, this must be done - // while holding the lock (if in threaded mode) in order to avoid race - // conditions! - if (status < 0) { - if (lob->env->threaded) - dpiMutex__acquire(lob->env->mutex); - lob->closing = 0; - if (lob->env->threaded) - dpiMutex__release(lob->env->mutex); - } - - return status; -} - - -//----------------------------------------------------------------------------- -// dpiLob__free() [INTERNAL] -// Free the memory for a LOB. -//----------------------------------------------------------------------------- -void dpiLob__free(dpiLob *lob, dpiError *error) -{ - dpiLob__close(lob, 0, error); - if (lob->conn) { - dpiGen__setRefCount(lob->conn, error, -1); - lob->conn = NULL; - } - dpiUtils__freeMemory(lob); -} - - -//----------------------------------------------------------------------------- -// dpiLob__readBytes() [INTERNAL] -// Return a portion (or all) of the data in the LOB. -//----------------------------------------------------------------------------- -int dpiLob__readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, - char *value, uint64_t *valueLength, dpiError *error) -{ - uint64_t lengthInBytes = 0, lengthInChars = 0; - int isOpen = 0; - - // amount is in characters for character LOBs and bytes for binary LOBs - if (lob->type->isCharacterData) - lengthInChars = amount; - else lengthInBytes = amount; - - // for files, open the file if needed - if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE) { - if (dpiOci__lobIsOpen(lob, &isOpen, error) < 0) - return DPI_FAILURE; - if (!isOpen) { - if (dpiOci__lobOpen(lob, error) < 0) - return DPI_FAILURE; - } - } - - // read the bytes from the LOB - if (dpiOci__lobRead2(lob, offset, &lengthInBytes, &lengthInChars, - value, *valueLength, error) < 0) - return DPI_FAILURE; - *valueLength = lengthInBytes; - - // if file was opened in this routine, close it again - if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE && !isOpen) { - if (dpiOci__lobClose(lob, error) < 0) - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiLob__setFromBytes() [INTERNAL] -// Clear the LOB completely and then write the specified bytes to it. -//----------------------------------------------------------------------------- -int dpiLob__setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength, - dpiError *error) -{ - if (dpiOci__lobTrim2(lob, 0, error) < 0) - return DPI_FAILURE; - if (valueLength == 0) - return DPI_SUCCESS; - return dpiOci__lobWrite2(lob, 1, value, valueLength, error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_addRef() [PUBLIC] -// Add a reference to the LOB. -//----------------------------------------------------------------------------- -int dpiLob_addRef(dpiLob *lob) -{ - return dpiGen__addRef(lob, DPI_HTYPE_LOB, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiLob_close() [PUBLIC] -// Close the LOB and make it unusable for further operations. -//----------------------------------------------------------------------------- -int dpiLob_close(dpiLob *lob) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - status = dpiLob__close(lob, 1, &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_closeResource() [PUBLIC] -// Close the LOB's resources. -//----------------------------------------------------------------------------- -int dpiLob_closeResource(dpiLob *lob) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - status = dpiOci__lobClose(lob, &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_copy() [PUBLIC] -// Create a copy of the LOB and return it. -//----------------------------------------------------------------------------- -int dpiLob_copy(dpiLob *lob, dpiLob **copiedLob) -{ - dpiLob *tempLob; - dpiError error; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(lob, copiedLob) - if (dpiLob__allocate(lob->conn, lob->type, &tempLob, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - if (dpiOci__lobLocatorAssign(lob, &tempLob->locator, &error) < 0) { - dpiLob__free(tempLob, &error); - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - } - *copiedLob = tempLob; - return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_getBufferSize() [PUBLIC] -// Get the required size of a buffer given the number of characters. If the -// LOB does not refer to a character LOB the value is returned unchanged. -//----------------------------------------------------------------------------- -int dpiLob_getBufferSize(dpiLob *lob, uint64_t sizeInChars, - uint64_t *sizeInBytes) -{ - dpiError error; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(lob, sizeInBytes) - if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_CLOB) - *sizeInBytes = sizeInChars * lob->env->maxBytesPerCharacter; - else if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB) - *sizeInBytes = sizeInChars * lob->env->nmaxBytesPerCharacter; - else *sizeInBytes = sizeInChars; - return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_getChunkSize() [PUBLIC] -// Return the chunk size associated with the LOB. -//----------------------------------------------------------------------------- -int dpiLob_getChunkSize(dpiLob *lob, uint32_t *size) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(lob, size) - status = dpiOci__lobGetChunkSize(lob, size, &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_getDirectoryAndFileName() [PUBLIC] -// Return the directory alias and file name for the BFILE lob. -//----------------------------------------------------------------------------- -int dpiLob_getDirectoryAndFileName(dpiLob *lob, const char **directoryAlias, - uint32_t *directoryAliasLength, const char **fileName, - uint32_t *fileNameLength) -{ - uint16_t ociDirectoryAliasLength, ociFileNameLength; - dpiError error; - - // validate parameters - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(lob, directoryAlias) - DPI_CHECK_PTR_NOT_NULL(lob, directoryAliasLength) - DPI_CHECK_PTR_NOT_NULL(lob, fileName) - DPI_CHECK_PTR_NOT_NULL(lob, fileNameLength) - - // get directory and file name - ociDirectoryAliasLength = 30; - ociFileNameLength = 255; - if (!lob->buffer) { - if (dpiUtils__allocateMemory(1, - ociDirectoryAliasLength + ociFileNameLength, 0, - "allocate name buffer", (void**) &lob->buffer, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - } - *directoryAlias = lob->buffer; - *fileName = lob->buffer + ociDirectoryAliasLength; - if (dpiOci__lobFileGetName(lob, (char*) *directoryAlias, - &ociDirectoryAliasLength, (char*) *fileName, &ociFileNameLength, - &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - *directoryAliasLength = ociDirectoryAliasLength; - *fileNameLength = ociFileNameLength; - return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_getFileExists() [PUBLIC] -// Return whether or not the file pointed to by the locator exists. -//----------------------------------------------------------------------------- -int dpiLob_getFileExists(dpiLob *lob, int *exists) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(lob, exists) - status = dpiOci__lobFileExists(lob, exists, &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_getIsResourceOpen() [PUBLIC] -// Return whether or not the LOB' resources are open. -//----------------------------------------------------------------------------- -int dpiLob_getIsResourceOpen(dpiLob *lob, int *isOpen) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(lob, isOpen) - status = dpiOci__lobIsOpen(lob, isOpen, &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_getSize() [PUBLIC] -// Returns the size of the LOB. -//----------------------------------------------------------------------------- -int dpiLob_getSize(dpiLob *lob, uint64_t *size) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(lob, size) - status = dpiOci__lobGetLength2(lob, size, &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_openResource() [PUBLIC] -// Open the LOB's resources to speed further accesses. -//----------------------------------------------------------------------------- -int dpiLob_openResource(dpiLob *lob) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - status = dpiOci__lobOpen(lob, &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_readBytes() [PUBLIC] -// Return a portion (or all) of the data in the LOB. -//----------------------------------------------------------------------------- -int dpiLob_readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, - char *value, uint64_t *valueLength) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(lob, value) - DPI_CHECK_PTR_NOT_NULL(lob, valueLength) - status = dpiLob__readBytes(lob, offset, amount, value, valueLength, - &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_release() [PUBLIC] -// Release a reference to the LOB. -//----------------------------------------------------------------------------- -int dpiLob_release(dpiLob *lob) -{ - return dpiGen__release(lob, DPI_HTYPE_LOB, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiLob_setDirectoryAndFileName() [PUBLIC] -// Set the directory alias and file name for the BFILE LOB. -//----------------------------------------------------------------------------- -int dpiLob_setDirectoryAndFileName(dpiLob *lob, const char *directoryAlias, - uint32_t directoryAliasLength, const char *fileName, - uint32_t fileNameLength) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(lob, directoryAlias) - DPI_CHECK_PTR_NOT_NULL(lob, fileName) - status = dpiOci__lobFileSetName(lob, directoryAlias, - (uint16_t) directoryAliasLength, fileName, - (uint16_t) fileNameLength, &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_setFromBytes() [PUBLIC] -// Clear the LOB completely and then write the specified bytes to it. -//----------------------------------------------------------------------------- -int dpiLob_setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(lob, value) - status = dpiLob__setFromBytes(lob, value, valueLength, &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_trim() [PUBLIC] -// Trim the LOB to the specified length. -//----------------------------------------------------------------------------- -int dpiLob_trim(dpiLob *lob, uint64_t newSize) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - status = dpiOci__lobTrim2(lob, newSize, &error); - return dpiGen__endPublicFn(lob, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiLob_writeBytes() [PUBLIC] -// Write the data to the LOB at the offset specified. -//----------------------------------------------------------------------------- -int dpiLob_writeBytes(dpiLob *lob, uint64_t offset, const char *value, - uint64_t valueLength) -{ - dpiError error; - int status; - - if (dpiLob__check(lob, __func__, &error) < 0) - return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(lob, value) - status = dpiOci__lobWrite2(lob, offset, value, valueLength, &error); - return dpiGen__endPublicFn(lob, status, &error); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiMsgProps.c b/vendor/github.com/godror/godror/odpi/src/dpiMsgProps.c deleted file mode 100644 index 518d2e7d20b..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiMsgProps.c +++ /dev/null @@ -1,487 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiMsgProps.c -// Implementation of AQ message properties. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiMsgProps__allocate() [INTERNAL] -// Create a new message properties structure and return it. In case of error -// NULL is returned. -//----------------------------------------------------------------------------- -int dpiMsgProps__allocate(dpiConn *conn, dpiMsgProps **props, dpiError *error) -{ - dpiMsgProps *tempProps; - - if (dpiGen__allocate(DPI_HTYPE_MSG_PROPS, conn->env, (void**) &tempProps, - error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(conn, error, 1); - tempProps->conn = conn; - if (dpiOci__descriptorAlloc(conn->env->handle, &tempProps->handle, - DPI_OCI_DTYPE_AQMSG_PROPERTIES, "allocate descriptor", - error) < 0) { - dpiMsgProps__free(tempProps, error); - return DPI_FAILURE; - } - - *props = tempProps; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps__extractMsgId() [INTERNAL] -// Extract bytes from the OCIRaw value containing the message id. -//----------------------------------------------------------------------------- -void dpiMsgProps__extractMsgId(dpiMsgProps *props, const char **msgId, - uint32_t *msgIdLength) -{ - dpiOci__rawPtr(props->env->handle, props->msgIdRaw, (void**) msgId); - dpiOci__rawSize(props->env->handle, props->msgIdRaw, msgIdLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps__free() [INTERNAL] -// Free the memory for a message properties structure. -//----------------------------------------------------------------------------- -void dpiMsgProps__free(dpiMsgProps *props, dpiError *error) -{ - if (props->handle) { - dpiOci__descriptorFree(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES); - props->handle = NULL; - } - if (props->payloadObj) { - dpiGen__setRefCount(props->payloadObj, error, -1); - props->payloadObj = NULL; - } - if (props->payloadRaw) { - dpiOci__rawResize(props->env->handle, &props->payloadRaw, 0, error); - props->payloadRaw = NULL; - } - if (props->msgIdRaw) { - dpiOci__rawResize(props->env->handle, &props->msgIdRaw, 0, error); - props->msgIdRaw = NULL; - } - if (props->conn) { - dpiGen__setRefCount(props->conn, error, -1); - props->conn = NULL; - } - dpiUtils__freeMemory(props); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps__getAttrValue() [INTERNAL] -// Get the attribute value in OCI. -//----------------------------------------------------------------------------- -static int dpiMsgProps__getAttrValue(dpiMsgProps *props, uint32_t attribute, - const char *fnName, void *value, uint32_t *valueLength) -{ - dpiError error; - int status; - - if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, fnName, &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(props, value) - DPI_CHECK_PTR_NOT_NULL(props, valueLength) - status = dpiOci__attrGet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, - value, valueLength, attribute, "get attribute value", &error); - return dpiGen__endPublicFn(props, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps__setAttrValue() [INTERNAL] -// Set the attribute value in OCI. -//----------------------------------------------------------------------------- -static int dpiMsgProps__setAttrValue(dpiMsgProps *props, uint32_t attribute, - const char *fnName, const void *value, uint32_t valueLength) -{ - dpiError error; - int status; - - if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, fnName, &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(props, value) - status = dpiOci__attrSet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, - (void*) value, valueLength, attribute, "set attribute value", - &error); - return dpiGen__endPublicFn(props, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_addRef() [PUBLIC] -// Add a reference to the message properties. -//----------------------------------------------------------------------------- -int dpiMsgProps_addRef(dpiMsgProps *props) -{ - return dpiGen__addRef(props, DPI_HTYPE_MSG_PROPS, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getCorrelation() [PUBLIC] -// Return correlation associated with the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_getCorrelation(dpiMsgProps *props, const char **value, - uint32_t *valueLength) -{ - return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_CORRELATION, __func__, - (void*) value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getDelay() [PUBLIC] -// Return the number of seconds the message was delayed. -//----------------------------------------------------------------------------- -int dpiMsgProps_getDelay(dpiMsgProps *props, int32_t *value) -{ - uint32_t valueLength = sizeof(uint32_t); - - return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_DELAY, __func__, - value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getDeliveryMode() [PUBLIC] -// Return the mode used for delivering the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_getDeliveryMode(dpiMsgProps *props, - dpiMessageDeliveryMode *value) -{ - uint32_t valueLength = sizeof(uint16_t); - - return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_MSG_DELIVERY_MODE, - __func__, value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getEnqTime() [PUBLIC] -// Return the time the message was enqueued. -//----------------------------------------------------------------------------- -int dpiMsgProps_getEnqTime(dpiMsgProps *props, dpiTimestamp *value) -{ - dpiOciDate ociValue; - dpiError error; - - if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, - &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(props, value) - if (dpiOci__attrGet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, - &ociValue, NULL, DPI_OCI_ATTR_ENQ_TIME, "get attribute value", - &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - value->year = ociValue.year; - value->month = ociValue.month; - value->day = ociValue.day; - value->hour = ociValue.hour; - value->minute = ociValue.minute; - value->second = ociValue.second; - value->fsecond = 0; - value->tzHourOffset = 0; - value->tzMinuteOffset = 0; - return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getExceptionQ() [PUBLIC] -// Return the name of the exception queue associated with the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_getExceptionQ(dpiMsgProps *props, const char **value, - uint32_t *valueLength) -{ - return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_EXCEPTION_QUEUE, - __func__, (void*) value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getExpiration() [PUBLIC] -// Return the number of seconds until the message expires. -//----------------------------------------------------------------------------- -int dpiMsgProps_getExpiration(dpiMsgProps *props, int32_t *value) -{ - uint32_t valueLength = sizeof(uint32_t); - - return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_EXPIRATION, __func__, - value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getNumAttempts() [PUBLIC] -// Return the number of attempts made to deliver the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_getNumAttempts(dpiMsgProps *props, int32_t *value) -{ - uint32_t valueLength = sizeof(uint32_t); - - return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_ATTEMPTS, __func__, - value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getMsgId() [PUBLIC] -// Return the message id for the message (available after enqueuing or -// dequeuing a message). -//----------------------------------------------------------------------------- -int dpiMsgProps_getMsgId(dpiMsgProps *props, const char **value, - uint32_t *valueLength) -{ - dpiError error; - - if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, - &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(props, value) - DPI_CHECK_PTR_NOT_NULL(props, valueLength) - if (!props->msgIdRaw) { - *value = NULL; - *valueLength = 0; - } else { - dpiOci__rawPtr(props->env->handle, props->msgIdRaw, (void**) value); - dpiOci__rawSize(props->env->handle, props->msgIdRaw, valueLength); - } - return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getOriginalMsgId() [PUBLIC] -// Return the original message id for the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_getOriginalMsgId(dpiMsgProps *props, const char **value, - uint32_t *valueLength) -{ - dpiError error; - void *rawValue; - - if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, - &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(props, value) - DPI_CHECK_PTR_NOT_NULL(props, valueLength) - if (dpiOci__attrGet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, - &rawValue, NULL, DPI_OCI_ATTR_ORIGINAL_MSGID, - "get attribute value", &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - dpiOci__rawPtr(props->env->handle, rawValue, (void**) value); - dpiOci__rawSize(props->env->handle, rawValue, valueLength); - return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getPayload() [PUBLIC] -// Get the payload for the message (as an object or a series of bytes). -//----------------------------------------------------------------------------- -int dpiMsgProps_getPayload(dpiMsgProps *props, dpiObject **obj, - const char **value, uint32_t *valueLength) -{ - dpiError error; - - if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, - &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - if (obj) - *obj = props->payloadObj; - if (value && valueLength) { - if (props->payloadRaw) { - dpiOci__rawPtr(props->env->handle, props->payloadRaw, - (void**) value); - dpiOci__rawSize(props->env->handle, props->payloadRaw, - valueLength); - } else { - *value = NULL; - *valueLength = 0; - } - } - - return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getPriority() [PUBLIC] -// Return the priority of the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_getPriority(dpiMsgProps *props, int32_t *value) -{ - uint32_t valueLength = sizeof(uint32_t); - - return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_PRIORITY, __func__, - value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_getState() [PUBLIC] -// Return the state of the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_getState(dpiMsgProps *props, dpiMessageState *value) -{ - uint32_t valueLength = sizeof(uint32_t); - - - return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_MSG_STATE, __func__, - value, &valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_release() [PUBLIC] -// Release a reference to the message properties. -//----------------------------------------------------------------------------- -int dpiMsgProps_release(dpiMsgProps *props) -{ - return dpiGen__release(props, DPI_HTYPE_MSG_PROPS, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_setCorrelation() [PUBLIC] -// Set correlation associated with the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_setCorrelation(dpiMsgProps *props, const char *value, - uint32_t valueLength) -{ - return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_CORRELATION, __func__, - value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_setDelay() [PUBLIC] -// Set the number of seconds to delay the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_setDelay(dpiMsgProps *props, int32_t value) -{ - return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_DELAY, __func__, - &value, 0); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_setExceptionQ() [PUBLIC] -// Set the name of the exception queue associated with the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_setExceptionQ(dpiMsgProps *props, const char *value, - uint32_t valueLength) -{ - return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_EXCEPTION_QUEUE, - __func__, value, valueLength); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_setExpiration() [PUBLIC] -// Set the number of seconds until the message expires. -//----------------------------------------------------------------------------- -int dpiMsgProps_setExpiration(dpiMsgProps *props, int32_t value) -{ - return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_EXPIRATION, __func__, - &value, 0); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_setOriginalMsgId() [PUBLIC] -// Set the original message id for the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_setOriginalMsgId(dpiMsgProps *props, const char *value, - uint32_t valueLength) -{ - void *rawValue = NULL; - dpiError error; - int status; - - if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, - &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(props, value) - if (dpiOci__rawAssignBytes(props->env->handle, value, valueLength, - &rawValue, &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - status = dpiOci__attrSet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, - (void*) rawValue, 0, DPI_OCI_ATTR_ORIGINAL_MSGID, "set value", - &error); - dpiOci__rawResize(props->env->handle, &rawValue, 0, &error); - return dpiGen__endPublicFn(props, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_setPayloadBytes() [PUBLIC] -// Set the payload for the message (as a series of bytes). -//----------------------------------------------------------------------------- -int dpiMsgProps_setPayloadBytes(dpiMsgProps *props, const char *value, - uint32_t valueLength) -{ - dpiError error; - int status; - - if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, - &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(props, value) - if (props->payloadRaw) { - dpiOci__rawResize(props->env->handle, &props->payloadRaw, 0, &error); - props->payloadRaw = NULL; - } - status = dpiOci__rawAssignBytes(props->env->handle, value, valueLength, - &props->payloadRaw, &error); - return dpiGen__endPublicFn(props, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_setPayloadObject() [PUBLIC] -// Set the payload for the message (as an object). -//----------------------------------------------------------------------------- -int dpiMsgProps_setPayloadObject(dpiMsgProps *props, dpiObject *obj) -{ - dpiError error; - - if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, - &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - if (dpiGen__checkHandle(obj, DPI_HTYPE_OBJECT, "check object", &error) < 0) - return dpiGen__endPublicFn(props, DPI_FAILURE, &error); - if (props->payloadObj) - dpiGen__setRefCount(props->payloadObj, &error, -1); - dpiGen__setRefCount(obj, &error, 1); - props->payloadObj = obj; - return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiMsgProps_setPriority() [PUBLIC] -// Set the priority of the message. -//----------------------------------------------------------------------------- -int dpiMsgProps_setPriority(dpiMsgProps *props, int32_t value) -{ - return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_PRIORITY, __func__, - &value, 0); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiObject.c b/vendor/github.com/godror/godror/odpi/src/dpiObject.c deleted file mode 100644 index 338c68aeeda..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiObject.c +++ /dev/null @@ -1,966 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiObject.c -// Implementation of objects. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -// forward declarations of internal functions only used in this file -int dpiObject__closeHelper(dpiObject *obj, int checkError, dpiError *error); - - -//----------------------------------------------------------------------------- -// dpiObject__allocate() [INTERNAL] -// Allocate and initialize an object structure. -//----------------------------------------------------------------------------- -int dpiObject__allocate(dpiObjectType *objType, void *instance, - void *indicator, dpiObject *dependsOnObj, dpiObject **obj, - dpiError *error) -{ - dpiObject *tempObj; - - if (dpiGen__allocate(DPI_HTYPE_OBJECT, objType->env, (void**) &tempObj, - error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(objType, error, 1); - tempObj->type = objType; - tempObj->instance = instance; - tempObj->indicator = indicator; - if (dependsOnObj) { - dpiGen__setRefCount(dependsOnObj, error, 1); - tempObj->dependsOnObj = dependsOnObj; - } - if (!instance) { - if (dpiOci__objectNew(tempObj, error) < 0) { - dpiObject__free(tempObj, error); - return DPI_FAILURE; - } - if (dpiOci__objectGetInd(tempObj, error) < 0) { - dpiObject__free(tempObj, error); - return DPI_FAILURE; - } - } - if (tempObj->instance && !dependsOnObj) { - if (dpiHandleList__addHandle(objType->conn->objects, tempObj, - &tempObj->openSlotNum, error) < 0) { - dpiObject__free(tempObj, error); - return DPI_FAILURE; - } - } - *obj = tempObj; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiObject__check() [INTERNAL] -// Determine if the object handle provided is available for use. -//----------------------------------------------------------------------------- -static int dpiObject__check(dpiObject *obj, const char *fnName, - dpiError *error) -{ - if (dpiGen__startPublicFn(obj, DPI_HTYPE_OBJECT, fnName, error) < 0) - return DPI_FAILURE; - return dpiConn__checkConnected(obj->type->conn, error); -} - - -//----------------------------------------------------------------------------- -// dpiObject__checkIsCollection() [INTERNAL] -// Check if the object is a collection, and if not, raise an exception. -//----------------------------------------------------------------------------- -static int dpiObject__checkIsCollection(dpiObject *obj, const char *fnName, - dpiError *error) -{ - if (dpiObject__check(obj, fnName, error) < 0) - return DPI_FAILURE; - if (!obj->type->isCollection) - return dpiError__set(error, "check collection", DPI_ERR_NOT_COLLECTION, - obj->type->schemaLength, obj->type->schema, - obj->type->nameLength, obj->type->name); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiObject__clearOracleValue() [INTERNAL] -// Clear the Oracle value after use. -//----------------------------------------------------------------------------- -static void dpiObject__clearOracleValue(dpiObject *obj, dpiError *error, - dpiOracleDataBuffer *buffer, dpiLob *lob, - dpiOracleTypeNum oracleTypeNum) -{ - switch (oracleTypeNum) { - case DPI_ORACLE_TYPE_CHAR: - case DPI_ORACLE_TYPE_NCHAR: - case DPI_ORACLE_TYPE_VARCHAR: - case DPI_ORACLE_TYPE_NVARCHAR: - if (buffer->asString) - dpiOci__stringResize(obj->env->handle, &buffer->asString, 0, - error); - break; - case DPI_ORACLE_TYPE_RAW: - if (buffer->asRawData) - dpiOci__rawResize(obj->env->handle, &buffer->asRawData, 0, - error); - break; - case DPI_ORACLE_TYPE_TIMESTAMP: - if (buffer->asTimestamp) - dpiOci__descriptorFree(buffer->asTimestamp, - DPI_OCI_DTYPE_TIMESTAMP); - break; - case DPI_ORACLE_TYPE_TIMESTAMP_TZ: - if (buffer->asTimestamp) - dpiOci__descriptorFree(buffer->asTimestamp, - DPI_OCI_DTYPE_TIMESTAMP_TZ); - break; - case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: - if (buffer->asTimestamp) - dpiOci__descriptorFree(buffer->asTimestamp, - DPI_OCI_DTYPE_TIMESTAMP_LTZ); - break; - case DPI_ORACLE_TYPE_CLOB: - case DPI_ORACLE_TYPE_NCLOB: - case DPI_ORACLE_TYPE_BLOB: - case DPI_ORACLE_TYPE_BFILE: - if (lob) - dpiGen__setRefCount(lob, error, -1); - break; - default: - break; - }; -} - - -//----------------------------------------------------------------------------- -// dpiObject__close() [INTERNAL] -// Close the object (frees the memory for the instance). This is needed to -// avoid trying to do so after the connection which created the object is -// closed. In some future release of the Oracle Client libraries this may not -// be needed, at which point this code and all of the code for managing the -// list of objects created by a collection can be removed. -//----------------------------------------------------------------------------- -int dpiObject__close(dpiObject *obj, int checkError, dpiError *error) -{ - int closing; - - // determine whether object is already being closed and if not, mark - // object as being closed; this MUST be done while holding the lock (if - // in threaded mode) to avoid race conditions! - if (obj->env->threaded) - dpiMutex__acquire(obj->env->mutex); - closing = obj->closing; - obj->closing = 1; - if (obj->env->threaded) - dpiMutex__release(obj->env->mutex); - - // if object is already being closed, nothing needs to be done - if (closing) - return DPI_SUCCESS; - - // perform actual work of closing object; if this fails, reset closing - // flag; again, this must be done while holding the lock (if in threaded - // mode) in order to avoid race conditions! - if (obj->instance && !obj->dependsOnObj) { - if (dpiObject__closeHelper(obj, checkError, error) < 0) { - if (obj->env->threaded) - dpiMutex__acquire(obj->env->mutex); - obj->closing = 0; - if (obj->env->threaded) - dpiMutex__release(obj->env->mutex); - return DPI_FAILURE; - } - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiObject__closeHelper() [INTERNAL] -// Helper function for closing an object. -//----------------------------------------------------------------------------- -int dpiObject__closeHelper(dpiObject *obj, int checkError, dpiError *error) -{ - if (dpiOci__objectFree(obj->env->handle, obj->instance, checkError, - error) < 0) - return DPI_FAILURE; - obj->instance = NULL; - if (obj->freeIndicator && dpiOci__objectFree(obj->env->handle, - obj->indicator, checkError, error) < 0) - return DPI_FAILURE; - obj->indicator = NULL; - if (!obj->type->conn->closing) - dpiHandleList__removeHandle(obj->type->conn->objects, - obj->openSlotNum); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiObject__free() [INTERNAL] -// Free the memory for an object. -//----------------------------------------------------------------------------- -void dpiObject__free(dpiObject *obj, dpiError *error) -{ - dpiObject__close(obj, 0, error); - if (obj->type) { - dpiGen__setRefCount(obj->type, error, -1); - obj->type = NULL; - } - if (obj->dependsOnObj) { - dpiGen__setRefCount(obj->dependsOnObj, error, -1); - obj->dependsOnObj = NULL; - } - dpiUtils__freeMemory(obj); -} - - -//----------------------------------------------------------------------------- -// dpiObject__fromOracleValue() [INTERNAL] -// Populate data from the Oracle value or return an error if this is not -// possible. -//----------------------------------------------------------------------------- -static int dpiObject__fromOracleValue(dpiObject *obj, dpiError *error, - const dpiDataTypeInfo *typeInfo, dpiOracleData *value, - int16_t *indicator, dpiNativeTypeNum nativeTypeNum, dpiData *data) -{ - dpiOracleTypeNum valueOracleTypeNum; - dpiBytes *asBytes; - - // null values are immediately returned (type is irrelevant) - if (*indicator == DPI_OCI_IND_NULL) { - data->isNull = 1; - return DPI_SUCCESS; - } - - // convert all other values - data->isNull = 0; - valueOracleTypeNum = typeInfo->oracleTypeNum; - switch (valueOracleTypeNum) { - case DPI_ORACLE_TYPE_CHAR: - case DPI_ORACLE_TYPE_NCHAR: - case DPI_ORACLE_TYPE_VARCHAR: - case DPI_ORACLE_TYPE_NVARCHAR: - if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { - asBytes = &data->value.asBytes; - dpiOci__stringPtr(obj->env->handle, *value->asString, - &asBytes->ptr); - dpiOci__stringSize(obj->env->handle, *value->asString, - &asBytes->length); - if (valueOracleTypeNum == DPI_ORACLE_TYPE_NCHAR || - valueOracleTypeNum == DPI_ORACLE_TYPE_NVARCHAR) - asBytes->encoding = obj->env->nencoding; - else asBytes->encoding = obj->env->encoding; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_RAW: - if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { - asBytes = &data->value.asBytes; - dpiOci__rawPtr(obj->env->handle, *value->asRawData, - (void**) &asBytes->ptr); - dpiOci__rawSize(obj->env->handle, *value->asRawData, - &asBytes->length); - asBytes->encoding = NULL; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_NATIVE_INT: - if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) { - data->value.asInt64 = *value->asInt32; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_NATIVE_FLOAT: - if (nativeTypeNum == DPI_NATIVE_TYPE_FLOAT) { - data->value.asFloat = *value->asFloat; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_NATIVE_DOUBLE: - if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { - data->value.asDouble = *value->asDouble; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_NUMBER: - if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) - return dpiDataBuffer__fromOracleNumberAsDouble(&data->value, - error, value->asNumber); - else if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) - return dpiDataBuffer__fromOracleNumberAsInteger(&data->value, - error, value->asNumber); - else if (nativeTypeNum == DPI_NATIVE_TYPE_UINT64) - return dpiDataBuffer__fromOracleNumberAsUnsignedInteger( - &data->value, error, value->asNumber); - else if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) - return dpiDataBuffer__fromOracleNumberAsText(&data->value, - obj->env, error, value->asNumber); - break; - case DPI_ORACLE_TYPE_DATE: - if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) - return dpiDataBuffer__fromOracleDate(&data->value, - value->asDate); - if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) - return dpiDataBuffer__fromOracleDateAsDouble(&data->value, - obj->env, error, value->asDate); - break; - case DPI_ORACLE_TYPE_TIMESTAMP: - if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) - return dpiDataBuffer__fromOracleTimestamp(&data->value, - obj->env, error, *value->asTimestamp, 0); - if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) - return dpiDataBuffer__fromOracleTimestampAsDouble(&data->value, - obj->env, error, *value->asTimestamp); - break; - case DPI_ORACLE_TYPE_TIMESTAMP_TZ: - case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: - if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) - return dpiDataBuffer__fromOracleTimestamp(&data->value, - obj->env, error, *value->asTimestamp, 1); - if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) - return dpiDataBuffer__fromOracleTimestampAsDouble(&data->value, - obj->env, error, *value->asTimestamp); - break; - case DPI_ORACLE_TYPE_OBJECT: - if (typeInfo->objectType && - nativeTypeNum == DPI_NATIVE_TYPE_OBJECT) { - void *instance = (typeInfo->objectType->isCollection) ? - *value->asCollection : value->asRaw; - dpiObject *tempObj; - if (dpiObject__allocate(typeInfo->objectType, instance, - indicator, obj, &tempObj, error) < 0) - return DPI_FAILURE; - data->value.asObject = tempObj; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_BOOLEAN: - if (nativeTypeNum == DPI_NATIVE_TYPE_BOOLEAN) { - data->value.asBoolean = *(value->asBoolean); - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_CLOB: - case DPI_ORACLE_TYPE_NCLOB: - case DPI_ORACLE_TYPE_BLOB: - case DPI_ORACLE_TYPE_BFILE: - if (nativeTypeNum == DPI_NATIVE_TYPE_LOB) { - const dpiOracleType *lobType; - void *tempLocator; - dpiLob *tempLob; - lobType = dpiOracleType__getFromNum(typeInfo->oracleTypeNum, - error); - if (dpiLob__allocate(obj->type->conn, lobType, &tempLob, - error) < 0) - return DPI_FAILURE; - tempLocator = tempLob->locator; - tempLob->locator = *(value->asLobLocator); - if (dpiOci__lobLocatorAssign(tempLob, &tempLocator, - error) < 0) { - tempLob->locator = tempLocator; - dpiLob__free(tempLob, error); - return DPI_FAILURE; - } - tempLob->locator = tempLocator; - data->value.asLOB = tempLob; - return DPI_SUCCESS; - } - break; - default: - break; - }; - - return dpiError__set(error, "from Oracle value", - DPI_ERR_UNHANDLED_CONVERSION, valueOracleTypeNum, nativeTypeNum); -} - - -//----------------------------------------------------------------------------- -// dpiObject__toOracleValue() [INTERNAL] -// Convert value from external type to the OCI data type required. -//----------------------------------------------------------------------------- -static int dpiObject__toOracleValue(dpiObject *obj, dpiError *error, - const dpiDataTypeInfo *dataTypeInfo, dpiOracleDataBuffer *buffer, - dpiLob **lob, void **ociValue, int16_t *valueIndicator, - void **objectIndicator, dpiNativeTypeNum nativeTypeNum, dpiData *data) -{ - dpiOracleTypeNum valueOracleTypeNum; - uint32_t handleType; - dpiObject *otherObj; - dpiBytes *bytes; - - // nulls are handled easily - *objectIndicator = NULL; - if (data->isNull) { - *ociValue = NULL; - *valueIndicator = DPI_OCI_IND_NULL; - buffer->asRaw = NULL; - return DPI_SUCCESS; - } - - // convert all other values - *valueIndicator = DPI_OCI_IND_NOTNULL; - valueOracleTypeNum = dataTypeInfo->oracleTypeNum; - switch (valueOracleTypeNum) { - case DPI_ORACLE_TYPE_CHAR: - case DPI_ORACLE_TYPE_NCHAR: - case DPI_ORACLE_TYPE_VARCHAR: - case DPI_ORACLE_TYPE_NVARCHAR: - buffer->asString = NULL; - if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { - bytes = &data->value.asBytes; - if (dpiOci__stringAssignText(obj->env->handle, bytes->ptr, - bytes->length, &buffer->asString, error) < 0) - return DPI_FAILURE; - *ociValue = buffer->asString; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_RAW: - buffer->asRawData = NULL; - if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { - bytes = &data->value.asBytes; - if (dpiOci__rawAssignBytes(obj->env->handle, bytes->ptr, - bytes->length, &buffer->asRawData, error) < 0) - return DPI_FAILURE; - *ociValue = buffer->asRawData; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_NATIVE_INT: - if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) { - buffer->asInt32 = (int32_t) data->value.asInt64; - *ociValue = &buffer->asInt32; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_NUMBER: - *ociValue = &buffer->asNumber; - if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) - return dpiDataBuffer__toOracleNumberFromInteger(&data->value, - error, &buffer->asNumber); - if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) - return dpiDataBuffer__toOracleNumberFromDouble(&data->value, - error, &buffer->asNumber); - if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) - return dpiDataBuffer__toOracleNumberFromText(&data->value, - obj->env, error, &buffer->asNumber); - break; - case DPI_ORACLE_TYPE_NATIVE_FLOAT: - if (nativeTypeNum == DPI_NATIVE_TYPE_FLOAT) { - buffer->asFloat = data->value.asFloat; - *ociValue = &buffer->asFloat; - return DPI_SUCCESS; - } else if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { - buffer->asFloat = (float) data->value.asDouble; - *ociValue = &buffer->asFloat; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_NATIVE_DOUBLE: - if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { - buffer->asDouble = data->value.asDouble; - *ociValue = &buffer->asDouble; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_DATE: - *ociValue = &buffer->asDate; - if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) - return dpiDataBuffer__toOracleDate(&data->value, - &buffer->asDate); - if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) - return dpiDataBuffer__toOracleDateFromDouble(&data->value, - obj->env, error, &buffer->asDate); - break; - case DPI_ORACLE_TYPE_TIMESTAMP: - case DPI_ORACLE_TYPE_TIMESTAMP_TZ: - case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: - buffer->asTimestamp = NULL; - if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP || - nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { - if (valueOracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_LTZ || - nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { - handleType = DPI_OCI_DTYPE_TIMESTAMP_LTZ; - } else if (valueOracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP) { - handleType = DPI_OCI_DTYPE_TIMESTAMP; - } else { - handleType = DPI_OCI_DTYPE_TIMESTAMP_TZ; - } - if (dpiOci__descriptorAlloc(obj->env->handle, - &buffer->asTimestamp, handleType, "allocate timestamp", - error) < 0) - return DPI_FAILURE; - *ociValue = buffer->asTimestamp; - if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) - return dpiDataBuffer__toOracleTimestamp(&data->value, - obj->env, error, buffer->asTimestamp, - (valueOracleTypeNum != DPI_ORACLE_TYPE_TIMESTAMP)); - return dpiDataBuffer__toOracleTimestampFromDouble(&data->value, - obj->env, error, buffer->asTimestamp); - } - break; - case DPI_ORACLE_TYPE_OBJECT: - otherObj = data->value.asObject; - if (nativeTypeNum == DPI_NATIVE_TYPE_OBJECT) { - if (otherObj->type->tdo != dataTypeInfo->objectType->tdo) - return dpiError__set(error, "check type", - DPI_ERR_WRONG_TYPE, otherObj->type->schemaLength, - otherObj->type->schema, otherObj->type->nameLength, - otherObj->type->name, - dataTypeInfo->objectType->schemaLength, - dataTypeInfo->objectType->schema, - dataTypeInfo->objectType->nameLength, - dataTypeInfo->objectType->name); - *ociValue = otherObj->instance; - *objectIndicator = otherObj->indicator; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_BOOLEAN: - if (nativeTypeNum == DPI_NATIVE_TYPE_BOOLEAN) { - buffer->asBoolean = data->value.asBoolean; - *ociValue = &buffer->asBoolean; - return DPI_SUCCESS; - } - break; - case DPI_ORACLE_TYPE_CLOB: - case DPI_ORACLE_TYPE_NCLOB: - case DPI_ORACLE_TYPE_BLOB: - case DPI_ORACLE_TYPE_BFILE: - buffer->asLobLocator = NULL; - if (nativeTypeNum == DPI_NATIVE_TYPE_LOB) { - *ociValue = data->value.asLOB->locator; - return DPI_SUCCESS; - } else if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { - const dpiOracleType *lobType; - lobType = dpiOracleType__getFromNum(valueOracleTypeNum, error); - if (dpiLob__allocate(obj->type->conn, lobType, lob, error) < 0) - return DPI_FAILURE; - bytes = &data->value.asBytes; - if (dpiLob__setFromBytes(*lob, bytes->ptr, bytes->length, - error) < 0) - return DPI_FAILURE; - buffer->asLobLocator = (*lob)->locator; - *ociValue = (*lob)->locator; - return DPI_SUCCESS; - } - break; - - default: - break; - } - - return dpiError__set(error, "to Oracle value", - DPI_ERR_UNHANDLED_CONVERSION, valueOracleTypeNum, nativeTypeNum); -} - - -//----------------------------------------------------------------------------- -// dpiObject_addRef() [PUBLIC] -// Add a reference to the object. -//----------------------------------------------------------------------------- -int dpiObject_addRef(dpiObject *obj) -{ - return dpiGen__addRef(obj, DPI_HTYPE_OBJECT, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiObject_appendElement() [PUBLIC] -// Append an element to the collection. -//----------------------------------------------------------------------------- -int dpiObject_appendElement(dpiObject *obj, dpiNativeTypeNum nativeTypeNum, - dpiData *data) -{ - dpiOracleDataBuffer valueBuffer; - int16_t scalarValueIndicator; - dpiLob *lob = NULL; - void *indicator; - dpiError error; - void *ociValue; - int status; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(obj, data) - status = dpiObject__toOracleValue(obj, &error, &obj->type->elementTypeInfo, - &valueBuffer, &lob, &ociValue, &scalarValueIndicator, - (void**) &indicator, nativeTypeNum, data); - if (status == DPI_SUCCESS) { - if (!indicator) - indicator = &scalarValueIndicator; - status = dpiOci__collAppend(obj->type->conn, ociValue, indicator, - obj->instance, &error); - } - dpiObject__clearOracleValue(obj, &error, &valueBuffer, lob, - obj->type->elementTypeInfo.oracleTypeNum); - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_copy() [PUBLIC] -// Create a copy of the object and return it. Return NULL upon error. -//----------------------------------------------------------------------------- -int dpiObject_copy(dpiObject *obj, dpiObject **copiedObj) -{ - dpiObject *tempObj; - dpiError error; - - if (dpiObject__check(obj, __func__, &error) < 0) - return DPI_FAILURE; - DPI_CHECK_PTR_NOT_NULL(obj, copiedObj) - if (dpiObject__allocate(obj->type, NULL, NULL, NULL, &tempObj, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - if (dpiOci__objectCopy(tempObj, obj->instance, obj->indicator, - &error) < 0) { - dpiObject__free(tempObj, &error); - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - } - *copiedObj = tempObj; - return dpiGen__endPublicFn(obj, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_deleteElementByIndex() [PUBLIC] -// Delete the element at the specified index in the collection. -//----------------------------------------------------------------------------- -int dpiObject_deleteElementByIndex(dpiObject *obj, int32_t index) -{ - dpiError error; - int status; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - status = dpiOci__tableDelete(obj, index, &error); - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_getAttributeValue() [PUBLIC] -// Get the value of the given attribute from the object. -//----------------------------------------------------------------------------- -int dpiObject_getAttributeValue(dpiObject *obj, dpiObjectAttr *attr, - dpiNativeTypeNum nativeTypeNum, dpiData *data) -{ - int16_t scalarValueIndicator; - void *valueIndicator, *tdo; - dpiOracleData value; - dpiError error; - int status; - - // validate parameters - if (dpiObject__check(obj, __func__, &error) < 0) - return DPI_FAILURE; - DPI_CHECK_PTR_NOT_NULL(obj, data) - if (dpiGen__checkHandle(attr, DPI_HTYPE_OBJECT_ATTR, "get attribute value", - &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - if (attr->belongsToType->tdo != obj->type->tdo) { - dpiError__set(&error, "get attribute value", DPI_ERR_WRONG_ATTR, - attr->nameLength, attr->name, obj->type->schemaLength, - obj->type->schema, obj->type->nameLength, obj->type->name); - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - } - - // get attribute value - if (dpiOci__objectGetAttr(obj, attr, &scalarValueIndicator, - &valueIndicator, &value.asRaw, &tdo, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - - // determine the proper null indicator - if (!valueIndicator) - valueIndicator = &scalarValueIndicator; - - // check to see if type is supported - if (!attr->typeInfo.oracleTypeNum) { - dpiError__set(&error, "get attribute value", - DPI_ERR_UNHANDLED_DATA_TYPE, attr->typeInfo.ociTypeCode); - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - } - - // convert to output data format - status = dpiObject__fromOracleValue(obj, &error, &attr->typeInfo, &value, - (int16_t*) valueIndicator, nativeTypeNum, data); - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_getElementExistsByIndex() [PUBLIC] -// Return boolean indicating if an element exists in the collection at the -// specified index. -//----------------------------------------------------------------------------- -int dpiObject_getElementExistsByIndex(dpiObject *obj, int32_t index, - int *exists) -{ - dpiError error; - int status; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(obj, exists) - status = dpiOci__tableExists(obj, index, exists, &error); - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_getElementValueByIndex() [PUBLIC] -// Return the element at the given index in the collection. -//----------------------------------------------------------------------------- -int dpiObject_getElementValueByIndex(dpiObject *obj, int32_t index, - dpiNativeTypeNum nativeTypeNum, dpiData *data) -{ - dpiOracleData value; - int exists, status; - void *indicator; - dpiError error; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(obj, data) - if (dpiOci__collGetElem(obj->type->conn, obj->instance, index, &exists, - &value.asRaw, &indicator, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - if (!exists) { - dpiError__set(&error, "get element value", DPI_ERR_INVALID_INDEX, - index); - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - } - status = dpiObject__fromOracleValue(obj, &error, - &obj->type->elementTypeInfo, &value, (int16_t*) indicator, - nativeTypeNum, data); - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_getFirstIndex() [PUBLIC] -// Return the index of the first entry in the collection. -//----------------------------------------------------------------------------- -int dpiObject_getFirstIndex(dpiObject *obj, int32_t *index, int *exists) -{ - dpiError error; - int32_t size; - int status; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(obj, index) - DPI_CHECK_PTR_NOT_NULL(obj, exists) - if (dpiOci__tableSize(obj, &size, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - *exists = (size != 0); - if (*exists) - status = dpiOci__tableFirst(obj, index, &error); - else status = DPI_SUCCESS; - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_getLastIndex() [PUBLIC] -// Return the index of the last entry in the collection. -//----------------------------------------------------------------------------- -int dpiObject_getLastIndex(dpiObject *obj, int32_t *index, int *exists) -{ - dpiError error; - int32_t size; - int status; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(obj, index) - DPI_CHECK_PTR_NOT_NULL(obj, exists) - if (dpiOci__tableSize(obj, &size, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - *exists = (size != 0); - if (*exists) - status = dpiOci__tableLast(obj, index, &error); - else status = DPI_SUCCESS; - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_getNextIndex() [PUBLIC] -// Return the index of the next entry in the collection following the index -// specified. If there is no next entry, exists is set to 0. -//----------------------------------------------------------------------------- -int dpiObject_getNextIndex(dpiObject *obj, int32_t index, int32_t *nextIndex, - int *exists) -{ - dpiError error; - int status; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(obj, nextIndex) - DPI_CHECK_PTR_NOT_NULL(obj, exists) - status = dpiOci__tableNext(obj, index, nextIndex, exists, &error); - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_getPrevIndex() [PUBLIC] -// Return the index of the previous entry in the collection preceding the -// index specified. If there is no previous entry, exists is set to 0. -//----------------------------------------------------------------------------- -int dpiObject_getPrevIndex(dpiObject *obj, int32_t index, int32_t *prevIndex, - int *exists) -{ - dpiError error; - int status; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(obj, prevIndex) - DPI_CHECK_PTR_NOT_NULL(obj, exists) - status = dpiOci__tablePrev(obj, index, prevIndex, exists, &error); - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_getSize() [PUBLIC] -// Return the size of the collection. -//----------------------------------------------------------------------------- -int dpiObject_getSize(dpiObject *obj, int32_t *size) -{ - dpiError error; - int status; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(obj, size) - status = dpiOci__collSize(obj->type->conn, obj->instance, size, &error); - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_release() [PUBLIC] -// Release a reference to the object. -//----------------------------------------------------------------------------- -int dpiObject_release(dpiObject *obj) -{ - return dpiGen__release(obj, DPI_HTYPE_OBJECT, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiObject_setAttributeValue() [PUBLIC] -// Create a copy of the object and return it. Return NULL upon error. -//----------------------------------------------------------------------------- -int dpiObject_setAttributeValue(dpiObject *obj, dpiObjectAttr *attr, - dpiNativeTypeNum nativeTypeNum, dpiData *data) -{ - void *valueIndicator, *ociValue; - dpiOracleDataBuffer valueBuffer; - int16_t scalarValueIndicator; - dpiLob *lob = NULL; - dpiError error; - int status; - - // validate parameters - if (dpiObject__check(obj, __func__, &error) < 0) - return DPI_FAILURE; - DPI_CHECK_PTR_NOT_NULL(obj, data) - if (dpiGen__checkHandle(attr, DPI_HTYPE_OBJECT_ATTR, "set attribute value", - &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - if (attr->belongsToType->tdo != obj->type->tdo) { - dpiError__set(&error, "set attribute value", DPI_ERR_WRONG_ATTR, - attr->nameLength, attr->name, obj->type->schemaLength, - obj->type->schema, obj->type->nameLength, obj->type->name); - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - } - - // check to see if type is supported - if (!attr->typeInfo.oracleTypeNum) { - dpiError__set(&error, "get attribute value", - DPI_ERR_UNHANDLED_DATA_TYPE, attr->typeInfo.ociTypeCode); - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - } - - // convert to input data format - status = dpiObject__toOracleValue(obj, &error, &attr->typeInfo, - &valueBuffer, &lob, &ociValue, &scalarValueIndicator, - &valueIndicator, nativeTypeNum, data); - - // set attribute value - if (status == DPI_SUCCESS) - status = dpiOci__objectSetAttr(obj, attr, scalarValueIndicator, - valueIndicator, ociValue, &error); - dpiObject__clearOracleValue(obj, &error, &valueBuffer, lob, - attr->typeInfo.oracleTypeNum); - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_setElementValueByIndex() [PUBLIC] -// Set the element at the specified index to the given value. -//----------------------------------------------------------------------------- -int dpiObject_setElementValueByIndex(dpiObject *obj, int32_t index, - dpiNativeTypeNum nativeTypeNum, dpiData *data) -{ - dpiOracleDataBuffer valueBuffer; - int16_t scalarValueIndicator; - dpiLob *lob = NULL; - void *indicator; - dpiError error; - void *ociValue; - int status; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(obj, data) - status = dpiObject__toOracleValue(obj, &error, &obj->type->elementTypeInfo, - &valueBuffer, &lob, &ociValue, &scalarValueIndicator, - (void**) &indicator, nativeTypeNum, data); - if (status == DPI_SUCCESS) { - if (!indicator) - indicator = &scalarValueIndicator; - status = dpiOci__collAssignElem(obj->type->conn, index, ociValue, - indicator, obj->instance, &error); - } - dpiObject__clearOracleValue(obj, &error, &valueBuffer, lob, - obj->type->elementTypeInfo.oracleTypeNum); - return dpiGen__endPublicFn(obj, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObject_trim() [PUBLIC] -// Trim a number of elements from the end of the collection. -//----------------------------------------------------------------------------- -int dpiObject_trim(dpiObject *obj, uint32_t numToTrim) -{ - dpiError error; - int status; - - if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) - return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); - status = dpiOci__collTrim(obj->type->conn, numToTrim, obj->instance, - &error); - return dpiGen__endPublicFn(obj, status, &error); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiObjectAttr.c b/vendor/github.com/godror/godror/odpi/src/dpiObjectAttr.c deleted file mode 100644 index 45d623ef573..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiObjectAttr.c +++ /dev/null @@ -1,114 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiObjectAttr.c -// Implementation of object attributes. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiObjectAttr__allocate() [INTERNAL] -// Allocate and initialize an object attribute structure. -//----------------------------------------------------------------------------- -int dpiObjectAttr__allocate(dpiObjectType *objType, void *param, - dpiObjectAttr **attr, dpiError *error) -{ - dpiObjectAttr *tempAttr; - - // allocate and assign main reference to the type this attribute belongs to - *attr = NULL; - if (dpiGen__allocate(DPI_HTYPE_OBJECT_ATTR, objType->env, - (void**) &tempAttr, error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(objType, error, 1); - tempAttr->belongsToType = objType; - - // determine the name of the attribute - if (dpiUtils__getAttrStringWithDup("get name", param, DPI_OCI_DTYPE_PARAM, - DPI_OCI_ATTR_NAME, &tempAttr->name, &tempAttr->nameLength, - error) < 0) { - dpiObjectAttr__free(tempAttr, error); - return DPI_FAILURE; - } - - // determine type information of the attribute - if (dpiOracleType__populateTypeInfo(objType->conn, param, - DPI_OCI_DTYPE_PARAM, &tempAttr->typeInfo, error) < 0) { - dpiObjectAttr__free(tempAttr, error); - return DPI_FAILURE; - } - - *attr = tempAttr; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiObjectAttr__free() [INTERNAL] -// Free the memory for an object attribute. -//----------------------------------------------------------------------------- -void dpiObjectAttr__free(dpiObjectAttr *attr, dpiError *error) -{ - if (attr->belongsToType) { - dpiGen__setRefCount(attr->belongsToType, error, -1); - attr->belongsToType = NULL; - } - if (attr->typeInfo.objectType) { - dpiGen__setRefCount(attr->typeInfo.objectType, error, -1); - attr->typeInfo.objectType = NULL; - } - if (attr->name) { - dpiUtils__freeMemory((void*) attr->name); - attr->name = NULL; - } - dpiUtils__freeMemory(attr); -} - - -//----------------------------------------------------------------------------- -// dpiObjectAttr_addRef() [PUBLIC] -// Add a reference to the object attribute. -//----------------------------------------------------------------------------- -int dpiObjectAttr_addRef(dpiObjectAttr *attr) -{ - return dpiGen__addRef(attr, DPI_HTYPE_OBJECT_ATTR, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiObjectAttr_getInfo() [PUBLIC] -// Return information about the attribute to the caller. -//----------------------------------------------------------------------------- -int dpiObjectAttr_getInfo(dpiObjectAttr *attr, dpiObjectAttrInfo *info) -{ - dpiError error; - - if (dpiGen__startPublicFn(attr, DPI_HTYPE_OBJECT_ATTR, __func__, - &error) < 0) - return dpiGen__endPublicFn(attr, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(attr, info) - info->name = attr->name; - info->nameLength = attr->nameLength; - info->typeInfo = attr->typeInfo; - return dpiGen__endPublicFn(attr, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObjectAttr_release() [PUBLIC] -// Release a reference to the object attribute. -//----------------------------------------------------------------------------- -int dpiObjectAttr_release(dpiObjectAttr *attr) -{ - return dpiGen__release(attr, DPI_HTYPE_OBJECT_ATTR, __func__); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiObjectType.c b/vendor/github.com/godror/godror/odpi/src/dpiObjectType.c deleted file mode 100644 index fbb2cf240c8..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiObjectType.c +++ /dev/null @@ -1,344 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiObjectType.c -// Implementation of object types. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -// forward declarations of internal functions only used in this file -static int dpiObjectType__init(dpiObjectType *objType, void *param, - uint32_t nameAttribute, dpiError *error); - - -//----------------------------------------------------------------------------- -// dpiObjectType__allocate() [INTERNAL] -// Allocate and initialize an object type structure. -//----------------------------------------------------------------------------- -int dpiObjectType__allocate(dpiConn *conn, void *param, - uint32_t nameAttribute, dpiObjectType **objType, dpiError *error) -{ - dpiObjectType *tempObjType; - - // create structure and retain reference to connection - *objType = NULL; - if (dpiGen__allocate(DPI_HTYPE_OBJECT_TYPE, conn->env, - (void**) &tempObjType, error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(conn, error, 1); - tempObjType->conn = conn; - - // perform initialization - if (dpiObjectType__init(tempObjType, param, nameAttribute, error) < 0) { - dpiObjectType__free(tempObjType, error); - return DPI_FAILURE; - } - - *objType = tempObjType; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiObjectType__check() [INTERNAL] -// Validate that the connection from which the object type was created is -// still connected and issue an error if it is not. -//----------------------------------------------------------------------------- -static int dpiObjectType__check(dpiObjectType *objType, const char *fnName, - dpiError *error) -{ - if (dpiGen__startPublicFn(objType, DPI_HTYPE_OBJECT_TYPE, fnName, - error) < 0) - return DPI_FAILURE; - return dpiConn__checkConnected(objType->conn, error); -} - - -//----------------------------------------------------------------------------- -// dpiObjectType__describe() [INTERNAL] -// Describe the object type and store information about it. Note that a -// separate call to OCIDescribeAny() is made in order to support nested types; -// an illegal attribute value is returned if this is not done. -//----------------------------------------------------------------------------- -static int dpiObjectType__describe(dpiObjectType *objType, - void *describeHandle, dpiError *error) -{ - void *collectionParam, *param; - uint16_t typeCode; - - // describe the type - if (dpiOci__describeAny(objType->conn, objType->tdo, 0, DPI_OCI_OTYPE_PTR, - describeHandle, error) < 0) - return DPI_FAILURE; - - // get top level parameter descriptor - if (dpiOci__attrGet(describeHandle, DPI_OCI_HTYPE_DESCRIBE, ¶m, 0, - DPI_OCI_ATTR_PARAM, "get top level parameter", error) < 0) - return DPI_FAILURE; - - // determine type code - if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, &typeCode, 0, - DPI_OCI_ATTR_TYPECODE, "get type code", error) < 0) - return DPI_FAILURE; - objType->typeCode = typeCode; - - // determine the number of attributes - if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, - (void*) &objType->numAttributes, 0, DPI_OCI_ATTR_NUM_TYPE_ATTRS, - "get number of attributes", error) < 0) - return DPI_FAILURE; - - // if a collection, need to determine the element type - if (typeCode == DPI_SQLT_NCO) { - objType->isCollection = 1; - - // acquire collection parameter descriptor - if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, &collectionParam, 0, - DPI_OCI_ATTR_COLLECTION_ELEMENT, "get collection descriptor", - error) < 0) - return DPI_FAILURE; - - // determine type of element - if (dpiOracleType__populateTypeInfo(objType->conn, collectionParam, - DPI_OCI_DTYPE_PARAM, &objType->elementTypeInfo, error) < 0) - return DPI_FAILURE; - - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiObjectType__free() [INTERNAL] -// Free the memory for an object type. -//----------------------------------------------------------------------------- -void dpiObjectType__free(dpiObjectType *objType, dpiError *error) -{ - if (objType->conn) { - dpiGen__setRefCount(objType->conn, error, -1); - objType->conn = NULL; - } - if (objType->elementTypeInfo.objectType) { - dpiGen__setRefCount(objType->elementTypeInfo.objectType, error, -1); - objType->elementTypeInfo.objectType = NULL; - } - if (objType->schema) { - dpiUtils__freeMemory((void*) objType->schema); - objType->schema = NULL; - } - if (objType->name) { - dpiUtils__freeMemory((void*) objType->name); - objType->name = NULL; - } - dpiUtils__freeMemory(objType); -} - - -//----------------------------------------------------------------------------- -// dpiObjectType__init() [INTERNAL] -// Initialize the object type. -//----------------------------------------------------------------------------- -static int dpiObjectType__init(dpiObjectType *objType, void *param, - uint32_t nameAttribute, dpiError *error) -{ - void *describeHandle; - void *tdoReference; - - // determine the schema of the type - if (dpiUtils__getAttrStringWithDup("get schema", param, - DPI_OCI_DTYPE_PARAM, DPI_OCI_ATTR_SCHEMA_NAME, &objType->schema, - &objType->schemaLength, error) < 0) - return DPI_FAILURE; - - // determine the name of the type - if (dpiUtils__getAttrStringWithDup("get name", param, DPI_OCI_DTYPE_PARAM, - nameAttribute, &objType->name, &objType->nameLength, error) < 0) - return DPI_FAILURE; - - // retrieve TDO of the parameter and pin it in the cache - if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, (void*) &tdoReference, 0, - DPI_OCI_ATTR_REF_TDO, "get TDO reference", error) < 0) - return DPI_FAILURE; - if (dpiOci__objectPin(objType->env->handle, tdoReference, &objType->tdo, - error) < 0) - return DPI_FAILURE; - - // acquire a describe handle - if (dpiOci__handleAlloc(objType->env->handle, &describeHandle, - DPI_OCI_HTYPE_DESCRIBE, "allocate describe handle", error) < 0) - return DPI_FAILURE; - - // describe the type - if (dpiObjectType__describe(objType, describeHandle, error) < 0) { - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return DPI_FAILURE; - } - - // free the describe handle - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiObjectType__isXmlType() [INTERNAL] -// Returns a boolean indicating if the object type in question refers to the -// type SYS.XMLTYPE. -//----------------------------------------------------------------------------- -int dpiObjectType__isXmlType(dpiObjectType *objType) -{ - static const char *schema = "SYS", *name = "XMLTYPE"; - size_t schemaLength, nameLength; - - schemaLength = strlen(schema); - nameLength = strlen(name); - return (objType->schemaLength == schemaLength && - strncmp(objType->schema, schema, schemaLength) == 0 && - objType->nameLength == nameLength && - strncmp(objType->name, name, nameLength) == 0); -} - - -//----------------------------------------------------------------------------- -// dpiObjectType_addRef() [PUBLIC] -// Add a reference to the object type. -//----------------------------------------------------------------------------- -int dpiObjectType_addRef(dpiObjectType *objType) -{ - return dpiGen__addRef(objType, DPI_HTYPE_OBJECT_TYPE, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiObjectType_createObject() [PUBLIC] -// Create a new object of the specified type and return it. Return NULL on -// error. -//----------------------------------------------------------------------------- -int dpiObjectType_createObject(dpiObjectType *objType, dpiObject **obj) -{ - dpiError error; - int status; - - // validate parameters - if (dpiObjectType__check(objType, __func__, &error) < 0) - return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(objType, obj) - status = dpiObject__allocate(objType, NULL, NULL, NULL, obj, &error); - return dpiGen__endPublicFn(objType, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObjectType_getAttributes() [PUBLIC] -// Get the attributes for the object type in the provided array. -//----------------------------------------------------------------------------- -int dpiObjectType_getAttributes(dpiObjectType *objType, uint16_t numAttributes, - dpiObjectAttr **attributes) -{ - void *topLevelParam, *attrListParam, *attrParam, *describeHandle; - dpiError error; - uint16_t i; - - // validate object type and the number of attributes - if (dpiObjectType__check(objType, __func__, &error) < 0) - return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(objType, attributes) - if (numAttributes < objType->numAttributes) { - dpiError__set(&error, "get attributes", DPI_ERR_ARRAY_SIZE_TOO_SMALL, - numAttributes); - return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); - } - if (numAttributes == 0) - return dpiGen__endPublicFn(objType, DPI_SUCCESS, &error); - - // acquire a describe handle - if (dpiOci__handleAlloc(objType->env->handle, &describeHandle, - DPI_OCI_HTYPE_DESCRIBE, "allocate describe handle", &error) < 0) - return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); - - // describe the type - if (dpiOci__describeAny(objType->conn, objType->tdo, 0, DPI_OCI_OTYPE_PTR, - describeHandle, &error) < 0) { - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); - } - - // get the top level parameter descriptor - if (dpiOci__attrGet(describeHandle, DPI_OCI_HTYPE_DESCRIBE, &topLevelParam, - 0, DPI_OCI_ATTR_PARAM, "get top level param", &error) < 0) { - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); - } - - // get the attribute list parameter descriptor - if (dpiOci__attrGet(topLevelParam, DPI_OCI_DTYPE_PARAM, - (void*) &attrListParam, 0, DPI_OCI_ATTR_LIST_TYPE_ATTRS, - "get attr list param", &error) < 0) { - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); - } - - // create attribute structure for each attribute - for (i = 0; i < objType->numAttributes; i++) { - if (dpiOci__paramGet(attrListParam, DPI_OCI_DTYPE_PARAM, &attrParam, - (uint32_t) i + 1, "get attribute param", &error) < 0) { - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); - } - if (dpiObjectAttr__allocate(objType, attrParam, &attributes[i], - &error) < 0) { - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); - } - } - - // free the describe handle - dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); - - return dpiGen__endPublicFn(objType, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObjectType_getInfo() [PUBLIC] -// Return information about the object type. -//----------------------------------------------------------------------------- -int dpiObjectType_getInfo(dpiObjectType *objType, dpiObjectTypeInfo *info) -{ - dpiError error; - - if (dpiGen__startPublicFn(objType, DPI_HTYPE_OBJECT_TYPE, __func__, - &error) < 0) - return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(objType, info) - info->name = objType->name; - info->nameLength = objType->nameLength; - info->schema = objType->schema; - info->schemaLength = objType->schemaLength; - info->isCollection = objType->isCollection; - info->elementTypeInfo = objType->elementTypeInfo; - info->numAttributes = objType->numAttributes; - return dpiGen__endPublicFn(objType, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiObjectType_release() [PUBLIC] -// Release a reference to the object type. -//----------------------------------------------------------------------------- -int dpiObjectType_release(dpiObjectType *objType) -{ - return dpiGen__release(objType, DPI_HTYPE_OBJECT_TYPE, __func__); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiOci.c b/vendor/github.com/godror/godror/odpi/src/dpiOci.c deleted file mode 100644 index c731324cb48..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiOci.c +++ /dev/null @@ -1,3823 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiOci.c -// Link to OCI using dynamic linking. The OCI library (11.2+) is loaded -// dynamically and a function table kept for the functions that are used by -// DPI. This function table is populated as functions are used and permits use -// of all versions of OCI from one driver. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -// forward declarations of internal functions only used in this file -static void *dpiOci__allocateMem(void *unused, size_t size); -static void dpiOci__freeMem(void *unused, void *ptr); -static int dpiOci__loadLib(dpiError *error); -static int dpiOci__loadLibValidate(dpiError *error); -static int dpiOci__loadSymbol(const char *symbolName, void **symbol, - dpiError *error); -static void *dpiOci__reallocMem(void *unused, void *ptr, size_t newSize); - - -// macro to simplify code for loading each symbol -#define DPI_OCI_LOAD_SYMBOL(symbolName, symbol) \ - if (!symbol && dpiOci__loadSymbol(symbolName, (void**) &symbol, \ - error) < 0) \ - return DPI_FAILURE; - -// macro to ensure that an error handle is available -#define DPI_OCI_ENSURE_ERROR_HANDLE(error) \ - if (!error->handle && dpiError__initHandle(error) < 0) \ - return DPI_FAILURE; - -// macros to simplify code for checking results of OCI calls -#define DPI_OCI_ERROR_OCCURRED(status) \ - (status != DPI_OCI_SUCCESS && status != DPI_OCI_SUCCESS_WITH_INFO) -#define DPI_OCI_CHECK_AND_RETURN(error, status, conn, action) \ - if (DPI_OCI_ERROR_OCCURRED(status)) \ - return dpiError__setFromOCI(error, status, conn, action); \ - return DPI_SUCCESS; - - -// typedefs for all OCI functions used by ODPI-C -typedef int (*dpiOciFnType__aqDeq)(void *svchp, void *errhp, - const char *queue_name, void *deqopt, void *msgprop, void *payload_tdo, - void **payload, void **payload_ind, void **msgid, uint32_t flags); -typedef int (*dpiOciFnType__aqDeqArray)(void *svchp, void *errhp, - const char *queue_name, void *deqopt, uint32_t *iters, void **msgprop, - void *payload_tdo, void **payload, void **payload_ind, void **msgid, - void *ctxp, void *deqcbfp, uint32_t flags); -typedef int (*dpiOciFnType__aqEnq)(void *svchp, void *errhp, - const char *queue_name, void *enqopt, void *msgprop, void *payload_tdo, - void **payload, void **payload_ind, void **msgid, uint32_t flags); -typedef int (*dpiOciFnType__aqEnqArray)(void *svchp, void *errhp, - const char *queue_name, void *enqopt, uint32_t *iters, void **msgprop, - void *payload_tdo, void **payload, void **payload_ind, void **msgid, - void *ctxp, void *enqcbfp, uint32_t flags); -typedef int (*dpiOciFnType__arrayDescriptorAlloc)(const void *parenth, - void **descpp, const uint32_t type, uint32_t array_size, - const size_t xtramem_sz, void **usrmempp); -typedef int (*dpiOciFnType__arrayDescriptorFree)(void **descp, - const uint32_t type); -typedef int (*dpiOciFnType__attrGet)(const void *trgthndlp, - uint32_t trghndltyp, void *attributep, uint32_t *sizep, - uint32_t attrtype, void *errhp); -typedef int (*dpiOciFnType__attrSet)(void *trgthndlp, uint32_t trghndltyp, - void *attributep, uint32_t size, uint32_t attrtype, void *errhp); -typedef int (*dpiOciFnType__bindByName)(void *stmtp, void **bindp, void *errhp, - const char *placeholder, int32_t placeh_len, void *valuep, - int32_t value_sz, uint16_t dty, void *indp, uint16_t *alenp, - uint16_t *rcodep, uint32_t maxarr_len, uint32_t *curelep, - uint32_t mode); -typedef int (*dpiOciFnType__bindByName2)(void *stmtp, void **bindp, - void *errhp, const char *placeholder, int32_t placeh_len, void *valuep, - int64_t value_sz, uint16_t dty, void *indp, uint32_t *alenp, - uint16_t *rcodep, uint32_t maxarr_len, uint32_t *curelep, - uint32_t mode); -typedef int (*dpiOciFnType__bindByPos)(void *stmtp, void **bindp, void *errhp, - uint32_t position, void *valuep, int32_t value_sz, uint16_t dty, - void *indp, uint16_t *alenp, uint16_t *rcodep, uint32_t maxarr_len, - uint32_t *curelep, uint32_t mode); -typedef int (*dpiOciFnType__bindByPos2)(void *stmtp, void **bindp, void *errhp, - uint32_t position, void *valuep, int64_t value_sz, uint16_t dty, - void *indp, uint32_t *alenp, uint16_t *rcodep, uint32_t maxarr_len, - uint32_t *curelep, uint32_t mode); -typedef int (*dpiOciFnType__bindDynamic)(void *bindp, void *errhp, void *ictxp, - void *icbfp, void *octxp, void *ocbfp); -typedef int (*dpiOciFnType__bindObject)(void *bindp, void *errhp, - const void *type, void **pgvpp, uint32_t *pvszsp, void **indpp, - uint32_t *indszp); -typedef int (*dpiOciFnType__break)(void *hndlp, void *errhp); -typedef void (*dpiOciFnType__clientVersion)(int *major_version, - int *minor_version, int *update_num, int *patch_num, - int *port_update_num); -typedef int (*dpiOciFnType__collAppend)(void *env, void *err, const void *elem, - const void *elemind, void *coll); -typedef int (*dpiOciFnType__collAssignElem)(void *env, void *err, - int32_t index, const void *elem, const void *elemind, void *coll); -typedef int (*dpiOciFnType__collGetElem)(void *env, void *err, - const void *coll, int32_t index, int *exists, void **elem, - void **elemind); -typedef int (*dpiOciFnType__collSize)(void *env, void *err, const void *coll, - int32_t *size); -typedef int (*dpiOciFnType__collTrim)(void *env, void *err, int32_t trim_num, - void *coll); -typedef int (*dpiOciFnType__contextGetValue)(void *hdl, void *err, - const char *key, uint8_t keylen, void **ctx_value); -typedef int (*dpiOciFnType__contextSetValue)(void *hdl, void *err, - uint16_t duration, const char *key, uint8_t keylen, void *ctx_value); -typedef int (*dpiOciFnType__dateTimeConstruct)(void *hndl, void *err, - void *datetime, int16_t yr, uint8_t mnth, uint8_t dy, uint8_t hr, - uint8_t mm, uint8_t ss, uint32_t fsec, const char *tz, - size_t tzLength); -typedef int (*dpiOciFnType__dateTimeConvert)(void *hndl, void *err, - void *indate, void *outdate); -typedef int (*dpiOciFnType__dateTimeGetDate)(void *hndl, void *err, - const void *date, int16_t *yr, uint8_t *mnth, uint8_t *dy); -typedef int (*dpiOciFnType__dateTimeGetTime)(void *hndl, void *err, - void *datetime, uint8_t *hr, uint8_t *mm, uint8_t *ss, uint32_t *fsec); -typedef int (*dpiOciFnType__dateTimeGetTimeZoneOffset)(void *hndl, void *err, - const void *datetime, int8_t *hr, int8_t *mm); -typedef int (*dpiOciFnType__dateTimeIntervalAdd)(void *hndl, void *err, - void *datetime, void *inter, void *outdatetime); -typedef int (*dpiOciFnType__dateTimeSubtract)(void *hndl, void *err, - void *indate1, void *indate2, void *inter); -typedef int (*dpiOciFnType__dbShutdown)(void *svchp, void *errhp, void *admhp, - uint32_t mode); -typedef int (*dpiOciFnType__dbStartup)(void *svchp, void *errhp, void *admhp, - uint32_t mode, uint32_t flags); -typedef int (*dpiOciFnType__defineByPos)(void *stmtp, void **defnp, - void *errhp, uint32_t position, void *valuep, int32_t value_sz, - uint16_t dty, void *indp, uint16_t *rlenp, uint16_t *rcodep, - uint32_t mode); -typedef int (*dpiOciFnType__defineByPos2)(void *stmtp, void **defnp, - void *errhp, uint32_t position, void *valuep, uint64_t value_sz, - uint16_t dty, void *indp, uint32_t *rlenp, uint16_t *rcodep, - uint32_t mode); -typedef int (*dpiOciFnType__defineDynamic)(void *defnp, void *errhp, - void *octxp, void *ocbfp); -typedef int (*dpiOciFnType__defineObject)(void *defnp, void *errhp, - const void *type, void **pgvpp, uint32_t *pvszsp, void **indpp, - uint32_t *indszp); -typedef int (*dpiOciFnType__describeAny)(void *svchp, void *errhp, - void *objptr, uint32_t objnm_len, uint8_t objptr_typ, - uint8_t info_level, uint8_t objtyp, void *dschp); -typedef int (*dpiOciFnType__descriptorAlloc)(const void *parenth, - void **descpp, const uint32_t type, const size_t xtramem_sz, - void **usrmempp); -typedef int (*dpiOciFnType__descriptorFree)(void *descp, const uint32_t type); -typedef int (*dpiOciFnType__envNlsCreate)(void **envp, uint32_t mode, - void *ctxp, void *malocfp, void *ralocfp, void *mfreefp, - size_t xtramem_sz, void **usrmempp, uint16_t charset, - uint16_t ncharset); -typedef int (*dpiOciFnType__errorGet)(void *hndlp, uint32_t recordno, - char *sqlstate, int32_t *errcodep, char *bufp, uint32_t bufsiz, - uint32_t type); -typedef int (*dpiOciFnType__handleAlloc)(const void *parenth, void **hndlpp, - const uint32_t type, const size_t xtramem_sz, void **usrmempp); -typedef int (*dpiOciFnType__handleFree)(void *hndlp, const uint32_t type); -typedef int (*dpiOciFnType__intervalGetDaySecond)(void *hndl, void *err, - int32_t *dy, int32_t *hr, int32_t *mm, int32_t *ss, int32_t *fsec, - const void *result); -typedef int (*dpiOciFnType__intervalGetYearMonth)(void *hndl, void *err, - int32_t *yr, int32_t *mnth, const void *result); -typedef int (*dpiOciFnType__intervalSetDaySecond)(void *hndl, void *err, - int32_t dy, int32_t hr, int32_t mm, int32_t ss, int32_t fsec, - void *result); -typedef int (*dpiOciFnType__intervalSetYearMonth)(void *hndl, void *err, - int32_t yr, int32_t mnth, void *result); -typedef int (*dpiOciFnType__lobClose)(void *svchp, void *errhp, void *locp); -typedef int (*dpiOciFnType__lobCreateTemporary)(void *svchp, void *errhp, - void *locp, uint16_t csid, uint8_t csfrm, uint8_t lobtype, int cache, - uint16_t duration); -typedef int (*dpiOciFnType__lobFileExists)(void *svchp, void *errhp, - void *filep, int *flag); -typedef int (*dpiOciFnType__lobFileGetName)(void *envhp, void *errhp, - const void *filep, char *dir_alias, uint16_t *d_length, char *filename, - uint16_t *f_length); -typedef int (*dpiOciFnType__lobFileSetName)(void *envhp, void *errhp, - void **filepp, const char *dir_alias, uint16_t d_length, - const char *filename, uint16_t f_length); -typedef int (*dpiOciFnType__lobFreeTemporary)(void *svchp, void *errhp, - void *locp); -typedef int (*dpiOciFnType__lobGetChunkSize)(void *svchp, void *errhp, - void *locp, uint32_t *chunksizep); -typedef int (*dpiOciFnType__lobGetLength2)(void *svchp, void *errhp, - void *locp, uint64_t *lenp); -typedef int (*dpiOciFnType__lobIsOpen)(void *svchp, void *errhp, void *locp, - int *flag); -typedef int (*dpiOciFnType__lobIsTemporary)(void *envp, void *errhp, - void *locp, int *is_temporary); -typedef int (*dpiOciFnType__lobLocatorAssign)(void *svchp, void *errhp, - const void *src_locp, void **dst_locpp); -typedef int (*dpiOciFnType__lobOpen)(void *svchp, void *errhp, void *locp, - uint8_t mode); -typedef int (*dpiOciFnType__lobRead2)(void *svchp, void *errhp, void *locp, - uint64_t *byte_amtp, uint64_t *char_amtp, uint64_t offset, void *bufp, - uint64_t bufl, uint8_t piece, void *ctxp, void *cbfp, uint16_t csid, - uint8_t csfrm); -typedef int (*dpiOciFnType__lobTrim2)(void *svchp, void *errhp, void *locp, - uint64_t newlen); -typedef int (*dpiOciFnType__lobWrite2)(void *svchp, void *errhp, void *locp, - uint64_t *byte_amtp, uint64_t *char_amtp, uint64_t offset, void *bufp, - uint64_t buflen, uint8_t piece, void *ctxp, void *cbfp, uint16_t csid, - uint8_t csfrm); -typedef int (*dpiOciFnType__memoryAlloc)(void *hdl, void *err, void **mem, - uint16_t dur, uint32_t size, uint32_t flags); -typedef int (*dpiOciFnType__memoryFree)(void *hdl, void *err, void *mem); -typedef int (*dpiOciFnType__nlsCharSetConvert)(void *envhp, void *errhp, - uint16_t dstid, void *dstp, size_t dstlen, uint16_t srcid, - const void *srcp, size_t srclen, size_t *rsize); -typedef int (*dpiOciFnType__nlsCharSetIdToName)(void *envhp, char *buf, - size_t buflen, uint16_t id); -typedef uint16_t (*dpiOciFnType__nlsCharSetNameToId)(void *envhp, - const char *name); -typedef int (*dpiOciFnType__nlsEnvironmentVariableGet)(void *val, size_t size, - uint16_t item, uint16_t charset, size_t *rsize); -typedef int (*dpiOciFnType__nlsNameMap)(void *envhp, char *buf, size_t buflen, - const char *srcbuf, uint32_t flag); -typedef int (*dpiOciFnType__nlsNumericInfoGet)(void *envhp, void *errhp, - int32_t *val, uint16_t item); -typedef int (*dpiOciFnType__numberFromInt)(void *err, const void *inum, - unsigned int inum_length, unsigned int inum_s_flag, void *number); -typedef int (*dpiOciFnType__numberFromReal)(void *err, const void *number, - unsigned int rsl_length, void *rsl); -typedef int (*dpiOciFnType__numberToInt)(void *err, const void *number, - unsigned int rsl_length, unsigned int rsl_flag, void *rsl); -typedef int (*dpiOciFnType__numberToReal)(void *err, const void *number, - unsigned int rsl_length, void *rsl); -typedef int (*dpiOciFnType__objectCopy)(void *env, void *err, const void *svc, - void *source, void *null_source, void *target, void *null_target, - void *tdo, uint16_t duration, uint8_t option); -typedef int (*dpiOciFnType__objectFree)(void *env, void *err, void *instance, - uint16_t flags); -typedef int (*dpiOciFnType__objectGetAttr)(void *env, void *err, - void *instance, void *null_struct, void *tdo, const char **names, - const uint32_t *lengths, const uint32_t name_count, - const uint32_t *indexes, const uint32_t index_count, - int16_t *attr_null_status, void **attr_null_struct, void **attr_value, - void **attr_tdo); -typedef int (*dpiOciFnType__objectGetInd)(void *env, void *err, void *instance, - void **null_struct); -typedef int (*dpiOciFnType__objectNew)(void *env, void *err, const void *svc, - uint16_t typecode, void *tdo, void *table, uint16_t duration, - int value, void **instance); -typedef int (*dpiOciFnType__objectPin)(void *env, void *err, void *object_ref, - void *corhdl, int pin_option, uint16_t pin_duration, int lock_option, - void **object); -typedef int (*dpiOciFnType__objectSetAttr)(void *env, void *err, - void *instance, void *null_struct, void *tdo, const char **names, - const uint32_t *lengths, const uint32_t name_count, - const uint32_t *indexes, const uint32_t index_count, - const int16_t null_status, const void *attr_null_struct, - const void *attr_value); -typedef int (*dpiOciFnType__paramGet)(const void *hndlp, uint32_t htype, - void *errhp, void **parmdpp, uint32_t pos); -typedef int (*dpiOciFnType__passwordChange)(void *svchp, void *errhp, - const char *user_name, uint32_t usernm_len, const char *opasswd, - uint32_t opasswd_len, const char *npasswd, uint32_t npasswd_len, - uint32_t mode); -typedef int (*dpiOciFnType__ping)(void *svchp, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__rawAssignBytes)(void *env, void *err, - const char *rhs, uint32_t rhs_len, void **lhs); -typedef void *(*dpiOciFnType__rawPtr)(void *env, const void *raw); -typedef int (*dpiOciFnType__rawResize)(void *env, void *err, uint32_t new_size, - void **raw); -typedef uint32_t (*dpiOciFnType__rawSize)(void * env, const void *raw); -typedef int (*dpiOciFnType__rowidToChar)(void *rowidDesc, char *outbfp, - uint16_t *outbflp, void *errhp); -typedef int (*dpiOciFnType__serverAttach)(void *srvhp, void *errhp, - const char *dblink, int32_t dblink_len, uint32_t mode); -typedef int (*dpiOciFnType__serverDetach)(void *srvhp, void *errhp, - uint32_t mode); -typedef int (*dpiOciFnType__serverRelease)(void *hndlp, void *errhp, - char *bufp, uint32_t bufsz, uint8_t hndltype, uint32_t *version); -typedef int (*dpiOciFnType__serverRelease2)(void *hndlp, void *errhp, - char *bufp, uint32_t bufsz, uint8_t hndltype, uint32_t *version, - uint32_t mode); -typedef int (*dpiOciFnType__sessionBegin)(void *svchp, void *errhp, - void *usrhp, uint32_t credt, uint32_t mode); -typedef int (*dpiOciFnType__sessionEnd)(void *svchp, void *errhp, void *usrhp, - uint32_t mode); -typedef int (*dpiOciFnType__sessionGet)(void *envhp, void *errhp, void **svchp, - void *authhp, const char *poolName, uint32_t poolName_len, - const char *tagInfo, uint32_t tagInfo_len, const char **retTagInfo, - uint32_t *retTagInfo_len, int *found, uint32_t mode); -typedef int (*dpiOciFnType__sessionPoolCreate)(void *envhp, void *errhp, - void *spoolhp, char **poolName, uint32_t *poolNameLen, - const char *connStr, uint32_t connStrLen, uint32_t sessMin, - uint32_t sessMax, uint32_t sessIncr, const char *userid, - uint32_t useridLen, const char *password, uint32_t passwordLen, - uint32_t mode); -typedef int (*dpiOciFnType__sessionPoolDestroy)(void *spoolhp, void *errhp, - uint32_t mode); -typedef int (*dpiOciFnType__sessionRelease)(void *svchp, void *errhp, - const char *tag, uint32_t tag_len, uint32_t mode); -typedef int (*dpiOciFnType__shardingKeyColumnAdd)(void *shardingKey, - void *errhp, void *col, uint32_t colLen, uint16_t colType, - uint32_t mode); -typedef int (*dpiOciFnType__sodaBulkInsert)(void *svchp, - void *collection, void **documentarray, uint32_t arraylen, - void *opoptns, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaBulkInsertAndGet)(void *svchp, - void *collection, void **documentarray, uint32_t arraylen, - void *opoptns, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaCollCreateWithMetadata)(void *svchp, - const char *collname, uint32_t collnamelen, const char *metadata, - uint32_t metadatalen, void **collection, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaCollDrop)(void *svchp, void *coll, - int *isDropped, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaCollGetNext)(void *svchp, const void *cur, - void **coll, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaCollList)(void *svchp, const char *startname, - uint32_t stnamelen, void **cur, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaCollOpen)(void *svchp, const char *collname, - uint32_t collnamelen, void **coll, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaDataGuideGet)(void *svchp, - const void *collection, uint32_t docFlags, void **doc, void *errhp, - uint32_t mode); -typedef int (*dpiOciFnType__sodaDocCount)(void *svchp, const void *coll, - const void *optns, uint64_t *numdocs, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaDocGetNext)(void *svchp, const void *cur, - void **doc, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaFind)(void *svchp, const void *coll, - const void *findOptions, uint32_t docFlags, void **cursor, - void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaFindOne)(void *svchp, const void *coll, - const void *findOptions, uint32_t docFlags, void **doc, void *errhp, - uint32_t mode); -typedef int (*dpiOciFnType__sodaIndexCreate)(void *svchp, const void *coll, - const char *indexspec, uint32_t speclen, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaIndexDrop)(void *svchp, const char *indexname, - uint32_t indexnamelen, int *isDropped, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaInsert)(void *svchp, void *collection, - void *document, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaInsertAndGet)(void *svchp, void *collection, - void **document, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaOperKeysSet)(const void *operhp, - const char **keysArray, uint32_t *lengthsArray, uint32_t count, - void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaRemove)(void *svchp, const void *coll, - const void *optns, uint64_t *removeCount, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__sodaReplOne)(void *svchp, const void *coll, - const void *optns, void *document, int *isReplaced, void *errhp, - uint32_t mode); -typedef int (*dpiOciFnType__sodaReplOneAndGet)(void *svchp, const void *coll, - const void *optns, void **document, int *isReplaced, void *errhp, - uint32_t mode); -typedef int (*dpiOciFnType__stmtExecute)(void *svchp, void *stmtp, void *errhp, - uint32_t iters, uint32_t rowoff, const void *snap_in, void *snap_out, - uint32_t mode); -typedef int (*dpiOciFnType__stmtFetch2)(void *stmtp, void *errhp, - uint32_t nrows, uint16_t orientation, int32_t scrollOffset, - uint32_t mode); -typedef int (*dpiOciFnType__stmtGetBindInfo)(void *stmtp, void *errhp, - uint32_t size, uint32_t startloc, int32_t *found, char *bvnp[], - uint8_t bvnl[], char *invp[], uint8_t inpl[], uint8_t dupl[], - void **hndl); -typedef int (*dpiOciFnType__stmtGetNextResult)(void *stmthp, void *errhp, - void **result, uint32_t *rtype, uint32_t mode); -typedef int (*dpiOciFnType__stmtPrepare2)(void *svchp, void **stmtp, - void *errhp, const char *stmt, uint32_t stmt_len, const char *key, - uint32_t key_len, uint32_t language, uint32_t mode); -typedef int (*dpiOciFnType__stmtRelease)(void *stmtp, void *errhp, - const char *key, uint32_t key_len, uint32_t mode); -typedef int (*dpiOciFnType__stringAssignText)(void *env, void *err, - const char *rhs, uint32_t rhs_len, void **lhs); -typedef char *(*dpiOciFnType__stringPtr)(void *env, const void *vs); -typedef int (*dpiOciFnType__stringResize)(void *env, void *err, - uint32_t new_size, void **str); -typedef uint32_t (*dpiOciFnType__stringSize)(void *env, const void *vs); -typedef int (*dpiOciFnType__subscriptionRegister)(void *svchp, - void **subscrhpp, uint16_t count, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__subscriptionUnRegister)(void *svchp, - void *subscrhp, void *errhp, uint32_t mode); -typedef int (*dpiOciFnType__tableDelete)(void *env, void *err, int32_t index, - void *tbl); -typedef int (*dpiOciFnType__tableExists)(void *env, void *err, const void *tbl, - int32_t index, int *exists); -typedef int (*dpiOciFnType__tableFirst)(void *env, void *err, const void *tbl, - int32_t *index); -typedef int (*dpiOciFnType__tableLast)(void *env, void *err, const void *tbl, - int32_t *index); -typedef int (*dpiOciFnType__tableNext)(void *env, void *err, int32_t index, - const void *tbl, int32_t *next_index, int *exists); -typedef int (*dpiOciFnType__tablePrev)(void *env, void *err, int32_t index, - const void *tbl, int32_t *prev_index, int *exists); -typedef int (*dpiOciFnType__tableSize)(void *env, void *err, const void *tbl, - int32_t *size); -typedef int (*dpiOciFnType__threadKeyDestroy)(void *hndl, void *err, - void **key); -typedef int (*dpiOciFnType__threadKeyGet)(void *hndl, void *err, void *key, - void **pValue); -typedef int (*dpiOciFnType__threadKeyInit)(void *hndl, void *err, void **key, - void *destFn); -typedef int (*dpiOciFnType__threadKeySet)(void *hndl, void *err, void *key, - void *value); -typedef void (*dpiOciFnType__threadProcessInit)(void); -typedef int (*dpiOciFnType__transCommit)(void *svchp, void *errhp, - uint32_t flags); -typedef int (*dpiOciFnType__transPrepare)(void *svchp, void *errhp, - uint32_t flags); -typedef int (*dpiOciFnType__transRollback)(void *svchp, void *errhp, - uint32_t flags); -typedef int (*dpiOciFnType__transStart)(void *svchp, void *errhp, - unsigned int timeout, uint32_t flags); -typedef int (*dpiOciFnType__typeByFullName)(void *env, void *err, - const void *svc, const char *full_type_name, - uint32_t full_type_name_length, const char *version_name, - uint32_t version_name_length, uint16_t pin_duration, int get_option, - void **tdo); -typedef int (*dpiOciFnType__typeByName)(void *env, void *err, const void *svc, - const char *schema_name, uint32_t s_length, const char *type_name, - uint32_t t_length, const char *version_name, uint32_t v_length, - uint16_t pin_duration, int get_option, void **tdo); - - -// library handle for dynamically loaded OCI library -static void *dpiOciLibHandle = NULL; - -// library names to search -static const char *dpiOciLibNames[] = { -#if defined _WIN32 || defined __CYGWIN__ - "oci.dll", -#elif __APPLE__ - "libclntsh.dylib", - "libclntsh.dylib.19.1", - "libclntsh.dylib.18.1", - "libclntsh.dylib.12.1", - "libclntsh.dylib.11.1", - "libclntsh.dylib.20.1", -#else - "libclntsh.so", - "libclntsh.so.19.1", - "libclntsh.so.18.1", - "libclntsh.so.12.1", - "libclntsh.so.11.1", - "libclntsh.so.20.1", -#endif - NULL -}; - -// URL fragment to use in load library exception -#if defined _WIN32 || defined __CYGWIN__ - #define DPI_ERR_LOAD_URL_FRAGMENT "windows" -#elif __APPLE__ - #define DPI_ERR_LOAD_URL_FRAGMENT "macos" -#else - #define DPI_ERR_LOAD_URL_FRAGMENT "linux" -#endif - -// version information for loaded OCI library -static dpiVersionInfo dpiOciLibVersionInfo; - -// all OCI symbols used by ODPI-C -static struct { - dpiOciFnType__aqDeq fnAqDeq; - dpiOciFnType__aqDeqArray fnAqDeqArray; - dpiOciFnType__aqEnq fnAqEnq; - dpiOciFnType__aqEnqArray fnAqEnqArray; - dpiOciFnType__arrayDescriptorAlloc fnArrayDescriptorAlloc; - dpiOciFnType__arrayDescriptorFree fnArrayDescriptorFree; - dpiOciFnType__attrGet fnAttrGet; - dpiOciFnType__attrSet fnAttrSet; - dpiOciFnType__bindByName fnBindByName; - dpiOciFnType__bindByName2 fnBindByName2; - dpiOciFnType__bindByPos fnBindByPos; - dpiOciFnType__bindByPos2 fnBindByPos2; - dpiOciFnType__bindDynamic fnBindDynamic; - dpiOciFnType__bindObject fnBindObject; - dpiOciFnType__break fnBreak; - dpiOciFnType__clientVersion fnClientVersion; - dpiOciFnType__collAppend fnCollAppend; - dpiOciFnType__collAssignElem fnCollAssignElem; - dpiOciFnType__collGetElem fnCollGetElem; - dpiOciFnType__collSize fnCollSize; - dpiOciFnType__collTrim fnCollTrim; - dpiOciFnType__contextGetValue fnContextGetValue; - dpiOciFnType__contextSetValue fnContextSetValue; - dpiOciFnType__dateTimeConstruct fnDateTimeConstruct; - dpiOciFnType__dateTimeConvert fnDateTimeConvert; - dpiOciFnType__dateTimeGetDate fnDateTimeGetDate; - dpiOciFnType__dateTimeGetTime fnDateTimeGetTime; - dpiOciFnType__dateTimeGetTimeZoneOffset fnDateTimeGetTimeZoneOffset; - dpiOciFnType__dateTimeIntervalAdd fnDateTimeIntervalAdd; - dpiOciFnType__dateTimeSubtract fnDateTimeSubtract; - dpiOciFnType__dbShutdown fnDbShutdown; - dpiOciFnType__dbStartup fnDbStartup; - dpiOciFnType__defineByPos fnDefineByPos; - dpiOciFnType__defineByPos2 fnDefineByPos2; - dpiOciFnType__defineDynamic fnDefineDynamic; - dpiOciFnType__defineObject fnDefineObject; - dpiOciFnType__describeAny fnDescribeAny; - dpiOciFnType__descriptorAlloc fnDescriptorAlloc; - dpiOciFnType__descriptorFree fnDescriptorFree; - dpiOciFnType__envNlsCreate fnEnvNlsCreate; - dpiOciFnType__errorGet fnErrorGet; - dpiOciFnType__handleAlloc fnHandleAlloc; - dpiOciFnType__handleFree fnHandleFree; - dpiOciFnType__intervalGetDaySecond fnIntervalGetDaySecond; - dpiOciFnType__intervalGetYearMonth fnIntervalGetYearMonth; - dpiOciFnType__intervalSetDaySecond fnIntervalSetDaySecond; - dpiOciFnType__intervalSetYearMonth fnIntervalSetYearMonth; - dpiOciFnType__lobClose fnLobClose; - dpiOciFnType__lobCreateTemporary fnLobCreateTemporary; - dpiOciFnType__lobFileExists fnLobFileExists; - dpiOciFnType__lobFileGetName fnLobFileGetName; - dpiOciFnType__lobFileSetName fnLobFileSetName; - dpiOciFnType__lobFreeTemporary fnLobFreeTemporary; - dpiOciFnType__lobGetChunkSize fnLobGetChunkSize; - dpiOciFnType__lobGetLength2 fnLobGetLength2; - dpiOciFnType__lobIsOpen fnLobIsOpen; - dpiOciFnType__lobIsTemporary fnLobIsTemporary; - dpiOciFnType__lobLocatorAssign fnLobLocatorAssign; - dpiOciFnType__lobOpen fnLobOpen; - dpiOciFnType__lobRead2 fnLobRead2; - dpiOciFnType__lobTrim2 fnLobTrim2; - dpiOciFnType__lobWrite2 fnLobWrite2; - dpiOciFnType__memoryAlloc fnMemoryAlloc; - dpiOciFnType__memoryFree fnMemoryFree; - dpiOciFnType__nlsCharSetConvert fnNlsCharSetConvert; - dpiOciFnType__nlsCharSetIdToName fnNlsCharSetIdToName; - dpiOciFnType__nlsCharSetNameToId fnNlsCharSetNameToId; - dpiOciFnType__nlsEnvironmentVariableGet fnNlsEnvironmentVariableGet; - dpiOciFnType__nlsNameMap fnNlsNameMap; - dpiOciFnType__nlsNumericInfoGet fnNlsNumericInfoGet; - dpiOciFnType__numberFromInt fnNumberFromInt; - dpiOciFnType__numberFromReal fnNumberFromReal; - dpiOciFnType__numberToInt fnNumberToInt; - dpiOciFnType__numberToReal fnNumberToReal; - dpiOciFnType__objectCopy fnObjectCopy; - dpiOciFnType__objectFree fnObjectFree; - dpiOciFnType__objectGetAttr fnObjectGetAttr; - dpiOciFnType__objectGetInd fnObjectGetInd; - dpiOciFnType__objectNew fnObjectNew; - dpiOciFnType__objectPin fnObjectPin; - dpiOciFnType__objectSetAttr fnObjectSetAttr; - dpiOciFnType__paramGet fnParamGet; - dpiOciFnType__passwordChange fnPasswordChange; - dpiOciFnType__ping fnPing; - dpiOciFnType__rawAssignBytes fnRawAssignBytes; - dpiOciFnType__rawPtr fnRawPtr; - dpiOciFnType__rawResize fnRawResize; - dpiOciFnType__rawSize fnRawSize; - dpiOciFnType__rowidToChar fnRowidToChar; - dpiOciFnType__serverAttach fnServerAttach; - dpiOciFnType__serverDetach fnServerDetach; - dpiOciFnType__serverRelease fnServerRelease; - dpiOciFnType__serverRelease2 fnServerRelease2; - dpiOciFnType__sessionBegin fnSessionBegin; - dpiOciFnType__sessionEnd fnSessionEnd; - dpiOciFnType__sessionGet fnSessionGet; - dpiOciFnType__sessionPoolCreate fnSessionPoolCreate; - dpiOciFnType__sessionPoolDestroy fnSessionPoolDestroy; - dpiOciFnType__sessionRelease fnSessionRelease; - dpiOciFnType__shardingKeyColumnAdd fnShardingKeyColumnAdd; - dpiOciFnType__stmtExecute fnStmtExecute; - dpiOciFnType__sodaBulkInsert fnSodaBulkInsert; - dpiOciFnType__sodaBulkInsertAndGet fnSodaBulkInsertAndGet; - dpiOciFnType__sodaCollCreateWithMetadata fnSodaCollCreateWithMetadata; - dpiOciFnType__sodaCollDrop fnSodaCollDrop; - dpiOciFnType__sodaCollGetNext fnSodaCollGetNext; - dpiOciFnType__sodaCollList fnSodaCollList; - dpiOciFnType__sodaCollOpen fnSodaCollOpen; - dpiOciFnType__sodaDataGuideGet fnSodaDataGuideGet; - dpiOciFnType__sodaDocCount fnSodaDocCount; - dpiOciFnType__sodaDocGetNext fnSodaDocGetNext; - dpiOciFnType__sodaFind fnSodaFind; - dpiOciFnType__sodaFindOne fnSodaFindOne; - dpiOciFnType__sodaIndexCreate fnSodaIndexCreate; - dpiOciFnType__sodaIndexDrop fnSodaIndexDrop; - dpiOciFnType__sodaInsert fnSodaInsert; - dpiOciFnType__sodaInsertAndGet fnSodaInsertAndGet; - dpiOciFnType__sodaOperKeysSet fnSodaOperKeysSet; - dpiOciFnType__sodaRemove fnSodaRemove; - dpiOciFnType__sodaReplOne fnSodaReplOne; - dpiOciFnType__sodaReplOneAndGet fnSodaReplOneAndGet; - dpiOciFnType__stmtFetch2 fnStmtFetch2; - dpiOciFnType__stmtGetBindInfo fnStmtGetBindInfo; - dpiOciFnType__stmtGetNextResult fnStmtGetNextResult; - dpiOciFnType__stmtPrepare2 fnStmtPrepare2; - dpiOciFnType__stmtRelease fnStmtRelease; - dpiOciFnType__stringAssignText fnStringAssignText; - dpiOciFnType__stringPtr fnStringPtr; - dpiOciFnType__stringResize fnStringResize; - dpiOciFnType__stringSize fnStringSize; - dpiOciFnType__subscriptionRegister fnSubscriptionRegister; - dpiOciFnType__subscriptionUnRegister fnSubscriptionUnRegister; - dpiOciFnType__tableDelete fnTableDelete; - dpiOciFnType__tableExists fnTableExists; - dpiOciFnType__tableFirst fnTableFirst; - dpiOciFnType__tableLast fnTableLast; - dpiOciFnType__tableNext fnTableNext; - dpiOciFnType__tablePrev fnTablePrev; - dpiOciFnType__tableSize fnTableSize; - dpiOciFnType__threadKeyDestroy fnThreadKeyDestroy; - dpiOciFnType__threadKeyGet fnThreadKeyGet; - dpiOciFnType__threadKeyInit fnThreadKeyInit; - dpiOciFnType__threadKeySet fnThreadKeySet; - dpiOciFnType__threadProcessInit fnThreadProcessInit; - dpiOciFnType__transCommit fnTransCommit; - dpiOciFnType__transPrepare fnTransPrepare; - dpiOciFnType__transRollback fnTransRollback; - dpiOciFnType__transStart fnTransStart; - dpiOciFnType__typeByFullName fnTypeByFullName; - dpiOciFnType__typeByName fnTypeByName; -} dpiOciSymbols; - - -//----------------------------------------------------------------------------- -// dpiOci__allocateMem() [INTERNAL] -// Wrapper for OCI allocation of memory, only used when debugging memory -// allocation. -//----------------------------------------------------------------------------- -static void *dpiOci__allocateMem(UNUSED void *unused, size_t size) -{ - void *ptr; - - ptr = malloc(size); - dpiDebug__print("OCI allocated %u bytes at %p\n", size, ptr); - return ptr; -} - - -//----------------------------------------------------------------------------- -// dpiOci__aqDeq() [INTERNAL] -// Wrapper for OCIAQDeq(). -//----------------------------------------------------------------------------- -int dpiOci__aqDeq(dpiConn *conn, const char *queueName, void *options, - void *msgProps, void *payloadType, void **payload, void **payloadInd, - void **msgId, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIAQDeq", dpiOciSymbols.fnAqDeq) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnAqDeq)(conn->handle, error->handle, queueName, - options, msgProps, payloadType, payload, payloadInd, msgId, - DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "dequeue message"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__aqDeqArray() [INTERNAL] -// Wrapper for OCIAQDeqArray(). -//----------------------------------------------------------------------------- -int dpiOci__aqDeqArray(dpiConn *conn, const char *queueName, void *options, - uint32_t *numIters, void **msgProps, void *payloadType, void **payload, - void **payloadInd, void **msgId, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIAQDeqArray", dpiOciSymbols.fnAqDeqArray) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnAqDeqArray)(conn->handle, error->handle, - queueName, options, numIters, msgProps, payloadType, payload, - payloadInd, msgId, NULL, NULL, DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "dequeue messages"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__aqEnq() [INTERNAL] -// Wrapper for OCIAQEnq(). -//----------------------------------------------------------------------------- -int dpiOci__aqEnq(dpiConn *conn, const char *queueName, void *options, - void *msgProps, void *payloadType, void **payload, void **payloadInd, - void **msgId, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIAQEnq", dpiOciSymbols.fnAqEnq) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnAqEnq)(conn->handle, error->handle, queueName, - options, msgProps, payloadType, payload, payloadInd, msgId, - DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "enqueue message"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__aqEnqArray() [INTERNAL] -// Wrapper for OCIAQEnqArray(). -//----------------------------------------------------------------------------- -int dpiOci__aqEnqArray(dpiConn *conn, const char *queueName, void *options, - uint32_t *numIters, void **msgProps, void *payloadType, void **payload, - void **payloadInd, void **msgId, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIAQEnqArray", dpiOciSymbols.fnAqEnqArray) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnAqEnqArray)(conn->handle, error->handle, - queueName, options, numIters, msgProps, payloadType, payload, - payloadInd, msgId, NULL, NULL, DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "enqueue messages"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__arrayDescriptorAlloc() [INTERNAL] -// Wrapper for OCIArrayDescriptorAlloc(). -//----------------------------------------------------------------------------- -int dpiOci__arrayDescriptorAlloc(void *envHandle, void **handle, - uint32_t handleType, uint32_t arraySize, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIArrayDescriptorAlloc", - dpiOciSymbols.fnArrayDescriptorAlloc) - status = (*dpiOciSymbols.fnArrayDescriptorAlloc)(envHandle, handle, - handleType, arraySize, 0, NULL); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "allocate descriptors"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__arrayDescriptorFree() [INTERNAL] -// Wrapper for OCIArrayDescriptorFree(). -//----------------------------------------------------------------------------- -int dpiOci__arrayDescriptorFree(void **handle, uint32_t handleType) -{ - dpiError *error = NULL; - int status; - - DPI_OCI_LOAD_SYMBOL("OCIArrayDescriptorFree", - dpiOciSymbols.fnArrayDescriptorFree) - status = (*dpiOciSymbols.fnArrayDescriptorFree)(handle, handleType); - if (status != DPI_OCI_SUCCESS && dpiDebugLevel & DPI_DEBUG_LEVEL_FREES) - dpiDebug__print("free array descriptors %p, handleType %d failed\n", - handle, handleType); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__attrGet() [INTERNAL] -// Wrapper for OCIAttrGet(). -//----------------------------------------------------------------------------- -int dpiOci__attrGet(const void *handle, uint32_t handleType, void *ptr, - uint32_t *size, uint32_t attribute, const char *action, - dpiError *error) -{ - int status; - - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnAttrGet)(handle, handleType, ptr, size, - attribute, error->handle); - if (!action) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); -} - - -//----------------------------------------------------------------------------- -// dpiOci__attrSet() [INTERNAL] -// Wrapper for OCIAttrSet(). -//----------------------------------------------------------------------------- -int dpiOci__attrSet(void *handle, uint32_t handleType, void *ptr, - uint32_t size, uint32_t attribute, const char *action, dpiError *error) -{ - int status; - - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnAttrSet)(handle, handleType, ptr, size, - attribute, error->handle); - if (!action) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); -} - - -//----------------------------------------------------------------------------- -// dpiOci__bindByName() [INTERNAL] -// Wrapper for OCIBindByName(). -//----------------------------------------------------------------------------- -int dpiOci__bindByName(dpiStmt *stmt, void **bindHandle, const char *name, - int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIBindByName", dpiOciSymbols.fnBindByName) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnBindByName)(stmt->handle, bindHandle, - error->handle, name, nameLength, - (dynamicBind) ? NULL : var->buffer.data.asRaw, - (var->isDynamic) ? INT_MAX : (int32_t) var->sizeInBytes, - var->type->oracleType, (dynamicBind) ? NULL : - var->buffer.indicator, - (dynamicBind || var->type->sizeInBytes) ? NULL : - var->buffer.actualLength16, - (dynamicBind) ? NULL : var->buffer.returnCode, - (var->isArray) ? var->buffer.maxArraySize : 0, - (var->isArray) ? &var->buffer.actualArraySize : NULL, - (dynamicBind) ? DPI_OCI_DATA_AT_EXEC : DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by name"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__bindByName2() [INTERNAL] -// Wrapper for OCIBindByName2(). -//----------------------------------------------------------------------------- -int dpiOci__bindByName2(dpiStmt *stmt, void **bindHandle, const char *name, - int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIBindByName2", dpiOciSymbols.fnBindByName2) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnBindByName2)(stmt->handle, bindHandle, - error->handle, name, nameLength, - (dynamicBind) ? NULL : var->buffer.data.asRaw, - (var->isDynamic) ? INT_MAX : var->sizeInBytes, - var->type->oracleType, (dynamicBind) ? NULL : - var->buffer.indicator, - (dynamicBind || var->type->sizeInBytes) ? NULL : - var->buffer.actualLength32, - (dynamicBind) ? NULL : var->buffer.returnCode, - (var->isArray) ? var->buffer.maxArraySize : 0, - (var->isArray) ? &var->buffer.actualArraySize : NULL, - (dynamicBind) ? DPI_OCI_DATA_AT_EXEC : DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by name"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__bindByPos() [INTERNAL] -// Wrapper for OCIBindByPos(). -//----------------------------------------------------------------------------- -int dpiOci__bindByPos(dpiStmt *stmt, void **bindHandle, uint32_t pos, - int dynamicBind, dpiVar *var, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIBindByPos", dpiOciSymbols.fnBindByPos) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnBindByPos)(stmt->handle, bindHandle, - error->handle, pos, (dynamicBind) ? NULL : var->buffer.data.asRaw, - (var->isDynamic) ? INT_MAX : (int32_t) var->sizeInBytes, - var->type->oracleType, (dynamicBind) ? NULL : - var->buffer.indicator, - (dynamicBind || var->type->sizeInBytes) ? NULL : - var->buffer.actualLength16, - (dynamicBind) ? NULL : var->buffer.returnCode, - (var->isArray) ? var->buffer.maxArraySize : 0, - (var->isArray) ? &var->buffer.actualArraySize : NULL, - (dynamicBind) ? DPI_OCI_DATA_AT_EXEC : DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by position"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__bindByPos2() [INTERNAL] -// Wrapper for OCIBindByPos2(). -//----------------------------------------------------------------------------- -int dpiOci__bindByPos2(dpiStmt *stmt, void **bindHandle, uint32_t pos, - int dynamicBind, dpiVar *var, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIBindByPos2", dpiOciSymbols.fnBindByPos2) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnBindByPos2)(stmt->handle, bindHandle, - error->handle, pos, (dynamicBind) ? NULL : var->buffer.data.asRaw, - (var->isDynamic) ? INT_MAX : var->sizeInBytes, - var->type->oracleType, (dynamicBind) ? NULL : - var->buffer.indicator, - (dynamicBind || var->type->sizeInBytes) ? NULL : - var->buffer.actualLength32, - (dynamicBind) ? NULL : var->buffer.returnCode, - (var->isArray) ? var->buffer.maxArraySize : 0, - (var->isArray) ? &var->buffer.actualArraySize : NULL, - (dynamicBind) ? DPI_OCI_DATA_AT_EXEC : DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by position"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__bindDynamic() [INTERNAL] -// Wrapper for OCIBindDynamic(). -//----------------------------------------------------------------------------- -int dpiOci__bindDynamic(dpiVar *var, void *bindHandle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIBindDynamic", dpiOciSymbols.fnBindDynamic) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnBindDynamic)(bindHandle, error->handle, var, - (void*) dpiVar__inBindCallback, var, - (void*) dpiVar__outBindCallback); - DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "bind dynamic"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__bindObject() [INTERNAL] -// Wrapper for OCIBindObject(). -//----------------------------------------------------------------------------- -int dpiOci__bindObject(dpiVar *var, void *bindHandle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIBindObject", dpiOciSymbols.fnBindObject) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnBindObject)(bindHandle, error->handle, - var->objectType->tdo, (void**) var->buffer.data.asRaw, 0, - var->buffer.objectIndicator, 0); - DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "bind object"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__break() [INTERNAL] -// Wrapper for OCIBreak(). -//----------------------------------------------------------------------------- -int dpiOci__break(dpiConn *conn, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIBreak", dpiOciSymbols.fnBreak) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnBreak)(conn->handle, error->handle); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "break execution"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__clientVersion() [INTERNAL] -// Set the version information in the context to the OCI client version -// information that was discovered when the OCI library was loaded. -//----------------------------------------------------------------------------- -void dpiOci__clientVersion(dpiContext *context) -{ - context->versionInfo = &dpiOciLibVersionInfo; -} - - -//----------------------------------------------------------------------------- -// dpiOci__collAppend() [INTERNAL] -// Wrapper for OCICollAppend(). -//----------------------------------------------------------------------------- -int dpiOci__collAppend(dpiConn *conn, const void *elem, const void *elemInd, - void *coll, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCICollAppend", dpiOciSymbols.fnCollAppend) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnCollAppend)(conn->env->handle, error->handle, - elem, elemInd, coll); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "append element"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__collAssignElem() [INTERNAL] -// Wrapper for OCICollAssignElem(). -//----------------------------------------------------------------------------- -int dpiOci__collAssignElem(dpiConn *conn, int32_t index, const void *elem, - const void *elemInd, void *coll, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCICollAssignElem", dpiOciSymbols.fnCollAssignElem) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnCollAssignElem)(conn->env->handle, - error->handle, index, elem, elemInd, coll); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "assign element"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__collGetElem() [INTERNAL] -// Wrapper for OCICollGetElem(). -//----------------------------------------------------------------------------- -int dpiOci__collGetElem(dpiConn *conn, void *coll, int32_t index, int *exists, - void **elem, void **elemInd, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCICollGetElem", dpiOciSymbols.fnCollGetElem) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnCollGetElem)(conn->env->handle, error->handle, - coll, index, exists, elem, elemInd); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get element"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__collSize() [INTERNAL] -// Wrapper for OCICollSize(). -//----------------------------------------------------------------------------- -int dpiOci__collSize(dpiConn *conn, void *coll, int32_t *size, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCICollSize", dpiOciSymbols.fnCollSize) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnCollSize)(conn->env->handle, error->handle, - coll, size); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get size"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__collTrim() [INTERNAL] -// Wrapper for OCICollTrim(). -//----------------------------------------------------------------------------- -int dpiOci__collTrim(dpiConn *conn, uint32_t numToTrim, void *coll, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCICollTrim", dpiOciSymbols.fnCollTrim) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnCollTrim)(conn->env->handle, error->handle, - (int32_t) numToTrim, coll); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "trim"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__contextGetValue() [INTERNAL] -// Wrapper for OCIContextGetValue(). -//----------------------------------------------------------------------------- -int dpiOci__contextGetValue(dpiConn *conn, const char *key, uint32_t keyLength, - void **value, int checkError, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIContextGetValue", dpiOciSymbols.fnContextGetValue) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnContextGetValue)(conn->sessionHandle, - error->handle, key, (uint8_t) keyLength, value); - if (!checkError) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get context value"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__contextSetValue() [INTERNAL] -// Wrapper for OCIContextSetValue(). -//----------------------------------------------------------------------------- -int dpiOci__contextSetValue(dpiConn *conn, const char *key, uint32_t keyLength, - void *value, int checkError, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIContextSetValue", dpiOciSymbols.fnContextSetValue) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnContextSetValue)(conn->sessionHandle, - error->handle, DPI_OCI_DURATION_SESSION, key, (uint8_t) keyLength, - value); - if (!checkError) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "set context value"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__dateTimeConstruct() [INTERNAL] -// Wrapper for OCIDateTimeConstruct(). -//----------------------------------------------------------------------------- -int dpiOci__dateTimeConstruct(void *envHandle, void *handle, int16_t year, - uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, - uint8_t second, uint32_t fsecond, const char *tz, size_t tzLength, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDateTimeConstruct", - dpiOciSymbols.fnDateTimeConstruct) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDateTimeConstruct)(envHandle, error->handle, - handle, year, month, day, hour, minute, second, fsecond, tz, - tzLength); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "construct date"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__dateTimeConvert() [INTERNAL] -// Wrapper for OCIDateTimeConvert(). -//----------------------------------------------------------------------------- -int dpiOci__dateTimeConvert(void *envHandle, void *inDate, void *outDate, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDateTimeConvert", dpiOciSymbols.fnDateTimeConvert) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDateTimeConvert)(envHandle, error->handle, - inDate, outDate); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "convert date"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__dateTimeGetDate() [INTERNAL] -// Wrapper for OCIDateTimeGetDate(). -//----------------------------------------------------------------------------- -int dpiOci__dateTimeGetDate(void *envHandle, void *handle, int16_t *year, - uint8_t *month, uint8_t *day, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDateTimeGetDate", dpiOciSymbols.fnDateTimeGetDate) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDateTimeGetDate)(envHandle, error->handle, - handle, year, month, day); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get date portion"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__dateTimeGetTime() [INTERNAL] -// Wrapper for OCIDateTimeGetTime(). -//----------------------------------------------------------------------------- -int dpiOci__dateTimeGetTime(void *envHandle, void *handle, uint8_t *hour, - uint8_t *minute, uint8_t *second, uint32_t *fsecond, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDateTimeGetTime", dpiOciSymbols.fnDateTimeGetTime) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDateTimeGetTime)(envHandle, error->handle, - handle, hour, minute, second, fsecond); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get time portion"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__dateTimeGetTimeZoneOffset() [INTERNAL] -// Wrapper for OCIDateTimeGetTimeZoneOffset(). -//----------------------------------------------------------------------------- -int dpiOci__dateTimeGetTimeZoneOffset(void *envHandle, void *handle, - int8_t *tzHourOffset, int8_t *tzMinuteOffset, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDateTimeGetTimeZoneOffset", - dpiOciSymbols.fnDateTimeGetTimeZoneOffset) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDateTimeGetTimeZoneOffset)(envHandle, - error->handle, handle, tzHourOffset, tzMinuteOffset); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get time zone portion"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__dateTimeIntervalAdd() [INTERNAL] -// Wrapper for OCIDateTimeIntervalAdd(). -//----------------------------------------------------------------------------- -int dpiOci__dateTimeIntervalAdd(void *envHandle, void *handle, void *interval, - void *outHandle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDateTimeIntervalAdd", - dpiOciSymbols.fnDateTimeIntervalAdd) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDateTimeIntervalAdd)(envHandle, error->handle, - handle, interval, outHandle); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "add interval to date"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__dateTimeSubtract() [INTERNAL] -// Wrapper for OCIDateTimeSubtract(). -//----------------------------------------------------------------------------- -int dpiOci__dateTimeSubtract(void *envHandle, void *handle1, void *handle2, - void *interval, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDateTimeSubtract", - dpiOciSymbols.fnDateTimeSubtract) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDateTimeSubtract)(envHandle, error->handle, - handle1, handle2, interval); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "subtract date"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__dbShutdown() [INTERNAL] -// Wrapper for OCIDBShutdown(). -//----------------------------------------------------------------------------- -int dpiOci__dbShutdown(dpiConn *conn, uint32_t mode, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDBShutdown", dpiOciSymbols.fnDbShutdown) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDbShutdown)(conn->handle, error->handle, NULL, - mode); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "shutdown database"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__dbStartup() [INTERNAL] -// Wrapper for OCIDBStartup(). -//----------------------------------------------------------------------------- -int dpiOci__dbStartup(dpiConn *conn, uint32_t mode, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDBStartup", dpiOciSymbols.fnDbStartup) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDbStartup)(conn->handle, error->handle, NULL, - DPI_OCI_DEFAULT, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "startup database"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__defineByPos() [INTERNAL] -// Wrapper for OCIDefineByPos(). -//----------------------------------------------------------------------------- -int dpiOci__defineByPos(dpiStmt *stmt, void **defineHandle, uint32_t pos, - dpiVar *var, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDefineByPos", dpiOciSymbols.fnDefineByPos) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDefineByPos)(stmt->handle, defineHandle, - error->handle, pos, (var->isDynamic) ? NULL : - var->buffer.data.asRaw, - (var->isDynamic) ? INT_MAX : (int32_t) var->sizeInBytes, - var->type->oracleType, (var->isDynamic) ? NULL : - var->buffer.indicator, - (var->isDynamic) ? NULL : var->buffer.actualLength16, - (var->isDynamic) ? NULL : var->buffer.returnCode, - (var->isDynamic) ? DPI_OCI_DYNAMIC_FETCH : DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "define"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__defineByPos2() [INTERNAL] -// Wrapper for OCIDefineByPos2(). -//----------------------------------------------------------------------------- -int dpiOci__defineByPos2(dpiStmt *stmt, void **defineHandle, uint32_t pos, - dpiVar *var, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDefineByPos2", dpiOciSymbols.fnDefineByPos2) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDefineByPos2)(stmt->handle, defineHandle, - error->handle, pos, (var->isDynamic) ? NULL : - var->buffer.data.asRaw, - (var->isDynamic) ? INT_MAX : var->sizeInBytes, - var->type->oracleType, (var->isDynamic) ? NULL : - var->buffer.indicator, - (var->isDynamic) ? NULL : var->buffer.actualLength32, - (var->isDynamic) ? NULL : var->buffer.returnCode, - (var->isDynamic) ? DPI_OCI_DYNAMIC_FETCH : DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "define"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__defineDynamic() [INTERNAL] -// Wrapper for OCIDefineDynamic(). -//----------------------------------------------------------------------------- -int dpiOci__defineDynamic(dpiVar *var, void *defineHandle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDefineDynamic", dpiOciSymbols.fnDefineDynamic) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDefineDynamic)(defineHandle, error->handle, var, - (void*) dpiVar__defineCallback); - DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "define dynamic"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__defineObject() [INTERNAL] -// Wrapper for OCIDefineObject(). -//----------------------------------------------------------------------------- -int dpiOci__defineObject(dpiVar *var, void *defineHandle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDefineObject", dpiOciSymbols.fnDefineObject) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDefineObject)(defineHandle, error->handle, - var->objectType->tdo, (void**) var->buffer.data.asRaw, 0, - var->buffer.objectIndicator, 0); - DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "define object"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__describeAny() [INTERNAL] -// Wrapper for OCIDescribeAny(). -//----------------------------------------------------------------------------- -int dpiOci__describeAny(dpiConn *conn, void *obj, uint32_t objLength, - uint8_t objType, void *describeHandle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDescribeAny", dpiOciSymbols.fnDescribeAny) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnDescribeAny)(conn->handle, error->handle, obj, - objLength, objType, 0, DPI_OCI_PTYPE_TYPE, describeHandle); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "describe type"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__descriptorAlloc() [INTERNAL] -// Wrapper for OCIDescriptorAlloc(). -//----------------------------------------------------------------------------- -int dpiOci__descriptorAlloc(void *envHandle, void **handle, - const uint32_t handleType, const char *action, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDescriptorAlloc", dpiOciSymbols.fnDescriptorAlloc) - status = (*dpiOciSymbols.fnDescriptorAlloc)(envHandle, handle, handleType, - 0, NULL); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); -} - - -//----------------------------------------------------------------------------- -// dpiOci__descriptorFree() [INTERNAL] -// Wrapper for OCIDescriptorFree(). -//----------------------------------------------------------------------------- -int dpiOci__descriptorFree(void *handle, uint32_t handleType) -{ - dpiError *error = NULL; - int status; - - DPI_OCI_LOAD_SYMBOL("OCIDescriptorFree", dpiOciSymbols.fnDescriptorFree) - status = (*dpiOciSymbols.fnDescriptorFree)(handle, handleType); - if (status != DPI_OCI_SUCCESS && dpiDebugLevel & DPI_DEBUG_LEVEL_FREES) - dpiDebug__print("free descriptor %p, type %d failed\n", handle, - handleType); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__envNlsCreate() [INTERNAL] -// Wrapper for OCIEnvNlsCreate(). -//----------------------------------------------------------------------------- -int dpiOci__envNlsCreate(void **envHandle, uint32_t mode, uint16_t charsetId, - uint16_t ncharsetId, dpiError *error) -{ - void *mallocFn = NULL, *reallocFn = NULL, *freeFn = NULL; - int status; - - *envHandle = NULL; - DPI_OCI_LOAD_SYMBOL("OCIEnvNlsCreate", dpiOciSymbols.fnEnvNlsCreate) - if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM) { - mallocFn = (void*) dpiOci__allocateMem; - reallocFn = (void*) dpiOci__reallocMem; - freeFn = (void*) dpiOci__freeMem; - } - status = (*dpiOciSymbols.fnEnvNlsCreate)(envHandle, mode, NULL, mallocFn, - reallocFn, freeFn, 0, NULL, charsetId, ncharsetId); - if (*envHandle) { - if (status == DPI_OCI_SUCCESS || status == DPI_OCI_SUCCESS_WITH_INFO) - return DPI_SUCCESS; - if (dpiOci__errorGet(*envHandle, DPI_OCI_HTYPE_ENV, charsetId, - "create env", error) == 0) - return DPI_FAILURE; - } - return dpiError__set(error, "create env", DPI_ERR_CREATE_ENV); -} - - -//----------------------------------------------------------------------------- -// dpiOci__errorGet() [INTERNAL] -// Wrapper for OCIErrorGet(). -//----------------------------------------------------------------------------- -int dpiOci__errorGet(void *handle, uint32_t handleType, uint16_t charsetId, - const char *action, dpiError *error) -{ - uint32_t i, numChars, bufferChars; - uint16_t *utf16chars; - int status; - char *ptr; - - DPI_OCI_LOAD_SYMBOL("OCIErrorGet", dpiOciSymbols.fnErrorGet) - status = (*dpiOciSymbols.fnErrorGet)(handle, 1, NULL, &error->buffer->code, - error->buffer->message, sizeof(error->buffer->message), - handleType); - if (status != DPI_OCI_SUCCESS) - return dpiError__set(error, action, DPI_ERR_GET_FAILED); - error->buffer->action = action; - - // determine length of message since OCI does not provide this information; - // all encodings except UTF-16 can use normal string processing; cannot use - // type whar_t for processing UTF-16, though, as its size may be 4 on some - // platforms, not 2; also strip trailing whitespace from error messages - if (charsetId == DPI_CHARSET_ID_UTF16) { - numChars = 0; - utf16chars = (uint16_t*) error->buffer->message; - bufferChars = sizeof(error->buffer->message) / 2; - for (i = 0; i < bufferChars; i++) { - if (utf16chars[i] == 0) - break; - if (utf16chars[i] > 127 || !isspace(utf16chars[i])) - numChars = i + 1; - } - error->buffer->messageLength = numChars * 2; - } else { - error->buffer->messageLength = - (uint32_t) strlen(error->buffer->message); - ptr = error->buffer->message + error->buffer->messageLength - 1; - while (ptr > error->buffer->message && isspace((uint8_t) *ptr--)) - error->buffer->messageLength--; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__freeMem() [INTERNAL] -// Wrapper for OCI allocation of memory, only used when debugging memory -// allocation. -//----------------------------------------------------------------------------- -static void dpiOci__freeMem(UNUSED void *unused, void *ptr) -{ - char message[40]; - - (void) sprintf(message, "OCI freed ptr at %p", ptr); - free(ptr); - dpiDebug__print("%s\n", message); -} - - -//----------------------------------------------------------------------------- -// dpiOci__handleAlloc() [INTERNAL] -// Wrapper for OCIHandleAlloc(). -//----------------------------------------------------------------------------- -int dpiOci__handleAlloc(void *envHandle, void **handle, uint32_t handleType, - const char *action, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIHandleAlloc", dpiOciSymbols.fnHandleAlloc) - status = (*dpiOciSymbols.fnHandleAlloc)(envHandle, handle, handleType, 0, - NULL); - if (handleType == DPI_OCI_HTYPE_ERROR && status != DPI_OCI_SUCCESS) - return dpiError__set(error, action, DPI_ERR_NO_MEMORY); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); -} - - -//----------------------------------------------------------------------------- -// dpiOci__handleFree() [INTERNAL] -// Wrapper for OCIHandleFree(). -//----------------------------------------------------------------------------- -int dpiOci__handleFree(void *handle, uint32_t handleType) -{ - dpiError *error = NULL; - int status; - - DPI_OCI_LOAD_SYMBOL("OCIHandleFree", dpiOciSymbols.fnHandleFree) - status = (*dpiOciSymbols.fnHandleFree)(handle, handleType); - if (status != DPI_OCI_SUCCESS && dpiDebugLevel & DPI_DEBUG_LEVEL_FREES) - dpiDebug__print("free handle %p, handleType %d failed\n", handle, - handleType); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__intervalGetDaySecond() [INTERNAL] -// Wrapper for OCIIntervalGetDaySecond(). -//----------------------------------------------------------------------------- -int dpiOci__intervalGetDaySecond(void *envHandle, int32_t *day, int32_t *hour, - int32_t *minute, int32_t *second, int32_t *fsecond, - const void *interval, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIIntervalGetDaySecond", - dpiOciSymbols.fnIntervalGetDaySecond) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnIntervalGetDaySecond)(envHandle, - error->handle, day, hour, minute, second, fsecond, interval); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get interval components"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__intervalGetYearMonth() [INTERNAL] -// Wrapper for OCIIntervalGetYearMonth(). -//----------------------------------------------------------------------------- -int dpiOci__intervalGetYearMonth(void *envHandle, int32_t *year, - int32_t *month, const void *interval, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIIntervalGetYearMonth", - dpiOciSymbols.fnIntervalGetYearMonth) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnIntervalGetYearMonth)(envHandle, error->handle, - year, month, interval); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get interval components"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__intervalSetDaySecond() [INTERNAL] -// Wrapper for OCIIntervalSetDaySecond(). -//----------------------------------------------------------------------------- -int dpiOci__intervalSetDaySecond(void *envHandle, int32_t day, int32_t hour, - int32_t minute, int32_t second, int32_t fsecond, void *interval, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIIntervalSetDaySecond", - dpiOciSymbols.fnIntervalSetDaySecond) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnIntervalSetDaySecond)(envHandle, error->handle, - day, hour, minute, second, fsecond, interval); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "set interval components"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__intervalSetYearMonth() [INTERNAL] -// Wrapper for OCIIntervalSetYearMonth(). -//----------------------------------------------------------------------------- -int dpiOci__intervalSetYearMonth(void *envHandle, int32_t year, int32_t month, - void *interval, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIIntervalSetYearMonth", - dpiOciSymbols.fnIntervalSetYearMonth) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnIntervalSetYearMonth)(envHandle, error->handle, - year, month, interval); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "set interval components"); -} - - -#ifdef _WIN32 -//----------------------------------------------------------------------------- -// dpiOci__checkDllArchitecture() [INTERNAL] -// Check the architecture of the specified DLL name and check that it -// matches the expected architecture. Returns -1 if the DLL architecture could -// not be determined, 0 if it does not match and 1 if it matches. -//----------------------------------------------------------------------------- -static int dpiOci__checkDllArchitecture(const char *name) -{ - IMAGE_DOS_HEADER dosHeader; - IMAGE_NT_HEADERS ntHeaders; - FILE *fp; - - fp = fopen(name, "rb"); - if (!fp) - return -1; - fread(&dosHeader, sizeof(dosHeader), 1, fp); - if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) { - fclose(fp); - return -1; - } - fseek(fp, dosHeader.e_lfanew, SEEK_SET); - fread(&ntHeaders, sizeof(ntHeaders), 1, fp); - fclose(fp); - if (ntHeaders.Signature != IMAGE_NT_SIGNATURE) - return -1; -#if defined _M_AMD64 - if (ntHeaders.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) - return 1; -#elif defined _M_IX86 - if (ntHeaders.FileHeader.Machine == IMAGE_FILE_MACHINE_I386) - return 1; -#endif - return 0; -} - - -//----------------------------------------------------------------------------- -// dpiOci__findAndCheckDllArchitecture() [INTERNAL] -// Attempt to find the specified DLL name using the standard search path and -// if the DLL can be found but is of the wrong architecture, include the full -// name of the DLL in the load error. Return -1 if such a DLL could not be -// found and 0 if the load error was changed. -//----------------------------------------------------------------------------- -static int dpiOci__findAndCheckDllArchitecture(const char *dllName, - char *loadError, size_t loadErrorLength) -{ - char fullName[_MAX_PATH + 1], *path, *temp; - size_t length; - int found = 0; - - // first search executable directory - if (GetModuleFileName(NULL, fullName, sizeof(fullName)) != 0) { - temp = strrchr(fullName, '\\'); - if (temp) { - *(temp + 1) = '\0'; - strncat(fullName, dllName, - sizeof(fullName) - strlen(fullName) - 1); - if (dpiOci__checkDllArchitecture(fullName) == 0) - found = 1; - } - } - - // check current directory - if (!found && GetCurrentDirectory(sizeof(fullName), fullName) != 0) { - temp = fullName + strlen(fullName); - snprintf(temp, sizeof(fullName) - strlen(fullName), "\\%s", dllName); - if (dpiOci__checkDllArchitecture(fullName) == 0) - found = 1; - } - - // search PATH - path = getenv("PATH"); - if (path) { - while (!found) { - temp = strchr(path, ';'); - if (!temp) - length = strlen(path); - else length = temp - path; - if (length <= _MAX_DIR) { - snprintf(fullName, sizeof(fullName), "%.*s\\%s", (int) length, - path, dllName); - if (dpiOci__checkDllArchitecture(fullName) == 0) { - found = 1; - break; - } - } - if (!temp) - break; - path = temp + 1; - } - } - - // if found, adjust the load error - if (found) { - snprintf(loadError, loadErrorLength, - "%s is not the correct architecture", fullName); - loadError[loadErrorLength - 1] = '\0'; - return 0; - } - - return -1; -} - - -//----------------------------------------------------------------------------- -// dpiOci__getLoadErrorOnWindows() [INTERNAL] -// Get the error message for a load failure on Windows. -//----------------------------------------------------------------------------- -static void dpiOci__getLoadErrorOnWindows(const char *dllName, - char *loadError, size_t loadErrorLength) -{ - DWORD length = 0, errorNum, status; - wchar_t *wLoadError = NULL; - - // if DLL is of the wrong architecture, attempt to locate the DLL that was - // loaded and use that information if it can be found - errorNum = GetLastError(); - if (errorNum == ERROR_BAD_EXE_FORMAT && - dpiOci__findAndCheckDllArchitecture(dllName, loadError, - loadErrorLength) == 0) - return; - - // get error message in Unicode first - // use English unless English error messages aren't available - status = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, errorNum, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), - (LPWSTR) &wLoadError, 0, NULL); - if (!status && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) - FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, errorNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPWSTR) &wLoadError, 0, NULL); - - if (wLoadError) { - - // strip trailing period and carriage return from message, if needed - length = (DWORD) wcslen(wLoadError); - while (length > 0) { - if (wLoadError[length - 1] > 127 || - (wLoadError[length - 1] != L'.' && - !isspace(wLoadError[length - 1]))) - break; - length--; - } - wLoadError[length] = L'\0'; - - // convert to a multi-byte string in UTF-8 encoding - if (length > 0) - length = WideCharToMultiByte(CP_UTF8, 0, wLoadError, -1, loadError, - (int) loadErrorLength, NULL, NULL); - LocalFree(wLoadError); - - } - - // fallback in case message cannot be determined - if (length == 0) - sprintf(loadError, "DLL load failed: Windows Error %d", errorNum); -} - - -//----------------------------------------------------------------------------- -// dpiOci__loadLibOnWindows() [INTERNAL] -// Load the library on the Windows platform. First an attempt is made to -// determine the location of the module containing ODPI-C. If found, an attempt -// is made to load oci.dll from that location; otherwise a standard Windows -// search is made for oci.dll. -//----------------------------------------------------------------------------- -static void dpiOci__loadLibOnWindows(const char *dllName) -{ - char moduleName[MAX_PATH + 1], *temp; - HMODULE module = NULL; - - // attempt to determine the location of the module containing ODPI-C; - // errors in this code are ignored and the normal loading mechanism is - // used instead - if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - (LPCSTR) dpiOci__loadLibOnWindows, &module)) { - if (GetModuleFileName(module, moduleName, sizeof(moduleName)) > 0) { - temp = strrchr(moduleName, '\\'); - if (temp) { - *(temp + 1) = '\0'; - strncat(moduleName, dllName, - sizeof(moduleName) - strlen(moduleName) - 1); - dpiOciLibHandle = LoadLibrary(moduleName); - } - } - FreeLibrary(module); - } - - // if library was not loaded in the same location as ODPI-C, use the - // standard Windows search to locate oci.dll instead - if (!dpiOciLibHandle) - dpiOciLibHandle = LoadLibrary(dllName); -} -#endif - - -//----------------------------------------------------------------------------- -// dpiOci__loadLib() [INTERNAL] -// Load the OCI library. -//----------------------------------------------------------------------------- -static int dpiOci__loadLib(dpiError *error) -{ - const char *libName; - char loadError[512]; - unsigned int i; -#ifndef _WIN32 - char *oracleHome, *oracleHomeLibName; - size_t oracleHomeLibNameLength; -#endif - - // dynamically load the OCI library - for (i = 0; !dpiOciLibHandle; i++) { - libName = dpiOciLibNames[i]; - if (!libName) - break; -#ifdef _WIN32 - dpiOci__loadLibOnWindows(libName); - if (!dpiOciLibHandle && i == 0) - dpiOci__getLoadErrorOnWindows(libName, loadError, - sizeof(loadError)); -#else - dpiOciLibHandle = dlopen(libName, RTLD_LAZY); - if (!dpiOciLibHandle && i == 0) { - strncpy(loadError, dlerror(), sizeof(loadError) - 1); - loadError[sizeof(loadError) - 1] = '\0'; - } -#endif - - } - -#ifndef _WIN32 - // on platforms other than Windows, attempt to use - // $ORACLE_HOME/lib/libclntsh.so - if (!dpiOciLibHandle) { - oracleHome = getenv("ORACLE_HOME"); - if (oracleHome) { - oracleHomeLibNameLength = strlen(oracleHome) + 6 + - strlen(dpiOciLibNames[0]); - oracleHomeLibName = (char*) malloc(oracleHomeLibNameLength); - if (oracleHomeLibName) { - (void) sprintf(oracleHomeLibName, "%s/lib/%s", oracleHome, - dpiOciLibNames[0]); - dpiOciLibHandle = dlopen(oracleHomeLibName, RTLD_LAZY); - free(oracleHomeLibName); - } - } - } -#endif - - if (!dpiOciLibHandle) { - const char *bits = (sizeof(void*) == 8) ? "64" : "32"; - return dpiError__set(error, "load library", DPI_ERR_LOAD_LIBRARY, - bits, loadError, DPI_ERR_LOAD_URL_FRAGMENT); - } - - // validate library - if (dpiOci__loadLibValidate(error) < 0) { -#ifdef _WIN32 - FreeLibrary(dpiOciLibHandle); -#else - dlclose(dpiOciLibHandle); -#endif - dpiOciLibHandle = NULL; - memset(&dpiOciSymbols, 0, sizeof(dpiOciSymbols)); - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__loadLibValidate() [INTERNAL] -// Validate the OCI library after loading. -//----------------------------------------------------------------------------- -static int dpiOci__loadLibValidate(dpiError *error) -{ - // determine the OCI client version information - if (dpiOci__loadSymbol("OCIClientVersion", - (void**) &dpiOciSymbols.fnClientVersion, NULL) < 0) - return dpiError__set(error, "load symbol OCIClientVersion", - DPI_ERR_ORACLE_CLIENT_UNSUPPORTED); - memset(&dpiOciLibVersionInfo, 0, sizeof(dpiOciLibVersionInfo)); - (*dpiOciSymbols.fnClientVersion)(&dpiOciLibVersionInfo.versionNum, - &dpiOciLibVersionInfo.releaseNum, - &dpiOciLibVersionInfo.updateNum, - &dpiOciLibVersionInfo.portReleaseNum, - &dpiOciLibVersionInfo.portUpdateNum); - if (dpiOciLibVersionInfo.versionNum == 0) - return dpiError__set(error, "get OCI client version", - DPI_ERR_ORACLE_CLIENT_UNSUPPORTED); - dpiOciLibVersionInfo.fullVersionNum = (uint32_t) - DPI_ORACLE_VERSION_TO_NUMBER(dpiOciLibVersionInfo.versionNum, - dpiOciLibVersionInfo.releaseNum, - dpiOciLibVersionInfo.updateNum, - dpiOciLibVersionInfo.portReleaseNum, - dpiOciLibVersionInfo.portUpdateNum); - - // OCI version must be a minimum of 11.2 - if (dpiUtils__checkClientVersion(&dpiOciLibVersionInfo, 11, 2, error) < 0) - return DPI_FAILURE; - - // initialize threading capability in the OCI library - // this must be run prior to any other OCI threading calls - DPI_OCI_LOAD_SYMBOL("OCIThreadProcessInit", - dpiOciSymbols.fnThreadProcessInit) - (*dpiOciSymbols.fnThreadProcessInit)(); - - // load symbols for key functions which are called many times - // this list should be kept as small as possible in order to avoid - // overhead in looking up symbols at startup - DPI_OCI_LOAD_SYMBOL("OCIAttrGet", dpiOciSymbols.fnAttrGet) - DPI_OCI_LOAD_SYMBOL("OCIAttrSet", dpiOciSymbols.fnAttrSet) - DPI_OCI_LOAD_SYMBOL("OCIThreadKeyGet", dpiOciSymbols.fnThreadKeyGet) - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__loadSymbol() [INTERNAL] -// Return the symbol for the function that is to be called. The symbol table -// is first consulted. If the symbol is not found there, it is looked up and -// then stored there so the next invocation does not have to perform the -// lookup. -//----------------------------------------------------------------------------- -static int dpiOci__loadSymbol(const char *symbolName, void **symbol, - dpiError *error) -{ - // if library not already opened, open it - if (!dpiOciLibHandle && dpiOci__loadLib(error) < 0) - return DPI_FAILURE; - - // load symbol -#ifdef _WIN32 - *symbol = GetProcAddress(dpiOciLibHandle, symbolName); -#else - *symbol = dlsym(dpiOciLibHandle, symbolName); -#endif - if (!*symbol) - return dpiError__set(error, "get symbol", DPI_ERR_LOAD_SYMBOL, - symbolName); - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobClose() [INTERNAL] -// Wrapper for OCILobClose(). -//----------------------------------------------------------------------------- -int dpiOci__lobClose(dpiLob *lob, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobClose", dpiOciSymbols.fnLobClose) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobClose)(lob->conn->handle, error->handle, - lob->locator); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "close LOB"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobCreateTemporary() [INTERNAL] -// Wrapper for OCILobCreateTemporary(). -//----------------------------------------------------------------------------- -int dpiOci__lobCreateTemporary(dpiLob *lob, dpiError *error) -{ - uint8_t lobType; - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobCreateTemporary", - dpiOciSymbols.fnLobCreateTemporary) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BLOB) - lobType = DPI_OCI_TEMP_BLOB; - else lobType = DPI_OCI_TEMP_CLOB; - status = (*dpiOciSymbols.fnLobCreateTemporary)(lob->conn->handle, - error->handle, lob->locator, DPI_OCI_DEFAULT, - lob->type->charsetForm, lobType, 1, DPI_OCI_DURATION_SESSION); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "create temporary LOB"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobFileExists() [INTERNAL] -// Wrapper for OCILobFileExists(). -//----------------------------------------------------------------------------- -int dpiOci__lobFileExists(dpiLob *lob, int *exists, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobFileExists", dpiOciSymbols.fnLobFileExists) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobFileExists)(lob->conn->handle, error->handle, - lob->locator, exists); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get file exists"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobFileGetName() [INTERNAL] -// Wrapper for OCILobFileGetName(). -//----------------------------------------------------------------------------- -int dpiOci__lobFileGetName(dpiLob *lob, char *dirAlias, - uint16_t *dirAliasLength, char *name, uint16_t *nameLength, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobFileGetName", dpiOciSymbols.fnLobFileGetName) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobFileGetName)(lob->env->handle, error->handle, - lob->locator, dirAlias, dirAliasLength, name, nameLength); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get LOB file name"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobFileSetName() [INTERNAL] -// Wrapper for OCILobFileSetName(). -//----------------------------------------------------------------------------- -int dpiOci__lobFileSetName(dpiLob *lob, const char *dirAlias, - uint16_t dirAliasLength, const char *name, uint16_t nameLength, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobFileSetName", dpiOciSymbols.fnLobFileSetName) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobFileSetName)(lob->env->handle, error->handle, - &lob->locator, dirAlias, dirAliasLength, name, nameLength); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "set LOB file name"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobFreeTemporary() [INTERNAL] -// Wrapper for OCILobFreeTemporary(). -//----------------------------------------------------------------------------- -int dpiOci__lobFreeTemporary(dpiConn *conn, void *lobLocator, int checkError, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobFreeTemporary", - dpiOciSymbols.fnLobFreeTemporary) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobFreeTemporary)(conn->handle, - error->handle, lobLocator); - if (!checkError) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "free temporary LOB"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobGetChunkSize() [INTERNAL] -// Wrapper for OCILobGetChunkSize(). -//----------------------------------------------------------------------------- -int dpiOci__lobGetChunkSize(dpiLob *lob, uint32_t *size, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobGetChunkSize", dpiOciSymbols.fnLobGetChunkSize) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobGetChunkSize)(lob->conn->handle, - error->handle, lob->locator, size); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get chunk size"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobGetLength2() [INTERNAL] -// Wrapper for OCILobGetLength2(). -//----------------------------------------------------------------------------- -int dpiOci__lobGetLength2(dpiLob *lob, uint64_t *size, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobGetLength2", dpiOciSymbols.fnLobGetLength2) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobGetLength2)(lob->conn->handle, error->handle, - lob->locator, size); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get length"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobIsOpen() [INTERNAL] -// Wrapper for OCILobIsOpen(). -//----------------------------------------------------------------------------- -int dpiOci__lobIsOpen(dpiLob *lob, int *isOpen, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobIsOpen", dpiOciSymbols.fnLobIsOpen) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobIsOpen)(lob->conn->handle, error->handle, - lob->locator, isOpen); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "check is open"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobIsTemporary() [INTERNAL] -// Wrapper for OCILobIsTemporary(). -//----------------------------------------------------------------------------- -int dpiOci__lobIsTemporary(dpiLob *lob, int *isTemporary, int checkError, - dpiError *error) -{ - int status; - - *isTemporary = 0; - DPI_OCI_LOAD_SYMBOL("OCILobIsTemporary", dpiOciSymbols.fnLobIsTemporary) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobIsTemporary)(lob->env->handle, error->handle, - lob->locator, isTemporary); - if (!checkError) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "check is temporary"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobLocatorAssign() [INTERNAL] -// Wrapper for OCILobLocatorAssign(). -//----------------------------------------------------------------------------- -int dpiOci__lobLocatorAssign(dpiLob *lob, void **copiedHandle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobLocatorAssign", - dpiOciSymbols.fnLobLocatorAssign) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobLocatorAssign)(lob->conn->handle, - error->handle, lob->locator, copiedHandle); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "assign locator"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobOpen() [INTERNAL] -// Wrapper for OCILobOpen(). -//----------------------------------------------------------------------------- -int dpiOci__lobOpen(dpiLob *lob, dpiError *error) -{ - uint8_t mode; - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobOpen", dpiOciSymbols.fnLobOpen) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - mode = (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE) ? - DPI_OCI_LOB_READONLY : DPI_OCI_LOB_READWRITE; - status = (*dpiOciSymbols.fnLobOpen)(lob->conn->handle, error->handle, - lob->locator, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "close LOB"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobRead2() [INTERNAL] -// Wrapper for OCILobRead2(). -//----------------------------------------------------------------------------- -int dpiOci__lobRead2(dpiLob *lob, uint64_t offset, uint64_t *amountInBytes, - uint64_t *amountInChars, char *buffer, uint64_t bufferLength, - dpiError *error) -{ - uint16_t charsetId; - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobRead2", dpiOciSymbols.fnLobRead2) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - charsetId = (lob->type->charsetForm == DPI_SQLCS_NCHAR) ? - lob->env->ncharsetId : lob->env->charsetId; - status = (*dpiOciSymbols.fnLobRead2)(lob->conn->handle, error->handle, - lob->locator, amountInBytes, amountInChars, offset, buffer, - bufferLength, DPI_OCI_ONE_PIECE, NULL, NULL, charsetId, - lob->type->charsetForm); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "read from LOB"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobTrim2() [INTERNAL] -// Wrapper for OCILobTrim2(). -//----------------------------------------------------------------------------- -int dpiOci__lobTrim2(dpiLob *lob, uint64_t newLength, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobTrim2", dpiOciSymbols.fnLobTrim2) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnLobTrim2)(lob->conn->handle, error->handle, - lob->locator, newLength); - if (status == DPI_OCI_INVALID_HANDLE) - return dpiOci__lobCreateTemporary(lob, error); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "trim LOB"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__lobWrite2() [INTERNAL] -// Wrapper for OCILobWrite2(). -//----------------------------------------------------------------------------- -int dpiOci__lobWrite2(dpiLob *lob, uint64_t offset, const char *value, - uint64_t valueLength, dpiError *error) -{ - uint64_t lengthInBytes = valueLength, lengthInChars = 0; - uint16_t charsetId; - int status; - - DPI_OCI_LOAD_SYMBOL("OCILobWrite2", dpiOciSymbols.fnLobWrite2) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - charsetId = (lob->type->charsetForm == DPI_SQLCS_NCHAR) ? - lob->env->ncharsetId : lob->env->charsetId; - status = (*dpiOciSymbols.fnLobWrite2)(lob->conn->handle, error->handle, - lob->locator, &lengthInBytes, &lengthInChars, offset, (void*) value, - valueLength, DPI_OCI_ONE_PIECE, NULL, NULL, charsetId, - lob->type->charsetForm); - DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "write to LOB"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__memoryAlloc() [INTERNAL] -// Wrapper for OCIMemoryAlloc(). -//----------------------------------------------------------------------------- -int dpiOci__memoryAlloc(dpiConn *conn, void **ptr, uint32_t size, - int checkError, dpiError *error) -{ - int status; - - *ptr = NULL; - DPI_OCI_LOAD_SYMBOL("OCIMemoryAlloc", dpiOciSymbols.fnMemoryAlloc) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnMemoryAlloc)(conn->sessionHandle, error->handle, - ptr, DPI_OCI_DURATION_SESSION, size, DPI_OCI_MEMORY_CLEARED); - if (!checkError) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "allocate memory"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__memoryFree() [INTERNAL] -// Wrapper for OCIMemoryFree(). -//----------------------------------------------------------------------------- -int dpiOci__memoryFree(dpiConn *conn, void *ptr, dpiError *error) -{ - DPI_OCI_LOAD_SYMBOL("OCIMemoryFree", dpiOciSymbols.fnMemoryFree) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - (*dpiOciSymbols.fnMemoryFree)(conn->sessionHandle, error->handle, ptr); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__nlsCharSetConvert() [INTERNAL] -// Wrapper for OCINlsCharSetConvert(). -//----------------------------------------------------------------------------- -int dpiOci__nlsCharSetConvert(void *envHandle, uint16_t destCharsetId, - char *dest, size_t destLength, uint16_t sourceCharsetId, - const char *source, size_t sourceLength, size_t *resultSize, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCINlsCharSetConvert", - dpiOciSymbols.fnNlsCharSetConvert) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnNlsCharSetConvert)(envHandle, error->handle, - destCharsetId, dest, destLength, sourceCharsetId, source, - sourceLength, resultSize); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "convert text"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__nlsCharSetIdToName() [INTERNAL] -// Wrapper for OCINlsCharSetIdToName(). -//----------------------------------------------------------------------------- -int dpiOci__nlsCharSetIdToName(void *envHandle, char *buf, size_t bufLength, - uint16_t charsetId, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCINlsCharSetIdToName", - dpiOciSymbols.fnNlsCharSetIdToName) - status = (*dpiOciSymbols.fnNlsCharSetIdToName)(envHandle, buf, bufLength, - charsetId); - return (status == DPI_OCI_SUCCESS) ? DPI_SUCCESS : DPI_FAILURE; -} - - -//----------------------------------------------------------------------------- -// dpiOci__nlsCharSetNameToId() [INTERNAL] -// Wrapper for OCINlsCharSetNameToId(). -//----------------------------------------------------------------------------- -int dpiOci__nlsCharSetNameToId(void *envHandle, const char *name, - uint16_t *charsetId, dpiError *error) -{ - DPI_OCI_LOAD_SYMBOL("OCINlsCharSetNameToId", - dpiOciSymbols.fnNlsCharSetNameToId) - *charsetId = (*dpiOciSymbols.fnNlsCharSetNameToId)(envHandle, name); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__nlsEnvironmentVariableGet() [INTERNAL] -// Wrapper for OCIEnvironmentVariableGet(). -//----------------------------------------------------------------------------- -int dpiOci__nlsEnvironmentVariableGet(uint16_t item, void *value, - dpiError *error) -{ - size_t ignored; - int status; - - DPI_OCI_LOAD_SYMBOL("OCINlsEnvironmentVariableGet", - dpiOciSymbols.fnNlsEnvironmentVariableGet) - status = (*dpiOciSymbols.fnNlsEnvironmentVariableGet)(value, 0, item, 0, - &ignored); - if (status != DPI_OCI_SUCCESS) - return dpiError__set(error, "get NLS environment variable", - DPI_ERR_NLS_ENV_VAR_GET); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__nlsNameMap() [INTERNAL] -// Wrapper for OCINlsNameMap(). -//----------------------------------------------------------------------------- -int dpiOci__nlsNameMap(void *envHandle, char *buf, size_t bufLength, - const char *source, uint32_t flag, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCINlsNameMap", dpiOciSymbols.fnNlsNameMap) - status = (*dpiOciSymbols.fnNlsNameMap)(envHandle, buf, bufLength, source, - flag); - return (status == DPI_OCI_SUCCESS) ? DPI_SUCCESS : DPI_FAILURE; -} - - -//----------------------------------------------------------------------------- -// dpiOci__nlsNumericInfoGet() [INTERNAL] -// Wrapper for OCINlsNumericInfoGet(). -//----------------------------------------------------------------------------- -int dpiOci__nlsNumericInfoGet(void *envHandle, int32_t *value, uint16_t item, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCINlsNumericInfoGet", - dpiOciSymbols.fnNlsNumericInfoGet) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnNlsNumericInfoGet)(envHandle, error->handle, - value, item); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get NLS info"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__numberFromInt() [INTERNAL] -// Wrapper for OCINumberFromInt(). -//----------------------------------------------------------------------------- -int dpiOci__numberFromInt(const void *value, unsigned int valueLength, - unsigned int flags, void *number, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCINumberFromInt", dpiOciSymbols.fnNumberFromInt) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnNumberFromInt)(error->handle, value, - valueLength, flags, number); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number from integer"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__numberFromReal() [INTERNAL] -// Wrapper for OCINumberFromReal(). -//----------------------------------------------------------------------------- -int dpiOci__numberFromReal(const double value, void *number, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCINumberFromReal", dpiOciSymbols.fnNumberFromReal) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnNumberFromReal)(error->handle, &value, - sizeof(double), number); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number from real"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__numberToInt() [INTERNAL] -// Wrapper for OCINumberToInt(). -//----------------------------------------------------------------------------- -int dpiOci__numberToInt(void *number, void *value, unsigned int valueLength, - unsigned int flags, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCINumberToInt", dpiOciSymbols.fnNumberToInt) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnNumberToInt)(error->handle, number, valueLength, - flags, value); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number to integer"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__numberToReal() [INTERNAL] -// Wrapper for OCINumberToReal(). -//----------------------------------------------------------------------------- -int dpiOci__numberToReal(double *value, void *number, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCINumberToReal", dpiOciSymbols.fnNumberToReal) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnNumberToReal)(error->handle, number, - sizeof(double), value); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number to real"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__objectCopy() [INTERNAL] -// Wrapper for OCIObjectCopy(). -//----------------------------------------------------------------------------- -int dpiOci__objectCopy(dpiObject *obj, void *sourceInstance, - void *sourceIndicator, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIObjectCopy", dpiOciSymbols.fnObjectCopy) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnObjectCopy)(obj->env->handle, error->handle, - obj->type->conn->handle, sourceInstance, sourceIndicator, - obj->instance, obj->indicator, obj->type->tdo, - DPI_OCI_DURATION_SESSION, DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "copy object"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__objectFree() [INTERNAL] -// Wrapper for OCIObjectFree(). -//----------------------------------------------------------------------------- -int dpiOci__objectFree(void *envHandle, void *data, int checkError, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIObjectFree", dpiOciSymbols.fnObjectFree) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnObjectFree)(envHandle, error->handle, data, - DPI_OCI_DEFAULT); - if (checkError && DPI_OCI_ERROR_OCCURRED(status)) { - dpiError__setFromOCI(error, status, NULL, "free instance"); - - // during the attempt to free, PL/SQL records fail with error - // "ORA-21602: operation does not support the specified typecode", but - // a subsequent attempt will yield error "OCI-21500: internal error - // code" and crash the process, so pretend like the free was - // successful! - if (error->buffer->code == 21602) - return DPI_SUCCESS; - return DPI_FAILURE; - } - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__objectGetAttr() [INTERNAL] -// Wrapper for OCIObjectGetAttr(). -//----------------------------------------------------------------------------- -int dpiOci__objectGetAttr(dpiObject *obj, dpiObjectAttr *attr, - int16_t *scalarValueIndicator, void **valueIndicator, void **value, - void **tdo, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIObjectGetAttr", dpiOciSymbols.fnObjectGetAttr) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnObjectGetAttr)(obj->env->handle, error->handle, - obj->instance, obj->indicator, obj->type->tdo, &attr->name, - &attr->nameLength, 1, 0, 0, scalarValueIndicator, valueIndicator, - value, tdo); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get attribute"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__objectGetInd() [INTERNAL] -// Wrapper for OCIObjectGetInd(). -//----------------------------------------------------------------------------- -int dpiOci__objectGetInd(dpiObject *obj, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIObjectGetInd", dpiOciSymbols.fnObjectGetInd) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnObjectGetInd)(obj->env->handle, error->handle, - obj->instance, &obj->indicator); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get indicator"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__objectNew() [INTERNAL] -// Wrapper for OCIObjectNew(). -//----------------------------------------------------------------------------- -int dpiOci__objectNew(dpiObject *obj, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIObjectNew", dpiOciSymbols.fnObjectNew) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnObjectNew)(obj->env->handle, error->handle, - obj->type->conn->handle, obj->type->typeCode, obj->type->tdo, NULL, - DPI_OCI_DURATION_SESSION, 1, &obj->instance); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "create object"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__objectPin() [INTERNAL] -// Wrapper for OCIObjectPin(). -//----------------------------------------------------------------------------- -int dpiOci__objectPin(void *envHandle, void *objRef, void **obj, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIObjectPin", dpiOciSymbols.fnObjectPin) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnObjectPin)(envHandle, error->handle, objRef, - NULL, DPI_OCI_PIN_ANY, DPI_OCI_DURATION_SESSION, DPI_OCI_LOCK_NONE, - obj); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "pin reference"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__objectSetAttr() [INTERNAL] -// Wrapper for OCIObjectSetAttr(). -//----------------------------------------------------------------------------- -int dpiOci__objectSetAttr(dpiObject *obj, dpiObjectAttr *attr, - int16_t scalarValueIndicator, void *valueIndicator, const void *value, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIObjectSetAttr", dpiOciSymbols.fnObjectSetAttr) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnObjectSetAttr)(obj->env->handle, error->handle, - obj->instance, obj->indicator, obj->type->tdo, &attr->name, - &attr->nameLength, 1, NULL, 0, scalarValueIndicator, - valueIndicator, value); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "set attribute"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__passwordChange() [INTERNAL] -// Wrapper for OCIPasswordChange(). -//----------------------------------------------------------------------------- -int dpiOci__passwordChange(dpiConn *conn, const char *userName, - uint32_t userNameLength, const char *oldPassword, - uint32_t oldPasswordLength, const char *newPassword, - uint32_t newPasswordLength, uint32_t mode, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIPasswordChange", dpiOciSymbols.fnPasswordChange) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnPasswordChange)(conn->handle, error->handle, - userName, userNameLength, oldPassword, oldPasswordLength, - newPassword, newPasswordLength, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "change password"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__paramGet() [INTERNAL] -// Wrapper for OCIParamGet(). -//----------------------------------------------------------------------------- -int dpiOci__paramGet(const void *handle, uint32_t handleType, void **parameter, - uint32_t pos, const char *action, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIParamGet", dpiOciSymbols.fnParamGet) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnParamGet)(handle, handleType, error->handle, - parameter, pos); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); -} - - -//----------------------------------------------------------------------------- -// dpiOci__ping() [INTERNAL] -// Wrapper for OCIPing(). -//----------------------------------------------------------------------------- -int dpiOci__ping(dpiConn *conn, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIPing", dpiOciSymbols.fnPing) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnPing)(conn->handle, error->handle, - DPI_OCI_DEFAULT); - if (DPI_OCI_ERROR_OCCURRED(status)) { - dpiError__setFromOCI(error, status, conn, "ping"); - - // attempting to ping a database earlier than 10g will result in error - // ORA-1010: invalid OCI operation, but that implies a successful ping - // so ignore that error and treat it as a successful operation - if (error->buffer->code == 1010) - return DPI_SUCCESS; - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__rawAssignBytes() [INTERNAL] -// Wrapper for OCIRawAssignBytes(). -//----------------------------------------------------------------------------- -int dpiOci__rawAssignBytes(void *envHandle, const char *value, - uint32_t valueLength, void **handle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIRawAssignBytes", dpiOciSymbols.fnRawAssignBytes) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnRawAssignBytes)(envHandle, error->handle, value, - valueLength, handle); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "assign bytes to raw"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__rawPtr() [INTERNAL] -// Wrapper for OCIRawPtr(). -//----------------------------------------------------------------------------- -int dpiOci__rawPtr(void *envHandle, void *handle, void **ptr) -{ - dpiError *error = NULL; - - DPI_OCI_LOAD_SYMBOL("OCIRawPtr", dpiOciSymbols.fnRawPtr) - *ptr = (*dpiOciSymbols.fnRawPtr)(envHandle, handle); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__rawResize() [INTERNAL] -// Wrapper for OCIRawResize(). -//----------------------------------------------------------------------------- -int dpiOci__rawResize(void *envHandle, void **handle, uint32_t newSize, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIRawResize", dpiOciSymbols.fnRawResize) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnRawResize)(envHandle, error->handle, newSize, - handle); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "resize raw"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__rawSize() [INTERNAL] -// Wrapper for OCIRawSize(). -//----------------------------------------------------------------------------- -int dpiOci__rawSize(void *envHandle, void *handle, uint32_t *size) -{ - dpiError *error = NULL; - - DPI_OCI_LOAD_SYMBOL("OCIRawSize", dpiOciSymbols.fnRawSize) - *size = (*dpiOciSymbols.fnRawSize)(envHandle, handle); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__reallocMem() [INTERNAL] -// Wrapper for OCI allocation of memory, only used when debugging memory -// allocation. -//----------------------------------------------------------------------------- -static void *dpiOci__reallocMem(UNUSED void *unused, void *ptr, size_t newSize) -{ - char message[80]; - void *newPtr; - - (void) sprintf(message, "OCI reallocated ptr at %p", ptr); - newPtr = realloc(ptr, newSize); - dpiDebug__print("%s to %u bytes at %p\n", message, newSize, newPtr); - return newPtr; -} - - -//----------------------------------------------------------------------------- -// dpiOci__rowidToChar() [INTERNAL] -// Wrapper for OCIRowidToChar(). -//----------------------------------------------------------------------------- -int dpiOci__rowidToChar(dpiRowid *rowid, char *buffer, uint16_t *bufferSize, - dpiError *error) -{ - uint16_t origSize; - int status; - - DPI_OCI_LOAD_SYMBOL("OCIRowidToChar", dpiOciSymbols.fnRowidToChar) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - origSize = *bufferSize; - status = (*dpiOciSymbols.fnRowidToChar)(rowid->handle, buffer, bufferSize, - error->handle); - if (origSize == 0) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get rowid as string"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__serverAttach() [INTERNAL] -// Wrapper for OCIServerAttach(). -//----------------------------------------------------------------------------- -int dpiOci__serverAttach(dpiConn *conn, const char *connectString, - uint32_t connectStringLength, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIServerAttach", dpiOciSymbols.fnServerAttach) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnServerAttach)(conn->serverHandle, error->handle, - connectString, (int32_t) connectStringLength, DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "server attach"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__serverDetach() [INTERNAL] -// Wrapper for OCIServerDetach(). -//----------------------------------------------------------------------------- -int dpiOci__serverDetach(dpiConn *conn, int checkError, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIServerDetach", dpiOciSymbols.fnServerDetach) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnServerDetach)(conn->serverHandle, error->handle, - DPI_OCI_DEFAULT); - if (!checkError) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "detatch from server"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__serverRelease() [INTERNAL] -// Wrapper for OCIServerRelease(). -//----------------------------------------------------------------------------- -int dpiOci__serverRelease(dpiConn *conn, char *buffer, uint32_t bufferSize, - uint32_t *version, dpiError *error) -{ - int status; - - DPI_OCI_ENSURE_ERROR_HANDLE(error) - if (conn->env->versionInfo->versionNum < 18) { - DPI_OCI_LOAD_SYMBOL("OCIServerRelease", dpiOciSymbols.fnServerRelease) - status = (*dpiOciSymbols.fnServerRelease)(conn->handle, error->handle, - buffer, bufferSize, DPI_OCI_HTYPE_SVCCTX, version); - } else { - DPI_OCI_LOAD_SYMBOL("OCIServerRelease2", - dpiOciSymbols.fnServerRelease2) - status = (*dpiOciSymbols.fnServerRelease2)(conn->handle, error->handle, - buffer, bufferSize, DPI_OCI_HTYPE_SVCCTX, version, - DPI_OCI_DEFAULT); - } - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get server version"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sessionBegin() [INTERNAL] -// Wrapper for OCISessionBegin(). -//----------------------------------------------------------------------------- -int dpiOci__sessionBegin(dpiConn *conn, uint32_t credentialType, - uint32_t mode, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISessionBegin", dpiOciSymbols.fnSessionBegin) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSessionBegin)(conn->handle, error->handle, - conn->sessionHandle, credentialType, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "begin session"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sessionEnd() [INTERNAL] -// Wrapper for OCISessionEnd(). -//----------------------------------------------------------------------------- -int dpiOci__sessionEnd(dpiConn *conn, int checkError, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISessionEnd", dpiOciSymbols.fnSessionEnd) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSessionEnd)(conn->handle, error->handle, - conn->sessionHandle, DPI_OCI_DEFAULT); - if (!checkError) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "end session"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sessionGet() [INTERNAL] -// Wrapper for OCISessionGet(). -//----------------------------------------------------------------------------- -int dpiOci__sessionGet(void *envHandle, void **handle, void *authInfo, - const char *connectString, uint32_t connectStringLength, - const char *tag, uint32_t tagLength, const char **outTag, - uint32_t *outTagLength, int *found, uint32_t mode, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISessionGet", dpiOciSymbols.fnSessionGet) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSessionGet)(envHandle, error->handle, handle, - authInfo, connectString, connectStringLength, tag, tagLength, - outTag, outTagLength, found, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get session"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sessionPoolCreate() [INTERNAL] -// Wrapper for OCISessionPoolCreate(). -//----------------------------------------------------------------------------- -int dpiOci__sessionPoolCreate(dpiPool *pool, const char *connectString, - uint32_t connectStringLength, uint32_t minSessions, - uint32_t maxSessions, uint32_t sessionIncrement, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - uint32_t mode, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISessionPoolCreate", - dpiOciSymbols.fnSessionPoolCreate) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSessionPoolCreate)(pool->env->handle, - error->handle, pool->handle, (char**) &pool->name, - &pool->nameLength, connectString, connectStringLength, minSessions, - maxSessions, sessionIncrement, userName, userNameLength, password, - passwordLength, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "create pool"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sessionPoolDestroy() [INTERNAL] -// Wrapper for OCISessionPoolDestroy(). -//----------------------------------------------------------------------------- -int dpiOci__sessionPoolDestroy(dpiPool *pool, uint32_t mode, int checkError, - dpiError *error) -{ - void *handle; - int status; - - DPI_OCI_LOAD_SYMBOL("OCISessionPoolDestroy", - dpiOciSymbols.fnSessionPoolDestroy) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - - // clear the pool handle immediately so that no further attempts are made - // to use the pool while the pool is being closed; if the pool close fails, - // restore the pool handle afterwards - handle = pool->handle; - pool->handle = NULL; - status = (*dpiOciSymbols.fnSessionPoolDestroy)(handle, error->handle, - mode); - if (checkError && DPI_OCI_ERROR_OCCURRED(status)) { - pool->handle = handle; - return dpiError__setFromOCI(error, status, NULL, "destroy pool"); - } - dpiOci__handleFree(handle, DPI_OCI_HTYPE_SPOOL); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__sessionRelease() [INTERNAL] -// Wrapper for OCISessionRelease(). -//----------------------------------------------------------------------------- -int dpiOci__sessionRelease(dpiConn *conn, const char *tag, uint32_t tagLength, - uint32_t mode, int checkError, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISessionRelease", dpiOciSymbols.fnSessionRelease) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSessionRelease)(conn->handle, error->handle, - tag, tagLength, mode); - if (!checkError) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "release session"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__shardingKeyColumnAdd() [INTERNAL] -// Wrapper for OCIshardingKeyColumnAdd(). -//----------------------------------------------------------------------------- -int dpiOci__shardingKeyColumnAdd(void *shardingKey, void *col, uint32_t colLen, - uint16_t colType, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIShardingKeyColumnAdd", - dpiOciSymbols.fnShardingKeyColumnAdd) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnShardingKeyColumnAdd)(shardingKey, - error->handle, col, colLen, colType, DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "add sharding column"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaBulkInsert() [INTERNAL] -// Wrapper for OCISodaBulkInsert(). -//----------------------------------------------------------------------------- -int dpiOci__sodaBulkInsert(dpiSodaColl *coll, void **documents, - uint32_t numDocuments, void *outputOptions, uint32_t mode, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaBulkInsert", dpiOciSymbols.fnSodaBulkInsert) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaBulkInsert)(coll->db->conn->handle, - coll->handle, documents, numDocuments, outputOptions, - error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "insert multiple documents"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaBulkInsertAndGet() [INTERNAL] -// Wrapper for OCISodaBulkInsert(). -//----------------------------------------------------------------------------- -int dpiOci__sodaBulkInsertAndGet(dpiSodaColl *coll, void **documents, - uint32_t numDocuments, void *outputOptions, uint32_t mode, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaBulkInsertAndGet", - dpiOciSymbols.fnSodaBulkInsertAndGet) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaBulkInsertAndGet)(coll->db->conn->handle, - coll->handle, documents, numDocuments, outputOptions, - error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "insert (and get) multiple documents"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaCollCreateWithMetadata() [INTERNAL] -// Wrapper for OCISodaCollCreateWithMetadata(). -//----------------------------------------------------------------------------- -int dpiOci__sodaCollCreateWithMetadata(dpiSodaDb *db, const char *name, - uint32_t nameLength, const char *metadata, uint32_t metadataLength, - uint32_t mode, void **handle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaCollCreateWithMetadata", - dpiOciSymbols.fnSodaCollCreateWithMetadata) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaCollCreateWithMetadata)(db->conn->handle, - name, nameLength, metadata, metadataLength, handle, error->handle, - mode); - DPI_OCI_CHECK_AND_RETURN(error, status, db->conn, - "create SODA collection"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaCollDrop() [INTERNAL] -// Wrapper for OCISodaCollDrop(). -//----------------------------------------------------------------------------- -int dpiOci__sodaCollDrop(dpiSodaColl *coll, int *isDropped, uint32_t mode, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaCollDrop", dpiOciSymbols.fnSodaCollDrop) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaCollDrop)(coll->db->conn->handle, - coll->handle, isDropped, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "drop SODA collection"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaCollGetNext() [INTERNAL] -// Wrapper for OCISodaCollGetNext(). -//----------------------------------------------------------------------------- -int dpiOci__sodaCollGetNext(dpiConn *conn, void *cursorHandle, - void **collectionHandle, uint32_t mode, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaCollGetNext", dpiOciSymbols.fnSodaCollGetNext) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaCollGetNext)(conn->handle, cursorHandle, - collectionHandle, error->handle, mode); - if (status == DPI_OCI_NO_DATA) { - *collectionHandle = NULL; - return DPI_SUCCESS; - } - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get next collection"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaCollList() [INTERNAL] -// Wrapper for OCISodaCollList(). -//----------------------------------------------------------------------------- -int dpiOci__sodaCollList(dpiSodaDb *db, const char *startingName, - uint32_t startingNameLength, void **handle, uint32_t mode, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaCollList", dpiOciSymbols.fnSodaCollList) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaCollList)(db->conn->handle, startingName, - startingNameLength, handle, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, db->conn, - "get SODA collection cursor"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaCollOpen() [INTERNAL] -// Wrapper for OCISodaCollOpen(). -//----------------------------------------------------------------------------- -int dpiOci__sodaCollOpen(dpiSodaDb *db, const char *name, uint32_t nameLength, - uint32_t mode, void **handle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaCollOpen", dpiOciSymbols.fnSodaCollOpen) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaCollOpen)(db->conn->handle, name, - nameLength, handle, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, db->conn, "open SODA collection"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaDataGuideGet() [INTERNAL] -// Wrapper for OCISodaDataGuideGet(). -//----------------------------------------------------------------------------- -int dpiOci__sodaDataGuideGet(dpiSodaColl *coll, void **handle, uint32_t mode, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaDataGuideGet", - dpiOciSymbols.fnSodaDataGuideGet) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaDataGuideGet)(coll->db->conn->handle, - coll->handle, DPI_OCI_DEFAULT, handle, error->handle, mode); - if (DPI_OCI_ERROR_OCCURRED(status)) { - dpiError__setFromOCI(error, status, coll->db->conn, "get data guide"); - if (error->buffer->code != 24801) - return DPI_FAILURE; - *handle = NULL; - } - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaDocCount() [INTERNAL] -// Wrapper for OCISodaDocCount(). -//----------------------------------------------------------------------------- -int dpiOci__sodaDocCount(dpiSodaColl *coll, void *options, uint32_t mode, - uint64_t *count, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaDocCount", dpiOciSymbols.fnSodaDocCount) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaDocCount)(coll->db->conn->handle, - coll->handle, options, count, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "get document count"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaDocGetNext() [INTERNAL] -// Wrapper for OCISodaDocGetNext(). -//----------------------------------------------------------------------------- -int dpiOci__sodaDocGetNext(dpiSodaDocCursor *cursor, void **handle, - uint32_t mode, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaDocGetNext", dpiOciSymbols.fnSodaDocGetNext) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaDocGetNext)(cursor->coll->db->conn->handle, - cursor->handle, handle, error->handle, mode); - if (status == DPI_OCI_NO_DATA) { - *handle = NULL; - return DPI_SUCCESS; - } - DPI_OCI_CHECK_AND_RETURN(error, status, cursor->coll->db->conn, - "get next document"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaFind() [INTERNAL] -// Wrapper for OCISodaFind(). -//----------------------------------------------------------------------------- -int dpiOci__sodaFind(dpiSodaColl *coll, const void *options, uint32_t flags, - uint32_t mode, void **handle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaFind", dpiOciSymbols.fnSodaFind) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaFind)(coll->db->conn->handle, - coll->handle, options, flags, handle, error->handle, mode); - if (status == DPI_OCI_NO_DATA) { - *handle = NULL; - return DPI_SUCCESS; - } - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "find SODA documents"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaFindOne() [INTERNAL] -// Wrapper for OCISodaFindOne(). -//----------------------------------------------------------------------------- -int dpiOci__sodaFindOne(dpiSodaColl *coll, const void *options, uint32_t flags, - uint32_t mode, void **handle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaFindOne", dpiOciSymbols.fnSodaFindOne) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaFindOne)(coll->db->conn->handle, - coll->handle, options, flags, handle, error->handle, mode); - if (status == DPI_OCI_NO_DATA) { - *handle = NULL; - return DPI_SUCCESS; - } - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "get SODA document"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaIndexCreate() [INTERNAL] -// Wrapper for OCISodaIndexCreate(). -//----------------------------------------------------------------------------- -int dpiOci__sodaIndexCreate(dpiSodaColl *coll, const char *indexSpec, - uint32_t indexSpecLength, uint32_t mode, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaIndexCreate", dpiOciSymbols.fnSodaIndexCreate) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaIndexCreate)(coll->db->conn->handle, - coll->handle, indexSpec, indexSpecLength, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "create index"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaIndexDrop() [INTERNAL] -// Wrapper for OCISodaIndexDrop(). -//----------------------------------------------------------------------------- -int dpiOci__sodaIndexDrop(dpiSodaColl *coll, const char *name, - uint32_t nameLength, uint32_t mode, int *isDropped, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaIndexDrop", dpiOciSymbols.fnSodaIndexDrop) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaIndexDrop)(coll->db->conn->handle, name, - nameLength, isDropped, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "drop index"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaInsert() [INTERNAL] -// Wrapper for OCISodaInsert(). -//----------------------------------------------------------------------------- -int dpiOci__sodaInsert(dpiSodaColl *coll, void *handle, uint32_t mode, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaInsert", dpiOciSymbols.fnSodaInsert) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaInsert)(coll->db->conn->handle, - coll->handle, handle, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "insert SODA document"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaInsertAndGet() [INTERNAL] -// Wrapper for OCISodaInsertAndGet(). -//----------------------------------------------------------------------------- -int dpiOci__sodaInsertAndGet(dpiSodaColl *coll, void **handle, uint32_t mode, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaInsertAndGet", - dpiOciSymbols.fnSodaInsertAndGet) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaInsertAndGet)(coll->db->conn->handle, - coll->handle, handle, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "insert and get SODA document"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaOperKeysSet() [INTERNAL] -// Wrapper for OCISodaOperKeysSet(). -//----------------------------------------------------------------------------- -int dpiOci__sodaOperKeysSet(const dpiSodaOperOptions *options, void *handle, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaOperKeysSet", dpiOciSymbols.fnSodaOperKeysSet) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaOperKeysSet)(handle, options->keys, - options->keyLengths, options->numKeys, error->handle, - DPI_OCI_DEFAULT); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, - "set operation options keys"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaRemove() [INTERNAL] -// Wrapper for OCISodaRemove(). -//----------------------------------------------------------------------------- -int dpiOci__sodaRemove(dpiSodaColl *coll, void *options, uint32_t mode, - uint64_t *count, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaRemove", dpiOciSymbols.fnSodaRemove) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaRemove)(coll->db->conn->handle, - coll->handle, options, count, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "remove documents from SODA collection"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaReplOne() [INTERNAL] -// Wrapper for OCISodaReplOne(). -//----------------------------------------------------------------------------- -int dpiOci__sodaReplOne(dpiSodaColl *coll, const void *options, void *handle, - uint32_t mode, int *isReplaced, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaReplOne", dpiOciSymbols.fnSodaReplOne) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaReplOne)(coll->db->conn->handle, - coll->handle, options, handle, isReplaced, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "replace SODA document"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__sodaReplOneAndGet() [INTERNAL] -// Wrapper for OCISodaReplOneAndGet(). -//----------------------------------------------------------------------------- -int dpiOci__sodaReplOneAndGet(dpiSodaColl *coll, const void *options, - void **handle, uint32_t mode, int *isReplaced, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISodaReplOneAndGet", - dpiOciSymbols.fnSodaReplOneAndGet) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSodaReplOneAndGet)(coll->db->conn->handle, - coll->handle, options, handle, isReplaced, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, - "replace and get SODA document"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__stmtExecute() [INTERNAL] -// Wrapper for OCIStmtExecute(). -//----------------------------------------------------------------------------- -int dpiOci__stmtExecute(dpiStmt *stmt, uint32_t numIters, uint32_t mode, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIStmtExecute", dpiOciSymbols.fnStmtExecute) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnStmtExecute)(stmt->conn->handle, stmt->handle, - error->handle, numIters, 0, 0, 0, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "execute"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__stmtFetch2() [INTERNAL] -// Wrapper for OCIStmtFetch2(). -//----------------------------------------------------------------------------- -int dpiOci__stmtFetch2(dpiStmt *stmt, uint32_t numRows, uint16_t fetchMode, - int32_t offset, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIStmtFetch2", dpiOciSymbols.fnStmtFetch2) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnStmtFetch2)(stmt->handle, error->handle, - numRows, fetchMode, offset, DPI_OCI_DEFAULT); - if (status == DPI_OCI_NO_DATA || fetchMode == DPI_MODE_FETCH_LAST) { - stmt->hasRowsToFetch = 0; - } else if (DPI_OCI_ERROR_OCCURRED(status)) { - return dpiError__setFromOCI(error, status, stmt->conn, "fetch"); - } else { - stmt->hasRowsToFetch = 1; - } - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__stmtGetBindInfo() [INTERNAL] -// Wrapper for OCIStmtGetBindInfo(). -//----------------------------------------------------------------------------- -int dpiOci__stmtGetBindInfo(dpiStmt *stmt, uint32_t size, uint32_t startLoc, - int32_t *numFound, char *names[], uint8_t nameLengths[], - char *indNames[], uint8_t indNameLengths[], uint8_t isDuplicate[], - void *bindHandles[], dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIStmtGetBindInfo", dpiOciSymbols.fnStmtGetBindInfo) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnStmtGetBindInfo)(stmt->handle, error->handle, - size, startLoc, numFound, names, nameLengths, indNames, - indNameLengths, isDuplicate, bindHandles); - if (status == DPI_OCI_NO_DATA) { - *numFound = 0; - return DPI_SUCCESS; - } - DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "get bind info"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__stmtGetNextResult() [INTERNAL] -// Wrapper for OCIStmtGetNextResult(). -//----------------------------------------------------------------------------- -int dpiOci__stmtGetNextResult(dpiStmt *stmt, void **handle, dpiError *error) -{ - uint32_t returnType; - int status; - - DPI_OCI_LOAD_SYMBOL("OCIStmtGetNextResult", - dpiOciSymbols.fnStmtGetNextResult) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnStmtGetNextResult)(stmt->handle, error->handle, - handle, &returnType, DPI_OCI_DEFAULT); - if (status == DPI_OCI_NO_DATA) { - *handle = NULL; - return DPI_SUCCESS; - } - DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "get next result"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__stmtPrepare2() [INTERNAL] -// Wrapper for OCIStmtPrepare2(). -//----------------------------------------------------------------------------- -int dpiOci__stmtPrepare2(dpiStmt *stmt, const char *sql, uint32_t sqlLength, - const char *tag, uint32_t tagLength, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIStmtPrepare2", dpiOciSymbols.fnStmtPrepare2) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnStmtPrepare2)(stmt->conn->handle, &stmt->handle, - error->handle, sql, sqlLength, tag, tagLength, DPI_OCI_NTV_SYNTAX, - DPI_OCI_DEFAULT); - if (DPI_OCI_ERROR_OCCURRED(status)) { - stmt->handle = NULL; - return dpiError__setFromOCI(error, status, stmt->conn, "prepare SQL"); - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__stmtRelease() [INTERNAL] -// Wrapper for OCIStmtRelease(). -//----------------------------------------------------------------------------- -int dpiOci__stmtRelease(dpiStmt *stmt, const char *tag, uint32_t tagLength, - int checkError, dpiError *error) -{ - uint32_t mode = DPI_OCI_DEFAULT; - uint32_t cacheSize = 0; - int status; - - // if the statement should be deleted from the cache, first check to see - // that there actually is a cache currently being used; otherwise, the - // error "ORA-24300: bad value for mode" will be raised - if (stmt->deleteFromCache) { - dpiOci__attrGet(stmt->conn->handle, DPI_OCI_HTYPE_SVCCTX, - &cacheSize, NULL, DPI_OCI_ATTR_STMTCACHESIZE, NULL, error); - if (cacheSize > 0) - mode = DPI_OCI_STRLS_CACHE_DELETE; - } - - DPI_OCI_LOAD_SYMBOL("OCIStmtRelease", dpiOciSymbols.fnStmtRelease) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnStmtRelease)(stmt->handle, error->handle, tag, - tagLength, mode); - if (!checkError) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "release statement"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__stringAssignText() [INTERNAL] -// Wrapper for OCIStringAssignText(). -//----------------------------------------------------------------------------- -int dpiOci__stringAssignText(void *envHandle, const char *value, - uint32_t valueLength, void **handle, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIStringAssignText", - dpiOciSymbols.fnStringAssignText) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnStringAssignText)(envHandle, error->handle, - value, valueLength, handle); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "assign to string"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__stringPtr() [INTERNAL] -// Wrapper for OCIStringPtr(). -//----------------------------------------------------------------------------- -int dpiOci__stringPtr(void *envHandle, void *handle, char **ptr) -{ - dpiError *error = NULL; - - DPI_OCI_LOAD_SYMBOL("OCIStringPtr", dpiOciSymbols.fnStringPtr) - *ptr = (*dpiOciSymbols.fnStringPtr)(envHandle, handle); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__stringResize() [INTERNAL] -// Wrapper for OCIStringResize(). -//----------------------------------------------------------------------------- -int dpiOci__stringResize(void *envHandle, void **handle, uint32_t newSize, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIStringResize", dpiOciSymbols.fnStringResize) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnStringResize)(envHandle, error->handle, newSize, - handle); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "resize string"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__stringSize() [INTERNAL] -// Wrapper for OCIStringSize(). -//----------------------------------------------------------------------------- -int dpiOci__stringSize(void *envHandle, void *handle, uint32_t *size) -{ - dpiError *error = NULL; - - DPI_OCI_LOAD_SYMBOL("OCIStringSize", dpiOciSymbols.fnStringSize) - *size = (*dpiOciSymbols.fnStringSize)(envHandle, handle); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__subscriptionRegister() [INTERNAL] -// Wrapper for OCISubscriptionRegister(). -//----------------------------------------------------------------------------- -int dpiOci__subscriptionRegister(dpiConn *conn, void **handle, uint32_t mode, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCISubscriptionRegister", - dpiOciSymbols.fnSubscriptionRegister) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnSubscriptionRegister)(conn->handle, handle, 1, - error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "register"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__subscriptionUnRegister() [INTERNAL] -// Wrapper for OCISubscriptionUnRegister(). -//----------------------------------------------------------------------------- -int dpiOci__subscriptionUnRegister(dpiConn *conn, dpiSubscr *subscr, - dpiError *error) -{ - uint32_t mode; - int status; - - DPI_OCI_LOAD_SYMBOL("OCISubscriptionUnRegister", - dpiOciSymbols.fnSubscriptionUnRegister) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - mode = (subscr->clientInitiated) ? DPI_OCI_SECURE_NOTIFICATION : - DPI_OCI_DEFAULT; - status = (*dpiOciSymbols.fnSubscriptionUnRegister)(conn->handle, - subscr->handle, error->handle, mode); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "unregister"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__tableDelete() [INTERNAL] -// Wrapper for OCITableDelete(). -//----------------------------------------------------------------------------- -int dpiOci__tableDelete(dpiObject *obj, int32_t index, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITableDelete", dpiOciSymbols.fnTableDelete) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTableDelete)(obj->env->handle, error->handle, - index, obj->instance); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "delete element"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__tableExists() [INTERNAL] -// Wrapper for OCITableExists(). -//----------------------------------------------------------------------------- -int dpiOci__tableExists(dpiObject *obj, int32_t index, int *exists, - dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITableExists", dpiOciSymbols.fnTableExists) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTableExists)(obj->env->handle, error->handle, - obj->instance, index, exists); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, - "get index exists"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__tableFirst() [INTERNAL] -// Wrapper for OCITableFirst(). -//----------------------------------------------------------------------------- -int dpiOci__tableFirst(dpiObject *obj, int32_t *index, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITableFirst", dpiOciSymbols.fnTableFirst) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTableFirst)(obj->env->handle, error->handle, - obj->instance, index); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, - "get first index"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__tableLast() [INTERNAL] -// Wrapper for OCITableLast(). -//----------------------------------------------------------------------------- -int dpiOci__tableLast(dpiObject *obj, int32_t *index, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITableLast", dpiOciSymbols.fnTableLast) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTableLast)(obj->env->handle, error->handle, - obj->instance, index); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get last index"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__tableNext() [INTERNAL] -// Wrapper for OCITableNext(). -//----------------------------------------------------------------------------- -int dpiOci__tableNext(dpiObject *obj, int32_t index, int32_t *nextIndex, - int *exists, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITableNext", dpiOciSymbols.fnTableNext) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTableNext)(obj->env->handle, error->handle, - index, obj->instance, nextIndex, exists); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get next index"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__tablePrev() [INTERNAL] -// Wrapper for OCITablePrev(). -//----------------------------------------------------------------------------- -int dpiOci__tablePrev(dpiObject *obj, int32_t index, int32_t *prevIndex, - int *exists, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITablePrev", dpiOciSymbols.fnTablePrev) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTablePrev)(obj->env->handle, error->handle, - index, obj->instance, prevIndex, exists); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get prev index"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__tableSize() [INTERNAL] -// Wrapper for OCITableSize(). -//----------------------------------------------------------------------------- -int dpiOci__tableSize(dpiObject *obj, int32_t *size, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITableSize", dpiOciSymbols.fnTableSize) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTableSize)(obj->env->handle, error->handle, - obj->instance, size); - DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get size"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__threadKeyDestroy() [INTERNAL] -// Wrapper for OCIThreadKeyDestroy(). -//----------------------------------------------------------------------------- -int dpiOci__threadKeyDestroy(void *envHandle, void *errorHandle, void **key, - dpiError *error) -{ - DPI_OCI_LOAD_SYMBOL("OCIThreadKeyDestroy", - dpiOciSymbols.fnThreadKeyDestroy) - (*dpiOciSymbols.fnThreadKeyDestroy)(envHandle, errorHandle, key); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__threadKeyGet() [INTERNAL] -// Wrapper for OCIThreadKeyGet(). -//----------------------------------------------------------------------------- -int dpiOci__threadKeyGet(void *envHandle, void *errorHandle, void *key, - void **value, dpiError *error) -{ - int status; - - status = (*dpiOciSymbols.fnThreadKeyGet)(envHandle, errorHandle, key, - value); - if (status != DPI_OCI_SUCCESS) - return dpiError__set(error, "get TLS error", DPI_ERR_TLS_ERROR); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__threadKeyInit() [INTERNAL] -// Wrapper for OCIThreadKeyInit(). -//----------------------------------------------------------------------------- -int dpiOci__threadKeyInit(void *envHandle, void *errorHandle, void **key, - void *destroyFunc, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIThreadKeyInit", dpiOciSymbols.fnThreadKeyInit) - status = (*dpiOciSymbols.fnThreadKeyInit)(envHandle, errorHandle, key, - destroyFunc); - DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "initialize thread key"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__threadKeySet() [INTERNAL] -// Wrapper for OCIThreadKeySet(). -//----------------------------------------------------------------------------- -int dpiOci__threadKeySet(void *envHandle, void *errorHandle, void *key, - void *value, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCIThreadKeySet", dpiOciSymbols.fnThreadKeySet) - status = (*dpiOciSymbols.fnThreadKeySet)(envHandle, errorHandle, key, - value); - if (status != DPI_OCI_SUCCESS) - return dpiError__set(error, "set TLS error", DPI_ERR_TLS_ERROR); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiOci__transCommit() [INTERNAL] -// Wrapper for OCITransCommit(). -//----------------------------------------------------------------------------- -int dpiOci__transCommit(dpiConn *conn, uint32_t flags, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITransCommit", dpiOciSymbols.fnTransCommit) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTransCommit)(conn->handle, error->handle, - flags); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "commit"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__transPrepare() [INTERNAL] -// Wrapper for OCITransPrepare(). -//----------------------------------------------------------------------------- -int dpiOci__transPrepare(dpiConn *conn, int *commitNeeded, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITransPrepare", dpiOciSymbols.fnTransPrepare) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTransPrepare)(conn->handle, error->handle, - DPI_OCI_DEFAULT); - *commitNeeded = (status == DPI_OCI_SUCCESS); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "prepare transaction"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__transRollback() [INTERNAL] -// Wrapper for OCITransRollback(). -//----------------------------------------------------------------------------- -int dpiOci__transRollback(dpiConn *conn, int checkError, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITransRollback", dpiOciSymbols.fnTransRollback) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTransRollback)(conn->handle, error->handle, - DPI_OCI_DEFAULT); - if (!checkError) - return DPI_SUCCESS; - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "rollback"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__transStart() [INTERNAL] -// Wrapper for OCITransStart(). -//----------------------------------------------------------------------------- -int dpiOci__transStart(dpiConn *conn, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITransStart", dpiOciSymbols.fnTransStart) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTransStart)(conn->handle, error->handle, 0, - DPI_OCI_TRANS_NEW); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "start transaction"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__typeByName() [INTERNAL] -// Wrapper for OCITypeByName(). -//----------------------------------------------------------------------------- -int dpiOci__typeByName(dpiConn *conn, const char *schema, - uint32_t schemaLength, const char *name, uint32_t nameLength, - void **tdo, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITypeByName", dpiOciSymbols.fnTypeByName) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTypeByName)(conn->env->handle, error->handle, - conn->handle, schema, schemaLength, name, nameLength, NULL, 0, - DPI_OCI_DURATION_SESSION, DPI_OCI_TYPEGET_ALL, tdo); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get type by name"); -} - - -//----------------------------------------------------------------------------- -// dpiOci__typeByFullName() [INTERNAL] -// Wrapper for OCITypeByFullName(). -//----------------------------------------------------------------------------- -int dpiOci__typeByFullName(dpiConn *conn, const char *name, - uint32_t nameLength, void **tdo, dpiError *error) -{ - int status; - - DPI_OCI_LOAD_SYMBOL("OCITypeByFullName", dpiOciSymbols.fnTypeByFullName) - DPI_OCI_ENSURE_ERROR_HANDLE(error) - status = (*dpiOciSymbols.fnTypeByFullName)(conn->env->handle, - error->handle, conn->handle, name, nameLength, NULL, 0, - DPI_OCI_DURATION_SESSION, DPI_OCI_TYPEGET_ALL, tdo); - DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get type by full name"); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiOracleType.c b/vendor/github.com/godror/godror/odpi/src/dpiOracleType.c deleted file mode 100644 index ee307a7d995..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiOracleType.c +++ /dev/null @@ -1,504 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiOracleType.c -// Implementation of variable types. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// definition of Oracle types (MUST be in same order as enumeration) -//----------------------------------------------------------------------------- -static const dpiOracleType - dpiAllOracleTypes[DPI_ORACLE_TYPE_MAX - DPI_ORACLE_TYPE_NONE - 1] = { - { - DPI_ORACLE_TYPE_VARCHAR, // public Oracle type - DPI_NATIVE_TYPE_BYTES, // default native type - DPI_SQLT_CHR, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - 0, // buffer size - 1, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_NVARCHAR, // public Oracle type - DPI_NATIVE_TYPE_BYTES, // default native type - DPI_SQLT_CHR, // internal Oracle type - DPI_SQLCS_NCHAR, // charset form - 0, // buffer size - 1, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_CHAR, // public Oracle type - DPI_NATIVE_TYPE_BYTES, // default native type - DPI_SQLT_AFC, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - 0, // buffer size - 1, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_NCHAR, // public Oracle type - DPI_NATIVE_TYPE_BYTES, // default native type - DPI_SQLT_AFC, // internal Oracle type - DPI_SQLCS_NCHAR, // charset form - 0, // buffer size - 1, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_ROWID, // public Oracle type - DPI_NATIVE_TYPE_ROWID, // default native type - DPI_SQLT_RDD, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 1, // is character data - 1, // can be in array - 1 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_RAW, // public Oracle type - DPI_NATIVE_TYPE_BYTES, // default native type - DPI_SQLT_BIN, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - 0, // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_NATIVE_FLOAT, // public Oracle type - DPI_NATIVE_TYPE_FLOAT, // default native type - DPI_SQLT_BFLOAT, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(float), // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_NATIVE_DOUBLE, // public Oracle type - DPI_NATIVE_TYPE_DOUBLE, // default native type - DPI_SQLT_BDOUBLE, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(double), // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_NATIVE_INT, // public Oracle type - DPI_NATIVE_TYPE_INT64, // default native type - DPI_SQLT_INT, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(int64_t), // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_NUMBER, // public Oracle type - DPI_NATIVE_TYPE_DOUBLE, // default native type - DPI_SQLT_VNU, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - DPI_OCI_NUMBER_SIZE, // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_DATE, // public Oracle type - DPI_NATIVE_TYPE_TIMESTAMP, // default native type - DPI_SQLT_ODT, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(dpiOciDate), // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_TIMESTAMP, // public Oracle type - DPI_NATIVE_TYPE_TIMESTAMP, // default native type - DPI_SQLT_TIMESTAMP, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_TIMESTAMP_TZ, // public Oracle type - DPI_NATIVE_TYPE_TIMESTAMP, // default native type - DPI_SQLT_TIMESTAMP_TZ, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_TIMESTAMP_LTZ, // public Oracle type - DPI_NATIVE_TYPE_TIMESTAMP, // default native type - DPI_SQLT_TIMESTAMP_LTZ, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_INTERVAL_DS, // public Oracle type - DPI_NATIVE_TYPE_INTERVAL_DS, // default native type - DPI_SQLT_INTERVAL_DS, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_INTERVAL_YM, // public Oracle type - DPI_NATIVE_TYPE_INTERVAL_YM, // default native type - DPI_SQLT_INTERVAL_YM, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_CLOB, // public Oracle type - DPI_NATIVE_TYPE_LOB, // default native type - DPI_SQLT_CLOB, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 1, // is character data - 0, // can be in array - 1 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_NCLOB, // public Oracle type - DPI_NATIVE_TYPE_LOB, // default native type - DPI_SQLT_CLOB, // internal Oracle type - DPI_SQLCS_NCHAR, // charset form - sizeof(void*), // buffer size - 1, // is character data - 0, // can be in array - 1 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_BLOB, // public Oracle type - DPI_NATIVE_TYPE_LOB, // default native type - DPI_SQLT_BLOB, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 0, // is character data - 0, // can be in array - 1 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_BFILE, // public Oracle type - DPI_NATIVE_TYPE_LOB, // default native type - DPI_SQLT_BFILE, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 0, // is character data - 0, // can be in array - 1 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_STMT, // public Oracle type - DPI_NATIVE_TYPE_STMT, // default native type - DPI_SQLT_RSET, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 0, // is character data - 0, // can be in array - 1 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_BOOLEAN, // public Oracle type - DPI_NATIVE_TYPE_BOOLEAN, // default native type - DPI_SQLT_BOL, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(int), // buffer size - 0, // is character data - 0, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_OBJECT, // public Oracle type - DPI_NATIVE_TYPE_OBJECT, // default native type - DPI_SQLT_NTY, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(void*), // buffer size - 0, // is character data - 0, // can be in array - 1 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_LONG_VARCHAR, // public Oracle type - DPI_NATIVE_TYPE_BYTES, // default native type - DPI_SQLT_CHR, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - DPI_MAX_BASIC_BUFFER_SIZE + 1, // buffer size - 1, // is character data - 0, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_LONG_RAW, // public Oracle type - DPI_NATIVE_TYPE_BYTES, // default native type - DPI_SQLT_BIN, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - DPI_MAX_BASIC_BUFFER_SIZE + 1, // buffer size - 0, // is character data - 0, // can be in array - 0 // requires pre-fetch - }, - { - DPI_ORACLE_TYPE_NATIVE_UINT, // public Oracle type - DPI_NATIVE_TYPE_UINT64, // default native type - DPI_SQLT_UIN, // internal Oracle type - DPI_SQLCS_IMPLICIT, // charset form - sizeof(uint64_t), // buffer size - 0, // is character data - 1, // can be in array - 0 // requires pre-fetch - } -}; - - -//----------------------------------------------------------------------------- -// dpiOracleType__convertFromOracle() [INTERNAL] -// Return a value from the dpiOracleTypeNum enumeration for the OCI data type -// and charset form. If the OCI data type is not supported, 0 is returned. -//----------------------------------------------------------------------------- -static dpiOracleTypeNum dpiOracleType__convertFromOracle(uint16_t typeCode, - uint8_t charsetForm) -{ - switch(typeCode) { - case DPI_SQLT_CHR: - case DPI_SQLT_VCS: - if (charsetForm == DPI_SQLCS_NCHAR) - return DPI_ORACLE_TYPE_NVARCHAR; - return DPI_ORACLE_TYPE_VARCHAR; - case DPI_SQLT_INT: - case DPI_SQLT_FLT: - case DPI_SQLT_NUM: - case DPI_SQLT_PDN: - case DPI_SQLT_VNU: - case DPI_SQLT_BFLOAT: - case DPI_SQLT_BDOUBLE: - case DPI_OCI_TYPECODE_SMALLINT: - return DPI_ORACLE_TYPE_NUMBER; - case DPI_SQLT_DAT: - case DPI_SQLT_ODT: - return DPI_ORACLE_TYPE_DATE; - case DPI_SQLT_BIN: - case DPI_SQLT_LVB: - return DPI_ORACLE_TYPE_RAW; - case DPI_SQLT_AFC: - if (charsetForm == DPI_SQLCS_NCHAR) - return DPI_ORACLE_TYPE_NCHAR; - return DPI_ORACLE_TYPE_CHAR; - case DPI_OCI_TYPECODE_BINARY_INTEGER: - case DPI_OCI_TYPECODE_PLS_INTEGER: - return DPI_ORACLE_TYPE_NATIVE_INT; - case DPI_SQLT_IBFLOAT: - return DPI_ORACLE_TYPE_NATIVE_FLOAT; - case DPI_SQLT_IBDOUBLE: - return DPI_ORACLE_TYPE_NATIVE_DOUBLE; - case DPI_SQLT_DATE: - case DPI_SQLT_TIMESTAMP: - return DPI_ORACLE_TYPE_TIMESTAMP; - case DPI_SQLT_TIMESTAMP_TZ: - return DPI_ORACLE_TYPE_TIMESTAMP_TZ; - case DPI_SQLT_TIMESTAMP_LTZ: - return DPI_ORACLE_TYPE_TIMESTAMP_LTZ; - case DPI_SQLT_NTY: - case DPI_SQLT_REC: - case DPI_SQLT_NCO: - return DPI_ORACLE_TYPE_OBJECT; - case DPI_SQLT_BOL: - return DPI_ORACLE_TYPE_BOOLEAN; - case DPI_SQLT_CLOB: - if (charsetForm == DPI_SQLCS_NCHAR) - return DPI_ORACLE_TYPE_NCLOB; - return DPI_ORACLE_TYPE_CLOB; - case DPI_SQLT_BLOB: - return DPI_ORACLE_TYPE_BLOB; - case DPI_SQLT_BFILE: - return DPI_ORACLE_TYPE_BFILE; - case DPI_SQLT_RDD: - case DPI_OCI_TYPECODE_ROWID: - return DPI_ORACLE_TYPE_ROWID; - case DPI_SQLT_RSET: - return DPI_ORACLE_TYPE_STMT; - case DPI_SQLT_INTERVAL_DS: - return DPI_ORACLE_TYPE_INTERVAL_DS; - case DPI_SQLT_INTERVAL_YM: - return DPI_ORACLE_TYPE_INTERVAL_YM; - case DPI_SQLT_LNG: - case DPI_OCI_TYPECODE_LONG: - return DPI_ORACLE_TYPE_LONG_VARCHAR; - case DPI_SQLT_LBI: - case DPI_OCI_TYPECODE_LONG_RAW: - return DPI_ORACLE_TYPE_LONG_RAW; - } - return (dpiOracleTypeNum) 0; -} - - -//----------------------------------------------------------------------------- -// dpiOracleType__getFromNum() [INTERNAL] -// Return the type associated with the type number. -//----------------------------------------------------------------------------- -const dpiOracleType *dpiOracleType__getFromNum(dpiOracleTypeNum typeNum, - dpiError *error) -{ - if (typeNum > DPI_ORACLE_TYPE_NONE && typeNum < DPI_ORACLE_TYPE_MAX) - return &dpiAllOracleTypes[typeNum - DPI_ORACLE_TYPE_NONE - 1]; - dpiError__set(error, "check type", DPI_ERR_INVALID_ORACLE_TYPE, typeNum); - return NULL; -} - - -//----------------------------------------------------------------------------- -// dpiOracleType__populateTypeInfo() [INTERNAL] -// Populate dpiDataTypeInfo structure given an Oracle descriptor. Note that -// no error is raised by this function if the data type is not supported. This -// method is called for both implicit and explicit describes (which behave -// slightly differently). -//----------------------------------------------------------------------------- -int dpiOracleType__populateTypeInfo(dpiConn *conn, void *handle, - uint32_t handleType, dpiDataTypeInfo *info, dpiError *error) -{ - const dpiOracleType *oracleType = NULL; - dpiNativeTypeNum nativeTypeNum; - uint32_t dataTypeAttribute; - uint8_t charsetForm; - uint16_t ociSize; - - // acquire data type - if (handleType == DPI_OCI_DTYPE_PARAM) - dataTypeAttribute = DPI_OCI_ATTR_TYPECODE; - else dataTypeAttribute = DPI_OCI_ATTR_DATA_TYPE; - if (dpiOci__attrGet(handle, handleType, (void*) &info->ociTypeCode, 0, - dataTypeAttribute, "get data type", error) < 0) - return DPI_FAILURE; - - // acquire character set form - if (info->ociTypeCode != DPI_SQLT_CHR && - info->ociTypeCode != DPI_SQLT_AFC && - info->ociTypeCode != DPI_SQLT_VCS && - info->ociTypeCode != DPI_SQLT_CLOB) - charsetForm = DPI_SQLCS_IMPLICIT; - else if (dpiOci__attrGet(handle, handleType, (void*) &charsetForm, 0, - DPI_OCI_ATTR_CHARSET_FORM, "get charset form", error) < 0) - return DPI_FAILURE; - - // convert Oracle type to ODPI-C enumerations, if possible - info->oracleTypeNum = dpiOracleType__convertFromOracle(info->ociTypeCode, - charsetForm); - if (!info->oracleTypeNum) - info->defaultNativeTypeNum = (dpiNativeTypeNum) 0; - else { - oracleType = dpiOracleType__getFromNum(info->oracleTypeNum, error); - if (!oracleType) - return DPI_FAILURE; - info->defaultNativeTypeNum = oracleType->defaultNativeTypeNum; - } - - // determine precision/scale - nativeTypeNum = info->defaultNativeTypeNum; - switch (nativeTypeNum) { - case DPI_NATIVE_TYPE_DOUBLE: - case DPI_NATIVE_TYPE_FLOAT: - case DPI_NATIVE_TYPE_INT64: - case DPI_NATIVE_TYPE_TIMESTAMP: - case DPI_NATIVE_TYPE_INTERVAL_YM: - case DPI_NATIVE_TYPE_INTERVAL_DS: - if (dpiOci__attrGet(handle, handleType, (void*) &info->scale, 0, - DPI_OCI_ATTR_SCALE, "get scale", error) < 0) - return DPI_FAILURE; - if (dpiOci__attrGet(handle, handleType, (void*) &info->precision, - 0, DPI_OCI_ATTR_PRECISION, "get precision", error) < 0) - return DPI_FAILURE; - if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP || - nativeTypeNum == DPI_NATIVE_TYPE_INTERVAL_DS) { - info->fsPrecision = (uint8_t) info->scale; - info->scale = 0; - } - break; - default: - info->precision = 0; - info->fsPrecision = 0; - info->scale = 0; - break; - } - - // change default type to integer if precision/scale supports it - if (info->oracleTypeNum == DPI_ORACLE_TYPE_NUMBER && info->scale == 0 && - info->precision > 0 && info->precision <= DPI_MAX_INT64_PRECISION) - info->defaultNativeTypeNum = DPI_NATIVE_TYPE_INT64; - - // acquire size (in bytes) of item - info->sizeInChars = 0; - if (oracleType && oracleType->sizeInBytes == 0) { - if (dpiOci__attrGet(handle, handleType, (void*) &ociSize, 0, - DPI_OCI_ATTR_DATA_SIZE, "get size (bytes)", error) < 0) - return DPI_FAILURE; - info->dbSizeInBytes = ociSize; - info->clientSizeInBytes = ociSize; - } else { - info->dbSizeInBytes = 0; - info->clientSizeInBytes = 0; - } - - // acquire size (in characters) of item, if applicable - if (oracleType && oracleType->isCharacterData && - oracleType->sizeInBytes == 0) { - if (dpiOci__attrGet(handle, handleType, (void*) &ociSize, 0, - DPI_OCI_ATTR_CHAR_SIZE, "get size (chars)", error) < 0) - return DPI_FAILURE; - info->sizeInChars = ociSize; - if (charsetForm == DPI_SQLCS_NCHAR) - info->clientSizeInBytes = info->sizeInChars * - conn->env->nmaxBytesPerCharacter; - else if (conn->charsetId != conn->env->charsetId) - info->clientSizeInBytes = info->sizeInChars * - conn->env->maxBytesPerCharacter; - } - - // acquire object type, if applicable - if (info->oracleTypeNum == DPI_ORACLE_TYPE_OBJECT) { - if (dpiObjectType__allocate(conn, handle, DPI_OCI_ATTR_TYPE_NAME, - &info->objectType, error) < 0) - return DPI_FAILURE; - if (dpiObjectType__isXmlType(info->objectType)) { - dpiObjectType__free(info->objectType, error); - info->objectType = NULL; - info->ociTypeCode = DPI_SQLT_CHR; - info->oracleTypeNum = DPI_ORACLE_TYPE_LONG_VARCHAR; - info->defaultNativeTypeNum = DPI_NATIVE_TYPE_BYTES; - } - } - - return DPI_SUCCESS; -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiPool.c b/vendor/github.com/godror/godror/odpi/src/dpiPool.c deleted file mode 100644 index 58f21e5efc9..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiPool.c +++ /dev/null @@ -1,586 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiPool.c -// Implementation of session pools. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiPool__acquireConnection() [INTERNAL] -// Internal method used for acquiring a connection from a pool. -//----------------------------------------------------------------------------- -int dpiPool__acquireConnection(dpiPool *pool, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - dpiConnCreateParams *params, dpiConn **conn, dpiError *error) -{ - dpiConn *tempConn; - - // allocate new connection - if (dpiGen__allocate(DPI_HTYPE_CONN, pool->env, (void**) &tempConn, - error) < 0) - return DPI_FAILURE; - error->env = pool->env; - - // create the connection - if (dpiConn__create(tempConn, pool->env->context, userName, userNameLength, - password, passwordLength, pool->name, pool->nameLength, pool, - NULL, params, error) < 0) { - dpiConn__free(tempConn, error); - return DPI_FAILURE; - } - - *conn = tempConn; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiPool__checkConnected() [INTERNAL] -// Determine if the session pool is connected to the database. If not, an -// error is raised. -//----------------------------------------------------------------------------- -static int dpiPool__checkConnected(dpiPool *pool, const char *fnName, - dpiError *error) -{ - if (dpiGen__startPublicFn(pool, DPI_HTYPE_POOL, fnName, error) < 0) - return DPI_FAILURE; - if (!pool->handle) - return dpiError__set(error, "check pool", DPI_ERR_NOT_CONNECTED); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiPool__create() [INTERNAL] -// Internal method for creating a session pool. -//----------------------------------------------------------------------------- -static int dpiPool__create(dpiPool *pool, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - const char *connectString, uint32_t connectStringLength, - const dpiCommonCreateParams *commonParams, - dpiPoolCreateParams *createParams, dpiError *error) -{ - uint32_t poolMode; - uint8_t getMode; - void *authInfo; - - // validate parameters - if (createParams->externalAuth && - ((userName && userNameLength > 0) || - (password && passwordLength > 0))) - return dpiError__set(error, "check mixed credentials", - DPI_ERR_EXT_AUTH_WITH_CREDENTIALS); - - // create the session pool handle - if (dpiOci__handleAlloc(pool->env->handle, &pool->handle, - DPI_OCI_HTYPE_SPOOL, "allocate pool handle", error) < 0) - return DPI_FAILURE; - - // prepare pool mode - poolMode = DPI_OCI_SPC_STMTCACHE; - if (createParams->homogeneous) - poolMode |= DPI_OCI_SPC_HOMOGENEOUS; - - // create authorization handle - if (dpiOci__handleAlloc(pool->env->handle, &authInfo, - DPI_OCI_HTYPE_AUTHINFO, "allocate authinfo handle", error) < 0) - return DPI_FAILURE; - - // set context attributes - if (dpiUtils__setAttributesFromCommonCreateParams(authInfo, - DPI_OCI_HTYPE_AUTHINFO, commonParams, error) < 0) - return DPI_FAILURE; - - // set PL/SQL session state fixup callback, if applicable - if (createParams->plsqlFixupCallback && - createParams->plsqlFixupCallbackLength > 0) { - if (dpiUtils__checkClientVersion(pool->env->versionInfo, 12, 2, - error) < 0) - return DPI_FAILURE; - if (dpiOci__attrSet(authInfo, DPI_OCI_HTYPE_AUTHINFO, - (void*) createParams->plsqlFixupCallback, - createParams->plsqlFixupCallbackLength, - DPI_OCI_ATTR_FIXUP_CALLBACK, - "set PL/SQL session state fixup callback", error) < 0) - return DPI_FAILURE; - } - - // set authorization info on session pool - if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) authInfo, 0, - DPI_OCI_ATTR_SPOOL_AUTH, "set auth info", error) < 0) - return DPI_FAILURE; - - // create pool - if (dpiOci__sessionPoolCreate(pool, connectString, connectStringLength, - createParams->minSessions, createParams->maxSessions, - createParams->sessionIncrement, userName, userNameLength, password, - passwordLength, poolMode, error) < 0) - return DPI_FAILURE; - - // set the get mode on the pool - getMode = (uint8_t) createParams->getMode; - if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) &getMode, 0, - DPI_OCI_ATTR_SPOOL_GETMODE, "set get mode", error) < 0) - return DPI_FAILURE; - - // set the session timeout on the pool - if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) - &createParams->timeout, 0, DPI_OCI_ATTR_SPOOL_TIMEOUT, - "set timeout", error) < 0) - return DPI_FAILURE; - - // set the wait timeout on the pool (valid in 12.2 and higher) - if (pool->env->versionInfo->versionNum > 12 || - (pool->env->versionInfo->versionNum == 12 && - pool->env->versionInfo->releaseNum >= 2)) { - if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) - &createParams->waitTimeout, 0, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT, - "set wait timeout", error) < 0) - return DPI_FAILURE; - } - - // set the maximum lifetime session on the pool (valid in 12.1 and higher) - if (pool->env->versionInfo->versionNum >= 12) { - if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) - &createParams->maxLifetimeSession, 0, - DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION, - "set max lifetime session", error) < 0) - return DPI_FAILURE; - } - - // set the maximum number of sessions per shard (valid in 18.3 and higher) - if (pool->env->versionInfo->versionNum > 18 || - (pool->env->versionInfo->versionNum == 18 && - pool->env->versionInfo->releaseNum >= 3)) { - if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) - &createParams->maxSessionsPerShard, 0, - DPI_OCI_ATTR_SPOOL_MAX_PER_SHARD, - "set max sessions per shard", error) < 0) - return DPI_FAILURE; - } - - // set reamining attributes directly - pool->homogeneous = createParams->homogeneous; - pool->externalAuth = createParams->externalAuth; - pool->pingInterval = createParams->pingInterval; - pool->pingTimeout = createParams->pingTimeout; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiPool__free() [INTERNAL] -// Free any memory associated with the pool. -//----------------------------------------------------------------------------- -void dpiPool__free(dpiPool *pool, dpiError *error) -{ - if (pool->handle) { - dpiOci__sessionPoolDestroy(pool, DPI_OCI_SPD_FORCE, 0, error); - pool->handle = NULL; - } - if (pool->env) { - dpiEnv__free(pool->env, error); - pool->env = NULL; - } - dpiUtils__freeMemory(pool); -} - - -//----------------------------------------------------------------------------- -// dpiPool__getAttributeUint() [INTERNAL] -// Return the value of the attribute as an unsigned integer. -//----------------------------------------------------------------------------- -static int dpiPool__getAttributeUint(dpiPool *pool, uint32_t attribute, - uint32_t *value, const char *fnName) -{ - int status, supported = 1; - dpiError error; - - if (dpiPool__checkConnected(pool, fnName, &error) < 0) - return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(pool, value) - switch (attribute) { - case DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION: - if (pool->env->versionInfo->versionNum < 12) - supported = 0; - break; - case DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT: - if (pool->env->versionInfo->versionNum < 12 || - (pool->env->versionInfo->versionNum == 12 && - pool->env->versionInfo->releaseNum < 2)) - supported = 0; - break; - case DPI_OCI_ATTR_SPOOL_BUSY_COUNT: - case DPI_OCI_ATTR_SPOOL_OPEN_COUNT: - case DPI_OCI_ATTR_SPOOL_STMTCACHESIZE: - case DPI_OCI_ATTR_SPOOL_TIMEOUT: - break; - default: - supported = 0; - break; - } - if (supported) - status = dpiOci__attrGet(pool->handle, DPI_OCI_HTYPE_SPOOL, value, - NULL, attribute, "get attribute value", &error); - else status = dpiError__set(&error, "get attribute value", - DPI_ERR_NOT_SUPPORTED); - return dpiGen__endPublicFn(pool, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiPool__setAttributeUint() [INTERNAL] -// Set the value of the OCI attribute as an unsigned integer. -//----------------------------------------------------------------------------- -static int dpiPool__setAttributeUint(dpiPool *pool, uint32_t attribute, - uint32_t value, const char *fnName) -{ - int status, supported = 1; - void *ociValue = &value; - uint8_t shortValue; - dpiError error; - - // make sure session pool is connected - if (dpiPool__checkConnected(pool, fnName, &error) < 0) - return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); - - // determine pointer to pass (OCI uses different sizes) - switch (attribute) { - case DPI_OCI_ATTR_SPOOL_GETMODE: - shortValue = (uint8_t) value; - ociValue = &shortValue; - break; - case DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION: - if (pool->env->versionInfo->versionNum < 12) - supported = 0; - break; - case DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT: - if (pool->env->versionInfo->versionNum < 12 || - (pool->env->versionInfo->versionNum == 12 && - pool->env->versionInfo->releaseNum < 2)) - supported = 0; - break; - case DPI_OCI_ATTR_SPOOL_STMTCACHESIZE: - case DPI_OCI_ATTR_SPOOL_TIMEOUT: - break; - default: - supported = 0; - break; - } - - // set value in the OCI - if (supported) - status = dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, ociValue, - 0, attribute, "set attribute value", &error); - else status = dpiError__set(&error, "set attribute value", - DPI_ERR_NOT_SUPPORTED); - return dpiGen__endPublicFn(pool, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiPool_acquireConnection() [PUBLIC] -// Acquire a connection from the pool. -//----------------------------------------------------------------------------- -int dpiPool_acquireConnection(dpiPool *pool, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - dpiConnCreateParams *params, dpiConn **conn) -{ - dpiConnCreateParams localParams; - dpiError error; - int status; - - // validate parameters - if (dpiPool__checkConnected(pool, __func__, &error) < 0) - return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(pool, userName) - DPI_CHECK_PTR_AND_LENGTH(pool, password) - DPI_CHECK_PTR_NOT_NULL(pool, conn) - - // use default parameters if none provided - if (!params) { - dpiContext__initConnCreateParams(&localParams); - params = &localParams; - } - - // the username must be enclosed within [] if external authentication - // with proxy is desired - if (pool->externalAuth && userName && userNameLength > 0 && - (userName[0] != '[' || userName[userNameLength - 1] != ']')) { - dpiError__set(&error, "verify proxy user name with external auth", - DPI_ERR_EXT_AUTH_INVALID_PROXY); - return dpiGen__endPublicFn(pool, DPI_FAILURE, &error ); - } - - status = dpiPool__acquireConnection(pool, userName, userNameLength, - password, passwordLength, params, conn, &error); - return dpiGen__endPublicFn(pool, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiPool_addRef() [PUBLIC] -// Add a reference to the pool. -//----------------------------------------------------------------------------- -int dpiPool_addRef(dpiPool *pool) -{ - return dpiGen__addRef(pool, DPI_HTYPE_POOL, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_close() [PUBLIC] -// Destroy the pool now, not when the reference count reaches zero. -//----------------------------------------------------------------------------- -int dpiPool_close(dpiPool *pool, dpiPoolCloseMode mode) -{ - dpiError error; - - if (dpiPool__checkConnected(pool, __func__, &error) < 0) - return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); - if (dpiOci__sessionPoolDestroy(pool, mode, 1, &error) < 0) - return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); - return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiPool_create() [PUBLIC] -// Create a new session pool and return it. -//----------------------------------------------------------------------------- -int dpiPool_create(const dpiContext *context, const char *userName, - uint32_t userNameLength, const char *password, uint32_t passwordLength, - const char *connectString, uint32_t connectStringLength, - const dpiCommonCreateParams *commonParams, - dpiPoolCreateParams *createParams, dpiPool **pool) -{ - dpiCommonCreateParams localCommonParams; - dpiPoolCreateParams localCreateParams; - dpiPool *tempPool; - dpiError error; - - // validate parameters - if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, - &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(context, userName) - DPI_CHECK_PTR_AND_LENGTH(context, password) - DPI_CHECK_PTR_AND_LENGTH(context, connectString) - DPI_CHECK_PTR_NOT_NULL(context, pool) - - // use default parameters if none provided - if (!commonParams) { - dpiContext__initCommonCreateParams(&localCommonParams); - commonParams = &localCommonParams; - } - - // size changed in 3.1; must use local variable until version 4 released - if (!createParams || context->dpiMinorVersion < 1) { - dpiContext__initPoolCreateParams(&localCreateParams); - if (createParams) - memcpy(&localCreateParams, createParams, - sizeof(dpiPoolCreateParams__v30)); - createParams = &localCreateParams; - } - - // allocate memory for pool - if (dpiGen__allocate(DPI_HTYPE_POOL, NULL, (void**) &tempPool, &error) < 0) - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - - // initialize environment - if (dpiEnv__init(tempPool->env, context, commonParams, NULL, &error) < 0) { - dpiPool__free(tempPool, &error); - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - } - - // perform remaining steps required to create pool - if (dpiPool__create(tempPool, userName, userNameLength, password, - passwordLength, connectString, connectStringLength, commonParams, - createParams, &error) < 0) { - dpiPool__free(tempPool, &error); - return dpiGen__endPublicFn(context, DPI_FAILURE, &error); - } - - createParams->outPoolName = tempPool->name; - createParams->outPoolNameLength = tempPool->nameLength; - *pool = tempPool; - dpiHandlePool__release(tempPool->env->errorHandles, &error.handle); - return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiPool_getBusyCount() [PUBLIC] -// Return the pool's busy count. -//----------------------------------------------------------------------------- -int dpiPool_getBusyCount(dpiPool *pool, uint32_t *value) -{ - return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_BUSY_COUNT, - value, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_getEncodingInfo() [PUBLIC] -// Get the encoding information from the pool. -//----------------------------------------------------------------------------- -int dpiPool_getEncodingInfo(dpiPool *pool, dpiEncodingInfo *info) -{ - dpiError error; - int status; - - if (dpiPool__checkConnected(pool, __func__, &error) < 0) - return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(pool, info) - status = dpiEnv__getEncodingInfo(pool->env, info); - return dpiGen__endPublicFn(pool, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiPool_getGetMode() [PUBLIC] -// Return the pool's "get" mode. -//----------------------------------------------------------------------------- -int dpiPool_getGetMode(dpiPool *pool, dpiPoolGetMode *value) -{ - dpiError error; - - if (dpiPool__checkConnected(pool, __func__, &error) < 0) - return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(pool, value) - if (dpiOci__attrGet(pool->handle, DPI_OCI_HTYPE_SPOOL, value, NULL, - DPI_OCI_ATTR_SPOOL_GETMODE, "get attribute value", &error) < 0) - return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); - return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiPool_getMaxLifetimeSession() [PUBLIC] -// Return the pool's maximum lifetime session. -//----------------------------------------------------------------------------- -int dpiPool_getMaxLifetimeSession(dpiPool *pool, uint32_t *value) -{ - return dpiPool__getAttributeUint(pool, - DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION, value, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_getOpenCount() [PUBLIC] -// Return the pool's open count. -//----------------------------------------------------------------------------- -int dpiPool_getOpenCount(dpiPool *pool, uint32_t *value) -{ - return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_OPEN_COUNT, - value, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_getStmtCacheSize() [PUBLIC] -// Return the pool's default statement cache size. -//----------------------------------------------------------------------------- -int dpiPool_getStmtCacheSize(dpiPool *pool, uint32_t *value) -{ - return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_STMTCACHESIZE, - value, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_getTimeout() [PUBLIC] -// Return the pool's timeout value. -//----------------------------------------------------------------------------- -int dpiPool_getTimeout(dpiPool *pool, uint32_t *value) -{ - return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_TIMEOUT, value, - __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_getWaitTimeout() [PUBLIC] -// Return the pool's wait timeout value. -//----------------------------------------------------------------------------- -int dpiPool_getWaitTimeout(dpiPool *pool, uint32_t *value) -{ - return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT, - value, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_release() [PUBLIC] -// Release a reference to the pool. -//----------------------------------------------------------------------------- -int dpiPool_release(dpiPool *pool) -{ - return dpiGen__release(pool, DPI_HTYPE_POOL, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_setGetMode() [PUBLIC] -// Set the pool's "get" mode. -//----------------------------------------------------------------------------- -int dpiPool_setGetMode(dpiPool *pool, dpiPoolGetMode value) -{ - return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_GETMODE, value, - __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_setMaxLifetimeSession() [PUBLIC] -// Set the pool's maximum lifetime session. -//----------------------------------------------------------------------------- -int dpiPool_setMaxLifetimeSession(dpiPool *pool, uint32_t value) -{ - return dpiPool__setAttributeUint(pool, - DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION, value, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_setStmtCacheSize() [PUBLIC] -// Set the pool's default statement cache size. -//----------------------------------------------------------------------------- -int dpiPool_setStmtCacheSize(dpiPool *pool, uint32_t value) -{ - return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_STMTCACHESIZE, - value, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_setTimeout() [PUBLIC] -// Set the pool's timeout value. -//----------------------------------------------------------------------------- -int dpiPool_setTimeout(dpiPool *pool, uint32_t value) -{ - return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_TIMEOUT, value, - __func__); -} - - -//----------------------------------------------------------------------------- -// dpiPool_setWaitTimeout() [PUBLIC] -// Set the pool's wait timeout value. -//----------------------------------------------------------------------------- -int dpiPool_setWaitTimeout(dpiPool *pool, uint32_t value) -{ - return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT, - value, __func__); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiQueue.c b/vendor/github.com/godror/godror/odpi/src/dpiQueue.c deleted file mode 100644 index 9c2f39a9a82..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiQueue.c +++ /dev/null @@ -1,560 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiQueue.c -// Implementation of AQ queues. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -// forward declarations of internal functions only used in this file -static int dpiQueue__allocateBuffer(dpiQueue *queue, uint32_t numElements, - dpiError *error); -static int dpiQueue__deq(dpiQueue *queue, uint32_t *numProps, - dpiMsgProps **props, dpiError *error); -static void dpiQueue__freeBuffer(dpiQueue *queue, dpiError *error); -static int dpiQueue__getPayloadTDO(dpiQueue *queue, void **tdo, - dpiError *error); - - -//----------------------------------------------------------------------------- -// dpiQueue__allocate() [INTERNAL] -// Allocate and initialize a queue. -//----------------------------------------------------------------------------- -int dpiQueue__allocate(dpiConn *conn, const char *name, uint32_t nameLength, - dpiObjectType *payloadType, dpiQueue **queue, dpiError *error) -{ - dpiQueue *tempQueue; - char *buffer; - - // allocate handle; store reference to the connection that created it - if (dpiGen__allocate(DPI_HTYPE_QUEUE, conn->env, (void**) &tempQueue, - error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(conn, error, 1); - tempQueue->conn = conn; - - // store payload type, which is either an object type or NULL (meaning that - // RAW payloads are being enqueued and dequeued) - if (payloadType) { - dpiGen__setRefCount(payloadType, error, 1); - tempQueue->payloadType = payloadType; - } - - // allocate space for the name of the queue; OCI requires a NULL-terminated - // string so allocate enough space to store the NULL terminator; UTF-16 - // encoded strings are not currently supported - if (dpiUtils__allocateMemory(1, nameLength + 1, 0, "queue name", - (void**) &buffer, error) < 0) { - dpiQueue__free(tempQueue, error); - return DPI_FAILURE; - } - memcpy(buffer, name, nameLength); - buffer[nameLength] = '\0'; - tempQueue->name = buffer; - - *queue = tempQueue; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiQueue__allocateBuffer() [INTERNAL] -// Ensure there is enough space in the buffer for the specified number of -// elements. -//----------------------------------------------------------------------------- -static int dpiQueue__allocateBuffer(dpiQueue *queue, uint32_t numElements, - dpiError *error) -{ - dpiQueue__freeBuffer(queue, error); - queue->buffer.numElements = numElements; - if (dpiUtils__allocateMemory(numElements, sizeof(dpiMsgProps*), 1, - "allocate msg props array", (void**) &queue->buffer.props, - error) < 0) - return DPI_FAILURE; - if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, - "allocate OCI handles array", (void**) &queue->buffer.handles, - error) < 0) - return DPI_FAILURE; - if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, - "allocate OCI instances array", (void**) &queue->buffer.instances, - error) < 0) - return DPI_FAILURE; - if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, - "allocate OCI indicators array", - (void**) &queue->buffer.indicators, error) < 0) - return DPI_FAILURE; - if (!queue->payloadType) { - if (dpiUtils__allocateMemory(numElements, sizeof(int16_t), 1, - "allocate OCI raw indicators array", - (void**) &queue->buffer.rawIndicators, error) < 0) - return DPI_FAILURE; - } - if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, - "allocate message ids array", (void**) &queue->buffer.msgIds, - error) < 0) - return DPI_FAILURE; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiQueue__check() [INTERNAL] -// Determine if the queue is available to use. -//----------------------------------------------------------------------------- -static int dpiQueue__check(dpiQueue *queue, const char *fnName, - dpiError *error) -{ - if (dpiGen__startPublicFn(queue, DPI_HTYPE_QUEUE, fnName, error) < 0) - return DPI_FAILURE; - if (!queue->conn->handle || queue->conn->closing) - return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiQueue__createDeqOptions() [INTERNAL] -// Create the dequeue options object that will be used for performing -// dequeues against the queue. -//----------------------------------------------------------------------------- -static int dpiQueue__createDeqOptions(dpiQueue *queue, dpiError *error) -{ - dpiDeqOptions *tempOptions; - - if (dpiGen__allocate(DPI_HTYPE_DEQ_OPTIONS, queue->env, - (void**) &tempOptions, error) < 0) - return DPI_FAILURE; - if (dpiDeqOptions__create(tempOptions, queue->conn, error) < 0) { - dpiDeqOptions__free(tempOptions, error); - return DPI_FAILURE; - } - - queue->deqOptions = tempOptions; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiQueue__createEnqOptions() [INTERNAL] -// Create the dequeue options object that will be used for performing -// dequeues against the queue. -//----------------------------------------------------------------------------- -static int dpiQueue__createEnqOptions(dpiQueue *queue, dpiError *error) -{ - dpiEnqOptions *tempOptions; - - if (dpiGen__allocate(DPI_HTYPE_ENQ_OPTIONS, queue->env, - (void**) &tempOptions, error) < 0) - return DPI_FAILURE; - if (dpiEnqOptions__create(tempOptions, queue->conn, error) < 0) { - dpiEnqOptions__free(tempOptions, error); - return DPI_FAILURE; - } - - queue->enqOptions = tempOptions; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiQueue__deq() [INTERNAL] -// Perform a dequeue of up to the specified number of properties. -//----------------------------------------------------------------------------- -static int dpiQueue__deq(dpiQueue *queue, uint32_t *numProps, - dpiMsgProps **props, dpiError *error) -{ - dpiMsgProps *prop; - void *payloadTDO; - uint32_t i; - - // create dequeue options, if necessary - if (!queue->deqOptions && dpiQueue__createDeqOptions(queue, error) < 0) - return DPI_FAILURE; - - // allocate buffer, if necessary - if (queue->buffer.numElements < *numProps && - dpiQueue__allocateBuffer(queue, *numProps, error) < 0) - return DPI_FAILURE; - - // populate buffer - for (i = 0; i < *numProps; i++) { - prop = queue->buffer.props[i]; - - // create new message properties, if applicable - if (!prop) { - if (dpiMsgProps__allocate(queue->conn, &prop, error) < 0) - return DPI_FAILURE; - queue->buffer.props[i] = prop; - } - - // create payload object, if applicable - if (queue->payloadType && !prop->payloadObj && - dpiObject__allocate(queue->payloadType, NULL, NULL, NULL, - &prop->payloadObj, error) < 0) - return DPI_FAILURE; - - // set OCI arrays - queue->buffer.handles[i] = prop->handle; - if (queue->payloadType) { - queue->buffer.instances[i] = prop->payloadObj->instance; - queue->buffer.indicators[i] = prop->payloadObj->indicator; - } else { - queue->buffer.instances[i] = prop->payloadRaw; - queue->buffer.indicators[i] = &queue->buffer.rawIndicators[i]; - } - queue->buffer.msgIds[i] = prop->msgIdRaw; - - } - - // perform dequeue - if (dpiQueue__getPayloadTDO(queue, &payloadTDO, error) < 0) - return DPI_FAILURE; - if (dpiOci__aqDeqArray(queue->conn, queue->name, queue->deqOptions->handle, - numProps, queue->buffer.handles, payloadTDO, - queue->buffer.instances, queue->buffer.indicators, - queue->buffer.msgIds, error) < 0) { - if (error->buffer->code != 25228) - return DPI_FAILURE; - error->buffer->offset = (uint16_t) *numProps; - } - - // transfer message properties to destination array - for (i = 0; i < *numProps; i++) { - props[i] = queue->buffer.props[i]; - queue->buffer.props[i] = NULL; - if (!queue->payloadType) - props[i]->payloadRaw = queue->buffer.instances[i]; - props[i]->msgIdRaw = queue->buffer.msgIds[i]; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiQueue__enq() [INTERNAL] -// Perform an enqueue of the specified properties. -//----------------------------------------------------------------------------- -static int dpiQueue__enq(dpiQueue *queue, uint32_t numProps, - dpiMsgProps **props, dpiError *error) -{ - void *payloadTDO; - uint32_t i; - - // if no messages are being enqueued, nothing to do! - if (numProps == 0) - return DPI_SUCCESS; - - // create enqueue options, if necessary - if (!queue->enqOptions && dpiQueue__createEnqOptions(queue, error) < 0) - return DPI_FAILURE; - - // allocate buffer, if necessary - if (queue->buffer.numElements < numProps && - dpiQueue__allocateBuffer(queue, numProps, error) < 0) - return DPI_FAILURE; - - // populate buffer - for (i = 0; i < numProps; i++) { - - // perform checks - if (!props[i]->payloadObj && !props[i]->payloadRaw) - return dpiError__set(error, "check payload", - DPI_ERR_QUEUE_NO_PAYLOAD); - if ((queue->payloadType && !props[i]->payloadObj) || - (!queue->payloadType && props[i]->payloadObj)) - return dpiError__set(error, "check payload", - DPI_ERR_QUEUE_WRONG_PAYLOAD_TYPE); - if (queue->payloadType && props[i]->payloadObj && - queue->payloadType->tdo != props[i]->payloadObj->type->tdo) - return dpiError__set(error, "check payload", - DPI_ERR_WRONG_TYPE, - props[i]->payloadObj->type->schemaLength, - props[i]->payloadObj->type->schema, - props[i]->payloadObj->type->nameLength, - props[i]->payloadObj->type->name, - queue->payloadType->schemaLength, - queue->payloadType->schema, - queue->payloadType->nameLength, - queue->payloadType->name); - - // set OCI arrays - queue->buffer.handles[i] = props[i]->handle; - if (queue->payloadType) { - queue->buffer.instances[i] = props[i]->payloadObj->instance; - queue->buffer.indicators[i] = props[i]->payloadObj->indicator; - } else { - queue->buffer.instances[i] = props[i]->payloadRaw; - queue->buffer.indicators[i] = &queue->buffer.rawIndicators[i]; - } - queue->buffer.msgIds[i] = props[i]->msgIdRaw; - - } - - // perform enqueue - if (dpiQueue__getPayloadTDO(queue, &payloadTDO, error) < 0) - return DPI_FAILURE; - if (numProps == 1) { - if (dpiOci__aqEnq(queue->conn, queue->name, queue->enqOptions->handle, - queue->buffer.handles[0], payloadTDO, queue->buffer.instances, - queue->buffer.indicators, queue->buffer.msgIds, error) < 0) - return DPI_FAILURE; - } else { - if (dpiOci__aqEnqArray(queue->conn, queue->name, - queue->enqOptions->handle, &numProps, queue->buffer.handles, - payloadTDO, queue->buffer.instances, queue->buffer.indicators, - queue->buffer.msgIds, error) < 0) { - error->buffer->offset = (uint16_t) numProps; - return DPI_FAILURE; - } - } - - // transfer message ids back to message properties - for (i = 0; i < numProps; i++) - props[i]->msgIdRaw = queue->buffer.msgIds[i]; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiQueue__free() [INTERNAL] -// Free the memory for a queue. -//----------------------------------------------------------------------------- -void dpiQueue__free(dpiQueue *queue, dpiError *error) -{ - if (queue->conn) { - dpiGen__setRefCount(queue->conn, error, -1); - queue->conn = NULL; - } - if (queue->payloadType) { - dpiGen__setRefCount(queue->payloadType, error, -1); - queue->payloadType = NULL; - } - if (queue->name) { - dpiUtils__freeMemory((void*) queue->name); - queue->name = NULL; - } - if (queue->deqOptions) { - dpiGen__setRefCount(queue->deqOptions, error, -1); - queue->deqOptions = NULL; - } - if (queue->enqOptions) { - dpiGen__setRefCount(queue->enqOptions, error, -1); - queue->enqOptions = NULL; - } - dpiQueue__freeBuffer(queue, error); - dpiUtils__freeMemory(queue); -} - - -//----------------------------------------------------------------------------- -// dpiQueue__freeBuffer() [INTERNAL] -// Free the memory areas in the queue buffer. -//----------------------------------------------------------------------------- -static void dpiQueue__freeBuffer(dpiQueue *queue, dpiError *error) -{ - dpiQueueBuffer *buffer = &queue->buffer; - uint32_t i; - - if (buffer->props) { - for (i = 0; i < buffer->numElements; i++) { - if (buffer->props[i]) { - dpiGen__setRefCount(buffer->props[i], error, -1); - buffer->props[i] = NULL; - } - } - dpiUtils__freeMemory(buffer->props); - buffer->props = NULL; - } - if (buffer->handles) { - dpiUtils__freeMemory(buffer->handles); - buffer->handles = NULL; - } - if (buffer->instances) { - dpiUtils__freeMemory(buffer->instances); - buffer->instances = NULL; - } - if (buffer->indicators) { - dpiUtils__freeMemory(buffer->indicators); - buffer->indicators = NULL; - } - if (buffer->rawIndicators) { - dpiUtils__freeMemory(buffer->rawIndicators); - buffer->rawIndicators = NULL; - } - if (buffer->msgIds) { - dpiUtils__freeMemory(buffer->msgIds); - buffer->msgIds = NULL; - } -} - - -//----------------------------------------------------------------------------- -// dpiQueue__getPayloadTDO() [INTERNAL] -// Acquire the TDO to use for the payload. This will either be the TDO of the -// object type (if one was specified when the queue was created) or it will be -// the RAW TDO cached on the connection. -//----------------------------------------------------------------------------- -static int dpiQueue__getPayloadTDO(dpiQueue *queue, void **tdo, - dpiError *error) -{ - if (queue->payloadType) { - *tdo = queue->payloadType->tdo; - } else { - if (dpiConn__getRawTDO(queue->conn, error) < 0) - return DPI_FAILURE; - *tdo = queue->conn->rawTDO; - } - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiQueue_addRef() [PUBLIC] -// Add a reference to the queue. -//----------------------------------------------------------------------------- -int dpiQueue_addRef(dpiQueue *queue) -{ - return dpiGen__addRef(queue, DPI_HTYPE_QUEUE, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiQueue_deqMany() [PUBLIC] -// Dequeue multiple messages from the queue. -//----------------------------------------------------------------------------- -int dpiQueue_deqMany(dpiQueue *queue, uint32_t *numProps, dpiMsgProps **props) -{ - dpiError error; - int status; - - if (dpiQueue__check(queue, __func__, &error) < 0) - return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(queue, numProps) - DPI_CHECK_PTR_NOT_NULL(queue, props) - status = dpiQueue__deq(queue, numProps, props, &error); - return dpiGen__endPublicFn(queue, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiQueue_deqOne() [PUBLIC] -// Dequeue a single message from the queue. -//----------------------------------------------------------------------------- -int dpiQueue_deqOne(dpiQueue *queue, dpiMsgProps **props) -{ - uint32_t numProps = 1; - dpiError error; - - if (dpiQueue__check(queue, __func__, &error) < 0) - return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(queue, props) - if (dpiQueue__deq(queue, &numProps, props, &error) < 0) - return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); - if (numProps == 0) - *props = NULL; - return dpiGen__endPublicFn(queue, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiQueue_enqMany() [PUBLIC] -// Enqueue multiple message to the queue. -//----------------------------------------------------------------------------- -int dpiQueue_enqMany(dpiQueue *queue, uint32_t numProps, dpiMsgProps **props) -{ - dpiError error; - uint32_t i; - int status; - - // validate parameters - if (dpiQueue__check(queue, __func__, &error) < 0) - return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(queue, props) - for (i = 0; i < numProps; i++) { - if (dpiGen__checkHandle(props[i], DPI_HTYPE_MSG_PROPS, - "check message properties", &error) < 0) - return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); - } - status = dpiQueue__enq(queue, numProps, props, &error); - return dpiGen__endPublicFn(queue, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiQueue_enqOne() [PUBLIC] -// Enqueue a single message to the queue. -//----------------------------------------------------------------------------- -int dpiQueue_enqOne(dpiQueue *queue, dpiMsgProps *props) -{ - dpiError error; - int status; - - if (dpiQueue__check(queue, __func__, &error) < 0) - return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); - if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS, - "check message properties", &error) < 0) - return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); - status = dpiQueue__enq(queue, 1, &props, &error); - return dpiGen__endPublicFn(queue, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiQueue_getDeqOptions() [PUBLIC] -// Return the dequeue options associated with the queue. If no dequeue -// options are currently associated with the queue, create them first. -//----------------------------------------------------------------------------- -int dpiQueue_getDeqOptions(dpiQueue *queue, dpiDeqOptions **options) -{ - dpiError error; - - if (dpiGen__startPublicFn(queue, DPI_HTYPE_QUEUE, __func__, &error) < 0) - return DPI_FAILURE; - DPI_CHECK_PTR_NOT_NULL(queue, options) - if (!queue->deqOptions && dpiQueue__createDeqOptions(queue, &error) < 0) - return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); - *options = queue->deqOptions; - return dpiGen__endPublicFn(queue, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiQueue_getEnqOptions() [PUBLIC] -// Return the enqueue options associated with the queue. If no enqueue -// options are currently associated with the queue, create them first. -//----------------------------------------------------------------------------- -int dpiQueue_getEnqOptions(dpiQueue *queue, dpiEnqOptions **options) -{ - dpiError error; - - if (dpiGen__startPublicFn(queue, DPI_HTYPE_QUEUE, __func__, &error) < 0) - return DPI_FAILURE; - DPI_CHECK_PTR_NOT_NULL(queue, options) - if (!queue->enqOptions && dpiQueue__createEnqOptions(queue, &error) < 0) - return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); - *options = queue->enqOptions; - return dpiGen__endPublicFn(queue, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiQueue_release() [PUBLIC] -// Release a reference to the queue. -//----------------------------------------------------------------------------- -int dpiQueue_release(dpiQueue *queue) -{ - return dpiGen__release(queue, DPI_HTYPE_QUEUE, __func__); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiRowid.c b/vendor/github.com/godror/godror/odpi/src/dpiRowid.c deleted file mode 100644 index 9bda49e7cd1..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiRowid.c +++ /dev/null @@ -1,134 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiRowid.c -// Implementation of rowids. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiRowid__allocate() [INTERNAL] -// Allocate and initialize a rowid object. -//----------------------------------------------------------------------------- -int dpiRowid__allocate(dpiConn *conn, dpiRowid **rowid, dpiError *error) -{ - dpiRowid *tempRowid; - - if (dpiGen__allocate(DPI_HTYPE_ROWID, conn->env, (void**) &tempRowid, - error) < 0) - return DPI_FAILURE; - if (dpiOci__descriptorAlloc(conn->env->handle, &tempRowid->handle, - DPI_OCI_DTYPE_ROWID, "allocate descriptor", error) < 0) { - dpiRowid__free(tempRowid, error); - return DPI_FAILURE; - } - - *rowid = tempRowid; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiRowid__free() [INTERNAL] -// Free the memory for a rowid. -//----------------------------------------------------------------------------- -void dpiRowid__free(dpiRowid *rowid, UNUSED dpiError *error) -{ - if (rowid->handle) { - dpiOci__descriptorFree(rowid->handle, DPI_OCI_DTYPE_ROWID); - rowid->handle = NULL; - } - if (rowid->buffer) { - dpiUtils__freeMemory(rowid->buffer); - rowid->buffer = NULL; - } - dpiUtils__freeMemory(rowid); -} - - -//----------------------------------------------------------------------------- -// dpiRowid_addRef() [PUBLIC] -// Add a reference to the rowid. -//----------------------------------------------------------------------------- -int dpiRowid_addRef(dpiRowid *rowid) -{ - return dpiGen__addRef(rowid, DPI_HTYPE_ROWID, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiRowid_getStringValue() [PUBLIC] -// Get the string representation of the rowid. -//----------------------------------------------------------------------------- -int dpiRowid_getStringValue(dpiRowid *rowid, const char **value, - uint32_t *valueLength) -{ - char temp, *adjustedBuffer, *sourcePtr; - uint16_t *targetPtr; - dpiError error; - uint16_t i; - - if (dpiGen__startPublicFn(rowid, DPI_HTYPE_ROWID, __func__, &error) < 0) - return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(rowid, value) - DPI_CHECK_PTR_NOT_NULL(rowid, valueLength) - if (!rowid->buffer) { - - // determine length of rowid - rowid->bufferLength = 0; - dpiOci__rowidToChar(rowid, &temp, &rowid->bufferLength, &error); - - // allocate and populate buffer containing string representation - if (dpiUtils__allocateMemory(1, rowid->bufferLength, 0, - "allocate rowid buffer", (void**) &rowid->buffer, &error) < 0) - return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); - if (dpiOci__rowidToChar(rowid, rowid->buffer, &rowid->bufferLength, - &error) < 0) - return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); - - // UTF-16 is not handled properly (data is returned as ASCII instead) - // adjust the buffer to use the correct encoding - if (rowid->env->charsetId == DPI_CHARSET_ID_UTF16) { - if (dpiUtils__allocateMemory(2, rowid->bufferLength, 0, - "allocate rowid buffer", (void**) &adjustedBuffer, - &error) < 0) { - dpiUtils__freeMemory(rowid->buffer); - rowid->bufferLength = 0; - rowid->buffer = NULL; - return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); - } - sourcePtr = rowid->buffer; - targetPtr = (uint16_t*) adjustedBuffer; - for (i = 0; i < rowid->bufferLength; i++) - *targetPtr++ = (uint16_t) *sourcePtr++; - dpiUtils__freeMemory(rowid->buffer); - rowid->buffer = adjustedBuffer; - rowid->bufferLength *= 2; - } - - } - - *value = rowid->buffer; - *valueLength = rowid->bufferLength; - return dpiGen__endPublicFn(rowid, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiRowid_release() [PUBLIC] -// Release a reference to the rowid. -//----------------------------------------------------------------------------- -int dpiRowid_release(dpiRowid *rowid) -{ - return dpiGen__release(rowid, DPI_HTYPE_ROWID, __func__); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSodaColl.c b/vendor/github.com/godror/godror/odpi/src/dpiSodaColl.c deleted file mode 100644 index b0a0ded7c34..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiSodaColl.c +++ /dev/null @@ -1,812 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiSodaColl.c -// Implementation of SODA collections. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiSodaColl__allocate() [INTERNAL] -// Allocate and initialize a SODA collection structure. -//----------------------------------------------------------------------------- -int dpiSodaColl__allocate(dpiSodaDb *db, void *handle, dpiSodaColl **coll, - dpiError *error) -{ - uint8_t sqlType, contentType; - dpiSodaColl *tempColl; - - if (dpiOci__attrGet(handle, DPI_OCI_HTYPE_SODA_COLLECTION, - (void*) &sqlType, 0, DPI_OCI_ATTR_SODA_CTNT_SQL_TYPE, - "get content sql type", error) < 0) - return DPI_FAILURE; - if (dpiGen__allocate(DPI_HTYPE_SODA_COLL, db->env, (void**) &tempColl, - error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(db, error, 1); - tempColl->db = db; - tempColl->handle = handle; - if (sqlType == DPI_SQLT_BLOB) { - tempColl->binaryContent = 1; - contentType = 0; - dpiOci__attrGet(handle, DPI_OCI_HTYPE_SODA_COLLECTION, - (void*) &contentType, 0, DPI_OCI_ATTR_SODA_CTNT_FORMAT, - NULL, error); - if (contentType == DPI_OCI_JSON_FORMAT_OSON) - tempColl->binaryContent = 0; - } - *coll = tempColl; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl__check() [INTERNAL] -// Determine if the SODA collection is available to use. -//----------------------------------------------------------------------------- -static int dpiSodaColl__check(dpiSodaColl *coll, const char *fnName, - dpiError *error) -{ - if (dpiGen__startPublicFn(coll, DPI_HTYPE_SODA_COLL, fnName, error) < 0) - return DPI_FAILURE; - if (!coll->db->conn->handle || coll->db->conn->closing) - return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl__createOperOptions() [INTERNAL] -// Create a SODA operation options handle with the specified information. -//----------------------------------------------------------------------------- -static int dpiSodaColl__createOperOptions(dpiSodaColl *coll, - const dpiSodaOperOptions *options, void **handle, dpiError *error) -{ - dpiSodaOperOptions localOptions; - - // if no options specified, use default values - if (!options) { - dpiContext__initSodaOperOptions(&localOptions); - options = &localOptions; - } - - // allocate new handle - if (dpiOci__handleAlloc(coll->env->handle, handle, - DPI_OCI_HTYPE_SODA_OPER_OPTIONS, - "allocate SODA operation options handle", error) < 0) - return DPI_FAILURE; - - // set multiple keys, if applicable - if (options->numKeys > 0) { - if (dpiOci__sodaOperKeysSet(options, *handle, error) < 0) { - dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); - return DPI_FAILURE; - } - } - - // set single key, if applicable - if (options->keyLength > 0) { - if (dpiOci__attrSet(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, - (void*) options->key, options->keyLength, - DPI_OCI_ATTR_SODA_KEY, "set key", error) < 0) { - dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); - return DPI_FAILURE; - } - } - - // set single version, if applicable - if (options->versionLength > 0) { - if (dpiOci__attrSet(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, - (void*) options->version, options->versionLength, - DPI_OCI_ATTR_SODA_VERSION, "set version", error) < 0) { - dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); - return DPI_FAILURE; - } - } - - // set filter, if applicable - if (options->filterLength > 0) { - if (dpiOci__attrSet(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, - (void*) options->filter, options->filterLength, - DPI_OCI_ATTR_SODA_FILTER, "set filter", error) < 0) { - dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); - return DPI_FAILURE; - } - } - - // set skip count, if applicable - if (options->skip > 0) { - if (dpiOci__attrSet(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, - (void*) &options->skip, 0, DPI_OCI_ATTR_SODA_SKIP, - "set skip count", error) < 0) { - dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); - return DPI_FAILURE; - } - } - - // set limit, if applicable - if (options->limit > 0) { - if (dpiOci__attrSet(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, - (void*) &options->limit, 0, DPI_OCI_ATTR_SODA_LIMIT, - "set limit", error) < 0) { - dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); - return DPI_FAILURE; - } - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl__find() [INTERNAL] -// Perform a find of SODA documents by creating an operation options handle -// and populating it with the requested options. Once the find is complete, -// return either a cursor or a document. -//----------------------------------------------------------------------------- -static int dpiSodaColl__find(dpiSodaColl *coll, - const dpiSodaOperOptions *options, uint32_t flags, - dpiSodaDocCursor **cursor, dpiSodaDoc **doc, dpiError *error) -{ - uint32_t ociMode, returnHandleType, ociFlags; - void *optionsHandle, *ociReturnHandle; - int status; - - // determine OCI mode to pass - ociMode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - ociMode |= DPI_OCI_SODA_ATOMIC_COMMIT; - - // create new OCI operation options handle - if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, - error) < 0) - return DPI_FAILURE; - - // determine OCI flags to use - ociFlags = (coll->binaryContent) ? DPI_OCI_SODA_AS_STORED : - DPI_OCI_SODA_AS_AL32UTF8; - - // perform actual find - if (cursor) { - *cursor = NULL; - status = dpiOci__sodaFind(coll, optionsHandle, ociFlags, ociMode, - &ociReturnHandle, error); - } else { - *doc = NULL; - status = dpiOci__sodaFindOne(coll, optionsHandle, ociFlags, ociMode, - &ociReturnHandle, error); - } - dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); - if (status < 0) - return DPI_FAILURE; - - // return cursor or document, as appropriate - if (cursor) { - status = dpiSodaDocCursor__allocate(coll, ociReturnHandle, cursor, - error); - returnHandleType = DPI_OCI_HTYPE_SODA_DOC_CURSOR; - } else if (ociReturnHandle) { - status = dpiSodaDoc__allocate(coll->db, ociReturnHandle, doc, error); - returnHandleType = DPI_OCI_HTYPE_SODA_DOCUMENT; - } - if (status < 0) - dpiOci__handleFree(ociReturnHandle, returnHandleType); - - return status; -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl__free() [INTERNAL] -// Free the memory for a SODA collection. Note that the reference to the -// database must remain until after the handle is freed; otherwise, a segfault -// can take place. -//----------------------------------------------------------------------------- -void dpiSodaColl__free(dpiSodaColl *coll, dpiError *error) -{ - if (coll->handle) { - dpiOci__handleFree(coll->handle, DPI_OCI_HTYPE_SODA_COLLECTION); - coll->handle = NULL; - } - if (coll->db) { - dpiGen__setRefCount(coll->db, error, -1); - coll->db = NULL; - } - dpiUtils__freeMemory(coll); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl__getDocCount() [INTERNAL] -// Internal method for getting document count. -//----------------------------------------------------------------------------- -static int dpiSodaColl__getDocCount(dpiSodaColl *coll, - const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count, - dpiError *error) -{ - void *optionsHandle; - uint32_t ociMode; - int status; - - // determine OCI mode to pass - ociMode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - ociMode |= DPI_OCI_SODA_ATOMIC_COMMIT; - - // create new OCI operation options handle - if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, - error) < 0) - return DPI_FAILURE; - - // perform actual document count - status = dpiOci__sodaDocCount(coll, optionsHandle, ociMode, count, error); - dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); - return status; -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl__insertMany() [INTERNAL] -// Insert multiple documents into the collection and return handles to the -// newly created documents, if desired. -//----------------------------------------------------------------------------- -static int dpiSodaColl__insertMany(dpiSodaColl *coll, uint32_t numDocs, - void **docHandles, uint32_t flags, dpiSodaDoc **insertedDocs, - dpiError *error) -{ - void *optionsHandle; - uint32_t i, j, mode; - uint64_t docCount; - int status; - - // create OCI output options handle - if (dpiOci__handleAlloc(coll->env->handle, &optionsHandle, - DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS, - "allocate SODA output options handle", error) < 0) - return DPI_FAILURE; - - // determine mode to pass - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - - // perform actual bulk insert - if (insertedDocs) { - status = dpiOci__sodaBulkInsertAndGet(coll, docHandles, numDocs, - optionsHandle, mode, error); - } else { - status = dpiOci__sodaBulkInsert(coll, docHandles, numDocs, - optionsHandle, mode, error); - } - - // on failure, determine the number of documents that were successfully - // inserted and store that information in the error buffer - if (status < 0) { - dpiOci__attrGet(optionsHandle, DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS, - (void*) &docCount, 0, DPI_OCI_ATTR_SODA_DOC_COUNT, - NULL, error); - error->buffer->offset = (uint16_t) docCount; - } - dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS); - - // on failure, if using the "AndGet" variant, any document handles that - // were created need to be freed - if (insertedDocs && status < 0) { - for (i = 0; i < numDocs; i++) { - if (docHandles[i]) { - dpiOci__handleFree(docHandles[i], DPI_OCI_HTYPE_SODA_DOCUMENT); - docHandles[i] = NULL; - } - } - } - if (status < 0) - return DPI_FAILURE; - - // return document handles, if desired - if (insertedDocs) { - for (i = 0; i < numDocs; i++) { - if (dpiSodaDoc__allocate(coll->db, docHandles[i], &insertedDocs[i], - error) < 0) { - for (j = 0; j < i; j++) { - dpiSodaDoc__free(insertedDocs[j], error); - insertedDocs[j] = NULL; - } - for (j = i; j < numDocs; j++) { - dpiOci__handleFree(docHandles[i], - DPI_OCI_HTYPE_SODA_DOCUMENT); - } - return DPI_FAILURE; - } - } - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl__remove() [INTERNAL] -// Internal method for removing documents from a collection. -//----------------------------------------------------------------------------- -static int dpiSodaColl__remove(dpiSodaColl *coll, - const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count, - dpiError *error) -{ - void *optionsHandle; - uint32_t mode; - int status; - - // determine OCI mode to pass - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - - // create new OCI operation options handle - if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, - error) < 0) - return DPI_FAILURE; - - // remove documents from collection - status = dpiOci__sodaRemove(coll, optionsHandle, mode, count, error); - dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); - return status; -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl__replace() [INTERNAL] -// Internal method for replacing a document in the collection. -//----------------------------------------------------------------------------- -static int dpiSodaColl__replace(dpiSodaColl *coll, - const dpiSodaOperOptions *options, dpiSodaDoc *doc, uint32_t flags, - int *replaced, dpiSodaDoc **replacedDoc, dpiError *error) -{ - void *docHandle, *optionsHandle; - int status, dummyIsReplaced; - uint32_t mode; - - // use dummy value if the replaced flag is not desired - if (!replaced) - replaced = &dummyIsReplaced; - - // determine OCI mode to pass - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - - // create new OCI operation options handle - if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, - error) < 0) - return DPI_FAILURE; - - // replace document in collection - // use "AndGet" variant if the replaced document is requested - docHandle = doc->handle; - if (!replacedDoc) { - status = dpiOci__sodaReplOne(coll, optionsHandle, docHandle, mode, - replaced, error); - } else { - *replacedDoc = NULL; - status = dpiOci__sodaReplOneAndGet(coll, optionsHandle, &docHandle, - mode, replaced, error); - if (status == 0 && docHandle) { - status = dpiSodaDoc__allocate(coll->db, docHandle, replacedDoc, - error); - if (status < 0) - dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); - } - } - - dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); - return status; -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_addRef() [PUBLIC] -// Add a reference to the SODA collection. -//----------------------------------------------------------------------------- -int dpiSodaColl_addRef(dpiSodaColl *coll) -{ - return dpiGen__addRef(coll, DPI_HTYPE_SODA_COLL, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_createIndex() [PUBLIC] -// Create an index on the collection. -//----------------------------------------------------------------------------- -int dpiSodaColl_createIndex(dpiSodaColl *coll, const char *indexSpec, - uint32_t indexSpecLength, uint32_t flags) -{ - dpiError error; - uint32_t mode; - int status; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(coll, indexSpec) - - // determine mode to pass to OCI - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - - // create index - status = dpiOci__sodaIndexCreate(coll, indexSpec, indexSpecLength, mode, - &error); - return dpiGen__endPublicFn(coll, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_drop() [PUBLIC] -// Drop the collection. -//----------------------------------------------------------------------------- -int dpiSodaColl_drop(dpiSodaColl *coll, uint32_t flags, int *isDropped) -{ - int status, dummyIsDropped; - dpiError error; - uint32_t mode; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - - // isDropped is not a mandatory parameter, but it is for OCI - if (!isDropped) - isDropped = &dummyIsDropped; - - // determine mode to pass to OCI - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - - // drop collection - status = dpiOci__sodaCollDrop(coll, isDropped, mode, &error); - return dpiGen__endPublicFn(coll, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_dropIndex() [PUBLIC] -// Drop the index on the collection. -//----------------------------------------------------------------------------- -int dpiSodaColl_dropIndex(dpiSodaColl *coll, const char *name, - uint32_t nameLength, uint32_t flags, int *isDropped) -{ - int status, dummyIsDropped; - dpiError error; - uint32_t mode; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(coll, name) - - // isDropped is not a mandatory parameter, but it is for OCI - if (!isDropped) - isDropped = &dummyIsDropped; - - // determine mode to pass to OCI - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - if (flags & DPI_SODA_FLAGS_INDEX_DROP_FORCE) - mode |= DPI_OCI_SODA_INDEX_DROP_FORCE; - - // drop index - status = dpiOci__sodaIndexDrop(coll, name, nameLength, mode, isDropped, - &error); - return dpiGen__endPublicFn(coll, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_find() [PUBLIC] -// Find documents in a collection and return a cursor. -//----------------------------------------------------------------------------- -int dpiSodaColl_find(dpiSodaColl *coll, const dpiSodaOperOptions *options, - uint32_t flags, dpiSodaDocCursor **cursor) -{ - dpiError error; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(coll, cursor) - - // perform find and return a cursor - if (dpiSodaColl__find(coll, options, flags, cursor, NULL, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - - return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_findOne() [PUBLIC] -// Find a single document in a collection and return it. -//----------------------------------------------------------------------------- -int dpiSodaColl_findOne(dpiSodaColl *coll, const dpiSodaOperOptions *options, - uint32_t flags, dpiSodaDoc **doc) -{ - dpiError error; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(coll, doc) - - // perform find and return a document - if (dpiSodaColl__find(coll, options, flags, NULL, doc, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - - return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_getDataGuide() [PUBLIC] -// Return the data guide document for the collection. -//----------------------------------------------------------------------------- -int dpiSodaColl_getDataGuide(dpiSodaColl *coll, uint32_t flags, - dpiSodaDoc **doc) -{ - void *docHandle; - dpiError error; - uint32_t mode; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(coll, doc) - - // determine mode to pass - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - - // get data guide - if (dpiOci__sodaDataGuideGet(coll, &docHandle, mode, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - if (!docHandle) { - *doc = NULL; - } else if (dpiSodaDoc__allocate(coll->db, docHandle, doc, &error) < 0) { - dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - } - - return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_getDocCount() [PUBLIC] -// Return the number of documents in the collection that match the specified -// criteria. -//----------------------------------------------------------------------------- -int dpiSodaColl_getDocCount(dpiSodaColl *coll, - const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count) -{ - dpiError error; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(coll, count) - - // get document count - if (dpiSodaColl__getDocCount(coll, options, flags, count, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - - return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_getMetadata() [PUBLIC] -// Return the metadata for the collection. -//----------------------------------------------------------------------------- -int dpiSodaColl_getMetadata(dpiSodaColl *coll, const char **value, - uint32_t *valueLength) -{ - dpiError error; - int status; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(coll, value) - DPI_CHECK_PTR_NOT_NULL(coll, valueLength) - - // get attribute value - status = dpiOci__attrGet(coll->handle, DPI_OCI_HTYPE_SODA_COLLECTION, - (void*) value, valueLength, DPI_OCI_ATTR_SODA_COLL_DESCRIPTOR, - "get value", &error); - return dpiGen__endPublicFn(coll, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_getName() [PUBLIC] -// Return the name of the collection. -//----------------------------------------------------------------------------- -int dpiSodaColl_getName(dpiSodaColl *coll, const char **value, - uint32_t *valueLength) -{ - dpiError error; - int status; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(coll, value) - DPI_CHECK_PTR_NOT_NULL(coll, valueLength) - - // get attribute value - status = dpiOci__attrGet(coll->handle, DPI_OCI_HTYPE_SODA_COLLECTION, - (void*) value, valueLength, DPI_OCI_ATTR_SODA_COLL_NAME, - "get value", &error); - return dpiGen__endPublicFn(coll, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_insertMany() [PUBLIC] -// Insert multiple documents into the collection and return handles to the -// newly created documents, if desired. -//----------------------------------------------------------------------------- -int dpiSodaColl_insertMany(dpiSodaColl *coll, uint32_t numDocs, - dpiSodaDoc **docs, uint32_t flags, dpiSodaDoc **insertedDocs) -{ - void **docHandles; - dpiError error; - uint32_t i; - int status; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(coll, docs) - if (numDocs == 0) { - dpiError__set(&error, "check num documents", DPI_ERR_ARRAY_SIZE_ZERO); - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - } - for (i = 0; i < numDocs; i++) { - if (dpiGen__checkHandle(docs[i], DPI_HTYPE_SODA_DOC, "check document", - &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - } - - // bulk insert is only supported with Oracle Client 18.5+ - if (dpiUtils__checkClientVersion(coll->env->versionInfo, 18, 5, - &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - - // create and populate array to hold document handles - if (dpiUtils__allocateMemory(numDocs, sizeof(void*), 1, - "allocate document handles", (void**) &docHandles, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - for (i = 0; i < numDocs; i++) - docHandles[i] = docs[i]->handle; - - // perform bulk insert - status = dpiSodaColl__insertMany(coll, numDocs, docHandles, flags, - insertedDocs, &error); - dpiUtils__freeMemory(docHandles); - return dpiGen__endPublicFn(coll, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_insertOne() [PUBLIC] -// Insert a document into the collection and return a handle to the newly -// created document, if desired. -//----------------------------------------------------------------------------- -int dpiSodaColl_insertOne(dpiSodaColl *coll, dpiSodaDoc *doc, uint32_t flags, - dpiSodaDoc **insertedDoc) -{ - void *docHandle; - dpiError error; - uint32_t mode; - int status; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - if (dpiGen__checkHandle(doc, DPI_HTYPE_SODA_DOC, "check document", - &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - - // determine OCI mode to use - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - - // insert document into collection - // use "AndGet" variant if the inserted document is requested - docHandle = doc->handle; - if (!insertedDoc) - status = dpiOci__sodaInsert(coll, docHandle, mode, &error); - else { - status = dpiOci__sodaInsertAndGet(coll, &docHandle, mode, &error); - if (status == 0) { - status = dpiSodaDoc__allocate(coll->db, docHandle, insertedDoc, - &error); - if (status < 0) - dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); - } - } - - return dpiGen__endPublicFn(coll, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_release() [PUBLIC] -// Release a reference to the SODA collection. -//----------------------------------------------------------------------------- -int dpiSodaColl_release(dpiSodaColl *coll) -{ - return dpiGen__release(coll, DPI_HTYPE_SODA_COLL, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_remove() [PUBLIC] -// Remove the documents from the collection that match the given criteria. -//----------------------------------------------------------------------------- -int dpiSodaColl_remove(dpiSodaColl *coll, const dpiSodaOperOptions *options, - uint32_t flags, uint64_t *count) -{ - dpiError error; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(coll, count) - - // perform removal - if (dpiSodaColl__remove(coll, options, flags, count, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - - return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaColl_replaceOne() [PUBLIC] -// Replace the first document in the collection that matches the given -// criteria. Returns a handle to the newly replaced document, if desired. -//----------------------------------------------------------------------------- -int dpiSodaColl_replaceOne(dpiSodaColl *coll, - const dpiSodaOperOptions *options, dpiSodaDoc *doc, uint32_t flags, - int *replaced, dpiSodaDoc **replacedDoc) -{ - dpiError error; - int status; - - // validate parameters - if (dpiSodaColl__check(coll, __func__, &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - if (dpiGen__checkHandle(doc, DPI_HTYPE_SODA_DOC, "check document", - &error) < 0) - return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); - - // perform replace - status = dpiSodaColl__replace(coll, options, doc, flags, replaced, - replacedDoc, &error); - return dpiGen__endPublicFn(coll, status, &error); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSodaCollCursor.c b/vendor/github.com/godror/godror/odpi/src/dpiSodaCollCursor.c deleted file mode 100644 index f4e91a427cb..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiSodaCollCursor.c +++ /dev/null @@ -1,144 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiSodaCollCursor.c -// Implementation of SODA collection cursors. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiSodaCollCursor__allocate() [INTERNAL] -// Allocate and initialize a SODA collection cursor structure. -//----------------------------------------------------------------------------- -int dpiSodaCollCursor__allocate(dpiSodaDb *db, void *handle, - dpiSodaCollCursor **cursor, dpiError *error) -{ - dpiSodaCollCursor *tempCursor; - - if (dpiGen__allocate(DPI_HTYPE_SODA_COLL_CURSOR, db->env, - (void**) &tempCursor, error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(db, error, 1); - tempCursor->db = db; - tempCursor->handle = handle; - *cursor = tempCursor; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaCollCursor__check() [INTERNAL] -// Determine if the SODA collection cursor is available to use. -//----------------------------------------------------------------------------- -static int dpiSodaCollCursor__check(dpiSodaCollCursor *cursor, - const char *fnName, dpiError *error) -{ - if (dpiGen__startPublicFn(cursor, DPI_HTYPE_SODA_COLL_CURSOR, fnName, - error) < 0) - return DPI_FAILURE; - if (!cursor->handle) - return dpiError__set(error, "check closed", - DPI_ERR_SODA_CURSOR_CLOSED); - if (!cursor->db->conn->handle || cursor->db->conn->closing) - return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaCollCursor__free() [INTERNAL] -// Free the memory for a SODA collection cursor. Note that the reference to -// the database must remain until after the handle is freed; otherwise, a -// segfault can take place. -//----------------------------------------------------------------------------- -void dpiSodaCollCursor__free(dpiSodaCollCursor *cursor, dpiError *error) -{ - if (cursor->handle) { - dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); - cursor->handle = NULL; - } - if (cursor->db) { - dpiGen__setRefCount(cursor->db, error, -1); - cursor->db = NULL; - } - dpiUtils__freeMemory(cursor); -} - - -//----------------------------------------------------------------------------- -// dpiSodaCollCursor_addRef() [PUBLIC] -// Add a reference to the SODA collection cursor. -//----------------------------------------------------------------------------- -int dpiSodaCollCursor_addRef(dpiSodaCollCursor *cursor) -{ - return dpiGen__addRef(cursor, DPI_HTYPE_SODA_COLL_CURSOR, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaCollCursor_close() [PUBLIC] -// Close the cursor. -//----------------------------------------------------------------------------- -int dpiSodaCollCursor_close(dpiSodaCollCursor *cursor) -{ - dpiError error; - - if (dpiSodaCollCursor__check(cursor, __func__, &error) < 0) - return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); - if (cursor->handle) { - dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); - cursor->handle = NULL; - } - return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaCollCursor_getNext() [PUBLIC] -// Return the next collection available from the cursor. -//----------------------------------------------------------------------------- -int dpiSodaCollCursor_getNext(dpiSodaCollCursor *cursor, uint32_t flags, - dpiSodaColl **coll) -{ - dpiError error; - uint32_t mode; - void *handle; - - if (dpiSodaCollCursor__check(cursor, __func__, &error) < 0) - return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(cursor, coll) - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - if (dpiOci__sodaCollGetNext(cursor->db->conn, cursor->handle, &handle, - mode, &error) < 0) - return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); - *coll = NULL; - if (handle) { - if (dpiSodaColl__allocate(cursor->db, handle, coll, &error) < 0) { - dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLLECTION); - return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); - } - } - return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaCollCursor_release() [PUBLIC] -// Release a reference to the SODA collection cursor. -//----------------------------------------------------------------------------- -int dpiSodaCollCursor_release(dpiSodaCollCursor *cursor) -{ - return dpiGen__release(cursor, DPI_HTYPE_SODA_COLL_CURSOR, __func__); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSodaDb.c b/vendor/github.com/godror/godror/odpi/src/dpiSodaDb.c deleted file mode 100644 index 0e1605a3507..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiSodaDb.c +++ /dev/null @@ -1,431 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiSodaDb.c -// Implementation of SODA database methods. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiSodaDb__checkConnected() [INTERNAL] -// Check to see that the connection to the database is available for use. -//----------------------------------------------------------------------------- -static int dpiSodaDb__checkConnected(dpiSodaDb *db, const char *fnName, - dpiError *error) -{ - if (dpiGen__startPublicFn(db, DPI_HTYPE_SODA_DB, fnName, error) < 0) - return DPI_FAILURE; - if (!db->conn->handle || db->conn->closing) - return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaDb__getCollectionNames() [PUBLIC] -// Internal method used for getting all collection names from the database. -// The provided cursor handle is iterated until either the limit is reached -// or there are no more collections to find. -//----------------------------------------------------------------------------- -static int dpiSodaDb__getCollectionNames(dpiSodaDb *db, void *cursorHandle, - uint32_t limit, dpiSodaCollNames *names, char **namesBuffer, - dpiError *error) -{ - uint32_t numAllocatedNames, namesBufferUsed, namesBufferAllocated; - uint32_t i, nameLength, *tempNameLengths; - char *name, *tempNamesBuffer, *ptr; - void *collectionHandle; - - ptr = *namesBuffer; - namesBufferUsed = namesBufferAllocated = numAllocatedNames = 0; - while (names->numNames < limit || limit == 0) { - - // get next collection from cursor - if (dpiOci__sodaCollGetNext(db->conn, cursorHandle, &collectionHandle, - DPI_OCI_DEFAULT, error) < 0) - return DPI_FAILURE; - if (!collectionHandle) - break; - - // get name from collection - if (dpiOci__attrGet(collectionHandle, DPI_OCI_HTYPE_SODA_COLLECTION, - (void*) &name, &nameLength, DPI_OCI_ATTR_SODA_COLL_NAME, - "get collection name", error) < 0) { - dpiOci__handleFree(collectionHandle, - DPI_OCI_HTYPE_SODA_COLLECTION); - return DPI_FAILURE; - } - - // allocate additional space for the lengths array, if needed - if (numAllocatedNames <= names->numNames) { - numAllocatedNames += 256; - if (dpiUtils__allocateMemory(numAllocatedNames, sizeof(uint32_t), - 0, "allocate lengths array", (void**) &tempNameLengths, - error) < 0) { - dpiOci__handleFree(collectionHandle, - DPI_OCI_HTYPE_SODA_COLLECTION); - return DPI_FAILURE; - } - if (names->nameLengths) { - memcpy(tempNameLengths, names->nameLengths, - names->numNames * sizeof(uint32_t)); - dpiUtils__freeMemory(names->nameLengths); - } - names->nameLengths = tempNameLengths; - } - - // allocate additional space for the names buffer, if needed - if (namesBufferUsed + nameLength > namesBufferAllocated) { - namesBufferAllocated += 32768; - if (dpiUtils__allocateMemory(namesBufferAllocated, 1, 0, - "allocate names buffer", (void**) &tempNamesBuffer, - error) < 0) { - dpiOci__handleFree(collectionHandle, - DPI_OCI_HTYPE_SODA_COLLECTION); - return DPI_FAILURE; - } - if (*namesBuffer) { - memcpy(tempNamesBuffer, *namesBuffer, namesBufferUsed); - dpiUtils__freeMemory(*namesBuffer); - } - *namesBuffer = tempNamesBuffer; - ptr = *namesBuffer + namesBufferUsed; - } - - // store name in buffer and length in array - // the names array itself is created and populated afterwards in order - // to avoid unnecessary copying - memcpy(ptr, name, nameLength); - namesBufferUsed += nameLength; - names->nameLengths[names->numNames] = nameLength; - names->numNames++; - ptr += nameLength; - - // free collection now that we have processed it successfully - dpiOci__handleFree(collectionHandle, DPI_OCI_HTYPE_SODA_COLLECTION); - - } - - // now that all of the names have been determined, populate names array - if (names->numNames > 0) { - if (dpiUtils__allocateMemory(names->numNames, sizeof(char*), 0, - "allocate names array", (void**) &names->names, error) < 0) - return DPI_FAILURE; - ptr = *namesBuffer; - for (i = 0; i < names->numNames; i++) { - names->names[i] = ptr; - ptr += names->nameLengths[i]; - } - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaDb__free() [INTERNAL] -// Free the memory for a SODA database. -//----------------------------------------------------------------------------- -void dpiSodaDb__free(dpiSodaDb *db, dpiError *error) -{ - if (db->conn) { - dpiGen__setRefCount(db->conn, error, -1); - db->conn = NULL; - } - dpiUtils__freeMemory(db); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDb_addRef() [PUBLIC] -// Add a reference to the SODA database. -//----------------------------------------------------------------------------- -int dpiSodaDb_addRef(dpiSodaDb *db) -{ - return dpiGen__addRef(db, DPI_HTYPE_SODA_DB, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDb_createCollection() [PUBLIC] -// Create a new SODA collection with the given name and metadata. -//----------------------------------------------------------------------------- -int dpiSodaDb_createCollection(dpiSodaDb *db, const char *name, - uint32_t nameLength, const char *metadata, uint32_t metadataLength, - uint32_t flags, dpiSodaColl **coll) -{ - dpiError error; - uint32_t mode; - void *handle; - - // validate parameters - if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(db, name) - DPI_CHECK_PTR_AND_LENGTH(db, metadata) - DPI_CHECK_PTR_NOT_NULL(db, coll) - - // determine OCI mode to use - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - if (flags & DPI_SODA_FLAGS_CREATE_COLL_MAP) - mode |= DPI_OCI_SODA_COLL_CREATE_MAP; - - // create collection - if (dpiOci__sodaCollCreateWithMetadata(db, name, nameLength, metadata, - metadataLength, mode, &handle, &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - if (dpiSodaColl__allocate(db, handle, coll, &error) < 0) { - dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLLECTION); - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - } - return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDb_createDocument() [PUBLIC] -// Create a SODA document that can be inserted in the collection or can be -// used to replace and existing document in the collection. -//----------------------------------------------------------------------------- -int dpiSodaDb_createDocument(dpiSodaDb *db, const char *key, - uint32_t keyLength, const char *content, uint32_t contentLength, - const char *mediaType, uint32_t mediaTypeLength, UNUSED uint32_t flags, - dpiSodaDoc **doc) -{ - int detectEncoding; - void *docHandle; - dpiError error; - - // validate parameters - if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(db, key) - DPI_CHECK_PTR_AND_LENGTH(db, content) - DPI_CHECK_PTR_AND_LENGTH(db, mediaType) - DPI_CHECK_PTR_NOT_NULL(db, doc) - - // allocate SODA document handle - if (dpiOci__handleAlloc(db->env->handle, &docHandle, - DPI_OCI_HTYPE_SODA_DOCUMENT, "allocate SODA document handle", - &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - - // set key, if applicable - if (key && keyLength > 0) { - if (dpiOci__attrSet(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT, - (void*) key, keyLength, DPI_OCI_ATTR_SODA_KEY, "set key", - &error) < 0) { - dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - } - } - - // set content, if applicable - if (content && contentLength > 0) { - detectEncoding = 1; - if (dpiOci__attrSet(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT, - (void*) &detectEncoding, 0, DPI_OCI_ATTR_SODA_DETECT_JSON_ENC, - "set detect encoding", &error) < 0) { - dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - } - if (dpiOci__attrSet(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT, - (void*) content, contentLength, DPI_OCI_ATTR_SODA_CONTENT, - "set content", &error) < 0) { - dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - } - } - - // set media type, if applicable - if (mediaType && mediaTypeLength > 0) { - if (dpiOci__attrSet(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT, - (void*) mediaType, mediaTypeLength, - DPI_OCI_ATTR_SODA_MEDIA_TYPE, "set media type", &error) < 0) { - dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - } - } - - // allocate the ODPI-C document that will be returned - if (dpiSodaDoc__allocate(db, docHandle, doc, &error) < 0) { - dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - } - (*doc)->binaryContent = 1; - - return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDb_freeCollectionNames() [PUBLIC] -// Free the names of the collections allocated earlier with a call to -// dpiSodaDb_getCollectionNames(). -//----------------------------------------------------------------------------- -int dpiSodaDb_freeCollectionNames(dpiSodaDb *db, dpiSodaCollNames *names) -{ - dpiError error; - - // validate parameters - if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(db, names) - - // perform frees; note that the memory for the names themselves is stored - // in one contiguous block pointed to by the first name - if (names->names) { - dpiUtils__freeMemory((void*) names->names[0]); - dpiUtils__freeMemory((void*) names->names); - names->names = NULL; - } - if (names->nameLengths) { - dpiUtils__freeMemory(names->nameLengths); - names->nameLengths = NULL; - } - names->numNames = 0; - - return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDb_getCollections() [PUBLIC] -// Return a cursor to iterate over the SODA collections in the database. -//----------------------------------------------------------------------------- -int dpiSodaDb_getCollections(dpiSodaDb *db, const char *startName, - uint32_t startNameLength, uint32_t flags, dpiSodaCollCursor **cursor) -{ - dpiError error; - uint32_t mode; - void *handle; - - if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(db, startName) - DPI_CHECK_PTR_NOT_NULL(db, cursor) - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - if (dpiOci__sodaCollList(db, startName, startNameLength, &handle, mode, - &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - if (dpiSodaCollCursor__allocate(db, handle, cursor, &error) < 0) { - dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - } - return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDb_getCollectionNames() [PUBLIC] -// Return the names of all collections in the provided array. -//----------------------------------------------------------------------------- -int dpiSodaDb_getCollectionNames(dpiSodaDb *db, const char *startName, - uint32_t startNameLength, uint32_t limit, uint32_t flags, - dpiSodaCollNames *names) -{ - char *namesBuffer; - dpiError error; - uint32_t mode; - void *handle; - int status; - - // validate parameters - if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(db, startName) - DPI_CHECK_PTR_NOT_NULL(db, names) - - // initialize output structure - names->numNames = 0; - names->names = NULL; - names->nameLengths = NULL; - - // determine OCI mode to use - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - - // acquire collection cursor - if (dpiOci__sodaCollList(db, startName, startNameLength, &handle, mode, - &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - - // iterate over cursor to acquire collection names - namesBuffer = NULL; - status = dpiSodaDb__getCollectionNames(db, handle, limit, names, - &namesBuffer, &error); - dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); - if (status < 0) { - names->numNames = 0; - if (namesBuffer) { - dpiUtils__freeMemory(namesBuffer); - namesBuffer = NULL; - } - if (names->names) { - dpiUtils__freeMemory((void*) names->names); - names->names = NULL; - } - if (names->nameLengths) { - dpiUtils__freeMemory(names->nameLengths); - names->nameLengths = NULL; - } - } - return dpiGen__endPublicFn(db, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDb_openCollection() [PUBLIC] -// Open an existing SODA collection and return a handle to it. -//----------------------------------------------------------------------------- -int dpiSodaDb_openCollection(dpiSodaDb *db, const char *name, - uint32_t nameLength, uint32_t flags, dpiSodaColl **coll) -{ - dpiError error; - uint32_t mode; - void *handle; - - if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(db, name) - DPI_CHECK_PTR_NOT_NULL(db, coll) - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - if (dpiOci__sodaCollOpen(db, name, nameLength, mode, &handle, - &error) < 0) - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - *coll = NULL; - if (handle) { - if (dpiSodaColl__allocate(db, handle, coll, &error) < 0) { - dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLLECTION); - return dpiGen__endPublicFn(db, DPI_FAILURE, &error); - } - } - return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDb_release() [PUBLIC] -// Release a reference to the SODA database. -//----------------------------------------------------------------------------- -int dpiSodaDb_release(dpiSodaDb *db) -{ - return dpiGen__release(db, DPI_HTYPE_SODA_DB, __func__); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSodaDoc.c b/vendor/github.com/godror/godror/odpi/src/dpiSodaDoc.c deleted file mode 100644 index b009e33a44a..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiSodaDoc.c +++ /dev/null @@ -1,231 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiSodaDoc.c -// Implementation of SODA documents. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiSodaDoc__allocate() [INTERNAL] -// Allocate and initialize a SODA document structure. -//----------------------------------------------------------------------------- -int dpiSodaDoc__allocate(dpiSodaDb *db, void *handle, dpiSodaDoc **doc, - dpiError *error) -{ - dpiSodaDoc *tempDoc; - - if (dpiGen__allocate(DPI_HTYPE_SODA_DOC, db->env, (void**) &tempDoc, - error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(db, error, 1); - tempDoc->db = db; - tempDoc->handle = handle; - *doc = tempDoc; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc__check() [INTERNAL] -// Determine if the SODA document is available to use. -//----------------------------------------------------------------------------- -static int dpiSodaDoc__check(dpiSodaDoc *doc, const char *fnName, - dpiError *error) -{ - if (dpiGen__startPublicFn(doc, DPI_HTYPE_SODA_DOC, fnName, error) < 0) - return DPI_FAILURE; - if (!doc->db->conn->handle || doc->db->conn->closing) - return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc__free() [INTERNAL] -// Free the memory for a SODA document. Note that the reference to the -// database must remain until after the handle is freed; otherwise, a segfault -// can take place. -//----------------------------------------------------------------------------- -void dpiSodaDoc__free(dpiSodaDoc *doc, dpiError *error) -{ - if (doc->handle) { - dpiOci__handleFree(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT); - doc->handle = NULL; - } - if (doc->db) { - dpiGen__setRefCount(doc->db, error, -1); - doc->db = NULL; - } - dpiUtils__freeMemory(doc); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc__getAttributeText() [INTERNAL] -// Get the value of the OCI attribute as a text string. -//----------------------------------------------------------------------------- -static int dpiSodaDoc__getAttributeText(dpiSodaDoc *doc, uint32_t attribute, - const char **value, uint32_t *valueLength, const char *fnName) -{ - dpiError error; - int status; - - // validate parameters - if (dpiSodaDoc__check(doc, fnName, &error) < 0) - return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(doc, value) - DPI_CHECK_PTR_NOT_NULL(doc, valueLength) - - // get attribute value - status = dpiOci__attrGet(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, - (void*) value, valueLength, attribute, "get value", &error); - return dpiGen__endPublicFn(doc, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc_addRef() [PUBLIC] -// Add a reference to the SODA document. -//----------------------------------------------------------------------------- -int dpiSodaDoc_addRef(dpiSodaDoc *doc) -{ - return dpiGen__addRef(doc, DPI_HTYPE_SODA_DOC, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc_getContent() [PUBLIC] -// Return the content of the SODA document. -//----------------------------------------------------------------------------- -int dpiSodaDoc_getContent(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength, const char **encoding) -{ - uint16_t charsetId; - dpiError error; - - // validate parameters - if (dpiSodaDoc__check(doc, __func__, &error) < 0) - return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(doc, value) - DPI_CHECK_PTR_NOT_NULL(doc, valueLength) - DPI_CHECK_PTR_NOT_NULL(doc, encoding) - - // get content - if (dpiOci__attrGet(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, - (void*) value, valueLength, DPI_OCI_ATTR_SODA_CONTENT, - "get content", &error) < 0) - return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); - - // if content is not in binary form, always use UTF-8 - if (!doc->binaryContent) - *encoding = DPI_CHARSET_NAME_UTF8; - - // otherwise, determine the encoding from OCI - else { - if (dpiOci__attrGet(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, - (void*) &charsetId, 0, DPI_OCI_ATTR_SODA_JSON_CHARSET_ID, - "get charset", &error) < 0) - return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); - switch (charsetId) { - case 0: - *encoding = NULL; - break; - case DPI_CHARSET_ID_UTF8: - *encoding = DPI_CHARSET_NAME_UTF8; - break; - case DPI_CHARSET_ID_UTF16BE: - *encoding = DPI_CHARSET_NAME_UTF16BE; - break; - case DPI_CHARSET_ID_UTF16LE: - *encoding = DPI_CHARSET_NAME_UTF16LE; - break; - default: - dpiError__set(&error, "check charset", - DPI_ERR_INVALID_CHARSET_ID, charsetId); - return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); - } - } - - return dpiGen__endPublicFn(doc, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc_getCreatedOn() [PUBLIC] -// Return the created timestamp of the SODA document. -//----------------------------------------------------------------------------- -int dpiSodaDoc_getCreatedOn(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength) -{ - return dpiSodaDoc__getAttributeText(doc, - DPI_OCI_ATTR_SODA_CREATE_TIMESTAMP, value, valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc_getKey() [PUBLIC] -// Return the key of the SODA document. -//----------------------------------------------------------------------------- -int dpiSodaDoc_getKey(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength) -{ - return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_KEY, value, - valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc_getLastModified() [PUBLIC] -// Return the last modified timestamp of the SODA document. -//----------------------------------------------------------------------------- -int dpiSodaDoc_getLastModified(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength) -{ - return dpiSodaDoc__getAttributeText(doc, - DPI_OCI_ATTR_SODA_LASTMOD_TIMESTAMP, value, valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc_getMediaType() [PUBLIC] -// Return the media type of the SODA document. -//----------------------------------------------------------------------------- -int dpiSodaDoc_getMediaType(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength) -{ - return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_MEDIA_TYPE, - value, valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc_getVersion() [PUBLIC] -// Return the version of the SODA document. -//----------------------------------------------------------------------------- -int dpiSodaDoc_getVersion(dpiSodaDoc *doc, const char **value, - uint32_t *valueLength) -{ - return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_VERSION, - value, valueLength, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDoc_release() [PUBLIC] -// Release a reference to the SODA document. -//----------------------------------------------------------------------------- -int dpiSodaDoc_release(dpiSodaDoc *doc) -{ - return dpiGen__release(doc, DPI_HTYPE_SODA_DOC, __func__); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSodaDocCursor.c b/vendor/github.com/godror/godror/odpi/src/dpiSodaDocCursor.c deleted file mode 100644 index 9bfd2bdbeea..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiSodaDocCursor.c +++ /dev/null @@ -1,144 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiSodaDocCursor.c -// Implementation of SODA document cursors. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiSodaDocCursor__allocate() [INTERNAL] -// Allocate and initialize a SODA document cursor structure. -//----------------------------------------------------------------------------- -int dpiSodaDocCursor__allocate(dpiSodaColl *coll, void *handle, - dpiSodaDocCursor **cursor, dpiError *error) -{ - dpiSodaDocCursor *tempCursor; - - if (dpiGen__allocate(DPI_HTYPE_SODA_DOC_CURSOR, coll->env, - (void**) &tempCursor, error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(coll, error, 1); - tempCursor->coll = coll; - tempCursor->handle = handle; - *cursor = tempCursor; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaDocCursor__check() [INTERNAL] -// Determine if the SODA document cursor is available to use. -//----------------------------------------------------------------------------- -static int dpiSodaDocCursor__check(dpiSodaDocCursor *cursor, - const char *fnName, dpiError *error) -{ - if (dpiGen__startPublicFn(cursor, DPI_HTYPE_SODA_DOC_CURSOR, fnName, - error) < 0) - return DPI_FAILURE; - if (!cursor->handle) - return dpiError__set(error, "check closed", - DPI_ERR_SODA_CURSOR_CLOSED); - if (!cursor->coll->db->conn->handle || cursor->coll->db->conn->closing) - return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSodaDocCursor__free() [INTERNAL] -// Free the memory for a SODA document cursor. Note that the reference to the -// collection must remain until after the handle is freed; otherwise, a -// segfault can take place. -//----------------------------------------------------------------------------- -void dpiSodaDocCursor__free(dpiSodaDocCursor *cursor, dpiError *error) -{ - if (cursor->handle) { - dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_DOC_CURSOR); - cursor->handle = NULL; - } - if (cursor->coll) { - dpiGen__setRefCount(cursor->coll, error, -1); - cursor->coll = NULL; - } - dpiUtils__freeMemory(cursor); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDocCursor_addRef() [PUBLIC] -// Add a reference to the SODA document cursor. -//----------------------------------------------------------------------------- -int dpiSodaDocCursor_addRef(dpiSodaDocCursor *cursor) -{ - return dpiGen__addRef(cursor, DPI_HTYPE_SODA_DOC_CURSOR, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDocCursor_close() [PUBLIC] -// Close the cursor. -//----------------------------------------------------------------------------- -int dpiSodaDocCursor_close(dpiSodaDocCursor *cursor) -{ - dpiError error; - - if (dpiSodaDocCursor__check(cursor, __func__, &error) < 0) - return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); - if (cursor->handle) { - dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_DOC_CURSOR); - cursor->handle = NULL; - } - return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDocCursor_getNext() [PUBLIC] -// Return the next document available from the cursor. -//----------------------------------------------------------------------------- -int dpiSodaDocCursor_getNext(dpiSodaDocCursor *cursor, uint32_t flags, - dpiSodaDoc **doc) -{ - dpiError error; - uint32_t mode; - void *handle; - - if (dpiSodaDocCursor__check(cursor, __func__, &error) < 0) - return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(cursor, doc) - mode = DPI_OCI_DEFAULT; - if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) - mode |= DPI_OCI_SODA_ATOMIC_COMMIT; - if (dpiOci__sodaDocGetNext(cursor, &handle, mode, &error) < 0) - return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); - *doc = NULL; - if (handle) { - if (dpiSodaDoc__allocate(cursor->coll->db, handle, doc, &error) < 0) { - dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_DOCUMENT); - return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); - } - (*doc)->binaryContent = cursor->coll->binaryContent; - } - return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSodaDocCursor_release() [PUBLIC] -// Release a reference to the SODA document cursor. -//----------------------------------------------------------------------------- -int dpiSodaDocCursor_release(dpiSodaDocCursor *cursor) -{ - return dpiGen__release(cursor, DPI_HTYPE_SODA_DOC_CURSOR, __func__); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiStmt.c b/vendor/github.com/godror/godror/odpi/src/dpiStmt.c deleted file mode 100644 index cd3520b93b0..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiStmt.c +++ /dev/null @@ -1,1898 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiStmt.c -// Implementation of statements (cursors). -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -// forward declarations of internal functions only used in this file -static int dpiStmt__getQueryInfo(dpiStmt *stmt, uint32_t pos, - dpiQueryInfo *info, dpiError *error); -static int dpiStmt__getQueryInfoFromParam(dpiStmt *stmt, void *param, - dpiQueryInfo *info, dpiError *error); -static int dpiStmt__postFetch(dpiStmt *stmt, dpiError *error); -static int dpiStmt__beforeFetch(dpiStmt *stmt, dpiError *error); -static int dpiStmt__reExecute(dpiStmt *stmt, uint32_t numIters, - uint32_t mode, dpiError *error); - - -//----------------------------------------------------------------------------- -// dpiStmt__allocate() [INTERNAL] -// Create a new statement object and return it. In case of error NULL is -// returned. -//----------------------------------------------------------------------------- -int dpiStmt__allocate(dpiConn *conn, int scrollable, dpiStmt **stmt, - dpiError *error) -{ - dpiStmt *tempStmt; - - *stmt = NULL; - if (dpiGen__allocate(DPI_HTYPE_STMT, conn->env, (void**) &tempStmt, - error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(conn, error, 1); - tempStmt->conn = conn; - tempStmt->fetchArraySize = DPI_DEFAULT_FETCH_ARRAY_SIZE; - tempStmt->scrollable = scrollable; - *stmt = tempStmt; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__bind() [INTERNAL] -// Bind the variable to the statement using either a position or a name. A -// reference to the variable will be retained. -//----------------------------------------------------------------------------- -static int dpiStmt__bind(dpiStmt *stmt, dpiVar *var, int addReference, - uint32_t pos, const char *name, uint32_t nameLength, dpiError *error) -{ - dpiBindVar *bindVars, *entry = NULL; - int found, dynamicBind, status; - void *bindHandle = NULL; - uint32_t i; - - // a zero length name is not supported - if (pos == 0 && nameLength == 0) - return dpiError__set(error, "bind zero length name", - DPI_ERR_NOT_SUPPORTED); - - // prevent attempts to bind a statement to itself - if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_STMT) { - for (i = 0; i < var->buffer.maxArraySize; i++) { - if (var->buffer.externalData[i].value.asStmt == stmt) { - return dpiError__set(error, "bind to self", - DPI_ERR_NOT_SUPPORTED); - } - } - } - - // check to see if the bind position or name has already been bound - found = 0; - for (i = 0; i < stmt->numBindVars; i++) { - entry = &stmt->bindVars[i]; - if (entry->pos == pos && entry->nameLength == nameLength) { - if (nameLength > 0 && strncmp(entry->name, name, nameLength) != 0) - continue; - found = 1; - break; - } - } - - // if already found, use that entry - if (found) { - - // if already bound, no need to bind a second time - if (entry->var == var) - return DPI_SUCCESS; - - // otherwise, release previously bound variable, if applicable - else if (entry->var) { - dpiGen__setRefCount(entry->var, error, -1); - entry->var = NULL; - } - - // if not found, add to the list of bind variables - } else { - - // allocate memory for additional bind variables, if needed - if (stmt->numBindVars == stmt->allocatedBindVars) { - if (dpiUtils__allocateMemory(stmt->allocatedBindVars + 8, - sizeof(dpiBindVar), 1, "allocate bind vars", - (void**) &bindVars, error) < 0) - return DPI_FAILURE; - if (stmt->bindVars) { - for (i = 0; i < stmt->numBindVars; i++) - bindVars[i] = stmt->bindVars[i]; - dpiUtils__freeMemory(stmt->bindVars); - } - stmt->bindVars = bindVars; - stmt->allocatedBindVars += 8; - } - - // add to the list of bind variables - entry = &stmt->bindVars[stmt->numBindVars]; - entry->var = NULL; - entry->pos = pos; - if (name) { - if (dpiUtils__allocateMemory(1, nameLength, 0, - "allocate memory for name", (void**) &entry->name, - error) < 0) - return DPI_FAILURE; - entry->nameLength = nameLength; - memcpy( (void*) entry->name, name, nameLength); - } - stmt->numBindVars++; - - } - - // for PL/SQL where the maxSize is greater than 32K, adjust the variable - // so that LOBs are used internally - if (var->isDynamic && (stmt->statementType == DPI_STMT_TYPE_BEGIN || - stmt->statementType == DPI_STMT_TYPE_DECLARE || - stmt->statementType == DPI_STMT_TYPE_CALL)) { - if (dpiVar__convertToLob(var, error) < 0) - return DPI_FAILURE; - } - - // perform actual bind - if (addReference) - dpiGen__setRefCount(var, error, 1); - entry->var = var; - dynamicBind = stmt->isReturning || var->isDynamic; - if (pos > 0) { - if (stmt->env->versionInfo->versionNum < 12) - status = dpiOci__bindByPos(stmt, &bindHandle, pos, dynamicBind, - var, error); - else status = dpiOci__bindByPos2(stmt, &bindHandle, pos, dynamicBind, - var, error); - } else { - if (stmt->env->versionInfo->versionNum < 12) - status = dpiOci__bindByName(stmt, &bindHandle, name, - (int32_t) nameLength, dynamicBind, var, error); - else status = dpiOci__bindByName2(stmt, &bindHandle, name, - (int32_t) nameLength, dynamicBind, var, error); - } - - // attempt to improve message "ORA-01036: illegal variable name/number" - if (status < 0) { - if (error->buffer->code == 1036) { - if (stmt->statementType == DPI_STMT_TYPE_CREATE || - stmt->statementType == DPI_STMT_TYPE_DROP || - stmt->statementType == DPI_STMT_TYPE_ALTER) - dpiError__set(error, error->buffer->action, - DPI_ERR_NO_BIND_VARS_IN_DDL); - } - return DPI_FAILURE; - } - - // set the charset form if applicable - if (var->type->charsetForm != DPI_SQLCS_IMPLICIT) { - if (dpiOci__attrSet(bindHandle, DPI_OCI_HTYPE_BIND, - (void*) &var->type->charsetForm, 0, DPI_OCI_ATTR_CHARSET_FORM, - "set charset form", error) < 0) - return DPI_FAILURE; - } - - // set the max data size, if applicable - if (var->type->sizeInBytes == 0 && !var->isDynamic) { - if (dpiOci__attrSet(bindHandle, DPI_OCI_HTYPE_BIND, - (void*) &var->sizeInBytes, 0, DPI_OCI_ATTR_MAXDATA_SIZE, - "set max data size", error) < 0) - return DPI_FAILURE; - } - - // bind object, if applicable - if (var->buffer.objectIndicator && - dpiOci__bindObject(var, bindHandle, error) < 0) - return DPI_FAILURE; - - // setup dynamic bind, if applicable - if (dynamicBind && dpiOci__bindDynamic(var, bindHandle, error) < 0) - return DPI_FAILURE; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__check() [INTERNAL] -// Determine if the statement is open and available for use. -//----------------------------------------------------------------------------- -static int dpiStmt__check(dpiStmt *stmt, const char *fnName, dpiError *error) -{ - if (dpiGen__startPublicFn(stmt, DPI_HTYPE_STMT, fnName, error) < 0) - return DPI_FAILURE; - if (!stmt->handle || (stmt->parentStmt && !stmt->parentStmt->handle)) - return dpiError__set(error, "check closed", DPI_ERR_STMT_CLOSED); - if (dpiConn__checkConnected(stmt->conn, error) < 0) - return DPI_FAILURE; - if (stmt->statementType == 0 && dpiStmt__init(stmt, error) < 0) - return DPI_FAILURE; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__clearBatchErrors() [INTERNAL] -// Clear the batch errors associated with the statement. -//----------------------------------------------------------------------------- -static void dpiStmt__clearBatchErrors(dpiStmt *stmt) -{ - if (stmt->batchErrors) { - dpiUtils__freeMemory(stmt->batchErrors); - stmt->batchErrors = NULL; - } - stmt->numBatchErrors = 0; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__clearBindVars() [INTERNAL] -// Clear the bind variables associated with the statement. -//----------------------------------------------------------------------------- -static void dpiStmt__clearBindVars(dpiStmt *stmt, dpiError *error) -{ - uint32_t i; - - if (stmt->bindVars) { - for (i = 0; i < stmt->numBindVars; i++) { - dpiGen__setRefCount(stmt->bindVars[i].var, error, -1); - if (stmt->bindVars[i].name) - dpiUtils__freeMemory( (void*) stmt->bindVars[i].name); - } - dpiUtils__freeMemory(stmt->bindVars); - stmt->bindVars = NULL; - } - stmt->numBindVars = 0; - stmt->allocatedBindVars = 0; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__clearQueryVars() [INTERNAL] -// Clear the query variables associated with the statement. -//----------------------------------------------------------------------------- -static void dpiStmt__clearQueryVars(dpiStmt *stmt, dpiError *error) -{ - uint32_t i; - - if (stmt->queryVars) { - for (i = 0; i < stmt->numQueryVars; i++) { - if (stmt->queryVars[i]) { - dpiGen__setRefCount(stmt->queryVars[i], error, -1); - stmt->queryVars[i] = NULL; - } - if (stmt->queryInfo[i].typeInfo.objectType) { - dpiGen__setRefCount(stmt->queryInfo[i].typeInfo.objectType, - error, -1); - stmt->queryInfo[i].typeInfo.objectType = NULL; - } - } - dpiUtils__freeMemory(stmt->queryVars); - stmt->queryVars = NULL; - } - if (stmt->queryInfo) { - dpiUtils__freeMemory(stmt->queryInfo); - stmt->queryInfo = NULL; - } - stmt->numQueryVars = 0; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__close() [INTERNAL] -// Internal method used for closing the statement. If the statement is marked -// as needing to be dropped from the statement cache that is done as well. This -// is called from dpiStmt_close() where errors are expected to be propagated -// and from dpiStmt__free() where errors are ignored. -//----------------------------------------------------------------------------- -int dpiStmt__close(dpiStmt *stmt, const char *tag, uint32_t tagLength, - int propagateErrors, dpiError *error) -{ - int closing, status = DPI_SUCCESS; - - // determine whether statement is already being closed and if not, mark - // statement as being closed; this MUST be done while holding the lock (if - // in threaded mode) to avoid race conditions! - if (stmt->env->threaded) - dpiMutex__acquire(stmt->env->mutex); - closing = stmt->closing; - stmt->closing = 1; - if (stmt->env->threaded) - dpiMutex__release(stmt->env->mutex); - - // if statement is already being closed, nothing needs to be done - if (closing) - return DPI_SUCCESS; - - // perform actual work of closing statement - dpiStmt__clearBatchErrors(stmt); - dpiStmt__clearBindVars(stmt, error); - dpiStmt__clearQueryVars(stmt, error); - if (stmt->lastRowid) - dpiGen__setRefCount(stmt->lastRowid, error, -1); - if (stmt->handle) { - if (stmt->parentStmt) { - dpiGen__setRefCount(stmt->parentStmt, error, -1); - stmt->parentStmt = NULL; - } else if (!stmt->conn->deadSession && stmt->conn->handle) { - if (stmt->isOwned) - dpiOci__handleFree(stmt->handle, DPI_OCI_HTYPE_STMT); - else status = dpiOci__stmtRelease(stmt, tag, tagLength, - propagateErrors, error); - } - if (!stmt->conn->closing && !stmt->parentStmt) - dpiHandleList__removeHandle(stmt->conn->openStmts, - stmt->openSlotNum); - stmt->handle = NULL; - } - - // if actual close fails, reset closing flag; again, this must be done - // while holding the lock (if in threaded mode) in order to avoid race - // conditions! - if (status < 0) { - if (stmt->env->threaded) - dpiMutex__acquire(stmt->env->mutex); - stmt->closing = 0; - if (stmt->env->threaded) - dpiMutex__release(stmt->env->mutex); - } - - return status; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__createBindVar() [INTERNAL] -// Create a bind variable given a value to bind. -//----------------------------------------------------------------------------- -static int dpiStmt__createBindVar(dpiStmt *stmt, - dpiNativeTypeNum nativeTypeNum, dpiData *data, dpiVar **var, - uint32_t pos, const char *name, uint32_t nameLength, dpiError *error) -{ - dpiOracleTypeNum oracleTypeNum; - dpiObjectType *objType; - dpiData *varData; - dpiVar *tempVar; - uint32_t size; - - // determine the type (and size) of bind variable to create - size = 0; - objType = NULL; - switch (nativeTypeNum) { - case DPI_NATIVE_TYPE_INT64: - case DPI_NATIVE_TYPE_UINT64: - case DPI_NATIVE_TYPE_FLOAT: - case DPI_NATIVE_TYPE_DOUBLE: - oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; - break; - case DPI_NATIVE_TYPE_BYTES: - oracleTypeNum = DPI_ORACLE_TYPE_VARCHAR; - size = data->value.asBytes.length; - break; - case DPI_NATIVE_TYPE_TIMESTAMP: - oracleTypeNum = DPI_ORACLE_TYPE_TIMESTAMP; - break; - case DPI_NATIVE_TYPE_INTERVAL_DS: - oracleTypeNum = DPI_ORACLE_TYPE_INTERVAL_DS; - break; - case DPI_NATIVE_TYPE_INTERVAL_YM: - oracleTypeNum = DPI_ORACLE_TYPE_INTERVAL_YM; - break; - case DPI_NATIVE_TYPE_OBJECT: - oracleTypeNum = DPI_ORACLE_TYPE_OBJECT; - if (data->value.asObject) - objType = data->value.asObject->type; - break; - case DPI_NATIVE_TYPE_ROWID: - oracleTypeNum = DPI_ORACLE_TYPE_ROWID; - break; - case DPI_NATIVE_TYPE_BOOLEAN: - oracleTypeNum = DPI_ORACLE_TYPE_BOOLEAN; - break; - default: - return dpiError__set(error, "create bind var", - DPI_ERR_UNHANDLED_CONVERSION, 0, nativeTypeNum); - } - - // create the variable and set its value - if (dpiVar__allocate(stmt->conn, oracleTypeNum, nativeTypeNum, 1, size, 1, - 0, objType, &tempVar, &varData, error) < 0) - return DPI_FAILURE; - - // copy value from source to target data - if (dpiVar__copyData(tempVar, 0, data, error) < 0) - return DPI_FAILURE; - - // bind variable to statement - if (dpiStmt__bind(stmt, tempVar, 0, pos, name, nameLength, error) < 0) { - dpiVar__free(tempVar, error); - return DPI_FAILURE; - } - - *var = tempVar; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__createQueryVars() [INTERNAL] -// Create space for the number of query variables required to support the -// query. -//----------------------------------------------------------------------------- -static int dpiStmt__createQueryVars(dpiStmt *stmt, dpiError *error) -{ - uint32_t numQueryVars, i; - - // determine number of query variables - if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, - (void*) &numQueryVars, 0, DPI_OCI_ATTR_PARAM_COUNT, - "get parameter count", error) < 0) - return DPI_FAILURE; - - // clear the previous query vars if the number has changed - if (stmt->numQueryVars > 0 && stmt->numQueryVars != numQueryVars) - dpiStmt__clearQueryVars(stmt, error); - - // allocate space for the query vars, if needed - if (numQueryVars != stmt->numQueryVars) { - if (dpiUtils__allocateMemory(numQueryVars, sizeof(dpiVar*), 1, - "allocate query vars", (void**) &stmt->queryVars, error) < 0) - return DPI_FAILURE; - if (dpiUtils__allocateMemory(numQueryVars, sizeof(dpiQueryInfo), 1, - "allocate query info", (void**) &stmt->queryInfo, error) < 0) { - dpiStmt__clearQueryVars(stmt, error); - return DPI_FAILURE; - } - stmt->numQueryVars = numQueryVars; - for (i = 0; i < numQueryVars; i++) { - if (dpiStmt__getQueryInfo(stmt, i + 1, &stmt->queryInfo[i], - error) < 0) { - dpiStmt__clearQueryVars(stmt, error); - return DPI_FAILURE; - } - } - } - - // indicate start of fetch - stmt->bufferRowIndex = stmt->fetchArraySize; - stmt->hasRowsToFetch = 1; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__define() [INTERNAL] -// Define the variable that will accept output from the statement in the -// specified column. At this point the statement, position and variable are all -// assumed to be valid. -//----------------------------------------------------------------------------- -static int dpiStmt__define(dpiStmt *stmt, uint32_t pos, dpiVar *var, - dpiError *error) -{ - void *defineHandle = NULL; - dpiQueryInfo *queryInfo; - int tempBool; - - // no need to perform define if variable is unchanged - if (stmt->queryVars[pos - 1] == var) - return DPI_SUCCESS; - - // for objects, the type specified must match the type in the database - queryInfo = &stmt->queryInfo[pos - 1]; - if (var->objectType && queryInfo->typeInfo.objectType && - var->objectType->tdo != queryInfo->typeInfo.objectType->tdo) - return dpiError__set(error, "check type", DPI_ERR_WRONG_TYPE, - var->objectType->schemaLength, var->objectType->schema, - var->objectType->nameLength, var->objectType->name, - queryInfo->typeInfo.objectType->schemaLength, - queryInfo->typeInfo.objectType->schema, - queryInfo->typeInfo.objectType->nameLength, - queryInfo->typeInfo.objectType->name); - - // perform the define - if (stmt->env->versionInfo->versionNum < 12) { - if (dpiOci__defineByPos(stmt, &defineHandle, pos, var, error) < 0) - return DPI_FAILURE; - } else { - if (dpiOci__defineByPos2(stmt, &defineHandle, pos, var, error) < 0) - return DPI_FAILURE; - } - - // set the charset form if applicable - if (var->type->charsetForm != DPI_SQLCS_IMPLICIT) { - if (dpiOci__attrSet(defineHandle, DPI_OCI_HTYPE_DEFINE, - (void*) &var->type->charsetForm, 0, DPI_OCI_ATTR_CHARSET_FORM, - "set charset form", error) < 0) - return DPI_FAILURE; - } - - // specify that the LOB length should be prefetched - if (var->nativeTypeNum == DPI_NATIVE_TYPE_LOB) { - tempBool = 1; - if (dpiOci__attrSet(defineHandle, DPI_OCI_HTYPE_DEFINE, - (void*) &tempBool, 0, DPI_OCI_ATTR_LOBPREFETCH_LENGTH, - "set lob prefetch length", error) < 0) - return DPI_FAILURE; - } - - // define objects, if applicable - if (var->buffer.objectIndicator && dpiOci__defineObject(var, defineHandle, - error) < 0) - return DPI_FAILURE; - - // register callback for dynamic defines - if (var->isDynamic && dpiOci__defineDynamic(var, defineHandle, error) < 0) - return DPI_FAILURE; - - // remove previous variable and retain new one - if (stmt->queryVars[pos - 1]) - dpiGen__setRefCount(stmt->queryVars[pos - 1], error, -1); - dpiGen__setRefCount(var, error, 1); - stmt->queryVars[pos - 1] = var; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__execute() [INTERNAL] -// Internal execution of statement. -//----------------------------------------------------------------------------- -static int dpiStmt__execute(dpiStmt *stmt, uint32_t numIters, - uint32_t mode, int reExecute, dpiError *error) -{ - uint32_t prefetchSize, i, j; - dpiData *data; - dpiVar *var; - - // for all bound variables, transfer data from dpiData structure to Oracle - // buffer structures - for (i = 0; i < stmt->numBindVars; i++) { - var = stmt->bindVars[i].var; - if (var->isArray && numIters > 1) - return dpiError__set(error, "bind array var", - DPI_ERR_ARRAY_VAR_NOT_SUPPORTED); - for (j = 0; j < var->buffer.maxArraySize; j++) { - data = &var->buffer.externalData[j]; - if (dpiVar__setValue(var, &var->buffer, j, data, error) < 0) - return DPI_FAILURE; - if (var->dynBindBuffers) - var->dynBindBuffers[j].actualArraySize = 0; - } - if (stmt->isReturning || var->isDynamic) - var->error = error; - } - - // for queries, set the OCI prefetch to a fixed value; this prevents an - // additional round trip for single row fetches while avoiding the overhead - // of copying from the OCI prefetch buffer to our own buffers for larger - // fetches - if (stmt->statementType == DPI_STMT_TYPE_SELECT) { - prefetchSize = DPI_PREFETCH_ROWS_DEFAULT; - if (dpiOci__attrSet(stmt->handle, DPI_OCI_HTYPE_STMT, &prefetchSize, - sizeof(prefetchSize), DPI_OCI_ATTR_PREFETCH_ROWS, - "set prefetch rows", error) < 0) - return DPI_FAILURE; - } - - // clear batch errors from any previous execution - dpiStmt__clearBatchErrors(stmt); - - // adjust mode for scrollable cursors - if (stmt->scrollable) - mode |= DPI_OCI_STMT_SCROLLABLE_READONLY; - - // perform execution - // re-execute statement for ORA-01007: variable not in select list - // drop statement from cache for all errors (except those which are due to - // invalid data which may be fixed in subsequent execution) - if (dpiOci__stmtExecute(stmt, numIters, mode, error) < 0) { - dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, - &error->buffer->offset, 0, DPI_OCI_ATTR_PARSE_ERROR_OFFSET, - "set parse offset", error); - switch (error->buffer->code) { - case 1007: - if (reExecute) - return dpiStmt__reExecute(stmt, numIters, mode, error); - stmt->deleteFromCache = 1; - break; - case 1: - case 1400: - case 1438: - case 1461: - case 2290: - case 2291: - case 2292: - case 21525: - break; - default: - stmt->deleteFromCache = 1; - } - return DPI_FAILURE; - } - - // for all bound variables, transfer data from Oracle buffer structures to - // dpiData structures; OCI doesn't provide a way of knowing if a variable - // is an out variable so do this for all of them when this is a possibility - if (stmt->isReturning || stmt->statementType == DPI_STMT_TYPE_BEGIN || - stmt->statementType == DPI_STMT_TYPE_DECLARE || - stmt->statementType == DPI_STMT_TYPE_CALL) { - for (i = 0; i < stmt->numBindVars; i++) { - var = stmt->bindVars[i].var; - for (j = 0; j < var->buffer.maxArraySize; j++) { - if (dpiVar__getValue(var, &var->buffer, j, 0, error) < 0) - return DPI_FAILURE; - } - var->error = NULL; - } - } - - // create query variables (if applicable) and reset row count to zero - if (stmt->statementType == DPI_STMT_TYPE_SELECT) { - stmt->rowCount = 0; - if (!(mode & DPI_MODE_EXEC_PARSE_ONLY) && - dpiStmt__createQueryVars(stmt, error) < 0) - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__fetch() [INTERNAL] -// Performs the actual fetch from Oracle. -//----------------------------------------------------------------------------- -static int dpiStmt__fetch(dpiStmt *stmt, dpiError *error) -{ - // perform any pre-fetch activities required - if (dpiStmt__beforeFetch(stmt, error) < 0) - return DPI_FAILURE; - - // perform fetch - if (dpiOci__stmtFetch2(stmt, stmt->fetchArraySize, DPI_MODE_FETCH_NEXT, 0, - error) < 0) - return DPI_FAILURE; - - // determine the number of rows fetched into buffers - if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, - &stmt->bufferRowCount, 0, DPI_OCI_ATTR_ROWS_FETCHED, - "get rows fetched", error) < 0) - return DPI_FAILURE; - - // set buffer row info - stmt->bufferMinRow = stmt->rowCount + 1; - stmt->bufferRowIndex = 0; - - // perform post-fetch activities required - if (dpiStmt__postFetch(stmt, error) < 0) - return DPI_FAILURE; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__free() [INTERNAL] -// Free the memory associated with the statement. -//----------------------------------------------------------------------------- -void dpiStmt__free(dpiStmt *stmt, dpiError *error) -{ - dpiStmt__close(stmt, NULL, 0, 0, error); - if (stmt->parentStmt) { - dpiGen__setRefCount(stmt->parentStmt, error, -1); - stmt->parentStmt = NULL; - } - if (stmt->conn) { - dpiGen__setRefCount(stmt->conn, error, -1); - stmt->conn = NULL; - } - dpiUtils__freeMemory(stmt); -} - - -//----------------------------------------------------------------------------- -// dpiStmt__getBatchErrors() [INTERNAL] -// Get batch errors after statement executed with batch errors enabled. -//----------------------------------------------------------------------------- -static int dpiStmt__getBatchErrors(dpiStmt *stmt, dpiError *error) -{ - void *batchErrorHandle, *localErrorHandle; - dpiError localError; - int overallStatus; - int32_t rowOffset; - uint32_t i; - - // determine the number of batch errors that were found - if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, - &stmt->numBatchErrors, 0, DPI_OCI_ATTR_NUM_DML_ERRORS, - "get batch error count", error) < 0) - return DPI_FAILURE; - - // allocate memory for the batch errors - if (dpiUtils__allocateMemory(stmt->numBatchErrors, sizeof(dpiErrorBuffer), - 1, "allocate errors", (void**) &stmt->batchErrors, error) < 0) { - stmt->numBatchErrors = 0; - return DPI_FAILURE; - } - - // allocate error handle used for OCIParamGet() - if (dpiOci__handleAlloc(stmt->env->handle, &localErrorHandle, - DPI_OCI_HTYPE_ERROR, "allocate parameter error handle", - error) < 0) { - dpiStmt__clearBatchErrors(stmt); - return DPI_FAILURE; - } - - // allocate error handle used for batch errors - if (dpiOci__handleAlloc(stmt->env->handle, &batchErrorHandle, - DPI_OCI_HTYPE_ERROR, "allocate batch error handle", error) < 0) { - dpiStmt__clearBatchErrors(stmt); - dpiOci__handleFree(localErrorHandle, DPI_OCI_HTYPE_ERROR); - return DPI_FAILURE; - } - - // process each error - overallStatus = DPI_SUCCESS; - localError.buffer = error->buffer; - localError.env = error->env; - for (i = 0; i < stmt->numBatchErrors; i++) { - - // get error handle for iteration - if (dpiOci__paramGet(error->handle, DPI_OCI_HTYPE_ERROR, - &batchErrorHandle, i, "get batch error", error) < 0) { - overallStatus = dpiError__set(error, "get batch error", - DPI_ERR_INVALID_INDEX, i); - break; - } - - // determine row offset - localError.handle = localErrorHandle; - if (dpiOci__attrGet(batchErrorHandle, DPI_OCI_HTYPE_ERROR, &rowOffset, - 0, DPI_OCI_ATTR_DML_ROW_OFFSET, "get row offset", - &localError) < 0) { - overallStatus = dpiError__set(error, "get row offset", - DPI_ERR_CANNOT_GET_ROW_OFFSET); - break; - } - - // get error message - localError.buffer = &stmt->batchErrors[i]; - localError.handle = batchErrorHandle; - dpiError__setFromOCI(&localError, DPI_OCI_ERROR, stmt->conn, - "get batch error"); - if (error->buffer->errorNum) { - overallStatus = DPI_FAILURE; - break; - } - localError.buffer->fnName = error->buffer->fnName; - localError.buffer->offset = (uint16_t) rowOffset; - - } - - // cleanup - dpiOci__handleFree(localErrorHandle, DPI_OCI_HTYPE_ERROR); - dpiOci__handleFree(batchErrorHandle, DPI_OCI_HTYPE_ERROR); - if (overallStatus < 0) - dpiStmt__clearBatchErrors(stmt); - return overallStatus; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__getRowCount() [INTERNAL] -// Return the number of rows affected by the last DML executed (for insert, -// update, delete and merge) or the number of rows fetched (for queries). In -// all other cases, 0 is returned. -//----------------------------------------------------------------------------- -static int dpiStmt__getRowCount(dpiStmt *stmt, uint64_t *count, - dpiError *error) -{ - uint32_t rowCount32; - - if (stmt->statementType == DPI_STMT_TYPE_SELECT) - *count = stmt->rowCount; - else if (stmt->statementType != DPI_STMT_TYPE_INSERT && - stmt->statementType != DPI_STMT_TYPE_UPDATE && - stmt->statementType != DPI_STMT_TYPE_DELETE && - stmt->statementType != DPI_STMT_TYPE_MERGE && - stmt->statementType != DPI_STMT_TYPE_CALL && - stmt->statementType != DPI_STMT_TYPE_BEGIN && - stmt->statementType != DPI_STMT_TYPE_DECLARE) { - *count = 0; - } else if (stmt->env->versionInfo->versionNum < 12) { - if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &rowCount32, 0, - DPI_OCI_ATTR_ROW_COUNT, "get row count", error) < 0) - return DPI_FAILURE; - *count = rowCount32; - } else { - if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, count, 0, - DPI_OCI_ATTR_UB8_ROW_COUNT, "get row count", error) < 0) - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__getQueryInfo() [INTERNAL] -// Get query information for the position in question. -//----------------------------------------------------------------------------- -static int dpiStmt__getQueryInfo(dpiStmt *stmt, uint32_t pos, - dpiQueryInfo *info, dpiError *error) -{ - void *param; - int status; - - // acquire parameter descriptor - if (dpiOci__paramGet(stmt->handle, DPI_OCI_HTYPE_STMT, ¶m, pos, - "get parameter", error) < 0) - return DPI_FAILURE; - - // acquire information from the parameter descriptor - status = dpiStmt__getQueryInfoFromParam(stmt, param, info, error); - dpiOci__descriptorFree(param, DPI_OCI_DTYPE_PARAM); - return status; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__getQueryInfoFromParam() [INTERNAL] -// Get query information from the parameter. -//----------------------------------------------------------------------------- -static int dpiStmt__getQueryInfoFromParam(dpiStmt *stmt, void *param, - dpiQueryInfo *info, dpiError *error) -{ - uint8_t ociNullOk; - - // aquire name of item - if (dpiOci__attrGet(param, DPI_OCI_HTYPE_DESCRIBE, (void*) &info->name, - &info->nameLength, DPI_OCI_ATTR_NAME, "get name", error) < 0) - return DPI_FAILURE; - - // acquire type information - if (dpiOracleType__populateTypeInfo(stmt->conn, param, - DPI_OCI_HTYPE_DESCRIBE, &info->typeInfo, error) < 0) - return DPI_FAILURE; - - // acquire if column is permitted to be null - if (dpiOci__attrGet(param, DPI_OCI_HTYPE_DESCRIBE, (void*) &ociNullOk, 0, - DPI_OCI_ATTR_IS_NULL, "get null ok", error) < 0) - return DPI_FAILURE; - info->nullOk = ociNullOk; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__init() [INTERNAL] -// Initialize the statement for use. This is needed when preparing a -// statement for use and when returning a REF cursor. -//----------------------------------------------------------------------------- -int dpiStmt__init(dpiStmt *stmt, dpiError *error) -{ - // get statement type - if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, - (void*) &stmt->statementType, 0, DPI_OCI_ATTR_STMT_TYPE, - "get statement type", error) < 0) - return DPI_FAILURE; - - // for queries, mark statement as having rows to fetch - if (stmt->statementType == DPI_STMT_TYPE_SELECT) - stmt->hasRowsToFetch = 1; - - // otherwise, check if this is a RETURNING statement - else if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, - (void*) &stmt->isReturning, 0, DPI_OCI_ATTR_STMT_IS_RETURNING, - "get is returning", error) < 0) - return DPI_FAILURE; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__postFetch() [INTERNAL] -// Performs the transformations required to convert Oracle data values into -// C data values. -//----------------------------------------------------------------------------- -static int dpiStmt__postFetch(dpiStmt *stmt, dpiError *error) -{ - uint32_t i, j; - dpiVar *var; - - for (i = 0; i < stmt->numQueryVars; i++) { - var = stmt->queryVars[i]; - for (j = 0; j < stmt->bufferRowCount; j++) { - if (dpiVar__getValue(var, &var->buffer, j, 1, error) < 0) - return DPI_FAILURE; - if (var->type->requiresPreFetch) - var->requiresPreFetch = 1; - } - var->error = NULL; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__beforeFetch() [INTERNAL] -// Performs work that needs to be done prior to fetch for each variable. In -// addition, variables are created if they do not already exist. A check is -// also made to ensure that the variable has enough space to support a fetch -// of the requested size. -//----------------------------------------------------------------------------- -static int dpiStmt__beforeFetch(dpiStmt *stmt, dpiError *error) -{ - dpiQueryInfo *queryInfo; - dpiData *data; - dpiVar *var; - uint32_t i; - - if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, error) < 0) - return DPI_FAILURE; - for (i = 0; i < stmt->numQueryVars; i++) { - var = stmt->queryVars[i]; - if (!var) { - queryInfo = &stmt->queryInfo[i]; - if (dpiVar__allocate(stmt->conn, queryInfo->typeInfo.oracleTypeNum, - queryInfo->typeInfo.defaultNativeTypeNum, - stmt->fetchArraySize, - queryInfo->typeInfo.clientSizeInBytes, 1, 0, - queryInfo->typeInfo.objectType, &var, &data, error) < 0) - return DPI_FAILURE; - if (dpiStmt__define(stmt, i + 1, var, error) < 0) - return DPI_FAILURE; - dpiGen__setRefCount(var, error, -1); - } - var->error = error; - if (stmt->fetchArraySize > var->buffer.maxArraySize) - return dpiError__set(error, "check array size", - DPI_ERR_ARRAY_SIZE_TOO_SMALL, var->buffer.maxArraySize); - if (var->requiresPreFetch && dpiVar__extendedPreFetch(var, - &var->buffer, error) < 0) - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiStmt__prepare() [INTERNAL] -// Prepare a statement for execution. -//----------------------------------------------------------------------------- -int dpiStmt__prepare(dpiStmt *stmt, const char *sql, uint32_t sqlLength, - const char *tag, uint32_t tagLength, dpiError *error) -{ - if (sql && dpiDebugLevel & DPI_DEBUG_LEVEL_SQL) - dpiDebug__print("SQL %.*s\n", sqlLength, sql); - if (dpiOci__stmtPrepare2(stmt, sql, sqlLength, tag, tagLength, error) < 0) - return DPI_FAILURE; - if (dpiHandleList__addHandle(stmt->conn->openStmts, stmt, - &stmt->openSlotNum, error) < 0) { - dpiOci__stmtRelease(stmt, NULL, 0, 0, error); - stmt->handle = NULL; - return DPI_FAILURE; - } - - return dpiStmt__init(stmt, error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt__reExecute() [INTERNAL] -// Re-execute the statement after receiving the error ORA-01007: variable not -// in select list. This takes place when one of the columns in a query is -// dropped, but the original metadata is still being used because the query -// statement was found in the statement cache. -//----------------------------------------------------------------------------- -static int dpiStmt__reExecute(dpiStmt *stmt, uint32_t numIters, - uint32_t mode, dpiError *error) -{ - void *origHandle, *newHandle; - uint32_t sqlLength, i; - dpiError localError; - dpiBindVar *bindVar; - dpiVar *var; - int status; - char *sql; - - // acquire the statement that was previously prepared; if this cannot be - // determined, let the original error propagate - localError.buffer = error->buffer; - localError.env = error->env; - localError.handle = error->handle; - if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) &sql, - &sqlLength, DPI_OCI_ATTR_STATEMENT, "get statement", - &localError) < 0) - return DPI_FAILURE; - - // prepare statement a second time before releasing the original statement; - // release the original statement and delete it from the statement cache - // so that it does not return with the invalid metadata; again, if this - // cannot be done, let the original error propagate - origHandle = stmt->handle; - status = dpiOci__stmtPrepare2(stmt, sql, sqlLength, NULL, 0, &localError); - newHandle = stmt->handle; - stmt->handle = origHandle; - stmt->deleteFromCache = 1; - if (dpiOci__stmtRelease(stmt, NULL, 0, 1, &localError) < 0 || status < 0) - return DPI_FAILURE; - stmt->handle = newHandle; - dpiStmt__clearBatchErrors(stmt); - dpiStmt__clearQueryVars(stmt, error); - - // perform binds - for (i = 0; i < stmt->numBindVars; i++) { - bindVar = &stmt->bindVars[i]; - if (!bindVar->var) - continue; - var = bindVar->var; - bindVar->var = NULL; - if (dpiStmt__bind(stmt, var, 0, bindVar->pos, bindVar->name, - bindVar->nameLength, error) < 0) { - dpiGen__setRefCount(var, error, -1); - return DPI_FAILURE; - } - } - - // now re-execute the statement - return dpiStmt__execute(stmt, numIters, mode, 0, error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_addRef() [PUBLIC] -// Add a reference to the statement. -//----------------------------------------------------------------------------- -int dpiStmt_addRef(dpiStmt *stmt) -{ - return dpiGen__addRef(stmt, DPI_HTYPE_STMT, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_bindByName() [PUBLIC] -// Bind the variable by name. -//----------------------------------------------------------------------------- -int dpiStmt_bindByName(dpiStmt *stmt, const char *name, uint32_t nameLength, - dpiVar *var) -{ - dpiError error; - int status; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, name) - if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "bind by name", &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - status = dpiStmt__bind(stmt, var, 1, 0, name, nameLength, &error); - return dpiGen__endPublicFn(stmt, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_bindByPos() [PUBLIC] -// Bind the variable by position. -//----------------------------------------------------------------------------- -int dpiStmt_bindByPos(dpiStmt *stmt, uint32_t pos, dpiVar *var) -{ - dpiError error; - int status; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "bind by pos", &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - status = dpiStmt__bind(stmt, var, 1, pos, NULL, 0, &error); - return dpiGen__endPublicFn(stmt, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_bindValueByName() [PUBLIC] -// Create a variable and bind it by name. -//----------------------------------------------------------------------------- -int dpiStmt_bindValueByName(dpiStmt *stmt, const char *name, - uint32_t nameLength, dpiNativeTypeNum nativeTypeNum, dpiData *data) -{ - dpiVar *var = NULL; - dpiError error; - int status; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, name) - DPI_CHECK_PTR_NOT_NULL(stmt, data) - if (dpiStmt__createBindVar(stmt, nativeTypeNum, data, &var, 0, name, - nameLength, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - status = dpiStmt__bind(stmt, var, 1, 0, name, nameLength, &error); - return dpiGen__endPublicFn(stmt, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_bindValueByPos() [PUBLIC] -// Create a variable and bind it by position. -//----------------------------------------------------------------------------- -int dpiStmt_bindValueByPos(dpiStmt *stmt, uint32_t pos, - dpiNativeTypeNum nativeTypeNum, dpiData *data) -{ - dpiVar *var = NULL; - dpiError error; - int status; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, data) - if (dpiStmt__createBindVar(stmt, nativeTypeNum, data, &var, pos, NULL, 0, - &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - status = dpiStmt__bind(stmt, var, 1, pos, NULL, 0, &error); - return dpiGen__endPublicFn(stmt, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_close() [PUBLIC] -// Close the statement so that it is no longer usable and all resources have -// been released. -//----------------------------------------------------------------------------- -int dpiStmt_close(dpiStmt *stmt, const char *tag, uint32_t tagLength) -{ - dpiError error; - int status; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(stmt, tag) - status = dpiStmt__close(stmt, tag, tagLength, 1, &error); - return dpiGen__endPublicFn(stmt, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_define() [PUBLIC] -// Define the variable that will accept output from the cursor in the -// specified column. -//----------------------------------------------------------------------------- -int dpiStmt_define(dpiStmt *stmt, uint32_t pos, dpiVar *var) -{ - dpiError error; - int status; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (pos == 0 || pos > stmt->numQueryVars) { - dpiError__set(&error, "check query position", - DPI_ERR_QUERY_POSITION_INVALID, pos); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "check variable", &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - - status = dpiStmt__define(stmt, pos, var, &error); - return dpiGen__endPublicFn(stmt, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_defineValue() [PUBLIC] -// Define the type of data to use for output from the cursor in the specified -// column. This implicitly creates a variable of the specified type and is -// intended for subsequent use by dpiStmt_getQueryValue(), which makes use of -// implicitly created variables. -//----------------------------------------------------------------------------- -int dpiStmt_defineValue(dpiStmt *stmt, uint32_t pos, - dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, - uint32_t size, int sizeIsBytes, dpiObjectType *objType) -{ - dpiError error; - dpiData *data; - dpiVar *var; - - // verify parameters - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (pos == 0 || pos > stmt->numQueryVars) { - dpiError__set(&error, "check query position", - DPI_ERR_QUERY_POSITION_INVALID, pos); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - - // create a new variable of the specified type - if (dpiVar__allocate(stmt->conn, oracleTypeNum, nativeTypeNum, - stmt->fetchArraySize, size, sizeIsBytes, 0, objType, &var, &data, - &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (dpiStmt__define(stmt, pos, var, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - dpiGen__setRefCount(var, &error, -1); - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_execute() [PUBLIC] -// Execute a statement. If the statement has been executed before, however, -// and this is a query, the describe information is already available so defer -// execution until the first fetch. -//----------------------------------------------------------------------------- -int dpiStmt_execute(dpiStmt *stmt, dpiExecMode mode, uint32_t *numQueryColumns) -{ - uint32_t numIters; - dpiError error; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - numIters = (stmt->statementType == DPI_STMT_TYPE_SELECT) ? 0 : 1; - if (dpiStmt__execute(stmt, numIters, mode, 1, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (numQueryColumns) - *numQueryColumns = stmt->numQueryVars; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_executeMany() [PUBLIC] -// Execute a statement multiple times. Queries are not supported. The bind -// variables are checked to ensure that their maxArraySize is sufficient to -// support this. -//----------------------------------------------------------------------------- -int dpiStmt_executeMany(dpiStmt *stmt, dpiExecMode mode, uint32_t numIters) -{ - dpiError error; - uint32_t i; - - // verify statement is open - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - - // queries are not supported - if (stmt->statementType == DPI_STMT_TYPE_SELECT) { - dpiError__set(&error, "check statement type", DPI_ERR_NOT_SUPPORTED); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - - // batch errors and array DML row counts are only supported with DML - // statements (insert, update, delete and merge) - if ((mode & DPI_MODE_EXEC_BATCH_ERRORS || - mode & DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS) && - stmt->statementType != DPI_STMT_TYPE_INSERT && - stmt->statementType != DPI_STMT_TYPE_UPDATE && - stmt->statementType != DPI_STMT_TYPE_DELETE && - stmt->statementType != DPI_STMT_TYPE_MERGE) { - dpiError__set(&error, "check mode", DPI_ERR_EXEC_MODE_ONLY_FOR_DML); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - - // ensure that all bind variables have a big enough maxArraySize to - // support this operation - for (i = 0; i < stmt->numBindVars; i++) { - if (stmt->bindVars[i].var->buffer.maxArraySize < numIters) { - dpiError__set(&error, "check array size", - DPI_ERR_ARRAY_SIZE_TOO_SMALL, - stmt->bindVars[i].var->buffer.maxArraySize); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - } - - // perform execution - dpiStmt__clearBatchErrors(stmt); - if (dpiStmt__execute(stmt, numIters, mode, 0, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - - // handle batch errors if mode was specified - if (mode & DPI_MODE_EXEC_BATCH_ERRORS) { - if (dpiStmt__getBatchErrors(stmt, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_fetch() [PUBLIC] -// Fetch a row from the database. -//----------------------------------------------------------------------------- -int dpiStmt_fetch(dpiStmt *stmt, int *found, uint32_t *bufferRowIndex) -{ - dpiError error; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, found) - DPI_CHECK_PTR_NOT_NULL(stmt, bufferRowIndex) - if (stmt->bufferRowIndex >= stmt->bufferRowCount) { - if (stmt->hasRowsToFetch && dpiStmt__fetch(stmt, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (stmt->bufferRowIndex >= stmt->bufferRowCount) { - *found = 0; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); - } - } - *found = 1; - *bufferRowIndex = stmt->bufferRowIndex; - stmt->bufferRowIndex++; - stmt->rowCount++; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_fetchRows() [PUBLIC] -// Fetch rows into buffers and return the number of rows that were so -// fetched. If there are still rows available in the buffer, no additional -// fetch will take place. -//----------------------------------------------------------------------------- -int dpiStmt_fetchRows(dpiStmt *stmt, uint32_t maxRows, - uint32_t *bufferRowIndex, uint32_t *numRowsFetched, int *moreRows) -{ - dpiError error; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, bufferRowIndex) - DPI_CHECK_PTR_NOT_NULL(stmt, numRowsFetched) - DPI_CHECK_PTR_NOT_NULL(stmt, moreRows) - if (stmt->bufferRowIndex >= stmt->bufferRowCount) { - if (stmt->hasRowsToFetch && dpiStmt__fetch(stmt, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (stmt->bufferRowIndex >= stmt->bufferRowCount) { - *moreRows = 0; - *bufferRowIndex = 0; - *numRowsFetched = 0; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); - } - } - *bufferRowIndex = stmt->bufferRowIndex; - *numRowsFetched = stmt->bufferRowCount - stmt->bufferRowIndex; - *moreRows = stmt->hasRowsToFetch; - if (*numRowsFetched > maxRows) { - *numRowsFetched = maxRows; - *moreRows = 1; - } - stmt->bufferRowIndex += *numRowsFetched; - stmt->rowCount += *numRowsFetched; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getBatchErrorCount() [PUBLIC] -// Return the number of batch errors that took place during the last -// execution of the statement. -//----------------------------------------------------------------------------- -int dpiStmt_getBatchErrorCount(dpiStmt *stmt, uint32_t *count) -{ - dpiError error; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, count) - *count = stmt->numBatchErrors; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getBatchErrors() [PUBLIC] -// Return the batch errors that took place during the last execution of the -// statement. -//----------------------------------------------------------------------------- -int dpiStmt_getBatchErrors(dpiStmt *stmt, uint32_t numErrors, - dpiErrorInfo *errors) -{ - dpiError error, tempError; - uint32_t i; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, errors) - if (numErrors < stmt->numBatchErrors) { - dpiError__set(&error, "check num errors", DPI_ERR_ARRAY_SIZE_TOO_SMALL, - numErrors); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - for (i = 0; i < stmt->numBatchErrors; i++) { - tempError.buffer = &stmt->batchErrors[i]; - dpiError__getInfo(&tempError, &errors[i]); - } - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getBindCount() [PUBLIC] -// Return the number of bind variables referenced in the prepared SQL. In -// SQL statements this counts all bind variables but in PL/SQL statements -// this counts only uniquely named bind variables. -//----------------------------------------------------------------------------- -int dpiStmt_getBindCount(dpiStmt *stmt, uint32_t *count) -{ - dpiError error; - int status; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, count) - status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) count, - 0, DPI_OCI_ATTR_BIND_COUNT, "get bind count", &error); - return dpiGen__endPublicFn(stmt, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getBindNames() [PUBLIC] -// Return the unique names of the bind variables referenced in the prepared -// SQL. -//----------------------------------------------------------------------------- -int dpiStmt_getBindNames(dpiStmt *stmt, uint32_t *numBindNames, - const char **bindNames, uint32_t *bindNameLengths) -{ - uint8_t bindNameLengthsBuffer[8], indNameLengthsBuffer[8], isDuplicate[8]; - uint32_t startLoc, i, numThisPass, numActualBindNames; - char *bindNamesBuffer[8], *indNamesBuffer[8]; - void *bindHandles[8]; - int32_t numFound; - dpiError error; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, numBindNames) - DPI_CHECK_PTR_NOT_NULL(stmt, bindNames) - DPI_CHECK_PTR_NOT_NULL(stmt, bindNameLengths) - startLoc = 1; - numActualBindNames = 0; - while (1) { - if (dpiOci__stmtGetBindInfo(stmt, 8, startLoc, &numFound, - bindNamesBuffer, bindNameLengthsBuffer, indNamesBuffer, - indNameLengthsBuffer, isDuplicate, bindHandles, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (numFound == 0) - break; - numThisPass = abs(numFound) - startLoc + 1; - if (numThisPass > 8) - numThisPass = 8; - for (i = 0; i < numThisPass; i++) { - startLoc++; - if (isDuplicate[i]) - continue; - if (numActualBindNames == *numBindNames) { - dpiError__set(&error, "check num bind names", - DPI_ERR_ARRAY_SIZE_TOO_SMALL, *numBindNames); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - bindNames[numActualBindNames] = bindNamesBuffer[i]; - bindNameLengths[numActualBindNames] = bindNameLengthsBuffer[i]; - numActualBindNames++; - } - if (numFound > 0) - break; - } - *numBindNames = numActualBindNames; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getFetchArraySize() [PUBLIC] -// Get the array size used for fetches. -//----------------------------------------------------------------------------- -int dpiStmt_getFetchArraySize(dpiStmt *stmt, uint32_t *arraySize) -{ - dpiError error; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, arraySize) - *arraySize = stmt->fetchArraySize; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getImplicitResult() [PUBLIC] -// Return the next implicit result from the previously executed statement. If -// no more implicit results exist, NULL is returned. -//----------------------------------------------------------------------------- -int dpiStmt_getImplicitResult(dpiStmt *stmt, dpiStmt **implicitResult) -{ - dpiStmt *tempStmt; - dpiError error; - void *handle; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, implicitResult) - if (dpiUtils__checkClientVersion(stmt->env->versionInfo, 12, 1, - &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (dpiOci__stmtGetNextResult(stmt, &handle, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - *implicitResult = NULL; - if (handle) { - if (dpiStmt__allocate(stmt->conn, 0, &tempStmt, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - tempStmt->handle = handle; - dpiGen__setRefCount(stmt, &error, 1); - tempStmt->parentStmt = stmt; - if (dpiStmt__createQueryVars(tempStmt, &error) < 0) { - dpiStmt__free(tempStmt, &error); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - *implicitResult = tempStmt; - } - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getInfo() [PUBLIC] -// Return information about the statement in the provided structure. -//----------------------------------------------------------------------------- -int dpiStmt_getInfo(dpiStmt *stmt, dpiStmtInfo *info) -{ - dpiError error; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, info) - info->isQuery = (stmt->statementType == DPI_STMT_TYPE_SELECT); - info->isPLSQL = (stmt->statementType == DPI_STMT_TYPE_BEGIN || - stmt->statementType == DPI_STMT_TYPE_DECLARE || - stmt->statementType == DPI_STMT_TYPE_CALL); - info->isDDL = (stmt->statementType == DPI_STMT_TYPE_CREATE || - stmt->statementType == DPI_STMT_TYPE_DROP || - stmt->statementType == DPI_STMT_TYPE_ALTER); - info->isDML = (stmt->statementType == DPI_STMT_TYPE_INSERT || - stmt->statementType == DPI_STMT_TYPE_UPDATE || - stmt->statementType == DPI_STMT_TYPE_DELETE || - stmt->statementType == DPI_STMT_TYPE_MERGE); - info->statementType = stmt->statementType; - info->isReturning = stmt->isReturning; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getLastRowid() [PUBLIC] -// Returns the rowid of the last row that was affected by a DML statement. If -// no rows were affected by the last statement executed or the last statement -// executed was not a DML statement, NULL is returned. -//----------------------------------------------------------------------------- -int dpiStmt_getLastRowid(dpiStmt *stmt, dpiRowid **rowid) -{ - uint64_t rowCount; - dpiError error; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, rowid) - *rowid = NULL; - if (stmt->statementType == DPI_STMT_TYPE_INSERT || - stmt->statementType == DPI_STMT_TYPE_UPDATE || - stmt->statementType == DPI_STMT_TYPE_DELETE || - stmt->statementType == DPI_STMT_TYPE_MERGE) { - if (dpiStmt__getRowCount(stmt, &rowCount, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (rowCount > 0) { - if (stmt->lastRowid) { - dpiGen__setRefCount(stmt->lastRowid, &error, -1); - stmt->lastRowid = NULL; - } - if (dpiRowid__allocate(stmt->conn, &stmt->lastRowid, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, - stmt->lastRowid->handle, 0, DPI_OCI_ATTR_ROWID, - "get last rowid", &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - *rowid = stmt->lastRowid; - } - } - - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getNumQueryColumns() [PUBLIC] -// Returns the number of query columns associated with a statement. If the -// statement does not refer to a query, 0 is returned. -//----------------------------------------------------------------------------- -int dpiStmt_getNumQueryColumns(dpiStmt *stmt, uint32_t *numQueryColumns) -{ - dpiError error; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, numQueryColumns) - if (stmt->statementType == DPI_STMT_TYPE_SELECT && - stmt->numQueryVars == 0 && - dpiStmt__createQueryVars(stmt, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - *numQueryColumns = stmt->numQueryVars; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getQueryInfo() [PUBLIC] -// Get query information for the position in question. -//----------------------------------------------------------------------------- -int dpiStmt_getQueryInfo(dpiStmt *stmt, uint32_t pos, dpiQueryInfo *info) -{ - dpiError error; - - // validate parameters - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, info) - if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (pos == 0 || pos > stmt->numQueryVars) { - dpiError__set(&error, "check query position", - DPI_ERR_QUERY_POSITION_INVALID, pos); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - - // copy query information from internal cache - memcpy(info, &stmt->queryInfo[pos - 1], sizeof(dpiQueryInfo)); - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getQueryValue() [PUBLIC] -// Get value from query at specified position. -//----------------------------------------------------------------------------- -int dpiStmt_getQueryValue(dpiStmt *stmt, uint32_t pos, - dpiNativeTypeNum *nativeTypeNum, dpiData **data) -{ - dpiError error; - dpiVar *var; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, nativeTypeNum) - DPI_CHECK_PTR_NOT_NULL(stmt, data) - if (!stmt->queryVars) { - dpiError__set(&error, "check query vars", DPI_ERR_QUERY_NOT_EXECUTED); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - if (pos == 0 || pos > stmt->numQueryVars) { - dpiError__set(&error, "check query position", - DPI_ERR_QUERY_POSITION_INVALID, pos); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - var = stmt->queryVars[pos - 1]; - if (!var || stmt->bufferRowIndex == 0 || - stmt->bufferRowIndex > stmt->bufferRowCount) { - dpiError__set(&error, "check fetched row", DPI_ERR_NO_ROW_FETCHED); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - *nativeTypeNum = var->nativeTypeNum; - *data = &var->buffer.externalData[stmt->bufferRowIndex - 1]; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getRowCount() [PUBLIC] -// Return the number of rows affected by the last DML executed (for insert, -// update, delete and merge) or the number of rows fetched (for queries). In -// all other cases, 0 is returned. -//----------------------------------------------------------------------------- -int dpiStmt_getRowCount(dpiStmt *stmt, uint64_t *count) -{ - dpiError error; - int status; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, count) - status = dpiStmt__getRowCount(stmt, count, &error); - return dpiGen__endPublicFn(stmt, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getRowCounts() [PUBLIC] -// Return the number of rows affected by each of the iterations executed -// using dpiStmt_executeMany(). -//----------------------------------------------------------------------------- -int dpiStmt_getRowCounts(dpiStmt *stmt, uint32_t *numRowCounts, - uint64_t **rowCounts) -{ - dpiError error; - int status; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, numRowCounts) - DPI_CHECK_PTR_NOT_NULL(stmt, rowCounts) - if (dpiUtils__checkClientVersion(stmt->env->versionInfo, 12, 1, - &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, rowCounts, - numRowCounts, DPI_OCI_ATTR_DML_ROW_COUNT_ARRAY, "get row counts", - &error); - return dpiGen__endPublicFn(stmt, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_getSubscrQueryId() [PUBLIC] -// Return the query id for a query registered using this statement. -//----------------------------------------------------------------------------- -int dpiStmt_getSubscrQueryId(dpiStmt *stmt, uint64_t *queryId) -{ - dpiError error; - int status; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(stmt, queryId) - status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, queryId, 0, - DPI_OCI_ATTR_CQ_QUERYID, "get query id", &error); - return dpiGen__endPublicFn(stmt, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_release() [PUBLIC] -// Release a reference to the statement. -//----------------------------------------------------------------------------- -int dpiStmt_release(dpiStmt *stmt) -{ - return dpiGen__release(stmt, DPI_HTYPE_STMT, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_scroll() [PUBLIC] -// Scroll to the specified location in the cursor. -//----------------------------------------------------------------------------- -int dpiStmt_scroll(dpiStmt *stmt, dpiFetchMode mode, int32_t offset, - int32_t rowCountOffset) -{ - uint32_t numRows, currentPosition; - uint64_t desiredRow = 0; - dpiError error; - - // make sure the cursor is open - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - - // validate mode; determine desired row to fetch - switch (mode) { - case DPI_MODE_FETCH_NEXT: - desiredRow = stmt->rowCount + rowCountOffset + 1; - break; - case DPI_MODE_FETCH_PRIOR: - desiredRow = stmt->rowCount + rowCountOffset - 1; - break; - case DPI_MODE_FETCH_FIRST: - desiredRow = 1; - break; - case DPI_MODE_FETCH_LAST: - break; - case DPI_MODE_FETCH_ABSOLUTE: - desiredRow = (uint64_t) offset; - break; - case DPI_MODE_FETCH_RELATIVE: - desiredRow = stmt->rowCount + rowCountOffset + offset; - offset = (int32_t) (desiredRow - - (stmt->bufferMinRow + stmt->bufferRowCount - 1)); - break; - default: - dpiError__set(&error, "scroll mode", DPI_ERR_NOT_SUPPORTED); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - - // determine if a fetch is actually required; "last" is always fetched - if (mode != DPI_MODE_FETCH_LAST && desiredRow >= stmt->bufferMinRow && - desiredRow < stmt->bufferMinRow + stmt->bufferRowCount) { - stmt->bufferRowIndex = (uint32_t) (desiredRow - stmt->bufferMinRow); - stmt->rowCount = desiredRow - 1; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); - } - - // perform any pre-fetch activities required - if (dpiStmt__beforeFetch(stmt, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - - // perform fetch; when fetching the last row, only fetch a single row - numRows = (mode == DPI_MODE_FETCH_LAST) ? 1 : stmt->fetchArraySize; - if (dpiOci__stmtFetch2(stmt, numRows, mode, offset, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - - // determine the number of rows actually fetched - if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, - &stmt->bufferRowCount, 0, DPI_OCI_ATTR_ROWS_FETCHED, - "get rows fetched", &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - - // check that we haven't gone outside of the result set - if (stmt->bufferRowCount == 0) { - if (mode != DPI_MODE_FETCH_FIRST && mode != DPI_MODE_FETCH_LAST) { - dpiError__set(&error, "check result set bounds", - DPI_ERR_SCROLL_OUT_OF_RS); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - stmt->hasRowsToFetch = 0; - stmt->rowCount = 0; - stmt->bufferRowIndex = 0; - stmt->bufferMinRow = 0; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); - } - - // determine the current position of the cursor - if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, ¤tPosition, 0, - DPI_OCI_ATTR_CURRENT_POSITION, "get current pos", &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - - // reset buffer row index and row count - stmt->rowCount = currentPosition - stmt->bufferRowCount; - stmt->bufferMinRow = stmt->rowCount + 1; - stmt->bufferRowIndex = 0; - - // perform post-fetch activities required - if (dpiStmt__postFetch(stmt, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiStmt_setFetchArraySize() [PUBLIC] -// Set the array size used for fetches. Using a value of zero will select the -// default value. A check is made to ensure that all defined variables have -// sufficient space to support the array size. -//----------------------------------------------------------------------------- -int dpiStmt_setFetchArraySize(dpiStmt *stmt, uint32_t arraySize) -{ - dpiError error; - dpiVar *var; - uint32_t i; - - if (dpiStmt__check(stmt, __func__, &error) < 0) - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - if (arraySize == 0) - arraySize = DPI_DEFAULT_FETCH_ARRAY_SIZE; - for (i = 0; i < stmt->numQueryVars; i++) { - var = stmt->queryVars[i]; - if (var && var->buffer.maxArraySize < arraySize) { - dpiError__set(&error, "check array size", - DPI_ERR_ARRAY_SIZE_TOO_BIG, arraySize); - return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); - } - } - stmt->fetchArraySize = arraySize; - return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSubscr.c b/vendor/github.com/godror/godror/odpi/src/dpiSubscr.c deleted file mode 100644 index cf1ed60b2d8..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiSubscr.c +++ /dev/null @@ -1,713 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiSubscr.c -// Implementation of subscriptions (CQN). -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -// forward declarations of internal functions only used in this file -static void dpiSubscr__freeMessage(dpiSubscrMessage *message); -static int dpiSubscr__populateMessage(dpiSubscr *subscr, - dpiSubscrMessage *message, void *descriptor, dpiError *error); -static int dpiSubscr__populateMessageTable(dpiSubscr *subscr, - dpiSubscrMessageTable *table, void *descriptor, dpiError *error); -static int dpiSubscr__populateQueryChangeMessage(dpiSubscr *subscr, - dpiSubscrMessage *message, void *descriptor, dpiError *error); - - -//----------------------------------------------------------------------------- -// dpiSubscr__callback() [INTERNAL] -// Callback that is used to execute the callback registered when the -// subscription was created. -//----------------------------------------------------------------------------- -static void dpiSubscr__callback(dpiSubscr *subscr, UNUSED void *handle, - UNUSED void *payload, UNUSED uint32_t payloadLength, void *descriptor, - UNUSED uint32_t mode) -{ - dpiSubscrMessage message; - dpiErrorInfo errorInfo; - dpiError error; - - // ensure that the subscription handle is still valid - if (dpiGen__startPublicFn(subscr, DPI_HTYPE_SUBSCR, __func__, - &error) < 0) { - dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); - return; - } - - // if the subscription is no longer registered, nothing further to do - dpiMutex__acquire(subscr->mutex); - if (!subscr->registered) { - dpiMutex__release(subscr->mutex); - dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); - return; - } - - // populate message - memset(&message, 0, sizeof(message)); - if (dpiSubscr__populateMessage(subscr, &message, descriptor, &error) < 0) { - dpiError__getInfo(&error, &errorInfo); - message.errorInfo = &errorInfo; - } - message.registered = subscr->registered; - - // invoke user callback; temporarily increase reference count to ensure - // that the subscription is not freed during the callback - dpiGen__setRefCount(subscr, &error, 1); - (*subscr->callback)(subscr->callbackContext, &message); - dpiSubscr__freeMessage(&message); - dpiMutex__release(subscr->mutex); - dpiGen__setRefCount(subscr, &error, -1); - dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__check() [INTERNAL] -// Determine if the subscription is open and available for use. -//----------------------------------------------------------------------------- -static int dpiSubscr__check(dpiSubscr *subscr, const char *fnName, - dpiError *error) -{ - if (dpiGen__startPublicFn(subscr, DPI_HTYPE_SUBSCR, fnName, error) < 0) - return DPI_FAILURE; - if (!subscr->handle) - return dpiError__set(error, "check closed", DPI_ERR_SUBSCR_CLOSED); - return dpiConn__checkConnected(subscr->conn, error); -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__create() [INTERNAL] -// Create a new subscription structure and return it. In case of error NULL -// is returned. -//----------------------------------------------------------------------------- -int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn, - dpiSubscrCreateParams *params, dpiError *error) -{ - uint32_t qosFlags, mode; - int32_t int32Val; - int rowids; - - // retain a reference to the connection - dpiGen__setRefCount(conn, error, 1); - subscr->conn = conn; - subscr->callback = params->callback; - subscr->callbackContext = params->callbackContext; - subscr->subscrNamespace = params->subscrNamespace; - subscr->qos = params->qos; - subscr->clientInitiated = params->clientInitiated; - dpiMutex__initialize(subscr->mutex); - - // create the subscription handle - if (dpiOci__handleAlloc(conn->env->handle, &subscr->handle, - DPI_OCI_HTYPE_SUBSCRIPTION, "create subscr handle", error) < 0) - return DPI_FAILURE; - - // set the namespace - if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) ¶ms->subscrNamespace, sizeof(uint32_t), - DPI_OCI_ATTR_SUBSCR_NAMESPACE, "set namespace", error) < 0) - return DPI_FAILURE; - - // set the protocol - if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) ¶ms->protocol, sizeof(uint32_t), - DPI_OCI_ATTR_SUBSCR_RECPTPROTO, "set protocol", error) < 0) - return DPI_FAILURE; - - // set the timeout - if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) ¶ms->timeout, sizeof(uint32_t), - DPI_OCI_ATTR_SUBSCR_TIMEOUT, "set timeout", error) < 0) - return DPI_FAILURE; - - // set the IP address used on the client to listen for events - if (params->ipAddress && params->ipAddressLength > 0 && - dpiOci__attrSet(subscr->env->handle, DPI_OCI_HTYPE_ENV, - (void*) params->ipAddress, params->ipAddressLength, - DPI_OCI_ATTR_SUBSCR_IPADDR, "set IP address", error) < 0) - return DPI_FAILURE; - - // set the port number used on the client to listen for events - if (params->portNumber > 0 && dpiOci__attrSet(subscr->env->handle, - DPI_OCI_HTYPE_ENV, (void*) ¶ms->portNumber, 0, - DPI_OCI_ATTR_SUBSCR_PORTNO, "set port number", error) < 0) - return DPI_FAILURE; - - // set the context for the callback - if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) subscr, 0, DPI_OCI_ATTR_SUBSCR_CTX, "set callback context", - error) < 0) - return DPI_FAILURE; - - // set the callback, if applicable - if (params->callback && dpiOci__attrSet(subscr->handle, - DPI_OCI_HTYPE_SUBSCRIPTION, (void*) dpiSubscr__callback, 0, - DPI_OCI_ATTR_SUBSCR_CALLBACK, "set callback", error) < 0) - return DPI_FAILURE; - - // set the subscription name, if applicable - if (params->name && params->nameLength > 0 && - dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) params->name, params->nameLength, - DPI_OCI_ATTR_SUBSCR_NAME, "set name", error) < 0) - return DPI_FAILURE; - - // set QOS flags - qosFlags = 0; - if (params->qos & DPI_SUBSCR_QOS_RELIABLE) - qosFlags |= DPI_OCI_SUBSCR_QOS_RELIABLE; - if (params->qos & DPI_SUBSCR_QOS_DEREG_NFY) - qosFlags |= DPI_OCI_SUBSCR_QOS_PURGE_ON_NTFN; - if (qosFlags && dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) &qosFlags, sizeof(uint32_t), DPI_OCI_ATTR_SUBSCR_QOSFLAGS, - "set QOS", error) < 0) - return DPI_FAILURE; - - // set CQ specific QOS flags - qosFlags = 0; - if (params->qos & DPI_SUBSCR_QOS_QUERY) - qosFlags |= DPI_OCI_SUBSCR_CQ_QOS_QUERY; - if (params->qos & DPI_SUBSCR_QOS_BEST_EFFORT) - qosFlags |= DPI_OCI_SUBSCR_CQ_QOS_BEST_EFFORT; - if (qosFlags && dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) &qosFlags, sizeof(uint32_t), - DPI_OCI_ATTR_SUBSCR_CQ_QOSFLAGS, "set CQ QOS", error) < 0) - return DPI_FAILURE; - - // set rowids flag, if applicable - if (params->qos & DPI_SUBSCR_QOS_ROWIDS) { - rowids = 1; - if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) &rowids, 0, DPI_OCI_ATTR_CHNF_ROWIDS, - "set rowids flag", error) < 0) - return DPI_FAILURE; - } - - // set which operations are desired, if applicable - if (params->operations && dpiOci__attrSet(subscr->handle, - DPI_OCI_HTYPE_SUBSCRIPTION, (void*) ¶ms->operations, 0, - DPI_OCI_ATTR_CHNF_OPERATIONS, "set operations", error) < 0) - return DPI_FAILURE; - - // set grouping information, if applicable - if (params->groupingClass) { - - // set grouping class - if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) ¶ms->groupingClass, 0, - DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_CLASS, "set grouping class", - error) < 0) - return DPI_FAILURE; - - // set grouping value - if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) ¶ms->groupingValue, 0, - DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_VALUE, "set grouping value", - error) < 0) - return DPI_FAILURE; - - // set grouping type - if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) ¶ms->groupingType, 0, - DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_TYPE, "set grouping type", - error) < 0) - return DPI_FAILURE; - - // set grouping repeat count - int32Val = DPI_SUBSCR_GROUPING_FOREVER; - if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - (void*) &int32Val, 0, - DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_REPEAT_COUNT, - "set grouping repeat count", error) < 0) - return DPI_FAILURE; - - } - - // register the subscription; client initiated subscriptions are only valid - // with 19.4 client and database - mode = DPI_OCI_DEFAULT; - if (params->clientInitiated) { - if (dpiUtils__checkClientVersion(conn->env->versionInfo, 19, 4, - error) < 0) - return DPI_FAILURE; - if (dpiUtils__checkDatabaseVersion(conn, 19, 4, error) < 0) - return DPI_FAILURE; - mode = DPI_OCI_SECURE_NOTIFICATION; - } - if (dpiOci__subscriptionRegister(conn, &subscr->handle, mode, error) < 0) - return DPI_FAILURE; - subscr->registered = 1; - - // acquire the registration id - if (dpiOci__attrGet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, - ¶ms->outRegId, NULL, DPI_OCI_ATTR_SUBSCR_CQ_REGID, - "get registration id", error) < 0) - return DPI_FAILURE; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__free() [INTERNAL] -// Free the memory and any resources associated with the subscription. -//----------------------------------------------------------------------------- -void dpiSubscr__free(dpiSubscr *subscr, dpiError *error) -{ - dpiMutex__acquire(subscr->mutex); - if (subscr->handle) { - if (subscr->registered) - dpiOci__subscriptionUnRegister(subscr->conn, subscr, error); - dpiOci__handleFree(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION); - subscr->handle = NULL; - } - if (subscr->conn) { - dpiGen__setRefCount(subscr->conn, error, -1); - subscr->conn = NULL; - } - dpiMutex__release(subscr->mutex); - dpiMutex__destroy(subscr->mutex); - dpiUtils__freeMemory(subscr); -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__freeMessage() [INTERNAL] -// Free memory associated with the message. -//----------------------------------------------------------------------------- -static void dpiSubscr__freeMessage(dpiSubscrMessage *message) -{ - dpiSubscrMessageQuery *query; - uint32_t i, j; - - // free the tables for the message - if (message->numTables > 0) { - for (i = 0; i < message->numTables; i++) { - if (message->tables[i].numRows > 0) - dpiUtils__freeMemory(message->tables[i].rows); - } - dpiUtils__freeMemory(message->tables); - } - - // free the queries for the message - if (message->numQueries > 0) { - for (i = 0; i < message->numQueries; i++) { - query = &message->queries[i]; - if (query->numTables > 0) { - for (j = 0; j < query->numTables; j++) { - if (query->tables[j].numRows > 0) - dpiUtils__freeMemory(query->tables[j].rows); - } - dpiUtils__freeMemory(query->tables); - } - } - dpiUtils__freeMemory(message->queries); - } -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__populateAQMessage() [INTERNAL] -// Populate message with details. -//----------------------------------------------------------------------------- -static int dpiSubscr__populateAQMessage(dpiSubscr *subscr, - dpiSubscrMessage *message, void *descriptor, dpiError *error) -{ - uint32_t flags = 0; - - // determine if message is a deregistration message - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, &flags, - NULL, DPI_OCI_ATTR_NFY_FLAGS, "get flags", error) < 0) - return DPI_FAILURE; - message->eventType = (flags == 1) ? DPI_EVENT_DEREG : DPI_EVENT_AQ; - if (message->eventType == DPI_EVENT_DEREG) { - subscr->registered = 0; - return DPI_SUCCESS; - } - - // determine the name of the queue which spawned the event - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, - (void*) &message->queueName, &message->queueNameLength, - DPI_OCI_ATTR_QUEUE_NAME, "get queue name", error) < 0) - return DPI_FAILURE; - - // determine the consumer name for the queue that spawned the event - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, - (void*) &message->consumerName, &message->consumerNameLength, - DPI_OCI_ATTR_CONSUMER_NAME, "get consumer name", error) < 0) - return DPI_FAILURE; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__populateObjectChangeMessage() [INTERNAL] -// Populate object change message with details. -//----------------------------------------------------------------------------- -static int dpiSubscr__populateObjectChangeMessage(dpiSubscr *subscr, - dpiSubscrMessage *message, void *descriptor, dpiError *error) -{ - void **tableDescriptor, *indicator; - int32_t numTables; - void *tables; - uint32_t i; - int exists; - - // determine table collection - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &tables, 0, - DPI_OCI_ATTR_CHDES_TABLE_CHANGES, "get tables", error) < 0) - return DPI_FAILURE; - if (!tables) - return DPI_SUCCESS; - - // determine number of tables - if (dpiOci__collSize(subscr->conn, tables, &numTables, error) < 0) - return DPI_FAILURE; - - // allocate memory for table entries - if (dpiUtils__allocateMemory((size_t) numTables, - sizeof(dpiSubscrMessageTable), 1, "allocate msg tables", - (void**) &message->tables, error) < 0) - return DPI_FAILURE; - message->numTables = (uint32_t) numTables; - - // populate message table entries - for (i = 0; i < message->numTables; i++) { - if (dpiOci__collGetElem(subscr->conn, tables, (int32_t) i, &exists, - (void**) &tableDescriptor, &indicator, error) < 0) - return DPI_FAILURE; - if (dpiSubscr__populateMessageTable(subscr, &message->tables[i], - *tableDescriptor, error) < 0) - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__populateMessage() [INTERNAL] -// Populate message with details. -//----------------------------------------------------------------------------- -static int dpiSubscr__populateMessage(dpiSubscr *subscr, - dpiSubscrMessage *message, void *descriptor, dpiError *error) -{ - void *rawValue; - - // if quality of service flag indicates that deregistration should take - // place when the first notification is received, mark the subscription - // as no longer registered - if (subscr->qos & DPI_SUBSCR_QOS_DEREG_NFY) - subscr->registered = 0; - - // handle AQ messages, if applicable - if (subscr->subscrNamespace == DPI_SUBSCR_NAMESPACE_AQ) - return dpiSubscr__populateAQMessage(subscr, message, descriptor, - error); - - // determine the type of event that was spawned - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &message->eventType, - NULL, DPI_OCI_ATTR_CHDES_NFYTYPE, "get event type", error) < 0) - return DPI_FAILURE; - - // determine the name of the database which spawned the event - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, - (void*) &message->dbName, &message->dbNameLength, - DPI_OCI_ATTR_CHDES_DBNAME, "get DB name", error) < 0) - return DPI_FAILURE; - - // determine the id of the transaction which spawned the event - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &rawValue, NULL, - DPI_OCI_ATTR_CHDES_XID, "get transaction id", error) < 0) - return DPI_FAILURE; - dpiOci__rawPtr(subscr->env->handle, rawValue, (void**) &message->txId); - dpiOci__rawSize(subscr->env->handle, rawValue, &message->txIdLength); - - // populate event specific attributes - switch (message->eventType) { - case DPI_EVENT_OBJCHANGE: - return dpiSubscr__populateObjectChangeMessage(subscr, message, - descriptor, error); - case DPI_EVENT_QUERYCHANGE: - return dpiSubscr__populateQueryChangeMessage(subscr, message, - descriptor, error); - case DPI_EVENT_DEREG: - subscr->registered = 0; - break; - case DPI_EVENT_STARTUP: - case DPI_EVENT_SHUTDOWN: - case DPI_EVENT_SHUTDOWN_ANY: - break; - default: - return dpiError__set(error, "event type", DPI_ERR_NOT_SUPPORTED); - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__populateMessageQuery() [INTERNAL] -// Populate a message query structure from the OCI descriptor. -//----------------------------------------------------------------------------- -static int dpiSubscr__populateMessageQuery(dpiSubscr *subscr, - dpiSubscrMessageQuery *query, void *descriptor, dpiError *error) -{ - void **tableDescriptor, *indicator, *tables; - int32_t numTables; - uint32_t i; - int exists; - - // determine query id - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CQDES, &query->id, 0, - DPI_OCI_ATTR_CQDES_QUERYID, "get id", error) < 0) - return DPI_FAILURE; - - // determine operation - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CQDES, &query->operation, 0, - DPI_OCI_ATTR_CQDES_OPERATION, "get operation", error) < 0) - return DPI_FAILURE; - - // determine table collection - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CQDES, &tables, 0, - DPI_OCI_ATTR_CQDES_TABLE_CHANGES, "get table descriptor", - error) < 0) - return DPI_FAILURE; - if (!tables) - return DPI_SUCCESS; - - // determine number of tables - if (dpiOci__collSize(subscr->conn, tables, &numTables, error) < 0) - return DPI_FAILURE; - - // allocate memory for table entries - if (dpiUtils__allocateMemory((size_t) numTables, - sizeof(dpiSubscrMessageTable), 1, "allocate query tables", - (void**) &query->tables, error) < 0) - return DPI_FAILURE; - query->numTables = (uint32_t) numTables; - - // populate message table entries - for (i = 0; i < query->numTables; i++) { - if (dpiOci__collGetElem(subscr->conn, tables, (int32_t) i, &exists, - (void**) &tableDescriptor, &indicator, error) < 0) - return DPI_FAILURE; - if (dpiSubscr__populateMessageTable(subscr, &query->tables[i], - *tableDescriptor, error) < 0) - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__populateMessageRow() [INTERNAL] -// Populate a message row structure from the OCI descriptor. -//----------------------------------------------------------------------------- -static int dpiSubscr__populateMessageRow(dpiSubscrMessageRow *row, - void *descriptor, dpiError *error) -{ - // determine operation - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_ROW_CHDES, &row->operation, - 0, DPI_OCI_ATTR_CHDES_ROW_OPFLAGS, "get operation", error) < 0) - return DPI_FAILURE; - - // determine rowid - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_ROW_CHDES, - (void*) &row->rowid, &row->rowidLength, - DPI_OCI_ATTR_CHDES_ROW_ROWID, "get rowid", error) < 0) - return DPI_FAILURE; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__populateMessageTable() [INTERNAL] -// Populate a message table structure from the OCI descriptor. -//----------------------------------------------------------------------------- -static int dpiSubscr__populateMessageTable(dpiSubscr *subscr, - dpiSubscrMessageTable *table, void *descriptor, dpiError *error) -{ - void **rowDescriptor, *indicator, *rows; - int32_t numRows; - int exists; - uint32_t i; - - // determine operation - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_TABLE_CHDES, - &table->operation, 0, DPI_OCI_ATTR_CHDES_TABLE_OPFLAGS, - "get operation", error) < 0) - return DPI_FAILURE; - - // determine table name - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_TABLE_CHDES, - (void*) &table->name, &table->nameLength, - DPI_OCI_ATTR_CHDES_TABLE_NAME, "get table name", error) < 0) - return DPI_FAILURE; - - // if change invalidated all rows, nothing to do - if (table->operation & DPI_OPCODE_ALL_ROWS) - return DPI_SUCCESS; - - // determine rows collection - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_TABLE_CHDES, &rows, 0, - DPI_OCI_ATTR_CHDES_TABLE_ROW_CHANGES, "get rows descriptor", - error) < 0) - return DPI_FAILURE; - - // determine number of rows in collection - if (dpiOci__collSize(subscr->conn, rows, &numRows, error) < 0) - return DPI_FAILURE; - - // allocate memory for row entries - if (dpiUtils__allocateMemory((size_t) numRows, sizeof(dpiSubscrMessageRow), - 1, "allocate rows", (void**) &table->rows, error) < 0) - return DPI_FAILURE; - table->numRows = (uint32_t) numRows; - - // populate the rows attribute - for (i = 0; i < table->numRows; i++) { - if (dpiOci__collGetElem(subscr->conn, rows, (int32_t) i, &exists, - (void**) &rowDescriptor, &indicator, error) < 0) - return DPI_FAILURE; - if (dpiSubscr__populateMessageRow(&table->rows[i], *rowDescriptor, - error) < 0) - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__populateQueryChangeMessage() [INTERNAL] -// Populate query change message with details. -//----------------------------------------------------------------------------- -static int dpiSubscr__populateQueryChangeMessage(dpiSubscr *subscr, - dpiSubscrMessage *message, void *descriptor, dpiError *error) -{ - void **queryDescriptor, *indicator, *queries; - int32_t numQueries; - int exists; - uint32_t i; - - // determine query collection - if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &queries, 0, - DPI_OCI_ATTR_CHDES_QUERIES, "get queries", error) < 0) - return DPI_FAILURE; - if (!queries) - return DPI_SUCCESS; - - // determine number of queries - if (dpiOci__collSize(subscr->conn, queries, &numQueries, error) < 0) - return DPI_FAILURE; - - // allocate memory for query entries - if (dpiUtils__allocateMemory((size_t) numQueries, - sizeof(dpiSubscrMessageQuery), 1, "allocate queries", - (void**) &message->queries, error) < 0) - return DPI_FAILURE; - message->numQueries = (uint32_t) numQueries; - - // populate each entry with a message query instance - for (i = 0; i < message->numQueries; i++) { - if (dpiOci__collGetElem(subscr->conn, queries, (int32_t) i, &exists, - (void**) &queryDescriptor, &indicator, error) < 0) - return DPI_FAILURE; - if (dpiSubscr__populateMessageQuery(subscr, &message->queries[i], - *queryDescriptor, error) < 0) - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiSubscr__prepareStmt() [INTERNAL] -// Internal method for preparing statement against a subscription. This -// allows for normal error processing without having to worry about freeing the -// statement for every error that might take place. -//----------------------------------------------------------------------------- -static int dpiSubscr__prepareStmt(dpiSubscr *subscr, dpiStmt *stmt, - const char *sql, uint32_t sqlLength, dpiError *error) -{ - // prepare statement for execution; only SELECT statements are supported - if (dpiStmt__prepare(stmt, sql, sqlLength, NULL, 0, error) < 0) - return DPI_FAILURE; - if (stmt->statementType != DPI_STMT_TYPE_SELECT) - return dpiError__set(error, "subscr prepare statement", - DPI_ERR_NOT_SUPPORTED); - - // fetch array size is set to 1 in order to avoid over allocation since - // the query is not really going to be used for fetching rows, just for - // registration - stmt->fetchArraySize = 1; - - // set subscription handle - return dpiOci__attrSet(stmt->handle, DPI_OCI_HTYPE_STMT, subscr->handle, 0, - DPI_OCI_ATTR_CHNF_REGHANDLE, "set subscription handle", error); -} - - -//----------------------------------------------------------------------------- -// dpiSubscr_addRef() [PUBLIC] -// Add a reference to the subscription. -//----------------------------------------------------------------------------- -int dpiSubscr_addRef(dpiSubscr *subscr) -{ - return dpiGen__addRef(subscr, DPI_HTYPE_SUBSCR, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiSubscr_prepareStmt() [PUBLIC] -// Prepare statement for registration with subscription. -//----------------------------------------------------------------------------- -int dpiSubscr_prepareStmt(dpiSubscr *subscr, const char *sql, - uint32_t sqlLength, dpiStmt **stmt) -{ - dpiStmt *tempStmt; - dpiError error; - - if (dpiSubscr__check(subscr, __func__, &error) < 0) - return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(subscr, sql) - DPI_CHECK_PTR_NOT_NULL(subscr, stmt) - if (dpiStmt__allocate(subscr->conn, 0, &tempStmt, &error) < 0) - return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); - if (dpiSubscr__prepareStmt(subscr, tempStmt, sql, sqlLength, - &error) < 0) { - dpiStmt__free(tempStmt, &error); - return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); - } - - *stmt = tempStmt; - return dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiSubscr_release() [PUBLIC] -// Release a reference to the subscription. -//----------------------------------------------------------------------------- -int dpiSubscr_release(dpiSubscr *subscr) -{ - return dpiGen__release(subscr, DPI_HTYPE_SUBSCR, __func__); -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiUtils.c b/vendor/github.com/godror/godror/odpi/src/dpiUtils.c deleted file mode 100644 index 0ab09e54487..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiUtils.c +++ /dev/null @@ -1,401 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiUtils.c -// Utility methods that aren't specific to a particular type. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -//----------------------------------------------------------------------------- -// dpiUtils__allocateMemory() [INTERNAL] -// Method for allocating memory which permits tracing and populates the error -// structure in the event of a memory allocation failure. -//----------------------------------------------------------------------------- -int dpiUtils__allocateMemory(size_t numMembers, size_t memberSize, - int clearMemory, const char *action, void **ptr, dpiError *error) -{ - if (clearMemory) - *ptr = calloc(numMembers, memberSize); - else *ptr = malloc(numMembers * memberSize); - if (!*ptr) - return dpiError__set(error, action, DPI_ERR_NO_MEMORY); - if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM) - dpiDebug__print("allocated %u bytes at %p (%s)\n", - numMembers * memberSize, *ptr, action); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiUtils__checkClientVersion() [INTERNAL] -// Check the Oracle Client version and verify that it is at least at the -// minimum version that is required. -//----------------------------------------------------------------------------- -int dpiUtils__checkClientVersion(dpiVersionInfo *versionInfo, - int minVersionNum, int minReleaseNum, dpiError *error) -{ - if (versionInfo->versionNum < minVersionNum || - (versionInfo->versionNum == minVersionNum && - versionInfo->releaseNum < minReleaseNum)) - return dpiError__set(error, "check Oracle Client version", - DPI_ERR_ORACLE_CLIENT_TOO_OLD, versionInfo->versionNum, - versionInfo->releaseNum, minVersionNum, minReleaseNum); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiUtils__checkDatabaseVersion() [INTERNAL] -// Check the Oracle Database version and verify that it is at least at the -// minimum version that is required. -//----------------------------------------------------------------------------- -int dpiUtils__checkDatabaseVersion(dpiConn *conn, int minVersionNum, - int minReleaseNum, dpiError *error) -{ - if (dpiConn__getServerVersion(conn, error) < 0) - return DPI_FAILURE; - if (conn->versionInfo.versionNum < minVersionNum || - (conn->versionInfo.versionNum == minVersionNum && - conn->versionInfo.releaseNum < minReleaseNum)) - return dpiError__set(error, "check Oracle Database version", - DPI_ERR_ORACLE_DB_TOO_OLD, conn->versionInfo.versionNum, - conn->versionInfo.releaseNum, minVersionNum, minReleaseNum); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiUtils__clearMemory() [INTERNAL] -// Method for clearing memory that will not be optimised away by the -// compiler. Simple use of memset() can be optimised away. This routine makes -// use of a volatile pointer which most compilers will avoid optimising away, -// even if the pointer appears to be unused after the call. -//----------------------------------------------------------------------------- -void dpiUtils__clearMemory(void *ptr, size_t length) -{ - volatile unsigned char *temp = (unsigned char *) ptr; - - while (length--) - *temp++ = '\0'; -} - - -//----------------------------------------------------------------------------- -// dpiUtils__freeMemory() [INTERNAL] -// Method for allocating memory which permits tracing and populates the error -// structure in the event of a memory allocation failure. -//----------------------------------------------------------------------------- -void dpiUtils__freeMemory(void *ptr) -{ - if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM) - dpiDebug__print("freed ptr at %p\n", ptr); - free(ptr); -} - - -//----------------------------------------------------------------------------- -// dpiUtils__getAttrStringWithDup() [INTERNAL] -// Get the string attribute from the OCI and duplicate its contents. -//----------------------------------------------------------------------------- -int dpiUtils__getAttrStringWithDup(const char *action, const void *ociHandle, - uint32_t ociHandleType, uint32_t ociAttribute, const char **value, - uint32_t *valueLength, dpiError *error) -{ - char *source, *temp; - - if (dpiOci__attrGet(ociHandle, ociHandleType, (void*) &source, - valueLength, ociAttribute, action, error) < 0) - return DPI_FAILURE; - if (dpiUtils__allocateMemory(1, *valueLength, 0, action, (void**) &temp, - error) < 0) - return DPI_FAILURE; - *value = (const char*) memcpy(temp, source, *valueLength); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiUtils__parseNumberString() [INTERNAL] -// Parse the contents of a string that is supposed to contain a number. The -// number is expected to be in the format (www.json.org): -// - optional negative sign (-) -// - any number of digits but at least one (0-9) -// - an optional decimal point (.) -// - any number of digits but at least one if decimal point specified (0-9) -// - an optional exponent indicator (e or E) -// - an optional exponent sign (+ or -) -// - any number of digits, but at least one if exponent specified (0-9) -// What is returned is an indication of whether the number is negative, what -// the index of the decimal point in the string is and the list of digits -// without the decimal point. Note that OCI doesn't support more than 40 digits -// so if there are more than this amount an error is raised. OCI doesn't -// support larger than 1e126 so check for this value and raise a numeric -// overflow error if found. OCI also doesn't support smaller than 1E-130 so -// check for this value as well and if smaller than that value simply return -// zero. -//----------------------------------------------------------------------------- -int dpiUtils__parseNumberString(const char *value, uint32_t valueLength, - uint16_t charsetId, int *isNegative, int16_t *decimalPointIndex, - uint8_t *numDigits, uint8_t *digits, dpiError *error) -{ - char convertedValue[DPI_NUMBER_AS_TEXT_CHARS], exponentDigits[4]; - uint8_t numExponentDigits, digit; - uint32_t convertedValueLength; - uint16_t *utf16chars, i; - int exponentIsNegative; - const char *endValue; - int16_t exponent; - - // empty strings are not valid numbers - if (valueLength == 0) - return dpiError__set(error, "zero length", DPI_ERR_INVALID_NUMBER); - - // strings longer than the maximum length of a valid number are also - // excluded - if ((charsetId == DPI_CHARSET_ID_UTF16 && - valueLength > DPI_NUMBER_AS_TEXT_CHARS * 2) || - (charsetId != DPI_CHARSET_ID_UTF16 && - valueLength > DPI_NUMBER_AS_TEXT_CHARS)) - return dpiError__set(error, "check length", - DPI_ERR_NUMBER_STRING_TOO_LONG); - - // if value is encoded in UTF-16, convert to single byte encoding first - // check for values that cannot be encoded in a single byte and are - // obviously not part of a valid numeric string - // also verify maximum length of number - if (charsetId == DPI_CHARSET_ID_UTF16) { - utf16chars = (uint16_t*) value; - convertedValue[0] = '\0'; - convertedValueLength = valueLength / 2; - for (i = 0; i < convertedValueLength; i++) { - if (*utf16chars > 127) - return dpiError__set(error, "convert from UTF-16", - DPI_ERR_INVALID_NUMBER); - convertedValue[i] = (char) *utf16chars++; - } - value = convertedValue; - valueLength = convertedValueLength; - } - - // see if first character is a minus sign (number is negative) - endValue = value + valueLength; - *isNegative = (*value == '-'); - if (*isNegative) - value++; - - // scan for digits until the decimal point or exponent indicator is found - *numDigits = 0; - while (value < endValue) { - if (*value == '.' || *value == 'e' || *value == 'E') - break; - if (*value < '0' || *value > '9') - return dpiError__set(error, "check digits before decimal point", - DPI_ERR_INVALID_NUMBER); - digit = (uint8_t) (*value++ - '0'); - if (digit == 0 && *numDigits == 0) - continue; - *digits++ = digit; - (*numDigits)++; - } - *decimalPointIndex = *numDigits; - - // scan for digits following the decimal point, if applicable - if (value < endValue && *value == '.') { - value++; - while (value < endValue) { - if (*value == 'e' || *value == 'E') - break; - if (*value < '0' || *value > '9') - return dpiError__set(error, "check digits after decimal point", - DPI_ERR_INVALID_NUMBER); - digit = (uint8_t) (*value++ - '0'); - if (digit == 0 && *numDigits == 0) { - (*decimalPointIndex)--; - continue; - } - *digits++ = digit; - (*numDigits)++; - } - } - - // handle exponent, if applicable - if (value < endValue && (*value == 'e' || *value == 'E')) { - value++; - exponentIsNegative = 0; - numExponentDigits = 0; - if (value < endValue && (*value == '+' || *value == '-')) { - exponentIsNegative = (*value == '-'); - value++; - } - while (value < endValue) { - if (*value < '0' || *value > '9') - return dpiError__set(error, "check digits in exponent", - DPI_ERR_INVALID_NUMBER); - if (numExponentDigits == 3) - return dpiError__set(error, "check exponent digits > 3", - DPI_ERR_NOT_SUPPORTED); - exponentDigits[numExponentDigits] = *value++; - numExponentDigits++; - } - if (numExponentDigits == 0) - return dpiError__set(error, "no digits in exponent", - DPI_ERR_INVALID_NUMBER); - exponentDigits[numExponentDigits] = '\0'; - exponent = (int16_t) strtol(exponentDigits, NULL, 10); - if (exponentIsNegative) - exponent = -exponent; - *decimalPointIndex += exponent; - } - - // if there is anything left in the string, that indicates an invalid - // number as well - if (value < endValue) - return dpiError__set(error, "check string used", - DPI_ERR_INVALID_NUMBER); - - // strip trailing zeroes - digits--; - while (*numDigits > 0 && *digits-- == 0) - (*numDigits)--; - - // values must be less than 1e126 and greater than 1e-129; the number of - // digits also cannot exceed the maximum precision of Oracle numbers - if (*numDigits > DPI_NUMBER_MAX_DIGITS || *decimalPointIndex > 126 || - *decimalPointIndex < -129) { - return dpiError__set(error, "check value can be represented", - DPI_ERR_NUMBER_NO_REPR); - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiUtils__parseOracleNumber() [INTERNAL] -// Parse the contents of an Oracle number and return its constituent parts -// so that a string can be generated from it easily. -//----------------------------------------------------------------------------- -int dpiUtils__parseOracleNumber(void *oracleValue, int *isNegative, - int16_t *decimalPointIndex, uint8_t *numDigits, uint8_t *digits, - dpiError *error) -{ - uint8_t *source, length, i, byte, digit; - int8_t ociExponent; - - // the first byte of the structure is a length byte which includes the - // exponent and the mantissa bytes - source = (uint8_t*) oracleValue; - length = *source++ - 1; - - // a mantissa length longer than 20 signals corruption of some kind - if (length > 20) - return dpiError__set(error, "check mantissa length", - DPI_ERR_INVALID_OCI_NUMBER); - - // the second byte of the structure is the exponent - // positive numbers have the highest order bit set whereas negative numbers - // have the highest order bit cleared and the bits inverted - ociExponent = (int8_t) *source++; - *isNegative = (ociExponent & 0x80) ? 0 : 1; - if (*isNegative) - ociExponent = ~ociExponent; - ociExponent -= 193; - *decimalPointIndex = ociExponent * 2 + 2; - - // a mantissa length of 0 implies a value of 0 (if positive) - // or -1e126 (if negative) - if (length == 0) { - if (*isNegative) { - *digits = 1; - *decimalPointIndex = 127; - } - else { - *decimalPointIndex = 1; - *digits = 0; - } - *numDigits = 1; - return DPI_SUCCESS; - } - - // check for the trailing 102 byte for negative numbers and if present, - // reduce the number of mantissa digits - if (*isNegative && source[length - 1] == 102) - length--; - - // process the mantissa which are the remaining bytes - // each mantissa byte is a base-100 digit - *numDigits = length * 2; - for (i = 0; i < length; i++) { - byte = *source++; - - // positive numbers have 1 added to them; negative numbers are - // subtracted from the value 101 - if (*isNegative) - byte = 101 - byte; - else byte--; - - // process the first digit; leading zeroes are ignored - digit = (uint8_t) (byte / 10); - if (digit == 0 && i == 0) { - (*numDigits)--; - (*decimalPointIndex)--; - } else if (digit == 10) { - (*numDigits)++; - (*decimalPointIndex)++; - *digits++ = 1; - *digits++ = 0; - } else *digits++ = digit; - - // process the second digit; trailing zeroes are ignored - digit = byte % 10; - if (digit == 0 && i == length - 1) - (*numDigits)--; - else *digits++ = digit; - - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiUtils__setAttributesFromCommonCreateParams() [INTERNAL] -// Set the attributes on the authorization info structure or session handle -// using the specified parameters. -//----------------------------------------------------------------------------- -int dpiUtils__setAttributesFromCommonCreateParams(void *handle, - uint32_t handleType, const dpiCommonCreateParams *params, - dpiError *error) -{ - uint32_t driverNameLength; - const char *driverName; - - if (params->driverName && params->driverNameLength > 0) { - driverName = params->driverName; - driverNameLength = params->driverNameLength; - } else { - driverName = DPI_DEFAULT_DRIVER_NAME; - driverNameLength = (uint32_t) strlen(driverName); - } - if (driverName && driverNameLength > 0 && dpiOci__attrSet(handle, - handleType, (void*) driverName, driverNameLength, - DPI_OCI_ATTR_DRIVER_NAME, "set driver name", error) < 0) - return DPI_FAILURE; - if (params->edition && params->editionLength > 0 && - dpiOci__attrSet(handle, handleType, - (void*) params->edition, params->editionLength, - DPI_OCI_ATTR_EDITION, "set edition", error) < 0) - return DPI_FAILURE; - - return DPI_SUCCESS; -} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiVar.c b/vendor/github.com/godror/godror/odpi/src/dpiVar.c deleted file mode 100644 index d8cde787c64..00000000000 --- a/vendor/github.com/godror/godror/odpi/src/dpiVar.c +++ /dev/null @@ -1,1813 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -// This program is free software: you can modify it and/or redistribute it -// under the terms of: -// -// (i) the Universal Permissive License v 1.0 or at your option, any -// later version (http://oss.oracle.com/licenses/upl); and/or -// -// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// dpiVar.c -// Implementation of variables. -//----------------------------------------------------------------------------- - -#include "dpiImpl.h" - -// forward declarations of internal functions only used in this file -static int dpiVar__initBuffer(dpiVar *var, dpiVarBuffer *buffer, - dpiError *error); -static int dpiVar__setBytesFromDynamicBytes(dpiBytes *bytes, - dpiDynamicBytes *dynBytes, dpiError *error); -static int dpiVar__setBytesFromLob(dpiBytes *bytes, dpiDynamicBytes *dynBytes, - dpiLob *lob, dpiError *error); -static int dpiVar__setFromBytes(dpiVar *var, uint32_t pos, const char *value, - uint32_t valueLength, dpiError *error); -static int dpiVar__setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob, - dpiError *error); -static int dpiVar__setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj, - dpiError *error); -static int dpiVar__setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid, - dpiError *error); -static int dpiVar__setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt, - dpiError *error); -static int dpiVar__validateTypes(const dpiOracleType *oracleType, - dpiNativeTypeNum nativeTypeNum, dpiError *error); - - -//----------------------------------------------------------------------------- -// dpiVar__allocate() [INTERNAL] -// Create a new variable object and return it. In case of error NULL is -// returned. -//----------------------------------------------------------------------------- -int dpiVar__allocate(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, - dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, - int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, - dpiData **data, dpiError *error) -{ - const dpiOracleType *type; - uint32_t sizeInBytes; - dpiVar *tempVar; - - // validate arguments - *var = NULL; - type = dpiOracleType__getFromNum(oracleTypeNum, error); - if (!type) - return DPI_FAILURE; - if (maxArraySize == 0) - return dpiError__set(error, "check max array size", - DPI_ERR_ARRAY_SIZE_ZERO); - if (isArray && !type->canBeInArray) - return dpiError__set(error, "check can be in array", - DPI_ERR_NOT_SUPPORTED); - if (oracleTypeNum == DPI_ORACLE_TYPE_BOOLEAN && - dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 1, - error) < 0) - return DPI_FAILURE; - if (nativeTypeNum != type->defaultNativeTypeNum) { - if (dpiVar__validateTypes(type, nativeTypeNum, error) < 0) - return DPI_FAILURE; - } - - // calculate size in bytes - if (size == 0) - size = 1; - if (type->sizeInBytes) - sizeInBytes = type->sizeInBytes; - else if (sizeIsBytes || !type->isCharacterData) - sizeInBytes = size; - else if (type->charsetForm == DPI_SQLCS_IMPLICIT) - sizeInBytes = size * conn->env->maxBytesPerCharacter; - else sizeInBytes = size * conn->env->nmaxBytesPerCharacter; - - // allocate memory for variable type - if (dpiGen__allocate(DPI_HTYPE_VAR, conn->env, (void**) &tempVar, - error) < 0) - return DPI_FAILURE; - - // basic initialization - tempVar->buffer.maxArraySize = maxArraySize; - if (!isArray) - tempVar->buffer.actualArraySize = maxArraySize; - tempVar->sizeInBytes = sizeInBytes; - if (sizeInBytes > DPI_MAX_BASIC_BUFFER_SIZE) { - tempVar->sizeInBytes = 0; - tempVar->isDynamic = 1; - tempVar->requiresPreFetch = 1; - } - tempVar->type = type; - tempVar->nativeTypeNum = nativeTypeNum; - tempVar->isArray = isArray; - dpiGen__setRefCount(conn, error, 1); - tempVar->conn = conn; - if (objType) { - if (dpiGen__checkHandle(objType, DPI_HTYPE_OBJECT_TYPE, - "check object type", error) < 0) { - dpiVar__free(tempVar, error); - return DPI_FAILURE; - } - dpiGen__setRefCount(objType, error, 1); - tempVar->objectType = objType; - } - - // allocate the data for the variable - if (dpiVar__initBuffer(tempVar, &tempVar->buffer, error) < 0) { - dpiVar__free(tempVar, error); - return DPI_FAILURE; - } - - *var = tempVar; - *data = tempVar->buffer.externalData; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__allocateChunks() [INTERNAL] -// Allocate more chunks for handling dynamic bytes. -//----------------------------------------------------------------------------- -static int dpiVar__allocateChunks(dpiDynamicBytes *dynBytes, dpiError *error) -{ - dpiDynamicBytesChunk *chunks; - uint32_t allocatedChunks; - - allocatedChunks = dynBytes->allocatedChunks + 8; - if (dpiUtils__allocateMemory(allocatedChunks, sizeof(dpiDynamicBytesChunk), - 1, "allocate chunks", (void**) &chunks, error) < 0) - return DPI_FAILURE; - if (dynBytes->chunks) { - memcpy(chunks, dynBytes->chunks, - dynBytes->numChunks * sizeof(dpiDynamicBytesChunk)); - dpiUtils__freeMemory(dynBytes->chunks); - } - dynBytes->chunks = chunks; - dynBytes->allocatedChunks = allocatedChunks; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__allocateDynamicBytes() [INTERNAL] -// Allocate space in the dynamic bytes structure for the specified number of -// bytes. When complete, there will be exactly one allocated chunk of the -// specified size or greater in the dynamic bytes structure. -//----------------------------------------------------------------------------- -static int dpiVar__allocateDynamicBytes(dpiDynamicBytes *dynBytes, - uint32_t size, dpiError *error) -{ - // if an error occurs, none of the original space is valid - dynBytes->numChunks = 0; - - // if there are no chunks at all, make sure some exist - if (dynBytes->allocatedChunks == 0 && - dpiVar__allocateChunks(dynBytes, error) < 0) - return DPI_FAILURE; - - // at this point there should be 0 or 1 chunks as any retrieval that - // resulted in multiple chunks would have been consolidated already - // make sure that chunk has enough space in it - if (size > dynBytes->chunks->allocatedLength) { - if (dynBytes->chunks->ptr) - dpiUtils__freeMemory(dynBytes->chunks->ptr); - dynBytes->chunks->allocatedLength = - (size + DPI_DYNAMIC_BYTES_CHUNK_SIZE - 1) & - ~(DPI_DYNAMIC_BYTES_CHUNK_SIZE - 1); - if (dpiUtils__allocateMemory(1, dynBytes->chunks->allocatedLength, 0, - "allocate chunk", (void**) &dynBytes->chunks->ptr, error) < 0) - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__assignCallbackBuffer() [INTERNAL] -// Assign callback pointers during OCI statement execution. This is used with -// the callack functions used for dynamic binding during DML returning -// statement execution. -//----------------------------------------------------------------------------- -static void dpiVar__assignCallbackBuffer(dpiVar *var, dpiVarBuffer *buffer, - uint32_t index, void **bufpp) -{ - switch (var->type->oracleTypeNum) { - case DPI_ORACLE_TYPE_TIMESTAMP: - case DPI_ORACLE_TYPE_TIMESTAMP_TZ: - case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: - *bufpp = buffer->data.asTimestamp[index]; - break; - case DPI_ORACLE_TYPE_INTERVAL_DS: - case DPI_ORACLE_TYPE_INTERVAL_YM: - *bufpp = buffer->data.asInterval[index]; - break; - case DPI_ORACLE_TYPE_CLOB: - case DPI_ORACLE_TYPE_BLOB: - case DPI_ORACLE_TYPE_NCLOB: - case DPI_ORACLE_TYPE_BFILE: - *bufpp = buffer->data.asLobLocator[index]; - break; - case DPI_ORACLE_TYPE_ROWID: - *bufpp = buffer->data.asRowid[index]; - break; - case DPI_ORACLE_TYPE_STMT: - *bufpp = buffer->data.asStmt[index]; - break; - default: - *bufpp = buffer->data.asBytes + index * var->sizeInBytes; - break; - } -} - - -//----------------------------------------------------------------------------- -// dpiVar__checkArraySize() [INTERNAL] -// Verifies that the array size has not been exceeded. -//----------------------------------------------------------------------------- -static int dpiVar__checkArraySize(dpiVar *var, uint32_t pos, - const char *fnName, dpiError *error) -{ - if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, fnName, error) < 0) - return DPI_FAILURE; - if (pos >= var->buffer.maxArraySize) - return dpiError__set(error, "check array size", - DPI_ERR_INVALID_ARRAY_POSITION, pos, - var->buffer.maxArraySize); - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__convertToLob() [INTERNAL] -// Convert the variable from using dynamic bytes for a long string to using a -// LOB instead. This is needed for PL/SQL which cannot handle more than 32K -// without the use of a LOB. -//----------------------------------------------------------------------------- -int dpiVar__convertToLob(dpiVar *var, dpiError *error) -{ - dpiDynamicBytes *dynBytes; - dpiLob *lob; - uint32_t i; - - // change type based on the original Oracle type - if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_RAW || - var->type->oracleTypeNum == DPI_ORACLE_TYPE_LONG_RAW) - var->type = dpiOracleType__getFromNum(DPI_ORACLE_TYPE_BLOB, error); - else if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_NCHAR) - var->type = dpiOracleType__getFromNum(DPI_ORACLE_TYPE_NCLOB, - error); - else var->type = dpiOracleType__getFromNum(DPI_ORACLE_TYPE_CLOB, - error); - - // adjust attributes and re-initialize buffers - // the dynamic bytes structures will not be removed - var->sizeInBytes = var->type->sizeInBytes; - var->isDynamic = 0; - if (dpiVar__initBuffer(var, &var->buffer, error) < 0) - return DPI_FAILURE; - - // copy any values already set - for (i = 0; i < var->buffer.maxArraySize; i++) { - dynBytes = &var->buffer.dynamicBytes[i]; - lob = var->buffer.references[i].asLOB; - if (dynBytes->numChunks == 0) - continue; - if (dpiLob__setFromBytes(lob, dynBytes->chunks->ptr, - dynBytes->chunks->length, error) < 0) - return DPI_FAILURE; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__copyData() [INTERNAL] -// Copy the data from the source to the target variable at the given array -// position. -//----------------------------------------------------------------------------- -int dpiVar__copyData(dpiVar *var, uint32_t pos, dpiData *sourceData, - dpiError *error) -{ - dpiData *targetData = &var->buffer.externalData[pos]; - - // handle null case - targetData->isNull = sourceData->isNull; - if (sourceData->isNull) - return DPI_SUCCESS; - - // handle copying of value from source to target - switch (var->nativeTypeNum) { - case DPI_NATIVE_TYPE_BYTES: - return dpiVar__setFromBytes(var, pos, - sourceData->value.asBytes.ptr, - sourceData->value.asBytes.length, error); - case DPI_NATIVE_TYPE_LOB: - return dpiVar__setFromLob(var, pos, sourceData->value.asLOB, - error); - case DPI_NATIVE_TYPE_OBJECT: - return dpiVar__setFromObject(var, pos, sourceData->value.asObject, - error); - case DPI_NATIVE_TYPE_STMT: - return dpiVar__setFromStmt(var, pos, sourceData->value.asStmt, - error); - case DPI_NATIVE_TYPE_ROWID: - return dpiVar__setFromRowid(var, pos, sourceData->value.asRowid, - error); - default: - memcpy(targetData, sourceData, sizeof(dpiData)); - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__defineCallback() [INTERNAL] -// Callback which runs during OCI statement execution and allocates the -// buffers required as well as provides that information to the OCI. This is -// intended for handling string and raw columns for which the size is unknown. -// These include LONG, LONG RAW and retrieving CLOB and BLOB as bytes, rather -// than use the LOB API. -//----------------------------------------------------------------------------- -int32_t dpiVar__defineCallback(dpiVar *var, UNUSED void *defnp, uint32_t iter, - void **bufpp, uint32_t **alenpp, UNUSED uint8_t *piecep, void **indpp, - uint16_t **rcodepp) -{ - dpiDynamicBytesChunk *chunk; - dpiDynamicBytes *bytes; - - // allocate more chunks, if necessary - bytes = &var->buffer.dynamicBytes[iter]; - if (bytes->numChunks == bytes->allocatedChunks && - dpiVar__allocateChunks(bytes, var->error) < 0) - return DPI_OCI_ERROR; - - // allocate memory for the chunk, if needed - chunk = &bytes->chunks[bytes->numChunks]; - if (!chunk->ptr) { - chunk->allocatedLength = DPI_DYNAMIC_BYTES_CHUNK_SIZE; - if (dpiUtils__allocateMemory(1, chunk->allocatedLength, 0, - "allocate chunk", (void**) &chunk->ptr, var->error) < 0) - return DPI_OCI_ERROR; - } - - // return chunk to OCI - bytes->numChunks++; - chunk->length = chunk->allocatedLength; - *bufpp = chunk->ptr; - *alenpp = &chunk->length; - *indpp = &(var->buffer.indicator[iter]); - *rcodepp = NULL; - return DPI_OCI_CONTINUE; -} - - -//----------------------------------------------------------------------------- -// dpiVar__extendedPreFetch() [INTERNAL] -// Perform any necessary actions prior to fetching data. -//----------------------------------------------------------------------------- -int dpiVar__extendedPreFetch(dpiVar *var, dpiVarBuffer *buffer, - dpiError *error) -{ - dpiRowid *rowid; - dpiData *data; - dpiStmt *stmt; - dpiLob *lob; - uint32_t i; - - if (var->isDynamic) { - for (i = 0; i < buffer->maxArraySize; i++) - buffer->dynamicBytes[i].numChunks = 0; - return DPI_SUCCESS; - } - - switch (var->type->oracleTypeNum) { - case DPI_ORACLE_TYPE_STMT: - for (i = 0; i < buffer->maxArraySize; i++) { - data = &buffer->externalData[i]; - if (buffer->references[i].asStmt) { - dpiGen__setRefCount(buffer->references[i].asStmt, - error, -1); - buffer->references[i].asStmt = NULL; - } - buffer->data.asStmt[i] = NULL; - data->value.asStmt = NULL; - if (dpiStmt__allocate(var->conn, 0, &stmt, error) < 0) - return DPI_FAILURE; - if (dpiOci__handleAlloc(var->env->handle, &stmt->handle, - DPI_OCI_HTYPE_STMT, "allocate statement", error) < 0) { - dpiStmt__free(stmt, error); - return DPI_FAILURE; - } - if (dpiHandleList__addHandle(var->conn->openStmts, stmt, - &stmt->openSlotNum, error) < 0) { - dpiOci__handleFree(stmt->handle, DPI_OCI_HTYPE_STMT); - stmt->handle = NULL; - dpiStmt__free(stmt, error); - return DPI_FAILURE; - } - buffer->references[i].asStmt = stmt; - stmt->isOwned = 1; - buffer->data.asStmt[i] = stmt->handle; - data->value.asStmt = stmt; - } - break; - case DPI_ORACLE_TYPE_CLOB: - case DPI_ORACLE_TYPE_BLOB: - case DPI_ORACLE_TYPE_NCLOB: - case DPI_ORACLE_TYPE_BFILE: - for (i = 0; i < buffer->maxArraySize; i++) { - data = &buffer->externalData[i]; - if (buffer->references[i].asLOB) { - dpiGen__setRefCount(buffer->references[i].asLOB, - error, -1); - buffer->references[i].asLOB = NULL; - } - buffer->data.asLobLocator[i] = NULL; - data->value.asLOB = NULL; - if (dpiLob__allocate(var->conn, var->type, &lob, error) < 0) - return DPI_FAILURE; - buffer->references[i].asLOB = lob; - buffer->data.asLobLocator[i] = lob->locator; - data->value.asLOB = lob; - if (buffer->dynamicBytes && - dpiOci__lobCreateTemporary(lob, error) < 0) - return DPI_FAILURE; - } - break; - case DPI_ORACLE_TYPE_ROWID: - for (i = 0; i < buffer->maxArraySize; i++) { - data = &buffer->externalData[i]; - if (buffer->references[i].asRowid) { - dpiGen__setRefCount(buffer->references[i].asRowid, - error, -1); - buffer->references[i].asRowid = NULL; - } - buffer->data.asRowid[i] = NULL; - data->value.asRowid = NULL; - if (dpiRowid__allocate(var->conn, &rowid, error) < 0) - return DPI_FAILURE; - buffer->references[i].asRowid = rowid; - buffer->data.asRowid[i] = rowid->handle; - data->value.asRowid = rowid; - } - break; - case DPI_ORACLE_TYPE_OBJECT: - for (i = 0; i < buffer->maxArraySize; i++) { - data = &buffer->externalData[i]; - if (buffer->references[i].asObject) { - dpiGen__setRefCount(buffer->references[i].asObject, - error, -1); - buffer->references[i].asObject = NULL; - } - buffer->data.asObject[i] = NULL; - buffer->objectIndicator[i] = NULL; - data->value.asObject = NULL; - } - break; - default: - break; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__finalizeBuffer() [INTERNAL] -// Finalize buffer used for passing data to/from Oracle. -//----------------------------------------------------------------------------- -static void dpiVar__finalizeBuffer(dpiVar *var, dpiVarBuffer *buffer, - dpiError *error) -{ - dpiDynamicBytes *dynBytes; - uint32_t i, j; - - // free any descriptors that were created - switch (var->type->oracleTypeNum) { - case DPI_ORACLE_TYPE_TIMESTAMP: - dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0], - DPI_OCI_DTYPE_TIMESTAMP); - break; - case DPI_ORACLE_TYPE_TIMESTAMP_TZ: - dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0], - DPI_OCI_DTYPE_TIMESTAMP_TZ); - break; - case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: - dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0], - DPI_OCI_DTYPE_TIMESTAMP_LTZ); - break; - case DPI_ORACLE_TYPE_INTERVAL_DS: - dpiOci__arrayDescriptorFree(&buffer->data.asInterval[0], - DPI_OCI_DTYPE_INTERVAL_DS); - break; - case DPI_ORACLE_TYPE_INTERVAL_YM: - dpiOci__arrayDescriptorFree(&buffer->data.asInterval[0], - DPI_OCI_DTYPE_INTERVAL_YM); - break; - default: - break; - } - - // release any references that were created - if (buffer->references) { - for (i = 0; i < buffer->maxArraySize; i++) { - if (buffer->references[i].asHandle) { - dpiGen__setRefCount(buffer->references[i].asHandle, error, -1); - buffer->references[i].asHandle = NULL; - } - } - dpiUtils__freeMemory(buffer->references); - buffer->references = NULL; - } - - // free any dynamic buffers - if (buffer->dynamicBytes) { - for (i = 0; i < buffer->maxArraySize; i++) { - dynBytes = &buffer->dynamicBytes[i]; - if (dynBytes->allocatedChunks > 0) { - for (j = 0; j < dynBytes->allocatedChunks; j++) { - if (dynBytes->chunks[j].ptr) { - dpiUtils__freeMemory(dynBytes->chunks[j].ptr); - dynBytes->chunks[j].ptr = NULL; - } - } - dpiUtils__freeMemory(dynBytes->chunks); - dynBytes->allocatedChunks = 0; - dynBytes->chunks = NULL; - } - } - dpiUtils__freeMemory(buffer->dynamicBytes); - buffer->dynamicBytes = NULL; - } - - // free other memory allocated - if (buffer->indicator) { - dpiUtils__freeMemory(buffer->indicator); - buffer->indicator = NULL; - } - if (buffer->returnCode) { - dpiUtils__freeMemory(buffer->returnCode); - buffer->returnCode = NULL; - } - if (buffer->actualLength16) { - dpiUtils__freeMemory(buffer->actualLength16); - buffer->actualLength16 = NULL; - } - if (buffer->actualLength32) { - dpiUtils__freeMemory(buffer->actualLength32); - buffer->actualLength32 = NULL; - } - if (buffer->externalData) { - dpiUtils__freeMemory(buffer->externalData); - buffer->externalData = NULL; - } - if (buffer->data.asRaw) { - dpiUtils__freeMemory(buffer->data.asRaw); - buffer->data.asRaw = NULL; - } - if (buffer->objectIndicator) { - dpiUtils__freeMemory(buffer->objectIndicator); - buffer->objectIndicator = NULL; - } - if (buffer->tempBuffer) { - dpiUtils__freeMemory(buffer->tempBuffer); - buffer->tempBuffer = NULL; - } -} - - -//----------------------------------------------------------------------------- -// dpiVar__free() [INTERNAL] -// Free the memory associated with the variable. -//----------------------------------------------------------------------------- -void dpiVar__free(dpiVar *var, dpiError *error) -{ - uint32_t i; - - dpiVar__finalizeBuffer(var, &var->buffer, error); - if (var->dynBindBuffers) { - for (i = 0; i < var->buffer.maxArraySize; i++) - dpiVar__finalizeBuffer(var, &var->dynBindBuffers[i], error); - dpiUtils__freeMemory(var->dynBindBuffers); - var->dynBindBuffers = NULL; - } - if (var->objectType) { - dpiGen__setRefCount(var->objectType, error, -1); - var->objectType = NULL; - } - if (var->conn) { - dpiGen__setRefCount(var->conn, error, -1); - var->conn = NULL; - } - dpiUtils__freeMemory(var); -} - - -//----------------------------------------------------------------------------- -// dpiVar__getValue() [PRIVATE] -// Returns the contents of the variable in the type specified, if possible. -//----------------------------------------------------------------------------- -int dpiVar__getValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, - int inFetch, dpiError *error) -{ - dpiOracleTypeNum oracleTypeNum; - dpiBytes *bytes; - dpiData *data; - uint32_t i; - - // check for dynamic binds first; if they exist, process them instead - if (var->dynBindBuffers && buffer == &var->buffer) { - buffer = &var->dynBindBuffers[pos]; - for (i = 0; i < buffer->maxArraySize; i++) { - if (dpiVar__getValue(var, buffer, i, inFetch, error) < 0) - return DPI_FAILURE; - } - return DPI_SUCCESS; - } - - // check for a NULL value; for objects the indicator is elsewhere - data = &buffer->externalData[pos]; - if (!buffer->objectIndicator) - data->isNull = (buffer->indicator[pos] == DPI_OCI_IND_NULL); - else if (buffer->objectIndicator[pos]) - data->isNull = (*((int16_t*) buffer->objectIndicator[pos]) == - DPI_OCI_IND_NULL); - else data->isNull = 1; - if (data->isNull) { - if (inFetch && var->objectType && var->objectType->isCollection) { - if (dpiOci__objectFree(var->env->handle, - buffer->data.asObject[pos], 1, error) < 0) - return DPI_FAILURE; - if (dpiOci__objectFree(var->env->handle, - buffer->objectIndicator[pos], 1, error) < 0) - return DPI_FAILURE; - } - return DPI_SUCCESS; - } - - // check return code for variable length data - if (buffer->returnCode) { - if (buffer->returnCode[pos] != 0) { - dpiError__set(error, "check return code", DPI_ERR_COLUMN_FETCH, - pos, buffer->returnCode[pos]); - error->buffer->code = buffer->returnCode[pos]; - return DPI_FAILURE; - } - } - - // for 11g, dynamic lengths are 32-bit whereas static lengths are 16-bit - if (buffer->actualLength16 && buffer->actualLength32) - buffer->actualLength16[pos] = (uint16_t) buffer->actualLength32[pos]; - - // transform the various types - oracleTypeNum = var->type->oracleTypeNum; - switch (var->nativeTypeNum) { - case DPI_NATIVE_TYPE_INT64: - case DPI_NATIVE_TYPE_UINT64: - switch (oracleTypeNum) { - case DPI_ORACLE_TYPE_NATIVE_INT: - data->value.asInt64 = buffer->data.asInt64[pos]; - return DPI_SUCCESS; - case DPI_ORACLE_TYPE_NATIVE_UINT: - data->value.asUint64 = buffer->data.asUint64[pos]; - return DPI_SUCCESS; - case DPI_ORACLE_TYPE_NUMBER: - if (var->nativeTypeNum == DPI_NATIVE_TYPE_INT64) - return dpiDataBuffer__fromOracleNumberAsInteger( - &data->value, error, - &buffer->data.asNumber[pos]); - return dpiDataBuffer__fromOracleNumberAsUnsignedInteger( - &data->value, error, &buffer->data.asNumber[pos]); - default: - break; - } - break; - case DPI_NATIVE_TYPE_DOUBLE: - switch (oracleTypeNum) { - case DPI_ORACLE_TYPE_NUMBER: - return dpiDataBuffer__fromOracleNumberAsDouble( - &data->value, error, &buffer->data.asNumber[pos]); - case DPI_ORACLE_TYPE_NATIVE_DOUBLE: - data->value.asDouble = buffer->data.asDouble[pos]; - return DPI_SUCCESS; - case DPI_ORACLE_TYPE_TIMESTAMP: - case DPI_ORACLE_TYPE_TIMESTAMP_TZ: - case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: - return dpiDataBuffer__fromOracleTimestampAsDouble( - &data->value, var->env, error, - buffer->data.asTimestamp[pos]); - default: - break; - } - break; - case DPI_NATIVE_TYPE_BYTES: - bytes = &data->value.asBytes; - switch (oracleTypeNum) { - case DPI_ORACLE_TYPE_VARCHAR: - case DPI_ORACLE_TYPE_NVARCHAR: - case DPI_ORACLE_TYPE_CHAR: - case DPI_ORACLE_TYPE_NCHAR: - case DPI_ORACLE_TYPE_ROWID: - case DPI_ORACLE_TYPE_RAW: - case DPI_ORACLE_TYPE_LONG_VARCHAR: - case DPI_ORACLE_TYPE_LONG_RAW: - if (buffer->dynamicBytes) - return dpiVar__setBytesFromDynamicBytes(bytes, - &buffer->dynamicBytes[pos], error); - if (buffer->actualLength16) - bytes->length = buffer->actualLength16[pos]; - else bytes->length = buffer->actualLength32[pos]; - return DPI_SUCCESS; - case DPI_ORACLE_TYPE_CLOB: - case DPI_ORACLE_TYPE_NCLOB: - case DPI_ORACLE_TYPE_BLOB: - case DPI_ORACLE_TYPE_BFILE: - return dpiVar__setBytesFromLob(bytes, - &buffer->dynamicBytes[pos], - buffer->references[pos].asLOB, error); - case DPI_ORACLE_TYPE_NUMBER: - bytes->length = DPI_NUMBER_AS_TEXT_CHARS; - if (var->env->charsetId == DPI_CHARSET_ID_UTF16) - bytes->length *= 2; - return dpiDataBuffer__fromOracleNumberAsText(&data->value, - var->env, error, &buffer->data.asNumber[pos]); - default: - break; - } - break; - case DPI_NATIVE_TYPE_FLOAT: - data->value.asFloat = buffer->data.asFloat[pos]; - break; - case DPI_NATIVE_TYPE_TIMESTAMP: - if (oracleTypeNum == DPI_ORACLE_TYPE_DATE) - return dpiDataBuffer__fromOracleDate(&data->value, - &buffer->data.asDate[pos]); - return dpiDataBuffer__fromOracleTimestamp(&data->value, var->env, - error, buffer->data.asTimestamp[pos], - oracleTypeNum != DPI_ORACLE_TYPE_TIMESTAMP); - break; - case DPI_NATIVE_TYPE_INTERVAL_DS: - return dpiDataBuffer__fromOracleIntervalDS(&data->value, var->env, - error, buffer->data.asInterval[pos]); - case DPI_NATIVE_TYPE_INTERVAL_YM: - return dpiDataBuffer__fromOracleIntervalYM(&data->value, var->env, - error, buffer->data.asInterval[pos]); - case DPI_NATIVE_TYPE_OBJECT: - data->value.asObject = NULL; - if (!buffer->references[pos].asObject) { - if (dpiObject__allocate(var->objectType, - buffer->data.asObject[pos], - buffer->objectIndicator[pos], NULL, - &buffer->references[pos].asObject, error) < 0) - return DPI_FAILURE; - if (inFetch && var->objectType->isCollection) - buffer->references[pos].asObject->freeIndicator = 1; - } - data->value.asObject = buffer->references[pos].asObject; - break; - case DPI_NATIVE_TYPE_STMT: - data->value.asStmt = buffer->references[pos].asStmt; - break; - case DPI_NATIVE_TYPE_BOOLEAN: - data->value.asBoolean = buffer->data.asBoolean[pos]; - break; - default: - break; - } - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__inBindCallback() [INTERNAL] -// Callback which runs during OCI statement execution and provides buffers to -// OCI for binding data IN. This is not used with DML returning so this method -// does nothing useful except satisfy OCI requirements. -//----------------------------------------------------------------------------- -int32_t dpiVar__inBindCallback(dpiVar *var, UNUSED void *bindp, - UNUSED uint32_t iter, UNUSED uint32_t index, void **bufpp, - uint32_t *alenp, uint8_t *piecep, void **indpp) -{ - dpiDynamicBytes *dynBytes; - - if (var->isDynamic) { - dynBytes = &var->buffer.dynamicBytes[iter]; - if (dynBytes->allocatedChunks == 0) { - *bufpp = NULL; - *alenp = 0; - } else { - *bufpp = dynBytes->chunks->ptr; - *alenp = dynBytes->chunks->length; - } - } else { - dpiVar__assignCallbackBuffer(var, &var->buffer, iter, bufpp); - if (var->buffer.actualLength16) - *alenp = var->buffer.actualLength16[iter]; - else if (var->buffer.actualLength32) - *alenp = var->buffer.actualLength32[iter]; - else *alenp = var->type->sizeInBytes; - } - *piecep = DPI_OCI_ONE_PIECE; - if (var->buffer.objectIndicator) - *indpp = var->buffer.objectIndicator[iter]; - else *indpp = &var->buffer.indicator[iter]; - return DPI_OCI_CONTINUE; -} - - -//----------------------------------------------------------------------------- -// dpiVar__initBuffer() [INTERNAL] -// Initialize buffers necessary for passing data to/from Oracle. -//----------------------------------------------------------------------------- -static int dpiVar__initBuffer(dpiVar *var, dpiVarBuffer *buffer, - dpiError *error) -{ - uint32_t i, tempBufferSize = 0; - unsigned long long dataLength; - dpiBytes *bytes; - - // initialize dynamic buffers for dynamic variables - if (var->isDynamic) { - if (dpiUtils__allocateMemory(buffer->maxArraySize, - sizeof(dpiDynamicBytes), 1, "allocate dynamic bytes", - (void**) &buffer->dynamicBytes, error) < 0) - return DPI_FAILURE; - - // for all other variables, validate length and allocate buffers - } else { - dataLength = (unsigned long long) buffer->maxArraySize * - (unsigned long long) var->sizeInBytes; - if (dataLength > INT_MAX) - return dpiError__set(error, "check max array size", - DPI_ERR_ARRAY_SIZE_TOO_BIG, buffer->maxArraySize); - if (dpiUtils__allocateMemory(1, (size_t) dataLength, 0, - "allocate buffer", (void**) &buffer->data.asRaw, error) < 0) - return DPI_FAILURE; - } - - // allocate the indicator for the variable - // ensure all values start out as null - if (!buffer->indicator) { - if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(int16_t), 0, - "allocate indicator", (void**) &buffer->indicator, error) < 0) - return DPI_FAILURE; - for (i = 0; i < buffer->maxArraySize; i++) - buffer->indicator[i] = DPI_OCI_IND_NULL; - } - - // allocate the actual length buffers for all but dynamic bytes which are - // handled differently; ensure actual length starts out as maximum value - if (!var->isDynamic && !buffer->actualLength16 && - !buffer->actualLength32) { - if (var->env->versionInfo->versionNum < 12 && buffer == &var->buffer) { - if (dpiUtils__allocateMemory(buffer->maxArraySize, - sizeof(uint16_t), 0, "allocate actual length", - (void**) &buffer->actualLength16, error) < 0) - return DPI_FAILURE; - for (i = 0; i < buffer->maxArraySize; i++) - buffer->actualLength16[i] = (uint16_t) var->sizeInBytes; - } else { - if (dpiUtils__allocateMemory(buffer->maxArraySize, - sizeof(uint32_t), 0, "allocate actual length", - (void**) &buffer->actualLength32, error) < 0) - return DPI_FAILURE; - for (i = 0; i < buffer->maxArraySize; i++) - buffer->actualLength32[i] = var->sizeInBytes; - } - } - - // for variable length data, also allocate the return code array - if (var->type->defaultNativeTypeNum == DPI_NATIVE_TYPE_BYTES && - !var->isDynamic && !buffer->returnCode) { - if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(uint16_t), 0, - "allocate return code", (void**) &buffer->returnCode, - error) < 0) - return DPI_FAILURE; - } - - // for numbers transferred to/from Oracle as bytes, allocate an additional - // set of buffers - if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_NUMBER && - var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { - tempBufferSize = DPI_NUMBER_AS_TEXT_CHARS; - if (var->env->charsetId == DPI_CHARSET_ID_UTF16) - tempBufferSize *= 2; - if (!buffer->tempBuffer) { - if (dpiUtils__allocateMemory(buffer->maxArraySize, tempBufferSize, - 0, "allocate temp buffer", (void**) &buffer->tempBuffer, - error) < 0) - return DPI_FAILURE; - } - } - - // allocate the external data array, if needed - if (!buffer->externalData) { - if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(dpiData), 1, - "allocate external data", (void**) &buffer->externalData, - error) < 0) - return DPI_FAILURE; - for (i = 0; i < buffer->maxArraySize; i++) - buffer->externalData[i].isNull = 1; - } - - // for bytes transfers, set encoding and pointers for small strings - if (var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { - for (i = 0; i < buffer->maxArraySize; i++) { - bytes = &buffer->externalData[i].value.asBytes; - if (var->type->charsetForm == DPI_SQLCS_IMPLICIT) - bytes->encoding = var->env->encoding; - else bytes->encoding = var->env->nencoding; - if (buffer->tempBuffer) - bytes->ptr = buffer->tempBuffer + i * tempBufferSize; - else if (!var->isDynamic && !buffer->dynamicBytes) - bytes->ptr = buffer->data.asBytes + i * var->sizeInBytes; - } - } - - // create array of references, if applicable - if (var->type->requiresPreFetch && !var->isDynamic) { - if (dpiUtils__allocateMemory(buffer->maxArraySize, - sizeof(dpiReferenceBuffer), 1, "allocate references", - (void**) &buffer->references, error) < 0) - return DPI_FAILURE; - } - - // perform variable specific initialization - switch (var->type->oracleTypeNum) { - case DPI_ORACLE_TYPE_TIMESTAMP: - return dpiOci__arrayDescriptorAlloc(var->env->handle, - &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP, - buffer->maxArraySize, error); - case DPI_ORACLE_TYPE_TIMESTAMP_TZ: - return dpiOci__arrayDescriptorAlloc(var->env->handle, - &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_TZ, - buffer->maxArraySize, error); - case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: - return dpiOci__arrayDescriptorAlloc(var->env->handle, - &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_LTZ, - buffer->maxArraySize, error); - case DPI_ORACLE_TYPE_INTERVAL_DS: - return dpiOci__arrayDescriptorAlloc(var->env->handle, - &buffer->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_DS, - buffer->maxArraySize, error); - case DPI_ORACLE_TYPE_INTERVAL_YM: - return dpiOci__arrayDescriptorAlloc(var->env->handle, - &buffer->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_YM, - buffer->maxArraySize, error); - break; - case DPI_ORACLE_TYPE_CLOB: - case DPI_ORACLE_TYPE_BLOB: - case DPI_ORACLE_TYPE_NCLOB: - case DPI_ORACLE_TYPE_BFILE: - case DPI_ORACLE_TYPE_STMT: - case DPI_ORACLE_TYPE_ROWID: - return dpiVar__extendedPreFetch(var, buffer, error); - case DPI_ORACLE_TYPE_OBJECT: - if (!var->objectType) - return dpiError__set(error, "check object type", - DPI_ERR_NO_OBJECT_TYPE); - if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(void*), - 0, "allocate object indicator", - (void**) &buffer->objectIndicator, error) < 0) - return DPI_FAILURE; - return dpiVar__extendedPreFetch(var, buffer, error); - default: - break; - } - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__outBindCallback() [INTERNAL] -// Callback which runs during OCI statement execution and allocates the -// buffers required as well as provides that information to the OCI. This is -// intended for use with DML returning only. -//----------------------------------------------------------------------------- -int32_t dpiVar__outBindCallback(dpiVar *var, void *bindp, UNUSED uint32_t iter, - uint32_t index, void **bufpp, uint32_t **alenpp, uint8_t *piecep, - void **indpp, uint16_t **rcodepp) -{ - dpiDynamicBytesChunk *chunk; - uint32_t numRowsReturned; - dpiDynamicBytes *bytes; - dpiVarBuffer *buffer; - - // determine which variable buffer to use - if (!var->dynBindBuffers) { - if (dpiUtils__allocateMemory(var->buffer.maxArraySize, - sizeof(dpiVarBuffer), 1, "allocate DML returning buffers", - (void**) &var->dynBindBuffers, var->error) < 0) - return DPI_FAILURE; - } - buffer = &var->dynBindBuffers[iter]; - - // special processing during first value returned for each iteration - if (index == 0) { - - // determine number of rows returned - if (dpiOci__attrGet(bindp, DPI_OCI_HTYPE_BIND, &numRowsReturned, 0, - DPI_OCI_ATTR_ROWS_RETURNED, "get rows returned", - var->error) < 0) - return DPI_OCI_ERROR; - - // reallocate buffers, if needed - if (numRowsReturned > buffer->maxArraySize) { - dpiVar__finalizeBuffer(var, buffer, var->error); - buffer->maxArraySize = numRowsReturned; - if (dpiVar__initBuffer(var, buffer, var->error) < 0) - return DPI_OCI_ERROR; - } - - // set actual array size to number of rows returned - buffer->actualArraySize = numRowsReturned; - - } - - // handle dynamically allocated strings (multiple piece) - // index is the current index into the chunks - if (var->isDynamic) { - - // allocate more chunks, if necessary - bytes = &buffer->dynamicBytes[index]; - if (*piecep == DPI_OCI_ONE_PIECE) - bytes->numChunks = 0; - if (bytes->numChunks == bytes->allocatedChunks && - dpiVar__allocateChunks(bytes, var->error) < 0) - return DPI_OCI_ERROR; - - // allocate memory for the chunk, if needed - chunk = &bytes->chunks[bytes->numChunks]; - if (!chunk->ptr) { - chunk->allocatedLength = DPI_DYNAMIC_BYTES_CHUNK_SIZE; - if (dpiUtils__allocateMemory(1, chunk->allocatedLength, 0, - "allocate chunk", (void**) &chunk->ptr, var->error) < 0) - return DPI_OCI_ERROR; - } - - // return chunk to OCI - bytes->numChunks++; - chunk->length = chunk->allocatedLength; - *bufpp = chunk->ptr; - *alenpp = &chunk->length; - *indpp = &(buffer->indicator[index]); - *rcodepp = NULL; - - // handle normally allocated variables (one piece) - } else { - - *piecep = DPI_OCI_ONE_PIECE; - if (dpiVar__setValue(var, buffer, index, &buffer->externalData[index], - var->error) < 0) - return DPI_OCI_ERROR; - dpiVar__assignCallbackBuffer(var, buffer, index, bufpp); - if (buffer->actualLength32 || buffer->actualLength16) { - if (!buffer->actualLength32) { - if (dpiUtils__allocateMemory(buffer->maxArraySize, - sizeof(uint32_t), 1, "allocate 11g lengths", - (void**) &buffer->actualLength32, var->error) < 0) - return DPI_OCI_ERROR; - } - buffer->actualLength32[index] = var->sizeInBytes; - *alenpp = &(buffer->actualLength32[index]); - } else if (*alenpp && var->type->sizeInBytes) - **alenpp = var->type->sizeInBytes; - if (buffer->objectIndicator) - *indpp = buffer->objectIndicator[index]; - else *indpp = &(buffer->indicator[index]); - if (buffer->returnCode) - *rcodepp = &buffer->returnCode[index]; - - } - - return DPI_OCI_CONTINUE; -} - - -//----------------------------------------------------------------------------- -// dpiVar__setBytesFromDynamicBytes() [PRIVATE] -// Set the pointer and length in the dpiBytes structure to the values -// retrieved from the database. At this point, if multiple chunks exist, they -// are combined into one. -//----------------------------------------------------------------------------- -static int dpiVar__setBytesFromDynamicBytes(dpiBytes *bytes, - dpiDynamicBytes *dynBytes, dpiError *error) -{ - uint32_t i, totalAllocatedLength; - - // if only one chunk is available, make use of it - if (dynBytes->numChunks == 1) { - bytes->ptr = dynBytes->chunks->ptr; - bytes->length = dynBytes->chunks->length; - return DPI_SUCCESS; - } - - // determine total allocated size of all chunks - totalAllocatedLength = 0; - for (i = 0; i < dynBytes->numChunks; i++) - totalAllocatedLength += dynBytes->chunks[i].allocatedLength; - - // allocate new memory consolidating all of the chunks - if (dpiUtils__allocateMemory(1, totalAllocatedLength, 0, - "allocate consolidated chunk", (void**) &bytes->ptr, error) < 0) - return DPI_FAILURE; - - // copy memory from chunks to consolidated chunk - bytes->length = 0; - for (i = 0; i < dynBytes->numChunks; i++) { - memcpy(bytes->ptr + bytes->length, dynBytes->chunks[i].ptr, - dynBytes->chunks[i].length); - bytes->length += dynBytes->chunks[i].length; - dpiUtils__freeMemory(dynBytes->chunks[i].ptr); - dynBytes->chunks[i].ptr = NULL; - dynBytes->chunks[i].length = 0; - dynBytes->chunks[i].allocatedLength = 0; - } - - // populate first chunk with consolidated information - dynBytes->numChunks = 1; - dynBytes->chunks->ptr = bytes->ptr; - dynBytes->chunks->length = bytes->length; - dynBytes->chunks->allocatedLength = totalAllocatedLength; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__setBytesFromLob() [PRIVATE] -// Populate the dynamic bytes structure with the data from the LOB and then -// populate the bytes structure. -//----------------------------------------------------------------------------- -static int dpiVar__setBytesFromLob(dpiBytes *bytes, dpiDynamicBytes *dynBytes, - dpiLob *lob, dpiError *error) -{ - uint64_t length, lengthInBytes, lengthReadInBytes; - - // determine length of LOB in bytes - if (dpiOci__lobGetLength2(lob, &length, error) < 0) - return DPI_FAILURE; - if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_CLOB) - lengthInBytes = length * lob->env->maxBytesPerCharacter; - else if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB) - lengthInBytes = length * lob->env->nmaxBytesPerCharacter; - else lengthInBytes = length; - - // ensure there is enough space to store the entire LOB value - if (lengthInBytes > UINT_MAX) - return dpiError__set(error, "check max length", DPI_ERR_NOT_SUPPORTED); - if (dpiVar__allocateDynamicBytes(dynBytes, (uint32_t) lengthInBytes, - error) < 0) - return DPI_FAILURE; - - // read data from the LOB - lengthReadInBytes = lengthInBytes; - if (length > 0 && dpiLob__readBytes(lob, 1, length, dynBytes->chunks->ptr, - &lengthReadInBytes, error) < 0) - return DPI_FAILURE; - - dynBytes->chunks->length = (uint32_t) lengthReadInBytes; - bytes->ptr = dynBytes->chunks->ptr; - bytes->length = dynBytes->chunks->length; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__setFromBytes() [PRIVATE] -// Set the value of the variable at the given array position from a byte -// string. The byte string is not retained in any way. A copy will be made into -// buffers allocated by ODPI-C. -//----------------------------------------------------------------------------- -static int dpiVar__setFromBytes(dpiVar *var, uint32_t pos, const char *value, - uint32_t valueLength, dpiError *error) -{ - dpiData *data = &var->buffer.externalData[pos]; - dpiDynamicBytes *dynBytes; - dpiBytes *bytes; - - // for internally used LOBs, write the data directly - if (var->buffer.references) { - data->isNull = 0; - return dpiLob__setFromBytes(var->buffer.references[pos].asLOB, value, - valueLength, error); - } - - // validate the target can accept the input - if ((var->buffer.tempBuffer && - var->env->charsetId == DPI_CHARSET_ID_UTF16 && - valueLength > DPI_NUMBER_AS_TEXT_CHARS * 2) || - (var->buffer.tempBuffer && - var->env->charsetId != DPI_CHARSET_ID_UTF16 && - valueLength > DPI_NUMBER_AS_TEXT_CHARS) || - (!var->buffer.dynamicBytes && !var->buffer.tempBuffer && - valueLength > var->sizeInBytes)) - return dpiError__set(error, "check source length", - DPI_ERR_BUFFER_SIZE_TOO_SMALL, var->sizeInBytes); - - // for dynamic bytes, allocate space as needed - bytes = &data->value.asBytes; - if (var->buffer.dynamicBytes) { - dynBytes = &var->buffer.dynamicBytes[pos]; - if (dpiVar__allocateDynamicBytes(dynBytes, valueLength, error) < 0) - return DPI_FAILURE; - if (valueLength > 0) - memcpy(dynBytes->chunks->ptr, value, valueLength); - dynBytes->numChunks = 1; - dynBytes->chunks->length = valueLength; - bytes->ptr = dynBytes->chunks->ptr; - bytes->length = valueLength; - - // for everything else, space has already been allocated - } else { - bytes->length = valueLength; - if (valueLength > 0) - memcpy(bytes->ptr, value, valueLength); - if (var->type->sizeInBytes == 0) { - if (var->buffer.actualLength32) - var->buffer.actualLength32[pos] = valueLength; - else if (var->buffer.actualLength16) - var->buffer.actualLength16[pos] = (uint16_t) valueLength; - } - if (var->buffer.returnCode) - var->buffer.returnCode[pos] = 0; - } - data->isNull = 0; - - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__setFromLob() [PRIVATE] -// Set the value of the variable at the given array position from a LOB. -// A reference to the LOB is retained by the variable. -//----------------------------------------------------------------------------- -static int dpiVar__setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob, - dpiError *error) -{ - dpiData *data; - - // validate the LOB object - if (dpiGen__checkHandle(lob, DPI_HTYPE_LOB, "check LOB", error) < 0) - return DPI_FAILURE; - - // mark the value as not null - data = &var->buffer.externalData[pos]; - data->isNull = 0; - - // if values are the same, nothing to do - if (var->buffer.references[pos].asLOB == lob) - return DPI_SUCCESS; - - // clear original value, if needed - if (var->buffer.references[pos].asLOB) { - dpiGen__setRefCount(var->buffer.references[pos].asLOB, error, -1); - var->buffer.references[pos].asLOB = NULL; - } - - // add reference to passed object - dpiGen__setRefCount(lob, error, 1); - var->buffer.references[pos].asLOB = lob; - var->buffer.data.asLobLocator[pos] = lob->locator; - data->value.asLOB = lob; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__setFromObject() [PRIVATE] -// Set the value of the variable at the given array position from an object. -// The variable and position are assumed to be valid at this point. A reference -// to the object is retained by the variable. -//----------------------------------------------------------------------------- -static int dpiVar__setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj, - dpiError *error) -{ - dpiData *data; - - // validate the object - if (dpiGen__checkHandle(obj, DPI_HTYPE_OBJECT, "check obj", error) < 0) - return DPI_FAILURE; - if (obj->type->tdo != var->objectType->tdo) - return dpiError__set(error, "check type", DPI_ERR_WRONG_TYPE, - obj->type->schemaLength, obj->type->schema, - obj->type->nameLength, obj->type->name, - var->objectType->schemaLength, var->objectType->schema, - var->objectType->nameLength, var->objectType->name); - - // mark the value as not null - data = &var->buffer.externalData[pos]; - data->isNull = 0; - - // if values are the same, nothing to do - if (var->buffer.references[pos].asObject == obj) - return DPI_SUCCESS; - - // clear original value, if needed - if (var->buffer.references[pos].asObject) { - dpiGen__setRefCount(var->buffer.references[pos].asObject, error, -1); - var->buffer.references[pos].asObject = NULL; - } - - // add reference to passed object - dpiGen__setRefCount(obj, error, 1); - var->buffer.references[pos].asObject = obj; - var->buffer.data.asObject[pos] = obj->instance; - var->buffer.objectIndicator[pos] = obj->indicator; - data->value.asObject = obj; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__setFromRowid() [PRIVATE] -// Set the value of the variable at the given array position from a rowid. -// A reference to the rowid is retained by the variable. -//----------------------------------------------------------------------------- -static int dpiVar__setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid, - dpiError *error) -{ - dpiData *data; - - // validate the rowid - if (dpiGen__checkHandle(rowid, DPI_HTYPE_ROWID, "check rowid", error) < 0) - return DPI_FAILURE; - - // mark the value as not null - data = &var->buffer.externalData[pos]; - data->isNull = 0; - - // if values are the same, nothing to do - if (var->buffer.references[pos].asRowid == rowid) - return DPI_SUCCESS; - - // clear original value, if needed - if (var->buffer.references[pos].asRowid) { - dpiGen__setRefCount(var->buffer.references[pos].asRowid, error, -1); - var->buffer.references[pos].asRowid = NULL; - } - - // add reference to passed object - dpiGen__setRefCount(rowid, error, 1); - var->buffer.references[pos].asRowid = rowid; - var->buffer.data.asRowid[pos] = rowid->handle; - data->value.asRowid = rowid; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__setFromStmt() [PRIVATE] -// Set the value of the variable at the given array position from a -// statement. A reference to the statement is retained by the variable. -//----------------------------------------------------------------------------- -static int dpiVar__setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt, - dpiError *error) -{ - dpiData *data; - uint32_t i; - - // validate the statement - if (dpiGen__checkHandle(stmt, DPI_HTYPE_STMT, "check stmt", error) < 0) - return DPI_FAILURE; - - // prevent attempts to bind a statement to itself - for (i = 0; i < stmt->numBindVars; i++) { - if (stmt->bindVars[i].var == var) - return dpiError__set(error, "bind to self", DPI_ERR_NOT_SUPPORTED); - } - - // mark the value as not null - data = &var->buffer.externalData[pos]; - data->isNull = 0; - - // if values are the same, nothing to do - if (var->buffer.references[pos].asStmt == stmt) - return DPI_SUCCESS; - - // clear original value, if needed - if (var->buffer.references[pos].asStmt) { - dpiGen__setRefCount(var->buffer.references[pos].asStmt, error, -1); - var->buffer.references[pos].asStmt = NULL; - } - - // add reference to passed object - dpiGen__setRefCount(stmt, error, 1); - var->buffer.references[pos].asStmt = stmt; - var->buffer.data.asStmt[pos] = stmt->handle; - data->value.asStmt = stmt; - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__setValue() [PRIVATE] -// Sets the contents of the variable using the type specified, if possible. -//----------------------------------------------------------------------------- -int dpiVar__setValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, - dpiData *data, dpiError *error) -{ - dpiOracleTypeNum oracleTypeNum; - dpiObject *obj; - - // if value is null, no need to proceed further - // however, when binding objects a value MUST be present or OCI will - // segfault! - if (data->isNull) { - buffer->indicator[pos] = DPI_OCI_IND_NULL; - if (buffer->objectIndicator && !buffer->data.asObject[pos]) { - if (dpiObject__allocate(var->objectType, NULL, NULL, NULL, &obj, - error) < 0) - return DPI_FAILURE; - buffer->references[pos].asObject = obj; - data->value.asObject = obj; - buffer->data.asObject[pos] = obj->instance; - buffer->objectIndicator[pos] = obj->indicator; - if (buffer->objectIndicator[pos]) - *((int16_t*) buffer->objectIndicator[pos]) = DPI_OCI_IND_NULL; - } - return DPI_SUCCESS; - } - - // transform the various types - buffer->indicator[pos] = DPI_OCI_IND_NOTNULL; - oracleTypeNum = var->type->oracleTypeNum; - switch (var->nativeTypeNum) { - case DPI_NATIVE_TYPE_INT64: - case DPI_NATIVE_TYPE_UINT64: - switch (oracleTypeNum) { - case DPI_ORACLE_TYPE_NATIVE_INT: - buffer->data.asInt64[pos] = data->value.asInt64; - return DPI_SUCCESS; - case DPI_ORACLE_TYPE_NATIVE_UINT: - buffer->data.asUint64[pos] = data->value.asUint64; - return DPI_SUCCESS; - case DPI_ORACLE_TYPE_NUMBER: - if (var->nativeTypeNum == DPI_NATIVE_TYPE_INT64) - return dpiDataBuffer__toOracleNumberFromInteger( - &data->value, error, - &buffer->data.asNumber[pos]); - return dpiDataBuffer__toOracleNumberFromUnsignedInteger( - &data->value, error, &buffer->data.asNumber[pos]); - default: - break; - } - break; - case DPI_NATIVE_TYPE_FLOAT: - buffer->data.asFloat[pos] = data->value.asFloat; - return DPI_SUCCESS; - case DPI_NATIVE_TYPE_DOUBLE: - switch (oracleTypeNum) { - case DPI_ORACLE_TYPE_NATIVE_DOUBLE: - buffer->data.asDouble[pos] = data->value.asDouble; - return DPI_SUCCESS; - case DPI_ORACLE_TYPE_NUMBER: - return dpiDataBuffer__toOracleNumberFromDouble( - &data->value, error, &buffer->data.asNumber[pos]); - case DPI_ORACLE_TYPE_DATE: - return dpiDataBuffer__toOracleDateFromDouble( - &data->value, var->env, error, - &buffer->data.asDate[pos]); - case DPI_ORACLE_TYPE_TIMESTAMP: - case DPI_ORACLE_TYPE_TIMESTAMP_TZ: - case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: - return dpiDataBuffer__toOracleTimestampFromDouble( - &data->value, var->env, error, - buffer->data.asTimestamp[pos]); - default: - break; - } - break; - case DPI_NATIVE_TYPE_BYTES: - if (oracleTypeNum == DPI_ORACLE_TYPE_NUMBER) - return dpiDataBuffer__toOracleNumberFromText(&data->value, - var->env, error, &buffer->data.asNumber[pos]); - if (buffer->actualLength32) - buffer->actualLength32[pos] = data->value.asBytes.length; - else if (buffer->actualLength16) - buffer->actualLength16[pos] = - (uint16_t) data->value.asBytes.length; - if (buffer->returnCode) - buffer->returnCode[pos] = 0; - break; - case DPI_NATIVE_TYPE_TIMESTAMP: - if (oracleTypeNum == DPI_ORACLE_TYPE_DATE) - return dpiDataBuffer__toOracleDate(&data->value, - &buffer->data.asDate[pos]); - else if (oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP) - return dpiDataBuffer__toOracleTimestamp(&data->value, - var->env, error, buffer->data.asTimestamp[pos], 0); - else if (oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_TZ || - oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_LTZ) - return dpiDataBuffer__toOracleTimestamp(&data->value, - var->env, error, buffer->data.asTimestamp[pos], 1); - break; - case DPI_NATIVE_TYPE_INTERVAL_DS: - return dpiDataBuffer__toOracleIntervalDS(&data->value, var->env, - error, buffer->data.asInterval[pos]); - case DPI_NATIVE_TYPE_INTERVAL_YM: - return dpiDataBuffer__toOracleIntervalYM(&data->value, var->env, - error, buffer->data.asInterval[pos]); - case DPI_NATIVE_TYPE_BOOLEAN: - buffer->data.asBoolean[pos] = data->value.asBoolean; - return DPI_SUCCESS; - default: - break; - } - return DPI_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// dpiVar__validateTypes() [PRIVATE] -// Validate that the Oracle type and the native type are compatible with -// each other when the native type is not already the default native type. -//----------------------------------------------------------------------------- -static int dpiVar__validateTypes(const dpiOracleType *oracleType, - dpiNativeTypeNum nativeTypeNum, dpiError *error) -{ - switch (oracleType->oracleTypeNum) { - case DPI_ORACLE_TYPE_DATE: - case DPI_ORACLE_TYPE_TIMESTAMP: - case DPI_ORACLE_TYPE_TIMESTAMP_TZ: - case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: - if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) - return DPI_SUCCESS; - break; - case DPI_ORACLE_TYPE_NUMBER: - if (nativeTypeNum == DPI_NATIVE_TYPE_INT64 || - nativeTypeNum == DPI_NATIVE_TYPE_UINT64 || - nativeTypeNum == DPI_NATIVE_TYPE_BYTES) - return DPI_SUCCESS; - break; - default: - break; - } - return dpiError__set(error, "validate types", DPI_ERR_UNHANDLED_CONVERSION, - oracleType->oracleTypeNum, nativeTypeNum); -} - - -//----------------------------------------------------------------------------- -// dpiVar_addRef() [PUBLIC] -// Add a reference to the variable. -//----------------------------------------------------------------------------- -int dpiVar_addRef(dpiVar *var) -{ - return dpiGen__addRef(var, DPI_HTYPE_VAR, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiVar_copyData() [PUBLIC] -// Copy the data from the source variable to the target variable at the given -// array position. The variables must use the same native type. If the -// variables contain variable length data, the source length must not exceed -// the target allocated memory. -//----------------------------------------------------------------------------- -int dpiVar_copyData(dpiVar *var, uint32_t pos, dpiVar *sourceVar, - uint32_t sourcePos) -{ - dpiData *sourceData; - dpiError error; - int status; - - if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - if (dpiGen__checkHandle(sourceVar, DPI_HTYPE_VAR, "check source var", - &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - if (sourcePos >= sourceVar->buffer.maxArraySize) { - dpiError__set(&error, "check source size", - DPI_ERR_INVALID_ARRAY_POSITION, sourcePos, - sourceVar->buffer.maxArraySize); - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - } - if (var->nativeTypeNum != sourceVar->nativeTypeNum) { - dpiError__set(&error, "check types match", DPI_ERR_NOT_SUPPORTED); - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - } - sourceData = &sourceVar->buffer.externalData[sourcePos]; - status = dpiVar__copyData(var, pos, sourceData, &error); - return dpiGen__endPublicFn(var, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiVar_getNumElementsInArray() [PUBLIC] -// Return the actual number of elements in the array. This value is only -// relevant if the variable is bound as an array. -//----------------------------------------------------------------------------- -int dpiVar_getNumElementsInArray(dpiVar *var, uint32_t *numElements) -{ - dpiError error; - - if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(var, numElements) - if (var->dynBindBuffers) - *numElements = var->dynBindBuffers->actualArraySize; - else *numElements = var->buffer.actualArraySize; - return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); -} - -//----------------------------------------------------------------------------- -// dpiVar_getReturnedData() [PUBLIC] -// Return a pointer to the array of dpiData structures allocated for the -// given row that have been returned by a DML returning statement. The number -// of returned rows is also provided. If the bind variable had no data -// returned, the number of rows returned will be 0 and the pointer to the array -// of dpiData structures will be NULL. This will also be the case if the -// variable was only bound IN or was not bound to a DML returning statement. -// There is no way to differentiate between the two. -//----------------------------------------------------------------------------- -int dpiVar_getReturnedData(dpiVar *var, uint32_t pos, uint32_t *numElements, - dpiData **data) -{ - dpiError error; - - if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(var, numElements) - DPI_CHECK_PTR_NOT_NULL(var, data) - if (var->dynBindBuffers) { - *numElements = var->dynBindBuffers[pos].actualArraySize; - *data = var->dynBindBuffers[pos].externalData; - } else { - *numElements = 0; - *data = NULL; - } - return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); -} - - - -//----------------------------------------------------------------------------- -// dpiVar_getSizeInBytes() [PUBLIC] -// Returns the size in bytes of the buffer allocated for the variable. -//----------------------------------------------------------------------------- -int dpiVar_getSizeInBytes(dpiVar *var, uint32_t *sizeInBytes) -{ - dpiError error; - - if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - DPI_CHECK_PTR_NOT_NULL(var, sizeInBytes) - *sizeInBytes = var->sizeInBytes; - return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); -} - - -//----------------------------------------------------------------------------- -// dpiVar_release() [PUBLIC] -// Release a reference to the variable. -//----------------------------------------------------------------------------- -int dpiVar_release(dpiVar *var) -{ - return dpiGen__release(var, DPI_HTYPE_VAR, __func__); -} - - -//----------------------------------------------------------------------------- -// dpiVar_setFromBytes() [PUBLIC] -// Set the value of the variable at the given array position from a byte -// string. Checks on the array position, the size of the string and the type of -// variable will be made. The byte string is not retained in any way. A copy -// will be made into buffers allocated by ODPI-C. -//----------------------------------------------------------------------------- -int dpiVar_setFromBytes(dpiVar *var, uint32_t pos, const char *value, - uint32_t valueLength) -{ - dpiError error; - int status; - - if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - DPI_CHECK_PTR_AND_LENGTH(var, value) - if (var->nativeTypeNum != DPI_NATIVE_TYPE_BYTES && - var->nativeTypeNum != DPI_NATIVE_TYPE_LOB) { - dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - } - if (valueLength > DPI_MAX_VAR_BUFFER_SIZE) { - dpiError__set(&error, "check buffer", DPI_ERR_BUFFER_SIZE_TOO_LARGE, - valueLength, DPI_MAX_VAR_BUFFER_SIZE); - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - } - status = dpiVar__setFromBytes(var, pos, value, valueLength, &error); - return dpiGen__endPublicFn(var, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiVar_setFromLob() [PUBLIC] -// Set the value of the variable at the given array position from a LOB. -// Checks on the array position and the validity of the passed handle. A -// reference to the LOB is retained by the variable. -//----------------------------------------------------------------------------- -int dpiVar_setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob) -{ - dpiError error; - int status; - - if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - if (var->nativeTypeNum != DPI_NATIVE_TYPE_LOB) { - dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - } - status = dpiVar__setFromLob(var, pos, lob, &error); - return dpiGen__endPublicFn(var, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiVar_setFromObject() [PUBLIC] -// Set the value of the variable at the given array position from an object. -// Checks on the array position and the validity of the passed handle. A -// reference to the object is retained by the variable. -//----------------------------------------------------------------------------- -int dpiVar_setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj) -{ - dpiError error; - int status; - - if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - if (var->nativeTypeNum != DPI_NATIVE_TYPE_OBJECT) { - dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - } - status = dpiVar__setFromObject(var, pos, obj, &error); - return dpiGen__endPublicFn(var, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiVar_setFromRowid() [PUBLIC] -// Set the value of the variable at the given array position from a rowid. -// Checks on the array position and the validity of the passed handle. A -// reference to the rowid is retained by the variable. -//----------------------------------------------------------------------------- -int dpiVar_setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid) -{ - dpiError error; - int status; - - if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - if (var->nativeTypeNum != DPI_NATIVE_TYPE_ROWID) { - dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - } - status = dpiVar__setFromRowid(var, pos, rowid, &error); - return dpiGen__endPublicFn(var, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiVar_setFromStmt() [PUBLIC] -// Set the value of the variable at the given array position from a -// statement. Checks on the array position and the validity of the passed -// handle. A reference to the statement is retained by the variable. -//----------------------------------------------------------------------------- -int dpiVar_setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt) -{ - dpiError error; - int status; - - if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - if (var->nativeTypeNum != DPI_NATIVE_TYPE_STMT) { - dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - } - status = dpiVar__setFromStmt(var, pos, stmt, &error); - return dpiGen__endPublicFn(var, status, &error); -} - - -//----------------------------------------------------------------------------- -// dpiVar_setNumElementsInArray() [PUBLIC] -// Set the number of elements in the array (different from the number of -// allocated elements). -//----------------------------------------------------------------------------- -int dpiVar_setNumElementsInArray(dpiVar *var, uint32_t numElements) -{ - dpiError error; - - if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, &error) < 0) - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - if (numElements > var->buffer.maxArraySize) { - dpiError__set(&error, "check num elements", - DPI_ERR_ARRAY_SIZE_TOO_SMALL, var->buffer.maxArraySize); - return dpiGen__endPublicFn(var, DPI_FAILURE, &error); - } - var->buffer.actualArraySize = numElements; - return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); -} diff --git a/vendor/github.com/h2non/filetype/.editorconfig b/vendor/github.com/h2non/filetype/.editorconfig new file mode 100644 index 00000000000..000dc0a7aa4 --- /dev/null +++ b/vendor/github.com/h2non/filetype/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = tabs +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/vendor/github.com/h2non/filetype/.gitignore b/vendor/github.com/h2non/filetype/.gitignore new file mode 100644 index 00000000000..6fefe6cce24 --- /dev/null +++ b/vendor/github.com/h2non/filetype/.gitignore @@ -0,0 +1,2 @@ +bin +.DS_Store diff --git a/vendor/github.com/h2non/filetype/.travis.yml b/vendor/github.com/h2non/filetype/.travis.yml new file mode 100644 index 00000000000..ed996a2aa92 --- /dev/null +++ b/vendor/github.com/h2non/filetype/.travis.yml @@ -0,0 +1,17 @@ +language: go + +go: + - "1.10" + - "1.11" + - "1.12" + - "1.13" + - "tip" + +before_install: + - go get -u -v golang.org/x/lint/golint + +script: + - diff -u <(echo -n) <(gofmt -s -d ./) + - diff -u <(echo -n) <(go vet ./...) + - diff -u <(echo -n) <(golint) + - go test -v -race ./... diff --git a/vendor/github.com/h2non/filetype/History.md b/vendor/github.com/h2non/filetype/History.md new file mode 100644 index 00000000000..ccb4014f785 --- /dev/null +++ b/vendor/github.com/h2non/filetype/History.md @@ -0,0 +1,128 @@ + +v1.0.10 / 2019-08-06 +==================== + + * Merge pull request #76 from lex-r/fix-matroska-detection + * fix: mkv and webm types detection + +v1.0.9 / 2019-07-25 +=================== + + * Merge pull request #75 from Trane9991/master + * add video/3gpp support + * fix: use proper iso file mime type + * feat: add iso image format + * Merge pull request #65 from Fentonz/master + * Merge pull request #70 from fanpei91/master + * add image/vnd.dwg to README + * add image/vnd.dwg support + * Added support for .iso files + +v1.0.8 / 2019-02-10 +=================== + + * refactor(images): heic -> heif + * feat(docs): add heif format + * Merge pull request #60 from rikonor/master + * add heif/heic support + * fix(docs): dicom -> dcm + * feat: add dicom type + * Merge pull request #58 from Fentonz/master + * Merge pull request #59 from kmanley/master + * fix example; related to h2non/filetype#43 + * Added DICOM type to archive + + +v1.0.7 / 2019-02-09 +=================== + + * Merge pull request #56 from akupila/wasm + * add wasm to readme + * detect wasm file type + +v1.0.6 / 2019-01-22 +=================== + + * Merge pull request #55 from ivanlemeshev/master + * Added ftypmp4v to MP4 matcher + * Merge pull request #54 from aofei/master + * chore: add support for Go modules + * feat: add support for AAC (audio/aac) + * Merge pull request #53 from lynxbyorion/check-for-docoments + * Added checks for documents. + * Merge pull request #51 from eriken/master + * fixed bad mime and import paths + * Merge pull request #50 from eriken/jpeg2000_support + * fix import paths + * jpeg2000 support + * Merge pull request #47 from Ma124/master + * Merge pull request #49 from amoore614/master + * more robust check for .mov files + * bugfix: reverse order of matcher key list so user registered matchers appear first + * bugfix: store ptr to MatcherKeys in case user registered matchers are used. + * update comment + * Bump buffer size to 8K to allow for more custom file matching + * refactor(readme): update package import path + * Merge pull request #48 from kumakichi/support_msooxml + * do not use v1 + * ok, master already changed travis + * add fixtures, but MatchReader may not work for some msooxml files, 4096 bytes maybe not enough + * support ms ooxml, #40 + * Fixed misspells + * fix(travis): use string notation for matrix items + * Merge pull request #42 from bruth/patch-2 + * refactor(travis): remove Go 1.6, add Go 1.10 + * Change maximum bytes required for detection + * Merge pull request #36 from yiiTT/patch-1 + * Add MP4 dash and additional ISO formats + * Merge pull request #34 from RangelReale/fix-mp4-case + * Merge pull request #32 from yiiTT/fix-m4v + * Fixed mp4 detection case-sensitivity according to http://www.ftyps.com/ + * Fix M4v matcher + +v1.0.5 / 2017-12-12 +=================== + + * Merge pull request #30 from RangelReale/fix_mp4 + * Fix duplicated item in mp4 fix + * Fix MP4 matcher, with information from http://www.file-recovery.com/mp4-signature-format.htm + * Merge pull request #28 from ikovic/master + * Updated file header example. + +v1.0.4 / 2017-11-29 +=================== + + * fix: tests and document types matchers + * refactor(docs): remove codesponsor + * Merge pull request #26 from bienkma/master + * Add support check file type: .doc, .docx, .pptx, .ppt, .xls, .xlsx + * feat(docs): add code sponsor banner + * feat(travis): add go 1.9 + * Merge pull request #24 from strazzere/patch-1 + * Fix typo in unknown + +v1.0.3 / 2017-08-03 +=================== + + * Merge pull request #21 from elemeta/master + * Add Elf file as supported matcher archive type + +v1.0.2 / 2017-07-26 +=================== + + * Merge pull request #20 from marshyski/master + * Added RedHat RPM as supported matcher archive type + * Merge pull request #19 from nlamirault/patch-1 + * Fix typo in documentation + +v1.0.1 / 2017-02-24 +=================== + + * Merge pull request #18 from Impyy/enable-webm + * Enable the webm matcher + * feat(docs): add Go version badge + +1.0.0 / 2016-12-11 +================== + +- Initial stable version (v1.0.0). diff --git a/vendor/github.com/h2non/filetype/LICENSE b/vendor/github.com/h2non/filetype/LICENSE new file mode 100644 index 00000000000..30ede59b653 --- /dev/null +++ b/vendor/github.com/h2non/filetype/LICENSE @@ -0,0 +1,24 @@ +The MIT License + +Copyright (c) Tomas Aparicio + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/h2non/filetype/README.md b/vendor/github.com/h2non/filetype/README.md new file mode 100644 index 00000000000..7f1e8e73537 --- /dev/null +++ b/vendor/github.com/h2non/filetype/README.md @@ -0,0 +1,290 @@ +# filetype [![Build Status](https://travis-ci.org/h2non/filetype.png)](https://travis-ci.org/h2non/filetype) [![GoDoc](https://godoc.org/github.com/h2non/filetype?status.svg)](https://godoc.org/github.com/h2non/filetype) [![Go Report Card](http://goreportcard.com/badge/h2non/filetype)](http://goreportcard.com/report/h2non/filetype) [![Go Version](https://img.shields.io/badge/go-v1.0+-green.svg?style=flat)](https://github.com/h2non/gentleman) + +Small and dependency free [Go](https://golang.org) package to infer file and MIME type checking the [magic numbers](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) signature. + +For SVG file type checking, see [go-is-svg](https://github.com/h2non/go-is-svg) package. + +## Features + +- Supports a [wide range](#supported-types) of file types +- Provides file extension and proper MIME type +- File discovery by extension or MIME type +- File discovery by class (image, video, audio...) +- Provides a bunch of helpers and file matching shortcuts +- [Pluggable](#add-additional-file-type-matchers): add custom new types and matchers +- Simple and semantic API +- [Blazing fast](#benchmarks), even processing large files +- Only first 262 bytes representing the max file header is required, so you can just [pass a slice](#file-header) +- Dependency free (just Go code, no C compilation needed) +- Cross-platform file recognition + +## Installation + +```bash +go get github.com/h2non/filetype +``` + +## API + +See [Godoc](https://godoc.org/github.com/h2non/filetype) reference. + +### Subpackages + +- [`github.com/h2non/filetype/types`](https://godoc.org/github.com/h2non/filetype/types) +- [`github.com/h2non/filetype/matchers`](https://godoc.org/github.com/h2non/filetype/matchers) + +## Examples + +#### Simple file type checking + +```go +package main + +import ( + "fmt" + "io/ioutil" + + "github.com/h2non/filetype" +) + +func main() { + buf, _ := ioutil.ReadFile("sample.jpg") + + kind, _ := filetype.Match(buf) + if kind == filetype.Unknown { + fmt.Println("Unknown file type") + return + } + + fmt.Printf("File type: %s. MIME: %s\n", kind.Extension, kind.MIME.Value) +} +``` + +#### Check type class + +```go +package main + +import ( + "fmt" + "io/ioutil" + + "github.com/h2non/filetype" +) + +func main() { + buf, _ := ioutil.ReadFile("sample.jpg") + + if filetype.IsImage(buf) { + fmt.Println("File is an image") + } else { + fmt.Println("Not an image") + } +} +``` + +#### Supported type + +```go +package main + +import ( + "fmt" + + "github.com/h2non/filetype" +) + +func main() { + // Check if file is supported by extension + if filetype.IsSupported("jpg") { + fmt.Println("Extension supported") + } else { + fmt.Println("Extension not supported") + } + + // Check if file is supported by extension + if filetype.IsMIMESupported("image/jpeg") { + fmt.Println("MIME type supported") + } else { + fmt.Println("MIME type not supported") + } +} +``` + +#### File header + +```go +package main + +import ( + "fmt" + "io/ioutil" + + "github.com/h2non/filetype" +) + +func main() { + // Open a file descriptor + file, _ := os.Open("movie.mp4") + + // We only have to pass the file header = first 261 bytes + head := make([]byte, 261) + file.Read(head) + + if filetype.IsImage(head) { + fmt.Println("File is an image") + } else { + fmt.Println("Not an image") + } +} +``` + +#### Add additional file type matchers + +```go +package main + +import ( + "fmt" + + "github.com/h2non/filetype" +) + +var fooType = filetype.NewType("foo", "foo/foo") + +func fooMatcher(buf []byte) bool { + return len(buf) > 1 && buf[0] == 0x01 && buf[1] == 0x02 +} + +func main() { + // Register the new matcher and its type + filetype.AddMatcher(fooType, fooMatcher) + + // Check if the new type is supported by extension + if filetype.IsSupported("foo") { + fmt.Println("New supported type: foo") + } + + // Check if the new type is supported by MIME + if filetype.IsMIMESupported("foo/foo") { + fmt.Println("New supported MIME type: foo/foo") + } + + // Try to match the file + fooFile := []byte{0x01, 0x02} + kind, _ := filetype.Match(fooFile) + if kind == filetype.Unknown { + fmt.Println("Unknown file type") + } else { + fmt.Printf("File type matched: %s\n", kind.Extension) + } +} +``` + +## Supported types + +#### Image + +- **jpg** - `image/jpeg` +- **png** - `image/png` +- **gif** - `image/gif` +- **webp** - `image/webp` +- **cr2** - `image/x-canon-cr2` +- **tif** - `image/tiff` +- **bmp** - `image/bmp` +- **heif** - `image/heif` +- **jxr** - `image/vnd.ms-photo` +- **psd** - `image/vnd.adobe.photoshop` +- **ico** - `image/x-icon` +- **dwg** - `image/vnd.dwg` + +#### Video + +- **mp4** - `video/mp4` +- **m4v** - `video/x-m4v` +- **mkv** - `video/x-matroska` +- **webm** - `video/webm` +- **mov** - `video/quicktime` +- **avi** - `video/x-msvideo` +- **wmv** - `video/x-ms-wmv` +- **mpg** - `video/mpeg` +- **flv** - `video/x-flv` +- **3gp** - `video/3gpp` + +#### Audio + +- **mid** - `audio/midi` +- **mp3** - `audio/mpeg` +- **m4a** - `audio/m4a` +- **ogg** - `audio/ogg` +- **flac** - `audio/x-flac` +- **wav** - `audio/x-wav` +- **amr** - `audio/amr` +- **aac** - `audio/aac` + +#### Archive + +- **epub** - `application/epub+zip` +- **zip** - `application/zip` +- **tar** - `application/x-tar` +- **rar** - `application/x-rar-compressed` +- **gz** - `application/gzip` +- **bz2** - `application/x-bzip2` +- **7z** - `application/x-7z-compressed` +- **xz** - `application/x-xz` +- **pdf** - `application/pdf` +- **exe** - `application/x-msdownload` +- **swf** - `application/x-shockwave-flash` +- **rtf** - `application/rtf` +- **iso** - `application/x-iso9660-image` +- **eot** - `application/octet-stream` +- **ps** - `application/postscript` +- **sqlite** - `application/x-sqlite3` +- **nes** - `application/x-nintendo-nes-rom` +- **crx** - `application/x-google-chrome-extension` +- **cab** - `application/vnd.ms-cab-compressed` +- **deb** - `application/x-deb` +- **ar** - `application/x-unix-archive` +- **Z** - `application/x-compress` +- **lz** - `application/x-lzip` +- **rpm** - `application/x-rpm` +- **elf** - `application/x-executable` +- **dcm** - `application/dicom` + +#### Documents + +- **doc** - `application/msword` +- **docx** - `application/vnd.openxmlformats-officedocument.wordprocessingml.document` +- **xls** - `application/vnd.ms-excel` +- **xlsx** - `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` +- **ppt** - `application/vnd.ms-powerpoint` +- **pptx** - `application/vnd.openxmlformats-officedocument.presentationml.presentation` + +#### Font + +- **woff** - `application/font-woff` +- **woff2** - `application/font-woff` +- **ttf** - `application/font-sfnt` +- **otf** - `application/font-sfnt` + +#### Application + +- **wasm** - `application/wasm` + +## Benchmarks + +Measured using [real files](https://github.com/h2non/filetype/tree/master/fixtures). + +Environment: OSX x64 i7 2.7 Ghz + +```bash +BenchmarkMatchTar-8 1000000 1083 ns/op +BenchmarkMatchZip-8 1000000 1162 ns/op +BenchmarkMatchJpeg-8 1000000 1280 ns/op +BenchmarkMatchGif-8 1000000 1315 ns/op +BenchmarkMatchPng-8 1000000 1121 ns/op +``` + +## License + +MIT - Tomas Aparicio diff --git a/vendor/github.com/h2non/filetype/filetype.go b/vendor/github.com/h2non/filetype/filetype.go new file mode 100644 index 00000000000..933058c8532 --- /dev/null +++ b/vendor/github.com/h2non/filetype/filetype.go @@ -0,0 +1,87 @@ +package filetype + +import ( + "errors" + + "github.com/h2non/filetype/matchers" + "github.com/h2non/filetype/types" +) + +// Types stores a map of supported types +var Types = types.Types + +// NewType creates and registers a new type +var NewType = types.NewType + +// Unknown represents an unknown file type +var Unknown = types.Unknown + +// ErrEmptyBuffer represents an empty buffer error +var ErrEmptyBuffer = errors.New("Empty buffer") + +// ErrUnknownBuffer represents a unknown buffer error +var ErrUnknownBuffer = errors.New("Unknown buffer type") + +// AddType registers a new file type +func AddType(ext, mime string) types.Type { + return types.NewType(ext, mime) +} + +// Is checks if a given buffer matches with the given file type extension +func Is(buf []byte, ext string) bool { + kind, ok := types.Types[ext] + if ok { + return IsType(buf, kind) + } + return false +} + +// IsExtension semantic alias to Is() +func IsExtension(buf []byte, ext string) bool { + return Is(buf, ext) +} + +// IsType checks if a given buffer matches with the given file type +func IsType(buf []byte, kind types.Type) bool { + matcher := matchers.Matchers[kind] + if matcher == nil { + return false + } + return matcher(buf) != types.Unknown +} + +// IsMIME checks if a given buffer matches with the given MIME type +func IsMIME(buf []byte, mime string) bool { + for _, kind := range types.Types { + if kind.MIME.Value == mime { + matcher := matchers.Matchers[kind] + return matcher(buf) != types.Unknown + } + } + return false +} + +// IsSupported checks if a given file extension is supported +func IsSupported(ext string) bool { + for name := range Types { + if name == ext { + return true + } + } + return false +} + +// IsMIMESupported checks if a given MIME type is supported +func IsMIMESupported(mime string) bool { + for _, m := range Types { + if m.MIME.Value == mime { + return true + } + } + return false +} + +// GetType retrieves a Type by file extension +func GetType(ext string) types.Type { + return types.Get(ext) +} diff --git a/vendor/github.com/h2non/filetype/go.mod b/vendor/github.com/h2non/filetype/go.mod new file mode 100644 index 00000000000..071ea73201e --- /dev/null +++ b/vendor/github.com/h2non/filetype/go.mod @@ -0,0 +1,3 @@ +module github.com/h2non/filetype + +go 1.13 diff --git a/vendor/github.com/h2non/filetype/kind.go b/vendor/github.com/h2non/filetype/kind.go new file mode 100644 index 00000000000..de8473507dc --- /dev/null +++ b/vendor/github.com/h2non/filetype/kind.go @@ -0,0 +1,80 @@ +package filetype + +import ( + "github.com/h2non/filetype/matchers" + "github.com/h2non/filetype/types" +) + +// Image tries to match a file as image type +func Image(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Image) +} + +// IsImage checks if the given buffer is an image type +func IsImage(buf []byte) bool { + kind, _ := Image(buf) + return kind != types.Unknown +} + +// Audio tries to match a file as audio type +func Audio(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Audio) +} + +// IsAudio checks if the given buffer is an audio type +func IsAudio(buf []byte) bool { + kind, _ := Audio(buf) + return kind != types.Unknown +} + +// Video tries to match a file as video type +func Video(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Video) +} + +// IsVideo checks if the given buffer is a video type +func IsVideo(buf []byte) bool { + kind, _ := Video(buf) + return kind != types.Unknown +} + +// Font tries to match a file as text font type +func Font(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Font) +} + +// IsFont checks if the given buffer is a font type +func IsFont(buf []byte) bool { + kind, _ := Font(buf) + return kind != types.Unknown +} + +// Archive tries to match a file as generic archive type +func Archive(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Archive) +} + +// IsArchive checks if the given buffer is an archive type +func IsArchive(buf []byte) bool { + kind, _ := Archive(buf) + return kind != types.Unknown +} + +// Document tries to match a file as document type +func Document(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Document) +} + +// IsDocument checks if the given buffer is an document type +func IsDocument(buf []byte) bool { + kind, _ := Document(buf) + return kind != types.Unknown +} + +func doMatchMap(buf []byte, machers matchers.Map) (types.Type, error) { + kind := MatchMap(buf, machers) + if kind != types.Unknown { + return kind, nil + } + return kind, ErrUnknownBuffer +} diff --git a/vendor/github.com/h2non/filetype/match.go b/vendor/github.com/h2non/filetype/match.go new file mode 100644 index 00000000000..82cf8046845 --- /dev/null +++ b/vendor/github.com/h2non/filetype/match.go @@ -0,0 +1,90 @@ +package filetype + +import ( + "io" + "os" + + "github.com/h2non/filetype/matchers" + "github.com/h2non/filetype/types" +) + +// Matchers is an alias to matchers.Matchers +var Matchers = matchers.Matchers + +// MatcherKeys is an alias to matchers.MatcherKeys +var MatcherKeys = &matchers.MatcherKeys + +// NewMatcher is an alias to matchers.NewMatcher +var NewMatcher = matchers.NewMatcher + +// Match infers the file type of a given buffer inspecting its magic numbers signature +func Match(buf []byte) (types.Type, error) { + length := len(buf) + if length == 0 { + return types.Unknown, ErrEmptyBuffer + } + + for _, kind := range *MatcherKeys { + checker := Matchers[kind] + match := checker(buf) + if match != types.Unknown && match.Extension != "" { + return match, nil + } + } + + return types.Unknown, nil +} + +// Get is an alias to Match() +func Get(buf []byte) (types.Type, error) { + return Match(buf) +} + +// MatchFile infers a file type for a file +func MatchFile(filepath string) (types.Type, error) { + file, err := os.Open(filepath) + if err != nil { + return types.Unknown, err + } + defer file.Close() + + return MatchReader(file) +} + +// MatchReader is convenient wrapper to Match() any Reader +func MatchReader(reader io.Reader) (types.Type, error) { + buffer := make([]byte, 8192) // 8K makes msooxml tests happy and allows for expanded custom file checks + + _, err := reader.Read(buffer) + if err != nil && err != io.EOF { + return types.Unknown, err + } + + return Match(buffer) +} + +// AddMatcher registers a new matcher type +func AddMatcher(fileType types.Type, matcher matchers.Matcher) matchers.TypeMatcher { + return matchers.NewMatcher(fileType, matcher) +} + +// Matches checks if the given buffer matches with some supported file type +func Matches(buf []byte) bool { + kind, _ := Match(buf) + return kind != types.Unknown +} + +// MatchMap performs a file matching against a map of match functions +func MatchMap(buf []byte, matchers matchers.Map) types.Type { + for kind, matcher := range matchers { + if matcher(buf) { + return kind + } + } + return types.Unknown +} + +// MatchesMap is an alias to Matches() but using matching against a map of match functions +func MatchesMap(buf []byte, matchers matchers.Map) bool { + return MatchMap(buf, matchers) != types.Unknown +} diff --git a/vendor/github.com/h2non/filetype/matchers/application.go b/vendor/github.com/h2non/filetype/matchers/application.go new file mode 100644 index 00000000000..f482062d6c0 --- /dev/null +++ b/vendor/github.com/h2non/filetype/matchers/application.go @@ -0,0 +1,20 @@ +package matchers + +var ( + TypeWasm = newType("wasm", "application/wasm") +) + +var Application = Map{ + TypeWasm: Wasm, +} + +// Wasm detects a Web Assembly 1.0 filetype. +func Wasm(buf []byte) bool { + // WASM has starts with `\0asm`, followed by the version. + // http://webassembly.github.io/spec/core/binary/modules.html#binary-magic + return len(buf) >= 8 && + buf[0] == 0x00 && buf[1] == 0x61 && + buf[2] == 0x73 && buf[3] == 0x6D && + buf[4] == 0x01 && buf[5] == 0x00 && + buf[6] == 0x00 && buf[7] == 0x00 +} diff --git a/vendor/github.com/h2non/filetype/matchers/archive.go b/vendor/github.com/h2non/filetype/matchers/archive.go new file mode 100644 index 00000000000..a2201378328 --- /dev/null +++ b/vendor/github.com/h2non/filetype/matchers/archive.go @@ -0,0 +1,234 @@ +package matchers + +var ( + TypeEpub = newType("epub", "application/epub+zip") + TypeZip = newType("zip", "application/zip") + TypeTar = newType("tar", "application/x-tar") + TypeRar = newType("rar", "application/x-rar-compressed") + TypeGz = newType("gz", "application/gzip") + TypeBz2 = newType("bz2", "application/x-bzip2") + Type7z = newType("7z", "application/x-7z-compressed") + TypeXz = newType("xz", "application/x-xz") + TypePdf = newType("pdf", "application/pdf") + TypeExe = newType("exe", "application/x-msdownload") + TypeSwf = newType("swf", "application/x-shockwave-flash") + TypeRtf = newType("rtf", "application/rtf") + TypeEot = newType("eot", "application/octet-stream") + TypePs = newType("ps", "application/postscript") + TypeSqlite = newType("sqlite", "application/x-sqlite3") + TypeNes = newType("nes", "application/x-nintendo-nes-rom") + TypeCrx = newType("crx", "application/x-google-chrome-extension") + TypeCab = newType("cab", "application/vnd.ms-cab-compressed") + TypeDeb = newType("deb", "application/x-deb") + TypeAr = newType("ar", "application/x-unix-archive") + TypeZ = newType("Z", "application/x-compress") + TypeLz = newType("lz", "application/x-lzip") + TypeRpm = newType("rpm", "application/x-rpm") + TypeElf = newType("elf", "application/x-executable") + TypeDcm = newType("dcm", "application/dicom") + TypeIso = newType("iso", "application/x-iso9660-image") +) + +var Archive = Map{ + TypeEpub: Epub, + TypeZip: Zip, + TypeTar: Tar, + TypeRar: Rar, + TypeGz: Gz, + TypeBz2: Bz2, + Type7z: SevenZ, + TypeXz: Xz, + TypePdf: Pdf, + TypeExe: Exe, + TypeSwf: Swf, + TypeRtf: Rtf, + TypeEot: Eot, + TypePs: Ps, + TypeSqlite: Sqlite, + TypeNes: Nes, + TypeCrx: Crx, + TypeCab: Cab, + TypeDeb: Deb, + TypeAr: Ar, + TypeZ: Z, + TypeLz: Lz, + TypeRpm: Rpm, + TypeElf: Elf, + TypeDcm: Dcm, + TypeIso: Iso, +} + +func Epub(buf []byte) bool { + return len(buf) > 57 && + buf[0] == 0x50 && buf[1] == 0x4B && buf[2] == 0x3 && buf[3] == 0x4 && + buf[30] == 0x6D && buf[31] == 0x69 && buf[32] == 0x6D && buf[33] == 0x65 && + buf[34] == 0x74 && buf[35] == 0x79 && buf[36] == 0x70 && buf[37] == 0x65 && + buf[38] == 0x61 && buf[39] == 0x70 && buf[40] == 0x70 && buf[41] == 0x6C && + buf[42] == 0x69 && buf[43] == 0x63 && buf[44] == 0x61 && buf[45] == 0x74 && + buf[46] == 0x69 && buf[47] == 0x6F && buf[48] == 0x6E && buf[49] == 0x2F && + buf[50] == 0x65 && buf[51] == 0x70 && buf[52] == 0x75 && buf[53] == 0x62 && + buf[54] == 0x2B && buf[55] == 0x7A && buf[56] == 0x69 && buf[57] == 0x70 +} + +func Zip(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x50 && buf[1] == 0x4B && + (buf[2] == 0x3 || buf[2] == 0x5 || buf[2] == 0x7) && + (buf[3] == 0x4 || buf[3] == 0x6 || buf[3] == 0x8) +} + +func Tar(buf []byte) bool { + return len(buf) > 261 && + buf[257] == 0x75 && buf[258] == 0x73 && + buf[259] == 0x74 && buf[260] == 0x61 && + buf[261] == 0x72 +} + +func Rar(buf []byte) bool { + return len(buf) > 6 && + buf[0] == 0x52 && buf[1] == 0x61 && buf[2] == 0x72 && + buf[3] == 0x21 && buf[4] == 0x1A && buf[5] == 0x7 && + (buf[6] == 0x0 || buf[6] == 0x1) +} + +func Gz(buf []byte) bool { + return len(buf) > 2 && + buf[0] == 0x1F && buf[1] == 0x8B && buf[2] == 0x8 +} + +func Bz2(buf []byte) bool { + return len(buf) > 2 && + buf[0] == 0x42 && buf[1] == 0x5A && buf[2] == 0x68 +} + +func SevenZ(buf []byte) bool { + return len(buf) > 5 && + buf[0] == 0x37 && buf[1] == 0x7A && buf[2] == 0xBC && + buf[3] == 0xAF && buf[4] == 0x27 && buf[5] == 0x1C +} + +func Pdf(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x25 && buf[1] == 0x50 && + buf[2] == 0x44 && buf[3] == 0x46 +} + +func Exe(buf []byte) bool { + return len(buf) > 1 && + buf[0] == 0x4D && buf[1] == 0x5A +} + +func Swf(buf []byte) bool { + return len(buf) > 2 && + (buf[0] == 0x43 || buf[0] == 0x46) && + buf[1] == 0x57 && buf[2] == 0x53 +} + +func Rtf(buf []byte) bool { + return len(buf) > 4 && + buf[0] == 0x7B && buf[1] == 0x5C && + buf[2] == 0x72 && buf[3] == 0x74 && + buf[4] == 0x66 +} + +func Nes(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x4E && buf[1] == 0x45 && + buf[2] == 0x53 && buf[3] == 0x1A +} + +func Crx(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x43 && buf[1] == 0x72 && + buf[2] == 0x32 && buf[3] == 0x34 +} + +func Cab(buf []byte) bool { + return len(buf) > 3 && + ((buf[0] == 0x4D && buf[1] == 0x53 && buf[2] == 0x43 && buf[3] == 0x46) || + (buf[0] == 0x49 && buf[1] == 0x53 && buf[2] == 0x63 && buf[3] == 0x28)) +} + +func Eot(buf []byte) bool { + return len(buf) > 35 && + buf[34] == 0x4C && buf[35] == 0x50 && + ((buf[8] == 0x02 && buf[9] == 0x00 && + buf[10] == 0x01) || (buf[8] == 0x01 && + buf[9] == 0x00 && buf[10] == 0x00) || + (buf[8] == 0x02 && buf[9] == 0x00 && + buf[10] == 0x02)) +} + +func Ps(buf []byte) bool { + return len(buf) > 1 && + buf[0] == 0x25 && buf[1] == 0x21 +} + +func Xz(buf []byte) bool { + return len(buf) > 5 && + buf[0] == 0xFD && buf[1] == 0x37 && + buf[2] == 0x7A && buf[3] == 0x58 && + buf[4] == 0x5A && buf[5] == 0x00 +} + +func Sqlite(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x53 && buf[1] == 0x51 && + buf[2] == 0x4C && buf[3] == 0x69 +} + +func Deb(buf []byte) bool { + return len(buf) > 20 && + buf[0] == 0x21 && buf[1] == 0x3C && buf[2] == 0x61 && + buf[3] == 0x72 && buf[4] == 0x63 && buf[5] == 0x68 && + buf[6] == 0x3E && buf[7] == 0x0A && buf[8] == 0x64 && + buf[9] == 0x65 && buf[10] == 0x62 && buf[11] == 0x69 && + buf[12] == 0x61 && buf[13] == 0x6E && buf[14] == 0x2D && + buf[15] == 0x62 && buf[16] == 0x69 && buf[17] == 0x6E && + buf[18] == 0x61 && buf[19] == 0x72 && buf[20] == 0x79 +} + +func Ar(buf []byte) bool { + return len(buf) > 6 && + buf[0] == 0x21 && buf[1] == 0x3C && + buf[2] == 0x61 && buf[3] == 0x72 && + buf[4] == 0x63 && buf[5] == 0x68 && + buf[6] == 0x3E +} + +func Z(buf []byte) bool { + return len(buf) > 1 && + ((buf[0] == 0x1F && buf[1] == 0xA0) || + (buf[0] == 0x1F && buf[1] == 0x9D)) +} + +func Lz(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x4C && buf[1] == 0x5A && + buf[2] == 0x49 && buf[3] == 0x50 +} + +func Rpm(buf []byte) bool { + return len(buf) > 96 && + buf[0] == 0xED && buf[1] == 0xAB && + buf[2] == 0xEE && buf[3] == 0xDB +} + +func Elf(buf []byte) bool { + return len(buf) > 52 && + buf[0] == 0x7F && buf[1] == 0x45 && + buf[2] == 0x4C && buf[3] == 0x46 +} + +func Dcm(buf []byte) bool { + return len(buf) > 131 && + buf[128] == 0x44 && buf[129] == 0x49 && + buf[130] == 0x43 && buf[131] == 0x4D +} + +func Iso(buf []byte) bool { + return len(buf) > 32773 && + buf[32769] == 0x43 && buf[32770] == 0x44 && + buf[32771] == 0x30 && buf[32772] == 0x30 && + buf[32773] == 0x31 +} diff --git a/vendor/github.com/h2non/filetype/matchers/audio.go b/vendor/github.com/h2non/filetype/matchers/audio.go new file mode 100644 index 00000000000..6d532630af0 --- /dev/null +++ b/vendor/github.com/h2non/filetype/matchers/audio.go @@ -0,0 +1,75 @@ +package matchers + +var ( + TypeMidi = newType("mid", "audio/midi") + TypeMp3 = newType("mp3", "audio/mpeg") + TypeM4a = newType("m4a", "audio/m4a") + TypeOgg = newType("ogg", "audio/ogg") + TypeFlac = newType("flac", "audio/x-flac") + TypeWav = newType("wav", "audio/x-wav") + TypeAmr = newType("amr", "audio/amr") + TypeAac = newType("aac", "audio/aac") +) + +var Audio = Map{ + TypeMidi: Midi, + TypeMp3: Mp3, + TypeM4a: M4a, + TypeOgg: Ogg, + TypeFlac: Flac, + TypeWav: Wav, + TypeAmr: Amr, + TypeAac: Aac, +} + +func Midi(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x4D && buf[1] == 0x54 && + buf[2] == 0x68 && buf[3] == 0x64 +} + +func Mp3(buf []byte) bool { + return len(buf) > 2 && + ((buf[0] == 0x49 && buf[1] == 0x44 && buf[2] == 0x33) || + (buf[0] == 0xFF && buf[1] == 0xfb)) +} + +func M4a(buf []byte) bool { + return len(buf) > 10 && + ((buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && + buf[7] == 0x70 && buf[8] == 0x4D && buf[9] == 0x34 && buf[10] == 0x41) || + (buf[0] == 0x4D && buf[1] == 0x34 && buf[2] == 0x41 && buf[3] == 0x20)) +} + +func Ogg(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x4F && buf[1] == 0x67 && + buf[2] == 0x67 && buf[3] == 0x53 +} + +func Flac(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x66 && buf[1] == 0x4C && + buf[2] == 0x61 && buf[3] == 0x43 +} + +func Wav(buf []byte) bool { + return len(buf) > 11 && + buf[0] == 0x52 && buf[1] == 0x49 && + buf[2] == 0x46 && buf[3] == 0x46 && + buf[8] == 0x57 && buf[9] == 0x41 && + buf[10] == 0x56 && buf[11] == 0x45 +} + +func Amr(buf []byte) bool { + return len(buf) > 11 && + buf[0] == 0x23 && buf[1] == 0x21 && + buf[2] == 0x41 && buf[3] == 0x4D && + buf[4] == 0x52 && buf[5] == 0x0A +} + +func Aac(buf []byte) bool { + return len(buf) > 1 && + ((buf[0] == 0xFF && buf[1] == 0xF1) || + (buf[0] == 0xFF && buf[1] == 0xF9)) +} diff --git a/vendor/github.com/h2non/filetype/matchers/document.go b/vendor/github.com/h2non/filetype/matchers/document.go new file mode 100644 index 00000000000..0a27217cf5d --- /dev/null +++ b/vendor/github.com/h2non/filetype/matchers/document.go @@ -0,0 +1,184 @@ +package matchers + +import ( + "bytes" + "encoding/binary" +) + +var ( + TypeDoc = newType("doc", "application/msword") + TypeDocx = newType("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document") + TypeXls = newType("xls", "application/vnd.ms-excel") + TypeXlsx = newType("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + TypePpt = newType("ppt", "application/vnd.ms-powerpoint") + TypePptx = newType("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation") +) + +var Document = Map{ + TypeDoc: Doc, + TypeDocx: Docx, + TypeXls: Xls, + TypeXlsx: Xlsx, + TypePpt: Ppt, + TypePptx: Pptx, +} + +type docType int + +const ( + TYPE_DOC docType = iota + TYPE_DOCX + TYPE_XLS + TYPE_XLSX + TYPE_PPT + TYPE_PPTX + TYPE_OOXML +) + +func Doc(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0xD0 && buf[1] == 0xCF && + buf[2] == 0x11 && buf[3] == 0xE0 && + buf[4] == 0xA1 && buf[5] == 0xB1 && + buf[6] == 0x1A && buf[7] == 0xE1 +} + +func Docx(buf []byte) bool { + typ, ok := msooxml(buf) + return ok && typ == TYPE_DOCX +} + +func Xls(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0xD0 && buf[1] == 0xCF && + buf[2] == 0x11 && buf[3] == 0xE0 && + buf[4] == 0xA1 && buf[5] == 0xB1 && + buf[6] == 0x1A && buf[7] == 0xE1 +} + +func Xlsx(buf []byte) bool { + typ, ok := msooxml(buf) + return ok && typ == TYPE_XLSX +} + +func Ppt(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0xD0 && buf[1] == 0xCF && + buf[2] == 0x11 && buf[3] == 0xE0 && + buf[4] == 0xA1 && buf[5] == 0xB1 && + buf[6] == 0x1A && buf[7] == 0xE1 +} + +func Pptx(buf []byte) bool { + typ, ok := msooxml(buf) + return ok && typ == TYPE_PPTX +} + +func msooxml(buf []byte) (typ docType, found bool) { + signature := []byte{'P', 'K', 0x03, 0x04} + + // start by checking for ZIP local file header signature + if ok := compareBytes(buf, signature, 0); !ok { + return + } + + // make sure the first file is correct + if v, ok := checkMSOoml(buf, 0x1E); ok { + return v, ok + } + + if !compareBytes(buf, []byte("[Content_Types].xml"), 0x1E) && + !compareBytes(buf, []byte("_rels/.rels"), 0x1E) && + !compareBytes(buf, []byte("docProps"), 0x1E) { + return + } + + // skip to the second local file header + // since some documents include a 520-byte extra field following the file + // header, we need to scan for the next header + startOffset := int(binary.LittleEndian.Uint32(buf[18:22]) + 49) + idx := search(buf, startOffset, 6000) + if idx == -1 { + return + } + + // now skip to the *third* local file header; again, we need to scan due to a + // 520-byte extra field following the file header + startOffset += idx + 4 + 26 + idx = search(buf, startOffset, 6000) + if idx == -1 { + return + } + + // and check the subdirectory name to determine which type of OOXML + // file we have. Correct the mimetype with the registered ones: + // http://technet.microsoft.com/en-us/library/cc179224.aspx + startOffset += idx + 4 + 26 + if typ, ok := checkMSOoml(buf, startOffset); ok { + return typ, ok + } + + // OpenOffice/Libreoffice orders ZIP entry differently, so check the 4th file + startOffset += 26 + idx = search(buf, startOffset, 6000) + if idx == -1 { + return TYPE_OOXML, true + } + + startOffset += idx + 4 + 26 + if typ, ok := checkMSOoml(buf, startOffset); ok { + return typ, ok + } else { + return TYPE_OOXML, true + } +} + +func compareBytes(slice, subSlice []byte, startOffset int) bool { + sl := len(subSlice) + + if startOffset+sl > len(slice) { + return false + } + + s := slice[startOffset : startOffset+sl] + for i := range s { + if subSlice[i] != s[i] { + return false + } + } + + return true +} + +func checkMSOoml(buf []byte, offset int) (typ docType, ok bool) { + ok = true + + switch { + case compareBytes(buf, []byte("word/"), offset): + typ = TYPE_DOCX + case compareBytes(buf, []byte("ppt/"), offset): + typ = TYPE_PPTX + case compareBytes(buf, []byte("xl/"), offset): + typ = TYPE_XLSX + default: + ok = false + } + + return +} + +func search(buf []byte, start, rangeNum int) int { + length := len(buf) + end := start + rangeNum + signature := []byte{'P', 'K', 0x03, 0x04} + + if end > length { + end = length + } + + if start >= end { + return -1 + } + + return bytes.Index(buf[start:end], signature) +} diff --git a/vendor/github.com/h2non/filetype/matchers/font.go b/vendor/github.com/h2non/filetype/matchers/font.go new file mode 100644 index 00000000000..f39171675e9 --- /dev/null +++ b/vendor/github.com/h2non/filetype/matchers/font.go @@ -0,0 +1,45 @@ +package matchers + +var ( + TypeWoff = newType("woff", "application/font-woff") + TypeWoff2 = newType("woff2", "application/font-woff") + TypeTtf = newType("ttf", "application/font-sfnt") + TypeOtf = newType("otf", "application/font-sfnt") +) + +var Font = Map{ + TypeWoff: Woff, + TypeWoff2: Woff2, + TypeTtf: Ttf, + TypeOtf: Otf, +} + +func Woff(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0x77 && buf[1] == 0x4F && + buf[2] == 0x46 && buf[3] == 0x46 && + buf[4] == 0x00 && buf[5] == 0x01 && + buf[6] == 0x00 && buf[7] == 0x00 +} + +func Woff2(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0x77 && buf[1] == 0x4F && + buf[2] == 0x46 && buf[3] == 0x32 && + buf[4] == 0x00 && buf[5] == 0x01 && + buf[6] == 0x00 && buf[7] == 0x00 +} + +func Ttf(buf []byte) bool { + return len(buf) > 4 && + buf[0] == 0x00 && buf[1] == 0x01 && + buf[2] == 0x00 && buf[3] == 0x00 && + buf[4] == 0x00 +} + +func Otf(buf []byte) bool { + return len(buf) > 4 && + buf[0] == 0x4F && buf[1] == 0x54 && + buf[2] == 0x54 && buf[3] == 0x4F && + buf[4] == 0x00 +} diff --git a/vendor/github.com/h2non/filetype/matchers/image.go b/vendor/github.com/h2non/filetype/matchers/image.go new file mode 100644 index 00000000000..6a5eefce3eb --- /dev/null +++ b/vendor/github.com/h2non/filetype/matchers/image.go @@ -0,0 +1,143 @@ +package matchers + +import "github.com/h2non/filetype/matchers/isobmff" + +var ( + TypeJpeg = newType("jpg", "image/jpeg") + TypeJpeg2000 = newType("jp2", "image/jp2") + TypePng = newType("png", "image/png") + TypeGif = newType("gif", "image/gif") + TypeWebp = newType("webp", "image/webp") + TypeCR2 = newType("cr2", "image/x-canon-cr2") + TypeTiff = newType("tif", "image/tiff") + TypeBmp = newType("bmp", "image/bmp") + TypeJxr = newType("jxr", "image/vnd.ms-photo") + TypePsd = newType("psd", "image/vnd.adobe.photoshop") + TypeIco = newType("ico", "image/x-icon") + TypeHeif = newType("heif", "image/heif") + TypeDwg = newType("dwg", "image/vnd.dwg") +) + +var Image = Map{ + TypeJpeg: Jpeg, + TypeJpeg2000: Jpeg2000, + TypePng: Png, + TypeGif: Gif, + TypeWebp: Webp, + TypeCR2: CR2, + TypeTiff: Tiff, + TypeBmp: Bmp, + TypeJxr: Jxr, + TypePsd: Psd, + TypeIco: Ico, + TypeHeif: Heif, + TypeDwg: Dwg, +} + +func Jpeg(buf []byte) bool { + return len(buf) > 2 && + buf[0] == 0xFF && + buf[1] == 0xD8 && + buf[2] == 0xFF +} + +func Jpeg2000(buf []byte) bool { + return len(buf) > 12 && + buf[0] == 0x0 && + buf[1] == 0x0 && + buf[2] == 0x0 && + buf[3] == 0xC && + buf[4] == 0x6A && + buf[5] == 0x50 && + buf[6] == 0x20 && + buf[7] == 0x20 && + buf[8] == 0xD && + buf[9] == 0xA && + buf[10] == 0x87 && + buf[11] == 0xA && + buf[12] == 0x0 +} + +func Png(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x89 && buf[1] == 0x50 && + buf[2] == 0x4E && buf[3] == 0x47 +} + +func Gif(buf []byte) bool { + return len(buf) > 2 && + buf[0] == 0x47 && buf[1] == 0x49 && buf[2] == 0x46 +} + +func Webp(buf []byte) bool { + return len(buf) > 11 && + buf[8] == 0x57 && buf[9] == 0x45 && + buf[10] == 0x42 && buf[11] == 0x50 +} + +func CR2(buf []byte) bool { + return len(buf) > 9 && + ((buf[0] == 0x49 && buf[1] == 0x49 && buf[2] == 0x2A && buf[3] == 0x0) || + (buf[0] == 0x4D && buf[1] == 0x4D && buf[2] == 0x0 && buf[3] == 0x2A)) && + buf[8] == 0x43 && buf[9] == 0x52 +} + +func Tiff(buf []byte) bool { + return len(buf) > 9 && + ((buf[0] == 0x49 && buf[1] == 0x49 && buf[2] == 0x2A && buf[3] == 0x0) || + (buf[0] == 0x4D && buf[1] == 0x4D && buf[2] == 0x0 && buf[3] == 0x2A)) && + // Differentiate Tiff from CR2 + buf[8] != 0x43 && buf[9] != 0x52 +} + +func Bmp(buf []byte) bool { + return len(buf) > 1 && + buf[0] == 0x42 && + buf[1] == 0x4D +} + +func Jxr(buf []byte) bool { + return len(buf) > 2 && + buf[0] == 0x49 && + buf[1] == 0x49 && + buf[2] == 0xBC +} + +func Psd(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x38 && buf[1] == 0x42 && + buf[2] == 0x50 && buf[3] == 0x53 +} + +func Ico(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x00 && buf[1] == 0x00 && + buf[2] == 0x01 && buf[3] == 0x00 +} + +func Heif(buf []byte) bool { + if !isobmff.IsISOBMFF(buf) { + return false + } + + majorBrand, _, compatibleBrands := isobmff.GetFtyp(buf) + if majorBrand == "heic" { + return true + } + + if majorBrand == "mif1" || majorBrand == "msf1" { + for _, compatibleBrand := range compatibleBrands { + if compatibleBrand == "heic" { + return true + } + } + } + + return false +} + +func Dwg(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x41 && buf[1] == 0x43 && + buf[2] == 0x31 && buf[3] == 0x30 +} diff --git a/vendor/github.com/h2non/filetype/matchers/isobmff/isobmff.go b/vendor/github.com/h2non/filetype/matchers/isobmff/isobmff.go new file mode 100644 index 00000000000..b3e39bf59a6 --- /dev/null +++ b/vendor/github.com/h2non/filetype/matchers/isobmff/isobmff.go @@ -0,0 +1,37 @@ +package isobmff + +import "encoding/binary" + +// IsISOBMFF checks whether the given buffer represents ISO Base Media File Format data +func IsISOBMFF(buf []byte) bool { + if len(buf) < 16 || string(buf[4:8]) != "ftyp" { + return false + } + + if ftypLength := binary.BigEndian.Uint32(buf[0:4]); len(buf) < int(ftypLength) { + return false + } + + return true +} + +// GetFtyp returns the major brand, minor version and compatible brands of the ISO-BMFF data +func GetFtyp(buf []byte) (string, string, []string) { + if len(buf) < 17 { + return "", "", []string{""} + } + + ftypLength := binary.BigEndian.Uint32(buf[0:4]) + + majorBrand := string(buf[8:12]) + minorVersion := string(buf[12:16]) + + compatibleBrands := []string{} + for i := 16; i < int(ftypLength); i += 4 { + if len(buf) >= (i + 4) { + compatibleBrands = append(compatibleBrands, string(buf[i:i+4])) + } + } + + return majorBrand, minorVersion, compatibleBrands +} diff --git a/vendor/github.com/h2non/filetype/matchers/matchers.go b/vendor/github.com/h2non/filetype/matchers/matchers.go new file mode 100644 index 00000000000..20d74d080d8 --- /dev/null +++ b/vendor/github.com/h2non/filetype/matchers/matchers.go @@ -0,0 +1,51 @@ +package matchers + +import ( + "github.com/h2non/filetype/types" +) + +// Internal shortcut to NewType +var newType = types.NewType + +// Matcher function interface as type alias +type Matcher func([]byte) bool + +// Type interface to store pairs of type with its matcher function +type Map map[types.Type]Matcher + +// Type specific matcher function interface +type TypeMatcher func([]byte) types.Type + +// Store registered file type matchers +var Matchers = make(map[types.Type]TypeMatcher) +var MatcherKeys []types.Type + +// Create and register a new type matcher function +func NewMatcher(kind types.Type, fn Matcher) TypeMatcher { + matcher := func(buf []byte) types.Type { + if fn(buf) { + return kind + } + return types.Unknown + } + + Matchers[kind] = matcher + // prepend here so any user defined matchers get added first + MatcherKeys = append([]types.Type{kind}, MatcherKeys...) + return matcher +} + +func register(matchers ...Map) { + MatcherKeys = MatcherKeys[:0] + for _, m := range matchers { + for kind, matcher := range m { + NewMatcher(kind, matcher) + } + } +} + +func init() { + // Arguments order is intentional + // Archive files will be checked last due to prepend above in func NewMatcher + register(Archive, Document, Font, Audio, Video, Image, Application) +} diff --git a/vendor/github.com/h2non/filetype/matchers/video.go b/vendor/github.com/h2non/filetype/matchers/video.go new file mode 100644 index 00000000000..e97cf28a11d --- /dev/null +++ b/vendor/github.com/h2non/filetype/matchers/video.go @@ -0,0 +1,145 @@ +package matchers + +import "bytes" + +var ( + TypeMp4 = newType("mp4", "video/mp4") + TypeM4v = newType("m4v", "video/x-m4v") + TypeMkv = newType("mkv", "video/x-matroska") + TypeWebm = newType("webm", "video/webm") + TypeMov = newType("mov", "video/quicktime") + TypeAvi = newType("avi", "video/x-msvideo") + TypeWmv = newType("wmv", "video/x-ms-wmv") + TypeMpeg = newType("mpg", "video/mpeg") + TypeFlv = newType("flv", "video/x-flv") + Type3gp = newType("3gp", "video/3gpp") +) + +var Video = Map{ + TypeMp4: Mp4, + TypeM4v: M4v, + TypeMkv: Mkv, + TypeWebm: Webm, + TypeMov: Mov, + TypeAvi: Avi, + TypeWmv: Wmv, + TypeMpeg: Mpeg, + TypeFlv: Flv, + Type3gp: Match3gp, +} + +func M4v(buf []byte) bool { + return len(buf) > 10 && + buf[4] == 0x66 && buf[5] == 0x74 && + buf[6] == 0x79 && buf[7] == 0x70 && + buf[8] == 0x4D && buf[9] == 0x34 && + buf[10] == 0x56 +} + +func Mkv(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x1A && buf[1] == 0x45 && + buf[2] == 0xDF && buf[3] == 0xA3 && + containsMatroskaSignature(buf, []byte{'m', 'a', 't', 'r', 'o', 's', 'k', 'a'}) +} + +func Webm(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x1A && buf[1] == 0x45 && + buf[2] == 0xDF && buf[3] == 0xA3 && + containsMatroskaSignature(buf, []byte{'w', 'e', 'b', 'm'}) +} + +func Mov(buf []byte) bool { + return len(buf) > 15 && ((buf[0] == 0x0 && buf[1] == 0x0 && + buf[2] == 0x0 && buf[3] == 0x14 && + buf[4] == 0x66 && buf[5] == 0x74 && + buf[6] == 0x79 && buf[7] == 0x70) || + (buf[4] == 0x6d && buf[5] == 0x6f && buf[6] == 0x6f && buf[7] == 0x76) || + (buf[4] == 0x6d && buf[5] == 0x64 && buf[6] == 0x61 && buf[7] == 0x74) || + (buf[12] == 0x6d && buf[13] == 0x64 && buf[14] == 0x61 && buf[15] == 0x74)) +} + +func Avi(buf []byte) bool { + return len(buf) > 10 && + buf[0] == 0x52 && buf[1] == 0x49 && + buf[2] == 0x46 && buf[3] == 0x46 && + buf[8] == 0x41 && buf[9] == 0x56 && + buf[10] == 0x49 +} + +func Wmv(buf []byte) bool { + return len(buf) > 9 && + buf[0] == 0x30 && buf[1] == 0x26 && + buf[2] == 0xB2 && buf[3] == 0x75 && + buf[4] == 0x8E && buf[5] == 0x66 && + buf[6] == 0xCF && buf[7] == 0x11 && + buf[8] == 0xA6 && buf[9] == 0xD9 +} + +func Mpeg(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x0 && buf[1] == 0x0 && + buf[2] == 0x1 && buf[3] >= 0xb0 && + buf[3] <= 0xbf +} + +func Flv(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x46 && buf[1] == 0x4C && + buf[2] == 0x56 && buf[3] == 0x01 +} + +func Mp4(buf []byte) bool { + return len(buf) > 11 && + (buf[4] == 'f' && buf[5] == 't' && buf[6] == 'y' && buf[7] == 'p') && + ((buf[8] == 'a' && buf[9] == 'v' && buf[10] == 'c' && buf[11] == '1') || + (buf[8] == 'd' && buf[9] == 'a' && buf[10] == 's' && buf[11] == 'h') || + (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '2') || + (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '3') || + (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '4') || + (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '5') || + (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '6') || + (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == 'm') || + (buf[8] == 'm' && buf[9] == 'm' && buf[10] == 'p' && buf[11] == '4') || + (buf[8] == 'm' && buf[9] == 'p' && buf[10] == '4' && buf[11] == '1') || + (buf[8] == 'm' && buf[9] == 'p' && buf[10] == '4' && buf[11] == '2') || + (buf[8] == 'm' && buf[9] == 'p' && buf[10] == '4' && buf[11] == 'v') || + (buf[8] == 'm' && buf[9] == 'p' && buf[10] == '7' && buf[11] == '1') || + (buf[8] == 'M' && buf[9] == 'S' && buf[10] == 'N' && buf[11] == 'V') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'A' && buf[11] == 'S') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'C') || + (buf[8] == 'N' && buf[9] == 'S' && buf[10] == 'D' && buf[11] == 'C') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'H') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'M') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'P') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'S' && buf[11] == 'S') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'C') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'H') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'M') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'P') || + (buf[8] == 'N' && buf[9] == 'D' && buf[10] == 'X' && buf[11] == 'S') || + (buf[8] == 'F' && buf[9] == '4' && buf[10] == 'V' && buf[11] == ' ') || + (buf[8] == 'F' && buf[9] == '4' && buf[10] == 'P' && buf[11] == ' ')) +} + +func Match3gp(buf []byte) bool { + return len(buf) > 10 && + buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && + buf[7] == 0x70 && buf[8] == 0x33 && buf[9] == 0x67 && + buf[10] == 0x70 +} + +func containsMatroskaSignature(buf, subType []byte) bool { + limit := 4096 + if len(buf) < limit { + limit = len(buf) + } + + index := bytes.Index(buf[:limit], subType) + if index < 3 { + return false + } + + return buf[index-3] == 0x42 && buf[index-2] == 0x82 +} diff --git a/vendor/github.com/h2non/filetype/types/defaults.go b/vendor/github.com/h2non/filetype/types/defaults.go new file mode 100644 index 00000000000..0d985a05d68 --- /dev/null +++ b/vendor/github.com/h2non/filetype/types/defaults.go @@ -0,0 +1,4 @@ +package types + +// Unknown default type +var Unknown = NewType("unknown", "") diff --git a/vendor/github.com/h2non/filetype/types/mime.go b/vendor/github.com/h2non/filetype/types/mime.go new file mode 100644 index 00000000000..fe8ea822e55 --- /dev/null +++ b/vendor/github.com/h2non/filetype/types/mime.go @@ -0,0 +1,14 @@ +package types + +// MIME stores the file MIME type values +type MIME struct { + Type string + Subtype string + Value string +} + +// Creates a new MIME type +func NewMIME(mime string) MIME { + kind, subtype := splitMime(mime) + return MIME{Type: kind, Subtype: subtype, Value: mime} +} diff --git a/vendor/github.com/h2non/filetype/types/split.go b/vendor/github.com/h2non/filetype/types/split.go new file mode 100644 index 00000000000..68a5a8b3b52 --- /dev/null +++ b/vendor/github.com/h2non/filetype/types/split.go @@ -0,0 +1,11 @@ +package types + +import "strings" + +func splitMime(s string) (string, string) { + x := strings.Split(s, "/") + if len(x) > 1 { + return x[0], x[1] + } + return x[0], "" +} diff --git a/vendor/github.com/h2non/filetype/types/type.go b/vendor/github.com/h2non/filetype/types/type.go new file mode 100644 index 00000000000..5cf7dfc4bbc --- /dev/null +++ b/vendor/github.com/h2non/filetype/types/type.go @@ -0,0 +1,16 @@ +package types + +// Type represents a file MIME type and its extension +type Type struct { + MIME MIME + Extension string +} + +// NewType creates a new Type +func NewType(ext, mime string) Type { + t := Type{ + MIME: NewMIME(mime), + Extension: ext, + } + return Add(t) +} diff --git a/vendor/github.com/h2non/filetype/types/types.go b/vendor/github.com/h2non/filetype/types/types.go new file mode 100644 index 00000000000..27d433eec31 --- /dev/null +++ b/vendor/github.com/h2non/filetype/types/types.go @@ -0,0 +1,18 @@ +package types + +var Types = make(map[string]Type) + +// Add registers a new type in the package +func Add(t Type) Type { + Types[t.Extension] = t + return t +} + +// Get retrieves a Type by extension +func Get(ext string) Type { + kind := Types[ext] + if kind.Extension != "" { + return kind + } + return Unknown +} diff --git a/vendor/github.com/h2non/filetype/version.go b/vendor/github.com/h2non/filetype/version.go new file mode 100644 index 00000000000..fd46bf3ffc0 --- /dev/null +++ b/vendor/github.com/h2non/filetype/version.go @@ -0,0 +1,4 @@ +package filetype + +// Version exposes the current package version. +const Version = "1.0.12" diff --git a/vendor/github.com/tsg/go-daemon/src/god.c b/vendor/github.com/tsg/go-daemon/src/god.c deleted file mode 100644 index 7f63e081efd..00000000000 --- a/vendor/github.com/tsg/go-daemon/src/god.c +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2013-2014 Alexandre Fiori -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -void usage() { - printf( - "Use: god [options] [--] program [arguments]\n" - "Options:\n" - "-h --help show this help and exit\n" - "-v --version show version and exit\n" - "-f --foreground run in foreground\n" - "-n --nohup make the program immune to SIGHUP\n" - "-l --logfile FILE write the program's stdout and stderr to FILE\n" - "-p --pidfile FILE write pid to FILE\n" - "-r --rundir DIR switch to DIR before executing the program\n" - "-u --user USER switch to USER before executing the program\n" - "-g --group GROUP switch to GROUP before executing the program\n" - "\nThe program's output go to a blackhole if no logfile is set.\n" - "Log files are recycled on SIGHUP.\n" - ); - exit(1); -} - -static int nohup = 0; -static int logfd[2]; // pipe -static pid_t childpid = 0; -static FILE *logfp = NULL; -static FILE *pidfp = NULL; -static char logfile[PATH_MAX]; -static char pidfile[PATH_MAX]; -static char linebuf[1024]; -static struct passwd *pwd = NULL; -static struct group *grp = NULL; -static pthread_mutex_t logger_mutex; - -void daemon_main(int optind, char **argv); -void *logger_thread(void *cmdname); -void sighup(int signum); -void sigfwd(int signum); - -int main(int argc, char **argv) { - char rundir[PATH_MAX]; - char user[64]; - char group[64]; - int foreground = 0; - struct stat exec_stat; - - memset(logfile, 0, sizeof logfile); - memset(pidfile, 0, sizeof pidfile); - memset(rundir, 0, sizeof rundir); - memset(user, 0, sizeof user); - memset(group, 0, sizeof group); - - static struct option opts[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v' }, - { "foreground", no_argument, NULL, 'f' }, - { "nohup", no_argument, NULL, 'n' }, - { "logfile", required_argument, NULL, 'l' }, - { "pidfile", required_argument, NULL, 'p' }, - { "rundir", required_argument, NULL, 'r' }, - { "user", required_argument, NULL, 'u' }, - { "group", required_argument, NULL, 'g' }, - { NULL, 0, NULL, 0 }, - }; - - int ch; - while (1) { - ch = getopt_long(argc, argv, "l:p:r:u:g:hvfns", opts, NULL); - if (ch == -1) - break; - - switch (ch) { - case 'v': - printf("Go daemon v1.2\n"); - printf("http://github.com/fiorix/go-daemon\n"); - return 0; - case 'f': - foreground = 1; - break; - case 'n': - nohup = 1; - break; - case 'l': - strncpy(logfile, optarg, sizeof logfile - 1); - break; - case 'p': - strncpy(pidfile, optarg, sizeof pidfile - 1); - break; - case 'r': - strncpy(rundir, optarg, sizeof rundir - 1); - break; - case 'u': - strncpy(user, optarg, sizeof user - 1); - break; - case 'g': - strncpy(group, optarg, sizeof group - 1); - break; - default: - usage(); - } - } - - // utility is expected to be argv's leftovers. - if (optind >= argc) - usage(); - - if (*rundir != 0 && chdir(rundir) == -1) { - perror("failed to switch to rundir"); - return 1; - } - - if (*user != 0 && (pwd = getpwnam(user)) == NULL) { - fprintf(stderr, "failed to switch to user %s: %s\n", - user, strerror(errno)); - return 1; - } - - if (*group != 0 && (grp = getgrnam(group)) == NULL) { - fprintf(stderr, "failed to switch to group %s: %s\n", - group, strerror(errno)); - return 1; - } - - if (*logfile != 0 && (logfp = fopen(logfile, "a")) == NULL) { - perror("failed to open logfile"); - return 1; - } - if (logfp) - setvbuf(logfp, linebuf, _IOLBF, sizeof linebuf); - - if (*pidfile != 0 && (pidfp = fopen(pidfile, "w+")) == NULL) { - perror("failed to open pidfile"); - return 1; - } - - if (grp != NULL && setegid(grp->gr_gid) == -1) { - fprintf(stderr, "failed to switch to group %s: %s\n", - group, strerror(errno)); - return 1; - } - - if (pwd != NULL && seteuid(pwd->pw_uid) == -1) { - fprintf(stderr, "failed to switch to user %s: %s\n", - user, strerror(errno)); - return 1; - } - - if (stat(argv[optind], &exec_stat) < 0) { - fprintf(stderr, "failed to stat %s: %s\n", - argv[optind], strerror(errno)); - return 1; - } - if (!(exec_stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { - fprintf(stderr, "permission denied: %s\n", - argv[optind]); - return 1; - } - - if (foreground) { - daemon_main(optind, argv); - } else { - // Daemonize. - pid_t pid = fork(); - if (pid) { - waitpid(pid, NULL, 0); - } else if (!pid) { - if ((pid = fork())) { - exit(0); - } else if (!pid) { - close(0); - close(1); - close(2); - daemon_main(optind, argv); - } else { - perror("fork"); - exit(1); - } - } else { - perror("fork"); - exit(1); - } - } - - return 0; -} - -void daemon_main(int optind, char **argv) { - if (pidfp) { - fprintf(pidfp, "%d\n", getpid()); - fclose(pidfp); - } - // Fwd all signals to the child, except SIGHUP. - int signum; - for (signum = 1; signum < 33; signum++) { - if (signal(signum, sigfwd) == SIG_IGN) - signal(signum, SIG_IGN); - } - signal(SIGHUP, sighup); - pipe(logfd); - if ((childpid = fork())) { - close(logfd[1]); - pthread_t logth; - pthread_create(&logth, NULL, logger_thread, argv[optind]); - waitpid(childpid, NULL, 0); - pthread_join(logth, NULL); - } else if (!childpid) { - close(logfd[0]); - close(0); - close(1); - close(2); - dup2(logfd[1], 1); - dup2(logfd[1], 2); - execvp(argv[optind], argv + optind); - printf("\x1b%s", strerror(errno)); - fflush(stdout); - close(logfd[1]); - close(1); - close(2); - } else { - perror("fork"); - exit(1); - } - if (pidfp) - unlink(pidfile); -} - -void *logger_thread(void *cmdname) { - int n; - char buf[4096]; - int has_read = 0; - - while(1) { - // read() will fail when the child process fails - // to execute or dies, and closes its terminal. - // This is what terminates this thread and therefore - // the main thread can move along. - n = read(logfd[0], buf, sizeof buf); - if (n <= 0) - break; - - buf[n] = 0; - if (!has_read) { - has_read = 1; - if (*buf == '\x1b') { - char *p = buf; - printf("%s: %s\n", (char *) cmdname, ++p); - close(logfd[0]); - break; - } - } - - pthread_mutex_lock(&logger_mutex); - if (logfp) { - fwrite(buf, 1, n, logfp); - //fflush(logfp); - } - pthread_mutex_unlock(&logger_mutex); - } - - return NULL; -} - -void sighup(int signum) { - if (pwd != NULL) { - seteuid(getuid()); - } - if (grp != NULL) { - setegid(getgid()); - } - pthread_mutex_lock(&logger_mutex); - if (logfp) { - FILE *fp = fopen(logfile, "a"); - if (fp != NULL) { - fclose(logfp); - logfp = fp; - setvbuf(logfp, linebuf, _IOLBF, sizeof linebuf); - } - } - if (grp != NULL) { - setegid(grp->gr_gid); - } - if (pwd != NULL) { - seteuid(pwd->pw_uid); - } - pthread_mutex_unlock(&logger_mutex); - if (!nohup && childpid) // nonohup :~ - kill(childpid, signum); -} - -void sigfwd(int signum) { - if (childpid) - kill(childpid, signum); -} diff --git a/vendor/github.com/yuin/gopher-lua/parse/Makefile b/vendor/github.com/yuin/gopher-lua/parse/Makefile new file mode 100644 index 00000000000..b5b69096086 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/parse/Makefile @@ -0,0 +1,4 @@ +all : parser.go + +parser.go : parser.go.y + go tool yacc -o $@ parser.go.y; [ -f y.output ] && ( rm -f y.output ) diff --git a/vendor/github.com/yuin/gopher-lua/parse/parser.go.y b/vendor/github.com/yuin/gopher-lua/parse/parser.go.y new file mode 100644 index 00000000000..956133db292 --- /dev/null +++ b/vendor/github.com/yuin/gopher-lua/parse/parser.go.y @@ -0,0 +1,524 @@ +%{ +package parse + +import ( + "github.com/yuin/gopher-lua/ast" +) +%} +%type chunk +%type chunk1 +%type block +%type stat +%type elseifs +%type laststat +%type funcname +%type funcname1 +%type varlist +%type var +%type namelist +%type exprlist +%type expr +%type string +%type prefixexp +%type functioncall +%type afunctioncall +%type args +%type function +%type funcbody +%type parlist +%type tableconstructor +%type fieldlist +%type field +%type fieldsep + +%union { + token ast.Token + + stmts []ast.Stmt + stmt ast.Stmt + + funcname *ast.FuncName + funcexpr *ast.FunctionExpr + + exprlist []ast.Expr + expr ast.Expr + + fieldlist []*ast.Field + field *ast.Field + fieldsep string + + namelist []string + parlist *ast.ParList +} + +/* Reserved words */ +%token TAnd TBreak TDo TElse TElseIf TEnd TFalse TFor TFunction TIf TIn TLocal TNil TNot TOr TReturn TRepeat TThen TTrue TUntil TWhile + +/* Literals */ +%token TEqeq TNeq TLte TGte T2Comma T3Comma TIdent TNumber TString '{' '(' + +/* Operators */ +%left TOr +%left TAnd +%left '>' '<' TGte TLte TEqeq TNeq +%right T2Comma +%left '+' '-' +%left '*' '/' '%' +%right UNARY /* not # -(unary) */ +%right '^' + +%% + +chunk: + chunk1 { + $$ = $1 + if l, ok := yylex.(*Lexer); ok { + l.Stmts = $$ + } + } | + chunk1 laststat { + $$ = append($1, $2) + if l, ok := yylex.(*Lexer); ok { + l.Stmts = $$ + } + } | + chunk1 laststat ';' { + $$ = append($1, $2) + if l, ok := yylex.(*Lexer); ok { + l.Stmts = $$ + } + } + +chunk1: + { + $$ = []ast.Stmt{} + } | + chunk1 stat { + $$ = append($1, $2) + } | + chunk1 ';' { + $$ = $1 + } + +block: + chunk { + $$ = $1 + } + +stat: + varlist '=' exprlist { + $$ = &ast.AssignStmt{Lhs: $1, Rhs: $3} + $$.SetLine($1[0].Line()) + } | + /* 'stat = functioncal' causes a reduce/reduce conflict */ + prefixexp { + if _, ok := $1.(*ast.FuncCallExpr); !ok { + yylex.(*Lexer).Error("parse error") + } else { + $$ = &ast.FuncCallStmt{Expr: $1} + $$.SetLine($1.Line()) + } + } | + TDo block TEnd { + $$ = &ast.DoBlockStmt{Stmts: $2} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($3.Pos.Line) + } | + TWhile expr TDo block TEnd { + $$ = &ast.WhileStmt{Condition: $2, Stmts: $4} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($5.Pos.Line) + } | + TRepeat block TUntil expr { + $$ = &ast.RepeatStmt{Condition: $4, Stmts: $2} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($4.Line()) + } | + TIf expr TThen block elseifs TEnd { + $$ = &ast.IfStmt{Condition: $2, Then: $4} + cur := $$ + for _, elseif := range $5 { + cur.(*ast.IfStmt).Else = []ast.Stmt{elseif} + cur = elseif + } + $$.SetLine($1.Pos.Line) + $$.SetLastLine($6.Pos.Line) + } | + TIf expr TThen block elseifs TElse block TEnd { + $$ = &ast.IfStmt{Condition: $2, Then: $4} + cur := $$ + for _, elseif := range $5 { + cur.(*ast.IfStmt).Else = []ast.Stmt{elseif} + cur = elseif + } + cur.(*ast.IfStmt).Else = $7 + $$.SetLine($1.Pos.Line) + $$.SetLastLine($8.Pos.Line) + } | + TFor TIdent '=' expr ',' expr TDo block TEnd { + $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Stmts: $8} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($9.Pos.Line) + } | + TFor TIdent '=' expr ',' expr ',' expr TDo block TEnd { + $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Step:$8, Stmts: $10} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($11.Pos.Line) + } | + TFor namelist TIn exprlist TDo block TEnd { + $$ = &ast.GenericForStmt{Names:$2, Exprs:$4, Stmts: $6} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($7.Pos.Line) + } | + TFunction funcname funcbody { + $$ = &ast.FuncDefStmt{Name: $2, Func: $3} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($3.LastLine()) + } | + TLocal TFunction TIdent funcbody { + $$ = &ast.LocalAssignStmt{Names:[]string{$3.Str}, Exprs: []ast.Expr{$4}} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($4.LastLine()) + } | + TLocal namelist '=' exprlist { + $$ = &ast.LocalAssignStmt{Names: $2, Exprs:$4} + $$.SetLine($1.Pos.Line) + } | + TLocal namelist { + $$ = &ast.LocalAssignStmt{Names: $2, Exprs:[]ast.Expr{}} + $$.SetLine($1.Pos.Line) + } + +elseifs: + { + $$ = []ast.Stmt{} + } | + elseifs TElseIf expr TThen block { + $$ = append($1, &ast.IfStmt{Condition: $3, Then: $5}) + $$[len($$)-1].SetLine($2.Pos.Line) + } + +laststat: + TReturn { + $$ = &ast.ReturnStmt{Exprs:nil} + $$.SetLine($1.Pos.Line) + } | + TReturn exprlist { + $$ = &ast.ReturnStmt{Exprs:$2} + $$.SetLine($1.Pos.Line) + } | + TBreak { + $$ = &ast.BreakStmt{} + $$.SetLine($1.Pos.Line) + } + +funcname: + funcname1 { + $$ = $1 + } | + funcname1 ':' TIdent { + $$ = &ast.FuncName{Func:nil, Receiver:$1.Func, Method: $3.Str} + } + +funcname1: + TIdent { + $$ = &ast.FuncName{Func: &ast.IdentExpr{Value:$1.Str}} + $$.Func.SetLine($1.Pos.Line) + } | + funcname1 '.' TIdent { + key:= &ast.StringExpr{Value:$3.Str} + key.SetLine($3.Pos.Line) + fn := &ast.AttrGetExpr{Object: $1.Func, Key: key} + fn.SetLine($3.Pos.Line) + $$ = &ast.FuncName{Func: fn} + } + +varlist: + var { + $$ = []ast.Expr{$1} + } | + varlist ',' var { + $$ = append($1, $3) + } + +var: + TIdent { + $$ = &ast.IdentExpr{Value:$1.Str} + $$.SetLine($1.Pos.Line) + } | + prefixexp '[' expr ']' { + $$ = &ast.AttrGetExpr{Object: $1, Key: $3} + $$.SetLine($1.Line()) + } | + prefixexp '.' TIdent { + key := &ast.StringExpr{Value:$3.Str} + key.SetLine($3.Pos.Line) + $$ = &ast.AttrGetExpr{Object: $1, Key: key} + $$.SetLine($1.Line()) + } + +namelist: + TIdent { + $$ = []string{$1.Str} + } | + namelist ',' TIdent { + $$ = append($1, $3.Str) + } + +exprlist: + expr { + $$ = []ast.Expr{$1} + } | + exprlist ',' expr { + $$ = append($1, $3) + } + +expr: + TNil { + $$ = &ast.NilExpr{} + $$.SetLine($1.Pos.Line) + } | + TFalse { + $$ = &ast.FalseExpr{} + $$.SetLine($1.Pos.Line) + } | + TTrue { + $$ = &ast.TrueExpr{} + $$.SetLine($1.Pos.Line) + } | + TNumber { + $$ = &ast.NumberExpr{Value: $1.Str} + $$.SetLine($1.Pos.Line) + } | + T3Comma { + $$ = &ast.Comma3Expr{} + $$.SetLine($1.Pos.Line) + } | + function { + $$ = $1 + } | + prefixexp { + $$ = $1 + } | + string { + $$ = $1 + } | + tableconstructor { + $$ = $1 + } | + expr TOr expr { + $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "or", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr TAnd expr { + $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "and", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '>' expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '<' expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr TGte expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">=", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr TLte expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<=", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr TEqeq expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "==", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr TNeq expr { + $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "~=", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr T2Comma expr { + $$ = &ast.StringConcatOpExpr{Lhs: $1, Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '+' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "+", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '-' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "-", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '*' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "*", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '/' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "/", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '%' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "%", Rhs: $3} + $$.SetLine($1.Line()) + } | + expr '^' expr { + $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "^", Rhs: $3} + $$.SetLine($1.Line()) + } | + '-' expr %prec UNARY { + $$ = &ast.UnaryMinusOpExpr{Expr: $2} + $$.SetLine($2.Line()) + } | + TNot expr %prec UNARY { + $$ = &ast.UnaryNotOpExpr{Expr: $2} + $$.SetLine($2.Line()) + } | + '#' expr %prec UNARY { + $$ = &ast.UnaryLenOpExpr{Expr: $2} + $$.SetLine($2.Line()) + } + +string: + TString { + $$ = &ast.StringExpr{Value: $1.Str} + $$.SetLine($1.Pos.Line) + } + +prefixexp: + var { + $$ = $1 + } | + afunctioncall { + $$ = $1 + } | + functioncall { + $$ = $1 + } | + '(' expr ')' { + $$ = $2 + $$.SetLine($1.Pos.Line) + } + +afunctioncall: + '(' functioncall ')' { + $2.(*ast.FuncCallExpr).AdjustRet = true + $$ = $2 + } + +functioncall: + prefixexp args { + $$ = &ast.FuncCallExpr{Func: $1, Args: $2} + $$.SetLine($1.Line()) + } | + prefixexp ':' TIdent args { + $$ = &ast.FuncCallExpr{Method: $3.Str, Receiver: $1, Args: $4} + $$.SetLine($1.Line()) + } + +args: + '(' ')' { + if yylex.(*Lexer).PNewLine { + yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)") + } + $$ = []ast.Expr{} + } | + '(' exprlist ')' { + if yylex.(*Lexer).PNewLine { + yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)") + } + $$ = $2 + } | + tableconstructor { + $$ = []ast.Expr{$1} + } | + string { + $$ = []ast.Expr{$1} + } + +function: + TFunction funcbody { + $$ = &ast.FunctionExpr{ParList:$2.ParList, Stmts: $2.Stmts} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($2.LastLine()) + } + +funcbody: + '(' parlist ')' block TEnd { + $$ = &ast.FunctionExpr{ParList: $2, Stmts: $4} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($5.Pos.Line) + } | + '(' ')' block TEnd { + $$ = &ast.FunctionExpr{ParList: &ast.ParList{HasVargs: false, Names: []string{}}, Stmts: $3} + $$.SetLine($1.Pos.Line) + $$.SetLastLine($4.Pos.Line) + } + +parlist: + T3Comma { + $$ = &ast.ParList{HasVargs: true, Names: []string{}} + } | + namelist { + $$ = &ast.ParList{HasVargs: false, Names: []string{}} + $$.Names = append($$.Names, $1...) + } | + namelist ',' T3Comma { + $$ = &ast.ParList{HasVargs: true, Names: []string{}} + $$.Names = append($$.Names, $1...) + } + + +tableconstructor: + '{' '}' { + $$ = &ast.TableExpr{Fields: []*ast.Field{}} + $$.SetLine($1.Pos.Line) + } | + '{' fieldlist '}' { + $$ = &ast.TableExpr{Fields: $2} + $$.SetLine($1.Pos.Line) + } + + +fieldlist: + field { + $$ = []*ast.Field{$1} + } | + fieldlist fieldsep field { + $$ = append($1, $3) + } | + fieldlist fieldsep { + $$ = $1 + } + +field: + TIdent '=' expr { + $$ = &ast.Field{Key: &ast.StringExpr{Value:$1.Str}, Value: $3} + $$.Key.SetLine($1.Pos.Line) + } | + '[' expr ']' '=' expr { + $$ = &ast.Field{Key: $2, Value: $5} + } | + expr { + $$ = &ast.Field{Value: $1} + } + +fieldsep: + ',' { + $$ = "," + } | + ';' { + $$ = ";" + } + +%% + +func TokenName(c int) string { + if c >= TAnd && c-TAnd < len(yyToknames) { + if yyToknames[c-TAnd] != "" { + return yyToknames[c-TAnd] + } + } + return string([]byte{byte(c)}) +} + diff --git a/vendor/modules.txt b/vendor/modules.txt index f98dccb3804..8ffeb4c6fee 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -575,6 +575,11 @@ github.com/gorilla/websocket github.com/grpc-ecosystem/grpc-gateway/internal github.com/grpc-ecosystem/grpc-gateway/runtime github.com/grpc-ecosystem/grpc-gateway/utilities +# github.com/h2non/filetype v1.0.12 +github.com/h2non/filetype +github.com/h2non/filetype/matchers +github.com/h2non/filetype/matchers/isobmff +github.com/h2non/filetype/types # github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce github.com/hashicorp/errwrap # github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874 From 07a1df47a00cdf9da00c0f0ea550d7383f8d43a9 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Mon, 27 Apr 2020 10:32:14 -0400 Subject: [PATCH 03/10] Add ECS categorization fields --- auditbeat/module/file_integrity/action.go | 41 +++++++++++++++++++ auditbeat/module/file_integrity/event.go | 9 +++- auditbeat/module/file_integrity/event_test.go | 25 +++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/auditbeat/module/file_integrity/action.go b/auditbeat/module/file_integrity/action.go index 8f32b2884c5..607f565f65e 100644 --- a/auditbeat/module/file_integrity/action.go +++ b/auditbeat/module/file_integrity/action.go @@ -20,6 +20,8 @@ package file_integrity import ( "math/bits" "strings" + + "github.com/elastic/beats/v7/libbeat/common" ) // Action is a description of the changes described by an event. @@ -51,6 +53,17 @@ var actionNames = map[Action]string{ InitialScan: "initial_scan", } +var ecsActionNames = map[Action]string{ + None: "info", + AttributesModified: "change", + Created: "creation", + Deleted: "deletion", + Updated: "change", + Moved: "change", + ConfigChange: "change", + InitialScan: "info", +} + type actionOrderKey struct { ExistsBefore, ExistsNow bool Action Action @@ -102,6 +115,22 @@ func (action Action) String() string { return strings.Join(list, "|") } +// ECSTypes returns the ECS categorization types associated with the +// particular action. +func (action Action) ECSTypes() []string { + if name, found := ecsActionNames[action]; found { + return []string{ name } + } + var list []string + for flag, name := range ecsActionNames { + if action&flag != 0 { + action ^= flag + list = append(list, name) + } + } + return common.MakeStringSet(list...).ToSlice() +} + // MarshalText marshals the Action to a textual representation of itself. func (action Action) MarshalText() ([]byte, error) { return []byte(action.String()), nil } @@ -174,3 +203,15 @@ func (actions ActionArray) StringArray() []string { } return result } + +// ECSTypes returns the array of ECS categorization types for +// the set of actions. +func (actions ActionArray) ECSTypes() []string { + var list []string + for _, action := range actions { + list = append(list, action.ECSTypes()...) + } + return common.MakeStringSet(list...).ToSlice() +} + + diff --git a/auditbeat/module/file_integrity/event.go b/auditbeat/module/file_integrity/event.go index 72c2c8db640..8a775ef0acc 100644 --- a/auditbeat/module/file_integrity/event.go +++ b/auditbeat/module/file_integrity/event.go @@ -300,9 +300,14 @@ func buildMetricbeatEvent(e *Event, existedBefore bool) mb.Event { out.MetricSetFields.Put("hash", hashes) } + out.MetricSetFields.Put("event.kind", "event") + out.MetricSetFields.Put("event.category", []string{"file"}) if e.Action > 0 { - actions := e.Action.InOrder(existedBefore, e.Info != nil).StringArray() - out.MetricSetFields.Put("event.action", actions) + actions := e.Action.InOrder(existedBefore, e.Info != nil) + out.MetricSetFields.Put("event.type", actions.ECSTypes()) + out.MetricSetFields.Put("event.action", actions.StringArray()) + } else { + out.MetricSetFields.Put("event.type", None.ECSTypes()) } return out diff --git a/auditbeat/module/file_integrity/event_test.go b/auditbeat/module/file_integrity/event_test.go index 48831f5ac1e..8e1c1e4e2d9 100644 --- a/auditbeat/module/file_integrity/event_test.go +++ b/auditbeat/module/file_integrity/event_test.go @@ -290,6 +290,9 @@ func TestBuildEvent(t *testing.T) { assert.Equal(t, testEventTime, e.Timestamp) assertHasKey(t, fields, "event.action") + assertHasKey(t, fields, "event.kind") + assertHasKey(t, fields, "event.category") + assertHasKey(t, fields, "event.type") assertHasKey(t, fields, "file.path") assertHasKey(t, fields, "file.extension") @@ -330,6 +333,28 @@ func TestBuildEvent(t *testing.T) { assert.Error(t, err) }) } + t.Run("ecs categorization", func(t *testing.T) { + e := testEvent() + e.Action = ConfigChange + fields := buildMetricbeatEvent(e, false).MetricSetFields + types, err := fields.GetValue("event.type") + if err != nil { + t.Fatal(err) + } + ecsTypes, ok := types.([]string) + assert.True(t, ok) + assert.Equal(t, []string{"change"}, ecsTypes) + + e.Action = Action(Created | Updated | Deleted) + fields = buildMetricbeatEvent(e, false).MetricSetFields + types, err = fields.GetValue("event.type") + if err != nil { + t.Fatal(err) + } + ecsTypes, ok = types.([]string) + assert.True(t, ok) + assert.Equal(t, []string{"change", "creation", "deletion"}, ecsTypes) + }) t.Run("no setuid/setgid", func(t *testing.T) { e := testEvent() e.Info.SetGID = false From d3029582b07770cef055aee0bbb2968ff779f826 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Mon, 27 Apr 2020 11:03:49 -0400 Subject: [PATCH 04/10] mage fmt --- auditbeat/module/file_integrity/action.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/auditbeat/module/file_integrity/action.go b/auditbeat/module/file_integrity/action.go index 607f565f65e..dbdd531b7ec 100644 --- a/auditbeat/module/file_integrity/action.go +++ b/auditbeat/module/file_integrity/action.go @@ -119,7 +119,7 @@ func (action Action) String() string { // particular action. func (action Action) ECSTypes() []string { if name, found := ecsActionNames[action]; found { - return []string{ name } + return []string{name} } var list []string for flag, name := range ecsActionNames { @@ -213,5 +213,3 @@ func (actions ActionArray) ECSTypes() []string { } return common.MakeStringSet(list...).ToSlice() } - - From 85cf58125a8bf16098689180e00445ca55e4ddd6 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Mon, 27 Apr 2020 18:41:45 -0400 Subject: [PATCH 05/10] Update hash and NOTICE --- NOTICE.txt | 254 +++-------------------- auditbeat/module/file_integrity/event.go | 2 + 2 files changed, 33 insertions(+), 223 deletions(-) diff --git a/NOTICE.txt b/NOTICE.txt index 58a4e3299bd..f75b853171e 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -2466,229 +2466,6 @@ License type (autodetected): Apache-2.0 Apache License 2.0 --------------------------------------------------------------------- -Dependency: github.com/godror/godror/odpi -License type (autodetected): UPL-1.0 -./vendor/github.com/godror/godror/odpi/LICENSE.md: --------------------------------------------------------------------- -Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved. - -This program is free software: you can modify it and/or redistribute it under -the terms of: - -(i) the Universal Permissive License v 1.0 or at your option, any - later version (); and/or - -(ii) the Apache License v 2.0. () - - -The Universal Permissive License (UPL), Version 1.0 -=================================================== - -Subject to the condition set forth below, permission is hereby granted to any -person obtaining a copy of this software, associated documentation and/or data -(collectively the "Software"), free of charge and under any and all copyright -rights in the Software, and any and all patent rights owned or freely -licensable by each licensor hereunder covering either (i) the unmodified -Software as contributed to or provided by such licensor, or (ii) the Larger -Works (as defined below), to deal in both - -(a) the Software, and - -(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if - one is included with the Software (each a "Larger Work" to which the - Software is contributed by such licensors), - -without restriction, including without limitation the rights to copy, create -derivative works of, display, perform, and distribute the Software and make, -use, sell, offer for sale, import, export, have made, and have sold the -Software and the Larger Work(s), and to sublicense the foregoing rights on -either these or other terms. - -This license is subject to the following condition: - -The above copyright notice and either this complete permission notice or at a -minimum a reference to the UPL must be included in all copies or substantial -portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -Apache License -============== - -Version 2.0, January 2004 - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. **Definitions**. - - "License" shall mean the terms and conditions for use, reproduction, and - distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by the - copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all other - entities that control, are controlled by, or are under common control with - that entity. For the purposes of this definition, "control" means (i) the - power, direct or indirect, to cause the direction or management of such - entity, whether by contract or otherwise, or (ii) ownership of fifty - percent (50%) or more of the outstanding shares, or (iii) beneficial - ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity exercising - permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation source, - and configuration files. - - "Object" form shall mean any form resulting from mechanical transformation - or translation of a Source form, including but not limited to compiled - object code, generated documentation, and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or Object form, - made available under the License, as indicated by a copyright notice that - is included in or attached to the work (an example is provided in the - Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object form, - that is based on (or derived from) the Work and for which the editorial - revisions, annotations, elaborations, or other modifications represent, as - a whole, an original work of authorship. For the purposes of this License, - Derivative Works shall not include works that remain separable from, or - merely link (or bind by name) to the interfaces of, the Work and Derivative - Works thereof. - - "Contribution" shall mean any work of authorship, including the original - version of the Work and any modifications or additions to that Work or - Derivative Works thereof, that is intentionally submitted to Licensor for - inclusion in the Work by the copyright owner or by an individual or Legal - Entity authorized to submit on behalf of the copyright owner. For the - purposes of this definition, "submitted" means any form of electronic, - verbal, or written communication sent to the Licensor or its - representatives, including but not limited to communication on electronic - mailing lists, source code control systems, and issue tracking systems that - are managed by, or on behalf of, the Licensor for the purpose of discussing - and improving the Work, but excluding communication that is conspicuously - marked or otherwise designated in writing by the copyright owner as "Not a - Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity on - behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. **Grant of Copyright License.** Subject to the terms and conditions of this - License, each Contributor hereby grants to You a perpetual, worldwide, - non-exclusive, no-charge, royalty-free, irrevocable copyright license to - reproduce, prepare Derivative Works of, publicly display, publicly perform, - sublicense, and distribute the Work and such Derivative Works in Source or - Object form. - -3. **Grant of Patent License.** Subject to the terms and conditions of this - License, each Contributor hereby grants to You a perpetual, worldwide, - non-exclusive, no-charge, royalty-free, irrevocable (except as stated in - this section) patent license to make, have made, use, offer to sell, sell, - import, and otherwise transfer the Work, where such license applies only to - those patent claims licensable by such Contributor that are necessarily - infringed by their Contribution(s) alone or by combination of their - Contribution(s) with the Work to which such Contribution(s) was submitted. - If You institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work or a - Contribution incorporated within the Work constitutes direct or - contributory patent infringement, then any patent licenses granted to You - under this License for that Work shall terminate as of the date such - litigation is filed. - -4. **Redistribution.** You may reproduce and distribute copies of the Work or - Derivative Works thereof in any medium, with or without modifications, and - in Source or Object form, provided that You meet the following conditions: - - 1. You must give any other recipients of the Work or Derivative Works a - copy of this License; and - - 2. You must cause any modified files to carry prominent notices stating - that You changed the files; and - - 3. You must retain, in the Source form of any Derivative Works that You - distribute, all copyright, patent, trademark, and attribution notices - from the Source form of the Work, excluding those notices that do not - pertain to any part of the Derivative Works; and - - 4. If the Work includes a "NOTICE" text file as part of its distribution, - then any Derivative Works that You distribute must include a readable - copy of the attribution notices contained within such NOTICE file, - excluding those notices that do not pertain to any part of the - Derivative Works, in at least one of the following places: within a - NOTICE text file distributed as part of the Derivative Works; within - the Source form or documentation, if provided along with the Derivative - Works; or, within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents of the - NOTICE file are for informational purposes only and do not modify the - License. You may add Your own attribution notices within Derivative - Works that You distribute, alongside or as an addendum to the NOTICE - text from the Work, provided that such additional attribution notices - cannot be construed as modifying the License. - - You may add Your own copyright statement to Your modifications and may - provide additional or different license terms and conditions for use, - reproduction, or distribution of Your modifications, or for any such - Derivative Works as a whole, provided Your use, reproduction, and - distribution of the Work otherwise complies with the conditions stated - in this License. - -5. **Submission of Contributions.** Unless You explicitly state otherwise, any - Contribution intentionally submitted for inclusion in the Work by You to - the Licensor shall be under the terms and conditions of this License, - without any additional terms or conditions. Notwithstanding the above, - nothing herein shall supersede or modify the terms of any separate license - agreement you may have executed with Licensor regarding such Contributions. - -6. **Trademarks.** This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, except - as required for reasonable and customary use in describing the origin of - the Work and reproducing the content of the NOTICE file. - -7. **Disclaimer of Warranty.** Unless required by applicable law or agreed to - in writing, Licensor provides the Work (and each Contributor provides its - Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied, including, without limitation, any - warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or - FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for - determining the appropriateness of using or redistributing the Work and - assume any risks associated with Your exercise of permissions under this - License. - -8. **Limitation of Liability.** In no event and under no legal theory, whether - in tort (including negligence), contract, or otherwise, unless required by - applicable law (such as deliberate and grossly negligent acts) or agreed to - in writing, shall any Contributor be liable to You for damages, including - any direct, indirect, special, incidental, or consequential damages of any - character arising as a result of this License or out of the use or - inability to use the Work (including but not limited to damages for loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor has been - advised of the possibility of such damages. - -9. **Accepting Warranty or Additional Liability.** While redistributing the - Work or Derivative Works thereof, You may choose to offer, and charge a fee - for, acceptance of support, warranty, indemnity, or other liability - obligations and/or rights consistent with this License. However, in - accepting such obligations, You may act only on Your own behalf and on Your - sole responsibility, not on behalf of any other Contributor, and only if - You agree to indemnify, defend, and hold each Contributor harmless for any - liability incurred by, or claims asserted against, such Contributor by - reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -------------------------------------------------------------------- Dependency: github.com/gofrs/flock Version: v0.7.2 @@ -3216,6 +2993,37 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------- +Dependency: github.com/h2non/filetype +Version: v1.0.12 +License type (autodetected): MIT +./vendor/github.com/h2non/filetype/LICENSE: +-------------------------------------------------------------------- +The MIT License + +Copyright (c) Tomas Aparicio + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + -------------------------------------------------------------------- Dependency: github.com/hashicorp/errwrap Revision: 7554cd9344ce diff --git a/auditbeat/module/file_integrity/event.go b/auditbeat/module/file_integrity/event.go index 8a775ef0acc..50b856f190c 100644 --- a/auditbeat/module/file_integrity/event.go +++ b/auditbeat/module/file_integrity/event.go @@ -297,6 +297,8 @@ func buildMetricbeatEvent(e *Event, existedBefore bool) mb.Event { for hashType, digest := range e.Hashes { hashes[string(hashType)] = digest } + file["hash"] = hashes + // Remove this for 8.x out.MetricSetFields.Put("hash", hashes) } From 54595501f3458346785968fb5986290867be13f4 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Mon, 27 Apr 2020 18:43:20 -0400 Subject: [PATCH 06/10] Update test --- auditbeat/module/file_integrity/event_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/auditbeat/module/file_integrity/event_test.go b/auditbeat/module/file_integrity/event_test.go index 8e1c1e4e2d9..79d1309903d 100644 --- a/auditbeat/module/file_integrity/event_test.go +++ b/auditbeat/module/file_integrity/event_test.go @@ -313,6 +313,9 @@ func TestBuildEvent(t *testing.T) { assertHasKey(t, fields, "file.mode") } + assertHasKey(t, fields, "file.hash.sha1") + assertHasKey(t, fields, "file.hash.sha256") + // Remove in 8.x assertHasKey(t, fields, "hash.sha1") assertHasKey(t, fields, "hash.sha256") }) From f789d53a168e2dba7a92758576f5193b997d8431 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Mon, 27 Apr 2020 21:13:23 -0400 Subject: [PATCH 07/10] Run mage vendor --- NOTICE.txt | 223 + .../godror/godror/odpi/CONTRIBUTING.md | 1 + .../github.com/godror/godror/odpi/LICENSE.md | 217 + .../github.com/godror/godror/odpi/README.md | 63 + .../godror/godror/odpi/embed/README.md | 3 + .../github.com/godror/godror/odpi/embed/dpi.c | 50 + .../godror/godror/odpi/include/dpi.h | 1814 ++++++++ .../godror/godror/odpi/src/dpiConn.c | 2249 ++++++++++ .../godror/godror/odpi/src/dpiContext.c | 329 ++ .../godror/godror/odpi/src/dpiData.c | 899 ++++ .../godror/godror/odpi/src/dpiDebug.c | 183 + .../godror/godror/odpi/src/dpiDeqOptions.c | 369 ++ .../godror/godror/odpi/src/dpiEnqOptions.c | 173 + .../godror/godror/odpi/src/dpiEnv.c | 180 + .../godror/godror/odpi/src/dpiError.c | 222 + .../godror/godror/odpi/src/dpiErrorMessages.h | 90 + .../godror/godror/odpi/src/dpiGen.c | 307 ++ .../godror/godror/odpi/src/dpiGlobal.c | 291 ++ .../godror/godror/odpi/src/dpiHandleList.c | 116 + .../godror/godror/odpi/src/dpiHandlePool.c | 119 + .../godror/godror/odpi/src/dpiImpl.h | 1905 ++++++++ .../godror/godror/odpi/src/dpiLob.c | 504 +++ .../godror/godror/odpi/src/dpiMsgProps.c | 487 +++ .../godror/godror/odpi/src/dpiObject.c | 966 +++++ .../godror/godror/odpi/src/dpiObjectAttr.c | 114 + .../godror/godror/odpi/src/dpiObjectType.c | 344 ++ .../godror/godror/odpi/src/dpiOci.c | 3823 +++++++++++++++++ .../godror/godror/odpi/src/dpiOracleType.c | 504 +++ .../godror/godror/odpi/src/dpiPool.c | 586 +++ .../godror/godror/odpi/src/dpiQueue.c | 560 +++ .../godror/godror/odpi/src/dpiRowid.c | 134 + .../godror/godror/odpi/src/dpiSodaColl.c | 812 ++++ .../godror/odpi/src/dpiSodaCollCursor.c | 144 + .../godror/godror/odpi/src/dpiSodaDb.c | 431 ++ .../godror/godror/odpi/src/dpiSodaDoc.c | 231 + .../godror/godror/odpi/src/dpiSodaDocCursor.c | 144 + .../godror/godror/odpi/src/dpiStmt.c | 1898 ++++++++ .../godror/godror/odpi/src/dpiSubscr.c | 713 +++ .../godror/godror/odpi/src/dpiUtils.c | 401 ++ .../godror/godror/odpi/src/dpiVar.c | 1813 ++++++++ vendor/github.com/tsg/go-daemon/src/god.c | 313 ++ .../github.com/yuin/gopher-lua/parse/Makefile | 4 - .../yuin/gopher-lua/parse/parser.go.y | 524 --- 43 files changed, 24725 insertions(+), 528 deletions(-) create mode 100644 vendor/github.com/godror/godror/odpi/CONTRIBUTING.md create mode 100644 vendor/github.com/godror/godror/odpi/LICENSE.md create mode 100644 vendor/github.com/godror/godror/odpi/README.md create mode 100644 vendor/github.com/godror/godror/odpi/embed/README.md create mode 100644 vendor/github.com/godror/godror/odpi/embed/dpi.c create mode 100644 vendor/github.com/godror/godror/odpi/include/dpi.h create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiConn.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiContext.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiData.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiDebug.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiDeqOptions.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiEnqOptions.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiEnv.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiError.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiErrorMessages.h create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiGen.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiGlobal.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiHandleList.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiHandlePool.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiImpl.h create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiLob.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiMsgProps.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiObject.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiObjectAttr.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiObjectType.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiOci.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiOracleType.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiPool.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiQueue.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiRowid.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSodaColl.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSodaCollCursor.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSodaDb.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSodaDoc.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSodaDocCursor.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiStmt.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiSubscr.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiUtils.c create mode 100644 vendor/github.com/godror/godror/odpi/src/dpiVar.c create mode 100644 vendor/github.com/tsg/go-daemon/src/god.c delete mode 100644 vendor/github.com/yuin/gopher-lua/parse/Makefile delete mode 100644 vendor/github.com/yuin/gopher-lua/parse/parser.go.y diff --git a/NOTICE.txt b/NOTICE.txt index f75b853171e..268a4fd5d44 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -2466,6 +2466,229 @@ License type (autodetected): Apache-2.0 Apache License 2.0 +-------------------------------------------------------------------- +Dependency: github.com/godror/godror/odpi +License type (autodetected): UPL-1.0 +./vendor/github.com/godror/godror/odpi/LICENSE.md: +-------------------------------------------------------------------- +Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved. + +This program is free software: you can modify it and/or redistribute it under +the terms of: + +(i) the Universal Permissive License v 1.0 or at your option, any + later version (); and/or + +(ii) the Apache License v 2.0. () + + +The Universal Permissive License (UPL), Version 1.0 +=================================================== + +Subject to the condition set forth below, permission is hereby granted to any +person obtaining a copy of this software, associated documentation and/or data +(collectively the "Software"), free of charge and under any and all copyright +rights in the Software, and any and all patent rights owned or freely +licensable by each licensor hereunder covering either (i) the unmodified +Software as contributed to or provided by such licensor, or (ii) the Larger +Works (as defined below), to deal in both + +(a) the Software, and + +(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + one is included with the Software (each a "Larger Work" to which the + Software is contributed by such licensors), + +without restriction, including without limitation the rights to copy, create +derivative works of, display, perform, and distribute the Software and make, +use, sell, offer for sale, import, export, have made, and have sold the +Software and the Larger Work(s), and to sublicense the foregoing rights on +either these or other terms. + +This license is subject to the following condition: + +The above copyright notice and either this complete permission notice or at a +minimum a reference to the UPL must be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Apache License +============== + +Version 2.0, January 2004 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. **Definitions**. + + "License" shall mean the terms and conditions for use, reproduction, and + distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by the + copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all other + entities that control, are controlled by, or are under common control with + that entity. For the purposes of this definition, "control" means (i) the + power, direct or indirect, to cause the direction or management of such + entity, whether by contract or otherwise, or (ii) ownership of fifty + percent (50%) or more of the outstanding shares, or (iii) beneficial + ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity exercising + permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation source, + and configuration files. + + "Object" form shall mean any form resulting from mechanical transformation + or translation of a Source form, including but not limited to compiled + object code, generated documentation, and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or Object form, + made available under the License, as indicated by a copyright notice that + is included in or attached to the work (an example is provided in the + Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object form, + that is based on (or derived from) the Work and for which the editorial + revisions, annotations, elaborations, or other modifications represent, as + a whole, an original work of authorship. For the purposes of this License, + Derivative Works shall not include works that remain separable from, or + merely link (or bind by name) to the interfaces of, the Work and Derivative + Works thereof. + + "Contribution" shall mean any work of authorship, including the original + version of the Work and any modifications or additions to that Work or + Derivative Works thereof, that is intentionally submitted to Licensor for + inclusion in the Work by the copyright owner or by an individual or Legal + Entity authorized to submit on behalf of the copyright owner. For the + purposes of this definition, "submitted" means any form of electronic, + verbal, or written communication sent to the Licensor or its + representatives, including but not limited to communication on electronic + mailing lists, source code control systems, and issue tracking systems that + are managed by, or on behalf of, the Licensor for the purpose of discussing + and improving the Work, but excluding communication that is conspicuously + marked or otherwise designated in writing by the copyright owner as "Not a + Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on + behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. **Grant of Copyright License.** Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable copyright license to + reproduce, prepare Derivative Works of, publicly display, publicly perform, + sublicense, and distribute the Work and such Derivative Works in Source or + Object form. + +3. **Grant of Patent License.** Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable (except as stated in + this section) patent license to make, have made, use, offer to sell, sell, + import, and otherwise transfer the Work, where such license applies only to + those patent claims licensable by such Contributor that are necessarily + infringed by their Contribution(s) alone or by combination of their + Contribution(s) with the Work to which such Contribution(s) was submitted. + If You institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work or a + Contribution incorporated within the Work constitutes direct or + contributory patent infringement, then any patent licenses granted to You + under this License for that Work shall terminate as of the date such + litigation is filed. + +4. **Redistribution.** You may reproduce and distribute copies of the Work or + Derivative Works thereof in any medium, with or without modifications, and + in Source or Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works a + copy of this License; and + + 2. You must cause any modified files to carry prominent notices stating + that You changed the files; and + + 3. You must retain, in the Source form of any Derivative Works that You + distribute, all copyright, patent, trademark, and attribution notices + from the Source form of the Work, excluding those notices that do not + pertain to any part of the Derivative Works; and + + 4. If the Work includes a "NOTICE" text file as part of its distribution, + then any Derivative Works that You distribute must include a readable + copy of the attribution notices contained within such NOTICE file, + excluding those notices that do not pertain to any part of the + Derivative Works, in at least one of the following places: within a + NOTICE text file distributed as part of the Derivative Works; within + the Source form or documentation, if provided along with the Derivative + Works; or, within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents of the + NOTICE file are for informational purposes only and do not modify the + License. You may add Your own attribution notices within Derivative + Works that You distribute, alongside or as an addendum to the NOTICE + text from the Work, provided that such additional attribution notices + cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may + provide additional or different license terms and conditions for use, + reproduction, or distribution of Your modifications, or for any such + Derivative Works as a whole, provided Your use, reproduction, and + distribution of the Work otherwise complies with the conditions stated + in this License. + +5. **Submission of Contributions.** Unless You explicitly state otherwise, any + Contribution intentionally submitted for inclusion in the Work by You to + the Licensor shall be under the terms and conditions of this License, + without any additional terms or conditions. Notwithstanding the above, + nothing herein shall supersede or modify the terms of any separate license + agreement you may have executed with Licensor regarding such Contributions. + +6. **Trademarks.** This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, except + as required for reasonable and customary use in describing the origin of + the Work and reproducing the content of the NOTICE file. + +7. **Disclaimer of Warranty.** Unless required by applicable law or agreed to + in writing, Licensor provides the Work (and each Contributor provides its + Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied, including, without limitation, any + warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or + FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for + determining the appropriateness of using or redistributing the Work and + assume any risks associated with Your exercise of permissions under this + License. + +8. **Limitation of Liability.** In no event and under no legal theory, whether + in tort (including negligence), contract, or otherwise, unless required by + applicable law (such as deliberate and grossly negligent acts) or agreed to + in writing, shall any Contributor be liable to You for damages, including + any direct, indirect, special, incidental, or consequential damages of any + character arising as a result of this License or out of the use or + inability to use the Work (including but not limited to damages for loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor has been + advised of the possibility of such damages. + +9. **Accepting Warranty or Additional Liability.** While redistributing the + Work or Derivative Works thereof, You may choose to offer, and charge a fee + for, acceptance of support, warranty, indemnity, or other liability + obligations and/or rights consistent with this License. However, in + accepting such obligations, You may act only on Your own behalf and on Your + sole responsibility, not on behalf of any other Contributor, and only if + You agree to indemnify, defend, and hold each Contributor harmless for any + liability incurred by, or claims asserted against, such Contributor by + reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + -------------------------------------------------------------------- Dependency: github.com/gofrs/flock Version: v0.7.2 diff --git a/vendor/github.com/godror/godror/odpi/CONTRIBUTING.md b/vendor/github.com/godror/godror/odpi/CONTRIBUTING.md new file mode 100644 index 00000000000..272ff94f74a --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/CONTRIBUTING.md @@ -0,0 +1 @@ +Sorry, Pull Requests for ODPI-C cannot be accepted. Please report bugs and ask questions using [GitHub issues](https://github.com/oracle/odpi/issues) diff --git a/vendor/github.com/godror/godror/odpi/LICENSE.md b/vendor/github.com/godror/godror/odpi/LICENSE.md new file mode 100644 index 00000000000..cb344b76c16 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/LICENSE.md @@ -0,0 +1,217 @@ +Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved. + +This program is free software: you can modify it and/or redistribute it under +the terms of: + +(i) the Universal Permissive License v 1.0 or at your option, any + later version (); and/or + +(ii) the Apache License v 2.0. () + + +The Universal Permissive License (UPL), Version 1.0 +=================================================== + +Subject to the condition set forth below, permission is hereby granted to any +person obtaining a copy of this software, associated documentation and/or data +(collectively the "Software"), free of charge and under any and all copyright +rights in the Software, and any and all patent rights owned or freely +licensable by each licensor hereunder covering either (i) the unmodified +Software as contributed to or provided by such licensor, or (ii) the Larger +Works (as defined below), to deal in both + +(a) the Software, and + +(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + one is included with the Software (each a "Larger Work" to which the + Software is contributed by such licensors), + +without restriction, including without limitation the rights to copy, create +derivative works of, display, perform, and distribute the Software and make, +use, sell, offer for sale, import, export, have made, and have sold the +Software and the Larger Work(s), and to sublicense the foregoing rights on +either these or other terms. + +This license is subject to the following condition: + +The above copyright notice and either this complete permission notice or at a +minimum a reference to the UPL must be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Apache License +============== + +Version 2.0, January 2004 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. **Definitions**. + + "License" shall mean the terms and conditions for use, reproduction, and + distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by the + copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all other + entities that control, are controlled by, or are under common control with + that entity. For the purposes of this definition, "control" means (i) the + power, direct or indirect, to cause the direction or management of such + entity, whether by contract or otherwise, or (ii) ownership of fifty + percent (50%) or more of the outstanding shares, or (iii) beneficial + ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity exercising + permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation source, + and configuration files. + + "Object" form shall mean any form resulting from mechanical transformation + or translation of a Source form, including but not limited to compiled + object code, generated documentation, and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or Object form, + made available under the License, as indicated by a copyright notice that + is included in or attached to the work (an example is provided in the + Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object form, + that is based on (or derived from) the Work and for which the editorial + revisions, annotations, elaborations, or other modifications represent, as + a whole, an original work of authorship. For the purposes of this License, + Derivative Works shall not include works that remain separable from, or + merely link (or bind by name) to the interfaces of, the Work and Derivative + Works thereof. + + "Contribution" shall mean any work of authorship, including the original + version of the Work and any modifications or additions to that Work or + Derivative Works thereof, that is intentionally submitted to Licensor for + inclusion in the Work by the copyright owner or by an individual or Legal + Entity authorized to submit on behalf of the copyright owner. For the + purposes of this definition, "submitted" means any form of electronic, + verbal, or written communication sent to the Licensor or its + representatives, including but not limited to communication on electronic + mailing lists, source code control systems, and issue tracking systems that + are managed by, or on behalf of, the Licensor for the purpose of discussing + and improving the Work, but excluding communication that is conspicuously + marked or otherwise designated in writing by the copyright owner as "Not a + Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on + behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. **Grant of Copyright License.** Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable copyright license to + reproduce, prepare Derivative Works of, publicly display, publicly perform, + sublicense, and distribute the Work and such Derivative Works in Source or + Object form. + +3. **Grant of Patent License.** Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable (except as stated in + this section) patent license to make, have made, use, offer to sell, sell, + import, and otherwise transfer the Work, where such license applies only to + those patent claims licensable by such Contributor that are necessarily + infringed by their Contribution(s) alone or by combination of their + Contribution(s) with the Work to which such Contribution(s) was submitted. + If You institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work or a + Contribution incorporated within the Work constitutes direct or + contributory patent infringement, then any patent licenses granted to You + under this License for that Work shall terminate as of the date such + litigation is filed. + +4. **Redistribution.** You may reproduce and distribute copies of the Work or + Derivative Works thereof in any medium, with or without modifications, and + in Source or Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works a + copy of this License; and + + 2. You must cause any modified files to carry prominent notices stating + that You changed the files; and + + 3. You must retain, in the Source form of any Derivative Works that You + distribute, all copyright, patent, trademark, and attribution notices + from the Source form of the Work, excluding those notices that do not + pertain to any part of the Derivative Works; and + + 4. If the Work includes a "NOTICE" text file as part of its distribution, + then any Derivative Works that You distribute must include a readable + copy of the attribution notices contained within such NOTICE file, + excluding those notices that do not pertain to any part of the + Derivative Works, in at least one of the following places: within a + NOTICE text file distributed as part of the Derivative Works; within + the Source form or documentation, if provided along with the Derivative + Works; or, within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents of the + NOTICE file are for informational purposes only and do not modify the + License. You may add Your own attribution notices within Derivative + Works that You distribute, alongside or as an addendum to the NOTICE + text from the Work, provided that such additional attribution notices + cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may + provide additional or different license terms and conditions for use, + reproduction, or distribution of Your modifications, or for any such + Derivative Works as a whole, provided Your use, reproduction, and + distribution of the Work otherwise complies with the conditions stated + in this License. + +5. **Submission of Contributions.** Unless You explicitly state otherwise, any + Contribution intentionally submitted for inclusion in the Work by You to + the Licensor shall be under the terms and conditions of this License, + without any additional terms or conditions. Notwithstanding the above, + nothing herein shall supersede or modify the terms of any separate license + agreement you may have executed with Licensor regarding such Contributions. + +6. **Trademarks.** This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, except + as required for reasonable and customary use in describing the origin of + the Work and reproducing the content of the NOTICE file. + +7. **Disclaimer of Warranty.** Unless required by applicable law or agreed to + in writing, Licensor provides the Work (and each Contributor provides its + Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied, including, without limitation, any + warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or + FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for + determining the appropriateness of using or redistributing the Work and + assume any risks associated with Your exercise of permissions under this + License. + +8. **Limitation of Liability.** In no event and under no legal theory, whether + in tort (including negligence), contract, or otherwise, unless required by + applicable law (such as deliberate and grossly negligent acts) or agreed to + in writing, shall any Contributor be liable to You for damages, including + any direct, indirect, special, incidental, or consequential damages of any + character arising as a result of this License or out of the use or + inability to use the Work (including but not limited to damages for loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor has been + advised of the possibility of such damages. + +9. **Accepting Warranty or Additional Liability.** While redistributing the + Work or Derivative Works thereof, You may choose to offer, and charge a fee + for, acceptance of support, warranty, indemnity, or other liability + obligations and/or rights consistent with this License. However, in + accepting such obligations, You may act only on Your own behalf and on Your + sole responsibility, not on behalf of any other Contributor, and only if + You agree to indemnify, defend, and hold each Contributor harmless for any + liability incurred by, or claims asserted against, such Contributor by + reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/vendor/github.com/godror/godror/odpi/README.md b/vendor/github.com/godror/godror/odpi/README.md new file mode 100644 index 00000000000..fa911cc2130 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/README.md @@ -0,0 +1,63 @@ +# ODPI-C version 3.3 + +Oracle Database Programming Interface for C (ODPI-C) is an open source library +of C code that simplifies access to Oracle Database for applications written in +C or C++. It is a wrapper over [Oracle Call Interface +(OCI)](http://www.oracle.com/technetwork/database/features/oci/index.html) that +makes applications and language interfaces easier to develop. + +ODPI-C supports basic and advanced features of Oracle Database and +Oracle Client. See the [homepage](https://oracle.github.io/odpi/) for +a list. + +## Installation + +See [ODPI-C Installation](https://oracle.github.io/odpi/doc/installation.html). + +## Documentation + +See the [ODPI-C Documentation](https://oracle.github.io/odpi/doc/index.html) and +[Release Notes](https://oracle.github.io/odpi/doc/releasenotes.html). + +## Samples + +See [/samples](https://github.com/oracle/odpi/tree/master/samples). + +## Help + +Please report bugs and ask questions using [GitHub issues](https://github.com/oracle/odpi/issues). + +## Tests + +See [/test](https://github.com/oracle/odpi/tree/master/test). + +## Contributing + +See [CONTRIBUTING](https://github.com/oracle/odpi/blob/master/CONTRIBUTING.md). + +## Drivers Using ODPI-C + +Oracle Drivers: +* [cx_Oracle](https://oracle.github.io/python-cx_Oracle) Python interface. +* [node-oracledb](https://oracle.github.io/node-oracledb) Node.js module. + +Third-party Drivers: +* [go-goracle](https://gopkg.in/goracle.v2) Go Driver. +* [mirmir](https://github.com/rustyhorde/mimir) Rust Bindings. +* [odpic-raw](https://github.com/leptonyu/odpic-raw) Haskell Raw Bindings. +* [ruby-ODPI ](https://github.com/kubo/ruby-odpi) Ruby Interface. +* [rust-oracle ](https://github.com/kubo/rust-oracle) Driver for Rust. +* [Oracle.jl](https://github.com/felipenoris/Oracle.jl) Driver for Julia. +* [oranif](https://github.com/K2InformaticsGmbH/oranif) Driver for Erlang. + +## License + +Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + +This program is free software: you can modify it and/or redistribute it under +the terms of: + +(i) the Universal Permissive License v 1.0 or at your option, any + later version (); and/or + +(ii) the Apache License v 2.0. () diff --git a/vendor/github.com/godror/godror/odpi/embed/README.md b/vendor/github.com/godror/godror/odpi/embed/README.md new file mode 100644 index 00000000000..dfe0b4524c0 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/embed/README.md @@ -0,0 +1,3 @@ +This directory contains the file dpi.c which can be used to embed ODPI-C +within your project without having to manage the individual files that make up +the library. The files can also be compiled independently if that is preferred. diff --git a/vendor/github.com/godror/godror/odpi/embed/dpi.c b/vendor/github.com/godror/godror/odpi/embed/dpi.c new file mode 100644 index 00000000000..7d0c6dc83bb --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/embed/dpi.c @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpi.c +// Include this file in your project in order to embed ODPI-C source without +// having to compile files individually. Only the definitions in the file +// include/dpi.h are intended to be used publicly. Each file can also be +// compiled independently if that is preferable. +//----------------------------------------------------------------------------- + +#include "../src/dpiConn.c" +#include "../src/dpiContext.c" +#include "../src/dpiData.c" +#include "../src/dpiDebug.c" +#include "../src/dpiDeqOptions.c" +#include "../src/dpiEnqOptions.c" +#include "../src/dpiEnv.c" +#include "../src/dpiError.c" +#include "../src/dpiGen.c" +#include "../src/dpiGlobal.c" +#include "../src/dpiHandleList.c" +#include "../src/dpiHandlePool.c" +#include "../src/dpiLob.c" +#include "../src/dpiMsgProps.c" +#include "../src/dpiObjectAttr.c" +#include "../src/dpiObject.c" +#include "../src/dpiObjectType.c" +#include "../src/dpiOci.c" +#include "../src/dpiOracleType.c" +#include "../src/dpiPool.c" +#include "../src/dpiQueue.c" +#include "../src/dpiRowid.c" +#include "../src/dpiSodaColl.c" +#include "../src/dpiSodaCollCursor.c" +#include "../src/dpiSodaDb.c" +#include "../src/dpiSodaDoc.c" +#include "../src/dpiSodaDocCursor.c" +#include "../src/dpiStmt.c" +#include "../src/dpiSubscr.c" +#include "../src/dpiUtils.c" +#include "../src/dpiVar.c" diff --git a/vendor/github.com/godror/godror/odpi/include/dpi.h b/vendor/github.com/godror/godror/odpi/include/dpi.h new file mode 100644 index 00000000000..58b3a2d5867 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/include/dpi.h @@ -0,0 +1,1814 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpi.h +// Master include file for ODPI-C library. +//----------------------------------------------------------------------------- + +#ifndef DPI_PUBLIC +#define DPI_PUBLIC + +// define standard integer types for older versions of Microsoft Visual Studio +#ifdef _MSC_VER +#if _MSC_VER < 1600 +#define int8_t signed __int8 +#define int16_t signed __int16 +#define int32_t signed __int32 +#define int64_t signed __int64 +#define uint8_t unsigned __int8 +#define uint16_t unsigned __int16 +#define uint32_t unsigned __int32 +#define uint64_t unsigned __int64 +#endif +#endif + +#ifndef int8_t +#include +#endif + +// define __func__ for older versions of Microsoft Visual Studio +#ifdef _MSC_VER +#if _MSC_VER < 1900 +#define __func__ __FUNCTION__ +#endif +#endif + +// define ODPI-C version information +#define DPI_MAJOR_VERSION 3 +#define DPI_MINOR_VERSION 3 +#define DPI_PATCH_LEVEL 0 +#define DPI_VERSION_SUFFIX + +#define DPI_STR_HELPER(x) #x +#define DPI_STR(x) DPI_STR_HELPER(x) +#define DPI_VERSION_STRING \ + DPI_STR(DPI_MAJOR_VERSION) "." \ + DPI_STR(DPI_MINOR_VERSION) "." \ + DPI_STR(DPI_PATCH_LEVEL) \ + DPI_VERSION_SUFFIX +#define DPI_DEFAULT_DRIVER_NAME "ODPI-C : " DPI_VERSION_STRING + +#define DPI_VERSION_TO_NUMBER(major, minor, patch) \ + ((major * 10000) + (minor * 100) + patch) +#define DPI_VERSION_NUMBER \ + DPI_VERSION_TO_NUMBER(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, \ + DPI_PATCH_LEVEL) + +#define DPI_ORACLE_VERSION_TO_NUMBER(versionNum, releaseNum, updateNum, \ + portReleaseNum, portUpdateNum) \ + ((versionNum * 100000000) + (releaseNum * 1000000) + \ + (updateNum * 10000) + (portReleaseNum * 100) + (portUpdateNum)) + +// define default array size to use +#define DPI_DEFAULT_FETCH_ARRAY_SIZE 100 + +// define ping interval (in seconds) used when getting connections +#define DPI_DEFAULT_PING_INTERVAL 60 + +// define ping timeout (in milliseconds) used when getting connections +#define DPI_DEFAULT_PING_TIMEOUT 5000 + +// define constants for dequeue wait (AQ) +#define DPI_DEQ_WAIT_NO_WAIT 0 +#define DPI_DEQ_WAIT_FOREVER ((uint32_t) -1) + +// define maximum precision that can be supported by an int64_t value +#define DPI_MAX_INT64_PRECISION 18 + +// define constants for success and failure of methods +#define DPI_SUCCESS 0 +#define DPI_FAILURE -1 + +// set debug level (DPI_DEBUG_LEVEL) as a bitmask of desired flags +// reporting is to stderr +// 0x0001: reports errors during free +// 0x0002: reports on reference count changes +// 0x0004: reports on public function calls +// 0x0008: reports on all errors +// 0x0010: reports on all SQL statements +// 0x0020: reports on all memory allocations/frees +#define DPI_DEBUG_LEVEL_FREES 0x0001 +#define DPI_DEBUG_LEVEL_REFS 0x0002 +#define DPI_DEBUG_LEVEL_FNS 0x0004 +#define DPI_DEBUG_LEVEL_ERRORS 0x0008 +#define DPI_DEBUG_LEVEL_SQL 0x0010 +#define DPI_DEBUG_LEVEL_MEM 0x0020 + + +//----------------------------------------------------------------------------- +// Enumerations +//----------------------------------------------------------------------------- + + +// connection/pool authorization modes +typedef uint32_t dpiAuthMode; +#define DPI_MODE_AUTH_DEFAULT 0x00000000 +#define DPI_MODE_AUTH_SYSDBA 0x00000002 +#define DPI_MODE_AUTH_SYSOPER 0x00000004 +#define DPI_MODE_AUTH_PRELIM 0x00000008 +#define DPI_MODE_AUTH_SYSASM 0x00008000 +#define DPI_MODE_AUTH_SYSBKP 0x00020000 +#define DPI_MODE_AUTH_SYSDGD 0x00040000 +#define DPI_MODE_AUTH_SYSKMT 0x00080000 +#define DPI_MODE_AUTH_SYSRAC 0x00100000 + +// connection close modes +typedef uint32_t dpiConnCloseMode; +#define DPI_MODE_CONN_CLOSE_DEFAULT 0x0000 +#define DPI_MODE_CONN_CLOSE_DROP 0x0001 +#define DPI_MODE_CONN_CLOSE_RETAG 0x0002 + +// connection/pool creation modes +typedef uint32_t dpiCreateMode; +#define DPI_MODE_CREATE_DEFAULT 0x00000000 +#define DPI_MODE_CREATE_THREADED 0x00000001 +#define DPI_MODE_CREATE_EVENTS 0x00000004 + +// dequeue modes for advanced queuing +typedef uint32_t dpiDeqMode; +#define DPI_MODE_DEQ_BROWSE 1 +#define DPI_MODE_DEQ_LOCKED 2 +#define DPI_MODE_DEQ_REMOVE 3 +#define DPI_MODE_DEQ_REMOVE_NO_DATA 4 + +// dequeue navigation flags for advanced queuing +typedef uint32_t dpiDeqNavigation; +#define DPI_DEQ_NAV_FIRST_MSG 1 +#define DPI_DEQ_NAV_NEXT_TRANSACTION 2 +#define DPI_DEQ_NAV_NEXT_MSG 3 + +// event types +typedef uint32_t dpiEventType; +#define DPI_EVENT_NONE 0 +#define DPI_EVENT_STARTUP 1 +#define DPI_EVENT_SHUTDOWN 2 +#define DPI_EVENT_SHUTDOWN_ANY 3 +#define DPI_EVENT_DEREG 5 +#define DPI_EVENT_OBJCHANGE 6 +#define DPI_EVENT_QUERYCHANGE 7 +#define DPI_EVENT_AQ 100 + +// statement execution modes +typedef uint32_t dpiExecMode; +#define DPI_MODE_EXEC_DEFAULT 0x00000000 +#define DPI_MODE_EXEC_DESCRIBE_ONLY 0x00000010 +#define DPI_MODE_EXEC_COMMIT_ON_SUCCESS 0x00000020 +#define DPI_MODE_EXEC_BATCH_ERRORS 0x00000080 +#define DPI_MODE_EXEC_PARSE_ONLY 0x00000100 +#define DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS 0x00100000 + +// statement fetch modes +typedef uint16_t dpiFetchMode; +#define DPI_MODE_FETCH_NEXT 0x0002 +#define DPI_MODE_FETCH_FIRST 0x0004 +#define DPI_MODE_FETCH_LAST 0x0008 +#define DPI_MODE_FETCH_PRIOR 0x0010 +#define DPI_MODE_FETCH_ABSOLUTE 0x0020 +#define DPI_MODE_FETCH_RELATIVE 0x0040 + +// message delivery modes in advanced queuing +typedef uint16_t dpiMessageDeliveryMode; +#define DPI_MODE_MSG_PERSISTENT 1 +#define DPI_MODE_MSG_BUFFERED 2 +#define DPI_MODE_MSG_PERSISTENT_OR_BUFFERED 3 + +// message states in advanced queuing +typedef uint32_t dpiMessageState; +#define DPI_MSG_STATE_READY 0 +#define DPI_MSG_STATE_WAITING 1 +#define DPI_MSG_STATE_PROCESSED 2 +#define DPI_MSG_STATE_EXPIRED 3 + +// native C types +typedef uint32_t dpiNativeTypeNum; +#define DPI_NATIVE_TYPE_INT64 3000 +#define DPI_NATIVE_TYPE_UINT64 3001 +#define DPI_NATIVE_TYPE_FLOAT 3002 +#define DPI_NATIVE_TYPE_DOUBLE 3003 +#define DPI_NATIVE_TYPE_BYTES 3004 +#define DPI_NATIVE_TYPE_TIMESTAMP 3005 +#define DPI_NATIVE_TYPE_INTERVAL_DS 3006 +#define DPI_NATIVE_TYPE_INTERVAL_YM 3007 +#define DPI_NATIVE_TYPE_LOB 3008 +#define DPI_NATIVE_TYPE_OBJECT 3009 +#define DPI_NATIVE_TYPE_STMT 3010 +#define DPI_NATIVE_TYPE_BOOLEAN 3011 +#define DPI_NATIVE_TYPE_ROWID 3012 + +// operation codes (database change and continuous query notification) +typedef uint32_t dpiOpCode; +#define DPI_OPCODE_ALL_OPS 0x0 +#define DPI_OPCODE_ALL_ROWS 0x1 +#define DPI_OPCODE_INSERT 0x2 +#define DPI_OPCODE_UPDATE 0x4 +#define DPI_OPCODE_DELETE 0x8 +#define DPI_OPCODE_ALTER 0x10 +#define DPI_OPCODE_DROP 0x20 +#define DPI_OPCODE_UNKNOWN 0x40 + +// Oracle types +typedef uint32_t dpiOracleTypeNum; +#define DPI_ORACLE_TYPE_NONE 2000 +#define DPI_ORACLE_TYPE_VARCHAR 2001 +#define DPI_ORACLE_TYPE_NVARCHAR 2002 +#define DPI_ORACLE_TYPE_CHAR 2003 +#define DPI_ORACLE_TYPE_NCHAR 2004 +#define DPI_ORACLE_TYPE_ROWID 2005 +#define DPI_ORACLE_TYPE_RAW 2006 +#define DPI_ORACLE_TYPE_NATIVE_FLOAT 2007 +#define DPI_ORACLE_TYPE_NATIVE_DOUBLE 2008 +#define DPI_ORACLE_TYPE_NATIVE_INT 2009 +#define DPI_ORACLE_TYPE_NUMBER 2010 +#define DPI_ORACLE_TYPE_DATE 2011 +#define DPI_ORACLE_TYPE_TIMESTAMP 2012 +#define DPI_ORACLE_TYPE_TIMESTAMP_TZ 2013 +#define DPI_ORACLE_TYPE_TIMESTAMP_LTZ 2014 +#define DPI_ORACLE_TYPE_INTERVAL_DS 2015 +#define DPI_ORACLE_TYPE_INTERVAL_YM 2016 +#define DPI_ORACLE_TYPE_CLOB 2017 +#define DPI_ORACLE_TYPE_NCLOB 2018 +#define DPI_ORACLE_TYPE_BLOB 2019 +#define DPI_ORACLE_TYPE_BFILE 2020 +#define DPI_ORACLE_TYPE_STMT 2021 +#define DPI_ORACLE_TYPE_BOOLEAN 2022 +#define DPI_ORACLE_TYPE_OBJECT 2023 +#define DPI_ORACLE_TYPE_LONG_VARCHAR 2024 +#define DPI_ORACLE_TYPE_LONG_RAW 2025 +#define DPI_ORACLE_TYPE_NATIVE_UINT 2026 +#define DPI_ORACLE_TYPE_MAX 2027 + +// session pool close modes +typedef uint32_t dpiPoolCloseMode; +#define DPI_MODE_POOL_CLOSE_DEFAULT 0x0000 +#define DPI_MODE_POOL_CLOSE_FORCE 0x0001 + +// modes used when acquiring a connection from a session pool +typedef uint8_t dpiPoolGetMode; +#define DPI_MODE_POOL_GET_WAIT 0 +#define DPI_MODE_POOL_GET_NOWAIT 1 +#define DPI_MODE_POOL_GET_FORCEGET 2 +#define DPI_MODE_POOL_GET_TIMEDWAIT 3 + +// purity values when acquiring a connection from a pool +typedef uint32_t dpiPurity; +#define DPI_PURITY_DEFAULT 0 +#define DPI_PURITY_NEW 1 +#define DPI_PURITY_SELF 2 + +// database shutdown modes +typedef uint32_t dpiShutdownMode; +#define DPI_MODE_SHUTDOWN_DEFAULT 0 +#define DPI_MODE_SHUTDOWN_TRANSACTIONAL 1 +#define DPI_MODE_SHUTDOWN_TRANSACTIONAL_LOCAL 2 +#define DPI_MODE_SHUTDOWN_IMMEDIATE 3 +#define DPI_MODE_SHUTDOWN_ABORT 4 +#define DPI_MODE_SHUTDOWN_FINAL 5 + +// SODA flags +#define DPI_SODA_FLAGS_DEFAULT 0x00 +#define DPI_SODA_FLAGS_ATOMIC_COMMIT 0x01 +#define DPI_SODA_FLAGS_CREATE_COLL_MAP 0x02 +#define DPI_SODA_FLAGS_INDEX_DROP_FORCE 0x04 + +// database startup modes +typedef uint32_t dpiStartupMode; +#define DPI_MODE_STARTUP_DEFAULT 0 +#define DPI_MODE_STARTUP_FORCE 1 +#define DPI_MODE_STARTUP_RESTRICT 2 + +// statement types +typedef uint16_t dpiStatementType; +#define DPI_STMT_TYPE_UNKNOWN 0 +#define DPI_STMT_TYPE_SELECT 1 +#define DPI_STMT_TYPE_UPDATE 2 +#define DPI_STMT_TYPE_DELETE 3 +#define DPI_STMT_TYPE_INSERT 4 +#define DPI_STMT_TYPE_CREATE 5 +#define DPI_STMT_TYPE_DROP 6 +#define DPI_STMT_TYPE_ALTER 7 +#define DPI_STMT_TYPE_BEGIN 8 +#define DPI_STMT_TYPE_DECLARE 9 +#define DPI_STMT_TYPE_CALL 10 +#define DPI_STMT_TYPE_EXPLAIN_PLAN 15 +#define DPI_STMT_TYPE_MERGE 16 +#define DPI_STMT_TYPE_ROLLBACK 17 +#define DPI_STMT_TYPE_COMMIT 21 + +// subscription grouping classes +typedef uint8_t dpiSubscrGroupingClass; +#define DPI_SUBSCR_GROUPING_CLASS_TIME 1 + +// subscription grouping types +typedef uint8_t dpiSubscrGroupingType; +#define DPI_SUBSCR_GROUPING_TYPE_SUMMARY 1 +#define DPI_SUBSCR_GROUPING_TYPE_LAST 2 + +// subscription namespaces +typedef uint32_t dpiSubscrNamespace; +#define DPI_SUBSCR_NAMESPACE_AQ 1 +#define DPI_SUBSCR_NAMESPACE_DBCHANGE 2 + +// subscription protocols +typedef uint32_t dpiSubscrProtocol; +#define DPI_SUBSCR_PROTO_CALLBACK 0 +#define DPI_SUBSCR_PROTO_MAIL 1 +#define DPI_SUBSCR_PROTO_PLSQL 2 +#define DPI_SUBSCR_PROTO_HTTP 3 + +// subscription quality of service +typedef uint32_t dpiSubscrQOS; +#define DPI_SUBSCR_QOS_RELIABLE 0x01 +#define DPI_SUBSCR_QOS_DEREG_NFY 0x02 +#define DPI_SUBSCR_QOS_ROWIDS 0x04 +#define DPI_SUBSCR_QOS_QUERY 0x08 +#define DPI_SUBSCR_QOS_BEST_EFFORT 0x10 + +// visibility of messages in advanced queuing +typedef uint32_t dpiVisibility; +#define DPI_VISIBILITY_IMMEDIATE 1 +#define DPI_VISIBILITY_ON_COMMIT 2 + + +//----------------------------------------------------------------------------- +// Handle Types +//----------------------------------------------------------------------------- +typedef struct dpiConn dpiConn; +typedef struct dpiPool dpiPool; +typedef struct dpiStmt dpiStmt; +typedef struct dpiVar dpiVar; +typedef struct dpiLob dpiLob; +typedef struct dpiObject dpiObject; +typedef struct dpiObjectAttr dpiObjectAttr; +typedef struct dpiObjectType dpiObjectType; +typedef struct dpiRowid dpiRowid; +typedef struct dpiSubscr dpiSubscr; +typedef struct dpiDeqOptions dpiDeqOptions; +typedef struct dpiEnqOptions dpiEnqOptions; +typedef struct dpiMsgProps dpiMsgProps; + + +//----------------------------------------------------------------------------- +// Complex Native Data Types (used for transferring data to/from ODPI-C) +//----------------------------------------------------------------------------- + +// structure used for transferring byte strings to/from ODPI-C +typedef struct { + char *ptr; + uint32_t length; + const char *encoding; +} dpiBytes; + +// structure used for transferring day/seconds intervals to/from ODPI-C +typedef struct { + int32_t days; + int32_t hours; + int32_t minutes; + int32_t seconds; + int32_t fseconds; +} dpiIntervalDS; + +// structure used for transferring years/months intervals to/from ODPI-C +typedef struct { + int32_t years; + int32_t months; +} dpiIntervalYM; + +// structure used for transferring dates to/from ODPI-C +typedef struct { + int16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint32_t fsecond; + int8_t tzHourOffset; + int8_t tzMinuteOffset; +} dpiTimestamp; + + +//----------------------------------------------------------------------------- +// Other Types +//----------------------------------------------------------------------------- + +// forward declarations +typedef struct dpiAppContext dpiAppContext; +typedef struct dpiCommonCreateParams dpiCommonCreateParams; +typedef struct dpiConnCreateParams dpiConnCreateParams; +typedef struct dpiContext dpiContext; +typedef struct dpiData dpiData; +typedef struct dpiDataTypeInfo dpiDataTypeInfo; +typedef struct dpiEncodingInfo dpiEncodingInfo; +typedef struct dpiErrorInfo dpiErrorInfo; +typedef struct dpiObjectAttrInfo dpiObjectAttrInfo; +typedef struct dpiObjectTypeInfo dpiObjectTypeInfo; +typedef struct dpiPoolCreateParams dpiPoolCreateParams; +typedef struct dpiQueryInfo dpiQueryInfo; +typedef struct dpiQueue dpiQueue; +typedef struct dpiShardingKeyColumn dpiShardingKeyColumn; +typedef struct dpiSodaColl dpiSodaColl; +typedef struct dpiSodaCollNames dpiSodaCollNames; +typedef struct dpiSodaCollCursor dpiSodaCollCursor; +typedef struct dpiSodaDb dpiSodaDb; +typedef struct dpiSodaDoc dpiSodaDoc; +typedef struct dpiSodaDocCursor dpiSodaDocCursor; +typedef struct dpiSodaOperOptions dpiSodaOperOptions; +typedef struct dpiStmtInfo dpiStmtInfo; +typedef struct dpiSubscrCreateParams dpiSubscrCreateParams; +typedef struct dpiSubscrMessage dpiSubscrMessage; +typedef struct dpiSubscrMessageQuery dpiSubscrMessageQuery; +typedef struct dpiSubscrMessageRow dpiSubscrMessageRow; +typedef struct dpiSubscrMessageTable dpiSubscrMessageTable; +typedef struct dpiVersionInfo dpiVersionInfo; + +// union used for providing a buffer of any data type +typedef union { + int asBoolean; + int64_t asInt64; + uint64_t asUint64; + float asFloat; + double asDouble; + dpiBytes asBytes; + dpiTimestamp asTimestamp; + dpiIntervalDS asIntervalDS; + dpiIntervalYM asIntervalYM; + dpiLob *asLOB; + dpiObject *asObject; + dpiStmt *asStmt; + dpiRowid *asRowid; +} dpiDataBuffer; + +// structure used for application context +struct dpiAppContext { + const char *namespaceName; + uint32_t namespaceNameLength; + const char *name; + uint32_t nameLength; + const char *value; + uint32_t valueLength; +}; + +// structure used for common parameters used for creating standalone +// connections and session pools +struct dpiCommonCreateParams { + dpiCreateMode createMode; + const char *encoding; + const char *nencoding; + const char *edition; + uint32_t editionLength; + const char *driverName; + uint32_t driverNameLength; +}; + +// structure used for creating connections +struct dpiConnCreateParams { + dpiAuthMode authMode; + const char *connectionClass; + uint32_t connectionClassLength; + dpiPurity purity; + const char *newPassword; + uint32_t newPasswordLength; + dpiAppContext *appContext; + uint32_t numAppContext; + int externalAuth; + void *externalHandle; + dpiPool *pool; + const char *tag; + uint32_t tagLength; + int matchAnyTag; + const char *outTag; + uint32_t outTagLength; + int outTagFound; + dpiShardingKeyColumn *shardingKeyColumns; + uint8_t numShardingKeyColumns; + dpiShardingKeyColumn *superShardingKeyColumns; + uint8_t numSuperShardingKeyColumns; + int outNewSession; +}; + +// structure used for transferring data to/from ODPI-C +struct dpiData { + int isNull; + dpiDataBuffer value; +}; + +// structure used for providing metadata about data types +struct dpiDataTypeInfo { + dpiOracleTypeNum oracleTypeNum; + dpiNativeTypeNum defaultNativeTypeNum; + uint16_t ociTypeCode; + uint32_t dbSizeInBytes; + uint32_t clientSizeInBytes; + uint32_t sizeInChars; + int16_t precision; + int8_t scale; + uint8_t fsPrecision; + dpiObjectType *objectType; +}; + +// structure used for transferring encoding information from ODPI-C +struct dpiEncodingInfo { + const char *encoding; + int32_t maxBytesPerCharacter; + const char *nencoding; + int32_t nmaxBytesPerCharacter; +}; + +// structure used for transferring error information from ODPI-C +struct dpiErrorInfo { + int32_t code; + uint16_t offset; + const char *message; + uint32_t messageLength; + const char *encoding; + const char *fnName; + const char *action; + const char *sqlState; + int isRecoverable; +}; + +// structure used for transferring object attribute information from ODPI-C +struct dpiObjectAttrInfo { + const char *name; + uint32_t nameLength; + dpiDataTypeInfo typeInfo; +}; + +// structure used for transferring object type information from ODPI-C +struct dpiObjectTypeInfo { + const char *schema; + uint32_t schemaLength; + const char *name; + uint32_t nameLength; + int isCollection; + dpiDataTypeInfo elementTypeInfo; + uint16_t numAttributes; +}; + +// structure used for creating pools +struct dpiPoolCreateParams { + uint32_t minSessions; + uint32_t maxSessions; + uint32_t sessionIncrement; + int pingInterval; + int pingTimeout; + int homogeneous; + int externalAuth; + dpiPoolGetMode getMode; + const char *outPoolName; + uint32_t outPoolNameLength; + uint32_t timeout; + uint32_t waitTimeout; + uint32_t maxLifetimeSession; + const char *plsqlFixupCallback; + uint32_t plsqlFixupCallbackLength; + uint32_t maxSessionsPerShard; +}; + +// structure used for transferring query metadata from ODPI-C +struct dpiQueryInfo { + const char *name; + uint32_t nameLength; + dpiDataTypeInfo typeInfo; + int nullOk; +}; + +// structure used for sharding key columns +struct dpiShardingKeyColumn { + dpiOracleTypeNum oracleTypeNum; + dpiNativeTypeNum nativeTypeNum; + dpiDataBuffer value; +}; + +// structure used for getting collection names from the database +struct dpiSodaCollNames { + uint32_t numNames; + const char **names; + uint32_t *nameLengths; +}; + +// structure used for SODA operations (find/replace/remove) +struct dpiSodaOperOptions { + uint32_t numKeys; + const char **keys; + uint32_t *keyLengths; + const char *key; + uint32_t keyLength; + const char *version; + uint32_t versionLength; + const char *filter; + uint32_t filterLength; + uint32_t skip; + uint32_t limit; +}; + +// structure used for transferring statement information from ODPI-C +struct dpiStmtInfo { + int isQuery; + int isPLSQL; + int isDDL; + int isDML; + dpiStatementType statementType; + int isReturning; +}; + +// callback for subscriptions +typedef void (*dpiSubscrCallback)(void* context, dpiSubscrMessage *message); + +// structure used for creating subscriptions +struct dpiSubscrCreateParams { + dpiSubscrNamespace subscrNamespace; + dpiSubscrProtocol protocol; + dpiSubscrQOS qos; + dpiOpCode operations; + uint32_t portNumber; + uint32_t timeout; + const char *name; + uint32_t nameLength; + dpiSubscrCallback callback; + void *callbackContext; + const char *recipientName; + uint32_t recipientNameLength; + const char *ipAddress; + uint32_t ipAddressLength; + uint8_t groupingClass; + uint32_t groupingValue; + uint8_t groupingType; + uint64_t outRegId; + int clientInitiated; +}; + +// structure used for transferring messages in subscription callbacks +struct dpiSubscrMessage { + dpiEventType eventType; + const char *dbName; + uint32_t dbNameLength; + dpiSubscrMessageTable *tables; + uint32_t numTables; + dpiSubscrMessageQuery *queries; + uint32_t numQueries; + dpiErrorInfo *errorInfo; + const void *txId; + uint32_t txIdLength; + int registered; + const char *queueName; + uint32_t queueNameLength; + const char *consumerName; + uint32_t consumerNameLength; +}; + +// structure used for transferring query information in messages in +// subscription callbacks (continuous query notification) +struct dpiSubscrMessageQuery { + uint64_t id; + dpiOpCode operation; + dpiSubscrMessageTable *tables; + uint32_t numTables; +}; + +// structure used for transferring row information in messages in +// subscription callbacks +struct dpiSubscrMessageRow { + dpiOpCode operation; + const char *rowid; + uint32_t rowidLength; +}; + +// structure used for transferring table information in messages in +// subscription callbacks +struct dpiSubscrMessageTable { + dpiOpCode operation; + const char *name; + uint32_t nameLength; + dpiSubscrMessageRow *rows; + uint32_t numRows; +}; + +// structure used for transferring version information +struct dpiVersionInfo { + int versionNum; + int releaseNum; + int updateNum; + int portReleaseNum; + int portUpdateNum; + uint32_t fullVersionNum; +}; + + +//----------------------------------------------------------------------------- +// Context Methods (dpiContext) +//----------------------------------------------------------------------------- + +// create a context handle and validate the version information +int dpiContext_create(unsigned int majorVersion, unsigned int minorVersion, + dpiContext **context, dpiErrorInfo *errorInfo); + +// destroy context handle +int dpiContext_destroy(dpiContext *context); + +// return the OCI client version in use +int dpiContext_getClientVersion(const dpiContext *context, + dpiVersionInfo *versionInfo); + +// get error information +void dpiContext_getError(const dpiContext *context, dpiErrorInfo *errorInfo); + +// initialize context parameters to default values +int dpiContext_initCommonCreateParams(const dpiContext *context, + dpiCommonCreateParams *params); + +// initialize connection create parameters to default values +int dpiContext_initConnCreateParams(const dpiContext *context, + dpiConnCreateParams *params); + +// initialize pool create parameters to default values +int dpiContext_initPoolCreateParams(const dpiContext *context, + dpiPoolCreateParams *params); + +// initialize SODA operation options to default values +int dpiContext_initSodaOperOptions(const dpiContext *context, + dpiSodaOperOptions *options); + +// initialize subscription create parameters to default values +int dpiContext_initSubscrCreateParams(const dpiContext *context, + dpiSubscrCreateParams *params); + + +//----------------------------------------------------------------------------- +// Connection Methods (dpiConn) +//----------------------------------------------------------------------------- + +// add a reference to a connection +int dpiConn_addRef(dpiConn *conn); + +// begin a distributed transaction +int dpiConn_beginDistribTrans(dpiConn *conn, long formatId, + const char *transactionId, uint32_t transactionIdLength, + const char *branchId, uint32_t branchIdLength); + +// break execution of the statement running on the connection +int dpiConn_breakExecution(dpiConn *conn); + +// change the password for the specified user +int dpiConn_changePassword(dpiConn *conn, const char *userName, + uint32_t userNameLength, const char *oldPassword, + uint32_t oldPasswordLength, const char *newPassword, + uint32_t newPasswordLength); + +// close the connection now, not when the reference count reaches zero +int dpiConn_close(dpiConn *conn, dpiConnCloseMode mode, const char *tag, + uint32_t tagLength); + +// commits the current active transaction +int dpiConn_commit(dpiConn *conn); + +// create a connection and return a reference to it +int dpiConn_create(const dpiContext *context, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + const char *connectString, uint32_t connectStringLength, + const dpiCommonCreateParams *commonParams, + dpiConnCreateParams *createParams, dpiConn **conn); + +// dequeue a message from a queue +int dpiConn_deqObject(dpiConn *conn, const char *queueName, + uint32_t queueNameLength, dpiDeqOptions *options, dpiMsgProps *props, + dpiObject *payload, const char **msgId, uint32_t *msgIdLength); + +// enqueue a message to a queue +int dpiConn_enqObject(dpiConn *conn, const char *queueName, + uint32_t queueNameLength, dpiEnqOptions *options, dpiMsgProps *props, + dpiObject *payload, const char **msgId, uint32_t *msgIdLength); + +// get call timeout in place for round-trips with this connection +int dpiConn_getCallTimeout(dpiConn *conn, uint32_t *value); + +// get current schema associated with the connection +int dpiConn_getCurrentSchema(dpiConn *conn, const char **value, + uint32_t *valueLength); + +// get edition associated with the connection +int dpiConn_getEdition(dpiConn *conn, const char **value, + uint32_t *valueLength); + +// return the encoding information used by the connection +int dpiConn_getEncodingInfo(dpiConn *conn, dpiEncodingInfo *info); + +// get external name associated with the connection +int dpiConn_getExternalName(dpiConn *conn, const char **value, + uint32_t *valueLength); + +// get the OCI service context handle associated with the connection +int dpiConn_getHandle(dpiConn *conn, void **handle); + +// get internal name associated with the connection +int dpiConn_getInternalName(dpiConn *conn, const char **value, + uint32_t *valueLength); + +// get logical transaction id associated with the connection +int dpiConn_getLTXID(dpiConn *conn, const char **value, uint32_t *valueLength); + +// create a new object type and return it for subsequent object creation +int dpiConn_getObjectType(dpiConn *conn, const char *name, uint32_t nameLength, + dpiObjectType **objType); + +// return information about the server version in use +int dpiConn_getServerVersion(dpiConn *conn, const char **releaseString, + uint32_t *releaseStringLength, dpiVersionInfo *versionInfo); + +// get SODA interface object +int dpiConn_getSodaDb(dpiConn *conn, dpiSodaDb **db); + +// return the statement cache size +int dpiConn_getStmtCacheSize(dpiConn *conn, uint32_t *cacheSize); + +// create a new dequeue options object and return it +int dpiConn_newDeqOptions(dpiConn *conn, dpiDeqOptions **options); + +// create a new enqueue options object and return it +int dpiConn_newEnqOptions(dpiConn *conn, dpiEnqOptions **options); + +// create a new message properties object and return it +int dpiConn_newMsgProps(dpiConn *conn, dpiMsgProps **props); + +// create a new AQ queue +int dpiConn_newQueue(dpiConn *conn, const char *name, uint32_t nameLength, + dpiObjectType *payloadType, dpiQueue **queue); + +// create a new temporary LOB +int dpiConn_newTempLob(dpiConn *conn, dpiOracleTypeNum lobType, dpiLob **lob); + +// create a new variable and return it for subsequent binding/defining +int dpiConn_newVar(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, + dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, + int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, + dpiData **data); + +// ping the connection to see if it is still alive +int dpiConn_ping(dpiConn *conn); + +// prepare a distributed transaction for commit +int dpiConn_prepareDistribTrans(dpiConn *conn, int *commitNeeded); + +// prepare a statement and return it for subsequent execution/fetching +int dpiConn_prepareStmt(dpiConn *conn, int scrollable, const char *sql, + uint32_t sqlLength, const char *tag, uint32_t tagLength, + dpiStmt **stmt); + +// release a reference to the connection +int dpiConn_release(dpiConn *conn); + +// rolls back the current active transaction +int dpiConn_rollback(dpiConn *conn); + +// set action associated with the connection +int dpiConn_setAction(dpiConn *conn, const char *value, uint32_t valueLength); + +// set call timeout for subsequent round-trips with this connection +int dpiConn_setCallTimeout(dpiConn *conn, uint32_t value); + +// set client identifier associated with the connection +int dpiConn_setClientIdentifier(dpiConn *conn, const char *value, + uint32_t valueLength); + +// set client info associated with the connection +int dpiConn_setClientInfo(dpiConn *conn, const char *value, + uint32_t valueLength); + +// set current schema associated with the connection +int dpiConn_setCurrentSchema(dpiConn *conn, const char *value, + uint32_t valueLength); + +// set database operation associated with the connection +int dpiConn_setDbOp(dpiConn *conn, const char *value, uint32_t valueLength); + +// set external name associated with the connection +int dpiConn_setExternalName(dpiConn *conn, const char *value, + uint32_t valueLength); + +// set internal name associated with the connection +int dpiConn_setInternalName(dpiConn *conn, const char *value, + uint32_t valueLength); + +// set module associated with the connection +int dpiConn_setModule(dpiConn *conn, const char *value, uint32_t valueLength); + +// set the statement cache size +int dpiConn_setStmtCacheSize(dpiConn *conn, uint32_t cacheSize); + +// shutdown the database +int dpiConn_shutdownDatabase(dpiConn *conn, dpiShutdownMode mode); + +// startup the database +int dpiConn_startupDatabase(dpiConn *conn, dpiStartupMode mode); + +// subscribe to events in the database +int dpiConn_subscribe(dpiConn *conn, dpiSubscrCreateParams *params, + dpiSubscr **subscr); + +// unsubscribe from events in the database +int dpiConn_unsubscribe(dpiConn *conn, dpiSubscr *subscr); + + +//----------------------------------------------------------------------------- +// Data Methods (dpiData) +//----------------------------------------------------------------------------- + +// return the boolean portion of the data +int dpiData_getBool(dpiData *data); + +// return the bytes portion of the data +dpiBytes *dpiData_getBytes(dpiData *data); + +// return the double portion of the data +double dpiData_getDouble(dpiData *data); + +// return the float portion of the data +float dpiData_getFloat(dpiData *data); + +// return the integer portion of the data +int64_t dpiData_getInt64(dpiData *data); + +// return the interval (days/seconds) portion of the data +dpiIntervalDS *dpiData_getIntervalDS(dpiData *data); + +// return the interval (years/months) portion of the data +dpiIntervalYM *dpiData_getIntervalYM(dpiData *data); + +// return whether data value is null or not +int dpiData_getIsNull(dpiData *data); + +// return the LOB portion of the data +dpiLob *dpiData_getLOB(dpiData *data); + +// return the object portion of the data +dpiObject *dpiData_getObject(dpiData *data); + +// return the statement portion of the data +dpiStmt *dpiData_getStmt(dpiData *data); + +// return the timestamp portion of the data +dpiTimestamp *dpiData_getTimestamp(dpiData *data); + +// return the unsigned integer portion of the data +uint64_t dpiData_getUint64(dpiData *data); + +// set the boolean portion of the data +void dpiData_setBool(dpiData *data, int value); + +// set the bytes portion of the data +void dpiData_setBytes(dpiData *data, char *ptr, uint32_t length); + +// set the double portion of the data +void dpiData_setDouble(dpiData *data, double value); + +// set the float portion of the data +void dpiData_setFloat(dpiData *data, float value); + +// set the integer portion of the data +void dpiData_setInt64(dpiData *data, int64_t value); + +// set the interval (days/seconds) portion of the data +void dpiData_setIntervalDS(dpiData *data, int32_t days, int32_t hours, + int32_t minutes, int32_t seconds, int32_t fsceconds); + +// set the interval (years/months) portion of the data +void dpiData_setIntervalYM(dpiData *data, int32_t years, int32_t months); + +// set the LOB portion of the data +void dpiData_setLOB(dpiData *data, dpiLob *lob); + +// set data to the null value +void dpiData_setNull(dpiData *data); + +// set the object portion of the data +void dpiData_setObject(dpiData *data, dpiObject *obj); + +// set the statement portion of the data +void dpiData_setStmt(dpiData *data, dpiStmt *stmt); + +// set the timestamp portion of the data +void dpiData_setTimestamp(dpiData *data, int16_t year, uint8_t month, + uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, + uint32_t fsecond, int8_t tzHourOffset, int8_t tzMinuteOffset); + +// set the unsigned integer portion of the data +void dpiData_setUint64(dpiData *data, uint64_t value); + + +//----------------------------------------------------------------------------- +// Dequeue Option Methods (dpiDeqOptions) +//----------------------------------------------------------------------------- + +// add a reference to dequeue options +int dpiDeqOptions_addRef(dpiDeqOptions *options); + +// return condition associated with dequeue options +int dpiDeqOptions_getCondition(dpiDeqOptions *options, const char **value, + uint32_t *valueLength); + +// return consumer name associated with dequeue options +int dpiDeqOptions_getConsumerName(dpiDeqOptions *options, const char **value, + uint32_t *valueLength); + +// return correlation associated with dequeue options +int dpiDeqOptions_getCorrelation(dpiDeqOptions *options, const char **value, + uint32_t *valueLength); + +// return mode associated with dequeue options +int dpiDeqOptions_getMode(dpiDeqOptions *options, dpiDeqMode *value); + +// return message id associated with dequeue options +int dpiDeqOptions_getMsgId(dpiDeqOptions *options, const char **value, + uint32_t *valueLength); + +// return navigation associated with dequeue options +int dpiDeqOptions_getNavigation(dpiDeqOptions *options, + dpiDeqNavigation *value); + +// return transformation associated with dequeue options +int dpiDeqOptions_getTransformation(dpiDeqOptions *options, const char **value, + uint32_t *valueLength); + +// return visibility associated with dequeue options +int dpiDeqOptions_getVisibility(dpiDeqOptions *options, dpiVisibility *value); + +// return wait time associated with dequeue options +int dpiDeqOptions_getWait(dpiDeqOptions *options, uint32_t *value); + +// release a reference from dequeue options +int dpiDeqOptions_release(dpiDeqOptions *options); + +// set condition associated with dequeue options +int dpiDeqOptions_setCondition(dpiDeqOptions *options, const char *value, + uint32_t valueLength); + +// set consumer name associated with dequeue options +int dpiDeqOptions_setConsumerName(dpiDeqOptions *options, const char *value, + uint32_t valueLength); + +// set correlation associated with dequeue options +int dpiDeqOptions_setCorrelation(dpiDeqOptions *options, const char *value, + uint32_t valueLength); + +// set delivery mode associated with dequeue options +int dpiDeqOptions_setDeliveryMode(dpiDeqOptions *options, + dpiMessageDeliveryMode value); + +// set mode associated with dequeue options +int dpiDeqOptions_setMode(dpiDeqOptions *options, dpiDeqMode value); + +// set message id associated with dequeue options +int dpiDeqOptions_setMsgId(dpiDeqOptions *options, const char *value, + uint32_t valueLength); + +// set navigation associated with dequeue options +int dpiDeqOptions_setNavigation(dpiDeqOptions *options, + dpiDeqNavigation value); + +// set transformation associated with dequeue options +int dpiDeqOptions_setTransformation(dpiDeqOptions *options, const char *value, + uint32_t valueLength); + +// set visibility associated with dequeue options +int dpiDeqOptions_setVisibility(dpiDeqOptions *options, dpiVisibility value); + +// set wait time associated with dequeue options +int dpiDeqOptions_setWait(dpiDeqOptions *options, uint32_t value); + + +//----------------------------------------------------------------------------- +// Enqueue Option Methods (dpiEnqOptions) +//----------------------------------------------------------------------------- + +// add a reference to enqueue options +int dpiEnqOptions_addRef(dpiEnqOptions *options); + +// return transformation associated with enqueue options +int dpiEnqOptions_getTransformation(dpiEnqOptions *options, const char **value, + uint32_t *valueLength); + +// return visibility associated with enqueue options +int dpiEnqOptions_getVisibility(dpiEnqOptions *options, dpiVisibility *value); + +// release a reference from enqueue options +int dpiEnqOptions_release(dpiEnqOptions *options); + +// set delivery mode associated with enqueue options +int dpiEnqOptions_setDeliveryMode(dpiEnqOptions *options, + dpiMessageDeliveryMode value); + +// set transformation associated with enqueue options +int dpiEnqOptions_setTransformation(dpiEnqOptions *options, const char *value, + uint32_t valueLength); + +// set visibility associated with enqueue options +int dpiEnqOptions_setVisibility(dpiEnqOptions *options, dpiVisibility value); + + +//----------------------------------------------------------------------------- +// LOB Methods (dpiLob) +//----------------------------------------------------------------------------- + +// add a reference to the LOB +int dpiLob_addRef(dpiLob *lob); + +// close the LOB +int dpiLob_close(dpiLob *lob); + +// close the LOB's resources +int dpiLob_closeResource(dpiLob *lob); + +// create a copy of the LOB +int dpiLob_copy(dpiLob *lob, dpiLob **copiedLob); + +// get buffer size in bytes for a LOB +int dpiLob_getBufferSize(dpiLob *lob, uint64_t sizeInChars, + uint64_t *sizeInBytes); + +// return the chunk size for the LOB +int dpiLob_getChunkSize(dpiLob *lob, uint32_t *size); + +// return the directory alias name and file name of a BFILE LOB +int dpiLob_getDirectoryAndFileName(dpiLob *lob, const char **directoryAlias, + uint32_t *directoryAliasLength, const char **fileName, + uint32_t *fileNameLength); + +// return if the file associated with a BFILE LOB exists +int dpiLob_getFileExists(dpiLob *lob, int *exists); + +// return if the LOB's resources are currently open +int dpiLob_getIsResourceOpen(dpiLob *lob, int *isOpen); + +// return the current size of the LOB +int dpiLob_getSize(dpiLob *lob, uint64_t *size); + +// open the LOB's resources (used to improve performance of multiple +// read/writes operations) +int dpiLob_openResource(dpiLob *lob); + +// read bytes from the LOB at the specified offset +int dpiLob_readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, + char *value, uint64_t *valueLength); + +// release a reference to the LOB +int dpiLob_release(dpiLob *lob); + +// set the directory name and file name of the BFILE LOB +int dpiLob_setDirectoryAndFileName(dpiLob *lob, const char *directoryAlias, + uint32_t directoryAliasLength, const char *fileName, + uint32_t fileNameLength); + +// sets the contents of a LOB from a byte string +int dpiLob_setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength); + +// trim the LOB to the specified size +int dpiLob_trim(dpiLob *lob, uint64_t newSize); + +// write bytes to the LOB at the specified offset +int dpiLob_writeBytes(dpiLob *lob, uint64_t offset, const char *value, + uint64_t valueLength); + + +//----------------------------------------------------------------------------- +// Message Properties Methods (dpiMsgProps) +//----------------------------------------------------------------------------- + +// add a reference to message properties +int dpiMsgProps_addRef(dpiMsgProps *props); + +// return the number of attempts made to deliver the message +int dpiMsgProps_getNumAttempts(dpiMsgProps *props, int32_t *value); + +// return correlation associated with the message +int dpiMsgProps_getCorrelation(dpiMsgProps *props, const char **value, + uint32_t *valueLength); + +// return the number of seconds the message was delayed +int dpiMsgProps_getDelay(dpiMsgProps *props, int32_t *value); + +// return the mode used for delivering the message +int dpiMsgProps_getDeliveryMode(dpiMsgProps *props, + dpiMessageDeliveryMode *value); + +// return the time the message was enqueued +int dpiMsgProps_getEnqTime(dpiMsgProps *props, dpiTimestamp *value); + +// return the name of the exception queue associated with the message +int dpiMsgProps_getExceptionQ(dpiMsgProps *props, const char **value, + uint32_t *valueLength); + +// return the number of seconds until the message expires +int dpiMsgProps_getExpiration(dpiMsgProps *props, int32_t *value); + +// return the message id for the message (after enqueuing or dequeuing) +int dpiMsgProps_getMsgId(dpiMsgProps *props, const char **value, + uint32_t *valueLength); + +// return the original message id for the message +int dpiMsgProps_getOriginalMsgId(dpiMsgProps *props, const char **value, + uint32_t *valueLength); + +// return the payload of the message (object or bytes) +int dpiMsgProps_getPayload(dpiMsgProps *props, dpiObject **obj, + const char **value, uint32_t *valueLength); + +// return the priority of the message +int dpiMsgProps_getPriority(dpiMsgProps *props, int32_t *value); + +// return the state of the message +int dpiMsgProps_getState(dpiMsgProps *props, dpiMessageState *value); + +// release a reference from message properties +int dpiMsgProps_release(dpiMsgProps *props); + +// set correlation associated with the message +int dpiMsgProps_setCorrelation(dpiMsgProps *props, const char *value, + uint32_t valueLength); + +// set the number of seconds to delay the message +int dpiMsgProps_setDelay(dpiMsgProps *props, int32_t value); + +// set the name of the exception queue associated with the message +int dpiMsgProps_setExceptionQ(dpiMsgProps *props, const char *value, + uint32_t valueLength); + +// set the number of seconds until the message expires +int dpiMsgProps_setExpiration(dpiMsgProps *props, int32_t value); + +// set the original message id for the message +int dpiMsgProps_setOriginalMsgId(dpiMsgProps *props, const char *value, + uint32_t valueLength); + +// set the payload of the message (as a series of bytes) +int dpiMsgProps_setPayloadBytes(dpiMsgProps *props, const char *value, + uint32_t valueLength); + +// set the payload of the message (as an object) +int dpiMsgProps_setPayloadObject(dpiMsgProps *props, dpiObject *obj); + +// set the priority of the message +int dpiMsgProps_setPriority(dpiMsgProps *props, int32_t value); + + +//----------------------------------------------------------------------------- +// Object Methods (dpiObject) +//----------------------------------------------------------------------------- + +// add a reference to the object +int dpiObject_addRef(dpiObject *obj); + +// append an element to the collection +int dpiObject_appendElement(dpiObject *obj, dpiNativeTypeNum nativeTypeNum, + dpiData *value); + +// copy the object and return the copied object +int dpiObject_copy(dpiObject *obj, dpiObject **copiedObj); + +// delete an element from the collection +int dpiObject_deleteElementByIndex(dpiObject *obj, int32_t index); + +// get the value of the specified attribute +int dpiObject_getAttributeValue(dpiObject *obj, dpiObjectAttr *attr, + dpiNativeTypeNum nativeTypeNum, dpiData *value); + +// return whether an element exists in a collection at the specified index +int dpiObject_getElementExistsByIndex(dpiObject *obj, int32_t index, + int *exists); + +// get the value of the element in a collection at the specified index +int dpiObject_getElementValueByIndex(dpiObject *obj, int32_t index, + dpiNativeTypeNum nativeTypeNum, dpiData *value); + +// return the first index used in a collection +int dpiObject_getFirstIndex(dpiObject *obj, int32_t *index, int *exists); + +// return the last index used in a collection +int dpiObject_getLastIndex(dpiObject *obj, int32_t *index, int *exists); + +// return the next index used in a collection given an index +int dpiObject_getNextIndex(dpiObject *obj, int32_t index, int32_t *nextIndex, + int *exists); + +// return the previous index used in a collection given an index +int dpiObject_getPrevIndex(dpiObject *obj, int32_t index, int32_t *prevIndex, + int *exists); + +// return the number of elements in a collection +int dpiObject_getSize(dpiObject *obj, int32_t *size); + +// release a reference to the object +int dpiObject_release(dpiObject *obj); + +// set the value of the specified attribute +int dpiObject_setAttributeValue(dpiObject *obj, dpiObjectAttr *attr, + dpiNativeTypeNum nativeTypeNum, dpiData *value); + +// set the value of the element in a collection at the specified index +int dpiObject_setElementValueByIndex(dpiObject *obj, int32_t index, + dpiNativeTypeNum nativeTypeNum, dpiData *value); + +// trim a number of elements from the end of a collection +int dpiObject_trim(dpiObject *obj, uint32_t numToTrim); + + +//----------------------------------------------------------------------------- +// Object Type Attribute Methods (dpiObjectAttr) +//----------------------------------------------------------------------------- + +// add a reference to the attribute +int dpiObjectAttr_addRef(dpiObjectAttr *attr); + +// return the name of the attribute +int dpiObjectAttr_getInfo(dpiObjectAttr *attr, dpiObjectAttrInfo *info); + +// release a reference to the attribute +int dpiObjectAttr_release(dpiObjectAttr *attr); + + +//----------------------------------------------------------------------------- +// Object Type Methods (dpiObjectType) +//----------------------------------------------------------------------------- + +// add a reference to the object type +int dpiObjectType_addRef(dpiObjectType *objType); + +// create an object of the specified type and return it +int dpiObjectType_createObject(dpiObjectType *objType, dpiObject **obj); + +// return the attributes available on the object type +int dpiObjectType_getAttributes(dpiObjectType *objType, uint16_t numAttributes, + dpiObjectAttr **attributes); + +// return information about the object type +int dpiObjectType_getInfo(dpiObjectType *objType, dpiObjectTypeInfo *info); + +// release a reference to the object type +int dpiObjectType_release(dpiObjectType *objType); + + +//----------------------------------------------------------------------------- +// Session Pools Methods (dpiPool) +//----------------------------------------------------------------------------- + +// acquire a connection from the pool and return it +int dpiPool_acquireConnection(dpiPool *pool, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + dpiConnCreateParams *createParams, dpiConn **conn); + +// add a reference to a pool +int dpiPool_addRef(dpiPool *pool); + +// destroy the pool now, not when its reference count reaches zero +int dpiPool_close(dpiPool *pool, dpiPoolCloseMode closeMode); + +// create a session pool and return it +int dpiPool_create(const dpiContext *context, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + const char *connectString, uint32_t connectStringLength, + const dpiCommonCreateParams *commonParams, + dpiPoolCreateParams *createParams, dpiPool **pool); + +// get the pool's busy count +int dpiPool_getBusyCount(dpiPool *pool, uint32_t *value); + +// return the encoding information used by the session pool +int dpiPool_getEncodingInfo(dpiPool *pool, dpiEncodingInfo *info); + +// get the pool's "get" mode +int dpiPool_getGetMode(dpiPool *pool, dpiPoolGetMode *value); + +// get the pool's maximum lifetime session +int dpiPool_getMaxLifetimeSession(dpiPool *pool, uint32_t *value); + +// get the pool's open count +int dpiPool_getOpenCount(dpiPool *pool, uint32_t *value); + +// return the statement cache size +int dpiPool_getStmtCacheSize(dpiPool *pool, uint32_t *cacheSize); + +// get the pool's timeout value +int dpiPool_getTimeout(dpiPool *pool, uint32_t *value); + +// get the pool's wait timeout value +int dpiPool_getWaitTimeout(dpiPool *pool, uint32_t *value); + +// release a reference to the pool +int dpiPool_release(dpiPool *pool); + +// set the pool's "get" mode +int dpiPool_setGetMode(dpiPool *pool, dpiPoolGetMode value); + +// set the pool's maximum lifetime session +int dpiPool_setMaxLifetimeSession(dpiPool *pool, uint32_t value); + +// set the statement cache size +int dpiPool_setStmtCacheSize(dpiPool *pool, uint32_t cacheSize); + +// set the pool's timeout value +int dpiPool_setTimeout(dpiPool *pool, uint32_t value); + +// set the pool's wait timeout value +int dpiPool_setWaitTimeout(dpiPool *pool, uint32_t value); + + +//----------------------------------------------------------------------------- +// AQ Queue Methods (dpiQueue) +//----------------------------------------------------------------------------- + +// add a reference to the queue +int dpiQueue_addRef(dpiQueue *queue); + +// dequeue multiple messages from the queue +int dpiQueue_deqMany(dpiQueue *queue, uint32_t *numProps, dpiMsgProps **props); + +// dequeue a single message from the queue +int dpiQueue_deqOne(dpiQueue *queue, dpiMsgProps **props); + +// enqueue multiple message to the queue +int dpiQueue_enqMany(dpiQueue *queue, uint32_t numProps, dpiMsgProps **props); + +// enqueue a single message to the queue +int dpiQueue_enqOne(dpiQueue *queue, dpiMsgProps *props); + +// get a reference to the dequeue options associated with the queue +int dpiQueue_getDeqOptions(dpiQueue *queue, dpiDeqOptions **options); + +// get a reference to the enqueue options associated with the queue +int dpiQueue_getEnqOptions(dpiQueue *queue, dpiEnqOptions **options); + +// release a reference to the queue +int dpiQueue_release(dpiQueue *queue); + + +//----------------------------------------------------------------------------- +// SODA Collection Methods (dpiSodaColl) +//----------------------------------------------------------------------------- + +// add a reference to the SODA collection +int dpiSodaColl_addRef(dpiSodaColl *coll); + +// create an index on the collection +int dpiSodaColl_createIndex(dpiSodaColl *coll, const char *indexSpec, + uint32_t indexSpecLength, uint32_t flags); + +// drop a SODA collection +int dpiSodaColl_drop(dpiSodaColl *coll, uint32_t flags, int *isDropped); + +// drop an index on the collection +int dpiSodaColl_dropIndex(dpiSodaColl *coll, const char *name, + uint32_t nameLength, uint32_t flags, int *isDropped); + +// find documents in a SODA collection and return a cursor +int dpiSodaColl_find(dpiSodaColl *coll, const dpiSodaOperOptions *options, + uint32_t flags, dpiSodaDocCursor **cursor); + +// find a single document in a SODA collection +int dpiSodaColl_findOne(dpiSodaColl *coll, const dpiSodaOperOptions *options, + uint32_t flags, dpiSodaDoc **doc); + +// get the data guide for the collection +int dpiSodaColl_getDataGuide(dpiSodaColl *coll, uint32_t flags, + dpiSodaDoc **doc); + +// get the count of documents that match the criteria +int dpiSodaColl_getDocCount(dpiSodaColl *coll, + const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count); + +// get the metadata of the collection +int dpiSodaColl_getMetadata(dpiSodaColl *coll, const char **value, + uint32_t *valueLength); + +// get the name of the collection +int dpiSodaColl_getName(dpiSodaColl *coll, const char **value, + uint32_t *valueLength); + +// insert multiple documents into the SODA collection +int dpiSodaColl_insertMany(dpiSodaColl *coll, uint32_t numDocs, + dpiSodaDoc **docs, uint32_t flags, dpiSodaDoc **insertedDocs); + +// insert a document into the SODA collection +int dpiSodaColl_insertOne(dpiSodaColl *coll, dpiSodaDoc *doc, uint32_t flags, + dpiSodaDoc **insertedDoc); + +// release a reference to the SODA collection +int dpiSodaColl_release(dpiSodaColl *coll); + +// remove documents from a SODA collection (with operation options) +int dpiSodaColl_remove(dpiSodaColl *coll, const dpiSodaOperOptions *options, + uint32_t flags, uint64_t *count); + +// replace a document in a SODA collection (with operation options) +int dpiSodaColl_replaceOne(dpiSodaColl *coll, + const dpiSodaOperOptions *options, dpiSodaDoc *doc, uint32_t flags, + int *replaced, dpiSodaDoc **replacedDoc); + + +//----------------------------------------------------------------------------- +// SODA Collection Cursor Methods (dpiSodaCollCursor) +//----------------------------------------------------------------------------- + +// add a reference to the SODA collection cursor +int dpiSodaCollCursor_addRef(dpiSodaCollCursor *cursor); + +// close the SODA collection cursor +int dpiSodaCollCursor_close(dpiSodaCollCursor *cursor); + +// get the next collection from the cursor +int dpiSodaCollCursor_getNext(dpiSodaCollCursor *cursor, uint32_t flags, + dpiSodaColl **coll); + +// release a reference to the SODA collection cursor +int dpiSodaCollCursor_release(dpiSodaCollCursor *cursor); + + +//----------------------------------------------------------------------------- +// SODA Database Methods (dpiSodaDb) +//----------------------------------------------------------------------------- + +// add a reference to the SODA database +int dpiSodaDb_addRef(dpiSodaDb *db); + +// create a new SODA collection +int dpiSodaDb_createCollection(dpiSodaDb *db, const char *name, + uint32_t nameLength, const char *metadata, uint32_t metadataLength, + uint32_t flags, dpiSodaColl **coll); + +// create a new SODA document +int dpiSodaDb_createDocument(dpiSodaDb *db, const char *key, + uint32_t keyLength, const char *content, uint32_t contentLength, + const char *mediaType, uint32_t mediaTypeLength, uint32_t flags, + dpiSodaDoc **doc); + +// free the memory allocated when getting an array of SODA collection names +int dpiSodaDb_freeCollectionNames(dpiSodaDb *db, dpiSodaCollNames *names); + +// return a cursor to iterate over SODA collections +int dpiSodaDb_getCollections(dpiSodaDb *db, const char *startName, + uint32_t startNameLength, uint32_t flags, dpiSodaCollCursor **cursor); + +// return an array of SODA collection names +int dpiSodaDb_getCollectionNames(dpiSodaDb *db, const char *startName, + uint32_t startNameLength, uint32_t limit, uint32_t flags, + dpiSodaCollNames *names); + +// open an existing SODA collection +int dpiSodaDb_openCollection(dpiSodaDb *db, const char *name, + uint32_t nameLength, uint32_t flags, dpiSodaColl **coll); + +// release a reference to the SODA database +int dpiSodaDb_release(dpiSodaDb *db); + + +//----------------------------------------------------------------------------- +// SODA Document Methods (dpiSodaDoc) +//----------------------------------------------------------------------------- + +// add a reference to the SODA document +int dpiSodaDoc_addRef(dpiSodaDoc *cursor); + +// get the content of the document +int dpiSodaDoc_getContent(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength, const char **encoding); + +// get the created timestamp associated with the document +int dpiSodaDoc_getCreatedOn(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength); + +// get the key associated with the document +int dpiSodaDoc_getKey(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength); + +// get the last modified timestamp associated with the document +int dpiSodaDoc_getLastModified(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength); + +// get the media type of the document +int dpiSodaDoc_getMediaType(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength); + +// get the version of the document +int dpiSodaDoc_getVersion(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength); + +// release a reference to the SODA document +int dpiSodaDoc_release(dpiSodaDoc *cursor); + + +//----------------------------------------------------------------------------- +// SODA Document Cursor Methods (dpiSodaDocCursor) +//----------------------------------------------------------------------------- + +// add a reference to the SODA document cursor +int dpiSodaDocCursor_addRef(dpiSodaDocCursor *cursor); + +// close the SODA document cursor +int dpiSodaDocCursor_close(dpiSodaDocCursor *cursor); + +// get the next document from the cursor +int dpiSodaDocCursor_getNext(dpiSodaDocCursor *cursor, uint32_t flags, + dpiSodaDoc **doc); + +// release a reference to the SODA document cursor +int dpiSodaDocCursor_release(dpiSodaDocCursor *cursor); + + +//----------------------------------------------------------------------------- +// Statement Methods (dpiStmt) +//----------------------------------------------------------------------------- + +// add a reference to a statement +int dpiStmt_addRef(dpiStmt *stmt); + +// bind a variable to the statement using the given name +int dpiStmt_bindByName(dpiStmt *stmt, const char *name, uint32_t nameLength, + dpiVar *var); + +// bind a variable to the statement at the given position +// positions are determined by the order in which names are introduced +int dpiStmt_bindByPos(dpiStmt *stmt, uint32_t pos, dpiVar *var); + +// bind a value to the statement using the given name +// this creates the variable by looking at the type and then binds it +int dpiStmt_bindValueByName(dpiStmt *stmt, const char *name, + uint32_t nameLength, dpiNativeTypeNum nativeTypeNum, dpiData *data); + +// bind a value to the statement at the given position +// this creates the variable by looking at the type and then binds it +int dpiStmt_bindValueByPos(dpiStmt *stmt, uint32_t pos, + dpiNativeTypeNum nativeTypeNum, dpiData *data); + +// close the statement now, not when its reference count reaches zero +int dpiStmt_close(dpiStmt *stmt, const char *tag, uint32_t tagLength); + +// define a variable to accept the data for the specified column (1 based) +int dpiStmt_define(dpiStmt *stmt, uint32_t pos, dpiVar *var); + +// define type of data to use for the specified column (1 based) +int dpiStmt_defineValue(dpiStmt *stmt, uint32_t pos, + dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, + uint32_t size, int sizeIsBytes, dpiObjectType *objType); + +// execute the statement and return the number of query columns +// zero implies the statement is not a query +int dpiStmt_execute(dpiStmt *stmt, dpiExecMode mode, + uint32_t *numQueryColumns); + +// execute the statement multiple times (queries not supported) +int dpiStmt_executeMany(dpiStmt *stmt, dpiExecMode mode, uint32_t numIters); + +// fetch a single row and return the index into the defined variables +// this will internally perform any execute and array fetch as needed +int dpiStmt_fetch(dpiStmt *stmt, int *found, uint32_t *bufferRowIndex); + +// return the number of rows that are available in the defined variables +// up to the maximum specified; this will internally perform execute/array +// fetch only if no rows are available in the defined variables and there are +// more rows available to fetch +int dpiStmt_fetchRows(dpiStmt *stmt, uint32_t maxRows, + uint32_t *bufferRowIndex, uint32_t *numRowsFetched, int *moreRows); + +// get the number of batch errors that took place in the previous execution +int dpiStmt_getBatchErrorCount(dpiStmt *stmt, uint32_t *count); + +// get the batch errors that took place in the previous execution +int dpiStmt_getBatchErrors(dpiStmt *stmt, uint32_t numErrors, + dpiErrorInfo *errors); + +// get the number of bind variables that are in the prepared statement +int dpiStmt_getBindCount(dpiStmt *stmt, uint32_t *count); + +// get the names of the bind variables that are in the prepared statement +int dpiStmt_getBindNames(dpiStmt *stmt, uint32_t *numBindNames, + const char **bindNames, uint32_t *bindNameLengths); + +// get the number of rows to (internally) fetch at one time +int dpiStmt_getFetchArraySize(dpiStmt *stmt, uint32_t *arraySize); + +// get next implicit result from previous execution; NULL if no more exist +int dpiStmt_getImplicitResult(dpiStmt *stmt, dpiStmt **implicitResult); + +// return information about the statement +int dpiStmt_getInfo(dpiStmt *stmt, dpiStmtInfo *info); + +// get the rowid of the last row affected by a DML statement +int dpiStmt_getLastRowid(dpiStmt *stmt, dpiRowid **rowid); + +// get the number of query columns (zero implies the statement is not a query) +int dpiStmt_getNumQueryColumns(dpiStmt *stmt, uint32_t *numQueryColumns); + +// return metadata about the column at the specified position (1 based) +int dpiStmt_getQueryInfo(dpiStmt *stmt, uint32_t pos, dpiQueryInfo *info); + +// get the value for the specified column of the current row fetched +int dpiStmt_getQueryValue(dpiStmt *stmt, uint32_t pos, + dpiNativeTypeNum *nativeTypeNum, dpiData **data); + +// get the row count for the statement +// for queries, this is the number of rows that have been fetched so far +// for non-queries, this is the number of rows affected by the last execution +int dpiStmt_getRowCount(dpiStmt *stmt, uint64_t *count); + +// get the number of rows affected for each DML operation just executed +// using the mode DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS +int dpiStmt_getRowCounts(dpiStmt *stmt, uint32_t *numRowCounts, + uint64_t **rowCounts); + +// get subscription query id for continuous query notification +int dpiStmt_getSubscrQueryId(dpiStmt *stmt, uint64_t *queryId); + +// release a reference to the statement +int dpiStmt_release(dpiStmt *stmt); + +// scroll the statement to the desired row +// this is only valid for scrollable statements +int dpiStmt_scroll(dpiStmt *stmt, dpiFetchMode mode, int32_t offset, + int32_t rowCountOffset); + +// set the number of rows to (internally) fetch at one time +int dpiStmt_setFetchArraySize(dpiStmt *stmt, uint32_t arraySize); + + +//----------------------------------------------------------------------------- +// Rowid Methods (dpiRowid) +//----------------------------------------------------------------------------- + +// add a reference to the rowid +int dpiRowid_addRef(dpiRowid *rowid); + +// get string representation from rowid +int dpiRowid_getStringValue(dpiRowid *rowid, const char **value, + uint32_t *valueLength); + +// release a reference to the rowid +int dpiRowid_release(dpiRowid *subscr); + + +//----------------------------------------------------------------------------- +// Subscription Methods (dpiSubscr) +//----------------------------------------------------------------------------- + +// add a reference to the subscription +int dpiSubscr_addRef(dpiSubscr *subscr); + +// prepare statement for registration with subscription +int dpiSubscr_prepareStmt(dpiSubscr *subscr, const char *sql, + uint32_t sqlLength, dpiStmt **stmt); + +// release a reference to the subscription +int dpiSubscr_release(dpiSubscr *subscr); + + +//----------------------------------------------------------------------------- +// Variable Methods (dpiVar) +//----------------------------------------------------------------------------- + +// add a reference to the variable +int dpiVar_addRef(dpiVar *var); + +// copy the data from one variable to another variable +int dpiVar_copyData(dpiVar *var, uint32_t pos, dpiVar *sourceVar, + uint32_t sourcePos); + +// return the number of elements in a PL/SQL index-by table +int dpiVar_getNumElementsInArray(dpiVar *var, uint32_t *numElements); + +// return pointer to array of dpiData structures for transferring data +// this is needed for DML returning where the number of elements is modified +int dpiVar_getReturnedData(dpiVar *var, uint32_t pos, uint32_t *numElements, + dpiData **data); + +// return the size in bytes of the buffer used for fetching/binding +int dpiVar_getSizeInBytes(dpiVar *var, uint32_t *sizeInBytes); + +// release a reference to the variable +int dpiVar_release(dpiVar *var); + +// set the value of the variable from a byte string +int dpiVar_setFromBytes(dpiVar *var, uint32_t pos, const char *value, + uint32_t valueLength); + +// set the value of the variable from a LOB +int dpiVar_setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob); + +// set the value of the variable from an object +int dpiVar_setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj); + +// set the value of the variable from a rowid +int dpiVar_setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid); + +// set the value of the variable from a statement +int dpiVar_setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt); + +// set the number of elements in a PL/SQL index-by table +int dpiVar_setNumElementsInArray(dpiVar *var, uint32_t numElements); + +#endif diff --git a/vendor/github.com/godror/godror/odpi/src/dpiConn.c b/vendor/github.com/godror/godror/odpi/src/dpiConn.c new file mode 100644 index 00000000000..faa5dc5266b --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiConn.c @@ -0,0 +1,2249 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiConn.c +// Implementation of connection. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" +#include + +// forward declarations of internal functions only used in this file +static int dpiConn__attachExternal(dpiConn *conn, void *externalHandle, + dpiError *error); +static int dpiConn__createStandalone(dpiConn *conn, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + const char *connectString, uint32_t connectStringLength, + const dpiCommonCreateParams *commonParams, + const dpiConnCreateParams *createParams, dpiError *error); +static int dpiConn__get(dpiConn *conn, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + const char *connectString, uint32_t connectStringLength, + dpiConnCreateParams *createParams, dpiPool *pool, dpiError *error); +static int dpiConn__getHandles(dpiConn *conn, dpiError *error); +static int dpiConn__getServerCharset(dpiConn *conn, dpiError *error); +static int dpiConn__getSession(dpiConn *conn, uint32_t mode, + const char *connectString, uint32_t connectStringLength, + dpiConnCreateParams *params, void *authInfo, dpiError *error); +static int dpiConn__setAttributesFromCreateParams(dpiConn *conn, void *handle, + uint32_t handleType, const char *userName, uint32_t userNameLength, + const char *password, uint32_t passwordLength, + const dpiConnCreateParams *params, dpiError *error); +static int dpiConn__setShardingKey(dpiConn *conn, void **shardingKey, + void *handle, uint32_t handleType, uint32_t attribute, + const char *action, dpiShardingKeyColumn *columns, uint8_t numColumns, + dpiError *error); +static int dpiConn__setShardingKeyValue(dpiConn *conn, void *shardingKey, + dpiShardingKeyColumn *column, dpiError *error); + + +//----------------------------------------------------------------------------- +// dpiConn__attachExternal() [INTERNAL] +// Attach to the server and session of an existing service context handle. +//----------------------------------------------------------------------------- +static int dpiConn__attachExternal(dpiConn *conn, void *externalHandle, + dpiError *error) +{ + // mark connection as using an external handle so that no attempts are + // made to close it + conn->externalHandle = 1; + + // acquire handles from existing service context handle + conn->handle = externalHandle; + if (dpiConn__getHandles(conn, error) < 0) { + conn->handle = NULL; + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiConn__check() [INTERNAL] +// Validate the connection handle and that it is still connected to the +// database. +//----------------------------------------------------------------------------- +static int dpiConn__check(dpiConn *conn, const char *fnName, dpiError *error) +{ + if (dpiGen__startPublicFn(conn, DPI_HTYPE_CONN, fnName, error) < 0) + return DPI_FAILURE; + return dpiConn__checkConnected(conn, error); +} + + +//----------------------------------------------------------------------------- +// dpiConn__checkConnected() [INTERNAL] +// Check to see if the connection is still open and raise an exception if it +// is not. +//----------------------------------------------------------------------------- +int dpiConn__checkConnected(dpiConn *conn, dpiError *error) +{ + if (!conn->handle || conn->closing || (conn->pool && !conn->pool->handle)) + return dpiError__set(error, "check connected", DPI_ERR_NOT_CONNECTED); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiConn__close() [INTERNAL] +// Internal method used for closing the connection. Any transaction is rolled +// back and any handles allocated are freed. For connections acquired from a +// pool and that aren't marked as needed to be dropped, the last time used is +// updated. This is called from dpiConn_close() where errors are expected to be +// propagated and from dpiConn__free() where errors are ignored. +//----------------------------------------------------------------------------- +static int dpiConn__close(dpiConn *conn, uint32_t mode, const char *tag, + uint32_t tagLength, int propagateErrors, dpiError *error) +{ + int status, txnInProgress; + uint32_t serverStatus, i; + time_t *lastTimeUsed; + dpiObject *obj; + dpiStmt *stmt; + dpiLob *lob; + + // rollback any outstanding transaction, if one is in progress; drop the + // session if any errors take place + txnInProgress = 0; + if (!conn->deadSession && !conn->externalHandle && conn->sessionHandle) { + txnInProgress = 1; + if (conn->env->versionInfo->versionNum >= 12) + dpiOci__attrGet(conn->sessionHandle, DPI_OCI_HTYPE_SESSION, + &txnInProgress, NULL, DPI_OCI_ATTR_TRANSACTION_IN_PROGRESS, + NULL, error); + } + if (txnInProgress && + dpiOci__transRollback(conn, propagateErrors, error) < 0) + conn->deadSession = 1; + + // close all objects; note that no references are retained by the + // handle list (otherwise all objects would be left until an explicit + // close of the connection was made) so a reference needs to be acquired + // first, as otherwise the object may be freed while the close is being + // performed! + if (conn->objects && !conn->externalHandle) { + for (i = 0; i < conn->objects->numSlots; i++) { + obj = (dpiObject*) conn->objects->handles[i]; + if (!obj) + continue; + if (conn->env->threaded) { + dpiMutex__acquire(conn->env->mutex); + status = dpiGen__checkHandle(obj, DPI_HTYPE_OBJECT, NULL, + NULL); + if (status == DPI_SUCCESS) + obj->refCount += 1; + dpiMutex__release(conn->env->mutex); + if (status < 0) + continue; + } + status = dpiObject__close(obj, propagateErrors, error); + if (conn->env->threaded) + dpiGen__setRefCount(obj, error, -1); + if (status < 0) + return DPI_FAILURE; + } + } + + // close all open statements; note that no references are retained by the + // handle list (otherwise all statements would be left open until an + // explicit close was made of either the statement or the connection) so + // a reference needs to be acquired first, as otherwise the statement may + // be freed while the close is being performed! + if (conn->openStmts && !conn->externalHandle) { + for (i = 0; i < conn->openStmts->numSlots; i++) { + stmt = (dpiStmt*) conn->openStmts->handles[i]; + if (!stmt) + continue; + if (conn->env->threaded) { + dpiMutex__acquire(conn->env->mutex); + status = dpiGen__checkHandle(stmt, DPI_HTYPE_STMT, NULL, NULL); + if (status == DPI_SUCCESS) + stmt->refCount += 1; + dpiMutex__release(conn->env->mutex); + if (status < 0) + continue; + } + status = dpiStmt__close(stmt, NULL, 0, propagateErrors, error); + if (conn->env->threaded) + dpiGen__setRefCount(stmt, error, -1); + if (status < 0) + return DPI_FAILURE; + } + } + + // close all open LOBs; the same comments apply as for statements + if (conn->openLobs && !conn->externalHandle) { + for (i = 0; i < conn->openLobs->numSlots; i++) { + lob = (dpiLob*) conn->openLobs->handles[i]; + if (!lob) + continue; + if (conn->env->threaded) { + dpiMutex__acquire(conn->env->mutex); + status = dpiGen__checkHandle(lob, DPI_HTYPE_LOB, NULL, NULL); + if (status == DPI_SUCCESS) + lob->refCount += 1; + dpiMutex__release(conn->env->mutex); + if (status < 0) + continue; + } + status = dpiLob__close(lob, propagateErrors, error); + if (conn->env->threaded) + dpiGen__setRefCount(lob, error, -1); + if (status < 0) + return DPI_FAILURE; + } + } + + // handle connections created with an external handle + if (conn->externalHandle) { + conn->sessionHandle = NULL; + + // handle standalone connections + } else if (conn->standalone) { + + // end session and free session handle + if (dpiOci__sessionEnd(conn, propagateErrors, error) < 0) + return DPI_FAILURE; + dpiOci__handleFree(conn->sessionHandle, DPI_OCI_HTYPE_SESSION); + conn->sessionHandle = NULL; + + // detach from server and free server handle + if (dpiOci__serverDetach(conn, propagateErrors, error) < 0) + return DPI_FAILURE; + dpiOci__handleFree(conn->serverHandle, DPI_OCI_HTYPE_SERVER); + + // free service context handle + dpiOci__handleFree(conn->handle, DPI_OCI_HTYPE_SVCCTX); + + // handle pooled connections + } else { + + // if session is to be dropped, mark it as a dead session + if (mode & DPI_OCI_SESSRLS_DROPSESS) + conn->deadSession = 1; + + // update last time used (if the session isn't going to be dropped) + // clear last time used (if the session is going to be dropped) + // do nothing, however, if not using a pool or the pool is being closed + if (conn->sessionHandle && conn->pool && conn->pool->handle) { + + // get the pointer from the context associated with the session + lastTimeUsed = NULL; + if (dpiOci__contextGetValue(conn, DPI_CONTEXT_LAST_TIME_USED, + (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), + (void**) &lastTimeUsed, propagateErrors, error) < 0) + return DPI_FAILURE; + + // if pointer available and session is going to be dropped, clear + // memory in order to avoid memory leak in OCI + if (lastTimeUsed && conn->deadSession) { + dpiOci__contextSetValue(conn, DPI_CONTEXT_LAST_TIME_USED, + (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), + NULL, 0, error); + dpiOci__memoryFree(conn, lastTimeUsed, error); + lastTimeUsed = NULL; + + // otherwise, if the pointer is not available, allocate a new + // pointer and set it + } else if (!lastTimeUsed && !conn->deadSession) { + if (dpiOci__memoryAlloc(conn, (void**) &lastTimeUsed, + sizeof(time_t), propagateErrors, error) < 0) + return DPI_FAILURE; + if (dpiOci__contextSetValue(conn, DPI_CONTEXT_LAST_TIME_USED, + (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), + lastTimeUsed, propagateErrors, error) < 0) { + dpiOci__memoryFree(conn, lastTimeUsed, error); + lastTimeUsed = NULL; + } + } + + // set last time used (used when acquiring a session to determine + // if ping is required) + if (lastTimeUsed) + *lastTimeUsed = time(NULL); + + } + + // check server status; if not connected, ensure session is dropped + if (conn->serverHandle) { + if (dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, + &serverStatus, NULL, DPI_OCI_ATTR_SERVER_STATUS, + "get server status", error) < 0 || + serverStatus != DPI_OCI_SERVER_NORMAL) + conn->deadSession = 1; + } + + // release session + if (conn->deadSession) + mode |= DPI_OCI_SESSRLS_DROPSESS; + else if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2, + NULL) == DPI_SUCCESS && (mode & DPI_MODE_CONN_CLOSE_RETAG) && + tag && tagLength > 0) + mode |= DPI_OCI_SESSRLS_MULTIPROPERTY_TAG; + if (dpiOci__sessionRelease(conn, tag, tagLength, mode, propagateErrors, + error) < 0) + return DPI_FAILURE; + conn->sessionHandle = NULL; + + } + conn->handle = NULL; + conn->serverHandle = NULL; + + // destroy sharding and super sharding key descriptors, if applicable + if (conn->shardingKey) { + dpiOci__descriptorFree(conn->shardingKey, DPI_OCI_DTYPE_SHARDING_KEY); + conn->shardingKey = NULL; + } + if (conn->superShardingKey) { + dpiOci__descriptorFree(conn->superShardingKey, + DPI_OCI_DTYPE_SHARDING_KEY); + conn->superShardingKey = NULL; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiConn__create() [PRIVATE] +// Perform internal initialization of the connection. +//----------------------------------------------------------------------------- +int dpiConn__create(dpiConn *conn, const dpiContext *context, + const char *userName, uint32_t userNameLength, const char *password, + uint32_t passwordLength, const char *connectString, + uint32_t connectStringLength, dpiPool *pool, + const dpiCommonCreateParams *commonParams, + dpiConnCreateParams *createParams, dpiError *error) +{ + void *envHandle = NULL; + + // allocate handle lists for statements, LOBs and objects + if (dpiHandleList__create(&conn->openStmts, error) < 0) + return DPI_FAILURE; + if (dpiHandleList__create(&conn->openLobs, error) < 0) + return DPI_FAILURE; + if (dpiHandleList__create(&conn->objects, error) < 0) + return DPI_FAILURE; + + // if an external service context handle is provided, acquire the + // environment handle from it; need a temporary environment handle in order + // to do so + if (createParams->externalHandle) { + error->env = conn->env; + if (dpiOci__envNlsCreate(&conn->env->handle, DPI_OCI_DEFAULT, 0, 0, + error) < 0) + return DPI_FAILURE; + if (dpiOci__handleAlloc(conn->env->handle, &error->handle, + DPI_OCI_HTYPE_ERROR, "allocate temp OCI error", error) < 0) + return DPI_FAILURE; + if (dpiOci__attrGet(createParams->externalHandle, DPI_OCI_HTYPE_SVCCTX, + &envHandle, NULL, DPI_OCI_ATTR_ENV, "get env handle", + error) < 0) + return DPI_FAILURE; + dpiOci__handleFree(conn->env->handle, DPI_OCI_HTYPE_ENV); + error->handle = NULL; + conn->env->handle = NULL; + } + + // initialize environment (for non-pooled connections) + if (!pool && dpiEnv__init(conn->env, context, commonParams, envHandle, + error) < 0) + return DPI_FAILURE; + + // if a handle is specified, use it + if (createParams->externalHandle) + return dpiConn__attachExternal(conn, createParams->externalHandle, + error); + + // connection class, sharding and the use of session pools require the use + // of the OCISessionGet() method; all other cases use the OCISessionBegin() + // method which is more capable + if (pool || (createParams->connectionClass && + createParams->connectionClassLength > 0) || + createParams->shardingKeyColumns || + createParams->superShardingKeyColumns) + return dpiConn__get(conn, userName, userNameLength, password, + passwordLength, connectString, connectStringLength, + createParams, pool, error); + return dpiConn__createStandalone(conn, userName, userNameLength, password, + passwordLength, connectString, connectStringLength, commonParams, + createParams, error); +} + + +//----------------------------------------------------------------------------- +// dpiConn__createStandalone() [PRIVATE] +// Create a standalone connection to the database using the parameters +// specified. +//----------------------------------------------------------------------------- +static int dpiConn__createStandalone(dpiConn *conn, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + const char *connectString, uint32_t connectStringLength, + const dpiCommonCreateParams *commonParams, + const dpiConnCreateParams *createParams, dpiError *error) +{ + uint32_t credentialType, authMode; + + // mark the connection as a standalone connection + conn->standalone = 1; + + // allocate the server handle + if (dpiOci__handleAlloc(conn->env->handle, &conn->serverHandle, + DPI_OCI_HTYPE_SERVER, "allocate server handle", error) < 0) + return DPI_FAILURE; + + // attach to the server + if (dpiOci__serverAttach(conn, connectString, connectStringLength, + error) < 0) + return DPI_FAILURE; + + // allocate the service context handle + if (dpiOci__handleAlloc(conn->env->handle, &conn->handle, + DPI_OCI_HTYPE_SVCCTX, "allocate service context handle", + error) < 0) + return DPI_FAILURE; + + // set attribute for server handle + if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, conn->serverHandle, + 0, DPI_OCI_ATTR_SERVER, "set server handle", error) < 0) + return DPI_FAILURE; + + // allocate the session handle + if (dpiOci__handleAlloc(conn->env->handle, &conn->sessionHandle, + DPI_OCI_HTYPE_SESSION, "allocate session handle", error) < 0) + return DPI_FAILURE; + + // driver name and edition are only relevant for standalone connections + if (dpiUtils__setAttributesFromCommonCreateParams(conn->sessionHandle, + DPI_OCI_HTYPE_SESSION, commonParams, error) < 0) + return DPI_FAILURE; + + // populate attributes on the session handle + if (dpiConn__setAttributesFromCreateParams(conn, conn->sessionHandle, + DPI_OCI_HTYPE_SESSION, userName, userNameLength, password, + passwordLength, createParams, error) < 0) + return DPI_FAILURE; + + // set the session handle on the service context handle + if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, + conn->sessionHandle, 0, DPI_OCI_ATTR_SESSION, "set session handle", + error) < 0) + return DPI_FAILURE; + + // if a new password is specified, change it (this also creates the session + // so a call to OCISessionBegin() is not needed) + if (createParams->newPassword && createParams->newPasswordLength > 0) { + authMode = DPI_OCI_AUTH; + if (createParams->authMode & DPI_MODE_AUTH_SYSDBA) + authMode |= DPI_OCI_CPW_SYSDBA; + if (createParams->authMode & DPI_MODE_AUTH_SYSOPER) + authMode |= DPI_OCI_CPW_SYSOPER; + if (createParams->authMode & DPI_MODE_AUTH_SYSASM) + authMode |= DPI_OCI_CPW_SYSASM; + if (createParams->authMode & DPI_MODE_AUTH_SYSBKP) + authMode |= DPI_OCI_CPW_SYSBKP; + if (createParams->authMode & DPI_MODE_AUTH_SYSDGD) + authMode |= DPI_OCI_CPW_SYSDGD; + if (createParams->authMode & DPI_MODE_AUTH_SYSKMT) + authMode |= DPI_OCI_CPW_SYSKMT; + return dpiOci__passwordChange(conn, userName, userNameLength, password, + passwordLength, createParams->newPassword, + createParams->newPasswordLength, authMode, error); + } + + // begin the session + credentialType = (createParams->externalAuth) ? DPI_OCI_CRED_EXT : + DPI_OCI_CRED_RDBMS; + authMode = createParams->authMode | DPI_OCI_STMT_CACHE; + if (dpiOci__sessionBegin(conn, credentialType, authMode, error) < 0) + return DPI_FAILURE; + return dpiConn__getServerCharset(conn, error); +} + + +//----------------------------------------------------------------------------- +// dpiConn__free() [INTERNAL] +// Free the memory and any resources associated with the connection. +//----------------------------------------------------------------------------- +void dpiConn__free(dpiConn *conn, dpiError *error) +{ + if (conn->handle) + dpiConn__close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0, 0, + error); + if (conn->pool) { + dpiGen__setRefCount(conn->pool, error, -1); + conn->pool = NULL; + conn->env = NULL; + } + if (conn->env) { + dpiEnv__free(conn->env, error); + conn->env = NULL; + } + if (conn->releaseString) { + dpiUtils__freeMemory((void*) conn->releaseString); + conn->releaseString = NULL; + } + if (conn->openStmts) { + dpiHandleList__free(conn->openStmts); + conn->openStmts = NULL; + } + if (conn->openLobs) { + dpiHandleList__free(conn->openLobs); + conn->openLobs = NULL; + } + if (conn->objects) { + dpiHandleList__free(conn->objects); + conn->objects = NULL; + } + dpiUtils__freeMemory(conn); +} + + +//----------------------------------------------------------------------------- +// dpiConn__get() [INTERNAL] +// Create a connection to the database using the parameters specified. This +// method uses the simplified OCI session creation protocol which is required +// when using pools and session tagging. +//----------------------------------------------------------------------------- +static int dpiConn__get(dpiConn *conn, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + const char *connectString, uint32_t connectStringLength, + dpiConnCreateParams *createParams, dpiPool *pool, dpiError *error) +{ + int externalAuth, status; + void *authInfo; + uint32_t mode; + + // clear pointers if length is 0 + if (userNameLength == 0) + userName = NULL; + if (passwordLength == 0) + password = NULL; + + // set things up for the call to acquire a session + if (pool) { + dpiGen__setRefCount(pool, error, 1); + conn->pool = pool; + mode = DPI_OCI_SESSGET_SPOOL; + externalAuth = pool->externalAuth; + if (userName && pool->homogeneous) + return dpiError__set(error, "check proxy", DPI_ERR_INVALID_PROXY); + + // if the userName is provided but no password is provided and external + // authentication is not being used, proxy authentication is taking + // place + if (userName && !password && !externalAuth) + mode |= DPI_OCI_SESSGET_CREDPROXY; + if (createParams->matchAnyTag) + mode |= DPI_OCI_SESSGET_SPOOL_MATCHANY; + if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2, + NULL) == DPI_SUCCESS && createParams->tag && + createParams->tagLength > 0) + mode |= DPI_OCI_SESSGET_MULTIPROPERTY_TAG; + } else { + mode = DPI_OCI_SESSGET_STMTCACHE; + externalAuth = createParams->externalAuth; + } + if (createParams->authMode & DPI_MODE_AUTH_SYSDBA) + mode |= DPI_OCI_SESSGET_SYSDBA; + if (externalAuth) + mode |= DPI_OCI_SESSGET_CREDEXT; + + // create authorization handle + if (dpiOci__handleAlloc(conn->env->handle, &authInfo, + DPI_OCI_HTYPE_AUTHINFO, "allocate authinfo handle", error) < 0) + return DPI_FAILURE; + + // set attributes for create parameters + if (dpiConn__setAttributesFromCreateParams(conn, authInfo, + DPI_OCI_HTYPE_AUTHINFO, userName, userNameLength, password, + passwordLength, createParams, error) < 0) { + dpiOci__handleFree(authInfo, DPI_OCI_HTYPE_AUTHINFO); + return DPI_FAILURE; + } + + // get a session from the pool + status = dpiConn__getSession(conn, mode, connectString, + connectStringLength, createParams, authInfo, error); + dpiOci__handleFree(authInfo, DPI_OCI_HTYPE_AUTHINFO); + if (status < 0) + return status; + return dpiConn__getServerCharset(conn, error); +} + + +//----------------------------------------------------------------------------- +// dpiConn__getAttributeText() [INTERNAL] +// Get the value of the OCI attribute from a text string. +//----------------------------------------------------------------------------- +static int dpiConn__getAttributeText(dpiConn *conn, uint32_t attribute, + const char **value, uint32_t *valueLength, const char *fnName) +{ + dpiError error; + int status; + + // validate parameters + if (dpiConn__check(conn, fnName, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, value) + DPI_CHECK_PTR_NOT_NULL(conn, valueLength) + + // determine pointer to pass (OCI uses different sizes) + switch (attribute) { + case DPI_OCI_ATTR_CURRENT_SCHEMA: + case DPI_OCI_ATTR_LTXID: + case DPI_OCI_ATTR_EDITION: + status = dpiOci__attrGet(conn->sessionHandle, + DPI_OCI_HTYPE_SESSION, (void*) value, valueLength, + attribute, "get session value", &error); + break; + case DPI_OCI_ATTR_INTERNAL_NAME: + case DPI_OCI_ATTR_EXTERNAL_NAME: + status = dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, + (void*) value, valueLength, attribute, "get server value", + &error); + break; + default: + status = dpiError__set(&error, "get attribute text", + DPI_ERR_NOT_SUPPORTED); + break; + } + + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn__getHandles() [INTERNAL] +// Get the server and session handle from the service context handle. +//----------------------------------------------------------------------------- +static int dpiConn__getHandles(dpiConn *conn, dpiError *error) +{ + if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, + (void*) &conn->sessionHandle, NULL, DPI_OCI_ATTR_SESSION, + "get session handle", error) < 0) + return DPI_FAILURE; + if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, + (void*) &conn->serverHandle, NULL, DPI_OCI_ATTR_SERVER, + "get server handle", error) < 0) + return DPI_FAILURE; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiConn__getRawTDO() [INTERNAL] +// Internal method used for ensuring that the RAW TDO has been cached on the +//connection. +//----------------------------------------------------------------------------- +int dpiConn__getRawTDO(dpiConn *conn, dpiError *error) +{ + if (conn->rawTDO) + return DPI_SUCCESS; + return dpiOci__typeByName(conn, "SYS", 3, "RAW", 3, &conn->rawTDO, error); +} + + +//----------------------------------------------------------------------------- +// dpiConn__getServerCharset() [INTERNAL] +// Internal method used for retrieving the server character set. This is used +// to determine if any conversion is required when transferring strings between +// the client and the server. +//----------------------------------------------------------------------------- +static int dpiConn__getServerCharset(dpiConn *conn, dpiError *error) +{ + return dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, + &conn->charsetId, NULL, DPI_OCI_ATTR_CHARSET_ID, + "get server charset id", error); +} + + +//----------------------------------------------------------------------------- +// dpiConn__getServerVersion() [INTERNAL] +// Internal method used for ensuring that the server version has been cached +// on the connection. +//----------------------------------------------------------------------------- +int dpiConn__getServerVersion(dpiConn *conn, dpiError *error) +{ + uint32_t serverRelease; + char buffer[512]; + + // nothing to do if the server version has been determined earlier + if (conn->releaseString) + return DPI_SUCCESS; + + // get server version + if (dpiOci__serverRelease(conn, buffer, sizeof(buffer), &serverRelease, + error) < 0) + return DPI_FAILURE; + conn->releaseStringLength = (uint32_t) strlen(buffer); + if (dpiUtils__allocateMemory(1, conn->releaseStringLength, 0, + "allocate release string", (void**) &conn->releaseString, + error) < 0) + return DPI_FAILURE; + strncpy( (char*) conn->releaseString, buffer, conn->releaseStringLength); + conn->versionInfo.versionNum = (int)((serverRelease >> 24) & 0xFF); + if (conn->versionInfo.versionNum >= 18) { + conn->versionInfo.releaseNum = (int)((serverRelease >> 16) & 0xFF); + conn->versionInfo.updateNum = (int)((serverRelease >> 12) & 0x0F); + conn->versionInfo.portReleaseNum = (int)((serverRelease >> 4) & 0xFF); + conn->versionInfo.portUpdateNum = (int)((serverRelease) & 0xF); + } else { + conn->versionInfo.releaseNum = (int)((serverRelease >> 20) & 0x0F); + conn->versionInfo.updateNum = (int)((serverRelease >> 12) & 0xFF); + conn->versionInfo.portReleaseNum = (int)((serverRelease >> 8) & 0x0F); + conn->versionInfo.portUpdateNum = (int)((serverRelease) & 0xFF); + } + conn->versionInfo.fullVersionNum = (uint32_t) + DPI_ORACLE_VERSION_TO_NUMBER(conn->versionInfo.versionNum, + conn->versionInfo.releaseNum, + conn->versionInfo.updateNum, + conn->versionInfo.portReleaseNum, + conn->versionInfo.portUpdateNum); + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiConn__getSession() [INTERNAL] +// Ping and loop until we get a good session. When a database instance goes +// down, it can leave several bad connections that need to be flushed out +// before a good connection can be acquired. If the connection is brand new +// (ping time context value has not been set) there is no need to do a ping. +// This also ensures that the loop cannot run forever! +//----------------------------------------------------------------------------- +static int dpiConn__getSession(dpiConn *conn, uint32_t mode, + const char *connectString, uint32_t connectStringLength, + dpiConnCreateParams *params, void *authInfo, dpiError *error) +{ + uint8_t savedBreakOnTimeout, breakOnTimeout; + uint32_t savedTimeout; + time_t *lastTimeUsed; + + while (1) { + + // acquire the new session + params->outNewSession = 0; + if (dpiOci__sessionGet(conn->env->handle, &conn->handle, authInfo, + connectString, connectStringLength, params->tag, + params->tagLength, ¶ms->outTag, ¶ms->outTagLength, + ¶ms->outTagFound, mode, error) < 0) + return DPI_FAILURE; + + // get session and server handles + if (dpiConn__getHandles(conn, error) < 0) + return DPI_FAILURE; + + // get last time used from session context + lastTimeUsed = NULL; + if (dpiOci__contextGetValue(conn, DPI_CONTEXT_LAST_TIME_USED, + (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), + (void**) &lastTimeUsed, 1, error) < 0) + return DPI_FAILURE; + + // if value is not found, a new connection has been created and there + // is no need to perform a ping; nor if we are creating a standalone + // connection + if (!lastTimeUsed || !conn->pool) { + params->outNewSession = 1; + break; + } + + // if ping interval is negative or the ping interval (in seconds) + // has not been exceeded yet, there is also no need to perform a ping + if (conn->pool->pingInterval < 0 || + *lastTimeUsed + conn->pool->pingInterval > time(NULL)) + break; + + // ping needs to be done at this point; set parameters to ensure that + // the ping does not take too long to complete; keep original values + dpiOci__attrGet(conn->serverHandle, + DPI_OCI_HTYPE_SERVER, &savedTimeout, NULL, + DPI_OCI_ATTR_RECEIVE_TIMEOUT, NULL, error); + dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, + &conn->pool->pingTimeout, 0, DPI_OCI_ATTR_RECEIVE_TIMEOUT, + NULL, error); + if (conn->env->versionInfo->versionNum >= 12) { + dpiOci__attrGet(conn->serverHandle, + DPI_OCI_HTYPE_SERVER, &savedBreakOnTimeout, NULL, + DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, NULL, error); + breakOnTimeout = 0; + dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, + &breakOnTimeout, 0, DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, + NULL, error); + } + + // if ping is successful, the connection is valid and can be returned + // restore original network parameters + if (dpiOci__ping(conn, error) == 0) { + dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, + &savedTimeout, 0, DPI_OCI_ATTR_RECEIVE_TIMEOUT, NULL, + error); + if (conn->env->versionInfo->versionNum >= 12) + dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, + &savedBreakOnTimeout, 0, + DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, NULL, error); + break; + } + + // session is bad, need to release and drop it + dpiOci__sessionRelease(conn, NULL, 0, DPI_OCI_SESSRLS_DROPSESS, 0, + error); + conn->handle = NULL; + conn->serverHandle = NULL; + conn->sessionHandle = NULL; + conn->deadSession = 0; + + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiConn__setAppContext() [INTERNAL] +// Populate the session handle with the application context. +//----------------------------------------------------------------------------- +static int dpiConn__setAppContext(void *handle, uint32_t handleType, + const dpiConnCreateParams *params, dpiError *error) +{ + void *listHandle, *entryHandle; + dpiAppContext *entry; + uint32_t i; + + // set the number of application context entries + if (dpiOci__attrSet(handle, handleType, (void*) ¶ms->numAppContext, + sizeof(params->numAppContext), DPI_OCI_ATTR_APPCTX_SIZE, + "set app context size", error) < 0) + return DPI_FAILURE; + + // get the application context list handle + if (dpiOci__attrGet(handle, handleType, &listHandle, NULL, + DPI_OCI_ATTR_APPCTX_LIST, "get context list handle", error) < 0) + return DPI_FAILURE; + + // set each application context entry + for (i = 0; i < params->numAppContext; i++) { + entry = ¶ms->appContext[i]; + + // retrieve the context element descriptor + if (dpiOci__paramGet(listHandle, DPI_OCI_DTYPE_PARAM, + &entryHandle, i + 1, "get context entry handle", error) < 0) + return DPI_FAILURE; + + // set the namespace name + if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM, + (void*) entry->namespaceName, entry->namespaceNameLength, + DPI_OCI_ATTR_APPCTX_NAME, "set namespace name", error) < 0) + return DPI_FAILURE; + + // set the name + if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM, + (void*) entry->name, entry->nameLength, + DPI_OCI_ATTR_APPCTX_ATTR, "set name", error) < 0) + return DPI_FAILURE; + + // set the value + if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM, + (void*) entry->value, entry->valueLength, + DPI_OCI_ATTR_APPCTX_VALUE, "set value", error) < 0) + return DPI_FAILURE; + + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiConn__setAttributesFromCreateParams() [INTERNAL] +// Populate the authorization info structure or session handle using the +// create parameters specified. +//----------------------------------------------------------------------------- +static int dpiConn__setAttributesFromCreateParams(dpiConn *conn, void *handle, + uint32_t handleType, const char *userName, uint32_t userNameLength, + const char *password, uint32_t passwordLength, + const dpiConnCreateParams *params, dpiError *error) +{ + uint32_t purity; + + // set credentials + if (userName && userNameLength > 0 && dpiOci__attrSet(handle, + handleType, (void*) userName, userNameLength, + DPI_OCI_ATTR_USERNAME, "set user name", error) < 0) + return DPI_FAILURE; + if (password && passwordLength > 0 && dpiOci__attrSet(handle, + handleType, (void*) password, passwordLength, + DPI_OCI_ATTR_PASSWORD, "set password", error) < 0) + return DPI_FAILURE; + + // set connection class and purity parameters + if (params->connectionClass && params->connectionClassLength > 0 && + dpiOci__attrSet(handle, handleType, + (void*) params->connectionClass, + params->connectionClassLength, + DPI_OCI_ATTR_CONNECTION_CLASS, "set connection class", + error) < 0) + return DPI_FAILURE; + if (params->purity != DPI_OCI_ATTR_PURITY_DEFAULT) { + purity = params->purity; + if (dpiOci__attrSet(handle, handleType, &purity, + sizeof(purity), DPI_OCI_ATTR_PURITY, "set purity", error) < 0) + return DPI_FAILURE; + } + + // set sharding key and super sharding key parameters + if (params->shardingKeyColumns && params->numShardingKeyColumns > 0) { + if (dpiConn__setShardingKey(conn, &conn->shardingKey, handle, + handleType, DPI_OCI_ATTR_SHARDING_KEY, "set sharding key", + params->shardingKeyColumns, params->numShardingKeyColumns, + error) < 0) + return DPI_FAILURE; + } + if (params->superShardingKeyColumns && + params->numSuperShardingKeyColumns > 0) { + if (params->numShardingKeyColumns == 0) + return dpiError__set(error, "ensure sharding key", + DPI_ERR_MISSING_SHARDING_KEY); + if (dpiConn__setShardingKey(conn, &conn->superShardingKey, handle, + handleType, DPI_OCI_ATTR_SUPER_SHARDING_KEY, + "set super sharding key", params->superShardingKeyColumns, + params->numSuperShardingKeyColumns, error) < 0) + return DPI_FAILURE; + } + + // set application context, if applicable + if (handleType == DPI_OCI_HTYPE_SESSION && params->numAppContext > 0) + return dpiConn__setAppContext(handle, handleType, params, error); + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiConn__setAttributeText() [INTERNAL] +// Set the value of the OCI attribute from a text string. +//----------------------------------------------------------------------------- +static int dpiConn__setAttributeText(dpiConn *conn, uint32_t attribute, + const char *value, uint32_t valueLength, const char *fnName) +{ + dpiError error; + int status; + + // validate parameters + if (dpiConn__check(conn, fnName, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(conn, value) + + // determine pointer to pass (OCI uses different sizes) + switch (attribute) { + case DPI_OCI_ATTR_ACTION: + case DPI_OCI_ATTR_CLIENT_IDENTIFIER: + case DPI_OCI_ATTR_CLIENT_INFO: + case DPI_OCI_ATTR_CURRENT_SCHEMA: + case DPI_OCI_ATTR_EDITION: + case DPI_OCI_ATTR_MODULE: + case DPI_OCI_ATTR_DBOP: + status = dpiOci__attrSet(conn->sessionHandle, + DPI_OCI_HTYPE_SESSION, (void*) value, valueLength, + attribute, "set session value", &error); + break; + case DPI_OCI_ATTR_INTERNAL_NAME: + case DPI_OCI_ATTR_EXTERNAL_NAME: + status = dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, + (void*) value, valueLength, attribute, "set server value", + &error); + break; + default: + status = dpiError__set(&error, "set attribute text", + DPI_ERR_NOT_SUPPORTED); + break; + } + + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn__setShardingKey() [INTERNAL] +// Using the specified columns, create a sharding key and set it on the given +// handle. +//----------------------------------------------------------------------------- +static int dpiConn__setShardingKey(dpiConn *conn, void **shardingKey, + void *handle, uint32_t handleType, uint32_t attribute, + const char *action, dpiShardingKeyColumn *columns, uint8_t numColumns, + dpiError *error) +{ + uint8_t i; + + // this is only supported on 12.2 and higher clients + if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2, + error) < 0) + return DPI_FAILURE; + + // create sharding key descriptor, if necessary + if (dpiOci__descriptorAlloc(conn->env->handle, shardingKey, + DPI_OCI_DTYPE_SHARDING_KEY, "allocate sharding key", error) < 0) + return DPI_FAILURE; + + // add each column to the sharding key + for (i = 0; i < numColumns; i++) { + if (dpiConn__setShardingKeyValue(conn, *shardingKey, &columns[i], + error) < 0) + return DPI_FAILURE; + } + + // add the sharding key to the handle + if (dpiOci__attrSet(handle, handleType, *shardingKey, 0, attribute, action, + error) < 0) + return DPI_FAILURE; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiConn__setShardingKeyValue() [INTERNAL] +// Using the specified columns, create a sharding key and set it on the given +// handle. +//----------------------------------------------------------------------------- +static int dpiConn__setShardingKeyValue(dpiConn *conn, void *shardingKey, + dpiShardingKeyColumn *column, dpiError *error) +{ + dpiShardingOciDate shardingDateValue; + uint32_t colLen = 0, descType = 0; + const dpiOracleType *oracleType; + dpiOciNumber numberValue; + int convertOk, status; + dpiOciDate dateValue; + void *col = NULL; + uint16_t colType; + + oracleType = dpiOracleType__getFromNum(column->oracleTypeNum, error); + if (!oracleType) + return DPI_FAILURE; + convertOk = 0; + colType = oracleType->oracleType; + switch (column->oracleTypeNum) { + case DPI_ORACLE_TYPE_VARCHAR: + case DPI_ORACLE_TYPE_CHAR: + case DPI_ORACLE_TYPE_RAW: + if (column->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { + col = column->value.asBytes.ptr; + colLen = column->value.asBytes.length; + convertOk = 1; + } + break; + case DPI_ORACLE_TYPE_NUMBER: + col = &numberValue; + colLen = sizeof(numberValue); + if (column->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { + if (dpiDataBuffer__toOracleNumberFromDouble(&column->value, + error, &numberValue) < 0) + return DPI_FAILURE; + convertOk = 1; + } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_INT64) { + if (dpiDataBuffer__toOracleNumberFromInteger(&column->value, + error, &numberValue) < 0) + return DPI_FAILURE; + convertOk = 1; + } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_UINT64) { + if (dpiDataBuffer__toOracleNumberFromUnsignedInteger( + &column->value, error, &numberValue) < 0) + return DPI_FAILURE; + convertOk = 1; + } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { + if (dpiDataBuffer__toOracleNumberFromText(&column->value, + conn->env, error, &numberValue) < 0) + return DPI_FAILURE; + convertOk = 1; + } + break; + case DPI_ORACLE_TYPE_DATE: + if (column->nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) { + if (dpiDataBuffer__toOracleDate(&column->value, + &dateValue) < 0) + return DPI_FAILURE; + convertOk = 1; + } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { + if (dpiDataBuffer__toOracleDateFromDouble(&column->value, + conn->env, error, &dateValue) < 0) + return DPI_FAILURE; + convertOk = 1; + } + + // for sharding only, the type must be SQLT_DAT, which uses a + // different format for storing the date values + if (convertOk) { + col = &shardingDateValue; + colLen = sizeof(shardingDateValue); + colType = DPI_SQLT_DAT; + shardingDateValue.century = + ((uint8_t) (dateValue.year / 100)) + 100; + shardingDateValue.year = (dateValue.year % 100) + 100; + shardingDateValue.month = dateValue.month; + shardingDateValue.day = dateValue.day; + shardingDateValue.hour = dateValue.hour + 1; + shardingDateValue.minute = dateValue.minute + 1; + shardingDateValue.second = dateValue.second + 1; + } + break; + case DPI_ORACLE_TYPE_TIMESTAMP: + case DPI_ORACLE_TYPE_TIMESTAMP_TZ: + case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: + colLen = sizeof(void*); + colType = DPI_SQLT_TIMESTAMP; + if (column->nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) { + descType = DPI_OCI_DTYPE_TIMESTAMP; + if (dpiOci__descriptorAlloc(conn->env->handle, &col, descType, + "alloc timestamp", error) < 0) + return DPI_FAILURE; + if (dpiDataBuffer__toOracleTimestamp(&column->value, conn->env, + error, col, 0) < 0) { + dpiOci__descriptorFree(col, descType); + return DPI_FAILURE; + } + convertOk = 1; + } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { + descType = DPI_OCI_DTYPE_TIMESTAMP_LTZ; + if (dpiOci__descriptorAlloc(conn->env->handle, &col, descType, + "alloc LTZ timestamp", error) < 0) + return DPI_FAILURE; + if (dpiDataBuffer__toOracleTimestampFromDouble(&column->value, + conn->env, error, col) < 0) { + dpiOci__descriptorFree(col, descType); + return DPI_FAILURE; + } + convertOk = 1; + } + break; + default: + break; + } + if (!convertOk) + return dpiError__set(error, "check type", DPI_ERR_NOT_SUPPORTED); + + status = dpiOci__shardingKeyColumnAdd(shardingKey, col, colLen, colType, + error); + if (descType) + dpiOci__descriptorFree(col, descType); + return status; +} + + +//----------------------------------------------------------------------------- +// dpiConn_addRef() [PUBLIC] +// Add a reference to the connection. +//----------------------------------------------------------------------------- +int dpiConn_addRef(dpiConn *conn) +{ + return dpiGen__addRef(conn, DPI_HTYPE_CONN, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_beginDistribTrans() [PUBLIC] +// Begin a distributed transaction. +//----------------------------------------------------------------------------- +int dpiConn_beginDistribTrans(dpiConn *conn, long formatId, + const char *transactionId, uint32_t transactionIdLength, + const char *branchId, uint32_t branchIdLength) +{ + void *transactionHandle; + dpiError error; + dpiOciXID xid; + int status; + + // validate parameters + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(conn, transactionId) + DPI_CHECK_PTR_AND_LENGTH(conn, branchId) + if (transactionIdLength > DPI_XA_MAXGTRIDSIZE) { + dpiError__set(&error, "check size of transaction id", + DPI_ERR_TRANS_ID_TOO_LARGE, transactionIdLength, + DPI_XA_MAXGTRIDSIZE); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + if (branchIdLength > DPI_XA_MAXBQUALSIZE) { + dpiError__set(&error, "check size of branch id", + DPI_ERR_BRANCH_ID_TOO_LARGE, branchIdLength, + DPI_XA_MAXBQUALSIZE); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + // determine if a transaction handle was previously allocated + if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, + (void*) &transactionHandle, NULL, DPI_OCI_ATTR_TRANS, + "get transaction handle", &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + + // if one was not found, create one and associate it with the connection + if (!transactionHandle) { + + // create new handle + if (dpiOci__handleAlloc(conn->env->handle, &transactionHandle, + DPI_OCI_HTYPE_TRANS, "create transaction handle", &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + + // associate the transaction with the connection + if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, + transactionHandle, 0, DPI_OCI_ATTR_TRANS, + "associate transaction", &error) < 0) { + dpiOci__handleFree(transactionHandle, DPI_OCI_HTYPE_TRANS); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + } + + // set the XID for the transaction, if applicable + if (formatId != -1) { + xid.formatID = formatId; + xid.gtrid_length = transactionIdLength; + xid.bqual_length = branchIdLength; + if (transactionIdLength > 0) + strncpy(xid.data, transactionId, transactionIdLength); + if (branchIdLength > 0) + strncpy(&xid.data[transactionIdLength], branchId, branchIdLength); + if (dpiOci__attrSet(transactionHandle, DPI_OCI_HTYPE_TRANS, &xid, + sizeof(dpiOciXID), DPI_OCI_ATTR_XID, "set XID", &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + // start the transaction + status = dpiOci__transStart(conn, &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_breakExecution() [PUBLIC] +// Break (interrupt) the currently executing operation. +//----------------------------------------------------------------------------- +int dpiConn_breakExecution(dpiConn *conn) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + status = dpiOci__break(conn, &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_changePassword() [PUBLIC] +// Change the password for the specified user. +//----------------------------------------------------------------------------- +int dpiConn_changePassword(dpiConn *conn, const char *userName, + uint32_t userNameLength, const char *oldPassword, + uint32_t oldPasswordLength, const char *newPassword, + uint32_t newPasswordLength) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(conn, userName) + DPI_CHECK_PTR_AND_LENGTH(conn, oldPassword) + DPI_CHECK_PTR_AND_LENGTH(conn, newPassword) + status = dpiOci__passwordChange(conn, userName, userNameLength, + oldPassword, oldPasswordLength, newPassword, newPasswordLength, + DPI_OCI_DEFAULT, &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_close() [PUBLIC] +// Close the connection and ensure it can no longer be used. +//----------------------------------------------------------------------------- +int dpiConn_close(dpiConn *conn, dpiConnCloseMode mode, const char *tag, + uint32_t tagLength) +{ + int propagateErrors = !(mode & DPI_MODE_CONN_CLOSE_DROP); + dpiError error; + int closing; + + // validate parameters + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(conn, tag) + if (mode && !conn->pool) { + dpiError__set(&error, "check in pool", DPI_ERR_CONN_NOT_IN_POOL); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + if (conn->externalHandle) { + dpiError__set(&error, "check external", DPI_ERR_CONN_IS_EXTERNAL); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + // determine whether connection is already being closed and if not, mark + // connection as being closed; this MUST be done while holding the lock + // (if in threaded mode) to avoid race conditions! + if (conn->env->threaded) + dpiMutex__acquire(conn->env->mutex); + closing = conn->closing; + conn->closing = 1; + if (conn->env->threaded) + dpiMutex__release(conn->env->mutex); + + // if connection is already being closed, raise an exception + if (closing) { + dpiError__set(&error, "check closing", DPI_ERR_NOT_CONNECTED); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + // if actual close fails, reset closing flag; again, this must be done + // while holding the lock (if in threaded mode) in order to avoid race + // conditions! + if (dpiConn__close(conn, mode, tag, tagLength, propagateErrors, + &error) < 0) { + if (conn->env->threaded) + dpiMutex__acquire(conn->env->mutex); + conn->closing = 0; + if (conn->env->threaded) + dpiMutex__release(conn->env->mutex); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_commit() [PUBLIC] +// Commit the transaction associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_commit(dpiConn *conn) +{ + dpiError error; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiOci__transCommit(conn, conn->commitMode, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + conn->commitMode = DPI_OCI_DEFAULT; + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_create() [PUBLIC] +// Create a standalone connection to the database using the parameters +// specified. +//----------------------------------------------------------------------------- +int dpiConn_create(const dpiContext *context, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + const char *connectString, uint32_t connectStringLength, + const dpiCommonCreateParams *commonParams, + dpiConnCreateParams *createParams, dpiConn **conn) +{ + dpiCommonCreateParams localCommonParams; + dpiConnCreateParams localCreateParams; + dpiConn *tempConn; + dpiError error; + int status; + + // validate parameters + if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, + &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(context, conn) + DPI_CHECK_PTR_AND_LENGTH(context, userName) + DPI_CHECK_PTR_AND_LENGTH(context, password) + DPI_CHECK_PTR_AND_LENGTH(context, connectString) + + // use default parameters if none provided + if (!commonParams) { + dpiContext__initCommonCreateParams(&localCommonParams); + commonParams = &localCommonParams; + } + + // size changed in 3.1; must use local variable until version 4 released + if (!createParams || context->dpiMinorVersion < 1) { + dpiContext__initConnCreateParams(&localCreateParams); + if (createParams) + memcpy(&localCreateParams, createParams, + sizeof(dpiConnCreateParams__v30)); + createParams = &localCreateParams; + } + + // password must not be specified if external authentication is desired + if (createParams->externalAuth && password && passwordLength > 0) { + dpiError__set(&error, "verify no password with external auth", + DPI_ERR_EXT_AUTH_WITH_CREDENTIALS); + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + } + + // the username must be enclosed within [] if external authentication + // with proxy is desired + if (createParams->externalAuth && userName && userNameLength > 0 && + (userName[0] != '[' || userName[userNameLength - 1] != ']')) { + dpiError__set(&error, "verify proxy user name with external auth", + DPI_ERR_EXT_AUTH_INVALID_PROXY); + return dpiGen__endPublicFn(context, DPI_FAILURE, &error ); + } + + // connectionClass and edition cannot be specified at the same time + if (createParams->connectionClass && + createParams->connectionClassLength > 0 && + commonParams->edition && commonParams->editionLength > 0) { + dpiError__set(&error, "check edition/conn class", + DPI_ERR_NO_EDITION_WITH_CONN_CLASS); + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + } + + // newPassword and edition cannot be specified at the same time + if (createParams->newPassword && createParams->newPasswordLength > 0 && + commonParams->edition && commonParams->editionLength > 0) { + dpiError__set(&error, "check edition/new password", + DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD); + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + } + + // handle case where pool is specified + if (createParams->pool) { + if (dpiGen__checkHandle(createParams->pool, DPI_HTYPE_POOL, + "verify pool", &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + if (!createParams->pool->handle) { + dpiError__set(&error, "check pool", DPI_ERR_NOT_CONNECTED); + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + } + status = dpiPool__acquireConnection(createParams->pool, userName, + userNameLength, password, passwordLength, createParams, conn, + &error); + return dpiGen__endPublicFn(context, status, &error); + } + + // create connection + if (dpiGen__allocate(DPI_HTYPE_CONN, NULL, (void**) &tempConn, &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + if (dpiConn__create(tempConn, context, userName, userNameLength, + password, passwordLength, connectString, connectStringLength, + NULL, commonParams, createParams, &error) < 0) { + dpiConn__free(tempConn, &error); + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + } + + *conn = tempConn; + dpiHandlePool__release(tempConn->env->errorHandles, &error.handle); + return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getSodaDb() [PUBLIC] +// Create a new SODA collection with the given name and metadata. +//----------------------------------------------------------------------------- +int dpiConn_getSodaDb(dpiConn *conn, dpiSodaDb **db) +{ + dpiError error; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 3, + &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiUtils__checkDatabaseVersion(conn, 18, 0, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiGen__allocate(DPI_HTYPE_SODA_DB, conn->env, (void**) db, + &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + dpiGen__setRefCount(conn, &error, 1); + (*db)->conn = conn; + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_deqObject() [PUBLIC] +// Dequeue a message from the specified queue. +//----------------------------------------------------------------------------- +int dpiConn_deqObject(dpiConn *conn, const char *queueName, + uint32_t queueNameLength, dpiDeqOptions *options, dpiMsgProps *props, + dpiObject *payload, const char **msgId, uint32_t *msgIdLength) +{ + dpiError error; + + // validate parameters + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiGen__checkHandle(options, DPI_HTYPE_DEQ_OPTIONS, "verify options", + &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS, + "verify message properties", &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiGen__checkHandle(payload, DPI_HTYPE_OBJECT, "verify payload", + &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(conn, queueName) + DPI_CHECK_PTR_NOT_NULL(conn, msgId) + DPI_CHECK_PTR_NOT_NULL(conn, msgIdLength) + + // dequeue message + if (dpiOci__aqDeq(conn, queueName, options->handle, props->handle, + payload->type->tdo, &payload->instance, &payload->indicator, + &props->msgIdRaw, &error) < 0) { + if (error.buffer->code == 25228) { + *msgId = NULL; + *msgIdLength = 0; + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); + } + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + dpiMsgProps__extractMsgId(props, msgId, msgIdLength); + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_enqObject() [PUBLIC] +// Enqueue a message to the specified queue. +//----------------------------------------------------------------------------- +int dpiConn_enqObject(dpiConn *conn, const char *queueName, + uint32_t queueNameLength, dpiEnqOptions *options, dpiMsgProps *props, + dpiObject *payload, const char **msgId, uint32_t *msgIdLength) +{ + dpiError error; + + // validate parameters + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiGen__checkHandle(options, DPI_HTYPE_ENQ_OPTIONS, "verify options", + &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS, + "verify message properties", &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiGen__checkHandle(payload, DPI_HTYPE_OBJECT, "verify payload", + &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(conn, queueName) + DPI_CHECK_PTR_NOT_NULL(conn, msgId) + DPI_CHECK_PTR_NOT_NULL(conn, msgIdLength) + + // enqueue message + if (dpiOci__aqEnq(conn, queueName, options->handle, props->handle, + payload->type->tdo, &payload->instance, &payload->indicator, + &props->msgIdRaw, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + dpiMsgProps__extractMsgId(props, msgId, msgIdLength); + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getCallTimeout() [PUBLIC] +// Return the call timeout (in milliseconds) used for round-trips to the +// database. This is only valid in Oracle Client 18c and higher. +//----------------------------------------------------------------------------- +int dpiConn_getCallTimeout(dpiConn *conn, uint32_t *value) +{ + dpiError error; + int status; + + // validate parameters + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, value) + if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 1, + &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + + // get call timeout + status = dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, + (void*) value, 0, DPI_OCI_ATTR_CALL_TIMEOUT, "get call timeout", + &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getCurrentSchema() [PUBLIC] +// Return the current schema associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_getCurrentSchema(dpiConn *conn, const char **value, + uint32_t *valueLength) +{ + return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_CURRENT_SCHEMA, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getEdition() [PUBLIC] +// Return the edition associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_getEdition(dpiConn *conn, const char **value, + uint32_t *valueLength) +{ + return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_EDITION, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getEncodingInfo() [PUBLIC] +// Get the encodings from the connection. +//----------------------------------------------------------------------------- +int dpiConn_getEncodingInfo(dpiConn *conn, dpiEncodingInfo *info) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + status = dpiEnv__getEncodingInfo(conn->env, info); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getExternalName() [PUBLIC] +// Return the external name associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_getExternalName(dpiConn *conn, const char **value, + uint32_t *valueLength) +{ + return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_EXTERNAL_NAME, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getHandle() [PUBLIC] +// Get the OCI service context handle associated with the connection. This is +// available in order to allow for extensions to the library using OCI +// directly. +//----------------------------------------------------------------------------- +int dpiConn_getHandle(dpiConn *conn, void **handle) +{ + dpiError error; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, handle) + *handle = conn->handle; + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getInternalName() [PUBLIC] +// Return the internal name associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_getInternalName(dpiConn *conn, const char **value, + uint32_t *valueLength) +{ + return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_INTERNAL_NAME, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getLTXID() [PUBLIC] +// Return the logical transaction id associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_getLTXID(dpiConn *conn, const char **value, uint32_t *valueLength) +{ + return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_LTXID, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getObjectType() [PUBLIC] +// Look up an object type given its name and return it. +//----------------------------------------------------------------------------- +int dpiConn_getObjectType(dpiConn *conn, const char *name, uint32_t nameLength, + dpiObjectType **objType) +{ + void *describeHandle, *param, *tdo; + int status, useTypeByFullName; + dpiError error; + + // validate parameters + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, name) + DPI_CHECK_PTR_NOT_NULL(conn, objType) + + // allocate describe handle + if (dpiOci__handleAlloc(conn->env->handle, &describeHandle, + DPI_OCI_HTYPE_DESCRIBE, "allocate describe handle", &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + + // Oracle Client 12.1 is capable of using OCITypeByFullName() but will + // fail if accessing an Oracle 11.2 database + useTypeByFullName = 1; + if (conn->env->versionInfo->versionNum < 12) + useTypeByFullName = 0; + else if (dpiConn__getServerVersion(conn, &error) < 0) + return DPI_FAILURE; + else if (conn->versionInfo.versionNum < 12) + useTypeByFullName = 0; + + // new API is supported so use it + if (useTypeByFullName) { + if (dpiOci__typeByFullName(conn, name, nameLength, &tdo, &error) < 0) { + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + if (dpiOci__describeAny(conn, tdo, 0, DPI_OCI_OTYPE_PTR, + describeHandle, &error) < 0) { + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + // use older API + } else { + if (dpiOci__describeAny(conn, (void*) name, nameLength, + DPI_OCI_OTYPE_NAME, describeHandle, &error) < 0) { + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + } + + // get the parameter handle + if (dpiOci__attrGet(describeHandle, + DPI_OCI_HTYPE_DESCRIBE, ¶m, 0, DPI_OCI_ATTR_PARAM, + "get param", &error) < 0) { + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + // create object type + status = dpiObjectType__allocate(conn, param, DPI_OCI_ATTR_NAME, objType, + &error); + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getServerVersion() [PUBLIC] +// Get the server version string from the database. +//----------------------------------------------------------------------------- +int dpiConn_getServerVersion(dpiConn *conn, const char **releaseString, + uint32_t *releaseStringLength, dpiVersionInfo *versionInfo) +{ + dpiError error; + + // validate parameters + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, versionInfo) + + // get server version + if (dpiConn__getServerVersion(conn, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (releaseString) + *releaseString = conn->releaseString; + if (releaseStringLength) + *releaseStringLength = conn->releaseStringLength; + memcpy(versionInfo, &conn->versionInfo, sizeof(dpiVersionInfo)); + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_getStmtCacheSize() [PUBLIC] +// Return the current size of the statement cache. +//----------------------------------------------------------------------------- +int dpiConn_getStmtCacheSize(dpiConn *conn, uint32_t *cacheSize) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, cacheSize) + status = dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, cacheSize, + NULL, DPI_OCI_ATTR_STMTCACHESIZE, "get stmt cache size", &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_newDeqOptions() [PUBLIC] +// Create a new dequeue options object and return it. +//----------------------------------------------------------------------------- +int dpiConn_newDeqOptions(dpiConn *conn, dpiDeqOptions **options) +{ + dpiDeqOptions *tempOptions; + dpiError error; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, options) + if (dpiGen__allocate(DPI_HTYPE_DEQ_OPTIONS, conn->env, + (void**) &tempOptions, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiDeqOptions__create(tempOptions, conn, &error) < 0) { + dpiDeqOptions__free(tempOptions, &error); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + *options = tempOptions; + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_newEnqOptions() [PUBLIC] +// Create a new enqueue options object and return it. +//----------------------------------------------------------------------------- +int dpiConn_newEnqOptions(dpiConn *conn, dpiEnqOptions **options) +{ + dpiEnqOptions *tempOptions; + dpiError error; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, options) + if (dpiGen__allocate(DPI_HTYPE_ENQ_OPTIONS, conn->env, + (void**) &tempOptions, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiEnqOptions__create(tempOptions, conn, &error) < 0) { + dpiEnqOptions__free(tempOptions, &error); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + *options = tempOptions; + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_newTempLob() [PUBLIC] +// Create a new temporary LOB and return it. +//----------------------------------------------------------------------------- +int dpiConn_newTempLob(dpiConn *conn, dpiOracleTypeNum lobType, dpiLob **lob) +{ + const dpiOracleType *type; + dpiLob *tempLob; + dpiError error; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, lob) + switch (lobType) { + case DPI_ORACLE_TYPE_CLOB: + case DPI_ORACLE_TYPE_BLOB: + case DPI_ORACLE_TYPE_NCLOB: + type = dpiOracleType__getFromNum(lobType, &error); + break; + default: + dpiError__set(&error, "check lob type", + DPI_ERR_INVALID_ORACLE_TYPE, lobType); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + if (dpiLob__allocate(conn, type, &tempLob, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiOci__lobCreateTemporary(tempLob, &error) < 0) { + dpiLob__free(tempLob, &error); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + *lob = tempLob; + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_newMsgProps() [PUBLIC] +// Create a new message properties object and return it. +//----------------------------------------------------------------------------- +int dpiConn_newMsgProps(dpiConn *conn, dpiMsgProps **props) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, props) + status = dpiMsgProps__allocate(conn, props, &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_newQueue() [PUBLIC] +// Create a new AQ queue object and return it. +//----------------------------------------------------------------------------- +int dpiConn_newQueue(dpiConn *conn, const char *name, uint32_t nameLength, + dpiObjectType *payloadType, dpiQueue **queue) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(conn, name) + DPI_CHECK_PTR_NOT_NULL(conn, queue) + status = dpiQueue__allocate(conn, name, nameLength, payloadType, queue, + &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_newVar() [PUBLIC] +// Create a new variable and return it. +//----------------------------------------------------------------------------- +int dpiConn_newVar(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, + dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, + int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, + dpiData **data) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, var) + DPI_CHECK_PTR_NOT_NULL(conn, data) + status = dpiVar__allocate(conn, oracleTypeNum, nativeTypeNum, maxArraySize, + size, sizeIsBytes, isArray, objType, var, data, &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_ping() [PUBLIC] +// Makes a round trip call to the server to confirm that the connection and +// server are still active. +//----------------------------------------------------------------------------- +int dpiConn_ping(dpiConn *conn) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + status = dpiOci__ping(conn, &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_prepareDistribTrans() [PUBLIC] +// Prepare a distributed transaction for commit. A boolean is returned +// indicating if a commit is actually needed as an attempt to perform a commit +// when nothing is actually prepared results in ORA-24756 (transaction does not +// exist). This is determined by the return value from OCITransPrepare() which +// is OCI_SUCCESS_WITH_INFO if there is no transaction requiring commit. +//----------------------------------------------------------------------------- +int dpiConn_prepareDistribTrans(dpiConn *conn, int *commitNeeded) +{ + dpiError error; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, commitNeeded) + if (dpiOci__transPrepare(conn, commitNeeded, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (*commitNeeded) + conn->commitMode = DPI_OCI_TRANS_TWOPHASE; + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_prepareStmt() [PUBLIC] +// Create a new statement and return it after preparing the specified SQL. +//----------------------------------------------------------------------------- +int dpiConn_prepareStmt(dpiConn *conn, int scrollable, const char *sql, + uint32_t sqlLength, const char *tag, uint32_t tagLength, + dpiStmt **stmt) +{ + dpiStmt *tempStmt; + dpiError error; + + *stmt = NULL; + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(conn, sql) + DPI_CHECK_PTR_AND_LENGTH(conn, tag) + DPI_CHECK_PTR_NOT_NULL(conn, stmt) + if (dpiStmt__allocate(conn, scrollable, &tempStmt, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiStmt__prepare(tempStmt, sql, sqlLength, tag, tagLength, + &error) < 0) { + dpiStmt__free(tempStmt, &error); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + *stmt = tempStmt; + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_release() [PUBLIC] +// Release a reference to the connection. +//----------------------------------------------------------------------------- +int dpiConn_release(dpiConn *conn) +{ + return dpiGen__release(conn, DPI_HTYPE_CONN, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_rollback() [PUBLIC] +// Rollback the transaction associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_rollback(dpiConn *conn) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + status = dpiOci__transRollback(conn, 1, &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_setAction() [PUBLIC] +// Set the action associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_setAction(dpiConn *conn, const char *value, uint32_t valueLength) +{ + return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_ACTION, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_setCallTimeout() [PUBLIC] +// Set the call timeout (in milliseconds) used for round-trips to the +// database. This is only valid in Oracle Client 18c and higher. +//----------------------------------------------------------------------------- +int dpiConn_setCallTimeout(dpiConn *conn, uint32_t value) +{ + dpiError error; + int status; + + // validate parameters + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 1, + &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + + // set call timeout + status = dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &value, + 0, DPI_OCI_ATTR_CALL_TIMEOUT, "set call timeout", &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_setClientIdentifier() [PUBLIC] +// Set the client identifier associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_setClientIdentifier(dpiConn *conn, const char *value, + uint32_t valueLength) +{ + return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CLIENT_IDENTIFIER, + value, valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_setClientInfo() [PUBLIC] +// Set the client info associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_setClientInfo(dpiConn *conn, const char *value, + uint32_t valueLength) +{ + return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CLIENT_INFO, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_setCurrentSchema() [PUBLIC] +// Set the current schema associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_setCurrentSchema(dpiConn *conn, const char *value, + uint32_t valueLength) +{ + return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CURRENT_SCHEMA, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_setDbOp() [PUBLIC] +// Set the database operation associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_setDbOp(dpiConn *conn, const char *value, uint32_t valueLength) +{ + return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_DBOP, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_setExternalName() [PUBLIC] +// Set the external name associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_setExternalName(dpiConn *conn, const char *value, + uint32_t valueLength) +{ + return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_EXTERNAL_NAME, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_setInternalName() [PUBLIC] +// Set the internal name associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_setInternalName(dpiConn *conn, const char *value, + uint32_t valueLength) +{ + return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_INTERNAL_NAME, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_setModule() [PUBLIC] +// Set the module associated with the connection. +//----------------------------------------------------------------------------- +int dpiConn_setModule(dpiConn *conn, const char *value, uint32_t valueLength) +{ + return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_MODULE, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiConn_setStmtCacheSize() [PUBLIC] +// Set the size of the statement cache. +//----------------------------------------------------------------------------- +int dpiConn_setStmtCacheSize(dpiConn *conn, uint32_t cacheSize) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + status = dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &cacheSize, 0, + DPI_OCI_ATTR_STMTCACHESIZE, "set stmt cache size", &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_shutdownDatabase() [PUBLIC] +// Shutdown the database. Note that this must be done in two phases except in +// the situation where the instance is being aborted. +//----------------------------------------------------------------------------- +int dpiConn_shutdownDatabase(dpiConn *conn, dpiShutdownMode mode) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + status = dpiOci__dbShutdown(conn, mode, &error); + return dpiGen__endPublicFn(conn, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_startupDatabase() [PUBLIC] +// Startup the database. This is equivalent to "startup nomount" in SQL*Plus. +//----------------------------------------------------------------------------- +int dpiConn_startupDatabase(dpiConn *conn, dpiStartupMode mode) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + status = dpiOci__dbStartup(conn, mode, &error); + return dpiGen__endPublicFn(conn, status, &error); +} + +//----------------------------------------------------------------------------- +// dpiConn_subscribe() [PUBLIC] +// Subscribe to events in the database. A subscription is created and +// returned. This replaces dpiConn_newSubscription(). +//----------------------------------------------------------------------------- +int dpiConn_subscribe(dpiConn *conn, dpiSubscrCreateParams *params, + dpiSubscr **subscr) +{ + dpiSubscr *tempSubscr; + dpiError error; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(conn, params) + DPI_CHECK_PTR_NOT_NULL(conn, subscr) + if (!conn->env->events) { + dpiError__set(&error, "subscribe", DPI_ERR_EVENTS_MODE_REQUIRED); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + if (dpiGen__allocate(DPI_HTYPE_SUBSCR, conn->env, (void**) &tempSubscr, + &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiSubscr__create(tempSubscr, conn, params, &error) < 0) { + dpiSubscr__free(tempSubscr, &error); + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + } + + *subscr = tempSubscr; + return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiConn_unsubscribe() [PUBLIC] +// Unsubscribe from events in the database. Once this call completes +// successfully no further notifications will be sent. +//----------------------------------------------------------------------------- +int dpiConn_unsubscribe(dpiConn *conn, dpiSubscr *subscr) +{ + dpiError error; + int status; + + if (dpiConn__check(conn, __func__, &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (dpiGen__checkHandle(subscr, DPI_HTYPE_SUBSCR, "check subscription", + &error) < 0) + return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); + if (subscr->registered) { + dpiMutex__acquire(subscr->mutex); + status = dpiOci__subscriptionUnRegister(conn, subscr, &error); + if (status == DPI_SUCCESS) + subscr->registered = 0; + dpiMutex__release(subscr->mutex); + if (status < 0) + return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); + } + + dpiGen__setRefCount(subscr, &error, -1); + return dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiContext.c b/vendor/github.com/godror/godror/odpi/src/dpiContext.c new file mode 100644 index 00000000000..e9adb18a33e --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiContext.c @@ -0,0 +1,329 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiContext.c +// Implementation of context. Each context uses a specific version of the +// ODPI-C library, which is checked for compatibility before allowing its use. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +// maintain major and minor versions compiled into the library +static const unsigned int dpiMajorVersion = DPI_MAJOR_VERSION; +static const unsigned int dpiMinorVersion = DPI_MINOR_VERSION; + + +//----------------------------------------------------------------------------- +// dpiContext__create() [INTERNAL] +// Create a new context for interaction with the library. The major versions +// must match and the minor version of the caller must be less than or equal to +// the minor version compiled into the library. +//----------------------------------------------------------------------------- +static int dpiContext__create(const char *fnName, unsigned int majorVersion, + unsigned int minorVersion, dpiContext **context, dpiError *error) +{ + dpiContext *tempContext; + + // get error structure first (populates global environment if needed) + if (dpiGlobal__initError(fnName, error) < 0) + return DPI_FAILURE; + + // validate context handle + if (!context) + return dpiError__set(error, "check context handle", + DPI_ERR_NULL_POINTER_PARAMETER, "context"); + + // verify that the supplied version is supported by the library + if (dpiMajorVersion != majorVersion || minorVersion > dpiMinorVersion) + return dpiError__set(error, "check version", + DPI_ERR_VERSION_NOT_SUPPORTED, majorVersion, majorVersion, + minorVersion, dpiMajorVersion, dpiMinorVersion); + + // allocate context and initialize it + if (dpiGen__allocate(DPI_HTYPE_CONTEXT, NULL, (void**) &tempContext, + error) < 0) + return DPI_FAILURE; + tempContext->dpiMinorVersion = (uint8_t) minorVersion; + dpiOci__clientVersion(tempContext); + + *context = tempContext; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiContext__initCommonCreateParams() [INTERNAL] +// Initialize the common connection/pool creation parameters to default +// values. +//----------------------------------------------------------------------------- +void dpiContext__initCommonCreateParams(dpiCommonCreateParams *params) +{ + memset(params, 0, sizeof(dpiCommonCreateParams)); +} + + +//----------------------------------------------------------------------------- +// dpiContext__initConnCreateParams() [INTERNAL] +// Initialize the connection creation parameters to default values. Return +// the structure size as a convenience for calling functions which may have to +// differentiate between different ODPI-C application versions. +//----------------------------------------------------------------------------- +void dpiContext__initConnCreateParams(dpiConnCreateParams *params) +{ + memset(params, 0, sizeof(dpiConnCreateParams)); +} + + +//----------------------------------------------------------------------------- +// dpiContext__initPoolCreateParams() [INTERNAL] +// Initialize the pool creation parameters to default values. +//----------------------------------------------------------------------------- +void dpiContext__initPoolCreateParams(dpiPoolCreateParams *params) +{ + memset(params, 0, sizeof(dpiPoolCreateParams)); + params->minSessions = 1; + params->maxSessions = 1; + params->sessionIncrement = 0; + params->homogeneous = 1; + params->getMode = DPI_MODE_POOL_GET_NOWAIT; + params->pingInterval = DPI_DEFAULT_PING_INTERVAL; + params->pingTimeout = DPI_DEFAULT_PING_TIMEOUT; +} + + +//----------------------------------------------------------------------------- +// dpiContext__initSodaOperOptions() [INTERNAL] +// Initialize the SODA operation options to default values. +//----------------------------------------------------------------------------- +void dpiContext__initSodaOperOptions(dpiSodaOperOptions *options) +{ + memset(options, 0, sizeof(dpiSodaOperOptions)); +} + + +//----------------------------------------------------------------------------- +// dpiContext__initSubscrCreateParams() [INTERNAL] +// Initialize the subscription creation parameters to default values. +//----------------------------------------------------------------------------- +void dpiContext__initSubscrCreateParams(dpiSubscrCreateParams *params) +{ + memset(params, 0, sizeof(dpiSubscrCreateParams)); + params->subscrNamespace = DPI_SUBSCR_NAMESPACE_DBCHANGE; + params->groupingType = DPI_SUBSCR_GROUPING_TYPE_SUMMARY; +} + + +//----------------------------------------------------------------------------- +// dpiContext_create() [PUBLIC] +// Create a new context for interaction with the library. The major versions +// must match and the minor version of the caller must be less than or equal to +// the minor version compiled into the library. +//----------------------------------------------------------------------------- +int dpiContext_create(unsigned int majorVersion, unsigned int minorVersion, + dpiContext **context, dpiErrorInfo *errorInfo) +{ + dpiError error; + int status; + + if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) + dpiDebug__print("fn start %s\n", __func__); + status = dpiContext__create(__func__, majorVersion, minorVersion, context, + &error); + if (status < 0) + dpiError__getInfo(&error, errorInfo); + if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) + dpiDebug__print("fn end %s -> %d\n", __func__, status); + return status; +} + + +//----------------------------------------------------------------------------- +// dpiContext_destroy() [PUBLIC] +// Destroy an existing context. The structure will be checked for validity +// first. +//----------------------------------------------------------------------------- +int dpiContext_destroy(dpiContext *context) +{ + char message[80]; + dpiError error; + + if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, + &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + dpiUtils__clearMemory(&context->checkInt, sizeof(context->checkInt)); + if (dpiDebugLevel & DPI_DEBUG_LEVEL_REFS) + dpiDebug__print("ref %p (%s) -> 0\n", context, context->typeDef->name); + if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) + (void) sprintf(message, "fn end %s(%p) -> %d", __func__, context, + DPI_SUCCESS); + dpiUtils__freeMemory(context); + if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) + dpiDebug__print("%s\n", message); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiContext_getClientVersion() [PUBLIC] +// Return the version of the Oracle client that is in use. +//----------------------------------------------------------------------------- +int dpiContext_getClientVersion(const dpiContext *context, + dpiVersionInfo *versionInfo) +{ + dpiError error; + + if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, + &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(context, versionInfo) + memcpy(versionInfo, context->versionInfo, sizeof(dpiVersionInfo)); + return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiContext_getError() [PUBLIC] +// Return information about the error that was last populated. +//----------------------------------------------------------------------------- +void dpiContext_getError(const dpiContext *context, dpiErrorInfo *info) +{ + dpiError error; + + dpiGlobal__initError(NULL, &error); + dpiGen__checkHandle(context, DPI_HTYPE_CONTEXT, "check handle", &error); + dpiError__getInfo(&error, info); +} + + +//----------------------------------------------------------------------------- +// dpiContext_initCommonCreateParams() [PUBLIC] +// Initialize the common connection/pool creation parameters to default +// values. +//----------------------------------------------------------------------------- +int dpiContext_initCommonCreateParams(const dpiContext *context, + dpiCommonCreateParams *params) +{ + dpiError error; + + if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, + &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(context, params) + dpiContext__initCommonCreateParams(params); + return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiContext_initConnCreateParams() [PUBLIC] +// Initialize the connection creation parameters to default values. +//----------------------------------------------------------------------------- +int dpiContext_initConnCreateParams(const dpiContext *context, + dpiConnCreateParams *params) +{ + dpiConnCreateParams localParams; + dpiError error; + + if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, + &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(context, params) + + // size changed in version 3.1; can be dropped once version 4 released + if (context->dpiMinorVersion > 0) + dpiContext__initConnCreateParams(params); + else { + dpiContext__initConnCreateParams(&localParams); + memcpy(params, &localParams, sizeof(dpiConnCreateParams__v30)); + } + return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiContext_initPoolCreateParams() [PUBLIC] +// Initialize the pool creation parameters to default values. +//----------------------------------------------------------------------------- +int dpiContext_initPoolCreateParams(const dpiContext *context, + dpiPoolCreateParams *params) +{ + dpiPoolCreateParams localParams; + dpiError error; + + if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, + &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(context, params) + + // size changed in versions 3.1 and 3.3 + // changes can be dropped once version 4 released + if (context->dpiMinorVersion > 2) { + dpiContext__initPoolCreateParams(params); + } else { + dpiContext__initPoolCreateParams(&localParams); + if (context->dpiMinorVersion > 0) { + memcpy(params, &localParams, sizeof(dpiPoolCreateParams__v32)); + } else { + memcpy(params, &localParams, sizeof(dpiPoolCreateParams__v30)); + } + } + return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiContext_initSodaOperOptions() [PUBLIC] +// Initialize the SODA operation options to default values. +//----------------------------------------------------------------------------- +int dpiContext_initSodaOperOptions(const dpiContext *context, + dpiSodaOperOptions *options) +{ + dpiError error; + + if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, + &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(context, options) + dpiContext__initSodaOperOptions(options); + return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiContext_initSubscrCreateParams() [PUBLIC] +// Initialize the subscription creation parameters to default values. +//----------------------------------------------------------------------------- +int dpiContext_initSubscrCreateParams(const dpiContext *context, + dpiSubscrCreateParams *params) +{ + dpiSubscrCreateParams localParams; + dpiError error; + + if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, + &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(context, params) + + // size changed in versions 3.2 and 3.3 + // changes can be dropped once version 4 released + if (context->dpiMinorVersion > 2) { + dpiContext__initSubscrCreateParams(params); + } else { + dpiContext__initSubscrCreateParams(&localParams); + if (context->dpiMinorVersion > 1) { + memcpy(params, &localParams, sizeof(dpiSubscrCreateParams__v32)); + } else { + memcpy(params, &localParams, sizeof(dpiSubscrCreateParams__v30)); + } + } + return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiData.c b/vendor/github.com/godror/godror/odpi/src/dpiData.c new file mode 100644 index 00000000000..57d3faac309 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiData.c @@ -0,0 +1,899 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiData.c +// Implementation of transformation routines. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +// constants used for converting timestamps to/from an interval +#define DPI_MS_DAY 86400000 // 24 * 60 * 60 * 1000 +#define DPI_MS_HOUR 3600000 // 60 * 60 * 1000 +#define DPI_MS_MINUTE 60000 // 60 * 1000 +#define DPI_MS_SECOND 1000 // ms per sec +#define DPI_MS_FSECOND 1000000 // 1000 * 1000 + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__fromOracleDate() [INTERNAL] +// Populate the data from an dpiOciDate structure. +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleDate(dpiDataBuffer *data, + dpiOciDate *oracleValue) +{ + dpiTimestamp *timestamp = &data->asTimestamp; + + timestamp->year = oracleValue->year; + timestamp->month = oracleValue->month; + timestamp->day = oracleValue->day; + timestamp->hour = oracleValue->hour; + timestamp->minute = oracleValue->minute; + timestamp->second = oracleValue->second; + timestamp->fsecond = 0; + timestamp->tzHourOffset = 0; + timestamp->tzMinuteOffset = 0; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__fromOracleDateAsDouble() [INTERNAL] +// Populate the data from an dpiOciDate structure as a double value (number +// of milliseconds since January 1, 1970). +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleDateAsDouble(dpiDataBuffer *data, + dpiEnv *env, dpiError *error, dpiOciDate *oracleValue) +{ + void *timestamp; + int status; + + // allocate and populate a timestamp with the value of the date + if (dpiOci__descriptorAlloc(env->handle, ×tamp, + DPI_OCI_DTYPE_TIMESTAMP_LTZ, "alloc timestamp", error) < 0) + return DPI_FAILURE; + if (dpiOci__dateTimeConstruct(env->handle, timestamp, oracleValue->year, + oracleValue->month, oracleValue->day, oracleValue->hour, + oracleValue->minute, oracleValue->second, 0, NULL, 0, error) < 0) { + dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP_LTZ); + return DPI_FAILURE; + } + + // now calculate the number of milliseconds since January 1, 1970 + status = dpiDataBuffer__fromOracleTimestampAsDouble(data, env, error, + timestamp); + dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP_LTZ); + return status; +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__fromOracleIntervalDS() [INTERNAL] +// Populate the data from an OCIInterval structure (days/seconds). +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue) +{ + dpiIntervalDS *interval = &data->asIntervalDS; + + return dpiOci__intervalGetDaySecond(env->handle, &interval->days, + &interval->hours, &interval->minutes, &interval->seconds, + &interval->fseconds, oracleValue, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__fromOracleIntervalYM() [INTERNAL] +// Populate the data from an OCIInterval structure (years/months). +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue) +{ + dpiIntervalYM *interval = &data->asIntervalYM; + + return dpiOci__intervalGetYearMonth(env->handle, &interval->years, + &interval->months, oracleValue, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__fromOracleNumberAsDouble() [INTERNAL] +// Populate the data from an OCINumber structure as a double. +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleNumberAsDouble(dpiDataBuffer *data, + dpiError *error, void *oracleValue) +{ + return dpiOci__numberToReal(&data->asDouble, oracleValue, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__fromOracleNumberAsInteger() [INTERNAL] +// Populate the data from an OCINumber structure as an integer. +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleNumberAsInteger(dpiDataBuffer *data, + dpiError *error, void *oracleValue) +{ + return dpiOci__numberToInt(oracleValue, &data->asInt64, sizeof(int64_t), + DPI_OCI_NUMBER_SIGNED, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__fromOracleNumberAsUnsignedInteger() [INTERNAL] +// Populate the data from an OCINumber structure as an unsigned integer. +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleNumberAsUnsignedInteger(dpiDataBuffer *data, + dpiError *error, void *oracleValue) +{ + return dpiOci__numberToInt(oracleValue, &data->asUint64, sizeof(uint64_t), + DPI_OCI_NUMBER_UNSIGNED, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__fromOracleNumberAsText() [INTERNAL] +// Populate the data from an OCINumber structure as text. +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleNumberAsText(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue) +{ + uint8_t *target, numDigits, digits[DPI_NUMBER_MAX_DIGITS]; + int16_t decimalPointIndex, i; + uint16_t *targetUtf16; + uint32_t numBytes; + dpiBytes *bytes; + int isNegative; + + // parse the OCINumber structure + if (dpiUtils__parseOracleNumber(oracleValue, &isNegative, + &decimalPointIndex, &numDigits, digits, error) < 0) + return DPI_FAILURE; + + // calculate the number of bytes that will be required for the string + numBytes = numDigits; + if (isNegative) + numBytes++; + if (decimalPointIndex <= 0) + numBytes += -decimalPointIndex + 2; + else if (decimalPointIndex < numDigits) + numBytes++; + else if (decimalPointIndex > numDigits) + numBytes += decimalPointIndex - numDigits; + if (env->charsetId == DPI_CHARSET_ID_UTF16) + numBytes *= 2; + + // verify that the provided buffer is large enough + bytes = &data->asBytes; + if (numBytes > bytes->length) + return dpiError__set(error, "check number to text size", + DPI_ERR_BUFFER_SIZE_TOO_SMALL, bytes->length); + bytes->length = numBytes; + + // UTF-16 must be handled differently; the platform endianness is used in + // order to be compatible with OCI which has this restriction + if (env->charsetId == DPI_CHARSET_ID_UTF16) { + targetUtf16 = (uint16_t*) bytes->ptr; + + // if negative, include the sign + if (isNegative) + *targetUtf16++ = '-'; + + // if the decimal point index is 0 or less, add the decimal point and + // any leading zeroes that are needed + if (decimalPointIndex <= 0) { + *targetUtf16++ = '0'; + *targetUtf16++ = '.'; + for (; decimalPointIndex < 0; decimalPointIndex++) + *targetUtf16++ = '0'; + } + + // add each of the digits + for (i = 0; i < numDigits; i++) { + if (i > 0 && i == decimalPointIndex) + *targetUtf16++ = '.'; + *targetUtf16++ = '0' + digits[i]; + } + + // if the decimal point index exceeds the number of digits, add any + // trailing zeroes that are needed + if (decimalPointIndex > numDigits) { + for (i = numDigits; i < decimalPointIndex; i++) + *targetUtf16++ = '0'; + } + + // the following should be the same logic as the section above for UTF-16, + // simply with single byte encodings instead + } else { + target = (uint8_t*) bytes->ptr; + + // if negative, include the sign + if (isNegative) + *target++ = '-'; + + // if the decimal point index is 0 or less, add the decimal point and + // any leading zeroes that are needed + if (decimalPointIndex <= 0) { + *target++ = '0'; + *target++ = '.'; + for (; decimalPointIndex < 0; decimalPointIndex++) + *target++ = '0'; + } + + // add each of the digits + for (i = 0; i < numDigits; i++) { + if (i > 0 && i == decimalPointIndex) + *target++ = '.'; + *target++ = '0' + digits[i]; + } + + // if the decimal point index exceeds the number of digits, add any + // trailing zeroes that are needed + if (decimalPointIndex > numDigits) { + for (i = numDigits; i < decimalPointIndex; i++) + *target++ = '0'; + } + + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__fromOracleTimestamp() [INTERNAL] +// Populate the data from an OCIDateTime structure. +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue, int withTZ) +{ + dpiTimestamp *timestamp = &data->asTimestamp; + + if (dpiOci__dateTimeGetDate(env->handle, oracleValue, ×tamp->year, + ×tamp->month, ×tamp->day, error) < 0) + return DPI_FAILURE; + if (dpiOci__dateTimeGetTime(env->handle, oracleValue, ×tamp->hour, + ×tamp->minute, ×tamp->second, ×tamp->fsecond, + error) < 0) + return DPI_FAILURE; + if (withTZ) { + if (dpiOci__dateTimeGetTimeZoneOffset(env->handle, oracleValue, + ×tamp->tzHourOffset, ×tamp->tzMinuteOffset, + error) < 0) + return DPI_FAILURE; + } else { + timestamp->tzHourOffset = 0; + timestamp->tzMinuteOffset = 0; + } + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__fromOracleTimestampAsDouble() [INTERNAL] +// Populate the data from an OCIDateTime structure as a double value (number +// of milliseconds since January 1, 1970). +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleTimestampAsDouble(dpiDataBuffer *data, + dpiEnv *env, dpiError *error, void *oracleValue) +{ + int32_t day, hour, minute, second, fsecond; + void *interval; + int status; + + // allocate interval to use in calculation + if (dpiOci__descriptorAlloc(env->handle, &interval, + DPI_OCI_DTYPE_INTERVAL_DS, "alloc interval", error) < 0) + return DPI_FAILURE; + + // subtract dates to determine interval between date and base date + if (dpiOci__dateTimeSubtract(env->handle, oracleValue, env->baseDate, + interval, error) < 0) { + dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); + return DPI_FAILURE; + } + + // get the days, hours, minutes and seconds from the interval + status = dpiOci__intervalGetDaySecond(env->handle, &day, &hour, &minute, + &second, &fsecond, interval, error); + dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); + if (status < 0) + return DPI_FAILURE; + + // calculate milliseconds since January 1, 1970 + data->asDouble = ((double) day) * DPI_MS_DAY + hour * DPI_MS_HOUR + + minute * DPI_MS_MINUTE + second * DPI_MS_SECOND + + fsecond / DPI_MS_FSECOND; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__toOracleDate() [INTERNAL] +// Populate the data in an dpiOciDate structure. +//----------------------------------------------------------------------------- +int dpiDataBuffer__toOracleDate(dpiDataBuffer *data, dpiOciDate *oracleValue) +{ + dpiTimestamp *timestamp = &data->asTimestamp; + + oracleValue->year = timestamp->year; + oracleValue->month = timestamp->month; + oracleValue->day = timestamp->day; + oracleValue->hour = timestamp->hour; + oracleValue->minute = timestamp->minute; + oracleValue->second = timestamp->second; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__toOracleDateFromDouble() [INTERNAL] +// Populate the data in an dpiOciDate structure given a double (number of +// milliseconds since January 1, 1970). +//----------------------------------------------------------------------------- +int dpiDataBuffer__toOracleDateFromDouble(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, dpiOciDate *oracleValue) +{ + void *timestamp, *timestampLTZ; + uint32_t fsecond; + + // allocate a descriptor to acquire a timestamp + if (dpiOci__descriptorAlloc(env->handle, ×tampLTZ, + DPI_OCI_DTYPE_TIMESTAMP_LTZ, "alloc timestamp", error) < 0) + return DPI_FAILURE; + if (dpiDataBuffer__toOracleTimestampFromDouble(data, env, error, + timestampLTZ) < 0) { + dpiOci__descriptorFree(timestampLTZ, DPI_OCI_DTYPE_TIMESTAMP_LTZ); + return DPI_FAILURE; + } + + // allocate a plain timestamp and convert to it + if (dpiOci__descriptorAlloc(env->handle, ×tamp, + DPI_OCI_DTYPE_TIMESTAMP, "alloc plain timestamp", error) < 0) { + dpiOci__descriptorFree(timestampLTZ, DPI_OCI_DTYPE_TIMESTAMP_LTZ); + return DPI_FAILURE; + } + if (dpiOci__dateTimeConvert(env->handle, timestampLTZ, timestamp, + error) < 0) { + dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); + dpiOci__descriptorFree(timestampLTZ, DPI_OCI_DTYPE_TIMESTAMP_LTZ); + return DPI_FAILURE; + } + dpiOci__descriptorFree(timestampLTZ, DPI_OCI_DTYPE_TIMESTAMP_LTZ); + + // populate date structure + if (dpiOci__dateTimeGetDate(env->handle, timestamp, &oracleValue->year, + &oracleValue->month, &oracleValue->day, error) < 0) { + dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); + return DPI_FAILURE; + } + if (dpiOci__dateTimeGetTime(env->handle, timestamp, &oracleValue->hour, + &oracleValue->minute, &oracleValue->second, &fsecond, error) < 0) { + dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); + return DPI_FAILURE; + } + + dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__toOracleIntervalDS() [INTERNAL] +// Populate the data in an OCIInterval structure (days/seconds). +//----------------------------------------------------------------------------- +int dpiDataBuffer__toOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue) +{ + dpiIntervalDS *interval = &data->asIntervalDS; + + return dpiOci__intervalSetDaySecond(env->handle, interval->days, + interval->hours, interval->minutes, interval->seconds, + interval->fseconds, oracleValue, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__toOracleIntervalYM() [INTERNAL] +// Populate the data in an OCIInterval structure (years/months). +//----------------------------------------------------------------------------- +int dpiDataBuffer__toOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue) +{ + dpiIntervalYM *interval = &data->asIntervalYM; + + return dpiOci__intervalSetYearMonth(env->handle, interval->years, + interval->months, oracleValue, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__toOracleNumberFromDouble() [INTERNAL] +// Populate the data in an OCINumber structure from a double. +//----------------------------------------------------------------------------- +int dpiDataBuffer__toOracleNumberFromDouble(dpiDataBuffer *data, + dpiError *error, void *oracleValue) +{ + if (isnan(data->asDouble)) + return dpiError__set(error, "convert double to Oracle number", + DPI_ERR_NAN); + return dpiOci__numberFromReal(data->asDouble, oracleValue, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__toOracleNumberFromInteger() [INTERNAL] +// Populate the data in an OCINumber structure from an integer. +//----------------------------------------------------------------------------- +int dpiDataBuffer__toOracleNumberFromInteger(dpiDataBuffer *data, + dpiError *error, void *oracleValue) +{ + return dpiOci__numberFromInt(&data->asInt64, sizeof(int64_t), + DPI_OCI_NUMBER_SIGNED, oracleValue, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__toOracleNumberFromText() [INTERNAL] +// Populate the data in an OCINumber structure from text. +//----------------------------------------------------------------------------- +int dpiDataBuffer__toOracleNumberFromText(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue) +{ + uint8_t numDigits, digits[DPI_NUMBER_AS_TEXT_CHARS], *source, *target, i; + int isNegative, prependZero, appendSentinel; + dpiBytes *value = &data->asBytes; + int16_t decimalPointIndex; + uint8_t byte, numPairs; + int8_t ociExponent; + + // parse the string into its constituent components + if (dpiUtils__parseNumberString(value->ptr, value->length, env->charsetId, + &isNegative, &decimalPointIndex, &numDigits, digits, error) < 0) + return DPI_FAILURE; + + // if the exponent is odd, prepend a zero + prependZero = (decimalPointIndex > 0 && decimalPointIndex % 2 == 1) || + (decimalPointIndex < 0 && decimalPointIndex % 2 == -1); + if (prependZero && numDigits != 0) { + digits[numDigits++] = 0; + decimalPointIndex++; + } + + // determine the number of digit pairs; if the number of digits is odd, + // append a zero to make the number of digits even + if (numDigits % 2 == 1) + digits[numDigits++] = 0; + numPairs = numDigits / 2; + + // append a sentinel 102 byte for negative numbers if there is room + appendSentinel = (isNegative && numDigits > 0 && + numDigits < DPI_NUMBER_MAX_DIGITS); + + // initialize the OCINumber value + // the length is the number of pairs, plus one for the exponent + // include an extra byte for the sentinel if applicable + target = (uint8_t*) oracleValue; + *target++ = (uint8_t) (numPairs + 1 + appendSentinel); + + // if the number of digits is zero, the value is itself zero since all + // leading and trailing zeroes are removed from the digits string; the OCI + // value for zero is a special case + if (numDigits == 0) { + *target = 128; + return DPI_SUCCESS; + } + + // calculate the exponent + ociExponent = (int8_t) ((decimalPointIndex - 2) / 2 + 193); + if (isNegative) + ociExponent = ~ociExponent; + *target++ = (uint8_t) ociExponent; + + // calculate the mantissa bytes + source = digits; + for (i = 0; i < numPairs; i++) { + if (i == 0 && prependZero) + byte = *source++; + else { + byte = *source++ * 10; + byte += *source++; + } + if (isNegative) + byte = 101 - byte; + else byte++; + *target++ = byte; + } + + // append 102 byte for negative numbers if the number of digits is less + // than the maximum allowable + if (appendSentinel) + *target = 102; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__toOracleNumberFromUnsignedInteger() [INTERNAL] +// Populate the data in an OCINumber structure from an integer. +//----------------------------------------------------------------------------- +int dpiDataBuffer__toOracleNumberFromUnsignedInteger(dpiDataBuffer *data, + dpiError *error, void *oracleValue) +{ + return dpiOci__numberFromInt(&data->asUint64, sizeof(uint64_t), + DPI_OCI_NUMBER_UNSIGNED, oracleValue, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__toOracleTimestamp() [INTERNAL] +// Populate the data in an OCIDateTime structure. +//----------------------------------------------------------------------------- +int dpiDataBuffer__toOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue, int withTZ) +{ + dpiTimestamp *timestamp = &data->asTimestamp; + char tzOffsetBuffer[10], *tzOffset = NULL; + size_t tzOffsetLength = 0; + char sign; + + if (withTZ) { + sign = (timestamp->tzHourOffset < 0 || timestamp->tzMinuteOffset < 0) ? + '-' : '+'; + tzOffsetLength = (size_t) sprintf(tzOffsetBuffer, "%c%.2d:%.2d", sign, + abs(timestamp->tzHourOffset), abs(timestamp->tzMinuteOffset)); + tzOffset = tzOffsetBuffer; + } + return dpiOci__dateTimeConstruct(env->handle, oracleValue, timestamp->year, + timestamp->month, timestamp->day, timestamp->hour, + timestamp->minute, timestamp->second, timestamp->fsecond, tzOffset, + tzOffsetLength, error); +} + + +//----------------------------------------------------------------------------- +// dpiDataBuffer__toOracleTimestampFromDouble() [INTERNAL] +// Populate the data in an OCIDateTime structure, given the number of +// milliseconds since January 1, 1970. +//----------------------------------------------------------------------------- +int dpiDataBuffer__toOracleTimestampFromDouble(dpiDataBuffer *data, + dpiEnv *env, dpiError *error, void *oracleValue) +{ + int32_t day, hour, minute, second, fsecond; + void *interval; + int status; + double ms; + + // allocate interval to use in calculation + if (dpiOci__descriptorAlloc(env->handle, &interval, + DPI_OCI_DTYPE_INTERVAL_DS, "alloc interval", error) < 0) + return DPI_FAILURE; + + // determine the interval + ms = data->asDouble; + day = (int32_t) (ms / DPI_MS_DAY); + ms = ms - ((double) day) * DPI_MS_DAY; + hour = (int32_t) (ms / DPI_MS_HOUR); + ms = ms - (hour * DPI_MS_HOUR); + minute = (int32_t) (ms / DPI_MS_MINUTE); + ms = ms - (minute * DPI_MS_MINUTE); + second = (int32_t) (ms / DPI_MS_SECOND); + ms = ms - (second * DPI_MS_SECOND); + fsecond = (int32_t)(ms * DPI_MS_FSECOND); + if (dpiOci__intervalSetDaySecond(env->handle, day, hour, minute, second, + fsecond, interval, error) < 0) { + dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); + return DPI_FAILURE; + } + + // add the interval to the base date + status = dpiOci__dateTimeIntervalAdd(env->handle, env->baseDate, interval, + oracleValue, error); + dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); + return status; +} + + +//----------------------------------------------------------------------------- +// dpiData_getBool() [PUBLIC] +// Return the boolean portion of the data. +//----------------------------------------------------------------------------- +int dpiData_getBool(dpiData *data) +{ + return data->value.asBoolean; +} + + +//----------------------------------------------------------------------------- +// dpiData_getBytes() [PUBLIC] +// Return the bytes portion of the data. +//----------------------------------------------------------------------------- +dpiBytes *dpiData_getBytes(dpiData *data) +{ + return &data->value.asBytes; +} + + +//----------------------------------------------------------------------------- +// dpiData_getDouble() [PUBLIC] +// Return the double portion of the data. +//----------------------------------------------------------------------------- +double dpiData_getDouble(dpiData *data) +{ + return data->value.asDouble; +} + + +//----------------------------------------------------------------------------- +// dpiData_getFloat() [PUBLIC] +// Return the float portion of the data. +//----------------------------------------------------------------------------- +float dpiData_getFloat(dpiData *data) +{ + return data->value.asFloat; +} + + +//----------------------------------------------------------------------------- +// dpiData_getInt64() [PUBLIC] +// Return the integer portion of the data. +//----------------------------------------------------------------------------- +int64_t dpiData_getInt64(dpiData *data) +{ + return data->value.asInt64; +} + + +//----------------------------------------------------------------------------- +// dpiData_getIntervalDS() [PUBLIC] +// Return the interval (days/seconds) portion of the data. +//----------------------------------------------------------------------------- +dpiIntervalDS *dpiData_getIntervalDS(dpiData *data) +{ + return &data->value.asIntervalDS; +} + + +//----------------------------------------------------------------------------- +// dpiData_getIntervalYM() [PUBLIC] +// Return the interval (years/months) portion of the data. +//----------------------------------------------------------------------------- +dpiIntervalYM *dpiData_getIntervalYM(dpiData *data) +{ + return &data->value.asIntervalYM; +} + + +//----------------------------------------------------------------------------- +// dpiData_getIsNull() [PUBLIC] +// Return a boolean indicating if the value is null or not. +//----------------------------------------------------------------------------- +int dpiData_getIsNull(dpiData *data) +{ + return data->isNull; +} + + +//----------------------------------------------------------------------------- +// dpiData_getLOB() [PUBLIC] +// Return the LOB portion of the data. +//----------------------------------------------------------------------------- +dpiLob *dpiData_getLOB(dpiData *data) +{ + return data->value.asLOB; +} + + +//----------------------------------------------------------------------------- +// dpiData_getObject() [PUBLIC] +// Return the object portion of the data. +//----------------------------------------------------------------------------- +dpiObject *dpiData_getObject(dpiData *data) +{ + return data->value.asObject; +} + + +//----------------------------------------------------------------------------- +// dpiData_getStmt() [PUBLIC] +// Return the statement portion of the data. +//----------------------------------------------------------------------------- +dpiStmt *dpiData_getStmt(dpiData *data) +{ + return data->value.asStmt; +} + + +//----------------------------------------------------------------------------- +// dpiData_getTimestamp() [PUBLIC] +// Return the timestamp portion of the data. +//----------------------------------------------------------------------------- +dpiTimestamp *dpiData_getTimestamp(dpiData *data) +{ + return &data->value.asTimestamp; +} + + +//----------------------------------------------------------------------------- +// dpiData_getUint64() [PUBLIC] +// Return the unsigned integer portion of the data. +//----------------------------------------------------------------------------- +uint64_t dpiData_getUint64(dpiData *data) +{ + return data->value.asUint64; +} + + +//----------------------------------------------------------------------------- +// dpiData_setBool() [PUBLIC] +// Set the boolean portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setBool(dpiData *data, int value) +{ + data->isNull = 0; + data->value.asBoolean = value; +} + + +//----------------------------------------------------------------------------- +// dpiData_setBytes() [PUBLIC] +// Set the bytes portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setBytes(dpiData *data, char *ptr, uint32_t length) +{ + data->isNull = 0; + data->value.asBytes.ptr = ptr; + data->value.asBytes.length = length; +} + + +//----------------------------------------------------------------------------- +// dpiData_setDouble() [PUBLIC] +// Set the double portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setDouble(dpiData *data, double value) +{ + data->isNull = 0; + data->value.asDouble = value; +} + + +//----------------------------------------------------------------------------- +// dpiData_setFloat() [PUBLIC] +// Set the float portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setFloat(dpiData *data, float value) +{ + data->isNull = 0; + data->value.asFloat = value; +} + + +//----------------------------------------------------------------------------- +// dpiData_setInt64() [PUBLIC] +// Set the integer portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setInt64(dpiData *data, int64_t value) +{ + data->isNull = 0; + data->value.asInt64 = value; +} + + +//----------------------------------------------------------------------------- +// dpiData_setIntervalDS() [PUBLIC] +// Set the interval (days/seconds) portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setIntervalDS(dpiData *data, int32_t days, int32_t hours, + int32_t minutes, int32_t seconds, int32_t fseconds) +{ + dpiIntervalDS *interval = &data->value.asIntervalDS; + + data->isNull = 0; + interval->days = days; + interval->hours = hours; + interval->minutes = minutes; + interval->seconds = seconds; + interval->fseconds = fseconds; +} + + +//----------------------------------------------------------------------------- +// dpiData_setIntervalYM() [PUBLIC] +// Set the interval (years/months) portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setIntervalYM(dpiData *data, int32_t years, int32_t months) +{ + dpiIntervalYM *interval = &data->value.asIntervalYM; + + data->isNull = 0; + interval->years = years; + interval->months = months; +} + + +//----------------------------------------------------------------------------- +// dpiData_setLOB() [PUBLIC] +// Set the LOB portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setLOB(dpiData *data, dpiLob *lob) +{ + data->isNull = 0; + data->value.asLOB = lob; +} + + +//----------------------------------------------------------------------------- +// dpiData_setNull() [PUBLIC] +// Set the data to be treated as a null value. +//----------------------------------------------------------------------------- +void dpiData_setNull(dpiData *data) +{ + data->isNull = 1; +} + + +//----------------------------------------------------------------------------- +// dpiData_setObject() [PUBLIC] +// Set the object portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setObject(dpiData *data, dpiObject *obj) +{ + data->isNull = 0; + data->value.asObject = obj; +} + + +//----------------------------------------------------------------------------- +// dpiData_setStmt() [PUBLIC] +// Set the statement portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setStmt(dpiData *data, dpiStmt *obj) +{ + data->isNull = 0; + data->value.asStmt = obj; +} + + +//----------------------------------------------------------------------------- +// dpiData_setTimestamp() [PUBLIC] +// Set the timestamp portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setTimestamp(dpiData *data, int16_t year, uint8_t month, + uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, + uint32_t fsecond, int8_t tzHourOffset, int8_t tzMinuteOffset) +{ + dpiTimestamp *timestamp = &data->value.asTimestamp; + + data->isNull = 0; + timestamp->year = year; + timestamp->month = month; + timestamp->day = day; + timestamp->hour = hour; + timestamp->minute = minute; + timestamp->second = second; + timestamp->fsecond = fsecond; + timestamp->tzHourOffset = tzHourOffset; + timestamp->tzMinuteOffset = tzMinuteOffset; +} + + +//----------------------------------------------------------------------------- +// dpiData_setUint64() [PUBLIC] +// Set the unsigned integer portion of the data. +//----------------------------------------------------------------------------- +void dpiData_setUint64(dpiData *data, uint64_t value) +{ + data->isNull = 0; + data->value.asUint64 = value; +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiDebug.c b/vendor/github.com/godror/godror/odpi/src/dpiDebug.c new file mode 100644 index 00000000000..28b8776475f --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiDebug.c @@ -0,0 +1,183 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiDebug.c +// Methods used for debugging ODPI-C. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +#define DPI_DEBUG_THREAD_FORMAT "%.5" PRIu64 +#define DPI_DEBUG_DATE_FORMAT "%.4d-%.2d-%.2d" +#define DPI_DEBUG_TIME_FORMAT "%.2d:%.2d:%.2d.%.3d" + +// debug level (populated by environment variable DPI_DEBUG_LEVEL) +unsigned long dpiDebugLevel = 0; + +// debug prefix format (populated by environment variable DPI_DEBUG_PREFIX) +static char dpiDebugPrefixFormat[64] = "ODPI [%i] %d %t: "; + +// debug file for printing (currently unchangeable) +static FILE *dpiDebugStream = NULL; + + +//----------------------------------------------------------------------------- +// dpiDebug__getFormatWithPrefix() [INTERNAL] +// Adjust the provided format to include the prefix requested by the user. +// This method is not permitted to fail, so if there is not enough space, the +// prefix is truncated as needed -- although this is a very unlikely scenario. +//----------------------------------------------------------------------------- +static void dpiDebug__getFormatWithPrefix(const char *format, + char *formatWithPrefix, size_t maxFormatWithPrefixSize) +{ + char *sourcePtr, *targetPtr; + int gotTime, tempSize; + uint64_t threadId; + size_t size; +#ifdef _WIN32 + SYSTEMTIME time; +#else + struct timeval timeOfDay; + struct tm time; +#endif + + gotTime = 0; + sourcePtr = dpiDebugPrefixFormat; + targetPtr = formatWithPrefix; + size = maxFormatWithPrefixSize - strlen(format); + while (*sourcePtr && size > 20) { + + // all characters except '%' are copied verbatim to the target + if (*sourcePtr != '%') { + *targetPtr++ = *sourcePtr++; + maxFormatWithPrefixSize--; + continue; + } + + // handle the different directives + sourcePtr++; + switch (*sourcePtr) { + case 'i': +#ifdef _WIN32 + threadId = (uint64_t) GetCurrentThreadId(); +#elif defined __linux + threadId = (uint64_t) syscall(SYS_gettid); +#elif defined __APPLE__ + pthread_threadid_np(NULL, &threadId); +#else + threadId = (uint64_t) pthread_self(); +#endif + tempSize = sprintf(targetPtr, DPI_DEBUG_THREAD_FORMAT, + threadId); + size -= tempSize; + targetPtr += tempSize; + sourcePtr++; + break; + case 'd': + case 't': + if (!gotTime) { + gotTime = 1; +#ifdef _WIN32 + GetLocalTime(&time); +#else + gettimeofday(&timeOfDay, NULL); + localtime_r(&timeOfDay.tv_sec, &time); +#endif + } +#ifdef _WIN32 + if (*sourcePtr == 'd') + tempSize = sprintf(targetPtr, DPI_DEBUG_DATE_FORMAT, + time.wYear, time.wMonth, time.wDay); + else tempSize = sprintf(targetPtr, DPI_DEBUG_TIME_FORMAT, + time.wHour, time.wMinute, time.wSecond, + time.wMilliseconds); +#else + if (*sourcePtr == 'd') + tempSize = sprintf(targetPtr, DPI_DEBUG_DATE_FORMAT, + time.tm_year + 1900, time.tm_mon + 1, + time.tm_mday); + else tempSize = sprintf(targetPtr, DPI_DEBUG_TIME_FORMAT, + time.tm_hour, time.tm_min, time.tm_sec, + (int) (timeOfDay.tv_usec / 1000)); +#endif + size -= tempSize; + targetPtr += tempSize; + sourcePtr++; + break; + case '\0': + break; + default: + *targetPtr++ = '%'; + *targetPtr++ = *sourcePtr++; + break; + } + } + + // append original format + strcpy(targetPtr, format); +} + + +//----------------------------------------------------------------------------- +// dpiDebug__initialize() [INTERNAL] +// Initialize debugging infrastructure. This reads the environment variables +// and populates the global variables used for determining which messages to +// print and what prefix should be placed in front of each message. +//----------------------------------------------------------------------------- +void dpiDebug__initialize(void) +{ + char *envValue; + + // determine the value of the environment variable DPI_DEBUG_LEVEL and + // convert to an integer; if the value in the environment variable is not a + // valid integer, it is ignored + envValue = getenv("DPI_DEBUG_LEVEL"); + if (envValue) + dpiDebugLevel = (unsigned long) strtol(envValue, NULL, 10); + + // determine the value of the environment variable DPI_DEBUG_PREFIX and + // store it in the static buffer available for it; a static buffer is used + // since this runs during startup and may not fail; if the value of the + // environment variable is too large for the buffer, the value is ignored + // and the default value is used instead + envValue = getenv("DPI_DEBUG_PREFIX"); + if (envValue && strlen(envValue) < sizeof(dpiDebugPrefixFormat)) + strcpy(dpiDebugPrefixFormat, envValue); + + // messages are written to stderr + dpiDebugStream = stderr; + + // for any debugging level > 0 print a message indicating that tracing + // has started + if (dpiDebugLevel) { + dpiDebug__print("ODPI-C %s\n", DPI_VERSION_STRING); + dpiDebug__print("debugging messages initialized at level %lu\n", + dpiDebugLevel); + } +} + + +//----------------------------------------------------------------------------- +// dpiDebug__print() [INTERNAL] +// Print the specified debugging message with a newly calculated prefix. +//----------------------------------------------------------------------------- +void dpiDebug__print(const char *format, ...) +{ + char formatWithPrefix[512]; + va_list varArgs; + + dpiDebug__getFormatWithPrefix(format, formatWithPrefix, + sizeof(formatWithPrefix)); + va_start(varArgs, format); + (void) vfprintf(dpiDebugStream, formatWithPrefix, varArgs); + va_end(varArgs); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiDeqOptions.c b/vendor/github.com/godror/godror/odpi/src/dpiDeqOptions.c new file mode 100644 index 00000000000..35cb84727ae --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiDeqOptions.c @@ -0,0 +1,369 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiDeqOptions.c +// Implementation of AQ dequeue options. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiDeqOptions__create() [INTERNAL] +// Create a new subscription structure and return it. In case of error NULL +// is returned. +//----------------------------------------------------------------------------- +int dpiDeqOptions__create(dpiDeqOptions *options, dpiConn *conn, + dpiError *error) +{ + dpiGen__setRefCount(conn, error, 1); + options->conn = conn; + return dpiOci__descriptorAlloc(conn->env->handle, &options->handle, + DPI_OCI_DTYPE_AQDEQ_OPTIONS, "allocate descriptor", error); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions__free() [INTERNAL] +// Free the memory for a dequeue options structure. +//----------------------------------------------------------------------------- +void dpiDeqOptions__free(dpiDeqOptions *options, dpiError *error) +{ + if (options->handle) { + dpiOci__descriptorFree(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS); + options->handle = NULL; + } + if (options->conn) { + dpiGen__setRefCount(options->conn, error, -1); + options->conn = NULL; + } + dpiUtils__freeMemory(options); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions__getAttrValue() [INTERNAL] +// Get the attribute value in OCI. +//----------------------------------------------------------------------------- +static int dpiDeqOptions__getAttrValue(dpiDeqOptions *options, + uint32_t attribute, const char *fnName, void *value, + uint32_t *valueLength) +{ + dpiError error; + int status; + + if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, fnName, + &error) < 0) + return dpiGen__endPublicFn(options, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(options, value) + DPI_CHECK_PTR_NOT_NULL(options, valueLength) + status = dpiOci__attrGet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, + value, valueLength, attribute, "get attribute value", &error); + return dpiGen__endPublicFn(options, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions__setAttrValue() [INTERNAL] +// Set the attribute value in OCI. +//----------------------------------------------------------------------------- +static int dpiDeqOptions__setAttrValue(dpiDeqOptions *options, + uint32_t attribute, const char *fnName, const void *value, + uint32_t valueLength) +{ + dpiError error; + int status; + + if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, fnName, + &error) < 0) + return dpiGen__endPublicFn(options, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(options, value) + status = dpiOci__attrSet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, + (void*) value, valueLength, attribute, "set attribute value", + &error); + return dpiGen__endPublicFn(options, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_addRef() [PUBLIC] +// Add a reference to the dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_addRef(dpiDeqOptions *options) +{ + return dpiGen__addRef(options, DPI_HTYPE_DEQ_OPTIONS, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_getCondition() [PUBLIC] +// Return condition associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_getCondition(dpiDeqOptions *options, const char **value, + uint32_t *valueLength) +{ + return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_DEQCOND, __func__, + (void*) value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_getConsumerName() [PUBLIC] +// Return consumer name associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_getConsumerName(dpiDeqOptions *options, const char **value, + uint32_t *valueLength) +{ + return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_CONSUMER_NAME, + __func__, (void*) value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_getCorrelation() [PUBLIC] +// Return correlation associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_getCorrelation(dpiDeqOptions *options, const char **value, + uint32_t *valueLength) +{ + return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_CORRELATION, + __func__, (void*) value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_getMode() [PUBLIC] +// Return mode associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_getMode(dpiDeqOptions *options, dpiDeqMode *value) +{ + uint32_t valueLength = sizeof(uint32_t); + + return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_DEQ_MODE, + __func__, value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_getMsgId() [PUBLIC] +// Return message id associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_getMsgId(dpiDeqOptions *options, const char **value, + uint32_t *valueLength) +{ + dpiError error; + void *rawValue; + + if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, __func__, + &error) < 0) + return dpiGen__endPublicFn(options, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(options, value) + DPI_CHECK_PTR_NOT_NULL(options, valueLength) + if (dpiOci__attrGet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, + &rawValue, NULL, DPI_OCI_ATTR_DEQ_MSGID, "get attribute value", + &error) < 0) + return dpiGen__endPublicFn(options, DPI_FAILURE, &error); + dpiOci__rawPtr(options->env->handle, rawValue, (void**) value); + dpiOci__rawSize(options->env->handle, rawValue, valueLength); + return dpiGen__endPublicFn(options, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_getNavigation() [PUBLIC] +// Return navigation associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_getNavigation(dpiDeqOptions *options, + dpiDeqNavigation *value) +{ + uint32_t valueLength = sizeof(uint32_t); + + return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_NAVIGATION, + __func__, value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_getTransformation() [PUBLIC] +// Return transformation associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_getTransformation(dpiDeqOptions *options, const char **value, + uint32_t *valueLength) +{ + return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, + __func__, (void*) value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_getVisibility() [PUBLIC] +// Return visibility associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_getVisibility(dpiDeqOptions *options, dpiVisibility *value) +{ + uint32_t valueLength = sizeof(uint32_t); + + return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_VISIBILITY, + __func__, value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_getWait() [PUBLIC] +// Return the number of seconds to wait for a message when dequeuing. +//----------------------------------------------------------------------------- +int dpiDeqOptions_getWait(dpiDeqOptions *options, uint32_t *value) +{ + uint32_t valueLength = sizeof(uint32_t); + + return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_WAIT, __func__, + value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_release() [PUBLIC] +// Release a reference to the dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_release(dpiDeqOptions *options) +{ + return dpiGen__release(options, DPI_HTYPE_DEQ_OPTIONS, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_setCondition() [PUBLIC] +// Set condition associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_setCondition(dpiDeqOptions *options, const char *value, + uint32_t valueLength) +{ + return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_DEQCOND, __func__, + value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_setConsumerName() [PUBLIC] +// Set consumer name associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_setConsumerName(dpiDeqOptions *options, const char *value, + uint32_t valueLength) +{ + return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_CONSUMER_NAME, + __func__, value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_setCorrelation() [PUBLIC] +// Set correlation associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_setCorrelation(dpiDeqOptions *options, const char *value, + uint32_t valueLength) +{ + return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_CORRELATION, + __func__, value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_setDeliveryMode() [PUBLIC] +// Set the delivery mode associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_setDeliveryMode(dpiDeqOptions *options, + dpiMessageDeliveryMode value) +{ + return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_MSG_DELIVERY_MODE, + __func__, &value, 0); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_setMode() [PUBLIC] +// Set the mode associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_setMode(dpiDeqOptions *options, dpiDeqMode value) +{ + return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_DEQ_MODE, + __func__, &value, 0); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_setMsgId() [PUBLIC] +// Set the message id associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_setMsgId(dpiDeqOptions *options, const char *value, + uint32_t valueLength) +{ + void *rawValue = NULL; + dpiError error; + int status; + + if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, __func__, + &error) < 0) + return dpiGen__endPublicFn(options, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(options, value) + if (dpiOci__rawAssignBytes(options->env->handle, value, valueLength, + &rawValue, &error) < 0) + return dpiGen__endPublicFn(options, DPI_FAILURE, &error); + status = dpiOci__attrSet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, + (void*) &rawValue, valueLength, DPI_OCI_ATTR_DEQ_MSGID, + "set value", &error); + dpiOci__rawResize(options->env->handle, &rawValue, 0, &error); + return dpiGen__endPublicFn(options, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_setNavigation() [PUBLIC] +// Set navigation associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_setNavigation(dpiDeqOptions *options, dpiDeqNavigation value) +{ + return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_NAVIGATION, + __func__, &value, 0); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_setTransformation() [PUBLIC] +// Set transformation associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_setTransformation(dpiDeqOptions *options, const char *value, + uint32_t valueLength) +{ + return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, + __func__, value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_setVisibility() [PUBLIC] +// Set visibility associated with dequeue options. +//----------------------------------------------------------------------------- +int dpiDeqOptions_setVisibility(dpiDeqOptions *options, dpiVisibility value) +{ + return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_VISIBILITY, + __func__, &value, 0); +} + + +//----------------------------------------------------------------------------- +// dpiDeqOptions_setWait() [PUBLIC] +// Set the number of seconds to wait for a message when dequeuing. +//----------------------------------------------------------------------------- +int dpiDeqOptions_setWait(dpiDeqOptions *options, uint32_t value) +{ + return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_WAIT, __func__, + &value, 0); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiEnqOptions.c b/vendor/github.com/godror/godror/odpi/src/dpiEnqOptions.c new file mode 100644 index 00000000000..24bf60a3229 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiEnqOptions.c @@ -0,0 +1,173 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiEnqOptions.c +// Implementation of AQ enqueue options. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiEnqOptions__create() [INTERNAL] +// Create a new subscription structure and return it. In case of error NULL +// is returned. +//----------------------------------------------------------------------------- +int dpiEnqOptions__create(dpiEnqOptions *options, dpiConn *conn, + dpiError *error) +{ + dpiGen__setRefCount(conn, error, 1); + options->conn = conn; + return dpiOci__descriptorAlloc(conn->env->handle, &options->handle, + DPI_OCI_DTYPE_AQENQ_OPTIONS, "allocate descriptor", error); +} + + +//----------------------------------------------------------------------------- +// dpiEnqOptions__free() [INTERNAL] +// Free the memory for a enqueue options structure. +//----------------------------------------------------------------------------- +void dpiEnqOptions__free(dpiEnqOptions *options, dpiError *error) +{ + if (options->handle) { + dpiOci__descriptorFree(options->handle, DPI_OCI_DTYPE_AQENQ_OPTIONS); + options->handle = NULL; + } + if (options->conn) { + dpiGen__setRefCount(options->conn, error, -1); + options->conn = NULL; + } + dpiUtils__freeMemory(options); +} + + +//----------------------------------------------------------------------------- +// dpiEnqOptions__getAttrValue() [INTERNAL] +// Get the attribute value in OCI. +//----------------------------------------------------------------------------- +static int dpiEnqOptions__getAttrValue(dpiEnqOptions *options, + uint32_t attribute, const char *fnName, void *value, + uint32_t *valueLength) +{ + dpiError error; + int status; + + if (dpiGen__startPublicFn(options, DPI_HTYPE_ENQ_OPTIONS, fnName, + &error) < 0) + return dpiGen__endPublicFn(options, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(options, value) + DPI_CHECK_PTR_NOT_NULL(options, valueLength) + status = dpiOci__attrGet(options->handle, DPI_OCI_DTYPE_AQENQ_OPTIONS, + value, valueLength, attribute, "get attribute value", &error); + return dpiGen__endPublicFn(options, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiEnqOptions__setAttrValue() [INTERNAL] +// Set the attribute value in OCI. +//----------------------------------------------------------------------------- +static int dpiEnqOptions__setAttrValue(dpiEnqOptions *options, + uint32_t attribute, const char *fnName, const void *value, + uint32_t valueLength) +{ + dpiError error; + int status; + + if (dpiGen__startPublicFn(options, DPI_HTYPE_ENQ_OPTIONS, fnName, + &error) < 0) + return dpiGen__endPublicFn(options, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(options, value) + status = dpiOci__attrSet(options->handle, DPI_OCI_DTYPE_AQENQ_OPTIONS, + (void*) value, valueLength, attribute, "set attribute value", + &error); + return dpiGen__endPublicFn(options, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiEnqOptions_addRef() [PUBLIC] +// Add a reference to the enqueue options. +//----------------------------------------------------------------------------- +int dpiEnqOptions_addRef(dpiEnqOptions *options) +{ + return dpiGen__addRef(options, DPI_HTYPE_ENQ_OPTIONS, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiEnqOptions_getTransformation() [PUBLIC] +// Return transformation associated with enqueue options. +//----------------------------------------------------------------------------- +int dpiEnqOptions_getTransformation(dpiEnqOptions *options, const char **value, + uint32_t *valueLength) +{ + return dpiEnqOptions__getAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, + __func__, (void*) value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiEnqOptions_getVisibility() [PUBLIC] +// Return visibility associated with enqueue options. +//----------------------------------------------------------------------------- +int dpiEnqOptions_getVisibility(dpiEnqOptions *options, dpiVisibility *value) +{ + uint32_t valueLength = sizeof(uint32_t); + + return dpiEnqOptions__getAttrValue(options, DPI_OCI_ATTR_VISIBILITY, + __func__, value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiEnqOptions_release() [PUBLIC] +// Release a reference to the enqueue options. +//----------------------------------------------------------------------------- +int dpiEnqOptions_release(dpiEnqOptions *options) +{ + return dpiGen__release(options, DPI_HTYPE_ENQ_OPTIONS, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiEnqOptions_setDeliveryMode() [PUBLIC] +// Set the delivery mode associated with enqueue options. +//----------------------------------------------------------------------------- +int dpiEnqOptions_setDeliveryMode(dpiEnqOptions *options, + dpiMessageDeliveryMode value) +{ + return dpiEnqOptions__setAttrValue(options, DPI_OCI_ATTR_MSG_DELIVERY_MODE, + __func__, &value, 0); +} + + +//----------------------------------------------------------------------------- +// dpiEnqOptions_setTransformation() [PUBLIC] +// Set transformation associated with enqueue options. +//----------------------------------------------------------------------------- +int dpiEnqOptions_setTransformation(dpiEnqOptions *options, const char *value, + uint32_t valueLength) +{ + return dpiEnqOptions__setAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, + __func__, value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiEnqOptions_setVisibility() [PUBLIC] +// Set visibility associated with enqueue options. +//----------------------------------------------------------------------------- +int dpiEnqOptions_setVisibility(dpiEnqOptions *options, dpiVisibility value) +{ + return dpiEnqOptions__setAttrValue(options, DPI_OCI_ATTR_VISIBILITY, + __func__, &value, 0); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiEnv.c b/vendor/github.com/godror/godror/odpi/src/dpiEnv.c new file mode 100644 index 00000000000..c1a2c3f7d61 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiEnv.c @@ -0,0 +1,180 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiEnv.c +// Implementation of environment. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiEnv__free() [INTERNAL] +// Free the memory associated with the environment. +//----------------------------------------------------------------------------- +void dpiEnv__free(dpiEnv *env, dpiError *error) +{ + if (env->threaded) + dpiMutex__destroy(env->mutex); + if (env->handle && !env->externalHandle) { + dpiOci__handleFree(env->handle, DPI_OCI_HTYPE_ENV); + env->handle = NULL; + } + if (env->errorHandles) { + dpiHandlePool__free(env->errorHandles); + env->errorHandles = NULL; + error->handle = NULL; + } + dpiUtils__freeMemory(env); +} + + +//----------------------------------------------------------------------------- +// dpiEnv__getCharacterSetIdAndName() [INTERNAL] +// Retrieve and store the IANA character set name for the attribute. +//----------------------------------------------------------------------------- +static int dpiEnv__getCharacterSetIdAndName(dpiEnv *env, uint16_t attribute, + uint16_t *charsetId, char *encoding, dpiError *error) +{ + *charsetId = 0; + dpiOci__attrGet(env->handle, DPI_OCI_HTYPE_ENV, charsetId, NULL, attribute, + "get environment", error); + return dpiGlobal__lookupEncoding(*charsetId, encoding, error); +} + + +//----------------------------------------------------------------------------- +// dpiEnv__getEncodingInfo() [INTERNAL] +// Populate the structure with the encoding info. +//----------------------------------------------------------------------------- +int dpiEnv__getEncodingInfo(dpiEnv *env, dpiEncodingInfo *info) +{ + info->encoding = env->encoding; + info->maxBytesPerCharacter = env->maxBytesPerCharacter; + info->nencoding = env->nencoding; + info->nmaxBytesPerCharacter = env->nmaxBytesPerCharacter; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiEnv__init() [INTERNAL] +// Initialize the environment structure. If an external handle is provided it +// is used directly; otherwise, a new OCI environment handle is created. In +// either case, information about the environment is stored for later use. +//----------------------------------------------------------------------------- +int dpiEnv__init(dpiEnv *env, const dpiContext *context, + const dpiCommonCreateParams *params, void *externalHandle, + dpiError *error) +{ + char timezoneBuffer[20]; + size_t timezoneLength; + + // store context and version information + env->context = context; + env->versionInfo = context->versionInfo; + + // an external handle is available, use it directly + if (externalHandle) { + env->handle = externalHandle; + env->externalHandle = 1; + + // otherwise, lookup encodings + } else { + + // lookup encoding + if (params->encoding && dpiGlobal__lookupCharSet(params->encoding, + &env->charsetId, error) < 0) + return DPI_FAILURE; + + // check for identical encoding before performing lookup of national + // character set encoding + if (params->nencoding && params->encoding && + strcmp(params->nencoding, params->encoding) == 0) + env->ncharsetId = env->charsetId; + else if (params->nencoding && + dpiGlobal__lookupCharSet(params->nencoding, + &env->ncharsetId, error) < 0) + return DPI_FAILURE; + + // both charsetId and ncharsetId must be zero or both must be non-zero + // use NLS routine to look up missing value, if needed + if (env->charsetId && !env->ncharsetId) { + if (dpiOci__nlsEnvironmentVariableGet(DPI_OCI_NLS_NCHARSET_ID, + &env->ncharsetId, error) < 0) + return DPI_FAILURE; + } else if (!env->charsetId && env->ncharsetId) { + if (dpiOci__nlsEnvironmentVariableGet(DPI_OCI_NLS_CHARSET_ID, + &env->charsetId, error) < 0) + return DPI_FAILURE; + } + + // create new environment handle + if (dpiOci__envNlsCreate(&env->handle, + params->createMode | DPI_OCI_OBJECT, + env->charsetId, env->ncharsetId, error) < 0) + return DPI_FAILURE; + + } + + // create the error handle pool + if (dpiHandlePool__create(&env->errorHandles, error) < 0) + return DPI_FAILURE; + error->env = env; + + // if threaded, create mutex for reference counts + if (params->createMode & DPI_OCI_THREADED) + dpiMutex__initialize(env->mutex); + + // determine encodings in use + if (dpiEnv__getCharacterSetIdAndName(env, DPI_OCI_ATTR_CHARSET_ID, + &env->charsetId, env->encoding, error) < 0) + return DPI_FAILURE; + if (dpiEnv__getCharacterSetIdAndName(env, DPI_OCI_ATTR_NCHARSET_ID, + &env->ncharsetId, env->nencoding, error) < 0) + return DPI_FAILURE; + + // acquire max bytes per character + if (dpiOci__nlsNumericInfoGet(env->handle, &env->maxBytesPerCharacter, + DPI_OCI_NLS_CHARSET_MAXBYTESZ, error) < 0) + return DPI_FAILURE; + + // for NCHAR we have no idea of how many so we simply take the worst case + // unless the charsets are identical + if (env->ncharsetId == env->charsetId) + env->nmaxBytesPerCharacter = env->maxBytesPerCharacter; + else env->nmaxBytesPerCharacter = 4; + + // allocate base date descriptor (for converting to/from time_t) + if (dpiOci__descriptorAlloc(env->handle, &env->baseDate, + DPI_OCI_DTYPE_TIMESTAMP_LTZ, "alloc base date descriptor", + error) < 0) + return DPI_FAILURE; + + // populate base date with January 1, 1970 + if (dpiOci__nlsCharSetConvert(env->handle, env->charsetId, timezoneBuffer, + sizeof(timezoneBuffer), DPI_CHARSET_ID_ASCII, "+00:00", 6, + &timezoneLength, error) < 0) + return DPI_FAILURE; + if (dpiOci__dateTimeConstruct(env->handle, env->baseDate, 1970, 1, 1, 0, 0, + 0, 0, timezoneBuffer, timezoneLength, error) < 0) + return DPI_FAILURE; + + // set whether or not we are threaded + if (params->createMode & DPI_MODE_CREATE_THREADED) + env->threaded = 1; + + // set whether or not events mode has been set + if (params->createMode & DPI_MODE_CREATE_EVENTS) + env->events = 1; + + return DPI_SUCCESS; +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiError.c b/vendor/github.com/godror/godror/odpi/src/dpiError.c new file mode 100644 index 00000000000..aac57b92f18 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiError.c @@ -0,0 +1,222 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiError.c +// Implementation of error. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" +#include "dpiErrorMessages.h" + +//----------------------------------------------------------------------------- +// dpiError__getInfo() [INTERNAL] +// Get the error state from the error structure. Returns DPI_FAILURE as a +// convenience to the caller. +//----------------------------------------------------------------------------- +int dpiError__getInfo(dpiError *error, dpiErrorInfo *info) +{ + if (!info) + return DPI_FAILURE; + info->code = error->buffer->code; + info->offset = error->buffer->offset; + info->message = error->buffer->message; + info->messageLength = error->buffer->messageLength; + info->fnName = error->buffer->fnName; + info->action = error->buffer->action; + info->isRecoverable = error->buffer->isRecoverable; + info->encoding = error->buffer->encoding; + switch(info->code) { + case 12154: // TNS:could not resolve the connect identifier specified + info->sqlState = "42S02"; + break; + case 22: // invalid session ID; access denied + case 378: // buffer pools cannot be created as specified + case 602: // Internal programming exception + case 603: // ORACLE server session terminated by fatal error + case 604: // error occurred at recursive SQL level + case 609: // could not attach to incoming connection + case 1012: // not logged on + case 1033: // ORACLE initialization or shutdown in progress + case 1041: // internal error. hostdef extension doesn't exist + case 1043: // user side memory corruption + case 1089: // immediate shutdown or close in progress + case 1090: // shutdown in progress + case 1092: // ORACLE instance terminated. Disconnection forced + case 3113: // end-of-file on communication channel + case 3114: // not connected to ORACLE + case 3122: // attempt to close ORACLE-side window on user side + case 3135: // connection lost contact + case 12153: // TNS:not connected + case 27146: // post/wait initialization failed + case 28511: // lost RPC connection to heterogeneous remote agent + info->sqlState = "01002"; + break; + default: + if (error->buffer->code == 0 && + error->buffer->errorNum == (dpiErrorNum) 0) + info->sqlState = "00000"; + else info->sqlState = "HY000"; + break; + } + return DPI_FAILURE; +} + + +//----------------------------------------------------------------------------- +// dpiError__initHandle() [INTERNAL] +// Retrieve the OCI error handle to use for error handling, from a pool of +// error handles common to the environment handle stored on the error. This +// environment also controls the encoding of OCI errors (which uses the CHAR +// encoding of the environment). +//----------------------------------------------------------------------------- +int dpiError__initHandle(dpiError *error) +{ + if (dpiHandlePool__acquire(error->env->errorHandles, &error->handle, + error) < 0) + return DPI_FAILURE; + if (!error->handle) { + if (dpiOci__handleAlloc(error->env->handle, &error->handle, + DPI_OCI_HTYPE_ERROR, "allocate OCI error", error) < 0) + return DPI_FAILURE; + } + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiError__set() [INTERNAL] +// Set the error buffer to the specified DPI error. Returns DPI_FAILURE as a +// convenience to the caller. +//----------------------------------------------------------------------------- +int dpiError__set(dpiError *error, const char *action, dpiErrorNum errorNum, + ...) +{ + va_list varArgs; + + if (error) { + error->buffer->code = 0; + error->buffer->isRecoverable = 0; + error->buffer->offset = 0; + strcpy(error->buffer->encoding, DPI_CHARSET_NAME_UTF8); + error->buffer->action = action; + error->buffer->errorNum = errorNum; + va_start(varArgs, errorNum); + error->buffer->messageLength = + (uint32_t) vsnprintf(error->buffer->message, + sizeof(error->buffer->message), + dpiErrorMessages[errorNum - DPI_ERR_NO_ERR], varArgs); + va_end(varArgs); + if (dpiDebugLevel & DPI_DEBUG_LEVEL_ERRORS) + dpiDebug__print("internal error %.*s (%s / %s)\n", + error->buffer->messageLength, error->buffer->message, + error->buffer->fnName, action); + } + return DPI_FAILURE; +} + + +//----------------------------------------------------------------------------- +// dpiError__setFromOCI() [INTERNAL] +// Called when an OCI error has occurred and sets the error structure with +// the contents of that error. Note that trailing newlines and spaces are +// truncated from the message if they exist. If the connection is not NULL a +// check is made to see if the connection is no longer viable. The value +// DPI_FAILURE is returned as a convenience to the caller. +//----------------------------------------------------------------------------- +int dpiError__setFromOCI(dpiError *error, int status, dpiConn *conn, + const char *action) +{ + uint32_t callTimeout; + + // special error cases + if (status == DPI_OCI_INVALID_HANDLE) + return dpiError__set(error, action, DPI_ERR_INVALID_HANDLE, "OCI"); + else if (!error) + return DPI_FAILURE; + else if (!error->handle) + return dpiError__set(error, action, DPI_ERR_ERR_NOT_INITIALIZED); + else if (status != DPI_OCI_ERROR && status != DPI_OCI_NO_DATA) + return dpiError__set(error, action, + DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE, status, + error->buffer->fnName); + + // fetch OCI error + error->buffer->action = action; + strcpy(error->buffer->encoding, error->env->encoding); + if (dpiOci__errorGet(error->handle, DPI_OCI_HTYPE_ERROR, + error->env->charsetId, action, error) < 0) + return DPI_FAILURE; + if (dpiDebugLevel & DPI_DEBUG_LEVEL_ERRORS) + dpiDebug__print("OCI error %.*s (%s / %s)\n", + error->buffer->messageLength, error->buffer->message, + error->buffer->fnName, action); + + // determine if error is recoverable (Transaction Guard) + // if the attribute cannot be read properly, simply leave it as false; + // otherwise, that error will mask the one that we really want to see + error->buffer->isRecoverable = 0; + dpiOci__attrGet(error->handle, DPI_OCI_HTYPE_ERROR, + (void*) &error->buffer->isRecoverable, 0, + DPI_OCI_ATTR_ERROR_IS_RECOVERABLE, NULL, error); + + // check for certain errors which indicate that the session is dead and + // should be dropped from the session pool (if a session pool was used) + // also check for call timeout and raise unified message instead + if (conn && !conn->deadSession) { + switch (error->buffer->code) { + case 22: // invalid session ID; access denied + case 28: // your session has been killed + case 31: // your session has been marked for kill + case 45: // your session has been terminated with no replay + case 378: // buffer pools cannot be created as specified + case 602: // internal programming exception + case 603: // ORACLE server session terminated by fatal error + case 609: // could not attach to incoming connection + case 1012: // not logged on + case 1041: // internal error. hostdef extension doesn't exist + case 1043: // user side memory corruption + case 1089: // immediate shutdown or close in progress + case 1092: // ORACLE instance terminated. Disconnection forced + case 2396: // exceeded maximum idle time, please connect again + case 3113: // end-of-file on communication channel + case 3114: // not connected to ORACLE + case 3122: // attempt to close ORACLE-side window on user side + case 3135: // connection lost contact + case 12153: // TNS:not connected + case 12537: // TNS:connection closed + case 12547: // TNS:lost contact + case 12570: // TNS:packet reader failure + case 12583: // TNS:no reader + case 27146: // post/wait initialization failed + case 28511: // lost RPC connection + case 56600: // an illegal OCI function call was issued + conn->deadSession = 1; + break; + case 3136: // inbound connection timed out + case 3156: // OCI call timed out + case 12161: // TNS:internal error: partial data received + callTimeout = 0; + if (conn->env->versionInfo->versionNum >= 18) + dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, + (void*) &callTimeout, 0, DPI_OCI_ATTR_CALL_TIMEOUT, + NULL, error); + if (callTimeout > 0) { + dpiError__set(error, action, DPI_ERR_CALL_TIMEOUT, + callTimeout, error->buffer->code); + error->buffer->code = 0; + } + break; + } + } + + return DPI_FAILURE; +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiErrorMessages.h b/vendor/github.com/godror/godror/odpi/src/dpiErrorMessages.h new file mode 100644 index 00000000000..1de52a2b17b --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiErrorMessages.h @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiErrorMessages.h +// Definition of error messages used in ODPI-C. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +static const char* const dpiErrorMessages[DPI_ERR_MAX - DPI_ERR_NO_ERR] = { + "DPI-1000: no error", // DPI_ERR_NO_ERR + "DPI-1001: out of memory", // DPI_ERR_NO_MEMORY + "DPI-1002: invalid %s handle", // DPI_ERR_INVALID_HANDLE + "DPI-1003: OCI error handle is not initialized", // DPI_ERR_ERR_NOT_INITIALIZED + "DPI-1004: unable to get error message", // DPI_ERR_GET_FAILED + "DPI-1005: unable to acquire Oracle environment handle", // DPI_ERR_CREATE_ENV + "DPI-1006: unable to convert text to session character set", // DPI_ERR_CONVERT_TEXT + "DPI-1007: no query has been executed", // DPI_ERR_QUERY_NOT_EXECUTED + "DPI-1008: data type %d is not supported", // DPI_ERR_UNHANDLED_DATA_TYPE + "DPI-1009: zero-based position %u is not valid with max array size of %u", // DPI_ERR_INVALID_ARRAY_POSITION + "DPI-1010: not connected", // DPI_ERR_NOT_CONNECTED + "DPI-1011: connection was not acquired from a session pool", // DPI_ERR_CONN_NOT_IN_POOL + "DPI-1012: proxy authentication is not possible with homogeneous pools", // DPI_ERR_INVALID_PROXY + "DPI-1013: not supported", // DPI_ERR_NOT_SUPPORTED + "DPI-1014: conversion between Oracle type %d and native type %d is not implemented", // DPI_ERR_UNHANDLED_CONVERSION + "DPI-1015: array size of %u is too large", // DPI_ERR_ARRAY_SIZE_TOO_BIG + "DPI-1016: invalid date", // DPI_ERR_INVALID_DATE + "DPI-1017: value is null", // DPI_ERR_VALUE_IS_NULL + "DPI-1018: array size of %u is too small", // DPI_ERR_ARRAY_SIZE_TOO_SMALL + "DPI-1019: buffer size of %u is too small", // DPI_ERR_BUFFER_SIZE_TOO_SMALL + "DPI-1020: application requires ODPI-C %d (min %d.%d) but is using a shared library at version %d.%d", // DPI_ERR_VERSION_NOT_SUPPORTED + "DPI-1021: Oracle type %u is invalid", // DPI_ERR_INVALID_ORACLE_TYPE + "DPI-1022: attribute %.*s is not part of object type %.*s.%.*s", // DPI_ERR_WRONG_ATTR + "DPI-1023: object %.*s.%.*s is not a collection", // DPI_ERR_NOT_COLLECTION + "DPI-1024: element at index %d does not exist", // DPI_ERR_INVALID_INDEX + "DPI-1025: no object type specified for object variable", // DPI_ERR_NO_OBJECT_TYPE + "DPI-1026: invalid character set %s", // DPI_ERR_INVALID_CHARSET + "DPI-1027: scroll operation would go out of the result set", // DPI_ERR_SCROLL_OUT_OF_RS + "DPI-1028: query position %u is invalid", // DPI_ERR_QUERY_POSITION_INVALID + "DPI-1029: no row currently fetched", // DPI_ERR_NO_ROW_FETCHED + "DPI-1030: unable to get or set error structure for thread local storage", // DPI_ERR_TLS_ERROR + "DPI-1031: array size cannot be zero", // DPI_ERR_ARRAY_SIZE_ZERO + "DPI-1032: user name and password cannot be set when using external authentication", // DPI_ERR_EXT_AUTH_WITH_CREDENTIALS + "DPI-1033: unable to get row offset", // DPI_ERR_CANNOT_GET_ROW_OFFSET + "DPI-1034: connection created from external handle cannot be closed", // DPI_ERR_CONN_IS_EXTERNAL + "DPI-1035: size of the transaction ID is %u and cannot exceed %u", // DPI_ERR_TRANS_ID_TOO_LARGE + "DPI-1036: size of the branch ID is %u and cannot exceed %u", // DPI_ERR_BRANCH_ID_TOO_LARGE + "DPI-1037: column at array position %u fetched with error %u", // DPI_ERR_COLUMN_FETCH + "DPI-1039: statement was already closed", // DPI_ERR_STMT_CLOSED + "DPI-1040: LOB was already closed", // DPI_ERR_LOB_CLOSED + "DPI-1041: invalid character set id %d", // DPI_ERR_INVALID_CHARSET_ID + "DPI-1042: invalid OCI number", // DPI_ERR_INVALID_OCI_NUMBER + "DPI-1043: invalid number", // DPI_ERR_INVALID_NUMBER + "DPI-1044: value cannot be represented as an Oracle number", // DPI_ERR_NUMBER_NO_REPR + "DPI-1045: strings converted to numbers can only be up to 172 characters long", // DPI_ERR_NUMBER_STRING_TOO_LONG + "DPI-1046: parameter %s cannot be a NULL pointer", // DPI_ERR_NULL_POINTER_PARAMETER + "DPI-1047: Cannot locate a %s-bit Oracle Client library: \"%s\". See https://oracle.github.io/odpi/doc/installation.html#%s for help", // DPI_ERR_LOAD_LIBRARY + "DPI-1049: symbol %s not found in OCI library", // DPI_ERR_LOAD_SYMBOL + "DPI-1050: Oracle Client library is at version %d.%d but version %d.%d or higher is needed", // DPI_ERR_ORACLE_CLIENT_TOO_OLD + "DPI-1052: unable to get NLS environment variable", // DPI_ERR_NLS_ENV_VAR_GET, + "DPI-1053: parameter %s cannot be a NULL pointer while corresponding length parameter is non-zero", // DPI_ERR_PTR_LENGTH_MISMATCH + "DPI-1055: value is not a number (NaN) and cannot be used in Oracle numbers", // DPI_ERR_NAN + "DPI-1056: found object of type %.*s.%.*s when expecting object of type %.*s.%.*s", // DPI_ERR_WRONG_TYPE + "DPI-1057: buffer size of %u is too large (max %u)", // DPI_ERR_BUFFER_SIZE_TOO_LARGE + "DPI-1058: edition not supported with connection class", // DPI_ERR_NO_EDITION_WITH_CONN_CLASS + "DPI-1059: bind variables are not supported in DDL statements", // DPI_ERR_NO_BIND_VARS_IN_DDL + "DPI-1060: subscription was already closed", // DPI_ERR_SUBSCR_CLOSED + "DPI-1061: edition is not supported when a new password is specified", // DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD + "DPI-1062: unexpected OCI return value %d in function %s", // DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE + "DPI-1063: modes DPI_MODE_EXEC_BATCH_ERRORS and DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS can only be used with insert, update, delete and merge statements", // DPI_ERR_EXEC_MODE_ONLY_FOR_DML + "DPI-1064: array variables are not supported with dpiStmt_executeMany()", // DPI_ERR_ARRAY_VAR_NOT_SUPPORTED + "DPI-1065: events mode is required to subscribe to events in the database", // DPI_ERR_EVENTS_MODE_REQUIRED + "DPI-1066: Oracle Database is at version %d.%d but version %d.%d or higher is needed", // DPI_ERR_ORACLE_DB_TOO_OLD + "DPI-1067: call timeout of %u ms exceeded with ORA-%d", // DPI_ERR_CALL_TIMEOUT + "DPI-1068: SODA cursor was already closed", // DPI_ERR_SODA_CURSOR_CLOSED + "DPI-1069: proxy user name must be enclosed in [] when using external authentication", // DPI_ERR_EXT_AUTH_INVALID_PROXY + "DPI-1070: no payload provided in message properties", // DPI_ERR_QUEUE_NO_PAYLOAD + "DPI-1071: payload type in message properties must match the payload type of the queue", // DPI_ERR_QUEUE_WRONG_PAYLOAD_TYPE + "DPI-1072: the Oracle Client library version is unsupported", // DPI_ERR_ORACLE_CLIENT_UNSUPPORTED + "DPI-1073: sharding key is required when specifying a super sharding key", // DPI_ERR_MISSING_SHARDING_KEY +}; diff --git a/vendor/github.com/godror/godror/odpi/src/dpiGen.c b/vendor/github.com/godror/godror/odpi/src/dpiGen.c new file mode 100644 index 00000000000..f671adf2a21 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiGen.c @@ -0,0 +1,307 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiGen.c +// Generic routines for managing the types available through public APIs. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// definition of handle types +//----------------------------------------------------------------------------- +static const dpiTypeDef dpiAllTypeDefs[DPI_HTYPE_MAX - DPI_HTYPE_NONE - 1] = { + { + "dpiConn", // name + sizeof(dpiConn), // size of structure + 0x49DC600C, // check integer + (dpiTypeFreeProc) dpiConn__free + }, + { + "dpiPool", // name + sizeof(dpiPool), // size of structure + 0x18E1AA4B, // check integer + (dpiTypeFreeProc) dpiPool__free + }, + { + "dpiStmt", // name + sizeof(dpiStmt), // size of structure + 0x31B02B2E, // check integer + (dpiTypeFreeProc) dpiStmt__free + }, + { + "dpiVar", // name + sizeof(dpiVar), // size of structure + 0x2AE8C6DC, // check integer + (dpiTypeFreeProc) dpiVar__free + }, + { + "dpiLob", // name + sizeof(dpiLob), // size of structure + 0xD8F31746, // check integer + (dpiTypeFreeProc) dpiLob__free + }, + { + "dpiObject", // name + sizeof(dpiObject), // size of structure + 0x38616080, // check integer + (dpiTypeFreeProc) dpiObject__free + }, + { + "dpiObjectType", // name + sizeof(dpiObjectType), // size of structure + 0x86036059, // check integer + (dpiTypeFreeProc) dpiObjectType__free + }, + { + "dpiObjectAttr", // name + sizeof(dpiObjectAttr), // size of structure + 0xea6d5dde, // check integer + (dpiTypeFreeProc) dpiObjectAttr__free + }, + { + "dpiSubscr", // name + sizeof(dpiSubscr), // size of structure + 0xa415a1c0, // check integer + (dpiTypeFreeProc) dpiSubscr__free + }, + { + "dpiDeqOptions", // name + sizeof(dpiDeqOptions), // size of structure + 0x70ee498d, // check integer + (dpiTypeFreeProc) dpiDeqOptions__free + }, + { + "dpiEnqOptions", // name + sizeof(dpiEnqOptions), // size of structure + 0x682f3946, // check integer + (dpiTypeFreeProc) dpiEnqOptions__free + }, + { + "dpiMsgProps", // name + sizeof(dpiMsgProps), // size of structure + 0xa2b75506, // check integer + (dpiTypeFreeProc) dpiMsgProps__free + }, + { + "dpiRowid", // name + sizeof(dpiRowid), // size of structure + 0x6204fa04, // check integer + (dpiTypeFreeProc) dpiRowid__free + }, + { + "dpiContext", // name + sizeof(dpiContext), // size of structure + 0xd81b9181, // check integer + NULL + }, + { + "dpiSodaColl", // name + sizeof(dpiSodaColl), // size of structure + 0x3684db22, // check integer + (dpiTypeFreeProc) dpiSodaColl__free + }, + { + "dpiSodaCollCursor", // name + sizeof(dpiSodaCollCursor), // size of structure + 0xcdc73b86, // check integer + (dpiTypeFreeProc) dpiSodaCollCursor__free + }, + { + "dpiSodaDb", // name + sizeof(dpiSodaDb), // size of structure + 0x1f386121, // check integer + (dpiTypeFreeProc) dpiSodaDb__free + }, + { + "dpiSodaDoc", // name + sizeof(dpiSodaDoc), // size of structure + 0xaffd950a, // check integer + (dpiTypeFreeProc) dpiSodaDoc__free + }, + { + "dpiSodaDocCursor", // name + sizeof(dpiSodaDocCursor), // size of structure + 0x80ceb83b, // check integer + (dpiTypeFreeProc) dpiSodaDocCursor__free + }, + { + "dpiQueue", // name + sizeof(dpiQueue), // size of structure + 0x54904ba2, // check integer + (dpiTypeFreeProc) dpiQueue__free + } +}; + + +//----------------------------------------------------------------------------- +// dpiGen__addRef() [INTERNAL] +// Add a reference to the specified handle. +//----------------------------------------------------------------------------- +int dpiGen__addRef(void *ptr, dpiHandleTypeNum typeNum, const char *fnName) +{ + dpiError error; + + if (dpiGen__startPublicFn(ptr, typeNum, fnName, &error) < 0) + return dpiGen__endPublicFn(ptr, DPI_FAILURE, &error); + dpiGen__setRefCount(ptr, &error, 1); + return dpiGen__endPublicFn(ptr, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiGen__allocate() [INTERNAL] +// Allocate memory for the specified type and initialize the base fields. The +// type specified is assumed to be valid. If the environment is specified, use +// it; otherwise, create a new one. No additional initialization is performed. +//----------------------------------------------------------------------------- +int dpiGen__allocate(dpiHandleTypeNum typeNum, dpiEnv *env, void **handle, + dpiError *error) +{ + const dpiTypeDef *typeDef; + dpiBaseType *value; + + typeDef = &dpiAllTypeDefs[typeNum - DPI_HTYPE_NONE - 1]; + if (dpiUtils__allocateMemory(1, typeDef->size, 1, "allocate handle", + (void**) &value, error) < 0) + return DPI_FAILURE; + value->typeDef = typeDef; + value->checkInt = typeDef->checkInt; + value->refCount = 1; + if (!env && typeNum != DPI_HTYPE_CONTEXT) { + if (dpiUtils__allocateMemory(1, sizeof(dpiEnv), 1, "allocate env", + (void**) &env, error) < 0) { + dpiUtils__freeMemory(value); + return DPI_FAILURE; + } + } + value->env = env; + if (dpiDebugLevel & DPI_DEBUG_LEVEL_REFS) + dpiDebug__print("ref %p (%s) -> 1 [NEW]\n", value, typeDef->name); + + *handle = value; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiGen__checkHandle() [INTERNAL] +// Check that the specific handle is valid, that it matches the type +// requested and that the check integer is still in place. +//----------------------------------------------------------------------------- +int dpiGen__checkHandle(const void *ptr, dpiHandleTypeNum typeNum, + const char *action, dpiError *error) +{ + dpiBaseType *value = (dpiBaseType*) ptr; + const dpiTypeDef *typeDef; + + typeDef = &dpiAllTypeDefs[typeNum - DPI_HTYPE_NONE - 1]; + if (!ptr || value->typeDef != typeDef || + value->checkInt != typeDef->checkInt) + return dpiError__set(error, action, DPI_ERR_INVALID_HANDLE, + typeDef->name); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiGen__endPublicFn() [INTERNAL] +// This method should be the last call made in any public method using an +// ODPI-C handle (other than dpiContext which is handled differently). +//----------------------------------------------------------------------------- +int dpiGen__endPublicFn(const void *ptr, int returnValue, dpiError *error) +{ + if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) + dpiDebug__print("fn end %s(%p) -> %d\n", error->buffer->fnName, ptr, + returnValue); + if (error->handle) + dpiHandlePool__release(error->env->errorHandles, &error->handle); + + return returnValue; +} + + +//----------------------------------------------------------------------------- +// dpiGen__release() [INTERNAL] +// Release a reference to the specified handle. If the reference count +// reaches zero, the resources associated with the handle are released and +// the memory associated with the handle is freed. Any internal references +// held to other handles are also released. +//----------------------------------------------------------------------------- +int dpiGen__release(void *ptr, dpiHandleTypeNum typeNum, const char *fnName) +{ + dpiError error; + + if (dpiGen__startPublicFn(ptr, typeNum, fnName, &error) < 0) + return dpiGen__endPublicFn(ptr, DPI_FAILURE, &error); + dpiGen__setRefCount(ptr, &error, -1); + return dpiGen__endPublicFn(ptr, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiGen__setRefCount() [INTERNAL] +// Increase or decrease the reference count by the given amount. The handle +// is assumed to be valid at this point. If the environment is in threaded +// mode, acquire the mutex first before making any adjustments to the reference +// count. If the operation sets the reference count to zero, release all +// resources and free the memory associated with the structure. +//----------------------------------------------------------------------------- +void dpiGen__setRefCount(void *ptr, dpiError *error, int increment) +{ + dpiBaseType *value = (dpiBaseType*) ptr; + unsigned localRefCount; + + // if threaded need to protect modification of the refCount with a mutex; + // also ensure that if the reference count reaches zero that it is + // immediately marked invalid in order to avoid race conditions + if (value->env->threaded) + dpiMutex__acquire(value->env->mutex); + value->refCount += increment; + localRefCount = value->refCount; + if (localRefCount == 0) + dpiUtils__clearMemory(&value->checkInt, sizeof(value->checkInt)); + if (value->env->threaded) + dpiMutex__release(value->env->mutex); + + // reference count debugging + if (dpiDebugLevel & DPI_DEBUG_LEVEL_REFS) + dpiDebug__print("ref %p (%s) -> %d\n", ptr, value->typeDef->name, + localRefCount); + + // if the refCount has reached zero, call the free routine + if (localRefCount == 0) + (*value->typeDef->freeProc)(value, error); +} + + +//----------------------------------------------------------------------------- +// dpiGen__startPublicFn() [INTERNAL] +// This method should be the first call made in any public method using an +// ODPI-C handle (other than dpiContext which is handled differently). The +// handle is checked for validity and an error handle is acquired for use in +// all subsequent calls. +//----------------------------------------------------------------------------- +int dpiGen__startPublicFn(const void *ptr, dpiHandleTypeNum typeNum, + const char *fnName, dpiError *error) +{ + dpiBaseType *value = (dpiBaseType*) ptr; + + if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) + dpiDebug__print("fn start %s(%p)\n", fnName, ptr); + if (dpiGlobal__initError(fnName, error) < 0) + return DPI_FAILURE; + if (dpiGen__checkHandle(ptr, typeNum, "check main handle", error) < 0) + return DPI_FAILURE; + error->env = value->env; + return DPI_SUCCESS; +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiGlobal.c b/vendor/github.com/godror/godror/odpi/src/dpiGlobal.c new file mode 100644 index 00000000000..6599d870421 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiGlobal.c @@ -0,0 +1,291 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiGlobal.c +// Global environment used for managing errors in a thread safe manner as +// well as for looking up encodings. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +// cross platform way of defining an initializer that runs at application +// startup (similar to what is done for the constructor calls for static C++ +// objects) +#if defined(_MSC_VER) + #pragma section(".CRT$XCU", read) + #define DPI_INITIALIZER_HELPER(f, p) \ + static void f(void); \ + __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \ + __pragma(comment(linker,"/include:" p #f "_")) \ + static void f(void) + #ifdef _WIN64 + #define DPI_INITIALIZER(f) DPI_INITIALIZER_HELPER(f, "") + #else + #define DPI_INITIALIZER(f) DPI_INITIALIZER_HELPER(f, "_") + #endif +#else + #define DPI_INITIALIZER(f) \ + static void f(void) __attribute__((constructor)); \ + static void f(void) +#endif + +// a global OCI environment is used for managing error buffers in a thread-safe +// manner; each thread is given its own error buffer; OCI error handles, +// though, must be created within the OCI environment created for use by +// standalone connections and session pools +static void *dpiGlobalEnvHandle = NULL; +static void *dpiGlobalErrorHandle = NULL; +static void *dpiGlobalThreadKey = NULL; +static dpiErrorBuffer dpiGlobalErrorBuffer; +static int dpiGlobalInitialized = 0; + +// a global mutex is used to ensure that only one thread is used to perform +// initialization of ODPI-C +static dpiMutexType dpiGlobalMutex; + +//----------------------------------------------------------------------------- +// dpiGlobal__extendedInitialize() [INTERNAL] +// Create the global environment used for managing error buffers in a +// thread-safe manner. This environment is solely used for implementing thread +// local storage for the error buffers and for looking up encodings given an +// IANA or Oracle character set name. +//----------------------------------------------------------------------------- +static int dpiGlobal__extendedInitialize(dpiError *error) +{ + int status; + + // create threaded OCI environment for storing error buffers and for + // looking up character sets; use character set AL32UTF8 solely to avoid + // the overhead of processing the environment variables; no error messages + // from this environment are ever used (ODPI-C specific error messages are + // used) + if (dpiOci__envNlsCreate(&dpiGlobalEnvHandle, DPI_OCI_THREADED, + DPI_CHARSET_ID_UTF8, DPI_CHARSET_ID_UTF8, error) < 0) + return DPI_FAILURE; + + // create global error handle + if (dpiOci__handleAlloc(dpiGlobalEnvHandle, &dpiGlobalErrorHandle, + DPI_OCI_HTYPE_ERROR, "create global error", error) < 0) { + dpiOci__handleFree(dpiGlobalEnvHandle, DPI_OCI_HTYPE_ENV); + return DPI_FAILURE; + } + + // create global thread key + status = dpiOci__threadKeyInit(dpiGlobalEnvHandle, dpiGlobalErrorHandle, + &dpiGlobalThreadKey, (void*) dpiUtils__freeMemory, error); + if (status < 0) { + dpiOci__handleFree(dpiGlobalEnvHandle, DPI_OCI_HTYPE_ENV); + return DPI_FAILURE; + } + + // mark library as fully initialized + dpiGlobalInitialized = 1; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiGlobal__finalize() [INTERNAL] +// Called when the process terminates and ensures that everything is cleaned +// up. +//----------------------------------------------------------------------------- +static void dpiGlobal__finalize(void) +{ + void *errorBuffer = NULL; + dpiError error; + + dpiMutex__acquire(dpiGlobalMutex); + dpiGlobalInitialized = 0; + error.buffer = &dpiGlobalErrorBuffer; + if (dpiGlobalThreadKey) { + dpiOci__threadKeyGet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, + dpiGlobalThreadKey, &errorBuffer, &error); + if (errorBuffer) { + dpiOci__threadKeySet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, + dpiGlobalThreadKey, NULL, &error); + dpiUtils__freeMemory(errorBuffer); + } + dpiOci__threadKeyDestroy(dpiGlobalEnvHandle, dpiGlobalErrorHandle, + &dpiGlobalThreadKey, &error); + dpiGlobalThreadKey = NULL; + } + if (dpiGlobalEnvHandle) { + dpiOci__handleFree(dpiGlobalEnvHandle, DPI_OCI_HTYPE_ENV); + dpiGlobalEnvHandle = NULL; + } + dpiMutex__release(dpiGlobalMutex); +} + + +//----------------------------------------------------------------------------- +// dpiGlobal__initError() [INTERNAL] +// Get the thread local error structure for use in all other functions. If +// an error structure cannot be determined for some reason, the global error +// buffer structure is returned instead. +//----------------------------------------------------------------------------- +int dpiGlobal__initError(const char *fnName, dpiError *error) +{ + dpiErrorBuffer *tempErrorBuffer; + + // initialize error buffer output to global error buffer structure; this is + // the value that is used if an error takes place before the thread local + // error structure can be returned + error->handle = NULL; + error->buffer = &dpiGlobalErrorBuffer; + if (fnName) + error->buffer->fnName = fnName; + + // initialize global environment, if necessary + // this should only ever be done once by the first thread to execute this + if (!dpiGlobalInitialized) { + dpiMutex__acquire(dpiGlobalMutex); + if (!dpiGlobalInitialized) + dpiGlobal__extendedInitialize(error); + dpiMutex__release(dpiGlobalMutex); + if (!dpiGlobalInitialized) + return DPI_FAILURE; + } + + // look up the error buffer specific to this thread + if (dpiOci__threadKeyGet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, + dpiGlobalThreadKey, (void**) &tempErrorBuffer, error) < 0) + return DPI_FAILURE; + + // if NULL, key has never been set for this thread, allocate new error + // and set it + if (!tempErrorBuffer) { + if (dpiUtils__allocateMemory(1, sizeof(dpiErrorBuffer), 1, + "allocate error buffer", (void**) &tempErrorBuffer, error) < 0) + return DPI_FAILURE; + if (dpiOci__threadKeySet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, + dpiGlobalThreadKey, tempErrorBuffer, error) < 0) { + dpiUtils__freeMemory(tempErrorBuffer); + return DPI_FAILURE; + } + } + + // if a function name has been specified, clear error + // the only time a function name is not specified is for + // dpiContext_getError() when the error information is being retrieved + if (fnName) { + tempErrorBuffer->code = 0; + tempErrorBuffer->offset = 0; + tempErrorBuffer->errorNum = (dpiErrorNum) 0; + tempErrorBuffer->isRecoverable = 0; + tempErrorBuffer->messageLength = 0; + tempErrorBuffer->fnName = fnName; + tempErrorBuffer->action = "start"; + strcpy(tempErrorBuffer->encoding, DPI_CHARSET_NAME_UTF8); + } + + error->buffer = tempErrorBuffer; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiGlobal__initialize() [INTERNAL] +// Initialization function that runs at process startup or when the library +// is first loaded. Some operating systems have limits on what can be run in +// this function, so most work is done in the dpiGlobal__extendedInitialize() +// function that runs when the first call to dpiContext_create() is made. +//----------------------------------------------------------------------------- +DPI_INITIALIZER(dpiGlobal__initialize) +{ + memset(&dpiGlobalErrorBuffer, 0, sizeof(dpiGlobalErrorBuffer)); + strcpy(dpiGlobalErrorBuffer.encoding, DPI_CHARSET_NAME_UTF8); + dpiMutex__initialize(dpiGlobalMutex); + dpiDebug__initialize(); + atexit(dpiGlobal__finalize); +} + + +//----------------------------------------------------------------------------- +// dpiGlobal__lookupCharSet() [INTERNAL] +// Lookup the character set id that can be used in the call to +// OCINlsEnvCreate(). +//----------------------------------------------------------------------------- +int dpiGlobal__lookupCharSet(const char *name, uint16_t *charsetId, + dpiError *error) +{ + char oraCharsetName[DPI_OCI_NLS_MAXBUFSZ]; + + // check for well-known encodings first + if (strcmp(name, DPI_CHARSET_NAME_UTF8) == 0) + *charsetId = DPI_CHARSET_ID_UTF8; + else if (strcmp(name, DPI_CHARSET_NAME_UTF16) == 0) + *charsetId = DPI_CHARSET_ID_UTF16; + else if (strcmp(name, DPI_CHARSET_NAME_ASCII) == 0) + *charsetId = DPI_CHARSET_ID_ASCII; + else if (strcmp(name, DPI_CHARSET_NAME_UTF16LE) == 0 || + strcmp(name, DPI_CHARSET_NAME_UTF16BE) == 0) + return dpiError__set(error, "check encoding", DPI_ERR_NOT_SUPPORTED); + + // perform lookup; check for the Oracle character set name first and if + // that fails, lookup using the IANA character set name + else { + if (dpiOci__nlsCharSetNameToId(dpiGlobalEnvHandle, name, charsetId, + error) < 0) + return DPI_FAILURE; + if (!*charsetId) { + if (dpiOci__nlsNameMap(dpiGlobalEnvHandle, oraCharsetName, + sizeof(oraCharsetName), name, DPI_OCI_NLS_CS_IANA_TO_ORA, + error) < 0) + return dpiError__set(error, "lookup charset", + DPI_ERR_INVALID_CHARSET, name); + dpiOci__nlsCharSetNameToId(dpiGlobalEnvHandle, oraCharsetName, + charsetId, error); + } + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiGlobal__lookupEncoding() [INTERNAL] +// Get the IANA character set name (encoding) given the Oracle character set +// id. +//----------------------------------------------------------------------------- +int dpiGlobal__lookupEncoding(uint16_t charsetId, char *encoding, + dpiError *error) +{ + char oracleName[DPI_OCI_NLS_MAXBUFSZ]; + + // check for well-known encodings first + switch (charsetId) { + case DPI_CHARSET_ID_UTF8: + strcpy(encoding, DPI_CHARSET_NAME_UTF8); + return DPI_SUCCESS; + case DPI_CHARSET_ID_UTF16: + strcpy(encoding, DPI_CHARSET_NAME_UTF16); + return DPI_SUCCESS; + case DPI_CHARSET_ID_ASCII: + strcpy(encoding, DPI_CHARSET_NAME_ASCII); + return DPI_SUCCESS; + } + + // get character set name + if (dpiOci__nlsCharSetIdToName(dpiGlobalEnvHandle, oracleName, + sizeof(oracleName), charsetId, error) < 0) + return dpiError__set(error, "lookup Oracle character set name", + DPI_ERR_INVALID_CHARSET_ID, charsetId); + + // get IANA character set name + if (dpiOci__nlsNameMap(dpiGlobalEnvHandle, encoding, DPI_OCI_NLS_MAXBUFSZ, + oracleName, DPI_OCI_NLS_CS_ORA_TO_IANA, error) < 0) + return dpiError__set(error, "lookup IANA name", + DPI_ERR_INVALID_CHARSET_ID, charsetId); + + return DPI_SUCCESS; +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiHandleList.c b/vendor/github.com/godror/godror/odpi/src/dpiHandleList.c new file mode 100644 index 00000000000..2f3864067bb --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiHandleList.c @@ -0,0 +1,116 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiHandleList.c +// Implementation of a list of handles which are managed in a thread-safe +// manner. The references to these handles are assumed to be held by other +// structures. No references are held by the list of handles defined here. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiHandleList__addHandle() [INTERNAL] +// Add a handle to the list. The list is expanded in sets of 8 handles as +// needed. A current position is maintained to reduce the number of scans of +// the list are required. An empty slot is designated by a NULL pointer. +//----------------------------------------------------------------------------- +int dpiHandleList__addHandle(dpiHandleList *list, void *handle, + uint32_t *slotNum, dpiError *error) +{ + uint32_t numSlots, i; + void **tempHandles; + + dpiMutex__acquire(list->mutex); + if (list->numUsedSlots == list->numSlots) { + numSlots = list->numSlots + 8; + if (dpiUtils__allocateMemory(numSlots, sizeof(void*), 1, + "allocate slots", (void**) &tempHandles, error) < 0) { + dpiMutex__release(list->mutex); + return DPI_FAILURE; + } + memcpy(tempHandles, list->handles, list->numSlots * sizeof(void*)); + dpiUtils__freeMemory(list->handles); + list->handles = tempHandles; + list->numSlots = numSlots; + *slotNum = list->numUsedSlots++; + list->currentPos = list->numUsedSlots; + } else { + for (i = 0; i < list->numSlots; i++) { + if (!list->handles[list->currentPos]) + break; + list->currentPos++; + if (list->currentPos == list->numSlots) + list->currentPos = 0; + } + list->numUsedSlots++; + *slotNum = list->currentPos++; + if (list->currentPos == list->numSlots) + list->currentPos = 0; + } + list->handles[*slotNum] = handle; + dpiMutex__release(list->mutex); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiHandleList__create() [INTERNAL] +// Create a new (empty) list of handles. +//----------------------------------------------------------------------------- +int dpiHandleList__create(dpiHandleList **list, dpiError *error) +{ + dpiHandleList *tempList; + + if (dpiUtils__allocateMemory(1, sizeof(dpiHandleList), 0, + "allocate handle list", (void**) &tempList, error) < 0) + return DPI_FAILURE; + tempList->numSlots = 8; + tempList->numUsedSlots = 0; + if (dpiUtils__allocateMemory(tempList->numSlots, sizeof(void*), 1, + "allocate handle list slots", (void**) &tempList->handles, + error) < 0) { + dpiUtils__freeMemory(tempList); + return DPI_FAILURE; + } + dpiMutex__initialize(tempList->mutex); + tempList->currentPos = 0; + *list = tempList; + return DPI_SUCCESS; +} + +//----------------------------------------------------------------------------- +// dpiHandleList__free() [INTERNAL] +// Free the memory associated with the handle list. +//----------------------------------------------------------------------------- +void dpiHandleList__free(dpiHandleList *list) +{ + if (list->handles) { + dpiUtils__freeMemory(list->handles); + list->handles = NULL; + } + dpiMutex__destroy(list->mutex); + dpiUtils__freeMemory(list); +} + + +//----------------------------------------------------------------------------- +// dpiHandleList__removeHandle() [INTERNAL] +// Remove the handle at the specified location from the list. +//----------------------------------------------------------------------------- +void dpiHandleList__removeHandle(dpiHandleList *list, uint32_t slotNum) +{ + dpiMutex__acquire(list->mutex); + list->handles[slotNum] = NULL; + list->numUsedSlots--; + dpiMutex__release(list->mutex); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiHandlePool.c b/vendor/github.com/godror/godror/odpi/src/dpiHandlePool.c new file mode 100644 index 00000000000..456f094f136 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiHandlePool.c @@ -0,0 +1,119 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiHandlePool.c +// Implementation of a pool of handles which can be acquired and released in +// a thread-safe manner. The pool is a circular queue where handles are +// acquired from the front and released to the back. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiHandlePool__acquire() [INTERNAL] +// Acquire a handle from the pool. If a handle is available, it will be +// cleared out of the pool and returned to the caller. It is the caller's +// responsibility to return the handle back to the pool when it is finished +// with it. If no handle is available, a NULL value is returned. The caller is +// expected to create a new handle and return it to the pool when it is +// finished with it. +//----------------------------------------------------------------------------- +int dpiHandlePool__acquire(dpiHandlePool *pool, void **handle, dpiError *error) +{ + void **tempHandles; + uint32_t numSlots; + + dpiMutex__acquire(pool->mutex); + if (pool->acquirePos != pool->releasePos) { + *handle = pool->handles[pool->acquirePos]; + pool->handles[pool->acquirePos++] = NULL; + if (pool->acquirePos == pool->numSlots) + pool->acquirePos = 0; + } else { + *handle = NULL; + pool->numUsedSlots++; + if (pool->numUsedSlots > pool->numSlots) { + numSlots = pool->numSlots + 8; + if (dpiUtils__allocateMemory(numSlots, sizeof(void*), 1, + "allocate slots", (void**) &tempHandles, error) < 0) { + dpiMutex__release(pool->mutex); + return DPI_FAILURE; + } + memcpy(tempHandles, pool->handles, pool->numSlots * sizeof(void*)); + dpiUtils__freeMemory(pool->handles); + pool->handles = tempHandles; + pool->numSlots = numSlots; + } + } + dpiMutex__release(pool->mutex); + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiHandlePool__create() [INTERNAL] +// Create a new handle pool. +//----------------------------------------------------------------------------- +int dpiHandlePool__create(dpiHandlePool **pool, dpiError *error) +{ + dpiHandlePool *tempPool; + + if (dpiUtils__allocateMemory(1, sizeof(dpiHandlePool), 0, + "allocate handle pool", (void**) &tempPool, error) < 0) + return DPI_FAILURE; + tempPool->numSlots = 8; + tempPool->numUsedSlots = 0; + if (dpiUtils__allocateMemory(tempPool->numSlots, sizeof(void*), 1, + "allocate handle pool slots", (void**) &tempPool->handles, + error) < 0) { + dpiUtils__freeMemory(tempPool); + return DPI_FAILURE; + } + dpiMutex__initialize(tempPool->mutex); + tempPool->acquirePos = 0; + tempPool->releasePos = 0; + *pool = tempPool; + return DPI_SUCCESS; +} + +//----------------------------------------------------------------------------- +// dpiHandlePool__free() [INTERNAL] +// Free the memory associated with the error pool. +//----------------------------------------------------------------------------- +void dpiHandlePool__free(dpiHandlePool *pool) +{ + if (pool->handles) { + dpiUtils__freeMemory(pool->handles); + pool->handles = NULL; + } + dpiMutex__destroy(pool->mutex); + dpiUtils__freeMemory(pool); +} + + +//----------------------------------------------------------------------------- +// dpiHandlePool__release() [INTERNAL] +// Release a handle back to the pool. No checks are performed on the handle +// that is being returned to the pool; It will simply be placed back in the +// pool. The handle is then NULLed in order to avoid multiple attempts to +// release the handle back to the pool. +//----------------------------------------------------------------------------- +void dpiHandlePool__release(dpiHandlePool *pool, void **handle) +{ + dpiMutex__acquire(pool->mutex); + pool->handles[pool->releasePos++] = *handle; + *handle = NULL; + if (pool->releasePos == pool->numSlots) + pool->releasePos = 0; + dpiMutex__release(pool->mutex); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiImpl.h b/vendor/github.com/godror/godror/odpi/src/dpiImpl.h new file mode 100644 index 00000000000..ec2ede13955 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiImpl.h @@ -0,0 +1,1905 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiImpl.h +// Master include file for implementation of ODPI-C library. The definitions +// in this file are subject to change without warning. Only the definitions in +// the file dpi.h are intended to be used publicly. +//----------------------------------------------------------------------------- + +#ifndef DPI_IMPL +#define DPI_IMPL + +// Visual Studio 2005 introduced deprecation warnings for "insecure" and POSIX +// functions; silence these warnings +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include "dpi.h" + +#ifdef _WIN32 +#include +#ifndef isnan +#define isnan _isnan +#endif +#else +#include +#include +#include +#endif +#ifdef __linux +#include +#include +#endif + +#ifdef _MSC_VER +#if _MSC_VER < 1900 +#define PRId64 "I64d" +#define PRIu64 "I64u" +#define snprintf _snprintf +#endif +#endif + +#ifndef PRIu64 +#include +#endif + +#ifdef __GNUC__ +#define UNUSED __attribute((unused)) +#else +#define UNUSED +#endif + +// define debugging level (defined in dpiGlobal.c) +extern unsigned long dpiDebugLevel; + +// define max error size +#define DPI_MAX_ERROR_SIZE 3072 + +// define context name for ping interval +#define DPI_CONTEXT_LAST_TIME_USED "DPI_LAST_TIME_USED" + +// define size of buffer used for numbers transferred to/from Oracle as text +#define DPI_NUMBER_AS_TEXT_CHARS 172 + +// define maximum number of digits possible in an Oracle number +#define DPI_NUMBER_MAX_DIGITS 38 + +// define maximum size in bytes supported by basic string handling +#define DPI_MAX_BASIC_BUFFER_SIZE 32767 + +// define internal chunk size used for dynamic binding/fetching +#define DPI_DYNAMIC_BYTES_CHUNK_SIZE 65536 + +// define maximum buffer size permitted in variables +#define DPI_MAX_VAR_BUFFER_SIZE (1024 * 1024 * 1024 - 2) + +// define subscription grouping repeat count +#define DPI_SUBSCR_GROUPING_FOREVER -1 + +// define number of rows to prefetch +#define DPI_PREFETCH_ROWS_DEFAULT 2 + +// define well-known character sets +#define DPI_CHARSET_ID_ASCII 1 +#define DPI_CHARSET_ID_UTF8 873 +#define DPI_CHARSET_ID_UTF16 1000 +#define DPI_CHARSET_ID_UTF16BE 2000 +#define DPI_CHARSET_ID_UTF16LE 2002 +#define DPI_CHARSET_NAME_ASCII "ASCII" +#define DPI_CHARSET_NAME_UTF8 "UTF-8" +#define DPI_CHARSET_NAME_UTF16 "UTF-16" +#define DPI_CHARSET_NAME_UTF16BE "UTF-16BE" +#define DPI_CHARSET_NAME_UTF16LE "UTF-16LE" + +// define handle types used for allocating OCI handles +#define DPI_OCI_HTYPE_ENV 1 +#define DPI_OCI_HTYPE_ERROR 2 +#define DPI_OCI_HTYPE_SVCCTX 3 +#define DPI_OCI_HTYPE_STMT 4 +#define DPI_OCI_HTYPE_BIND 5 +#define DPI_OCI_HTYPE_DEFINE 6 +#define DPI_OCI_HTYPE_DESCRIBE 7 +#define DPI_OCI_HTYPE_SERVER 8 +#define DPI_OCI_HTYPE_SESSION 9 +#define DPI_OCI_HTYPE_AUTHINFO 9 +#define DPI_OCI_HTYPE_TRANS 10 +#define DPI_OCI_HTYPE_SUBSCRIPTION 13 +#define DPI_OCI_HTYPE_SPOOL 27 +#define DPI_OCI_HTYPE_SODA_COLLECTION 30 +#define DPI_OCI_HTYPE_SODA_DOCUMENT 31 +#define DPI_OCI_HTYPE_SODA_COLL_CURSOR 32 +#define DPI_OCI_HTYPE_SODA_OPER_OPTIONS 33 +#define DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS 34 +#define DPI_OCI_HTYPE_SODA_DOC_CURSOR 36 + +// define OCI descriptor types +#define DPI_OCI_DTYPE_LOB 50 +#define DPI_OCI_DTYPE_PARAM 53 +#define DPI_OCI_DTYPE_ROWID 54 +#define DPI_OCI_DTYPE_AQENQ_OPTIONS 57 +#define DPI_OCI_DTYPE_AQDEQ_OPTIONS 58 +#define DPI_OCI_DTYPE_AQMSG_PROPERTIES 59 +#define DPI_OCI_DTYPE_INTERVAL_YM 62 +#define DPI_OCI_DTYPE_INTERVAL_DS 63 +#define DPI_OCI_DTYPE_AQNFY_DESCRIPTOR 64 +#define DPI_OCI_DTYPE_TIMESTAMP 68 +#define DPI_OCI_DTYPE_TIMESTAMP_TZ 69 +#define DPI_OCI_DTYPE_TIMESTAMP_LTZ 70 +#define DPI_OCI_DTYPE_CHDES 77 +#define DPI_OCI_DTYPE_TABLE_CHDES 78 +#define DPI_OCI_DTYPE_ROW_CHDES 79 +#define DPI_OCI_DTYPE_CQDES 80 +#define DPI_OCI_DTYPE_SHARDING_KEY 83 + +// define values used for getting/setting OCI attributes +#define DPI_OCI_ATTR_DATA_SIZE 1 +#define DPI_OCI_ATTR_DATA_TYPE 2 +#define DPI_OCI_ATTR_ENV 5 +#define DPI_OCI_ATTR_PRECISION 5 +#define DPI_OCI_ATTR_SCALE 6 +#define DPI_OCI_ATTR_NAME 4 +#define DPI_OCI_ATTR_SERVER 6 +#define DPI_OCI_ATTR_SESSION 7 +#define DPI_OCI_ATTR_IS_NULL 7 +#define DPI_OCI_ATTR_TRANS 8 +#define DPI_OCI_ATTR_TYPE_NAME 8 +#define DPI_OCI_ATTR_SCHEMA_NAME 9 +#define DPI_OCI_ATTR_ROW_COUNT 9 +#define DPI_OCI_ATTR_PREFETCH_ROWS 11 +#define DPI_OCI_ATTR_PARAM_COUNT 18 +#define DPI_OCI_ATTR_ROWID 19 +#define DPI_OCI_ATTR_USERNAME 22 +#define DPI_OCI_ATTR_PASSWORD 23 +#define DPI_OCI_ATTR_STMT_TYPE 24 +#define DPI_OCI_ATTR_INTERNAL_NAME 25 +#define DPI_OCI_ATTR_EXTERNAL_NAME 26 +#define DPI_OCI_ATTR_XID 27 +#define DPI_OCI_ATTR_CHARSET_ID 31 +#define DPI_OCI_ATTR_CHARSET_FORM 32 +#define DPI_OCI_ATTR_MAXDATA_SIZE 33 +#define DPI_OCI_ATTR_ROWS_RETURNED 42 +#define DPI_OCI_ATTR_VISIBILITY 47 +#define DPI_OCI_ATTR_CONSUMER_NAME 50 +#define DPI_OCI_ATTR_DEQ_MODE 51 +#define DPI_OCI_ATTR_NAVIGATION 52 +#define DPI_OCI_ATTR_WAIT 53 +#define DPI_OCI_ATTR_DEQ_MSGID 54 +#define DPI_OCI_ATTR_PRIORITY 55 +#define DPI_OCI_ATTR_DELAY 56 +#define DPI_OCI_ATTR_EXPIRATION 57 +#define DPI_OCI_ATTR_CORRELATION 58 +#define DPI_OCI_ATTR_ATTEMPTS 59 +#define DPI_OCI_ATTR_EXCEPTION_QUEUE 61 +#define DPI_OCI_ATTR_ENQ_TIME 62 +#define DPI_OCI_ATTR_MSG_STATE 63 +#define DPI_OCI_ATTR_ORIGINAL_MSGID 69 +#define DPI_OCI_ATTR_QUEUE_NAME 70 +#define DPI_OCI_ATTR_NUM_DML_ERRORS 73 +#define DPI_OCI_ATTR_DML_ROW_OFFSET 74 +#define DPI_OCI_ATTR_SUBSCR_NAME 94 +#define DPI_OCI_ATTR_SUBSCR_CALLBACK 95 +#define DPI_OCI_ATTR_SUBSCR_CTX 96 +#define DPI_OCI_ATTR_SUBSCR_NAMESPACE 98 +#define DPI_OCI_ATTR_REF_TDO 110 +#define DPI_OCI_ATTR_PARAM 124 +#define DPI_OCI_ATTR_PARSE_ERROR_OFFSET 129 +#define DPI_OCI_ATTR_SERVER_STATUS 143 +#define DPI_OCI_ATTR_STATEMENT 144 +#define DPI_OCI_ATTR_DEQCOND 146 +#define DPI_OCI_ATTR_SUBSCR_RECPTPROTO 149 +#define DPI_OCI_ATTR_CURRENT_POSITION 164 +#define DPI_OCI_ATTR_STMTCACHESIZE 176 +#define DPI_OCI_ATTR_BIND_COUNT 190 +#define DPI_OCI_ATTR_TRANSFORMATION 196 +#define DPI_OCI_ATTR_ROWS_FETCHED 197 +#define DPI_OCI_ATTR_SPOOL_STMTCACHESIZE 208 +#define DPI_OCI_ATTR_TYPECODE 216 +#define DPI_OCI_ATTR_STMT_IS_RETURNING 218 +#define DPI_OCI_ATTR_CURRENT_SCHEMA 224 +#define DPI_OCI_ATTR_SUBSCR_QOSFLAGS 225 +#define DPI_OCI_ATTR_COLLECTION_ELEMENT 227 +#define DPI_OCI_ATTR_SUBSCR_TIMEOUT 227 +#define DPI_OCI_ATTR_NUM_TYPE_ATTRS 228 +#define DPI_OCI_ATTR_SUBSCR_CQ_QOSFLAGS 229 +#define DPI_OCI_ATTR_LIST_TYPE_ATTRS 229 +#define DPI_OCI_ATTR_SUBSCR_CQ_REGID 230 +#define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_CLASS 231 +#define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_VALUE 232 +#define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_TYPE 233 +#define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_REPEAT_COUNT 235 +#define DPI_OCI_ATTR_NCHARSET_ID 262 +#define DPI_OCI_ATTR_APPCTX_SIZE 273 +#define DPI_OCI_ATTR_APPCTX_LIST 274 +#define DPI_OCI_ATTR_APPCTX_NAME 275 +#define DPI_OCI_ATTR_APPCTX_ATTR 276 +#define DPI_OCI_ATTR_APPCTX_VALUE 277 +#define DPI_OCI_ATTR_CLIENT_IDENTIFIER 278 +#define DPI_OCI_ATTR_CHAR_SIZE 286 +#define DPI_OCI_ATTR_EDITION 288 +#define DPI_OCI_ATTR_CQ_QUERYID 304 +#define DPI_OCI_ATTR_SPOOL_TIMEOUT 308 +#define DPI_OCI_ATTR_SPOOL_GETMODE 309 +#define DPI_OCI_ATTR_SPOOL_BUSY_COUNT 310 +#define DPI_OCI_ATTR_SPOOL_OPEN_COUNT 311 +#define DPI_OCI_ATTR_MODULE 366 +#define DPI_OCI_ATTR_ACTION 367 +#define DPI_OCI_ATTR_CLIENT_INFO 368 +#define DPI_OCI_ATTR_SUBSCR_PORTNO 390 +#define DPI_OCI_ATTR_CHNF_ROWIDS 402 +#define DPI_OCI_ATTR_CHNF_OPERATIONS 403 +#define DPI_OCI_ATTR_CHDES_DBNAME 405 +#define DPI_OCI_ATTR_CHDES_NFYTYPE 406 +#define DPI_OCI_ATTR_NFY_FLAGS 406 +#define DPI_OCI_ATTR_CHDES_XID 407 +#define DPI_OCI_ATTR_MSG_DELIVERY_MODE 407 +#define DPI_OCI_ATTR_CHDES_TABLE_CHANGES 408 +#define DPI_OCI_ATTR_CHDES_TABLE_NAME 409 +#define DPI_OCI_ATTR_CHDES_TABLE_OPFLAGS 410 +#define DPI_OCI_ATTR_CHDES_TABLE_ROW_CHANGES 411 +#define DPI_OCI_ATTR_CHDES_ROW_ROWID 412 +#define DPI_OCI_ATTR_CHDES_ROW_OPFLAGS 413 +#define DPI_OCI_ATTR_CHNF_REGHANDLE 414 +#define DPI_OCI_ATTR_CQDES_OPERATION 422 +#define DPI_OCI_ATTR_CQDES_TABLE_CHANGES 423 +#define DPI_OCI_ATTR_CQDES_QUERYID 424 +#define DPI_OCI_ATTR_DRIVER_NAME 424 +#define DPI_OCI_ATTR_CHDES_QUERIES 425 +#define DPI_OCI_ATTR_CONNECTION_CLASS 425 +#define DPI_OCI_ATTR_PURITY 426 +#define DPI_OCI_ATTR_RECEIVE_TIMEOUT 436 +#define DPI_OCI_ATTR_LOBPREFETCH_LENGTH 440 +#define DPI_OCI_ATTR_SUBSCR_IPADDR 452 +#define DPI_OCI_ATTR_UB8_ROW_COUNT 457 +#define DPI_OCI_ATTR_SPOOL_AUTH 460 +#define DPI_OCI_ATTR_LTXID 462 +#define DPI_OCI_ATTR_DML_ROW_COUNT_ARRAY 469 +#define DPI_OCI_ATTR_ERROR_IS_RECOVERABLE 472 +#define DPI_OCI_ATTR_TRANSACTION_IN_PROGRESS 484 +#define DPI_OCI_ATTR_DBOP 485 +#define DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION 490 +#define DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT 495 +#define DPI_OCI_ATTR_SHARDING_KEY 496 +#define DPI_OCI_ATTR_SUPER_SHARDING_KEY 497 +#define DPI_OCI_ATTR_FIXUP_CALLBACK 501 +#define DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT 506 +#define DPI_OCI_ATTR_CALL_TIMEOUT 531 +#define DPI_OCI_ATTR_SODA_COLL_NAME 535 +#define DPI_OCI_ATTR_SODA_COLL_DESCRIPTOR 536 +#define DPI_OCI_ATTR_SODA_CTNT_SQL_TYPE 549 +#define DPI_OCI_ATTR_SODA_KEY 563 +#define DPI_OCI_ATTR_SODA_LASTMOD_TIMESTAMP 564 +#define DPI_OCI_ATTR_SODA_CREATE_TIMESTAMP 565 +#define DPI_OCI_ATTR_SODA_VERSION 566 +#define DPI_OCI_ATTR_SODA_CONTENT 567 +#define DPI_OCI_ATTR_SODA_JSON_CHARSET_ID 568 +#define DPI_OCI_ATTR_SODA_DETECT_JSON_ENC 569 +#define DPI_OCI_ATTR_SODA_MEDIA_TYPE 571 +#define DPI_OCI_ATTR_SODA_CTNT_FORMAT 572 +#define DPI_OCI_ATTR_SODA_FILTER 576 +#define DPI_OCI_ATTR_SODA_SKIP 577 +#define DPI_OCI_ATTR_SODA_LIMIT 578 +#define DPI_OCI_ATTR_SODA_DOC_COUNT 593 +#define DPI_OCI_ATTR_SPOOL_MAX_PER_SHARD 602 + +// define OCI object type constants +#define DPI_OCI_OTYPE_NAME 1 +#define DPI_OCI_OTYPE_PTR 3 + +// define OCI data type constants +#define DPI_SQLT_CHR 1 +#define DPI_SQLT_NUM 2 +#define DPI_SQLT_INT 3 +#define DPI_SQLT_FLT 4 +#define DPI_SQLT_VNU 6 +#define DPI_SQLT_PDN 7 +#define DPI_SQLT_LNG 8 +#define DPI_SQLT_VCS 9 +#define DPI_SQLT_DAT 12 +#define DPI_SQLT_BFLOAT 21 +#define DPI_SQLT_BDOUBLE 22 +#define DPI_SQLT_BIN 23 +#define DPI_SQLT_LBI 24 +#define DPI_SQLT_UIN 68 +#define DPI_SQLT_LVB 95 +#define DPI_SQLT_AFC 96 +#define DPI_SQLT_IBFLOAT 100 +#define DPI_SQLT_IBDOUBLE 101 +#define DPI_SQLT_RDD 104 +#define DPI_SQLT_NTY 108 +#define DPI_SQLT_CLOB 112 +#define DPI_SQLT_BLOB 113 +#define DPI_SQLT_BFILE 114 +#define DPI_SQLT_RSET 116 +#define DPI_SQLT_NCO 122 +#define DPI_SQLT_ODT 156 +#define DPI_SQLT_DATE 184 +#define DPI_SQLT_TIMESTAMP 187 +#define DPI_SQLT_TIMESTAMP_TZ 188 +#define DPI_SQLT_INTERVAL_YM 189 +#define DPI_SQLT_INTERVAL_DS 190 +#define DPI_SQLT_TIMESTAMP_LTZ 232 +#define DPI_OCI_TYPECODE_SMALLINT 246 +#define DPI_SQLT_REC 250 +#define DPI_SQLT_BOL 252 +#define DPI_OCI_TYPECODE_ROWID 262 +#define DPI_OCI_TYPECODE_LONG 263 +#define DPI_OCI_TYPECODE_LONG_RAW 264 +#define DPI_OCI_TYPECODE_BINARY_INTEGER 265 +#define DPI_OCI_TYPECODE_PLS_INTEGER 266 + +// define session pool constants +#define DPI_OCI_SPD_FORCE 0x0001 +#define DPI_OCI_SPC_HOMOGENEOUS 0x0002 +#define DPI_OCI_SPC_STMTCACHE 0x0004 + +// define OCI session pool get constants +#define DPI_OCI_SESSGET_SPOOL 0x0001 +#define DPI_OCI_SESSGET_STMTCACHE 0x0004 +#define DPI_OCI_SESSGET_CREDPROXY 0x0008 +#define DPI_OCI_SESSGET_CREDEXT 0x0010 +#define DPI_OCI_SESSGET_SPOOL_MATCHANY 0x0020 +#define DPI_OCI_SESSGET_SYSDBA 0x0100 +#define DPI_OCI_SESSGET_MULTIPROPERTY_TAG 0x0400 + +// define OCI authentication constants +#define DPI_OCI_CPW_SYSDBA 0x00000010 +#define DPI_OCI_CPW_SYSOPER 0x00000020 +#define DPI_OCI_CPW_SYSASM 0x00800040 +#define DPI_OCI_CPW_SYSBKP 0x00000080 +#define DPI_OCI_CPW_SYSDGD 0x00000100 +#define DPI_OCI_CPW_SYSKMT 0x00000200 + +// define NLS constants +#define DPI_OCI_NLS_CS_IANA_TO_ORA 0 +#define DPI_OCI_NLS_CS_ORA_TO_IANA 1 +#define DPI_OCI_NLS_CHARSET_MAXBYTESZ 91 +#define DPI_OCI_NLS_CHARSET_ID 93 +#define DPI_OCI_NLS_NCHARSET_ID 94 +#define DPI_OCI_NLS_MAXBUFSZ 100 +#define DPI_SQLCS_IMPLICIT 1 +#define DPI_SQLCS_NCHAR 2 + +// define XA constants +#define DPI_XA_MAXGTRIDSIZE 64 +#define DPI_XA_MAXBQUALSIZE 64 +#define DPI_XA_XIDDATASIZE 128 + +// define null indicator values +#define DPI_OCI_IND_NULL -1 +#define DPI_OCI_IND_NOTNULL 0 + +// define subscription QOS values +#define DPI_OCI_SUBSCR_QOS_RELIABLE 0x01 +#define DPI_OCI_SUBSCR_QOS_PURGE_ON_NTFN 0x10 +#define DPI_OCI_SUBSCR_CQ_QOS_QUERY 0x01 +#define DPI_OCI_SUBSCR_CQ_QOS_BEST_EFFORT 0x02 + +// define miscellaneous OCI constants +#define DPI_OCI_CONTINUE -24200 +#define DPI_OCI_INVALID_HANDLE -2 +#define DPI_OCI_ERROR -1 +#define DPI_OCI_DEFAULT 0 +#define DPI_OCI_SUCCESS 0 +#define DPI_OCI_ONE_PIECE 0 +#define DPI_OCI_ATTR_PURITY_DEFAULT 0 +#define DPI_OCI_NUMBER_UNSIGNED 0 +#define DPI_OCI_SUCCESS_WITH_INFO 1 +#define DPI_OCI_NTV_SYNTAX 1 +#define DPI_OCI_MEMORY_CLEARED 1 +#define DPI_OCI_SESSRLS_DROPSESS 1 +#define DPI_OCI_SESSRLS_MULTIPROPERTY_TAG 4 +#define DPI_OCI_SERVER_NORMAL 1 +#define DPI_OCI_TYPEGET_ALL 1 +#define DPI_OCI_TRANS_NEW 1 +#define DPI_OCI_LOCK_NONE 1 +#define DPI_OCI_TEMP_BLOB 1 +#define DPI_OCI_CRED_RDBMS 1 +#define DPI_OCI_LOB_READONLY 1 +#define DPI_OCI_JSON_FORMAT_OSON 1 +#define DPI_OCI_TEMP_CLOB 2 +#define DPI_OCI_CRED_EXT 2 +#define DPI_OCI_LOB_READWRITE 2 +#define DPI_OCI_DATA_AT_EXEC 2 +#define DPI_OCI_DYNAMIC_FETCH 2 +#define DPI_OCI_NUMBER_SIGNED 2 +#define DPI_OCI_PIN_ANY 3 +#define DPI_OCI_PTYPE_TYPE 6 +#define DPI_OCI_AUTH 8 +#define DPI_OCI_DURATION_SESSION 10 +#define DPI_OCI_NUMBER_SIZE 22 +#define DPI_OCI_NO_DATA 100 +#define DPI_OCI_STRLS_CACHE_DELETE 0x0010 +#define DPI_OCI_THREADED 0x00000001 +#define DPI_OCI_OBJECT 0x00000002 +#define DPI_OCI_SODA_ATOMIC_COMMIT 0x00000001 +#define DPI_OCI_SODA_AS_STORED 0x00000002 +#define DPI_OCI_SODA_AS_AL32UTF8 0x00000004 +#define DPI_OCI_STMT_SCROLLABLE_READONLY 0x00000008 +#define DPI_OCI_STMT_CACHE 0x00000040 +#define DPI_OCI_SODA_COLL_CREATE_MAP 0x00010000 +#define DPI_OCI_SODA_INDEX_DROP_FORCE 0x00010000 +#define DPI_OCI_TRANS_TWOPHASE 0x01000000 +#define DPI_OCI_SECURE_NOTIFICATION 0x20000000 + +//----------------------------------------------------------------------------- +// Macros +//----------------------------------------------------------------------------- +#define DPI_CHECK_PTR_NOT_NULL(handle, parameter) \ + if (!parameter) { \ + dpiError__set(&error, "check parameter " #parameter, \ + DPI_ERR_NULL_POINTER_PARAMETER, #parameter); \ + return dpiGen__endPublicFn(handle, DPI_FAILURE, &error); \ + } + +#define DPI_CHECK_PTR_AND_LENGTH(handle, parameter) \ + if (!parameter && parameter ## Length > 0) { \ + dpiError__set(&error, "check parameter " #parameter, \ + DPI_ERR_PTR_LENGTH_MISMATCH, #parameter); \ + return dpiGen__endPublicFn(handle, DPI_FAILURE, &error); \ + } + + +//----------------------------------------------------------------------------- +// Enumerations +//----------------------------------------------------------------------------- + +// error numbers +typedef enum { + DPI_ERR_NO_ERR = 1000, + DPI_ERR_NO_MEMORY, + DPI_ERR_INVALID_HANDLE, + DPI_ERR_ERR_NOT_INITIALIZED, + DPI_ERR_GET_FAILED, + DPI_ERR_CREATE_ENV, + DPI_ERR_CONVERT_TEXT, + DPI_ERR_QUERY_NOT_EXECUTED, + DPI_ERR_UNHANDLED_DATA_TYPE, + DPI_ERR_INVALID_ARRAY_POSITION, + DPI_ERR_NOT_CONNECTED, + DPI_ERR_CONN_NOT_IN_POOL, + DPI_ERR_INVALID_PROXY, + DPI_ERR_NOT_SUPPORTED, + DPI_ERR_UNHANDLED_CONVERSION, + DPI_ERR_ARRAY_SIZE_TOO_BIG, + DPI_ERR_INVALID_DATE, + DPI_ERR_VALUE_IS_NULL, + DPI_ERR_ARRAY_SIZE_TOO_SMALL, + DPI_ERR_BUFFER_SIZE_TOO_SMALL, + DPI_ERR_VERSION_NOT_SUPPORTED, + DPI_ERR_INVALID_ORACLE_TYPE, + DPI_ERR_WRONG_ATTR, + DPI_ERR_NOT_COLLECTION, + DPI_ERR_INVALID_INDEX, + DPI_ERR_NO_OBJECT_TYPE, + DPI_ERR_INVALID_CHARSET, + DPI_ERR_SCROLL_OUT_OF_RS, + DPI_ERR_QUERY_POSITION_INVALID, + DPI_ERR_NO_ROW_FETCHED, + DPI_ERR_TLS_ERROR, + DPI_ERR_ARRAY_SIZE_ZERO, + DPI_ERR_EXT_AUTH_WITH_CREDENTIALS, + DPI_ERR_CANNOT_GET_ROW_OFFSET, + DPI_ERR_CONN_IS_EXTERNAL, + DPI_ERR_TRANS_ID_TOO_LARGE, + DPI_ERR_BRANCH_ID_TOO_LARGE, + DPI_ERR_COLUMN_FETCH, + DPI_ERR_STMT_CLOSED, + DPI_ERR_LOB_CLOSED, + DPI_ERR_INVALID_CHARSET_ID, + DPI_ERR_INVALID_OCI_NUMBER, + DPI_ERR_INVALID_NUMBER, + DPI_ERR_NUMBER_NO_REPR, + DPI_ERR_NUMBER_STRING_TOO_LONG, + DPI_ERR_NULL_POINTER_PARAMETER, + DPI_ERR_LOAD_LIBRARY, + DPI_ERR_LOAD_SYMBOL, + DPI_ERR_ORACLE_CLIENT_TOO_OLD, + DPI_ERR_NLS_ENV_VAR_GET, + DPI_ERR_PTR_LENGTH_MISMATCH, + DPI_ERR_NAN, + DPI_ERR_WRONG_TYPE, + DPI_ERR_BUFFER_SIZE_TOO_LARGE, + DPI_ERR_NO_EDITION_WITH_CONN_CLASS, + DPI_ERR_NO_BIND_VARS_IN_DDL, + DPI_ERR_SUBSCR_CLOSED, + DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD, + DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE, + DPI_ERR_EXEC_MODE_ONLY_FOR_DML, + DPI_ERR_ARRAY_VAR_NOT_SUPPORTED, + DPI_ERR_EVENTS_MODE_REQUIRED, + DPI_ERR_ORACLE_DB_TOO_OLD, + DPI_ERR_CALL_TIMEOUT, + DPI_ERR_SODA_CURSOR_CLOSED, + DPI_ERR_EXT_AUTH_INVALID_PROXY, + DPI_ERR_QUEUE_NO_PAYLOAD, + DPI_ERR_QUEUE_WRONG_PAYLOAD_TYPE, + DPI_ERR_ORACLE_CLIENT_UNSUPPORTED, + DPI_ERR_MISSING_SHARDING_KEY, + DPI_ERR_MAX +} dpiErrorNum; + +// handle types +typedef enum { + DPI_HTYPE_NONE = 4000, + DPI_HTYPE_CONN, + DPI_HTYPE_POOL, + DPI_HTYPE_STMT, + DPI_HTYPE_VAR, + DPI_HTYPE_LOB, + DPI_HTYPE_OBJECT, + DPI_HTYPE_OBJECT_TYPE, + DPI_HTYPE_OBJECT_ATTR, + DPI_HTYPE_SUBSCR, + DPI_HTYPE_DEQ_OPTIONS, + DPI_HTYPE_ENQ_OPTIONS, + DPI_HTYPE_MSG_PROPS, + DPI_HTYPE_ROWID, + DPI_HTYPE_CONTEXT, + DPI_HTYPE_SODA_COLL, + DPI_HTYPE_SODA_COLL_CURSOR, + DPI_HTYPE_SODA_DB, + DPI_HTYPE_SODA_DOC, + DPI_HTYPE_SODA_DOC_CURSOR, + DPI_HTYPE_QUEUE, + DPI_HTYPE_MAX +} dpiHandleTypeNum; + + +//----------------------------------------------------------------------------- +// Mutex definitions +//----------------------------------------------------------------------------- +#ifdef _WIN32 + typedef CRITICAL_SECTION dpiMutexType; + #define dpiMutex__initialize(m) InitializeCriticalSection(&m) + #define dpiMutex__destroy(m) DeleteCriticalSection(&m) + #define dpiMutex__acquire(m) EnterCriticalSection(&m) + #define dpiMutex__release(m) LeaveCriticalSection(&m) +#else + typedef pthread_mutex_t dpiMutexType; + #define dpiMutex__initialize(m) pthread_mutex_init(&m, NULL) + #define dpiMutex__destroy(m) pthread_mutex_destroy(&m) + #define dpiMutex__acquire(m) pthread_mutex_lock(&m) + #define dpiMutex__release(m) pthread_mutex_unlock(&m) +#endif + + +//----------------------------------------------------------------------------- +// old type definitions (to be dropped) +//----------------------------------------------------------------------------- + +// structure used for creating pools (3.0) +typedef struct { + uint32_t minSessions; + uint32_t maxSessions; + uint32_t sessionIncrement; + int pingInterval; + int pingTimeout; + int homogeneous; + int externalAuth; + dpiPoolGetMode getMode; + const char *outPoolName; + uint32_t outPoolNameLength; + uint32_t timeout; + uint32_t waitTimeout; + uint32_t maxLifetimeSession; +} dpiPoolCreateParams__v30; + +// structure used for creating pools (3.2) +typedef struct { + uint32_t minSessions; + uint32_t maxSessions; + uint32_t sessionIncrement; + int pingInterval; + int pingTimeout; + int homogeneous; + int externalAuth; + dpiPoolGetMode getMode; + const char *outPoolName; + uint32_t outPoolNameLength; + uint32_t timeout; + uint32_t waitTimeout; + uint32_t maxLifetimeSession; + const char *plsqlFixupCallback; + uint32_t plsqlFixupCallbackLength; +} dpiPoolCreateParams__v32; + +// structure used for creating connections (3.0) +typedef struct { + dpiAuthMode authMode; + const char *connectionClass; + uint32_t connectionClassLength; + dpiPurity purity; + const char *newPassword; + uint32_t newPasswordLength; + dpiAppContext *appContext; + uint32_t numAppContext; + int externalAuth; + void *externalHandle; + dpiPool *pool; + const char *tag; + uint32_t tagLength; + int matchAnyTag; + const char *outTag; + uint32_t outTagLength; + int outTagFound; + dpiShardingKeyColumn *shardingKeyColumns; + uint8_t numShardingKeyColumns; + dpiShardingKeyColumn *superShardingKeyColumns; + uint8_t numSuperShardingKeyColumns; +} dpiConnCreateParams__v30; + +// structure used for creating subscriptions (3.0 and 3.1) +typedef struct { + dpiSubscrNamespace subscrNamespace; + dpiSubscrProtocol protocol; + dpiSubscrQOS qos; + dpiOpCode operations; + uint32_t portNumber; + uint32_t timeout; + const char *name; + uint32_t nameLength; + dpiSubscrCallback callback; + void *callbackContext; + const char *recipientName; + uint32_t recipientNameLength; + const char *ipAddress; + uint32_t ipAddressLength; + uint8_t groupingClass; + uint32_t groupingValue; + uint8_t groupingType; +} dpiSubscrCreateParams__v30; + +// structure used for creating subscriptions (3.2) +typedef struct { + dpiSubscrNamespace subscrNamespace; + dpiSubscrProtocol protocol; + dpiSubscrQOS qos; + dpiOpCode operations; + uint32_t portNumber; + uint32_t timeout; + const char *name; + uint32_t nameLength; + dpiSubscrCallback callback; + void *callbackContext; + const char *recipientName; + uint32_t recipientNameLength; + const char *ipAddress; + uint32_t ipAddressLength; + uint8_t groupingClass; + uint32_t groupingValue; + uint8_t groupingType; + uint64_t outRegId; +} dpiSubscrCreateParams__v32; + + +//----------------------------------------------------------------------------- +// OCI type definitions +//----------------------------------------------------------------------------- + +// representation of OCI Number type +typedef struct { + unsigned char value[DPI_OCI_NUMBER_SIZE]; +} dpiOciNumber; + +// representation of OCI Date type +typedef struct { + int16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; +} dpiOciDate; + +// alternative representation of OCI Date type used for sharding +typedef struct { + uint8_t century; + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; +} dpiShardingOciDate; + +// representation of OCI XID type (two-phase commit) +typedef struct { + long formatID; + long gtrid_length; + long bqual_length; + char data[DPI_XA_XIDDATASIZE]; +} dpiOciXID; + + +//----------------------------------------------------------------------------- +// Internal implementation type definitions +//----------------------------------------------------------------------------- + +// used to manage a list of shared handles in a thread-safe manner; currently +// used for managing the list of open statements, LOBs and created objects for +// a connection (so that they can be closed before the connection itself is +// closed); the functions for managing this structure can be found in the file +// dpiHandleList.c; empty slots in the array are represented by a NULL handle +typedef struct { + void **handles; // array of handles managed by list + uint32_t numSlots; // length of handles array + uint32_t numUsedSlots; // actual number of managed handles + uint32_t currentPos; // next position to search + dpiMutexType mutex; // enables thread safety +} dpiHandleList; + +// used to manage a pool of shared handles in a thread-safe manner; currently +// used for managing the pool of error handles in the dpiEnv structure; the +// functions for managing this structure are found in the file dpiHandlePool.c +typedef struct { + void **handles; // array of handles managed by pool + uint32_t numSlots; // length of handles array + uint32_t numUsedSlots; // actual number of managed handles + uint32_t acquirePos; // position from which to acquire + uint32_t releasePos; // position to place released handles + dpiMutexType mutex; // enables thread safety +} dpiHandlePool; + +// used to save error information internally; one of these is stored for each +// thread using OCIThreadKeyGet() and OCIThreadKeySet() with a globally created +// OCI environment handle; it is also used when getting batch error information +// with the function dpiStmt_getBatchErrors() +typedef struct { + int32_t code; // Oracle error code or 0 + uint16_t offset; // parse error offset or row offset + dpiErrorNum errorNum; // OCPI-C error number + const char *fnName; // ODPI-C function name + const char *action; // internal action + char encoding[DPI_OCI_NLS_MAXBUFSZ]; // encoding (IANA name) + char message[DPI_MAX_ERROR_SIZE]; // buffer for storing messages + uint32_t messageLength; // length of message in buffer + int isRecoverable; // is recoverable? +} dpiErrorBuffer; + +// represents an OCI environment; a pointer to this structure is stored on each +// handle exposed publicly but it is created only when a pool is created or +// when a standalone connection is created; connections acquired from a pool +// shared the same environment as the pool; the functions for manipulating the +// environment are found in the file dpiEnv.c; all values are read-only after +// initialization of environment is complete +typedef struct { + const dpiContext *context; // context used to create environment + void *handle; // OCI environment handle + dpiMutexType mutex; // for reference count (threaded mode) + char encoding[DPI_OCI_NLS_MAXBUFSZ]; // CHAR encoding (IANA name) + int32_t maxBytesPerCharacter; // max bytes per CHAR character + uint16_t charsetId; // CHAR encoding (Oracle charset ID) + char nencoding[DPI_OCI_NLS_MAXBUFSZ]; // NCHAR encoding (IANA name) + int32_t nmaxBytesPerCharacter; // max bytes per NCHAR character + uint16_t ncharsetId; // NCHAR encoding (Oracle charset ID) + dpiHandlePool *errorHandles; // pool of OCI error handles + dpiVersionInfo *versionInfo; // OCI client version info + void *baseDate; // midnight, January 1, 1970 + int threaded; // threaded mode enabled? + int events; // events mode enabled? + int externalHandle; // external handle? +} dpiEnv; + +// used to manage all errors that take place in the library; the implementation +// for the functions that use this structure are found in dpiError.c; a pointer +// to this structure is passed to all internal functions and the first thing +// that takes place in every public function is a call to this this error +// structure +typedef struct { + dpiErrorBuffer *buffer; // buffer to store error information + void *handle; // OCI error handle or NULL + dpiEnv *env; // env which created OCI error handle +} dpiError; + +// function signature for all methods that free publicly exposed handles +typedef void (*dpiTypeFreeProc)(void*, dpiError*); + +// strcture used to provide metadata for the different types of handles exposed +// publicly; a list of these structures (defined as constants) can be found in +// the file dpiGen.c; the enumeration dpiHandleTypeNum is used to identify the +// structures instead of being used directly +typedef struct { + const char *name; // name (used in error messages) + size_t size; // size of structure, in bytes + uint32_t checkInt; // check integer (unique) + dpiTypeFreeProc freeProc; // procedure to call to free handle +} dpiTypeDef; + +// all structures exposed publicly by handle have these members +#define dpiType_HEAD \ + const dpiTypeDef *typeDef; \ + uint32_t checkInt; \ + unsigned refCount; \ + dpiEnv *env; + +// contains the base attributes that all handles exposed publicly have; generic +// functions for checking and manipulating handles are found in the file +// dpiGen.c; the check integer is used to verify the validity of the handle and +// is reset to zero when the handle is freed; the reference count is used to +// manage how many references (either publicly or internally) are held; when +// the reference count reaches zero the handle is freed +typedef struct { + dpiType_HEAD +} dpiBaseType; + +// represents the different types of Oracle data that the library supports; an +// array of these structures (defined as constants) can be found in the file +// dpiOracleType.c; the enumeration dpiOracleTypeNum is used to identify the +// structures +typedef struct dpiOracleType { + dpiOracleTypeNum oracleTypeNum; // enumeration value identifying type + dpiNativeTypeNum defaultNativeTypeNum; // default native (C) type + uint16_t oracleType; // OCI type code + uint8_t charsetForm; // specifies CHAR or NCHAR encoding + uint32_t sizeInBytes; // buffer size (fixed) or 0 (variable) + int isCharacterData; // is type character data? + int canBeInArray; // can type be in an index-by table? + int requiresPreFetch; // prefetch processing required? +} dpiOracleType; + +// represents a chunk of data that has been allocated dynamically for use in +// dynamic fetching of LONG or LONG RAW columns, or when the calling +// application wishes to use strings or raw byte strings instead of LOBs; an +// array of these chunks is found in the structure dpiDynamicBytes +typedef struct { + char *ptr; // pointer to buffer + uint32_t length; // actual length of buffer + uint32_t allocatedLength; // allocated length of buffer +} dpiDynamicBytesChunk; + +// represents a set of chunks allocated dynamically for use in dynamic fetching +// of LONG or LONG RAW columns, or when the calling application wishes to use +// strings or raw byte strings instead of LOBS +typedef struct { + uint32_t numChunks; // actual number of chunks + uint32_t allocatedChunks; // allocated number of chunks + dpiDynamicBytesChunk *chunks; // array of chunks +} dpiDynamicBytes; + +// represents a single bound variable; an array of these is retained in the +// dpiStmt structure in order to retain references to the variables that were +// bound to the statement, which ensures that the values remain valid while the +// statement is executed; the position is populated for bind by position +// (otherwise it is 0) and the name/nameLength are populated for bind by name +// (otherwise they are NULL/0) +typedef struct { + dpiVar *var; + uint32_t pos; + const char *name; + uint32_t nameLength; +} dpiBindVar; + +// intended to avoid the need for casts; contains references to LOBs, objects +// and statements (as part of dpiVar) +typedef union { + void *asHandle; + dpiObject *asObject; + dpiStmt *asStmt; + dpiLob *asLOB; + dpiRowid *asRowid; +} dpiReferenceBuffer; + +// intended to avoid the need for casts; contains the actual values that are +// bound or fetched (as part of dpiVar); it is also used for getting data into +// and out of Oracle object instances +typedef union { + void *asRaw; + char *asBytes; + float *asFloat; + double *asDouble; + int32_t *asInt32; + int64_t *asInt64; + uint64_t *asUint64; + dpiOciNumber *asNumber; + dpiOciDate *asDate; + void **asTimestamp; + void **asInterval; + void **asLobLocator; + void **asString; + void **asRawData; + void **asStmt; + void **asRowid; + int *asBoolean; + void **asObject; + void **asCollection; +} dpiOracleData; + +// intended to avoid the need for casts; contains the memory needed to supply +// buffers to Oracle when values are being transferred to or from the Oracle +// database +typedef union { + int32_t asInt32; + int64_t asInt64; + uint64_t asUint64; + float asFloat; + double asDouble; + dpiOciNumber asNumber; + dpiOciDate asDate; + int asBoolean; + void *asString; + void *asRawData; + void *asTimestamp; + void *asLobLocator; + void *asRaw; +} dpiOracleDataBuffer; + +// represents memory areas used for transferring data to and from the database +// and is used by the dpiVar structure; most statements only use one buffer, +// but DML returning statements can use multiple buffers since multiple rows +// can be returned for each execution of the statement +typedef struct { + uint32_t maxArraySize; // max number of rows in arrays + uint32_t actualArraySize; // actual number of rows in arrays + int16_t *indicator; // array of indicator values + uint16_t *returnCode; // array of return code values + uint16_t *actualLength16; // array of actual lengths (11.2 only) + uint32_t *actualLength32; // array of actual lengths (12.1+) + void **objectIndicator; // array of object indicator values + dpiReferenceBuffer *references; // array of references (specific types) + dpiDynamicBytes *dynamicBytes; // array of dynamically alloced chunks + char *tempBuffer; // buffer for numeric conversion + dpiData *externalData; // array of buffers (externally used) + dpiOracleData data; // Oracle data buffers (internal only) +} dpiVarBuffer; + +// represents memory areas used for enqueuing and dequeuing messages from +// queues +typedef struct { + uint32_t numElements; // number of elements in next arrays + dpiMsgProps **props; // array of dpiMsgProps handles + void **handles; // array of OCI msg prop handles + void **instances; // array of instances + void **indicators; // array of indicators + int16_t *rawIndicators; // array of indicators (RAW queues) + void **msgIds; // array of OCI message ids +} dpiQueueBuffer; + + +//----------------------------------------------------------------------------- +// External implementation type definitions +//----------------------------------------------------------------------------- + +// represents session pools and is exposed publicly as a handle of type +// DPI_HTYPE_POOL; the implementation for this is found in the file +// dpiPool.c +struct dpiPool { + dpiType_HEAD + void *handle; // OCI session pool handle + const char *name; // pool name (CHAR encoding) + uint32_t nameLength; // length of pool name + int pingInterval; // interval (seconds) between pings + int pingTimeout; // timeout (milliseconds) for ping + int homogeneous; // homogeneous pool? + int externalAuth; // use external authentication? +}; + +// represents connections to the database and is exposed publicly as a handle +// of type DPI_HTYPE_CONN; the implementation for this is found in the file +// dpiConn.c; the list of statement, LOB and object handles created by this +// connection is maintained and all of these are automatically closed when the +// connection itself is closed (in order to avoid memory leaks and segfaults if +// the correct order is not observed) +struct dpiConn { + dpiType_HEAD + dpiPool *pool; // pool acquired from or NULL + void *handle; // OCI service context handle + void *serverHandle; // OCI server handle + void *sessionHandle; // OCI session handle + void *shardingKey; // OCI sharding key descriptor + void *superShardingKey; // OCI supper sharding key descriptor + const char *releaseString; // cached release string or NULL + uint32_t releaseStringLength; // cached release string length or 0 + void *rawTDO; // cached RAW TDO + dpiVersionInfo versionInfo; // Oracle database version info + uint32_t commitMode; // commit mode (for two-phase commits) + uint16_t charsetId; // database character set ID + dpiHandleList *openStmts; // list of statements created + dpiHandleList *openLobs; // list of LOBs created + dpiHandleList *objects; // list of objects created + int externalHandle; // OCI handle provided directly? + int deadSession; // dead session (drop from pool)? + int standalone; // standalone connection (not pooled)? + int closing; // connection is being closed? +}; + +// represents the context in which all activity in the library takes place; the +// implementation for this is found in the file dpiContext.c; the minor +// version of the calling application is retained in order to adjust as needed +// for differing sizes of public structures +struct dpiContext { + dpiType_HEAD + dpiVersionInfo *versionInfo; // OCI client version info + uint8_t dpiMinorVersion; // ODPI-C minor version of application +}; + +// represents statements of all types (queries, DML, DDL, PL/SQL) and is +// exposed publicly as a handle of type DPI_HTYPE_STMT; the implementation for +// this is found in the file dpiStmt.c +struct dpiStmt { + dpiType_HEAD + dpiConn *conn; // connection which created this + uint32_t openSlotNum; // slot in connection handle list + void *handle; // OCI statement handle + dpiStmt *parentStmt; // parent statement (implicit results) + uint32_t fetchArraySize; // rows to fetch each time + uint32_t bufferRowCount; // number of rows in fetch buffers + uint32_t bufferRowIndex; // index into buffers for current row + uint32_t numQueryVars; // number of query variables + dpiVar **queryVars; // array of query variables + dpiQueryInfo *queryInfo; // array of query metadata + uint32_t allocatedBindVars; // number of allocated bind variables + uint32_t numBindVars; // actual nubmer of bind variables + dpiBindVar *bindVars; // array of bind variables + uint32_t numBatchErrors; // number of batch errors + dpiErrorBuffer *batchErrors; // array of batch errors + uint64_t rowCount; // rows affected or rows fetched so far + uint64_t bufferMinRow; // row num of first row in buffers + uint16_t statementType; // type of statement + dpiRowid *lastRowid; // rowid of last affected row + int isOwned; // owned by structure? + int hasRowsToFetch; // potentially more rows to fetch? + int scrollable; // scrollable cursor? + int isReturning; // statement has RETURNING clause? + int deleteFromCache; // drop from statement cache on close? + int closing; // statement is being closed? +}; + +// represents memory areas used for transferring data to and from the database +// and is exposed publicly as a handle of type DPI_HTYPE_VAR; the +// implementation for this is found in the file dpiVar.c; variables can be +// bound to a statement or fetched into by a statement +struct dpiVar { + dpiType_HEAD + dpiConn *conn; // connection which created this + const dpiOracleType *type; // type of data contained in variable + dpiNativeTypeNum nativeTypeNum; // native (C) type of data + int requiresPreFetch; // requires prefetch processing? + int isArray; // is an index-by table (array)? + uint32_t sizeInBytes; // size in bytes of each row + int isDynamic; // dynamically bound or defined? + dpiObjectType *objectType; // object type (or NULL) + dpiVarBuffer buffer; // main buffer for data + dpiVarBuffer *dynBindBuffers; // array of buffers (DML returning) + dpiError *error; // error (only for dynamic bind/define) +}; + +// represents large objects (CLOB, BLOB, NCLOB and BFILE) and is exposed +// publicly as a handle of type DPI_HTYPE_LOB; the implementation for this is +// found in the file dpiLob.c +struct dpiLob { + dpiType_HEAD + dpiConn *conn; // connection which created this + uint32_t openSlotNum; // slot in connection handle list + const dpiOracleType *type; // type of LOB + void *locator; // OCI LOB locator descriptor + char *buffer; // stores dir alias/name for BFILE + int closing; // is LOB being closed? +}; + +// represents object attributes of the types created by the SQL command CREATE +// OR REPLACE TYPE and is exposed publicly as a handle of type +// DPI_HTYPE_OBJECT_ATTR; the implementation for this is found in the file +// dpiObjectAttr.c +struct dpiObjectAttr { + dpiType_HEAD + dpiObjectType *belongsToType; // type attribute belongs to + const char *name; // name of attribute (CHAR encoding) + uint32_t nameLength; // length of name of attribute + dpiDataTypeInfo typeInfo; // attribute data type info +}; + +// represents types created by the SQL command CREATE OR REPLACE TYPE and is +// exposed publicly as a handle of type DPI_HTYPE_OBJECT_TYPE; the +// implementation for this is found in the file dpiObjectType.c +struct dpiObjectType { + dpiType_HEAD + dpiConn *conn; // connection which created this + void *tdo; // OCI type descriptor object + uint16_t typeCode; // OCI type code + const char *schema; // schema owning type (CHAR encoding) + uint32_t schemaLength; // length of schema owning type + const char *name; // name of type (CHAR encoding) + uint32_t nameLength; // length of name of type + dpiDataTypeInfo elementTypeInfo; // type info of elements of collection + int isCollection; // is type a collection? + uint16_t numAttributes; // number of attributes type has +}; + +// represents objects of the types created by the SQL command CREATE OR REPLACE +// TYPE and is exposed publicly as a handle of type DPI_HTYPE_OBJECT; the +// implementation for this is found in the file dpiObject.c +struct dpiObject { + dpiType_HEAD + dpiObjectType *type; // type of object + uint32_t openSlotNum; // slot in connection handle list + void *instance; // OCI instance + void *indicator; // OCI indicator + dpiObject *dependsOnObj; // extracted from parent obj, or NULL + int freeIndicator; // should indicator be freed? + int closing; // is object being closed? +}; + +// represents the unique identifier of a row in Oracle Database and is exposed +// publicly as a handle of type DPI_HTYPE_ROWID; the implementation for this is +// found in the file dpiRowid.c +struct dpiRowid { + dpiType_HEAD + void *handle; // OCI rowid descriptor + char *buffer; // cached string rep (or NULL) + uint16_t bufferLength; // length of string rep (or 0) +}; + +// represents a subscription to events such as continuous query notification +// (CQN) and object change notification and is exposed publicly as a handle of +// type DPI_HTYPE_SUBSCR; the implementation for this is found in the file +// dpiSubscr.c +struct dpiSubscr { + dpiType_HEAD + dpiConn *conn; // connection which created this + void *handle; // OCI subscription handle + dpiMutexType mutex; // enables thread safety + dpiSubscrNamespace subscrNamespace; // OCI namespace + dpiSubscrQOS qos; // quality of service flags + dpiSubscrCallback callback; // callback when event is propagated + void *callbackContext; // context pointer for callback + int clientInitiated; // client initiated? + int registered; // registered with database? +}; + +// represents the available options for dequeueing messages when using advanced +// queueing and is exposed publicly as a handle of type DPI_HTYPE_DEQ_OPTIONS; +// the implementation for this is found in dpiDeqOptions.c +struct dpiDeqOptions { + dpiType_HEAD + dpiConn *conn; // connection which created this + void *handle; // OCI dequeue options handle +}; + +// represents the available options for enqueueing messages when using advanced +// queueing and is exposed publicly as a handle of type DPI_HTYPE_ENQ_OPTIONS; +// the implementation for this is found in dpiEnqOptions.c +struct dpiEnqOptions { + dpiType_HEAD + dpiConn *conn; // connection which created this + void *handle; // OCI enqueue options handle +}; + +// represents the available properties for messages when using advanced queuing +// and is exposed publicly as a handle of type DPI_HTYPE_MSG_PROPS; the +// implementation for this is found in the file dpiMsgProps.c +struct dpiMsgProps { + dpiType_HEAD + dpiConn *conn; // connection which created this + void *handle; // OCI message properties handle + dpiObject *payloadObj; // payload (object) + void *payloadRaw; // payload (RAW) + void *msgIdRaw; // message ID (RAW) +}; + +// represents SODA collections and is exposed publicly as a handle of type +// DPI_HTYPE_SODA_COLL; the implementation for this is found in the file +// dpiSodaColl.c +struct dpiSodaColl { + dpiType_HEAD + dpiSodaDb *db; // database which created this + void *handle; // OCI SODA collection handle + int binaryContent; // content stored in BLOB? +}; + +// represents cursors that iterate over SODA collections and is exposed +// publicly as a handle of type DPI_HTYPE_SODA_COLL_CURSOR; the implementation +// for this is found in the file dpiSodaCollCursor.c +struct dpiSodaCollCursor { + dpiType_HEAD + dpiSodaDb *db; // database which created this + void *handle; // OCI SODA collection cursor handle +}; + +// represents a SODA database (contains SODA collections) and is exposed +// publicly as a handle of type DPI_HTYPE_SODA_DB; the implementation for this +// is found in the file dpiSodaDb.c +struct dpiSodaDb { + dpiType_HEAD + dpiConn *conn; // connection which created this +}; + +// represents a SODA document and is exposed publicly as a handle of type +// DPI_HTYPE_SODA_DOC; the implementation for this is found in the file +// dpiSodaDoc.c +struct dpiSodaDoc { + dpiType_HEAD + dpiSodaDb *db; // database which created this + void *handle; // OCI SODA document handle + int binaryContent; // binary content? +}; + +// represents a SODA document cursor and is exposed publicly as a handle of +// type DPI_HTYPE_SODA_DOC_CURSOR; the implementation for this is found in the +// file dpiSodaDocCursor.c +struct dpiSodaDocCursor { + dpiType_HEAD + dpiSodaColl *coll; // collection which created this + void *handle; // OCI SODA document cursor handle +}; + +// represents a queue used in AQ (advanced queuing) and is exposed publicly as +// a handle of type DPI_HTYPE_QUEUE; the implementation for this is found in +// the file dpiQueue.c +struct dpiQueue { + dpiType_HEAD + dpiConn *conn; // connection which created this + const char *name; // name of the queue (NULL-terminated) + dpiObjectType *payloadType; // object type (for object payloads) + dpiDeqOptions *deqOptions; // dequeue options + dpiEnqOptions *enqOptions; // enqueue options + dpiQueueBuffer buffer; // buffer area +}; + + +//----------------------------------------------------------------------------- +// definition of internal dpiContext methods +//----------------------------------------------------------------------------- +void dpiContext__initCommonCreateParams(dpiCommonCreateParams *params); +void dpiContext__initConnCreateParams(dpiConnCreateParams *params); +void dpiContext__initPoolCreateParams(dpiPoolCreateParams *params); +void dpiContext__initSodaOperOptions(dpiSodaOperOptions *options); +void dpiContext__initSubscrCreateParams(dpiSubscrCreateParams *params); + + +//----------------------------------------------------------------------------- +// definition of internal dpiDataBuffer methods +//----------------------------------------------------------------------------- +int dpiDataBuffer__fromOracleDate(dpiDataBuffer *data, + dpiOciDate *oracleValue); +int dpiDataBuffer__fromOracleDateAsDouble(dpiDataBuffer *data, + dpiEnv *env, dpiError *error, dpiOciDate *oracleValue); +int dpiDataBuffer__fromOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue); +int dpiDataBuffer__fromOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue); +int dpiDataBuffer__fromOracleNumberAsDouble(dpiDataBuffer *data, + dpiError *error, void *oracleValue); +int dpiDataBuffer__fromOracleNumberAsInteger(dpiDataBuffer *data, + dpiError *error, void *oracleValue); +int dpiDataBuffer__fromOracleNumberAsText(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue); +int dpiDataBuffer__fromOracleNumberAsUnsignedInteger(dpiDataBuffer *data, + dpiError *error, void *oracleValue); +int dpiDataBuffer__fromOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue, int withTZ); +int dpiDataBuffer__fromOracleTimestampAsDouble(dpiDataBuffer *data, + dpiEnv *env, dpiError *error, void *oracleValue); +int dpiDataBuffer__toOracleDate(dpiDataBuffer *data, dpiOciDate *oracleValue); +int dpiDataBuffer__toOracleDateFromDouble(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, dpiOciDate *oracleValue); +int dpiDataBuffer__toOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue); +int dpiDataBuffer__toOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue); +int dpiDataBuffer__toOracleNumberFromDouble(dpiDataBuffer *data, + dpiError *error, void *oracleValue); +int dpiDataBuffer__toOracleNumberFromInteger(dpiDataBuffer *data, + dpiError *error, void *oracleValue); +int dpiDataBuffer__toOracleNumberFromText(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue); +int dpiDataBuffer__toOracleNumberFromUnsignedInteger(dpiDataBuffer *data, + dpiError *error, void *oracleValue); +int dpiDataBuffer__toOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, + dpiError *error, void *oracleValue, int withTZ); +int dpiDataBuffer__toOracleTimestampFromDouble(dpiDataBuffer *data, + dpiEnv *env, dpiError *error, void *oracleValue); + + +//----------------------------------------------------------------------------- +// definition of internal dpiEnv methods +//----------------------------------------------------------------------------- +void dpiEnv__free(dpiEnv *env, dpiError *error); +int dpiEnv__init(dpiEnv *env, const dpiContext *context, + const dpiCommonCreateParams *params, void *externalHandle, + dpiError *error); +int dpiEnv__getEncodingInfo(dpiEnv *env, dpiEncodingInfo *info); + + +//----------------------------------------------------------------------------- +// definition of internal dpiError methods +//----------------------------------------------------------------------------- +int dpiError__getInfo(dpiError *error, dpiErrorInfo *info); +int dpiError__initHandle(dpiError *error); +int dpiError__set(dpiError *error, const char *context, dpiErrorNum errorNum, + ...); +int dpiError__setFromOCI(dpiError *error, int status, dpiConn *conn, + const char *action); + + +//----------------------------------------------------------------------------- +// definition of internal dpiGen methods +//----------------------------------------------------------------------------- +int dpiGen__addRef(void *ptr, dpiHandleTypeNum typeNum, const char *fnName); +int dpiGen__allocate(dpiHandleTypeNum typeNum, dpiEnv *env, void **handle, + dpiError *error); +int dpiGen__checkHandle(const void *ptr, dpiHandleTypeNum typeNum, + const char *context, dpiError *error); +int dpiGen__endPublicFn(const void *ptr, int returnValue, dpiError *error); +int dpiGen__release(void *ptr, dpiHandleTypeNum typeNum, const char *fnName); +void dpiGen__setRefCount(void *ptr, dpiError *error, int increment); +int dpiGen__startPublicFn(const void *ptr, dpiHandleTypeNum typeNum, + const char *fnName, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiGlobal methods +//----------------------------------------------------------------------------- +int dpiGlobal__initError(const char *fnName, dpiError *error); +int dpiGlobal__lookupCharSet(const char *name, uint16_t *charsetId, + dpiError *error); +int dpiGlobal__lookupEncoding(uint16_t charsetId, char *encoding, + dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiOracleType methods +//----------------------------------------------------------------------------- +const dpiOracleType *dpiOracleType__getFromNum(dpiOracleTypeNum oracleTypeNum, + dpiError *error); +int dpiOracleType__populateTypeInfo(dpiConn *conn, void *handle, + uint32_t handleType, dpiDataTypeInfo *info, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiConn methods +//----------------------------------------------------------------------------- +int dpiConn__checkConnected(dpiConn *conn, dpiError *error); +int dpiConn__create(dpiConn *conn, const dpiContext *context, + const char *userName, uint32_t userNameLength, const char *password, + uint32_t passwordLength, const char *connectString, + uint32_t connectStringLength, dpiPool *pool, + const dpiCommonCreateParams *commonParams, + dpiConnCreateParams *createParams, dpiError *error); +void dpiConn__free(dpiConn *conn, dpiError *error); +int dpiConn__getRawTDO(dpiConn *conn, dpiError *error); +int dpiConn__getServerVersion(dpiConn *conn, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiPool methods +//----------------------------------------------------------------------------- +int dpiPool__acquireConnection(dpiPool *pool, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + dpiConnCreateParams *params, dpiConn **conn, dpiError *error); +void dpiPool__free(dpiPool *pool, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiStmt methods +//----------------------------------------------------------------------------- +int dpiStmt__allocate(dpiConn *conn, int scrollable, dpiStmt **stmt, + dpiError *error); +int dpiStmt__close(dpiStmt *stmt, const char *tag, uint32_t tagLength, + int propagateErrors, dpiError *error); +void dpiStmt__free(dpiStmt *stmt, dpiError *error); +int dpiStmt__init(dpiStmt *stmt, dpiError *error); +int dpiStmt__prepare(dpiStmt *stmt, const char *sql, uint32_t sqlLength, + const char *tag, uint32_t tagLength, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiVar methods +//----------------------------------------------------------------------------- +int dpiVar__allocate(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, + dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, + int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, + dpiData **data, dpiError *error); +int dpiVar__convertToLob(dpiVar *var, dpiError *error); +int dpiVar__copyData(dpiVar *var, uint32_t pos, dpiData *sourceData, + dpiError *error); +int32_t dpiVar__defineCallback(dpiVar *var, void *defnp, uint32_t iter, + void **bufpp, uint32_t **alenpp, uint8_t *piecep, void **indpp, + uint16_t **rcodepp); +int dpiVar__extendedPreFetch(dpiVar *var, dpiVarBuffer *buffer, + dpiError *error); +void dpiVar__free(dpiVar *var, dpiError *error); +int32_t dpiVar__inBindCallback(dpiVar *var, void *bindp, uint32_t iter, + uint32_t index, void **bufpp, uint32_t *alenp, uint8_t *piecep, + void **indpp); +int dpiVar__getValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, + int inFetch, dpiError *error); +int dpiVar__setValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, + dpiData *data, dpiError *error); +int32_t dpiVar__outBindCallback(dpiVar *var, void *bindp, uint32_t iter, + uint32_t index, void **bufpp, uint32_t **alenpp, uint8_t *piecep, + void **indpp, uint16_t **rcodepp); + + +//----------------------------------------------------------------------------- +// definition of internal dpiLob methods +//----------------------------------------------------------------------------- +int dpiLob__allocate(dpiConn *conn, const dpiOracleType *type, dpiLob **lob, + dpiError *error); +int dpiLob__close(dpiLob *lob, int propagateErrors, dpiError *error); +void dpiLob__free(dpiLob *lob, dpiError *error); +int dpiLob__readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, + char *value, uint64_t *valueLength, dpiError *error); +int dpiLob__setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength, + dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiObject methods +//----------------------------------------------------------------------------- +int dpiObject__allocate(dpiObjectType *objType, void *instance, + void *indicator, dpiObject *dependsOnObj, dpiObject **obj, + dpiError *error); +int dpiObject__close(dpiObject *obj, int propagateErrors, dpiError *error); +void dpiObject__free(dpiObject *obj, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiObjectType methods +//----------------------------------------------------------------------------- +int dpiObjectType__allocate(dpiConn *conn, void *param, + uint32_t nameAttribute, dpiObjectType **objType, dpiError *error); +void dpiObjectType__free(dpiObjectType *objType, dpiError *error); +int dpiObjectType__isXmlType(dpiObjectType *objType); + + +//----------------------------------------------------------------------------- +// definition of internal dpiObjectAttr methods +//----------------------------------------------------------------------------- +int dpiObjectAttr__allocate(dpiObjectType *objType, void *param, + dpiObjectAttr **attr, dpiError *error); +int dpiObjectAttr__check(dpiObjectAttr *attr, dpiError *error); +void dpiObjectAttr__free(dpiObjectAttr *attr, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiRowid methods +//----------------------------------------------------------------------------- +int dpiRowid__allocate(dpiConn *conn, dpiRowid **rowid, dpiError *error); +void dpiRowid__free(dpiRowid *rowid, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiSubscr methods +//----------------------------------------------------------------------------- +void dpiSubscr__free(dpiSubscr *subscr, dpiError *error); +int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn, + dpiSubscrCreateParams *params, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiDeqOptions methods +//----------------------------------------------------------------------------- +int dpiDeqOptions__create(dpiDeqOptions *options, dpiConn *conn, + dpiError *error); +void dpiDeqOptions__free(dpiDeqOptions *options, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiEnqOptions methods +//----------------------------------------------------------------------------- +int dpiEnqOptions__create(dpiEnqOptions *options, dpiConn *conn, + dpiError *error); +void dpiEnqOptions__free(dpiEnqOptions *options, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiSodaColl methods +//----------------------------------------------------------------------------- +int dpiSodaColl__allocate(dpiSodaDb *db, void *handle, dpiSodaColl **coll, + dpiError *error); +void dpiSodaColl__free(dpiSodaColl *coll, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiSodaCollCursor methods +//----------------------------------------------------------------------------- +int dpiSodaCollCursor__allocate(dpiSodaDb *db, void *handle, + dpiSodaCollCursor **cursor, dpiError *error); +void dpiSodaCollCursor__free(dpiSodaCollCursor *cursor, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiSodaDb methods +//----------------------------------------------------------------------------- +void dpiSodaDb__free(dpiSodaDb *db, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiSodaDoc methods +//----------------------------------------------------------------------------- +int dpiSodaDoc__allocate(dpiSodaDb *db, void *handle, dpiSodaDoc **doc, + dpiError *error); +void dpiSodaDoc__free(dpiSodaDoc *doc, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiSodaDocCursor methods +//----------------------------------------------------------------------------- +int dpiSodaDocCursor__allocate(dpiSodaColl *coll, void *handle, + dpiSodaDocCursor **cursor, dpiError *error); +void dpiSodaDocCursor__free(dpiSodaDocCursor *cursor, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiQueue methods +//----------------------------------------------------------------------------- +int dpiQueue__allocate(dpiConn *conn, const char *name, uint32_t nameLength, + dpiObjectType *payloadType, dpiQueue **queue, dpiError *error); +void dpiQueue__free(dpiQueue *queue, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiOci methods +//----------------------------------------------------------------------------- +int dpiOci__aqDeq(dpiConn *conn, const char *queueName, void *options, + void *msgProps, void *payloadType, void **payload, void **payloadInd, + void **msgId, dpiError *error); +int dpiOci__aqDeqArray(dpiConn *conn, const char *queueName, void *options, + uint32_t *numIters, void **msgProps, void *payloadType, void **payload, void **payloadInd, void **msgId, dpiError *error); +int dpiOci__aqEnq(dpiConn *conn, const char *queueName, void *options, + void *msgProps, void *payloadType, void **payload, void **payloadInd, + void **msgId, dpiError *error); +int dpiOci__aqEnqArray(dpiConn *conn, const char *queueName, void *options, + uint32_t *numIters, void **msgProps, void *payloadType, void **payload, + void **payloadInd, void **msgId, dpiError *error); +int dpiOci__arrayDescriptorAlloc(void *envHandle, void **handle, + uint32_t handleType, uint32_t arraySize, dpiError *error); +int dpiOci__arrayDescriptorFree(void **handle, uint32_t handleType); +int dpiOci__attrGet(const void *handle, uint32_t handleType, void *ptr, + uint32_t *size, uint32_t attribute, const char *action, + dpiError *error); +int dpiOci__attrSet(void *handle, uint32_t handleType, void *ptr, + uint32_t size, uint32_t attribute, const char *action, + dpiError *error); +int dpiOci__bindByName(dpiStmt *stmt, void **bindHandle, const char *name, + int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error); +int dpiOci__bindByName2(dpiStmt *stmt, void **bindHandle, const char *name, + int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error); +int dpiOci__bindByPos(dpiStmt *stmt, void **bindHandle, uint32_t pos, + int dynamicBind, dpiVar *var, dpiError *error); +int dpiOci__bindByPos2(dpiStmt *stmt, void **bindHandle, uint32_t pos, + int dynamicBind, dpiVar *var, dpiError *error); +int dpiOci__bindDynamic(dpiVar *var, void *bindHandle, dpiError *error); +int dpiOci__bindObject(dpiVar *var, void *bindHandle, dpiError *error); +int dpiOci__break(dpiConn *conn, dpiError *error); +void dpiOci__clientVersion(dpiContext *context); +int dpiOci__collAppend(dpiConn *conn, const void *elem, const void *elemInd, + void *coll, dpiError *error); +int dpiOci__collAssignElem(dpiConn *conn, int32_t index, const void *elem, + const void *elemInd, void *coll, dpiError *error); +int dpiOci__collGetElem(dpiConn *conn, void *coll, int32_t index, int *exists, + void **elem, void **elemInd, dpiError *error); +int dpiOci__collSize(dpiConn *conn, void *coll, int32_t *size, + dpiError *error); +int dpiOci__collTrim(dpiConn *conn, uint32_t numToTrim, void *coll, + dpiError *error); +int dpiOci__contextGetValue(dpiConn *conn, const char *key, uint32_t keyLength, + void **value, int checkError, dpiError *error); +int dpiOci__contextSetValue(dpiConn *conn, const char *key, uint32_t keyLength, + void *value, int checkError, dpiError *error); +int dpiOci__dateTimeConstruct(void *envHandle, void *handle, int16_t year, + uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, + uint8_t second, uint32_t fsecond, const char *tz, size_t tzLength, + dpiError *error); +int dpiOci__dateTimeConvert(void *envHandle, void *inDate, void *outDate, + dpiError *error); +int dpiOci__dateTimeGetDate(void *envHandle, void *handle, int16_t *year, + uint8_t *month, uint8_t *day, dpiError *error); +int dpiOci__dateTimeGetTime(void *envHandle, void *handle, uint8_t *hour, + uint8_t *minute, uint8_t *second, uint32_t *fsecond, dpiError *error); +int dpiOci__dateTimeGetTimeZoneOffset(void *envHandle, void *handle, + int8_t *tzHourOffset, int8_t *tzMinuteOffset, dpiError *error); +int dpiOci__dateTimeIntervalAdd(void *envHandle, void *handle, void *interval, + void *outHandle, dpiError *error); +int dpiOci__dateTimeSubtract(void *envHandle, void *handle1, void *handle2, + void *interval, dpiError *error); +int dpiOci__dbShutdown(dpiConn *conn, uint32_t mode, dpiError *error); +int dpiOci__dbStartup(dpiConn *conn, uint32_t mode, dpiError *error); +int dpiOci__defineByPos(dpiStmt *stmt, void **defineHandle, uint32_t pos, + dpiVar *var, dpiError *error); +int dpiOci__defineByPos2(dpiStmt *stmt, void **defineHandle, uint32_t pos, + dpiVar *var, dpiError *error); +int dpiOci__defineDynamic(dpiVar *var, void *defineHandle, dpiError *error); +int dpiOci__defineObject(dpiVar *var, void *defineHandle, dpiError *error); +int dpiOci__describeAny(dpiConn *conn, void *obj, uint32_t objLength, + uint8_t objType, void *describeHandle, dpiError *error); +int dpiOci__descriptorAlloc(void *envHandle, void **handle, + const uint32_t handleType, const char *action, dpiError *error); +int dpiOci__descriptorFree(void *handle, uint32_t handleType); +int dpiOci__envNlsCreate(void **envHandle, uint32_t mode, uint16_t charsetId, + uint16_t ncharsetId, dpiError *error); +int dpiOci__errorGet(void *handle, uint32_t handleType, uint16_t charsetId, + const char *action, dpiError *error); +int dpiOci__handleAlloc(void *envHandle, void **handle, uint32_t handleType, + const char *action, dpiError *error); +int dpiOci__handleFree(void *handle, uint32_t handleType); +int dpiOci__intervalGetDaySecond(void *envHandle, int32_t *day, int32_t *hour, + int32_t *minute, int32_t *second, int32_t *fsecond, + const void *interval, dpiError *error); +int dpiOci__intervalGetYearMonth(void *envHandle, int32_t *year, + int32_t *month, const void *interval, dpiError *error); +int dpiOci__intervalSetDaySecond(void *envHandle, int32_t day, int32_t hour, + int32_t minute, int32_t second, int32_t fsecond, void *interval, + dpiError *error); +int dpiOci__intervalSetYearMonth(void *envHandle, int32_t year, int32_t month, + void *interval, dpiError *error); +int dpiOci__lobClose(dpiLob *lob, dpiError *error); +int dpiOci__lobCreateTemporary(dpiLob *lob, dpiError *error); +int dpiOci__lobFileExists(dpiLob *lob, int *exists, dpiError *error); +int dpiOci__lobFileGetName(dpiLob *lob, char *dirAlias, + uint16_t *dirAliasLength, char *name, uint16_t *nameLength, + dpiError *error); +int dpiOci__lobFileSetName(dpiLob *lob, const char *dirAlias, + uint16_t dirAliasLength, const char *name, uint16_t nameLength, + dpiError *error); +int dpiOci__lobFreeTemporary(dpiConn *conn, void *lobLocator, int checkError, + dpiError *error); +int dpiOci__lobGetChunkSize(dpiLob *lob, uint32_t *size, dpiError *error); +int dpiOci__lobGetLength2(dpiLob *lob, uint64_t *size, dpiError *error); +int dpiOci__lobIsOpen(dpiLob *lob, int *isOpen, dpiError *error); +int dpiOci__lobIsTemporary(dpiLob *lob, int *isTemporary, int checkError, + dpiError *error); +int dpiOci__lobLocatorAssign(dpiLob *lob, void **copiedHandle, + dpiError *error); +int dpiOci__lobOpen(dpiLob *lob, dpiError *error); +int dpiOci__lobRead2(dpiLob *lob, uint64_t offset, uint64_t *amountInBytes, + uint64_t *amountInChars, char *buffer, uint64_t bufferLength, + dpiError *error); +int dpiOci__lobTrim2(dpiLob *lob, uint64_t newLength, dpiError *error); +int dpiOci__lobWrite2(dpiLob *lob, uint64_t offset, const char *value, + uint64_t valueLength, dpiError *error); +int dpiOci__memoryAlloc(dpiConn *conn, void **ptr, uint32_t size, + int checkError, dpiError *error); +int dpiOci__memoryFree(dpiConn *conn, void *ptr, dpiError *error); +int dpiOci__nlsCharSetConvert(void *envHandle, uint16_t destCharsetId, + char *dest, size_t destLength, uint16_t sourceCharsetId, + const char *source, size_t sourceLength, size_t *resultSize, + dpiError *error); +int dpiOci__nlsCharSetIdToName(void *envHandle, char *buf, size_t bufLength, + uint16_t charsetId, dpiError *error); +int dpiOci__nlsCharSetNameToId(void *envHandle, const char *name, + uint16_t *charsetId, dpiError *error); +int dpiOci__nlsEnvironmentVariableGet(uint16_t item, void *value, + dpiError *error); +int dpiOci__nlsNameMap(void *envHandle, char *buf, size_t bufLength, + const char *source, uint32_t flag, dpiError *error); +int dpiOci__nlsNumericInfoGet(void *envHandle, int32_t *value, uint16_t item, + dpiError *error); +int dpiOci__numberFromInt(const void *value, unsigned int valueLength, + unsigned int flags, void *number, dpiError *error); +int dpiOci__numberFromReal(const double value, void *number, dpiError *error); +int dpiOci__numberToInt(void *number, void *value, unsigned int valueLength, + unsigned int flags, dpiError *error); +int dpiOci__numberToReal(double *value, void *number, dpiError *error); +int dpiOci__objectCopy(dpiObject *obj, void *sourceInstance, + void *sourceIndicator, dpiError *error); +int dpiOci__objectFree(void *envHandle, void *data, int checkError, + dpiError *error); +int dpiOci__objectGetAttr(dpiObject *obj, dpiObjectAttr *attr, + int16_t *scalarValueIndicator, void **valueIndicator, void **value, + void **tdo, dpiError *error); +int dpiOci__objectGetInd(dpiObject *obj, dpiError *error); +int dpiOci__objectNew(dpiObject *obj, dpiError *error); +int dpiOci__objectPin(void *envHandle, void *objRef, void **obj, + dpiError *error); +int dpiOci__objectSetAttr(dpiObject *obj, dpiObjectAttr *attr, + int16_t scalarValueIndicator, void *valueIndicator, const void *value, + dpiError *error); +int dpiOci__paramGet(const void *handle, uint32_t handleType, void **parameter, + uint32_t pos, const char *action, dpiError *error); +int dpiOci__passwordChange(dpiConn *conn, const char *userName, + uint32_t userNameLength, const char *oldPassword, + uint32_t oldPasswordLength, const char *newPassword, + uint32_t newPasswordLength, uint32_t mode, dpiError *error); +int dpiOci__ping(dpiConn *conn, dpiError *error); +int dpiOci__rawAssignBytes(void *envHandle, const char *value, + uint32_t valueLength, void **handle, dpiError *error); +int dpiOci__rawPtr(void *envHandle, void *handle, void **ptr); +int dpiOci__rawResize(void *envHandle, void **handle, uint32_t newSize, + dpiError *error); +int dpiOci__rawSize(void *envHandle, void *handle, uint32_t *size); +int dpiOci__rowidToChar(dpiRowid *rowid, char *buffer, uint16_t *bufferSize, + dpiError *error); +int dpiOci__serverAttach(dpiConn *conn, const char *connectString, + uint32_t connectStringLength, dpiError *error); +int dpiOci__serverDetach(dpiConn *conn, int checkError, dpiError *error); +int dpiOci__serverRelease(dpiConn *conn, char *buffer, uint32_t bufferSize, + uint32_t *version, dpiError *error); +int dpiOci__sessionBegin(dpiConn *conn, uint32_t credentialType, + uint32_t mode, dpiError *error); +int dpiOci__sessionEnd(dpiConn *conn, int checkError, dpiError *error); +int dpiOci__sessionGet(void *envHandle, void **handle, void *authInfo, + const char *connectString, uint32_t connectStringLength, + const char *tag, uint32_t tagLength, const char **outTag, + uint32_t *outTagLength, int *found, uint32_t mode, dpiError *error); +int dpiOci__sessionPoolCreate(dpiPool *pool, const char *connectString, + uint32_t connectStringLength, uint32_t minSessions, + uint32_t maxSessions, uint32_t sessionIncrement, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + uint32_t mode, dpiError *error); +int dpiOci__sessionPoolDestroy(dpiPool *pool, uint32_t mode, int checkError, + dpiError *error); +int dpiOci__sessionRelease(dpiConn *conn, const char *tag, uint32_t tagLength, + uint32_t mode, int checkError, dpiError *error); +int dpiOci__shardingKeyColumnAdd(void *shardingKey, void *col, uint32_t colLen, + uint16_t colType, dpiError *error); +int dpiOci__sodaBulkInsert(dpiSodaColl *coll, void **documents, + uint32_t numDocuments, void *outputOptions, uint32_t mode, + dpiError *error); +int dpiOci__sodaBulkInsertAndGet(dpiSodaColl *coll, void **documents, + uint32_t numDocuments, void *outputOptions, uint32_t mode, + dpiError *error); +int dpiOci__sodaCollCreateWithMetadata(dpiSodaDb *db, const char *name, + uint32_t nameLength, const char *metadata, uint32_t metadataLength, + uint32_t mode, void **handle, dpiError *error); +int dpiOci__sodaCollDrop(dpiSodaColl *coll, int *isDropped, uint32_t mode, + dpiError *error); +int dpiOci__sodaCollGetNext(dpiConn *conn, void *cursorHandle, + void **collectionHandle, uint32_t mode, dpiError *error); +int dpiOci__sodaCollList(dpiSodaDb *db, const char *startingName, + uint32_t startingNameLength, void **handle, uint32_t mode, + dpiError *error); +int dpiOci__sodaCollOpen(dpiSodaDb *db, const char *name, uint32_t nameLength, + uint32_t mode, void **handle, dpiError *error); +int dpiOci__sodaDataGuideGet(dpiSodaColl *coll, void **handle, uint32_t mode, + dpiError *error); +int dpiOci__sodaDocCount(dpiSodaColl *coll, void *options, uint32_t mode, + uint64_t *count, dpiError *error); +int dpiOci__sodaDocGetNext(dpiSodaDocCursor *cursor, void **handle, + uint32_t mode, dpiError *error); +int dpiOci__sodaFind(dpiSodaColl *coll, const void *options, uint32_t flags, + uint32_t mode, void **handle, dpiError *error); +int dpiOci__sodaFindOne(dpiSodaColl *coll, const void *options, uint32_t flags, + uint32_t mode, void **handle, dpiError *error); +int dpiOci__sodaIndexCreate(dpiSodaColl *coll, const char *indexSpec, + uint32_t indexSpecLength, uint32_t mode, dpiError *error); +int dpiOci__sodaIndexDrop(dpiSodaColl *coll, const char *name, + uint32_t nameLength, uint32_t mode, int *isDropped, dpiError *error); +int dpiOci__sodaInsert(dpiSodaColl *coll, void *handle, uint32_t mode, + dpiError *error); +int dpiOci__sodaInsertAndGet(dpiSodaColl *coll, void **handle, uint32_t mode, + dpiError *error); +int dpiOci__sodaOperKeysSet(const dpiSodaOperOptions *options, void *handle, + dpiError *error); +int dpiOci__sodaRemove(dpiSodaColl *coll, void *options, uint32_t mode, + uint64_t *count, dpiError *error); +int dpiOci__sodaReplOne(dpiSodaColl *coll, const void *options, void *handle, + uint32_t mode, int *isReplaced, dpiError *error); +int dpiOci__sodaReplOneAndGet(dpiSodaColl *coll, const void *options, + void **handle, uint32_t mode, int *isReplaced, dpiError *error); +int dpiOci__sodaSave(dpiSodaColl *coll, void *handle, uint32_t mode, + dpiError *error); +int dpiOci__sodaSaveAndGet(dpiSodaColl *coll, void **handle, uint32_t mode, + dpiError *error); +int dpiOci__stmtExecute(dpiStmt *stmt, uint32_t numIters, uint32_t mode, + dpiError *error); +int dpiOci__stmtFetch2(dpiStmt *stmt, uint32_t numRows, uint16_t fetchMode, + int32_t offset, dpiError *error); +int dpiOci__stmtGetBindInfo(dpiStmt *stmt, uint32_t size, uint32_t startLoc, + int32_t *numFound, char *names[], uint8_t nameLengths[], + char *indNames[], uint8_t indNameLengths[], uint8_t isDuplicate[], + void *bindHandles[], dpiError *error); +int dpiOci__stmtGetNextResult(dpiStmt *stmt, void **handle, dpiError *error); +int dpiOci__stmtPrepare2(dpiStmt *stmt, const char *sql, uint32_t sqlLength, + const char *tag, uint32_t tagLength, dpiError *error); +int dpiOci__stmtRelease(dpiStmt *stmt, const char *tag, uint32_t tagLength, + int checkError, dpiError *error); +int dpiOci__stringAssignText(void *envHandle, const char *value, + uint32_t valueLength, void **handle, dpiError *error); +int dpiOci__stringPtr(void *envHandle, void *handle, char **ptr); +int dpiOci__stringResize(void *envHandle, void **handle, uint32_t newSize, + dpiError *error); +int dpiOci__stringSize(void *envHandle, void *handle, uint32_t *size); +int dpiOci__subscriptionRegister(dpiConn *conn, void **handle, uint32_t mode, + dpiError *error); +int dpiOci__subscriptionUnRegister(dpiConn *conn, dpiSubscr *subscr, + dpiError *error); +int dpiOci__tableDelete(dpiObject *obj, int32_t index, dpiError *error); +int dpiOci__tableExists(dpiObject *obj, int32_t index, int *exists, + dpiError *error); +int dpiOci__tableFirst(dpiObject *obj, int32_t *index, dpiError *error); +int dpiOci__tableLast(dpiObject *obj, int32_t *index, dpiError *error); +int dpiOci__tableNext(dpiObject *obj, int32_t index, int32_t *nextIndex, + int *exists, dpiError *error); +int dpiOci__tablePrev(dpiObject *obj, int32_t index, int32_t *prevIndex, + int *exists, dpiError *error); +int dpiOci__tableSize(dpiObject *obj, int32_t *size, dpiError *error); +int dpiOci__threadKeyDestroy(void *envHandle, void *errorHandle, void **key, + dpiError *error); +int dpiOci__threadKeyGet(void *envHandle, void *errorHandle, void *key, + void **value, dpiError *error); +int dpiOci__threadKeyInit(void *envHandle, void *errorHandle, void **key, + void *destroyFunc, dpiError *error); +int dpiOci__threadKeySet(void *envHandle, void *errorHandle, void *key, + void *value, dpiError *error); +int dpiOci__transCommit(dpiConn *conn, uint32_t flags, dpiError *error); +int dpiOci__transPrepare(dpiConn *conn, int *commitNeeded, dpiError *error); +int dpiOci__transRollback(dpiConn *conn, int checkError, dpiError *error); +int dpiOci__transStart(dpiConn *conn, dpiError *error); +int dpiOci__typeByFullName(dpiConn *conn, const char *name, + uint32_t nameLength, void **tdo, dpiError *error); +int dpiOci__typeByName(dpiConn *conn, const char *schema, + uint32_t schemaLength, const char *name, uint32_t nameLength, + void **tdo, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiMsgProps methods +//----------------------------------------------------------------------------- +int dpiMsgProps__allocate(dpiConn *conn, dpiMsgProps **props, dpiError *error); +void dpiMsgProps__extractMsgId(dpiMsgProps *props, const char **msgId, + uint32_t *msgIdLength); +void dpiMsgProps__free(dpiMsgProps *props, dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiHandlePool methods +//----------------------------------------------------------------------------- +int dpiHandlePool__acquire(dpiHandlePool *pool, void **handle, + dpiError *error); +int dpiHandlePool__create(dpiHandlePool **pool, dpiError *error); +void dpiHandlePool__free(dpiHandlePool *pool); +void dpiHandlePool__release(dpiHandlePool *pool, void **handle); + + +//----------------------------------------------------------------------------- +// definition of internal dpiHandleList methods +//----------------------------------------------------------------------------- +int dpiHandleList__addHandle(dpiHandleList *list, void *handle, + uint32_t *slotNum, dpiError *error); +int dpiHandleList__create(dpiHandleList **list, dpiError *error); +void dpiHandleList__free(dpiHandleList *list); +void dpiHandleList__removeHandle(dpiHandleList *list, uint32_t slotNum); + + +//----------------------------------------------------------------------------- +// definition of internal dpiUtils methods +//----------------------------------------------------------------------------- +int dpiUtils__allocateMemory(size_t numMembers, size_t memberSize, + int clearMemory, const char *action, void **ptr, dpiError *error); +int dpiUtils__checkClientVersion(dpiVersionInfo *versionInfo, + int minVersionNum, int minReleaseNum, dpiError *error); +int dpiUtils__checkDatabaseVersion(dpiConn *conn, int minVersionNum, + int minReleaseNum, dpiError *error); +void dpiUtils__clearMemory(void *ptr, size_t length); +void dpiUtils__freeMemory(void *ptr); +int dpiUtils__getAttrStringWithDup(const char *action, const void *ociHandle, + uint32_t ociHandleType, uint32_t ociAttribute, const char **value, + uint32_t *valueLength, dpiError *error); +int dpiUtils__parseNumberString(const char *value, uint32_t valueLength, + uint16_t charsetId, int *isNegative, int16_t *decimalPointIndex, + uint8_t *numDigits, uint8_t *digits, dpiError *error); +int dpiUtils__parseOracleNumber(void *oracleValue, int *isNegative, + int16_t *decimalPointIndex, uint8_t *numDigits, uint8_t *digits, + dpiError *error); +int dpiUtils__setAttributesFromCommonCreateParams(void *handle, + uint32_t handleType, const dpiCommonCreateParams *params, + dpiError *error); + + +//----------------------------------------------------------------------------- +// definition of internal dpiDebug methods +//----------------------------------------------------------------------------- +void dpiDebug__initialize(void); +void dpiDebug__print(const char *format, ...); + +#endif diff --git a/vendor/github.com/godror/godror/odpi/src/dpiLob.c b/vendor/github.com/godror/godror/odpi/src/dpiLob.c new file mode 100644 index 00000000000..55dfcebad6e --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiLob.c @@ -0,0 +1,504 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiLob.c +// Implementation of LOB data. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiLob__allocate() [INTERNAL] +// Allocate and initialize LOB object. +//----------------------------------------------------------------------------- +int dpiLob__allocate(dpiConn *conn, const dpiOracleType *type, dpiLob **lob, + dpiError *error) +{ + dpiLob *tempLob; + + if (dpiGen__allocate(DPI_HTYPE_LOB, conn->env, (void**) &tempLob, + error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(conn, error, 1); + tempLob->conn = conn; + tempLob->type = type; + if (dpiOci__descriptorAlloc(conn->env->handle, &tempLob->locator, + DPI_OCI_DTYPE_LOB, "allocate descriptor", error) < 0) { + dpiLob__free(tempLob, error); + return DPI_FAILURE; + } + if (dpiHandleList__addHandle(conn->openLobs, tempLob, + &tempLob->openSlotNum, error) < 0) { + dpiOci__descriptorFree(tempLob->locator, DPI_OCI_DTYPE_LOB); + tempLob->locator = NULL; + dpiLob__free(tempLob, error); + return DPI_FAILURE; + } + + *lob = tempLob; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiLob__check() [INTERNAL] +// Check that the LOB is valid and get an error handle for subsequent calls. +//----------------------------------------------------------------------------- +static int dpiLob__check(dpiLob *lob, const char *fnName, dpiError *error) +{ + if (dpiGen__startPublicFn(lob, DPI_HTYPE_LOB, fnName, error) < 0) + return DPI_FAILURE; + if (!lob->locator) + return dpiError__set(error, "check closed", DPI_ERR_LOB_CLOSED); + return dpiConn__checkConnected(lob->conn, error); +} + + +//----------------------------------------------------------------------------- +// dpiLob__close() [INTERNAL] +// Internal method used for closing the LOB. +//----------------------------------------------------------------------------- +int dpiLob__close(dpiLob *lob, int propagateErrors, dpiError *error) +{ + int isTemporary, closing, status = DPI_SUCCESS; + + // determine whether LOB is already being closed and if not, mark LOB as + // being closed; this MUST be done while holding the lock (if in threaded + // mode) to avoid race conditions! + if (lob->env->threaded) + dpiMutex__acquire(lob->env->mutex); + closing = lob->closing; + lob->closing = 1; + if (lob->env->threaded) + dpiMutex__release(lob->env->mutex); + + // if LOB is already being closed, nothing needs to be done + if (closing) + return DPI_SUCCESS; + + // perform actual work of closing LOB + if (lob->locator) { + if (!lob->conn->deadSession && lob->conn->handle) { + status = dpiOci__lobIsTemporary(lob, &isTemporary, propagateErrors, + error); + if (isTemporary && status == DPI_SUCCESS) + status = dpiOci__lobFreeTemporary(lob->conn, + lob->locator, propagateErrors, error); + } + dpiOci__descriptorFree(lob->locator, DPI_OCI_DTYPE_LOB); + if (!lob->conn->closing) + dpiHandleList__removeHandle(lob->conn->openLobs, lob->openSlotNum); + lob->locator = NULL; + } + if (lob->buffer) { + dpiUtils__freeMemory(lob->buffer); + lob->buffer = NULL; + } + + // if actual close fails, reset closing flag; again, this must be done + // while holding the lock (if in threaded mode) in order to avoid race + // conditions! + if (status < 0) { + if (lob->env->threaded) + dpiMutex__acquire(lob->env->mutex); + lob->closing = 0; + if (lob->env->threaded) + dpiMutex__release(lob->env->mutex); + } + + return status; +} + + +//----------------------------------------------------------------------------- +// dpiLob__free() [INTERNAL] +// Free the memory for a LOB. +//----------------------------------------------------------------------------- +void dpiLob__free(dpiLob *lob, dpiError *error) +{ + dpiLob__close(lob, 0, error); + if (lob->conn) { + dpiGen__setRefCount(lob->conn, error, -1); + lob->conn = NULL; + } + dpiUtils__freeMemory(lob); +} + + +//----------------------------------------------------------------------------- +// dpiLob__readBytes() [INTERNAL] +// Return a portion (or all) of the data in the LOB. +//----------------------------------------------------------------------------- +int dpiLob__readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, + char *value, uint64_t *valueLength, dpiError *error) +{ + uint64_t lengthInBytes = 0, lengthInChars = 0; + int isOpen = 0; + + // amount is in characters for character LOBs and bytes for binary LOBs + if (lob->type->isCharacterData) + lengthInChars = amount; + else lengthInBytes = amount; + + // for files, open the file if needed + if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE) { + if (dpiOci__lobIsOpen(lob, &isOpen, error) < 0) + return DPI_FAILURE; + if (!isOpen) { + if (dpiOci__lobOpen(lob, error) < 0) + return DPI_FAILURE; + } + } + + // read the bytes from the LOB + if (dpiOci__lobRead2(lob, offset, &lengthInBytes, &lengthInChars, + value, *valueLength, error) < 0) + return DPI_FAILURE; + *valueLength = lengthInBytes; + + // if file was opened in this routine, close it again + if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE && !isOpen) { + if (dpiOci__lobClose(lob, error) < 0) + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiLob__setFromBytes() [INTERNAL] +// Clear the LOB completely and then write the specified bytes to it. +//----------------------------------------------------------------------------- +int dpiLob__setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength, + dpiError *error) +{ + if (dpiOci__lobTrim2(lob, 0, error) < 0) + return DPI_FAILURE; + if (valueLength == 0) + return DPI_SUCCESS; + return dpiOci__lobWrite2(lob, 1, value, valueLength, error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_addRef() [PUBLIC] +// Add a reference to the LOB. +//----------------------------------------------------------------------------- +int dpiLob_addRef(dpiLob *lob) +{ + return dpiGen__addRef(lob, DPI_HTYPE_LOB, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiLob_close() [PUBLIC] +// Close the LOB and make it unusable for further operations. +//----------------------------------------------------------------------------- +int dpiLob_close(dpiLob *lob) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + status = dpiLob__close(lob, 1, &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_closeResource() [PUBLIC] +// Close the LOB's resources. +//----------------------------------------------------------------------------- +int dpiLob_closeResource(dpiLob *lob) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + status = dpiOci__lobClose(lob, &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_copy() [PUBLIC] +// Create a copy of the LOB and return it. +//----------------------------------------------------------------------------- +int dpiLob_copy(dpiLob *lob, dpiLob **copiedLob) +{ + dpiLob *tempLob; + dpiError error; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(lob, copiedLob) + if (dpiLob__allocate(lob->conn, lob->type, &tempLob, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + if (dpiOci__lobLocatorAssign(lob, &tempLob->locator, &error) < 0) { + dpiLob__free(tempLob, &error); + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + } + *copiedLob = tempLob; + return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_getBufferSize() [PUBLIC] +// Get the required size of a buffer given the number of characters. If the +// LOB does not refer to a character LOB the value is returned unchanged. +//----------------------------------------------------------------------------- +int dpiLob_getBufferSize(dpiLob *lob, uint64_t sizeInChars, + uint64_t *sizeInBytes) +{ + dpiError error; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(lob, sizeInBytes) + if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_CLOB) + *sizeInBytes = sizeInChars * lob->env->maxBytesPerCharacter; + else if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB) + *sizeInBytes = sizeInChars * lob->env->nmaxBytesPerCharacter; + else *sizeInBytes = sizeInChars; + return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_getChunkSize() [PUBLIC] +// Return the chunk size associated with the LOB. +//----------------------------------------------------------------------------- +int dpiLob_getChunkSize(dpiLob *lob, uint32_t *size) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(lob, size) + status = dpiOci__lobGetChunkSize(lob, size, &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_getDirectoryAndFileName() [PUBLIC] +// Return the directory alias and file name for the BFILE lob. +//----------------------------------------------------------------------------- +int dpiLob_getDirectoryAndFileName(dpiLob *lob, const char **directoryAlias, + uint32_t *directoryAliasLength, const char **fileName, + uint32_t *fileNameLength) +{ + uint16_t ociDirectoryAliasLength, ociFileNameLength; + dpiError error; + + // validate parameters + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(lob, directoryAlias) + DPI_CHECK_PTR_NOT_NULL(lob, directoryAliasLength) + DPI_CHECK_PTR_NOT_NULL(lob, fileName) + DPI_CHECK_PTR_NOT_NULL(lob, fileNameLength) + + // get directory and file name + ociDirectoryAliasLength = 30; + ociFileNameLength = 255; + if (!lob->buffer) { + if (dpiUtils__allocateMemory(1, + ociDirectoryAliasLength + ociFileNameLength, 0, + "allocate name buffer", (void**) &lob->buffer, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + } + *directoryAlias = lob->buffer; + *fileName = lob->buffer + ociDirectoryAliasLength; + if (dpiOci__lobFileGetName(lob, (char*) *directoryAlias, + &ociDirectoryAliasLength, (char*) *fileName, &ociFileNameLength, + &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + *directoryAliasLength = ociDirectoryAliasLength; + *fileNameLength = ociFileNameLength; + return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_getFileExists() [PUBLIC] +// Return whether or not the file pointed to by the locator exists. +//----------------------------------------------------------------------------- +int dpiLob_getFileExists(dpiLob *lob, int *exists) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(lob, exists) + status = dpiOci__lobFileExists(lob, exists, &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_getIsResourceOpen() [PUBLIC] +// Return whether or not the LOB' resources are open. +//----------------------------------------------------------------------------- +int dpiLob_getIsResourceOpen(dpiLob *lob, int *isOpen) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(lob, isOpen) + status = dpiOci__lobIsOpen(lob, isOpen, &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_getSize() [PUBLIC] +// Returns the size of the LOB. +//----------------------------------------------------------------------------- +int dpiLob_getSize(dpiLob *lob, uint64_t *size) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(lob, size) + status = dpiOci__lobGetLength2(lob, size, &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_openResource() [PUBLIC] +// Open the LOB's resources to speed further accesses. +//----------------------------------------------------------------------------- +int dpiLob_openResource(dpiLob *lob) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + status = dpiOci__lobOpen(lob, &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_readBytes() [PUBLIC] +// Return a portion (or all) of the data in the LOB. +//----------------------------------------------------------------------------- +int dpiLob_readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, + char *value, uint64_t *valueLength) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(lob, value) + DPI_CHECK_PTR_NOT_NULL(lob, valueLength) + status = dpiLob__readBytes(lob, offset, amount, value, valueLength, + &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_release() [PUBLIC] +// Release a reference to the LOB. +//----------------------------------------------------------------------------- +int dpiLob_release(dpiLob *lob) +{ + return dpiGen__release(lob, DPI_HTYPE_LOB, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiLob_setDirectoryAndFileName() [PUBLIC] +// Set the directory alias and file name for the BFILE LOB. +//----------------------------------------------------------------------------- +int dpiLob_setDirectoryAndFileName(dpiLob *lob, const char *directoryAlias, + uint32_t directoryAliasLength, const char *fileName, + uint32_t fileNameLength) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(lob, directoryAlias) + DPI_CHECK_PTR_NOT_NULL(lob, fileName) + status = dpiOci__lobFileSetName(lob, directoryAlias, + (uint16_t) directoryAliasLength, fileName, + (uint16_t) fileNameLength, &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_setFromBytes() [PUBLIC] +// Clear the LOB completely and then write the specified bytes to it. +//----------------------------------------------------------------------------- +int dpiLob_setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(lob, value) + status = dpiLob__setFromBytes(lob, value, valueLength, &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_trim() [PUBLIC] +// Trim the LOB to the specified length. +//----------------------------------------------------------------------------- +int dpiLob_trim(dpiLob *lob, uint64_t newSize) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + status = dpiOci__lobTrim2(lob, newSize, &error); + return dpiGen__endPublicFn(lob, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiLob_writeBytes() [PUBLIC] +// Write the data to the LOB at the offset specified. +//----------------------------------------------------------------------------- +int dpiLob_writeBytes(dpiLob *lob, uint64_t offset, const char *value, + uint64_t valueLength) +{ + dpiError error; + int status; + + if (dpiLob__check(lob, __func__, &error) < 0) + return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(lob, value) + status = dpiOci__lobWrite2(lob, offset, value, valueLength, &error); + return dpiGen__endPublicFn(lob, status, &error); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiMsgProps.c b/vendor/github.com/godror/godror/odpi/src/dpiMsgProps.c new file mode 100644 index 00000000000..518d2e7d20b --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiMsgProps.c @@ -0,0 +1,487 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiMsgProps.c +// Implementation of AQ message properties. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiMsgProps__allocate() [INTERNAL] +// Create a new message properties structure and return it. In case of error +// NULL is returned. +//----------------------------------------------------------------------------- +int dpiMsgProps__allocate(dpiConn *conn, dpiMsgProps **props, dpiError *error) +{ + dpiMsgProps *tempProps; + + if (dpiGen__allocate(DPI_HTYPE_MSG_PROPS, conn->env, (void**) &tempProps, + error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(conn, error, 1); + tempProps->conn = conn; + if (dpiOci__descriptorAlloc(conn->env->handle, &tempProps->handle, + DPI_OCI_DTYPE_AQMSG_PROPERTIES, "allocate descriptor", + error) < 0) { + dpiMsgProps__free(tempProps, error); + return DPI_FAILURE; + } + + *props = tempProps; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps__extractMsgId() [INTERNAL] +// Extract bytes from the OCIRaw value containing the message id. +//----------------------------------------------------------------------------- +void dpiMsgProps__extractMsgId(dpiMsgProps *props, const char **msgId, + uint32_t *msgIdLength) +{ + dpiOci__rawPtr(props->env->handle, props->msgIdRaw, (void**) msgId); + dpiOci__rawSize(props->env->handle, props->msgIdRaw, msgIdLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps__free() [INTERNAL] +// Free the memory for a message properties structure. +//----------------------------------------------------------------------------- +void dpiMsgProps__free(dpiMsgProps *props, dpiError *error) +{ + if (props->handle) { + dpiOci__descriptorFree(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES); + props->handle = NULL; + } + if (props->payloadObj) { + dpiGen__setRefCount(props->payloadObj, error, -1); + props->payloadObj = NULL; + } + if (props->payloadRaw) { + dpiOci__rawResize(props->env->handle, &props->payloadRaw, 0, error); + props->payloadRaw = NULL; + } + if (props->msgIdRaw) { + dpiOci__rawResize(props->env->handle, &props->msgIdRaw, 0, error); + props->msgIdRaw = NULL; + } + if (props->conn) { + dpiGen__setRefCount(props->conn, error, -1); + props->conn = NULL; + } + dpiUtils__freeMemory(props); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps__getAttrValue() [INTERNAL] +// Get the attribute value in OCI. +//----------------------------------------------------------------------------- +static int dpiMsgProps__getAttrValue(dpiMsgProps *props, uint32_t attribute, + const char *fnName, void *value, uint32_t *valueLength) +{ + dpiError error; + int status; + + if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, fnName, &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(props, value) + DPI_CHECK_PTR_NOT_NULL(props, valueLength) + status = dpiOci__attrGet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, + value, valueLength, attribute, "get attribute value", &error); + return dpiGen__endPublicFn(props, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps__setAttrValue() [INTERNAL] +// Set the attribute value in OCI. +//----------------------------------------------------------------------------- +static int dpiMsgProps__setAttrValue(dpiMsgProps *props, uint32_t attribute, + const char *fnName, const void *value, uint32_t valueLength) +{ + dpiError error; + int status; + + if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, fnName, &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(props, value) + status = dpiOci__attrSet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, + (void*) value, valueLength, attribute, "set attribute value", + &error); + return dpiGen__endPublicFn(props, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_addRef() [PUBLIC] +// Add a reference to the message properties. +//----------------------------------------------------------------------------- +int dpiMsgProps_addRef(dpiMsgProps *props) +{ + return dpiGen__addRef(props, DPI_HTYPE_MSG_PROPS, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getCorrelation() [PUBLIC] +// Return correlation associated with the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_getCorrelation(dpiMsgProps *props, const char **value, + uint32_t *valueLength) +{ + return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_CORRELATION, __func__, + (void*) value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getDelay() [PUBLIC] +// Return the number of seconds the message was delayed. +//----------------------------------------------------------------------------- +int dpiMsgProps_getDelay(dpiMsgProps *props, int32_t *value) +{ + uint32_t valueLength = sizeof(uint32_t); + + return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_DELAY, __func__, + value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getDeliveryMode() [PUBLIC] +// Return the mode used for delivering the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_getDeliveryMode(dpiMsgProps *props, + dpiMessageDeliveryMode *value) +{ + uint32_t valueLength = sizeof(uint16_t); + + return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_MSG_DELIVERY_MODE, + __func__, value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getEnqTime() [PUBLIC] +// Return the time the message was enqueued. +//----------------------------------------------------------------------------- +int dpiMsgProps_getEnqTime(dpiMsgProps *props, dpiTimestamp *value) +{ + dpiOciDate ociValue; + dpiError error; + + if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, + &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(props, value) + if (dpiOci__attrGet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, + &ociValue, NULL, DPI_OCI_ATTR_ENQ_TIME, "get attribute value", + &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + value->year = ociValue.year; + value->month = ociValue.month; + value->day = ociValue.day; + value->hour = ociValue.hour; + value->minute = ociValue.minute; + value->second = ociValue.second; + value->fsecond = 0; + value->tzHourOffset = 0; + value->tzMinuteOffset = 0; + return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getExceptionQ() [PUBLIC] +// Return the name of the exception queue associated with the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_getExceptionQ(dpiMsgProps *props, const char **value, + uint32_t *valueLength) +{ + return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_EXCEPTION_QUEUE, + __func__, (void*) value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getExpiration() [PUBLIC] +// Return the number of seconds until the message expires. +//----------------------------------------------------------------------------- +int dpiMsgProps_getExpiration(dpiMsgProps *props, int32_t *value) +{ + uint32_t valueLength = sizeof(uint32_t); + + return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_EXPIRATION, __func__, + value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getNumAttempts() [PUBLIC] +// Return the number of attempts made to deliver the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_getNumAttempts(dpiMsgProps *props, int32_t *value) +{ + uint32_t valueLength = sizeof(uint32_t); + + return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_ATTEMPTS, __func__, + value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getMsgId() [PUBLIC] +// Return the message id for the message (available after enqueuing or +// dequeuing a message). +//----------------------------------------------------------------------------- +int dpiMsgProps_getMsgId(dpiMsgProps *props, const char **value, + uint32_t *valueLength) +{ + dpiError error; + + if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, + &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(props, value) + DPI_CHECK_PTR_NOT_NULL(props, valueLength) + if (!props->msgIdRaw) { + *value = NULL; + *valueLength = 0; + } else { + dpiOci__rawPtr(props->env->handle, props->msgIdRaw, (void**) value); + dpiOci__rawSize(props->env->handle, props->msgIdRaw, valueLength); + } + return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getOriginalMsgId() [PUBLIC] +// Return the original message id for the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_getOriginalMsgId(dpiMsgProps *props, const char **value, + uint32_t *valueLength) +{ + dpiError error; + void *rawValue; + + if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, + &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(props, value) + DPI_CHECK_PTR_NOT_NULL(props, valueLength) + if (dpiOci__attrGet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, + &rawValue, NULL, DPI_OCI_ATTR_ORIGINAL_MSGID, + "get attribute value", &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + dpiOci__rawPtr(props->env->handle, rawValue, (void**) value); + dpiOci__rawSize(props->env->handle, rawValue, valueLength); + return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getPayload() [PUBLIC] +// Get the payload for the message (as an object or a series of bytes). +//----------------------------------------------------------------------------- +int dpiMsgProps_getPayload(dpiMsgProps *props, dpiObject **obj, + const char **value, uint32_t *valueLength) +{ + dpiError error; + + if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, + &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + if (obj) + *obj = props->payloadObj; + if (value && valueLength) { + if (props->payloadRaw) { + dpiOci__rawPtr(props->env->handle, props->payloadRaw, + (void**) value); + dpiOci__rawSize(props->env->handle, props->payloadRaw, + valueLength); + } else { + *value = NULL; + *valueLength = 0; + } + } + + return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getPriority() [PUBLIC] +// Return the priority of the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_getPriority(dpiMsgProps *props, int32_t *value) +{ + uint32_t valueLength = sizeof(uint32_t); + + return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_PRIORITY, __func__, + value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_getState() [PUBLIC] +// Return the state of the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_getState(dpiMsgProps *props, dpiMessageState *value) +{ + uint32_t valueLength = sizeof(uint32_t); + + + return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_MSG_STATE, __func__, + value, &valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_release() [PUBLIC] +// Release a reference to the message properties. +//----------------------------------------------------------------------------- +int dpiMsgProps_release(dpiMsgProps *props) +{ + return dpiGen__release(props, DPI_HTYPE_MSG_PROPS, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_setCorrelation() [PUBLIC] +// Set correlation associated with the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_setCorrelation(dpiMsgProps *props, const char *value, + uint32_t valueLength) +{ + return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_CORRELATION, __func__, + value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_setDelay() [PUBLIC] +// Set the number of seconds to delay the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_setDelay(dpiMsgProps *props, int32_t value) +{ + return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_DELAY, __func__, + &value, 0); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_setExceptionQ() [PUBLIC] +// Set the name of the exception queue associated with the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_setExceptionQ(dpiMsgProps *props, const char *value, + uint32_t valueLength) +{ + return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_EXCEPTION_QUEUE, + __func__, value, valueLength); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_setExpiration() [PUBLIC] +// Set the number of seconds until the message expires. +//----------------------------------------------------------------------------- +int dpiMsgProps_setExpiration(dpiMsgProps *props, int32_t value) +{ + return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_EXPIRATION, __func__, + &value, 0); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_setOriginalMsgId() [PUBLIC] +// Set the original message id for the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_setOriginalMsgId(dpiMsgProps *props, const char *value, + uint32_t valueLength) +{ + void *rawValue = NULL; + dpiError error; + int status; + + if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, + &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(props, value) + if (dpiOci__rawAssignBytes(props->env->handle, value, valueLength, + &rawValue, &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + status = dpiOci__attrSet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, + (void*) rawValue, 0, DPI_OCI_ATTR_ORIGINAL_MSGID, "set value", + &error); + dpiOci__rawResize(props->env->handle, &rawValue, 0, &error); + return dpiGen__endPublicFn(props, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_setPayloadBytes() [PUBLIC] +// Set the payload for the message (as a series of bytes). +//----------------------------------------------------------------------------- +int dpiMsgProps_setPayloadBytes(dpiMsgProps *props, const char *value, + uint32_t valueLength) +{ + dpiError error; + int status; + + if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, + &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(props, value) + if (props->payloadRaw) { + dpiOci__rawResize(props->env->handle, &props->payloadRaw, 0, &error); + props->payloadRaw = NULL; + } + status = dpiOci__rawAssignBytes(props->env->handle, value, valueLength, + &props->payloadRaw, &error); + return dpiGen__endPublicFn(props, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_setPayloadObject() [PUBLIC] +// Set the payload for the message (as an object). +//----------------------------------------------------------------------------- +int dpiMsgProps_setPayloadObject(dpiMsgProps *props, dpiObject *obj) +{ + dpiError error; + + if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, + &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + if (dpiGen__checkHandle(obj, DPI_HTYPE_OBJECT, "check object", &error) < 0) + return dpiGen__endPublicFn(props, DPI_FAILURE, &error); + if (props->payloadObj) + dpiGen__setRefCount(props->payloadObj, &error, -1); + dpiGen__setRefCount(obj, &error, 1); + props->payloadObj = obj; + return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiMsgProps_setPriority() [PUBLIC] +// Set the priority of the message. +//----------------------------------------------------------------------------- +int dpiMsgProps_setPriority(dpiMsgProps *props, int32_t value) +{ + return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_PRIORITY, __func__, + &value, 0); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiObject.c b/vendor/github.com/godror/godror/odpi/src/dpiObject.c new file mode 100644 index 00000000000..338c68aeeda --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiObject.c @@ -0,0 +1,966 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiObject.c +// Implementation of objects. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +// forward declarations of internal functions only used in this file +int dpiObject__closeHelper(dpiObject *obj, int checkError, dpiError *error); + + +//----------------------------------------------------------------------------- +// dpiObject__allocate() [INTERNAL] +// Allocate and initialize an object structure. +//----------------------------------------------------------------------------- +int dpiObject__allocate(dpiObjectType *objType, void *instance, + void *indicator, dpiObject *dependsOnObj, dpiObject **obj, + dpiError *error) +{ + dpiObject *tempObj; + + if (dpiGen__allocate(DPI_HTYPE_OBJECT, objType->env, (void**) &tempObj, + error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(objType, error, 1); + tempObj->type = objType; + tempObj->instance = instance; + tempObj->indicator = indicator; + if (dependsOnObj) { + dpiGen__setRefCount(dependsOnObj, error, 1); + tempObj->dependsOnObj = dependsOnObj; + } + if (!instance) { + if (dpiOci__objectNew(tempObj, error) < 0) { + dpiObject__free(tempObj, error); + return DPI_FAILURE; + } + if (dpiOci__objectGetInd(tempObj, error) < 0) { + dpiObject__free(tempObj, error); + return DPI_FAILURE; + } + } + if (tempObj->instance && !dependsOnObj) { + if (dpiHandleList__addHandle(objType->conn->objects, tempObj, + &tempObj->openSlotNum, error) < 0) { + dpiObject__free(tempObj, error); + return DPI_FAILURE; + } + } + *obj = tempObj; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiObject__check() [INTERNAL] +// Determine if the object handle provided is available for use. +//----------------------------------------------------------------------------- +static int dpiObject__check(dpiObject *obj, const char *fnName, + dpiError *error) +{ + if (dpiGen__startPublicFn(obj, DPI_HTYPE_OBJECT, fnName, error) < 0) + return DPI_FAILURE; + return dpiConn__checkConnected(obj->type->conn, error); +} + + +//----------------------------------------------------------------------------- +// dpiObject__checkIsCollection() [INTERNAL] +// Check if the object is a collection, and if not, raise an exception. +//----------------------------------------------------------------------------- +static int dpiObject__checkIsCollection(dpiObject *obj, const char *fnName, + dpiError *error) +{ + if (dpiObject__check(obj, fnName, error) < 0) + return DPI_FAILURE; + if (!obj->type->isCollection) + return dpiError__set(error, "check collection", DPI_ERR_NOT_COLLECTION, + obj->type->schemaLength, obj->type->schema, + obj->type->nameLength, obj->type->name); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiObject__clearOracleValue() [INTERNAL] +// Clear the Oracle value after use. +//----------------------------------------------------------------------------- +static void dpiObject__clearOracleValue(dpiObject *obj, dpiError *error, + dpiOracleDataBuffer *buffer, dpiLob *lob, + dpiOracleTypeNum oracleTypeNum) +{ + switch (oracleTypeNum) { + case DPI_ORACLE_TYPE_CHAR: + case DPI_ORACLE_TYPE_NCHAR: + case DPI_ORACLE_TYPE_VARCHAR: + case DPI_ORACLE_TYPE_NVARCHAR: + if (buffer->asString) + dpiOci__stringResize(obj->env->handle, &buffer->asString, 0, + error); + break; + case DPI_ORACLE_TYPE_RAW: + if (buffer->asRawData) + dpiOci__rawResize(obj->env->handle, &buffer->asRawData, 0, + error); + break; + case DPI_ORACLE_TYPE_TIMESTAMP: + if (buffer->asTimestamp) + dpiOci__descriptorFree(buffer->asTimestamp, + DPI_OCI_DTYPE_TIMESTAMP); + break; + case DPI_ORACLE_TYPE_TIMESTAMP_TZ: + if (buffer->asTimestamp) + dpiOci__descriptorFree(buffer->asTimestamp, + DPI_OCI_DTYPE_TIMESTAMP_TZ); + break; + case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: + if (buffer->asTimestamp) + dpiOci__descriptorFree(buffer->asTimestamp, + DPI_OCI_DTYPE_TIMESTAMP_LTZ); + break; + case DPI_ORACLE_TYPE_CLOB: + case DPI_ORACLE_TYPE_NCLOB: + case DPI_ORACLE_TYPE_BLOB: + case DPI_ORACLE_TYPE_BFILE: + if (lob) + dpiGen__setRefCount(lob, error, -1); + break; + default: + break; + }; +} + + +//----------------------------------------------------------------------------- +// dpiObject__close() [INTERNAL] +// Close the object (frees the memory for the instance). This is needed to +// avoid trying to do so after the connection which created the object is +// closed. In some future release of the Oracle Client libraries this may not +// be needed, at which point this code and all of the code for managing the +// list of objects created by a collection can be removed. +//----------------------------------------------------------------------------- +int dpiObject__close(dpiObject *obj, int checkError, dpiError *error) +{ + int closing; + + // determine whether object is already being closed and if not, mark + // object as being closed; this MUST be done while holding the lock (if + // in threaded mode) to avoid race conditions! + if (obj->env->threaded) + dpiMutex__acquire(obj->env->mutex); + closing = obj->closing; + obj->closing = 1; + if (obj->env->threaded) + dpiMutex__release(obj->env->mutex); + + // if object is already being closed, nothing needs to be done + if (closing) + return DPI_SUCCESS; + + // perform actual work of closing object; if this fails, reset closing + // flag; again, this must be done while holding the lock (if in threaded + // mode) in order to avoid race conditions! + if (obj->instance && !obj->dependsOnObj) { + if (dpiObject__closeHelper(obj, checkError, error) < 0) { + if (obj->env->threaded) + dpiMutex__acquire(obj->env->mutex); + obj->closing = 0; + if (obj->env->threaded) + dpiMutex__release(obj->env->mutex); + return DPI_FAILURE; + } + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiObject__closeHelper() [INTERNAL] +// Helper function for closing an object. +//----------------------------------------------------------------------------- +int dpiObject__closeHelper(dpiObject *obj, int checkError, dpiError *error) +{ + if (dpiOci__objectFree(obj->env->handle, obj->instance, checkError, + error) < 0) + return DPI_FAILURE; + obj->instance = NULL; + if (obj->freeIndicator && dpiOci__objectFree(obj->env->handle, + obj->indicator, checkError, error) < 0) + return DPI_FAILURE; + obj->indicator = NULL; + if (!obj->type->conn->closing) + dpiHandleList__removeHandle(obj->type->conn->objects, + obj->openSlotNum); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiObject__free() [INTERNAL] +// Free the memory for an object. +//----------------------------------------------------------------------------- +void dpiObject__free(dpiObject *obj, dpiError *error) +{ + dpiObject__close(obj, 0, error); + if (obj->type) { + dpiGen__setRefCount(obj->type, error, -1); + obj->type = NULL; + } + if (obj->dependsOnObj) { + dpiGen__setRefCount(obj->dependsOnObj, error, -1); + obj->dependsOnObj = NULL; + } + dpiUtils__freeMemory(obj); +} + + +//----------------------------------------------------------------------------- +// dpiObject__fromOracleValue() [INTERNAL] +// Populate data from the Oracle value or return an error if this is not +// possible. +//----------------------------------------------------------------------------- +static int dpiObject__fromOracleValue(dpiObject *obj, dpiError *error, + const dpiDataTypeInfo *typeInfo, dpiOracleData *value, + int16_t *indicator, dpiNativeTypeNum nativeTypeNum, dpiData *data) +{ + dpiOracleTypeNum valueOracleTypeNum; + dpiBytes *asBytes; + + // null values are immediately returned (type is irrelevant) + if (*indicator == DPI_OCI_IND_NULL) { + data->isNull = 1; + return DPI_SUCCESS; + } + + // convert all other values + data->isNull = 0; + valueOracleTypeNum = typeInfo->oracleTypeNum; + switch (valueOracleTypeNum) { + case DPI_ORACLE_TYPE_CHAR: + case DPI_ORACLE_TYPE_NCHAR: + case DPI_ORACLE_TYPE_VARCHAR: + case DPI_ORACLE_TYPE_NVARCHAR: + if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { + asBytes = &data->value.asBytes; + dpiOci__stringPtr(obj->env->handle, *value->asString, + &asBytes->ptr); + dpiOci__stringSize(obj->env->handle, *value->asString, + &asBytes->length); + if (valueOracleTypeNum == DPI_ORACLE_TYPE_NCHAR || + valueOracleTypeNum == DPI_ORACLE_TYPE_NVARCHAR) + asBytes->encoding = obj->env->nencoding; + else asBytes->encoding = obj->env->encoding; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_RAW: + if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { + asBytes = &data->value.asBytes; + dpiOci__rawPtr(obj->env->handle, *value->asRawData, + (void**) &asBytes->ptr); + dpiOci__rawSize(obj->env->handle, *value->asRawData, + &asBytes->length); + asBytes->encoding = NULL; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_NATIVE_INT: + if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) { + data->value.asInt64 = *value->asInt32; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_NATIVE_FLOAT: + if (nativeTypeNum == DPI_NATIVE_TYPE_FLOAT) { + data->value.asFloat = *value->asFloat; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_NATIVE_DOUBLE: + if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { + data->value.asDouble = *value->asDouble; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_NUMBER: + if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) + return dpiDataBuffer__fromOracleNumberAsDouble(&data->value, + error, value->asNumber); + else if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) + return dpiDataBuffer__fromOracleNumberAsInteger(&data->value, + error, value->asNumber); + else if (nativeTypeNum == DPI_NATIVE_TYPE_UINT64) + return dpiDataBuffer__fromOracleNumberAsUnsignedInteger( + &data->value, error, value->asNumber); + else if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) + return dpiDataBuffer__fromOracleNumberAsText(&data->value, + obj->env, error, value->asNumber); + break; + case DPI_ORACLE_TYPE_DATE: + if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) + return dpiDataBuffer__fromOracleDate(&data->value, + value->asDate); + if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) + return dpiDataBuffer__fromOracleDateAsDouble(&data->value, + obj->env, error, value->asDate); + break; + case DPI_ORACLE_TYPE_TIMESTAMP: + if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) + return dpiDataBuffer__fromOracleTimestamp(&data->value, + obj->env, error, *value->asTimestamp, 0); + if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) + return dpiDataBuffer__fromOracleTimestampAsDouble(&data->value, + obj->env, error, *value->asTimestamp); + break; + case DPI_ORACLE_TYPE_TIMESTAMP_TZ: + case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: + if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) + return dpiDataBuffer__fromOracleTimestamp(&data->value, + obj->env, error, *value->asTimestamp, 1); + if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) + return dpiDataBuffer__fromOracleTimestampAsDouble(&data->value, + obj->env, error, *value->asTimestamp); + break; + case DPI_ORACLE_TYPE_OBJECT: + if (typeInfo->objectType && + nativeTypeNum == DPI_NATIVE_TYPE_OBJECT) { + void *instance = (typeInfo->objectType->isCollection) ? + *value->asCollection : value->asRaw; + dpiObject *tempObj; + if (dpiObject__allocate(typeInfo->objectType, instance, + indicator, obj, &tempObj, error) < 0) + return DPI_FAILURE; + data->value.asObject = tempObj; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_BOOLEAN: + if (nativeTypeNum == DPI_NATIVE_TYPE_BOOLEAN) { + data->value.asBoolean = *(value->asBoolean); + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_CLOB: + case DPI_ORACLE_TYPE_NCLOB: + case DPI_ORACLE_TYPE_BLOB: + case DPI_ORACLE_TYPE_BFILE: + if (nativeTypeNum == DPI_NATIVE_TYPE_LOB) { + const dpiOracleType *lobType; + void *tempLocator; + dpiLob *tempLob; + lobType = dpiOracleType__getFromNum(typeInfo->oracleTypeNum, + error); + if (dpiLob__allocate(obj->type->conn, lobType, &tempLob, + error) < 0) + return DPI_FAILURE; + tempLocator = tempLob->locator; + tempLob->locator = *(value->asLobLocator); + if (dpiOci__lobLocatorAssign(tempLob, &tempLocator, + error) < 0) { + tempLob->locator = tempLocator; + dpiLob__free(tempLob, error); + return DPI_FAILURE; + } + tempLob->locator = tempLocator; + data->value.asLOB = tempLob; + return DPI_SUCCESS; + } + break; + default: + break; + }; + + return dpiError__set(error, "from Oracle value", + DPI_ERR_UNHANDLED_CONVERSION, valueOracleTypeNum, nativeTypeNum); +} + + +//----------------------------------------------------------------------------- +// dpiObject__toOracleValue() [INTERNAL] +// Convert value from external type to the OCI data type required. +//----------------------------------------------------------------------------- +static int dpiObject__toOracleValue(dpiObject *obj, dpiError *error, + const dpiDataTypeInfo *dataTypeInfo, dpiOracleDataBuffer *buffer, + dpiLob **lob, void **ociValue, int16_t *valueIndicator, + void **objectIndicator, dpiNativeTypeNum nativeTypeNum, dpiData *data) +{ + dpiOracleTypeNum valueOracleTypeNum; + uint32_t handleType; + dpiObject *otherObj; + dpiBytes *bytes; + + // nulls are handled easily + *objectIndicator = NULL; + if (data->isNull) { + *ociValue = NULL; + *valueIndicator = DPI_OCI_IND_NULL; + buffer->asRaw = NULL; + return DPI_SUCCESS; + } + + // convert all other values + *valueIndicator = DPI_OCI_IND_NOTNULL; + valueOracleTypeNum = dataTypeInfo->oracleTypeNum; + switch (valueOracleTypeNum) { + case DPI_ORACLE_TYPE_CHAR: + case DPI_ORACLE_TYPE_NCHAR: + case DPI_ORACLE_TYPE_VARCHAR: + case DPI_ORACLE_TYPE_NVARCHAR: + buffer->asString = NULL; + if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { + bytes = &data->value.asBytes; + if (dpiOci__stringAssignText(obj->env->handle, bytes->ptr, + bytes->length, &buffer->asString, error) < 0) + return DPI_FAILURE; + *ociValue = buffer->asString; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_RAW: + buffer->asRawData = NULL; + if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { + bytes = &data->value.asBytes; + if (dpiOci__rawAssignBytes(obj->env->handle, bytes->ptr, + bytes->length, &buffer->asRawData, error) < 0) + return DPI_FAILURE; + *ociValue = buffer->asRawData; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_NATIVE_INT: + if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) { + buffer->asInt32 = (int32_t) data->value.asInt64; + *ociValue = &buffer->asInt32; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_NUMBER: + *ociValue = &buffer->asNumber; + if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) + return dpiDataBuffer__toOracleNumberFromInteger(&data->value, + error, &buffer->asNumber); + if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) + return dpiDataBuffer__toOracleNumberFromDouble(&data->value, + error, &buffer->asNumber); + if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) + return dpiDataBuffer__toOracleNumberFromText(&data->value, + obj->env, error, &buffer->asNumber); + break; + case DPI_ORACLE_TYPE_NATIVE_FLOAT: + if (nativeTypeNum == DPI_NATIVE_TYPE_FLOAT) { + buffer->asFloat = data->value.asFloat; + *ociValue = &buffer->asFloat; + return DPI_SUCCESS; + } else if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { + buffer->asFloat = (float) data->value.asDouble; + *ociValue = &buffer->asFloat; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_NATIVE_DOUBLE: + if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { + buffer->asDouble = data->value.asDouble; + *ociValue = &buffer->asDouble; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_DATE: + *ociValue = &buffer->asDate; + if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) + return dpiDataBuffer__toOracleDate(&data->value, + &buffer->asDate); + if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) + return dpiDataBuffer__toOracleDateFromDouble(&data->value, + obj->env, error, &buffer->asDate); + break; + case DPI_ORACLE_TYPE_TIMESTAMP: + case DPI_ORACLE_TYPE_TIMESTAMP_TZ: + case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: + buffer->asTimestamp = NULL; + if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP || + nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { + if (valueOracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_LTZ || + nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { + handleType = DPI_OCI_DTYPE_TIMESTAMP_LTZ; + } else if (valueOracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP) { + handleType = DPI_OCI_DTYPE_TIMESTAMP; + } else { + handleType = DPI_OCI_DTYPE_TIMESTAMP_TZ; + } + if (dpiOci__descriptorAlloc(obj->env->handle, + &buffer->asTimestamp, handleType, "allocate timestamp", + error) < 0) + return DPI_FAILURE; + *ociValue = buffer->asTimestamp; + if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) + return dpiDataBuffer__toOracleTimestamp(&data->value, + obj->env, error, buffer->asTimestamp, + (valueOracleTypeNum != DPI_ORACLE_TYPE_TIMESTAMP)); + return dpiDataBuffer__toOracleTimestampFromDouble(&data->value, + obj->env, error, buffer->asTimestamp); + } + break; + case DPI_ORACLE_TYPE_OBJECT: + otherObj = data->value.asObject; + if (nativeTypeNum == DPI_NATIVE_TYPE_OBJECT) { + if (otherObj->type->tdo != dataTypeInfo->objectType->tdo) + return dpiError__set(error, "check type", + DPI_ERR_WRONG_TYPE, otherObj->type->schemaLength, + otherObj->type->schema, otherObj->type->nameLength, + otherObj->type->name, + dataTypeInfo->objectType->schemaLength, + dataTypeInfo->objectType->schema, + dataTypeInfo->objectType->nameLength, + dataTypeInfo->objectType->name); + *ociValue = otherObj->instance; + *objectIndicator = otherObj->indicator; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_BOOLEAN: + if (nativeTypeNum == DPI_NATIVE_TYPE_BOOLEAN) { + buffer->asBoolean = data->value.asBoolean; + *ociValue = &buffer->asBoolean; + return DPI_SUCCESS; + } + break; + case DPI_ORACLE_TYPE_CLOB: + case DPI_ORACLE_TYPE_NCLOB: + case DPI_ORACLE_TYPE_BLOB: + case DPI_ORACLE_TYPE_BFILE: + buffer->asLobLocator = NULL; + if (nativeTypeNum == DPI_NATIVE_TYPE_LOB) { + *ociValue = data->value.asLOB->locator; + return DPI_SUCCESS; + } else if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { + const dpiOracleType *lobType; + lobType = dpiOracleType__getFromNum(valueOracleTypeNum, error); + if (dpiLob__allocate(obj->type->conn, lobType, lob, error) < 0) + return DPI_FAILURE; + bytes = &data->value.asBytes; + if (dpiLob__setFromBytes(*lob, bytes->ptr, bytes->length, + error) < 0) + return DPI_FAILURE; + buffer->asLobLocator = (*lob)->locator; + *ociValue = (*lob)->locator; + return DPI_SUCCESS; + } + break; + + default: + break; + } + + return dpiError__set(error, "to Oracle value", + DPI_ERR_UNHANDLED_CONVERSION, valueOracleTypeNum, nativeTypeNum); +} + + +//----------------------------------------------------------------------------- +// dpiObject_addRef() [PUBLIC] +// Add a reference to the object. +//----------------------------------------------------------------------------- +int dpiObject_addRef(dpiObject *obj) +{ + return dpiGen__addRef(obj, DPI_HTYPE_OBJECT, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiObject_appendElement() [PUBLIC] +// Append an element to the collection. +//----------------------------------------------------------------------------- +int dpiObject_appendElement(dpiObject *obj, dpiNativeTypeNum nativeTypeNum, + dpiData *data) +{ + dpiOracleDataBuffer valueBuffer; + int16_t scalarValueIndicator; + dpiLob *lob = NULL; + void *indicator; + dpiError error; + void *ociValue; + int status; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(obj, data) + status = dpiObject__toOracleValue(obj, &error, &obj->type->elementTypeInfo, + &valueBuffer, &lob, &ociValue, &scalarValueIndicator, + (void**) &indicator, nativeTypeNum, data); + if (status == DPI_SUCCESS) { + if (!indicator) + indicator = &scalarValueIndicator; + status = dpiOci__collAppend(obj->type->conn, ociValue, indicator, + obj->instance, &error); + } + dpiObject__clearOracleValue(obj, &error, &valueBuffer, lob, + obj->type->elementTypeInfo.oracleTypeNum); + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_copy() [PUBLIC] +// Create a copy of the object and return it. Return NULL upon error. +//----------------------------------------------------------------------------- +int dpiObject_copy(dpiObject *obj, dpiObject **copiedObj) +{ + dpiObject *tempObj; + dpiError error; + + if (dpiObject__check(obj, __func__, &error) < 0) + return DPI_FAILURE; + DPI_CHECK_PTR_NOT_NULL(obj, copiedObj) + if (dpiObject__allocate(obj->type, NULL, NULL, NULL, &tempObj, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + if (dpiOci__objectCopy(tempObj, obj->instance, obj->indicator, + &error) < 0) { + dpiObject__free(tempObj, &error); + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + } + *copiedObj = tempObj; + return dpiGen__endPublicFn(obj, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_deleteElementByIndex() [PUBLIC] +// Delete the element at the specified index in the collection. +//----------------------------------------------------------------------------- +int dpiObject_deleteElementByIndex(dpiObject *obj, int32_t index) +{ + dpiError error; + int status; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + status = dpiOci__tableDelete(obj, index, &error); + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_getAttributeValue() [PUBLIC] +// Get the value of the given attribute from the object. +//----------------------------------------------------------------------------- +int dpiObject_getAttributeValue(dpiObject *obj, dpiObjectAttr *attr, + dpiNativeTypeNum nativeTypeNum, dpiData *data) +{ + int16_t scalarValueIndicator; + void *valueIndicator, *tdo; + dpiOracleData value; + dpiError error; + int status; + + // validate parameters + if (dpiObject__check(obj, __func__, &error) < 0) + return DPI_FAILURE; + DPI_CHECK_PTR_NOT_NULL(obj, data) + if (dpiGen__checkHandle(attr, DPI_HTYPE_OBJECT_ATTR, "get attribute value", + &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + if (attr->belongsToType->tdo != obj->type->tdo) { + dpiError__set(&error, "get attribute value", DPI_ERR_WRONG_ATTR, + attr->nameLength, attr->name, obj->type->schemaLength, + obj->type->schema, obj->type->nameLength, obj->type->name); + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + } + + // get attribute value + if (dpiOci__objectGetAttr(obj, attr, &scalarValueIndicator, + &valueIndicator, &value.asRaw, &tdo, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + + // determine the proper null indicator + if (!valueIndicator) + valueIndicator = &scalarValueIndicator; + + // check to see if type is supported + if (!attr->typeInfo.oracleTypeNum) { + dpiError__set(&error, "get attribute value", + DPI_ERR_UNHANDLED_DATA_TYPE, attr->typeInfo.ociTypeCode); + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + } + + // convert to output data format + status = dpiObject__fromOracleValue(obj, &error, &attr->typeInfo, &value, + (int16_t*) valueIndicator, nativeTypeNum, data); + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_getElementExistsByIndex() [PUBLIC] +// Return boolean indicating if an element exists in the collection at the +// specified index. +//----------------------------------------------------------------------------- +int dpiObject_getElementExistsByIndex(dpiObject *obj, int32_t index, + int *exists) +{ + dpiError error; + int status; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(obj, exists) + status = dpiOci__tableExists(obj, index, exists, &error); + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_getElementValueByIndex() [PUBLIC] +// Return the element at the given index in the collection. +//----------------------------------------------------------------------------- +int dpiObject_getElementValueByIndex(dpiObject *obj, int32_t index, + dpiNativeTypeNum nativeTypeNum, dpiData *data) +{ + dpiOracleData value; + int exists, status; + void *indicator; + dpiError error; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(obj, data) + if (dpiOci__collGetElem(obj->type->conn, obj->instance, index, &exists, + &value.asRaw, &indicator, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + if (!exists) { + dpiError__set(&error, "get element value", DPI_ERR_INVALID_INDEX, + index); + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + } + status = dpiObject__fromOracleValue(obj, &error, + &obj->type->elementTypeInfo, &value, (int16_t*) indicator, + nativeTypeNum, data); + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_getFirstIndex() [PUBLIC] +// Return the index of the first entry in the collection. +//----------------------------------------------------------------------------- +int dpiObject_getFirstIndex(dpiObject *obj, int32_t *index, int *exists) +{ + dpiError error; + int32_t size; + int status; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(obj, index) + DPI_CHECK_PTR_NOT_NULL(obj, exists) + if (dpiOci__tableSize(obj, &size, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + *exists = (size != 0); + if (*exists) + status = dpiOci__tableFirst(obj, index, &error); + else status = DPI_SUCCESS; + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_getLastIndex() [PUBLIC] +// Return the index of the last entry in the collection. +//----------------------------------------------------------------------------- +int dpiObject_getLastIndex(dpiObject *obj, int32_t *index, int *exists) +{ + dpiError error; + int32_t size; + int status; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(obj, index) + DPI_CHECK_PTR_NOT_NULL(obj, exists) + if (dpiOci__tableSize(obj, &size, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + *exists = (size != 0); + if (*exists) + status = dpiOci__tableLast(obj, index, &error); + else status = DPI_SUCCESS; + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_getNextIndex() [PUBLIC] +// Return the index of the next entry in the collection following the index +// specified. If there is no next entry, exists is set to 0. +//----------------------------------------------------------------------------- +int dpiObject_getNextIndex(dpiObject *obj, int32_t index, int32_t *nextIndex, + int *exists) +{ + dpiError error; + int status; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(obj, nextIndex) + DPI_CHECK_PTR_NOT_NULL(obj, exists) + status = dpiOci__tableNext(obj, index, nextIndex, exists, &error); + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_getPrevIndex() [PUBLIC] +// Return the index of the previous entry in the collection preceding the +// index specified. If there is no previous entry, exists is set to 0. +//----------------------------------------------------------------------------- +int dpiObject_getPrevIndex(dpiObject *obj, int32_t index, int32_t *prevIndex, + int *exists) +{ + dpiError error; + int status; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(obj, prevIndex) + DPI_CHECK_PTR_NOT_NULL(obj, exists) + status = dpiOci__tablePrev(obj, index, prevIndex, exists, &error); + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_getSize() [PUBLIC] +// Return the size of the collection. +//----------------------------------------------------------------------------- +int dpiObject_getSize(dpiObject *obj, int32_t *size) +{ + dpiError error; + int status; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(obj, size) + status = dpiOci__collSize(obj->type->conn, obj->instance, size, &error); + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_release() [PUBLIC] +// Release a reference to the object. +//----------------------------------------------------------------------------- +int dpiObject_release(dpiObject *obj) +{ + return dpiGen__release(obj, DPI_HTYPE_OBJECT, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiObject_setAttributeValue() [PUBLIC] +// Create a copy of the object and return it. Return NULL upon error. +//----------------------------------------------------------------------------- +int dpiObject_setAttributeValue(dpiObject *obj, dpiObjectAttr *attr, + dpiNativeTypeNum nativeTypeNum, dpiData *data) +{ + void *valueIndicator, *ociValue; + dpiOracleDataBuffer valueBuffer; + int16_t scalarValueIndicator; + dpiLob *lob = NULL; + dpiError error; + int status; + + // validate parameters + if (dpiObject__check(obj, __func__, &error) < 0) + return DPI_FAILURE; + DPI_CHECK_PTR_NOT_NULL(obj, data) + if (dpiGen__checkHandle(attr, DPI_HTYPE_OBJECT_ATTR, "set attribute value", + &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + if (attr->belongsToType->tdo != obj->type->tdo) { + dpiError__set(&error, "set attribute value", DPI_ERR_WRONG_ATTR, + attr->nameLength, attr->name, obj->type->schemaLength, + obj->type->schema, obj->type->nameLength, obj->type->name); + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + } + + // check to see if type is supported + if (!attr->typeInfo.oracleTypeNum) { + dpiError__set(&error, "get attribute value", + DPI_ERR_UNHANDLED_DATA_TYPE, attr->typeInfo.ociTypeCode); + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + } + + // convert to input data format + status = dpiObject__toOracleValue(obj, &error, &attr->typeInfo, + &valueBuffer, &lob, &ociValue, &scalarValueIndicator, + &valueIndicator, nativeTypeNum, data); + + // set attribute value + if (status == DPI_SUCCESS) + status = dpiOci__objectSetAttr(obj, attr, scalarValueIndicator, + valueIndicator, ociValue, &error); + dpiObject__clearOracleValue(obj, &error, &valueBuffer, lob, + attr->typeInfo.oracleTypeNum); + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_setElementValueByIndex() [PUBLIC] +// Set the element at the specified index to the given value. +//----------------------------------------------------------------------------- +int dpiObject_setElementValueByIndex(dpiObject *obj, int32_t index, + dpiNativeTypeNum nativeTypeNum, dpiData *data) +{ + dpiOracleDataBuffer valueBuffer; + int16_t scalarValueIndicator; + dpiLob *lob = NULL; + void *indicator; + dpiError error; + void *ociValue; + int status; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(obj, data) + status = dpiObject__toOracleValue(obj, &error, &obj->type->elementTypeInfo, + &valueBuffer, &lob, &ociValue, &scalarValueIndicator, + (void**) &indicator, nativeTypeNum, data); + if (status == DPI_SUCCESS) { + if (!indicator) + indicator = &scalarValueIndicator; + status = dpiOci__collAssignElem(obj->type->conn, index, ociValue, + indicator, obj->instance, &error); + } + dpiObject__clearOracleValue(obj, &error, &valueBuffer, lob, + obj->type->elementTypeInfo.oracleTypeNum); + return dpiGen__endPublicFn(obj, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObject_trim() [PUBLIC] +// Trim a number of elements from the end of the collection. +//----------------------------------------------------------------------------- +int dpiObject_trim(dpiObject *obj, uint32_t numToTrim) +{ + dpiError error; + int status; + + if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) + return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); + status = dpiOci__collTrim(obj->type->conn, numToTrim, obj->instance, + &error); + return dpiGen__endPublicFn(obj, status, &error); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiObjectAttr.c b/vendor/github.com/godror/godror/odpi/src/dpiObjectAttr.c new file mode 100644 index 00000000000..45d623ef573 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiObjectAttr.c @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiObjectAttr.c +// Implementation of object attributes. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiObjectAttr__allocate() [INTERNAL] +// Allocate and initialize an object attribute structure. +//----------------------------------------------------------------------------- +int dpiObjectAttr__allocate(dpiObjectType *objType, void *param, + dpiObjectAttr **attr, dpiError *error) +{ + dpiObjectAttr *tempAttr; + + // allocate and assign main reference to the type this attribute belongs to + *attr = NULL; + if (dpiGen__allocate(DPI_HTYPE_OBJECT_ATTR, objType->env, + (void**) &tempAttr, error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(objType, error, 1); + tempAttr->belongsToType = objType; + + // determine the name of the attribute + if (dpiUtils__getAttrStringWithDup("get name", param, DPI_OCI_DTYPE_PARAM, + DPI_OCI_ATTR_NAME, &tempAttr->name, &tempAttr->nameLength, + error) < 0) { + dpiObjectAttr__free(tempAttr, error); + return DPI_FAILURE; + } + + // determine type information of the attribute + if (dpiOracleType__populateTypeInfo(objType->conn, param, + DPI_OCI_DTYPE_PARAM, &tempAttr->typeInfo, error) < 0) { + dpiObjectAttr__free(tempAttr, error); + return DPI_FAILURE; + } + + *attr = tempAttr; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiObjectAttr__free() [INTERNAL] +// Free the memory for an object attribute. +//----------------------------------------------------------------------------- +void dpiObjectAttr__free(dpiObjectAttr *attr, dpiError *error) +{ + if (attr->belongsToType) { + dpiGen__setRefCount(attr->belongsToType, error, -1); + attr->belongsToType = NULL; + } + if (attr->typeInfo.objectType) { + dpiGen__setRefCount(attr->typeInfo.objectType, error, -1); + attr->typeInfo.objectType = NULL; + } + if (attr->name) { + dpiUtils__freeMemory((void*) attr->name); + attr->name = NULL; + } + dpiUtils__freeMemory(attr); +} + + +//----------------------------------------------------------------------------- +// dpiObjectAttr_addRef() [PUBLIC] +// Add a reference to the object attribute. +//----------------------------------------------------------------------------- +int dpiObjectAttr_addRef(dpiObjectAttr *attr) +{ + return dpiGen__addRef(attr, DPI_HTYPE_OBJECT_ATTR, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiObjectAttr_getInfo() [PUBLIC] +// Return information about the attribute to the caller. +//----------------------------------------------------------------------------- +int dpiObjectAttr_getInfo(dpiObjectAttr *attr, dpiObjectAttrInfo *info) +{ + dpiError error; + + if (dpiGen__startPublicFn(attr, DPI_HTYPE_OBJECT_ATTR, __func__, + &error) < 0) + return dpiGen__endPublicFn(attr, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(attr, info) + info->name = attr->name; + info->nameLength = attr->nameLength; + info->typeInfo = attr->typeInfo; + return dpiGen__endPublicFn(attr, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObjectAttr_release() [PUBLIC] +// Release a reference to the object attribute. +//----------------------------------------------------------------------------- +int dpiObjectAttr_release(dpiObjectAttr *attr) +{ + return dpiGen__release(attr, DPI_HTYPE_OBJECT_ATTR, __func__); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiObjectType.c b/vendor/github.com/godror/godror/odpi/src/dpiObjectType.c new file mode 100644 index 00000000000..fbb2cf240c8 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiObjectType.c @@ -0,0 +1,344 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiObjectType.c +// Implementation of object types. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +// forward declarations of internal functions only used in this file +static int dpiObjectType__init(dpiObjectType *objType, void *param, + uint32_t nameAttribute, dpiError *error); + + +//----------------------------------------------------------------------------- +// dpiObjectType__allocate() [INTERNAL] +// Allocate and initialize an object type structure. +//----------------------------------------------------------------------------- +int dpiObjectType__allocate(dpiConn *conn, void *param, + uint32_t nameAttribute, dpiObjectType **objType, dpiError *error) +{ + dpiObjectType *tempObjType; + + // create structure and retain reference to connection + *objType = NULL; + if (dpiGen__allocate(DPI_HTYPE_OBJECT_TYPE, conn->env, + (void**) &tempObjType, error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(conn, error, 1); + tempObjType->conn = conn; + + // perform initialization + if (dpiObjectType__init(tempObjType, param, nameAttribute, error) < 0) { + dpiObjectType__free(tempObjType, error); + return DPI_FAILURE; + } + + *objType = tempObjType; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiObjectType__check() [INTERNAL] +// Validate that the connection from which the object type was created is +// still connected and issue an error if it is not. +//----------------------------------------------------------------------------- +static int dpiObjectType__check(dpiObjectType *objType, const char *fnName, + dpiError *error) +{ + if (dpiGen__startPublicFn(objType, DPI_HTYPE_OBJECT_TYPE, fnName, + error) < 0) + return DPI_FAILURE; + return dpiConn__checkConnected(objType->conn, error); +} + + +//----------------------------------------------------------------------------- +// dpiObjectType__describe() [INTERNAL] +// Describe the object type and store information about it. Note that a +// separate call to OCIDescribeAny() is made in order to support nested types; +// an illegal attribute value is returned if this is not done. +//----------------------------------------------------------------------------- +static int dpiObjectType__describe(dpiObjectType *objType, + void *describeHandle, dpiError *error) +{ + void *collectionParam, *param; + uint16_t typeCode; + + // describe the type + if (dpiOci__describeAny(objType->conn, objType->tdo, 0, DPI_OCI_OTYPE_PTR, + describeHandle, error) < 0) + return DPI_FAILURE; + + // get top level parameter descriptor + if (dpiOci__attrGet(describeHandle, DPI_OCI_HTYPE_DESCRIBE, ¶m, 0, + DPI_OCI_ATTR_PARAM, "get top level parameter", error) < 0) + return DPI_FAILURE; + + // determine type code + if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, &typeCode, 0, + DPI_OCI_ATTR_TYPECODE, "get type code", error) < 0) + return DPI_FAILURE; + objType->typeCode = typeCode; + + // determine the number of attributes + if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, + (void*) &objType->numAttributes, 0, DPI_OCI_ATTR_NUM_TYPE_ATTRS, + "get number of attributes", error) < 0) + return DPI_FAILURE; + + // if a collection, need to determine the element type + if (typeCode == DPI_SQLT_NCO) { + objType->isCollection = 1; + + // acquire collection parameter descriptor + if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, &collectionParam, 0, + DPI_OCI_ATTR_COLLECTION_ELEMENT, "get collection descriptor", + error) < 0) + return DPI_FAILURE; + + // determine type of element + if (dpiOracleType__populateTypeInfo(objType->conn, collectionParam, + DPI_OCI_DTYPE_PARAM, &objType->elementTypeInfo, error) < 0) + return DPI_FAILURE; + + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiObjectType__free() [INTERNAL] +// Free the memory for an object type. +//----------------------------------------------------------------------------- +void dpiObjectType__free(dpiObjectType *objType, dpiError *error) +{ + if (objType->conn) { + dpiGen__setRefCount(objType->conn, error, -1); + objType->conn = NULL; + } + if (objType->elementTypeInfo.objectType) { + dpiGen__setRefCount(objType->elementTypeInfo.objectType, error, -1); + objType->elementTypeInfo.objectType = NULL; + } + if (objType->schema) { + dpiUtils__freeMemory((void*) objType->schema); + objType->schema = NULL; + } + if (objType->name) { + dpiUtils__freeMemory((void*) objType->name); + objType->name = NULL; + } + dpiUtils__freeMemory(objType); +} + + +//----------------------------------------------------------------------------- +// dpiObjectType__init() [INTERNAL] +// Initialize the object type. +//----------------------------------------------------------------------------- +static int dpiObjectType__init(dpiObjectType *objType, void *param, + uint32_t nameAttribute, dpiError *error) +{ + void *describeHandle; + void *tdoReference; + + // determine the schema of the type + if (dpiUtils__getAttrStringWithDup("get schema", param, + DPI_OCI_DTYPE_PARAM, DPI_OCI_ATTR_SCHEMA_NAME, &objType->schema, + &objType->schemaLength, error) < 0) + return DPI_FAILURE; + + // determine the name of the type + if (dpiUtils__getAttrStringWithDup("get name", param, DPI_OCI_DTYPE_PARAM, + nameAttribute, &objType->name, &objType->nameLength, error) < 0) + return DPI_FAILURE; + + // retrieve TDO of the parameter and pin it in the cache + if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, (void*) &tdoReference, 0, + DPI_OCI_ATTR_REF_TDO, "get TDO reference", error) < 0) + return DPI_FAILURE; + if (dpiOci__objectPin(objType->env->handle, tdoReference, &objType->tdo, + error) < 0) + return DPI_FAILURE; + + // acquire a describe handle + if (dpiOci__handleAlloc(objType->env->handle, &describeHandle, + DPI_OCI_HTYPE_DESCRIBE, "allocate describe handle", error) < 0) + return DPI_FAILURE; + + // describe the type + if (dpiObjectType__describe(objType, describeHandle, error) < 0) { + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return DPI_FAILURE; + } + + // free the describe handle + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiObjectType__isXmlType() [INTERNAL] +// Returns a boolean indicating if the object type in question refers to the +// type SYS.XMLTYPE. +//----------------------------------------------------------------------------- +int dpiObjectType__isXmlType(dpiObjectType *objType) +{ + static const char *schema = "SYS", *name = "XMLTYPE"; + size_t schemaLength, nameLength; + + schemaLength = strlen(schema); + nameLength = strlen(name); + return (objType->schemaLength == schemaLength && + strncmp(objType->schema, schema, schemaLength) == 0 && + objType->nameLength == nameLength && + strncmp(objType->name, name, nameLength) == 0); +} + + +//----------------------------------------------------------------------------- +// dpiObjectType_addRef() [PUBLIC] +// Add a reference to the object type. +//----------------------------------------------------------------------------- +int dpiObjectType_addRef(dpiObjectType *objType) +{ + return dpiGen__addRef(objType, DPI_HTYPE_OBJECT_TYPE, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiObjectType_createObject() [PUBLIC] +// Create a new object of the specified type and return it. Return NULL on +// error. +//----------------------------------------------------------------------------- +int dpiObjectType_createObject(dpiObjectType *objType, dpiObject **obj) +{ + dpiError error; + int status; + + // validate parameters + if (dpiObjectType__check(objType, __func__, &error) < 0) + return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(objType, obj) + status = dpiObject__allocate(objType, NULL, NULL, NULL, obj, &error); + return dpiGen__endPublicFn(objType, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObjectType_getAttributes() [PUBLIC] +// Get the attributes for the object type in the provided array. +//----------------------------------------------------------------------------- +int dpiObjectType_getAttributes(dpiObjectType *objType, uint16_t numAttributes, + dpiObjectAttr **attributes) +{ + void *topLevelParam, *attrListParam, *attrParam, *describeHandle; + dpiError error; + uint16_t i; + + // validate object type and the number of attributes + if (dpiObjectType__check(objType, __func__, &error) < 0) + return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(objType, attributes) + if (numAttributes < objType->numAttributes) { + dpiError__set(&error, "get attributes", DPI_ERR_ARRAY_SIZE_TOO_SMALL, + numAttributes); + return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); + } + if (numAttributes == 0) + return dpiGen__endPublicFn(objType, DPI_SUCCESS, &error); + + // acquire a describe handle + if (dpiOci__handleAlloc(objType->env->handle, &describeHandle, + DPI_OCI_HTYPE_DESCRIBE, "allocate describe handle", &error) < 0) + return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); + + // describe the type + if (dpiOci__describeAny(objType->conn, objType->tdo, 0, DPI_OCI_OTYPE_PTR, + describeHandle, &error) < 0) { + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); + } + + // get the top level parameter descriptor + if (dpiOci__attrGet(describeHandle, DPI_OCI_HTYPE_DESCRIBE, &topLevelParam, + 0, DPI_OCI_ATTR_PARAM, "get top level param", &error) < 0) { + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); + } + + // get the attribute list parameter descriptor + if (dpiOci__attrGet(topLevelParam, DPI_OCI_DTYPE_PARAM, + (void*) &attrListParam, 0, DPI_OCI_ATTR_LIST_TYPE_ATTRS, + "get attr list param", &error) < 0) { + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); + } + + // create attribute structure for each attribute + for (i = 0; i < objType->numAttributes; i++) { + if (dpiOci__paramGet(attrListParam, DPI_OCI_DTYPE_PARAM, &attrParam, + (uint32_t) i + 1, "get attribute param", &error) < 0) { + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); + } + if (dpiObjectAttr__allocate(objType, attrParam, &attributes[i], + &error) < 0) { + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); + } + } + + // free the describe handle + dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); + + return dpiGen__endPublicFn(objType, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObjectType_getInfo() [PUBLIC] +// Return information about the object type. +//----------------------------------------------------------------------------- +int dpiObjectType_getInfo(dpiObjectType *objType, dpiObjectTypeInfo *info) +{ + dpiError error; + + if (dpiGen__startPublicFn(objType, DPI_HTYPE_OBJECT_TYPE, __func__, + &error) < 0) + return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(objType, info) + info->name = objType->name; + info->nameLength = objType->nameLength; + info->schema = objType->schema; + info->schemaLength = objType->schemaLength; + info->isCollection = objType->isCollection; + info->elementTypeInfo = objType->elementTypeInfo; + info->numAttributes = objType->numAttributes; + return dpiGen__endPublicFn(objType, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiObjectType_release() [PUBLIC] +// Release a reference to the object type. +//----------------------------------------------------------------------------- +int dpiObjectType_release(dpiObjectType *objType) +{ + return dpiGen__release(objType, DPI_HTYPE_OBJECT_TYPE, __func__); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiOci.c b/vendor/github.com/godror/godror/odpi/src/dpiOci.c new file mode 100644 index 00000000000..c731324cb48 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiOci.c @@ -0,0 +1,3823 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiOci.c +// Link to OCI using dynamic linking. The OCI library (11.2+) is loaded +// dynamically and a function table kept for the functions that are used by +// DPI. This function table is populated as functions are used and permits use +// of all versions of OCI from one driver. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +// forward declarations of internal functions only used in this file +static void *dpiOci__allocateMem(void *unused, size_t size); +static void dpiOci__freeMem(void *unused, void *ptr); +static int dpiOci__loadLib(dpiError *error); +static int dpiOci__loadLibValidate(dpiError *error); +static int dpiOci__loadSymbol(const char *symbolName, void **symbol, + dpiError *error); +static void *dpiOci__reallocMem(void *unused, void *ptr, size_t newSize); + + +// macro to simplify code for loading each symbol +#define DPI_OCI_LOAD_SYMBOL(symbolName, symbol) \ + if (!symbol && dpiOci__loadSymbol(symbolName, (void**) &symbol, \ + error) < 0) \ + return DPI_FAILURE; + +// macro to ensure that an error handle is available +#define DPI_OCI_ENSURE_ERROR_HANDLE(error) \ + if (!error->handle && dpiError__initHandle(error) < 0) \ + return DPI_FAILURE; + +// macros to simplify code for checking results of OCI calls +#define DPI_OCI_ERROR_OCCURRED(status) \ + (status != DPI_OCI_SUCCESS && status != DPI_OCI_SUCCESS_WITH_INFO) +#define DPI_OCI_CHECK_AND_RETURN(error, status, conn, action) \ + if (DPI_OCI_ERROR_OCCURRED(status)) \ + return dpiError__setFromOCI(error, status, conn, action); \ + return DPI_SUCCESS; + + +// typedefs for all OCI functions used by ODPI-C +typedef int (*dpiOciFnType__aqDeq)(void *svchp, void *errhp, + const char *queue_name, void *deqopt, void *msgprop, void *payload_tdo, + void **payload, void **payload_ind, void **msgid, uint32_t flags); +typedef int (*dpiOciFnType__aqDeqArray)(void *svchp, void *errhp, + const char *queue_name, void *deqopt, uint32_t *iters, void **msgprop, + void *payload_tdo, void **payload, void **payload_ind, void **msgid, + void *ctxp, void *deqcbfp, uint32_t flags); +typedef int (*dpiOciFnType__aqEnq)(void *svchp, void *errhp, + const char *queue_name, void *enqopt, void *msgprop, void *payload_tdo, + void **payload, void **payload_ind, void **msgid, uint32_t flags); +typedef int (*dpiOciFnType__aqEnqArray)(void *svchp, void *errhp, + const char *queue_name, void *enqopt, uint32_t *iters, void **msgprop, + void *payload_tdo, void **payload, void **payload_ind, void **msgid, + void *ctxp, void *enqcbfp, uint32_t flags); +typedef int (*dpiOciFnType__arrayDescriptorAlloc)(const void *parenth, + void **descpp, const uint32_t type, uint32_t array_size, + const size_t xtramem_sz, void **usrmempp); +typedef int (*dpiOciFnType__arrayDescriptorFree)(void **descp, + const uint32_t type); +typedef int (*dpiOciFnType__attrGet)(const void *trgthndlp, + uint32_t trghndltyp, void *attributep, uint32_t *sizep, + uint32_t attrtype, void *errhp); +typedef int (*dpiOciFnType__attrSet)(void *trgthndlp, uint32_t trghndltyp, + void *attributep, uint32_t size, uint32_t attrtype, void *errhp); +typedef int (*dpiOciFnType__bindByName)(void *stmtp, void **bindp, void *errhp, + const char *placeholder, int32_t placeh_len, void *valuep, + int32_t value_sz, uint16_t dty, void *indp, uint16_t *alenp, + uint16_t *rcodep, uint32_t maxarr_len, uint32_t *curelep, + uint32_t mode); +typedef int (*dpiOciFnType__bindByName2)(void *stmtp, void **bindp, + void *errhp, const char *placeholder, int32_t placeh_len, void *valuep, + int64_t value_sz, uint16_t dty, void *indp, uint32_t *alenp, + uint16_t *rcodep, uint32_t maxarr_len, uint32_t *curelep, + uint32_t mode); +typedef int (*dpiOciFnType__bindByPos)(void *stmtp, void **bindp, void *errhp, + uint32_t position, void *valuep, int32_t value_sz, uint16_t dty, + void *indp, uint16_t *alenp, uint16_t *rcodep, uint32_t maxarr_len, + uint32_t *curelep, uint32_t mode); +typedef int (*dpiOciFnType__bindByPos2)(void *stmtp, void **bindp, void *errhp, + uint32_t position, void *valuep, int64_t value_sz, uint16_t dty, + void *indp, uint32_t *alenp, uint16_t *rcodep, uint32_t maxarr_len, + uint32_t *curelep, uint32_t mode); +typedef int (*dpiOciFnType__bindDynamic)(void *bindp, void *errhp, void *ictxp, + void *icbfp, void *octxp, void *ocbfp); +typedef int (*dpiOciFnType__bindObject)(void *bindp, void *errhp, + const void *type, void **pgvpp, uint32_t *pvszsp, void **indpp, + uint32_t *indszp); +typedef int (*dpiOciFnType__break)(void *hndlp, void *errhp); +typedef void (*dpiOciFnType__clientVersion)(int *major_version, + int *minor_version, int *update_num, int *patch_num, + int *port_update_num); +typedef int (*dpiOciFnType__collAppend)(void *env, void *err, const void *elem, + const void *elemind, void *coll); +typedef int (*dpiOciFnType__collAssignElem)(void *env, void *err, + int32_t index, const void *elem, const void *elemind, void *coll); +typedef int (*dpiOciFnType__collGetElem)(void *env, void *err, + const void *coll, int32_t index, int *exists, void **elem, + void **elemind); +typedef int (*dpiOciFnType__collSize)(void *env, void *err, const void *coll, + int32_t *size); +typedef int (*dpiOciFnType__collTrim)(void *env, void *err, int32_t trim_num, + void *coll); +typedef int (*dpiOciFnType__contextGetValue)(void *hdl, void *err, + const char *key, uint8_t keylen, void **ctx_value); +typedef int (*dpiOciFnType__contextSetValue)(void *hdl, void *err, + uint16_t duration, const char *key, uint8_t keylen, void *ctx_value); +typedef int (*dpiOciFnType__dateTimeConstruct)(void *hndl, void *err, + void *datetime, int16_t yr, uint8_t mnth, uint8_t dy, uint8_t hr, + uint8_t mm, uint8_t ss, uint32_t fsec, const char *tz, + size_t tzLength); +typedef int (*dpiOciFnType__dateTimeConvert)(void *hndl, void *err, + void *indate, void *outdate); +typedef int (*dpiOciFnType__dateTimeGetDate)(void *hndl, void *err, + const void *date, int16_t *yr, uint8_t *mnth, uint8_t *dy); +typedef int (*dpiOciFnType__dateTimeGetTime)(void *hndl, void *err, + void *datetime, uint8_t *hr, uint8_t *mm, uint8_t *ss, uint32_t *fsec); +typedef int (*dpiOciFnType__dateTimeGetTimeZoneOffset)(void *hndl, void *err, + const void *datetime, int8_t *hr, int8_t *mm); +typedef int (*dpiOciFnType__dateTimeIntervalAdd)(void *hndl, void *err, + void *datetime, void *inter, void *outdatetime); +typedef int (*dpiOciFnType__dateTimeSubtract)(void *hndl, void *err, + void *indate1, void *indate2, void *inter); +typedef int (*dpiOciFnType__dbShutdown)(void *svchp, void *errhp, void *admhp, + uint32_t mode); +typedef int (*dpiOciFnType__dbStartup)(void *svchp, void *errhp, void *admhp, + uint32_t mode, uint32_t flags); +typedef int (*dpiOciFnType__defineByPos)(void *stmtp, void **defnp, + void *errhp, uint32_t position, void *valuep, int32_t value_sz, + uint16_t dty, void *indp, uint16_t *rlenp, uint16_t *rcodep, + uint32_t mode); +typedef int (*dpiOciFnType__defineByPos2)(void *stmtp, void **defnp, + void *errhp, uint32_t position, void *valuep, uint64_t value_sz, + uint16_t dty, void *indp, uint32_t *rlenp, uint16_t *rcodep, + uint32_t mode); +typedef int (*dpiOciFnType__defineDynamic)(void *defnp, void *errhp, + void *octxp, void *ocbfp); +typedef int (*dpiOciFnType__defineObject)(void *defnp, void *errhp, + const void *type, void **pgvpp, uint32_t *pvszsp, void **indpp, + uint32_t *indszp); +typedef int (*dpiOciFnType__describeAny)(void *svchp, void *errhp, + void *objptr, uint32_t objnm_len, uint8_t objptr_typ, + uint8_t info_level, uint8_t objtyp, void *dschp); +typedef int (*dpiOciFnType__descriptorAlloc)(const void *parenth, + void **descpp, const uint32_t type, const size_t xtramem_sz, + void **usrmempp); +typedef int (*dpiOciFnType__descriptorFree)(void *descp, const uint32_t type); +typedef int (*dpiOciFnType__envNlsCreate)(void **envp, uint32_t mode, + void *ctxp, void *malocfp, void *ralocfp, void *mfreefp, + size_t xtramem_sz, void **usrmempp, uint16_t charset, + uint16_t ncharset); +typedef int (*dpiOciFnType__errorGet)(void *hndlp, uint32_t recordno, + char *sqlstate, int32_t *errcodep, char *bufp, uint32_t bufsiz, + uint32_t type); +typedef int (*dpiOciFnType__handleAlloc)(const void *parenth, void **hndlpp, + const uint32_t type, const size_t xtramem_sz, void **usrmempp); +typedef int (*dpiOciFnType__handleFree)(void *hndlp, const uint32_t type); +typedef int (*dpiOciFnType__intervalGetDaySecond)(void *hndl, void *err, + int32_t *dy, int32_t *hr, int32_t *mm, int32_t *ss, int32_t *fsec, + const void *result); +typedef int (*dpiOciFnType__intervalGetYearMonth)(void *hndl, void *err, + int32_t *yr, int32_t *mnth, const void *result); +typedef int (*dpiOciFnType__intervalSetDaySecond)(void *hndl, void *err, + int32_t dy, int32_t hr, int32_t mm, int32_t ss, int32_t fsec, + void *result); +typedef int (*dpiOciFnType__intervalSetYearMonth)(void *hndl, void *err, + int32_t yr, int32_t mnth, void *result); +typedef int (*dpiOciFnType__lobClose)(void *svchp, void *errhp, void *locp); +typedef int (*dpiOciFnType__lobCreateTemporary)(void *svchp, void *errhp, + void *locp, uint16_t csid, uint8_t csfrm, uint8_t lobtype, int cache, + uint16_t duration); +typedef int (*dpiOciFnType__lobFileExists)(void *svchp, void *errhp, + void *filep, int *flag); +typedef int (*dpiOciFnType__lobFileGetName)(void *envhp, void *errhp, + const void *filep, char *dir_alias, uint16_t *d_length, char *filename, + uint16_t *f_length); +typedef int (*dpiOciFnType__lobFileSetName)(void *envhp, void *errhp, + void **filepp, const char *dir_alias, uint16_t d_length, + const char *filename, uint16_t f_length); +typedef int (*dpiOciFnType__lobFreeTemporary)(void *svchp, void *errhp, + void *locp); +typedef int (*dpiOciFnType__lobGetChunkSize)(void *svchp, void *errhp, + void *locp, uint32_t *chunksizep); +typedef int (*dpiOciFnType__lobGetLength2)(void *svchp, void *errhp, + void *locp, uint64_t *lenp); +typedef int (*dpiOciFnType__lobIsOpen)(void *svchp, void *errhp, void *locp, + int *flag); +typedef int (*dpiOciFnType__lobIsTemporary)(void *envp, void *errhp, + void *locp, int *is_temporary); +typedef int (*dpiOciFnType__lobLocatorAssign)(void *svchp, void *errhp, + const void *src_locp, void **dst_locpp); +typedef int (*dpiOciFnType__lobOpen)(void *svchp, void *errhp, void *locp, + uint8_t mode); +typedef int (*dpiOciFnType__lobRead2)(void *svchp, void *errhp, void *locp, + uint64_t *byte_amtp, uint64_t *char_amtp, uint64_t offset, void *bufp, + uint64_t bufl, uint8_t piece, void *ctxp, void *cbfp, uint16_t csid, + uint8_t csfrm); +typedef int (*dpiOciFnType__lobTrim2)(void *svchp, void *errhp, void *locp, + uint64_t newlen); +typedef int (*dpiOciFnType__lobWrite2)(void *svchp, void *errhp, void *locp, + uint64_t *byte_amtp, uint64_t *char_amtp, uint64_t offset, void *bufp, + uint64_t buflen, uint8_t piece, void *ctxp, void *cbfp, uint16_t csid, + uint8_t csfrm); +typedef int (*dpiOciFnType__memoryAlloc)(void *hdl, void *err, void **mem, + uint16_t dur, uint32_t size, uint32_t flags); +typedef int (*dpiOciFnType__memoryFree)(void *hdl, void *err, void *mem); +typedef int (*dpiOciFnType__nlsCharSetConvert)(void *envhp, void *errhp, + uint16_t dstid, void *dstp, size_t dstlen, uint16_t srcid, + const void *srcp, size_t srclen, size_t *rsize); +typedef int (*dpiOciFnType__nlsCharSetIdToName)(void *envhp, char *buf, + size_t buflen, uint16_t id); +typedef uint16_t (*dpiOciFnType__nlsCharSetNameToId)(void *envhp, + const char *name); +typedef int (*dpiOciFnType__nlsEnvironmentVariableGet)(void *val, size_t size, + uint16_t item, uint16_t charset, size_t *rsize); +typedef int (*dpiOciFnType__nlsNameMap)(void *envhp, char *buf, size_t buflen, + const char *srcbuf, uint32_t flag); +typedef int (*dpiOciFnType__nlsNumericInfoGet)(void *envhp, void *errhp, + int32_t *val, uint16_t item); +typedef int (*dpiOciFnType__numberFromInt)(void *err, const void *inum, + unsigned int inum_length, unsigned int inum_s_flag, void *number); +typedef int (*dpiOciFnType__numberFromReal)(void *err, const void *number, + unsigned int rsl_length, void *rsl); +typedef int (*dpiOciFnType__numberToInt)(void *err, const void *number, + unsigned int rsl_length, unsigned int rsl_flag, void *rsl); +typedef int (*dpiOciFnType__numberToReal)(void *err, const void *number, + unsigned int rsl_length, void *rsl); +typedef int (*dpiOciFnType__objectCopy)(void *env, void *err, const void *svc, + void *source, void *null_source, void *target, void *null_target, + void *tdo, uint16_t duration, uint8_t option); +typedef int (*dpiOciFnType__objectFree)(void *env, void *err, void *instance, + uint16_t flags); +typedef int (*dpiOciFnType__objectGetAttr)(void *env, void *err, + void *instance, void *null_struct, void *tdo, const char **names, + const uint32_t *lengths, const uint32_t name_count, + const uint32_t *indexes, const uint32_t index_count, + int16_t *attr_null_status, void **attr_null_struct, void **attr_value, + void **attr_tdo); +typedef int (*dpiOciFnType__objectGetInd)(void *env, void *err, void *instance, + void **null_struct); +typedef int (*dpiOciFnType__objectNew)(void *env, void *err, const void *svc, + uint16_t typecode, void *tdo, void *table, uint16_t duration, + int value, void **instance); +typedef int (*dpiOciFnType__objectPin)(void *env, void *err, void *object_ref, + void *corhdl, int pin_option, uint16_t pin_duration, int lock_option, + void **object); +typedef int (*dpiOciFnType__objectSetAttr)(void *env, void *err, + void *instance, void *null_struct, void *tdo, const char **names, + const uint32_t *lengths, const uint32_t name_count, + const uint32_t *indexes, const uint32_t index_count, + const int16_t null_status, const void *attr_null_struct, + const void *attr_value); +typedef int (*dpiOciFnType__paramGet)(const void *hndlp, uint32_t htype, + void *errhp, void **parmdpp, uint32_t pos); +typedef int (*dpiOciFnType__passwordChange)(void *svchp, void *errhp, + const char *user_name, uint32_t usernm_len, const char *opasswd, + uint32_t opasswd_len, const char *npasswd, uint32_t npasswd_len, + uint32_t mode); +typedef int (*dpiOciFnType__ping)(void *svchp, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__rawAssignBytes)(void *env, void *err, + const char *rhs, uint32_t rhs_len, void **lhs); +typedef void *(*dpiOciFnType__rawPtr)(void *env, const void *raw); +typedef int (*dpiOciFnType__rawResize)(void *env, void *err, uint32_t new_size, + void **raw); +typedef uint32_t (*dpiOciFnType__rawSize)(void * env, const void *raw); +typedef int (*dpiOciFnType__rowidToChar)(void *rowidDesc, char *outbfp, + uint16_t *outbflp, void *errhp); +typedef int (*dpiOciFnType__serverAttach)(void *srvhp, void *errhp, + const char *dblink, int32_t dblink_len, uint32_t mode); +typedef int (*dpiOciFnType__serverDetach)(void *srvhp, void *errhp, + uint32_t mode); +typedef int (*dpiOciFnType__serverRelease)(void *hndlp, void *errhp, + char *bufp, uint32_t bufsz, uint8_t hndltype, uint32_t *version); +typedef int (*dpiOciFnType__serverRelease2)(void *hndlp, void *errhp, + char *bufp, uint32_t bufsz, uint8_t hndltype, uint32_t *version, + uint32_t mode); +typedef int (*dpiOciFnType__sessionBegin)(void *svchp, void *errhp, + void *usrhp, uint32_t credt, uint32_t mode); +typedef int (*dpiOciFnType__sessionEnd)(void *svchp, void *errhp, void *usrhp, + uint32_t mode); +typedef int (*dpiOciFnType__sessionGet)(void *envhp, void *errhp, void **svchp, + void *authhp, const char *poolName, uint32_t poolName_len, + const char *tagInfo, uint32_t tagInfo_len, const char **retTagInfo, + uint32_t *retTagInfo_len, int *found, uint32_t mode); +typedef int (*dpiOciFnType__sessionPoolCreate)(void *envhp, void *errhp, + void *spoolhp, char **poolName, uint32_t *poolNameLen, + const char *connStr, uint32_t connStrLen, uint32_t sessMin, + uint32_t sessMax, uint32_t sessIncr, const char *userid, + uint32_t useridLen, const char *password, uint32_t passwordLen, + uint32_t mode); +typedef int (*dpiOciFnType__sessionPoolDestroy)(void *spoolhp, void *errhp, + uint32_t mode); +typedef int (*dpiOciFnType__sessionRelease)(void *svchp, void *errhp, + const char *tag, uint32_t tag_len, uint32_t mode); +typedef int (*dpiOciFnType__shardingKeyColumnAdd)(void *shardingKey, + void *errhp, void *col, uint32_t colLen, uint16_t colType, + uint32_t mode); +typedef int (*dpiOciFnType__sodaBulkInsert)(void *svchp, + void *collection, void **documentarray, uint32_t arraylen, + void *opoptns, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaBulkInsertAndGet)(void *svchp, + void *collection, void **documentarray, uint32_t arraylen, + void *opoptns, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaCollCreateWithMetadata)(void *svchp, + const char *collname, uint32_t collnamelen, const char *metadata, + uint32_t metadatalen, void **collection, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaCollDrop)(void *svchp, void *coll, + int *isDropped, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaCollGetNext)(void *svchp, const void *cur, + void **coll, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaCollList)(void *svchp, const char *startname, + uint32_t stnamelen, void **cur, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaCollOpen)(void *svchp, const char *collname, + uint32_t collnamelen, void **coll, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaDataGuideGet)(void *svchp, + const void *collection, uint32_t docFlags, void **doc, void *errhp, + uint32_t mode); +typedef int (*dpiOciFnType__sodaDocCount)(void *svchp, const void *coll, + const void *optns, uint64_t *numdocs, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaDocGetNext)(void *svchp, const void *cur, + void **doc, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaFind)(void *svchp, const void *coll, + const void *findOptions, uint32_t docFlags, void **cursor, + void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaFindOne)(void *svchp, const void *coll, + const void *findOptions, uint32_t docFlags, void **doc, void *errhp, + uint32_t mode); +typedef int (*dpiOciFnType__sodaIndexCreate)(void *svchp, const void *coll, + const char *indexspec, uint32_t speclen, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaIndexDrop)(void *svchp, const char *indexname, + uint32_t indexnamelen, int *isDropped, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaInsert)(void *svchp, void *collection, + void *document, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaInsertAndGet)(void *svchp, void *collection, + void **document, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaOperKeysSet)(const void *operhp, + const char **keysArray, uint32_t *lengthsArray, uint32_t count, + void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaRemove)(void *svchp, const void *coll, + const void *optns, uint64_t *removeCount, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__sodaReplOne)(void *svchp, const void *coll, + const void *optns, void *document, int *isReplaced, void *errhp, + uint32_t mode); +typedef int (*dpiOciFnType__sodaReplOneAndGet)(void *svchp, const void *coll, + const void *optns, void **document, int *isReplaced, void *errhp, + uint32_t mode); +typedef int (*dpiOciFnType__stmtExecute)(void *svchp, void *stmtp, void *errhp, + uint32_t iters, uint32_t rowoff, const void *snap_in, void *snap_out, + uint32_t mode); +typedef int (*dpiOciFnType__stmtFetch2)(void *stmtp, void *errhp, + uint32_t nrows, uint16_t orientation, int32_t scrollOffset, + uint32_t mode); +typedef int (*dpiOciFnType__stmtGetBindInfo)(void *stmtp, void *errhp, + uint32_t size, uint32_t startloc, int32_t *found, char *bvnp[], + uint8_t bvnl[], char *invp[], uint8_t inpl[], uint8_t dupl[], + void **hndl); +typedef int (*dpiOciFnType__stmtGetNextResult)(void *stmthp, void *errhp, + void **result, uint32_t *rtype, uint32_t mode); +typedef int (*dpiOciFnType__stmtPrepare2)(void *svchp, void **stmtp, + void *errhp, const char *stmt, uint32_t stmt_len, const char *key, + uint32_t key_len, uint32_t language, uint32_t mode); +typedef int (*dpiOciFnType__stmtRelease)(void *stmtp, void *errhp, + const char *key, uint32_t key_len, uint32_t mode); +typedef int (*dpiOciFnType__stringAssignText)(void *env, void *err, + const char *rhs, uint32_t rhs_len, void **lhs); +typedef char *(*dpiOciFnType__stringPtr)(void *env, const void *vs); +typedef int (*dpiOciFnType__stringResize)(void *env, void *err, + uint32_t new_size, void **str); +typedef uint32_t (*dpiOciFnType__stringSize)(void *env, const void *vs); +typedef int (*dpiOciFnType__subscriptionRegister)(void *svchp, + void **subscrhpp, uint16_t count, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__subscriptionUnRegister)(void *svchp, + void *subscrhp, void *errhp, uint32_t mode); +typedef int (*dpiOciFnType__tableDelete)(void *env, void *err, int32_t index, + void *tbl); +typedef int (*dpiOciFnType__tableExists)(void *env, void *err, const void *tbl, + int32_t index, int *exists); +typedef int (*dpiOciFnType__tableFirst)(void *env, void *err, const void *tbl, + int32_t *index); +typedef int (*dpiOciFnType__tableLast)(void *env, void *err, const void *tbl, + int32_t *index); +typedef int (*dpiOciFnType__tableNext)(void *env, void *err, int32_t index, + const void *tbl, int32_t *next_index, int *exists); +typedef int (*dpiOciFnType__tablePrev)(void *env, void *err, int32_t index, + const void *tbl, int32_t *prev_index, int *exists); +typedef int (*dpiOciFnType__tableSize)(void *env, void *err, const void *tbl, + int32_t *size); +typedef int (*dpiOciFnType__threadKeyDestroy)(void *hndl, void *err, + void **key); +typedef int (*dpiOciFnType__threadKeyGet)(void *hndl, void *err, void *key, + void **pValue); +typedef int (*dpiOciFnType__threadKeyInit)(void *hndl, void *err, void **key, + void *destFn); +typedef int (*dpiOciFnType__threadKeySet)(void *hndl, void *err, void *key, + void *value); +typedef void (*dpiOciFnType__threadProcessInit)(void); +typedef int (*dpiOciFnType__transCommit)(void *svchp, void *errhp, + uint32_t flags); +typedef int (*dpiOciFnType__transPrepare)(void *svchp, void *errhp, + uint32_t flags); +typedef int (*dpiOciFnType__transRollback)(void *svchp, void *errhp, + uint32_t flags); +typedef int (*dpiOciFnType__transStart)(void *svchp, void *errhp, + unsigned int timeout, uint32_t flags); +typedef int (*dpiOciFnType__typeByFullName)(void *env, void *err, + const void *svc, const char *full_type_name, + uint32_t full_type_name_length, const char *version_name, + uint32_t version_name_length, uint16_t pin_duration, int get_option, + void **tdo); +typedef int (*dpiOciFnType__typeByName)(void *env, void *err, const void *svc, + const char *schema_name, uint32_t s_length, const char *type_name, + uint32_t t_length, const char *version_name, uint32_t v_length, + uint16_t pin_duration, int get_option, void **tdo); + + +// library handle for dynamically loaded OCI library +static void *dpiOciLibHandle = NULL; + +// library names to search +static const char *dpiOciLibNames[] = { +#if defined _WIN32 || defined __CYGWIN__ + "oci.dll", +#elif __APPLE__ + "libclntsh.dylib", + "libclntsh.dylib.19.1", + "libclntsh.dylib.18.1", + "libclntsh.dylib.12.1", + "libclntsh.dylib.11.1", + "libclntsh.dylib.20.1", +#else + "libclntsh.so", + "libclntsh.so.19.1", + "libclntsh.so.18.1", + "libclntsh.so.12.1", + "libclntsh.so.11.1", + "libclntsh.so.20.1", +#endif + NULL +}; + +// URL fragment to use in load library exception +#if defined _WIN32 || defined __CYGWIN__ + #define DPI_ERR_LOAD_URL_FRAGMENT "windows" +#elif __APPLE__ + #define DPI_ERR_LOAD_URL_FRAGMENT "macos" +#else + #define DPI_ERR_LOAD_URL_FRAGMENT "linux" +#endif + +// version information for loaded OCI library +static dpiVersionInfo dpiOciLibVersionInfo; + +// all OCI symbols used by ODPI-C +static struct { + dpiOciFnType__aqDeq fnAqDeq; + dpiOciFnType__aqDeqArray fnAqDeqArray; + dpiOciFnType__aqEnq fnAqEnq; + dpiOciFnType__aqEnqArray fnAqEnqArray; + dpiOciFnType__arrayDescriptorAlloc fnArrayDescriptorAlloc; + dpiOciFnType__arrayDescriptorFree fnArrayDescriptorFree; + dpiOciFnType__attrGet fnAttrGet; + dpiOciFnType__attrSet fnAttrSet; + dpiOciFnType__bindByName fnBindByName; + dpiOciFnType__bindByName2 fnBindByName2; + dpiOciFnType__bindByPos fnBindByPos; + dpiOciFnType__bindByPos2 fnBindByPos2; + dpiOciFnType__bindDynamic fnBindDynamic; + dpiOciFnType__bindObject fnBindObject; + dpiOciFnType__break fnBreak; + dpiOciFnType__clientVersion fnClientVersion; + dpiOciFnType__collAppend fnCollAppend; + dpiOciFnType__collAssignElem fnCollAssignElem; + dpiOciFnType__collGetElem fnCollGetElem; + dpiOciFnType__collSize fnCollSize; + dpiOciFnType__collTrim fnCollTrim; + dpiOciFnType__contextGetValue fnContextGetValue; + dpiOciFnType__contextSetValue fnContextSetValue; + dpiOciFnType__dateTimeConstruct fnDateTimeConstruct; + dpiOciFnType__dateTimeConvert fnDateTimeConvert; + dpiOciFnType__dateTimeGetDate fnDateTimeGetDate; + dpiOciFnType__dateTimeGetTime fnDateTimeGetTime; + dpiOciFnType__dateTimeGetTimeZoneOffset fnDateTimeGetTimeZoneOffset; + dpiOciFnType__dateTimeIntervalAdd fnDateTimeIntervalAdd; + dpiOciFnType__dateTimeSubtract fnDateTimeSubtract; + dpiOciFnType__dbShutdown fnDbShutdown; + dpiOciFnType__dbStartup fnDbStartup; + dpiOciFnType__defineByPos fnDefineByPos; + dpiOciFnType__defineByPos2 fnDefineByPos2; + dpiOciFnType__defineDynamic fnDefineDynamic; + dpiOciFnType__defineObject fnDefineObject; + dpiOciFnType__describeAny fnDescribeAny; + dpiOciFnType__descriptorAlloc fnDescriptorAlloc; + dpiOciFnType__descriptorFree fnDescriptorFree; + dpiOciFnType__envNlsCreate fnEnvNlsCreate; + dpiOciFnType__errorGet fnErrorGet; + dpiOciFnType__handleAlloc fnHandleAlloc; + dpiOciFnType__handleFree fnHandleFree; + dpiOciFnType__intervalGetDaySecond fnIntervalGetDaySecond; + dpiOciFnType__intervalGetYearMonth fnIntervalGetYearMonth; + dpiOciFnType__intervalSetDaySecond fnIntervalSetDaySecond; + dpiOciFnType__intervalSetYearMonth fnIntervalSetYearMonth; + dpiOciFnType__lobClose fnLobClose; + dpiOciFnType__lobCreateTemporary fnLobCreateTemporary; + dpiOciFnType__lobFileExists fnLobFileExists; + dpiOciFnType__lobFileGetName fnLobFileGetName; + dpiOciFnType__lobFileSetName fnLobFileSetName; + dpiOciFnType__lobFreeTemporary fnLobFreeTemporary; + dpiOciFnType__lobGetChunkSize fnLobGetChunkSize; + dpiOciFnType__lobGetLength2 fnLobGetLength2; + dpiOciFnType__lobIsOpen fnLobIsOpen; + dpiOciFnType__lobIsTemporary fnLobIsTemporary; + dpiOciFnType__lobLocatorAssign fnLobLocatorAssign; + dpiOciFnType__lobOpen fnLobOpen; + dpiOciFnType__lobRead2 fnLobRead2; + dpiOciFnType__lobTrim2 fnLobTrim2; + dpiOciFnType__lobWrite2 fnLobWrite2; + dpiOciFnType__memoryAlloc fnMemoryAlloc; + dpiOciFnType__memoryFree fnMemoryFree; + dpiOciFnType__nlsCharSetConvert fnNlsCharSetConvert; + dpiOciFnType__nlsCharSetIdToName fnNlsCharSetIdToName; + dpiOciFnType__nlsCharSetNameToId fnNlsCharSetNameToId; + dpiOciFnType__nlsEnvironmentVariableGet fnNlsEnvironmentVariableGet; + dpiOciFnType__nlsNameMap fnNlsNameMap; + dpiOciFnType__nlsNumericInfoGet fnNlsNumericInfoGet; + dpiOciFnType__numberFromInt fnNumberFromInt; + dpiOciFnType__numberFromReal fnNumberFromReal; + dpiOciFnType__numberToInt fnNumberToInt; + dpiOciFnType__numberToReal fnNumberToReal; + dpiOciFnType__objectCopy fnObjectCopy; + dpiOciFnType__objectFree fnObjectFree; + dpiOciFnType__objectGetAttr fnObjectGetAttr; + dpiOciFnType__objectGetInd fnObjectGetInd; + dpiOciFnType__objectNew fnObjectNew; + dpiOciFnType__objectPin fnObjectPin; + dpiOciFnType__objectSetAttr fnObjectSetAttr; + dpiOciFnType__paramGet fnParamGet; + dpiOciFnType__passwordChange fnPasswordChange; + dpiOciFnType__ping fnPing; + dpiOciFnType__rawAssignBytes fnRawAssignBytes; + dpiOciFnType__rawPtr fnRawPtr; + dpiOciFnType__rawResize fnRawResize; + dpiOciFnType__rawSize fnRawSize; + dpiOciFnType__rowidToChar fnRowidToChar; + dpiOciFnType__serverAttach fnServerAttach; + dpiOciFnType__serverDetach fnServerDetach; + dpiOciFnType__serverRelease fnServerRelease; + dpiOciFnType__serverRelease2 fnServerRelease2; + dpiOciFnType__sessionBegin fnSessionBegin; + dpiOciFnType__sessionEnd fnSessionEnd; + dpiOciFnType__sessionGet fnSessionGet; + dpiOciFnType__sessionPoolCreate fnSessionPoolCreate; + dpiOciFnType__sessionPoolDestroy fnSessionPoolDestroy; + dpiOciFnType__sessionRelease fnSessionRelease; + dpiOciFnType__shardingKeyColumnAdd fnShardingKeyColumnAdd; + dpiOciFnType__stmtExecute fnStmtExecute; + dpiOciFnType__sodaBulkInsert fnSodaBulkInsert; + dpiOciFnType__sodaBulkInsertAndGet fnSodaBulkInsertAndGet; + dpiOciFnType__sodaCollCreateWithMetadata fnSodaCollCreateWithMetadata; + dpiOciFnType__sodaCollDrop fnSodaCollDrop; + dpiOciFnType__sodaCollGetNext fnSodaCollGetNext; + dpiOciFnType__sodaCollList fnSodaCollList; + dpiOciFnType__sodaCollOpen fnSodaCollOpen; + dpiOciFnType__sodaDataGuideGet fnSodaDataGuideGet; + dpiOciFnType__sodaDocCount fnSodaDocCount; + dpiOciFnType__sodaDocGetNext fnSodaDocGetNext; + dpiOciFnType__sodaFind fnSodaFind; + dpiOciFnType__sodaFindOne fnSodaFindOne; + dpiOciFnType__sodaIndexCreate fnSodaIndexCreate; + dpiOciFnType__sodaIndexDrop fnSodaIndexDrop; + dpiOciFnType__sodaInsert fnSodaInsert; + dpiOciFnType__sodaInsertAndGet fnSodaInsertAndGet; + dpiOciFnType__sodaOperKeysSet fnSodaOperKeysSet; + dpiOciFnType__sodaRemove fnSodaRemove; + dpiOciFnType__sodaReplOne fnSodaReplOne; + dpiOciFnType__sodaReplOneAndGet fnSodaReplOneAndGet; + dpiOciFnType__stmtFetch2 fnStmtFetch2; + dpiOciFnType__stmtGetBindInfo fnStmtGetBindInfo; + dpiOciFnType__stmtGetNextResult fnStmtGetNextResult; + dpiOciFnType__stmtPrepare2 fnStmtPrepare2; + dpiOciFnType__stmtRelease fnStmtRelease; + dpiOciFnType__stringAssignText fnStringAssignText; + dpiOciFnType__stringPtr fnStringPtr; + dpiOciFnType__stringResize fnStringResize; + dpiOciFnType__stringSize fnStringSize; + dpiOciFnType__subscriptionRegister fnSubscriptionRegister; + dpiOciFnType__subscriptionUnRegister fnSubscriptionUnRegister; + dpiOciFnType__tableDelete fnTableDelete; + dpiOciFnType__tableExists fnTableExists; + dpiOciFnType__tableFirst fnTableFirst; + dpiOciFnType__tableLast fnTableLast; + dpiOciFnType__tableNext fnTableNext; + dpiOciFnType__tablePrev fnTablePrev; + dpiOciFnType__tableSize fnTableSize; + dpiOciFnType__threadKeyDestroy fnThreadKeyDestroy; + dpiOciFnType__threadKeyGet fnThreadKeyGet; + dpiOciFnType__threadKeyInit fnThreadKeyInit; + dpiOciFnType__threadKeySet fnThreadKeySet; + dpiOciFnType__threadProcessInit fnThreadProcessInit; + dpiOciFnType__transCommit fnTransCommit; + dpiOciFnType__transPrepare fnTransPrepare; + dpiOciFnType__transRollback fnTransRollback; + dpiOciFnType__transStart fnTransStart; + dpiOciFnType__typeByFullName fnTypeByFullName; + dpiOciFnType__typeByName fnTypeByName; +} dpiOciSymbols; + + +//----------------------------------------------------------------------------- +// dpiOci__allocateMem() [INTERNAL] +// Wrapper for OCI allocation of memory, only used when debugging memory +// allocation. +//----------------------------------------------------------------------------- +static void *dpiOci__allocateMem(UNUSED void *unused, size_t size) +{ + void *ptr; + + ptr = malloc(size); + dpiDebug__print("OCI allocated %u bytes at %p\n", size, ptr); + return ptr; +} + + +//----------------------------------------------------------------------------- +// dpiOci__aqDeq() [INTERNAL] +// Wrapper for OCIAQDeq(). +//----------------------------------------------------------------------------- +int dpiOci__aqDeq(dpiConn *conn, const char *queueName, void *options, + void *msgProps, void *payloadType, void **payload, void **payloadInd, + void **msgId, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIAQDeq", dpiOciSymbols.fnAqDeq) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnAqDeq)(conn->handle, error->handle, queueName, + options, msgProps, payloadType, payload, payloadInd, msgId, + DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "dequeue message"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__aqDeqArray() [INTERNAL] +// Wrapper for OCIAQDeqArray(). +//----------------------------------------------------------------------------- +int dpiOci__aqDeqArray(dpiConn *conn, const char *queueName, void *options, + uint32_t *numIters, void **msgProps, void *payloadType, void **payload, + void **payloadInd, void **msgId, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIAQDeqArray", dpiOciSymbols.fnAqDeqArray) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnAqDeqArray)(conn->handle, error->handle, + queueName, options, numIters, msgProps, payloadType, payload, + payloadInd, msgId, NULL, NULL, DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "dequeue messages"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__aqEnq() [INTERNAL] +// Wrapper for OCIAQEnq(). +//----------------------------------------------------------------------------- +int dpiOci__aqEnq(dpiConn *conn, const char *queueName, void *options, + void *msgProps, void *payloadType, void **payload, void **payloadInd, + void **msgId, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIAQEnq", dpiOciSymbols.fnAqEnq) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnAqEnq)(conn->handle, error->handle, queueName, + options, msgProps, payloadType, payload, payloadInd, msgId, + DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "enqueue message"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__aqEnqArray() [INTERNAL] +// Wrapper for OCIAQEnqArray(). +//----------------------------------------------------------------------------- +int dpiOci__aqEnqArray(dpiConn *conn, const char *queueName, void *options, + uint32_t *numIters, void **msgProps, void *payloadType, void **payload, + void **payloadInd, void **msgId, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIAQEnqArray", dpiOciSymbols.fnAqEnqArray) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnAqEnqArray)(conn->handle, error->handle, + queueName, options, numIters, msgProps, payloadType, payload, + payloadInd, msgId, NULL, NULL, DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "enqueue messages"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__arrayDescriptorAlloc() [INTERNAL] +// Wrapper for OCIArrayDescriptorAlloc(). +//----------------------------------------------------------------------------- +int dpiOci__arrayDescriptorAlloc(void *envHandle, void **handle, + uint32_t handleType, uint32_t arraySize, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIArrayDescriptorAlloc", + dpiOciSymbols.fnArrayDescriptorAlloc) + status = (*dpiOciSymbols.fnArrayDescriptorAlloc)(envHandle, handle, + handleType, arraySize, 0, NULL); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "allocate descriptors"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__arrayDescriptorFree() [INTERNAL] +// Wrapper for OCIArrayDescriptorFree(). +//----------------------------------------------------------------------------- +int dpiOci__arrayDescriptorFree(void **handle, uint32_t handleType) +{ + dpiError *error = NULL; + int status; + + DPI_OCI_LOAD_SYMBOL("OCIArrayDescriptorFree", + dpiOciSymbols.fnArrayDescriptorFree) + status = (*dpiOciSymbols.fnArrayDescriptorFree)(handle, handleType); + if (status != DPI_OCI_SUCCESS && dpiDebugLevel & DPI_DEBUG_LEVEL_FREES) + dpiDebug__print("free array descriptors %p, handleType %d failed\n", + handle, handleType); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__attrGet() [INTERNAL] +// Wrapper for OCIAttrGet(). +//----------------------------------------------------------------------------- +int dpiOci__attrGet(const void *handle, uint32_t handleType, void *ptr, + uint32_t *size, uint32_t attribute, const char *action, + dpiError *error) +{ + int status; + + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnAttrGet)(handle, handleType, ptr, size, + attribute, error->handle); + if (!action) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); +} + + +//----------------------------------------------------------------------------- +// dpiOci__attrSet() [INTERNAL] +// Wrapper for OCIAttrSet(). +//----------------------------------------------------------------------------- +int dpiOci__attrSet(void *handle, uint32_t handleType, void *ptr, + uint32_t size, uint32_t attribute, const char *action, dpiError *error) +{ + int status; + + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnAttrSet)(handle, handleType, ptr, size, + attribute, error->handle); + if (!action) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); +} + + +//----------------------------------------------------------------------------- +// dpiOci__bindByName() [INTERNAL] +// Wrapper for OCIBindByName(). +//----------------------------------------------------------------------------- +int dpiOci__bindByName(dpiStmt *stmt, void **bindHandle, const char *name, + int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIBindByName", dpiOciSymbols.fnBindByName) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnBindByName)(stmt->handle, bindHandle, + error->handle, name, nameLength, + (dynamicBind) ? NULL : var->buffer.data.asRaw, + (var->isDynamic) ? INT_MAX : (int32_t) var->sizeInBytes, + var->type->oracleType, (dynamicBind) ? NULL : + var->buffer.indicator, + (dynamicBind || var->type->sizeInBytes) ? NULL : + var->buffer.actualLength16, + (dynamicBind) ? NULL : var->buffer.returnCode, + (var->isArray) ? var->buffer.maxArraySize : 0, + (var->isArray) ? &var->buffer.actualArraySize : NULL, + (dynamicBind) ? DPI_OCI_DATA_AT_EXEC : DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by name"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__bindByName2() [INTERNAL] +// Wrapper for OCIBindByName2(). +//----------------------------------------------------------------------------- +int dpiOci__bindByName2(dpiStmt *stmt, void **bindHandle, const char *name, + int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIBindByName2", dpiOciSymbols.fnBindByName2) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnBindByName2)(stmt->handle, bindHandle, + error->handle, name, nameLength, + (dynamicBind) ? NULL : var->buffer.data.asRaw, + (var->isDynamic) ? INT_MAX : var->sizeInBytes, + var->type->oracleType, (dynamicBind) ? NULL : + var->buffer.indicator, + (dynamicBind || var->type->sizeInBytes) ? NULL : + var->buffer.actualLength32, + (dynamicBind) ? NULL : var->buffer.returnCode, + (var->isArray) ? var->buffer.maxArraySize : 0, + (var->isArray) ? &var->buffer.actualArraySize : NULL, + (dynamicBind) ? DPI_OCI_DATA_AT_EXEC : DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by name"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__bindByPos() [INTERNAL] +// Wrapper for OCIBindByPos(). +//----------------------------------------------------------------------------- +int dpiOci__bindByPos(dpiStmt *stmt, void **bindHandle, uint32_t pos, + int dynamicBind, dpiVar *var, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIBindByPos", dpiOciSymbols.fnBindByPos) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnBindByPos)(stmt->handle, bindHandle, + error->handle, pos, (dynamicBind) ? NULL : var->buffer.data.asRaw, + (var->isDynamic) ? INT_MAX : (int32_t) var->sizeInBytes, + var->type->oracleType, (dynamicBind) ? NULL : + var->buffer.indicator, + (dynamicBind || var->type->sizeInBytes) ? NULL : + var->buffer.actualLength16, + (dynamicBind) ? NULL : var->buffer.returnCode, + (var->isArray) ? var->buffer.maxArraySize : 0, + (var->isArray) ? &var->buffer.actualArraySize : NULL, + (dynamicBind) ? DPI_OCI_DATA_AT_EXEC : DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by position"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__bindByPos2() [INTERNAL] +// Wrapper for OCIBindByPos2(). +//----------------------------------------------------------------------------- +int dpiOci__bindByPos2(dpiStmt *stmt, void **bindHandle, uint32_t pos, + int dynamicBind, dpiVar *var, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIBindByPos2", dpiOciSymbols.fnBindByPos2) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnBindByPos2)(stmt->handle, bindHandle, + error->handle, pos, (dynamicBind) ? NULL : var->buffer.data.asRaw, + (var->isDynamic) ? INT_MAX : var->sizeInBytes, + var->type->oracleType, (dynamicBind) ? NULL : + var->buffer.indicator, + (dynamicBind || var->type->sizeInBytes) ? NULL : + var->buffer.actualLength32, + (dynamicBind) ? NULL : var->buffer.returnCode, + (var->isArray) ? var->buffer.maxArraySize : 0, + (var->isArray) ? &var->buffer.actualArraySize : NULL, + (dynamicBind) ? DPI_OCI_DATA_AT_EXEC : DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by position"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__bindDynamic() [INTERNAL] +// Wrapper for OCIBindDynamic(). +//----------------------------------------------------------------------------- +int dpiOci__bindDynamic(dpiVar *var, void *bindHandle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIBindDynamic", dpiOciSymbols.fnBindDynamic) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnBindDynamic)(bindHandle, error->handle, var, + (void*) dpiVar__inBindCallback, var, + (void*) dpiVar__outBindCallback); + DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "bind dynamic"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__bindObject() [INTERNAL] +// Wrapper for OCIBindObject(). +//----------------------------------------------------------------------------- +int dpiOci__bindObject(dpiVar *var, void *bindHandle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIBindObject", dpiOciSymbols.fnBindObject) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnBindObject)(bindHandle, error->handle, + var->objectType->tdo, (void**) var->buffer.data.asRaw, 0, + var->buffer.objectIndicator, 0); + DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "bind object"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__break() [INTERNAL] +// Wrapper for OCIBreak(). +//----------------------------------------------------------------------------- +int dpiOci__break(dpiConn *conn, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIBreak", dpiOciSymbols.fnBreak) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnBreak)(conn->handle, error->handle); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "break execution"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__clientVersion() [INTERNAL] +// Set the version information in the context to the OCI client version +// information that was discovered when the OCI library was loaded. +//----------------------------------------------------------------------------- +void dpiOci__clientVersion(dpiContext *context) +{ + context->versionInfo = &dpiOciLibVersionInfo; +} + + +//----------------------------------------------------------------------------- +// dpiOci__collAppend() [INTERNAL] +// Wrapper for OCICollAppend(). +//----------------------------------------------------------------------------- +int dpiOci__collAppend(dpiConn *conn, const void *elem, const void *elemInd, + void *coll, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCICollAppend", dpiOciSymbols.fnCollAppend) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnCollAppend)(conn->env->handle, error->handle, + elem, elemInd, coll); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "append element"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__collAssignElem() [INTERNAL] +// Wrapper for OCICollAssignElem(). +//----------------------------------------------------------------------------- +int dpiOci__collAssignElem(dpiConn *conn, int32_t index, const void *elem, + const void *elemInd, void *coll, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCICollAssignElem", dpiOciSymbols.fnCollAssignElem) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnCollAssignElem)(conn->env->handle, + error->handle, index, elem, elemInd, coll); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "assign element"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__collGetElem() [INTERNAL] +// Wrapper for OCICollGetElem(). +//----------------------------------------------------------------------------- +int dpiOci__collGetElem(dpiConn *conn, void *coll, int32_t index, int *exists, + void **elem, void **elemInd, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCICollGetElem", dpiOciSymbols.fnCollGetElem) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnCollGetElem)(conn->env->handle, error->handle, + coll, index, exists, elem, elemInd); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get element"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__collSize() [INTERNAL] +// Wrapper for OCICollSize(). +//----------------------------------------------------------------------------- +int dpiOci__collSize(dpiConn *conn, void *coll, int32_t *size, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCICollSize", dpiOciSymbols.fnCollSize) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnCollSize)(conn->env->handle, error->handle, + coll, size); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get size"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__collTrim() [INTERNAL] +// Wrapper for OCICollTrim(). +//----------------------------------------------------------------------------- +int dpiOci__collTrim(dpiConn *conn, uint32_t numToTrim, void *coll, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCICollTrim", dpiOciSymbols.fnCollTrim) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnCollTrim)(conn->env->handle, error->handle, + (int32_t) numToTrim, coll); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "trim"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__contextGetValue() [INTERNAL] +// Wrapper for OCIContextGetValue(). +//----------------------------------------------------------------------------- +int dpiOci__contextGetValue(dpiConn *conn, const char *key, uint32_t keyLength, + void **value, int checkError, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIContextGetValue", dpiOciSymbols.fnContextGetValue) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnContextGetValue)(conn->sessionHandle, + error->handle, key, (uint8_t) keyLength, value); + if (!checkError) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get context value"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__contextSetValue() [INTERNAL] +// Wrapper for OCIContextSetValue(). +//----------------------------------------------------------------------------- +int dpiOci__contextSetValue(dpiConn *conn, const char *key, uint32_t keyLength, + void *value, int checkError, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIContextSetValue", dpiOciSymbols.fnContextSetValue) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnContextSetValue)(conn->sessionHandle, + error->handle, DPI_OCI_DURATION_SESSION, key, (uint8_t) keyLength, + value); + if (!checkError) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "set context value"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__dateTimeConstruct() [INTERNAL] +// Wrapper for OCIDateTimeConstruct(). +//----------------------------------------------------------------------------- +int dpiOci__dateTimeConstruct(void *envHandle, void *handle, int16_t year, + uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, + uint8_t second, uint32_t fsecond, const char *tz, size_t tzLength, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDateTimeConstruct", + dpiOciSymbols.fnDateTimeConstruct) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDateTimeConstruct)(envHandle, error->handle, + handle, year, month, day, hour, minute, second, fsecond, tz, + tzLength); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "construct date"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__dateTimeConvert() [INTERNAL] +// Wrapper for OCIDateTimeConvert(). +//----------------------------------------------------------------------------- +int dpiOci__dateTimeConvert(void *envHandle, void *inDate, void *outDate, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDateTimeConvert", dpiOciSymbols.fnDateTimeConvert) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDateTimeConvert)(envHandle, error->handle, + inDate, outDate); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "convert date"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__dateTimeGetDate() [INTERNAL] +// Wrapper for OCIDateTimeGetDate(). +//----------------------------------------------------------------------------- +int dpiOci__dateTimeGetDate(void *envHandle, void *handle, int16_t *year, + uint8_t *month, uint8_t *day, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDateTimeGetDate", dpiOciSymbols.fnDateTimeGetDate) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDateTimeGetDate)(envHandle, error->handle, + handle, year, month, day); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get date portion"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__dateTimeGetTime() [INTERNAL] +// Wrapper for OCIDateTimeGetTime(). +//----------------------------------------------------------------------------- +int dpiOci__dateTimeGetTime(void *envHandle, void *handle, uint8_t *hour, + uint8_t *minute, uint8_t *second, uint32_t *fsecond, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDateTimeGetTime", dpiOciSymbols.fnDateTimeGetTime) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDateTimeGetTime)(envHandle, error->handle, + handle, hour, minute, second, fsecond); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get time portion"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__dateTimeGetTimeZoneOffset() [INTERNAL] +// Wrapper for OCIDateTimeGetTimeZoneOffset(). +//----------------------------------------------------------------------------- +int dpiOci__dateTimeGetTimeZoneOffset(void *envHandle, void *handle, + int8_t *tzHourOffset, int8_t *tzMinuteOffset, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDateTimeGetTimeZoneOffset", + dpiOciSymbols.fnDateTimeGetTimeZoneOffset) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDateTimeGetTimeZoneOffset)(envHandle, + error->handle, handle, tzHourOffset, tzMinuteOffset); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get time zone portion"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__dateTimeIntervalAdd() [INTERNAL] +// Wrapper for OCIDateTimeIntervalAdd(). +//----------------------------------------------------------------------------- +int dpiOci__dateTimeIntervalAdd(void *envHandle, void *handle, void *interval, + void *outHandle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDateTimeIntervalAdd", + dpiOciSymbols.fnDateTimeIntervalAdd) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDateTimeIntervalAdd)(envHandle, error->handle, + handle, interval, outHandle); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "add interval to date"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__dateTimeSubtract() [INTERNAL] +// Wrapper for OCIDateTimeSubtract(). +//----------------------------------------------------------------------------- +int dpiOci__dateTimeSubtract(void *envHandle, void *handle1, void *handle2, + void *interval, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDateTimeSubtract", + dpiOciSymbols.fnDateTimeSubtract) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDateTimeSubtract)(envHandle, error->handle, + handle1, handle2, interval); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "subtract date"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__dbShutdown() [INTERNAL] +// Wrapper for OCIDBShutdown(). +//----------------------------------------------------------------------------- +int dpiOci__dbShutdown(dpiConn *conn, uint32_t mode, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDBShutdown", dpiOciSymbols.fnDbShutdown) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDbShutdown)(conn->handle, error->handle, NULL, + mode); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "shutdown database"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__dbStartup() [INTERNAL] +// Wrapper for OCIDBStartup(). +//----------------------------------------------------------------------------- +int dpiOci__dbStartup(dpiConn *conn, uint32_t mode, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDBStartup", dpiOciSymbols.fnDbStartup) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDbStartup)(conn->handle, error->handle, NULL, + DPI_OCI_DEFAULT, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "startup database"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__defineByPos() [INTERNAL] +// Wrapper for OCIDefineByPos(). +//----------------------------------------------------------------------------- +int dpiOci__defineByPos(dpiStmt *stmt, void **defineHandle, uint32_t pos, + dpiVar *var, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDefineByPos", dpiOciSymbols.fnDefineByPos) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDefineByPos)(stmt->handle, defineHandle, + error->handle, pos, (var->isDynamic) ? NULL : + var->buffer.data.asRaw, + (var->isDynamic) ? INT_MAX : (int32_t) var->sizeInBytes, + var->type->oracleType, (var->isDynamic) ? NULL : + var->buffer.indicator, + (var->isDynamic) ? NULL : var->buffer.actualLength16, + (var->isDynamic) ? NULL : var->buffer.returnCode, + (var->isDynamic) ? DPI_OCI_DYNAMIC_FETCH : DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "define"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__defineByPos2() [INTERNAL] +// Wrapper for OCIDefineByPos2(). +//----------------------------------------------------------------------------- +int dpiOci__defineByPos2(dpiStmt *stmt, void **defineHandle, uint32_t pos, + dpiVar *var, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDefineByPos2", dpiOciSymbols.fnDefineByPos2) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDefineByPos2)(stmt->handle, defineHandle, + error->handle, pos, (var->isDynamic) ? NULL : + var->buffer.data.asRaw, + (var->isDynamic) ? INT_MAX : var->sizeInBytes, + var->type->oracleType, (var->isDynamic) ? NULL : + var->buffer.indicator, + (var->isDynamic) ? NULL : var->buffer.actualLength32, + (var->isDynamic) ? NULL : var->buffer.returnCode, + (var->isDynamic) ? DPI_OCI_DYNAMIC_FETCH : DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "define"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__defineDynamic() [INTERNAL] +// Wrapper for OCIDefineDynamic(). +//----------------------------------------------------------------------------- +int dpiOci__defineDynamic(dpiVar *var, void *defineHandle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDefineDynamic", dpiOciSymbols.fnDefineDynamic) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDefineDynamic)(defineHandle, error->handle, var, + (void*) dpiVar__defineCallback); + DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "define dynamic"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__defineObject() [INTERNAL] +// Wrapper for OCIDefineObject(). +//----------------------------------------------------------------------------- +int dpiOci__defineObject(dpiVar *var, void *defineHandle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDefineObject", dpiOciSymbols.fnDefineObject) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDefineObject)(defineHandle, error->handle, + var->objectType->tdo, (void**) var->buffer.data.asRaw, 0, + var->buffer.objectIndicator, 0); + DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "define object"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__describeAny() [INTERNAL] +// Wrapper for OCIDescribeAny(). +//----------------------------------------------------------------------------- +int dpiOci__describeAny(dpiConn *conn, void *obj, uint32_t objLength, + uint8_t objType, void *describeHandle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDescribeAny", dpiOciSymbols.fnDescribeAny) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnDescribeAny)(conn->handle, error->handle, obj, + objLength, objType, 0, DPI_OCI_PTYPE_TYPE, describeHandle); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "describe type"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__descriptorAlloc() [INTERNAL] +// Wrapper for OCIDescriptorAlloc(). +//----------------------------------------------------------------------------- +int dpiOci__descriptorAlloc(void *envHandle, void **handle, + const uint32_t handleType, const char *action, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDescriptorAlloc", dpiOciSymbols.fnDescriptorAlloc) + status = (*dpiOciSymbols.fnDescriptorAlloc)(envHandle, handle, handleType, + 0, NULL); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); +} + + +//----------------------------------------------------------------------------- +// dpiOci__descriptorFree() [INTERNAL] +// Wrapper for OCIDescriptorFree(). +//----------------------------------------------------------------------------- +int dpiOci__descriptorFree(void *handle, uint32_t handleType) +{ + dpiError *error = NULL; + int status; + + DPI_OCI_LOAD_SYMBOL("OCIDescriptorFree", dpiOciSymbols.fnDescriptorFree) + status = (*dpiOciSymbols.fnDescriptorFree)(handle, handleType); + if (status != DPI_OCI_SUCCESS && dpiDebugLevel & DPI_DEBUG_LEVEL_FREES) + dpiDebug__print("free descriptor %p, type %d failed\n", handle, + handleType); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__envNlsCreate() [INTERNAL] +// Wrapper for OCIEnvNlsCreate(). +//----------------------------------------------------------------------------- +int dpiOci__envNlsCreate(void **envHandle, uint32_t mode, uint16_t charsetId, + uint16_t ncharsetId, dpiError *error) +{ + void *mallocFn = NULL, *reallocFn = NULL, *freeFn = NULL; + int status; + + *envHandle = NULL; + DPI_OCI_LOAD_SYMBOL("OCIEnvNlsCreate", dpiOciSymbols.fnEnvNlsCreate) + if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM) { + mallocFn = (void*) dpiOci__allocateMem; + reallocFn = (void*) dpiOci__reallocMem; + freeFn = (void*) dpiOci__freeMem; + } + status = (*dpiOciSymbols.fnEnvNlsCreate)(envHandle, mode, NULL, mallocFn, + reallocFn, freeFn, 0, NULL, charsetId, ncharsetId); + if (*envHandle) { + if (status == DPI_OCI_SUCCESS || status == DPI_OCI_SUCCESS_WITH_INFO) + return DPI_SUCCESS; + if (dpiOci__errorGet(*envHandle, DPI_OCI_HTYPE_ENV, charsetId, + "create env", error) == 0) + return DPI_FAILURE; + } + return dpiError__set(error, "create env", DPI_ERR_CREATE_ENV); +} + + +//----------------------------------------------------------------------------- +// dpiOci__errorGet() [INTERNAL] +// Wrapper for OCIErrorGet(). +//----------------------------------------------------------------------------- +int dpiOci__errorGet(void *handle, uint32_t handleType, uint16_t charsetId, + const char *action, dpiError *error) +{ + uint32_t i, numChars, bufferChars; + uint16_t *utf16chars; + int status; + char *ptr; + + DPI_OCI_LOAD_SYMBOL("OCIErrorGet", dpiOciSymbols.fnErrorGet) + status = (*dpiOciSymbols.fnErrorGet)(handle, 1, NULL, &error->buffer->code, + error->buffer->message, sizeof(error->buffer->message), + handleType); + if (status != DPI_OCI_SUCCESS) + return dpiError__set(error, action, DPI_ERR_GET_FAILED); + error->buffer->action = action; + + // determine length of message since OCI does not provide this information; + // all encodings except UTF-16 can use normal string processing; cannot use + // type whar_t for processing UTF-16, though, as its size may be 4 on some + // platforms, not 2; also strip trailing whitespace from error messages + if (charsetId == DPI_CHARSET_ID_UTF16) { + numChars = 0; + utf16chars = (uint16_t*) error->buffer->message; + bufferChars = sizeof(error->buffer->message) / 2; + for (i = 0; i < bufferChars; i++) { + if (utf16chars[i] == 0) + break; + if (utf16chars[i] > 127 || !isspace(utf16chars[i])) + numChars = i + 1; + } + error->buffer->messageLength = numChars * 2; + } else { + error->buffer->messageLength = + (uint32_t) strlen(error->buffer->message); + ptr = error->buffer->message + error->buffer->messageLength - 1; + while (ptr > error->buffer->message && isspace((uint8_t) *ptr--)) + error->buffer->messageLength--; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__freeMem() [INTERNAL] +// Wrapper for OCI allocation of memory, only used when debugging memory +// allocation. +//----------------------------------------------------------------------------- +static void dpiOci__freeMem(UNUSED void *unused, void *ptr) +{ + char message[40]; + + (void) sprintf(message, "OCI freed ptr at %p", ptr); + free(ptr); + dpiDebug__print("%s\n", message); +} + + +//----------------------------------------------------------------------------- +// dpiOci__handleAlloc() [INTERNAL] +// Wrapper for OCIHandleAlloc(). +//----------------------------------------------------------------------------- +int dpiOci__handleAlloc(void *envHandle, void **handle, uint32_t handleType, + const char *action, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIHandleAlloc", dpiOciSymbols.fnHandleAlloc) + status = (*dpiOciSymbols.fnHandleAlloc)(envHandle, handle, handleType, 0, + NULL); + if (handleType == DPI_OCI_HTYPE_ERROR && status != DPI_OCI_SUCCESS) + return dpiError__set(error, action, DPI_ERR_NO_MEMORY); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); +} + + +//----------------------------------------------------------------------------- +// dpiOci__handleFree() [INTERNAL] +// Wrapper for OCIHandleFree(). +//----------------------------------------------------------------------------- +int dpiOci__handleFree(void *handle, uint32_t handleType) +{ + dpiError *error = NULL; + int status; + + DPI_OCI_LOAD_SYMBOL("OCIHandleFree", dpiOciSymbols.fnHandleFree) + status = (*dpiOciSymbols.fnHandleFree)(handle, handleType); + if (status != DPI_OCI_SUCCESS && dpiDebugLevel & DPI_DEBUG_LEVEL_FREES) + dpiDebug__print("free handle %p, handleType %d failed\n", handle, + handleType); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__intervalGetDaySecond() [INTERNAL] +// Wrapper for OCIIntervalGetDaySecond(). +//----------------------------------------------------------------------------- +int dpiOci__intervalGetDaySecond(void *envHandle, int32_t *day, int32_t *hour, + int32_t *minute, int32_t *second, int32_t *fsecond, + const void *interval, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIIntervalGetDaySecond", + dpiOciSymbols.fnIntervalGetDaySecond) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnIntervalGetDaySecond)(envHandle, + error->handle, day, hour, minute, second, fsecond, interval); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get interval components"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__intervalGetYearMonth() [INTERNAL] +// Wrapper for OCIIntervalGetYearMonth(). +//----------------------------------------------------------------------------- +int dpiOci__intervalGetYearMonth(void *envHandle, int32_t *year, + int32_t *month, const void *interval, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIIntervalGetYearMonth", + dpiOciSymbols.fnIntervalGetYearMonth) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnIntervalGetYearMonth)(envHandle, error->handle, + year, month, interval); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get interval components"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__intervalSetDaySecond() [INTERNAL] +// Wrapper for OCIIntervalSetDaySecond(). +//----------------------------------------------------------------------------- +int dpiOci__intervalSetDaySecond(void *envHandle, int32_t day, int32_t hour, + int32_t minute, int32_t second, int32_t fsecond, void *interval, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIIntervalSetDaySecond", + dpiOciSymbols.fnIntervalSetDaySecond) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnIntervalSetDaySecond)(envHandle, error->handle, + day, hour, minute, second, fsecond, interval); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "set interval components"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__intervalSetYearMonth() [INTERNAL] +// Wrapper for OCIIntervalSetYearMonth(). +//----------------------------------------------------------------------------- +int dpiOci__intervalSetYearMonth(void *envHandle, int32_t year, int32_t month, + void *interval, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIIntervalSetYearMonth", + dpiOciSymbols.fnIntervalSetYearMonth) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnIntervalSetYearMonth)(envHandle, error->handle, + year, month, interval); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "set interval components"); +} + + +#ifdef _WIN32 +//----------------------------------------------------------------------------- +// dpiOci__checkDllArchitecture() [INTERNAL] +// Check the architecture of the specified DLL name and check that it +// matches the expected architecture. Returns -1 if the DLL architecture could +// not be determined, 0 if it does not match and 1 if it matches. +//----------------------------------------------------------------------------- +static int dpiOci__checkDllArchitecture(const char *name) +{ + IMAGE_DOS_HEADER dosHeader; + IMAGE_NT_HEADERS ntHeaders; + FILE *fp; + + fp = fopen(name, "rb"); + if (!fp) + return -1; + fread(&dosHeader, sizeof(dosHeader), 1, fp); + if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) { + fclose(fp); + return -1; + } + fseek(fp, dosHeader.e_lfanew, SEEK_SET); + fread(&ntHeaders, sizeof(ntHeaders), 1, fp); + fclose(fp); + if (ntHeaders.Signature != IMAGE_NT_SIGNATURE) + return -1; +#if defined _M_AMD64 + if (ntHeaders.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) + return 1; +#elif defined _M_IX86 + if (ntHeaders.FileHeader.Machine == IMAGE_FILE_MACHINE_I386) + return 1; +#endif + return 0; +} + + +//----------------------------------------------------------------------------- +// dpiOci__findAndCheckDllArchitecture() [INTERNAL] +// Attempt to find the specified DLL name using the standard search path and +// if the DLL can be found but is of the wrong architecture, include the full +// name of the DLL in the load error. Return -1 if such a DLL could not be +// found and 0 if the load error was changed. +//----------------------------------------------------------------------------- +static int dpiOci__findAndCheckDllArchitecture(const char *dllName, + char *loadError, size_t loadErrorLength) +{ + char fullName[_MAX_PATH + 1], *path, *temp; + size_t length; + int found = 0; + + // first search executable directory + if (GetModuleFileName(NULL, fullName, sizeof(fullName)) != 0) { + temp = strrchr(fullName, '\\'); + if (temp) { + *(temp + 1) = '\0'; + strncat(fullName, dllName, + sizeof(fullName) - strlen(fullName) - 1); + if (dpiOci__checkDllArchitecture(fullName) == 0) + found = 1; + } + } + + // check current directory + if (!found && GetCurrentDirectory(sizeof(fullName), fullName) != 0) { + temp = fullName + strlen(fullName); + snprintf(temp, sizeof(fullName) - strlen(fullName), "\\%s", dllName); + if (dpiOci__checkDllArchitecture(fullName) == 0) + found = 1; + } + + // search PATH + path = getenv("PATH"); + if (path) { + while (!found) { + temp = strchr(path, ';'); + if (!temp) + length = strlen(path); + else length = temp - path; + if (length <= _MAX_DIR) { + snprintf(fullName, sizeof(fullName), "%.*s\\%s", (int) length, + path, dllName); + if (dpiOci__checkDllArchitecture(fullName) == 0) { + found = 1; + break; + } + } + if (!temp) + break; + path = temp + 1; + } + } + + // if found, adjust the load error + if (found) { + snprintf(loadError, loadErrorLength, + "%s is not the correct architecture", fullName); + loadError[loadErrorLength - 1] = '\0'; + return 0; + } + + return -1; +} + + +//----------------------------------------------------------------------------- +// dpiOci__getLoadErrorOnWindows() [INTERNAL] +// Get the error message for a load failure on Windows. +//----------------------------------------------------------------------------- +static void dpiOci__getLoadErrorOnWindows(const char *dllName, + char *loadError, size_t loadErrorLength) +{ + DWORD length = 0, errorNum, status; + wchar_t *wLoadError = NULL; + + // if DLL is of the wrong architecture, attempt to locate the DLL that was + // loaded and use that information if it can be found + errorNum = GetLastError(); + if (errorNum == ERROR_BAD_EXE_FORMAT && + dpiOci__findAndCheckDllArchitecture(dllName, loadError, + loadErrorLength) == 0) + return; + + // get error message in Unicode first + // use English unless English error messages aren't available + status = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, errorNum, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + (LPWSTR) &wLoadError, 0, NULL); + if (!status && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, errorNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPWSTR) &wLoadError, 0, NULL); + + if (wLoadError) { + + // strip trailing period and carriage return from message, if needed + length = (DWORD) wcslen(wLoadError); + while (length > 0) { + if (wLoadError[length - 1] > 127 || + (wLoadError[length - 1] != L'.' && + !isspace(wLoadError[length - 1]))) + break; + length--; + } + wLoadError[length] = L'\0'; + + // convert to a multi-byte string in UTF-8 encoding + if (length > 0) + length = WideCharToMultiByte(CP_UTF8, 0, wLoadError, -1, loadError, + (int) loadErrorLength, NULL, NULL); + LocalFree(wLoadError); + + } + + // fallback in case message cannot be determined + if (length == 0) + sprintf(loadError, "DLL load failed: Windows Error %d", errorNum); +} + + +//----------------------------------------------------------------------------- +// dpiOci__loadLibOnWindows() [INTERNAL] +// Load the library on the Windows platform. First an attempt is made to +// determine the location of the module containing ODPI-C. If found, an attempt +// is made to load oci.dll from that location; otherwise a standard Windows +// search is made for oci.dll. +//----------------------------------------------------------------------------- +static void dpiOci__loadLibOnWindows(const char *dllName) +{ + char moduleName[MAX_PATH + 1], *temp; + HMODULE module = NULL; + + // attempt to determine the location of the module containing ODPI-C; + // errors in this code are ignored and the normal loading mechanism is + // used instead + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCSTR) dpiOci__loadLibOnWindows, &module)) { + if (GetModuleFileName(module, moduleName, sizeof(moduleName)) > 0) { + temp = strrchr(moduleName, '\\'); + if (temp) { + *(temp + 1) = '\0'; + strncat(moduleName, dllName, + sizeof(moduleName) - strlen(moduleName) - 1); + dpiOciLibHandle = LoadLibrary(moduleName); + } + } + FreeLibrary(module); + } + + // if library was not loaded in the same location as ODPI-C, use the + // standard Windows search to locate oci.dll instead + if (!dpiOciLibHandle) + dpiOciLibHandle = LoadLibrary(dllName); +} +#endif + + +//----------------------------------------------------------------------------- +// dpiOci__loadLib() [INTERNAL] +// Load the OCI library. +//----------------------------------------------------------------------------- +static int dpiOci__loadLib(dpiError *error) +{ + const char *libName; + char loadError[512]; + unsigned int i; +#ifndef _WIN32 + char *oracleHome, *oracleHomeLibName; + size_t oracleHomeLibNameLength; +#endif + + // dynamically load the OCI library + for (i = 0; !dpiOciLibHandle; i++) { + libName = dpiOciLibNames[i]; + if (!libName) + break; +#ifdef _WIN32 + dpiOci__loadLibOnWindows(libName); + if (!dpiOciLibHandle && i == 0) + dpiOci__getLoadErrorOnWindows(libName, loadError, + sizeof(loadError)); +#else + dpiOciLibHandle = dlopen(libName, RTLD_LAZY); + if (!dpiOciLibHandle && i == 0) { + strncpy(loadError, dlerror(), sizeof(loadError) - 1); + loadError[sizeof(loadError) - 1] = '\0'; + } +#endif + + } + +#ifndef _WIN32 + // on platforms other than Windows, attempt to use + // $ORACLE_HOME/lib/libclntsh.so + if (!dpiOciLibHandle) { + oracleHome = getenv("ORACLE_HOME"); + if (oracleHome) { + oracleHomeLibNameLength = strlen(oracleHome) + 6 + + strlen(dpiOciLibNames[0]); + oracleHomeLibName = (char*) malloc(oracleHomeLibNameLength); + if (oracleHomeLibName) { + (void) sprintf(oracleHomeLibName, "%s/lib/%s", oracleHome, + dpiOciLibNames[0]); + dpiOciLibHandle = dlopen(oracleHomeLibName, RTLD_LAZY); + free(oracleHomeLibName); + } + } + } +#endif + + if (!dpiOciLibHandle) { + const char *bits = (sizeof(void*) == 8) ? "64" : "32"; + return dpiError__set(error, "load library", DPI_ERR_LOAD_LIBRARY, + bits, loadError, DPI_ERR_LOAD_URL_FRAGMENT); + } + + // validate library + if (dpiOci__loadLibValidate(error) < 0) { +#ifdef _WIN32 + FreeLibrary(dpiOciLibHandle); +#else + dlclose(dpiOciLibHandle); +#endif + dpiOciLibHandle = NULL; + memset(&dpiOciSymbols, 0, sizeof(dpiOciSymbols)); + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__loadLibValidate() [INTERNAL] +// Validate the OCI library after loading. +//----------------------------------------------------------------------------- +static int dpiOci__loadLibValidate(dpiError *error) +{ + // determine the OCI client version information + if (dpiOci__loadSymbol("OCIClientVersion", + (void**) &dpiOciSymbols.fnClientVersion, NULL) < 0) + return dpiError__set(error, "load symbol OCIClientVersion", + DPI_ERR_ORACLE_CLIENT_UNSUPPORTED); + memset(&dpiOciLibVersionInfo, 0, sizeof(dpiOciLibVersionInfo)); + (*dpiOciSymbols.fnClientVersion)(&dpiOciLibVersionInfo.versionNum, + &dpiOciLibVersionInfo.releaseNum, + &dpiOciLibVersionInfo.updateNum, + &dpiOciLibVersionInfo.portReleaseNum, + &dpiOciLibVersionInfo.portUpdateNum); + if (dpiOciLibVersionInfo.versionNum == 0) + return dpiError__set(error, "get OCI client version", + DPI_ERR_ORACLE_CLIENT_UNSUPPORTED); + dpiOciLibVersionInfo.fullVersionNum = (uint32_t) + DPI_ORACLE_VERSION_TO_NUMBER(dpiOciLibVersionInfo.versionNum, + dpiOciLibVersionInfo.releaseNum, + dpiOciLibVersionInfo.updateNum, + dpiOciLibVersionInfo.portReleaseNum, + dpiOciLibVersionInfo.portUpdateNum); + + // OCI version must be a minimum of 11.2 + if (dpiUtils__checkClientVersion(&dpiOciLibVersionInfo, 11, 2, error) < 0) + return DPI_FAILURE; + + // initialize threading capability in the OCI library + // this must be run prior to any other OCI threading calls + DPI_OCI_LOAD_SYMBOL("OCIThreadProcessInit", + dpiOciSymbols.fnThreadProcessInit) + (*dpiOciSymbols.fnThreadProcessInit)(); + + // load symbols for key functions which are called many times + // this list should be kept as small as possible in order to avoid + // overhead in looking up symbols at startup + DPI_OCI_LOAD_SYMBOL("OCIAttrGet", dpiOciSymbols.fnAttrGet) + DPI_OCI_LOAD_SYMBOL("OCIAttrSet", dpiOciSymbols.fnAttrSet) + DPI_OCI_LOAD_SYMBOL("OCIThreadKeyGet", dpiOciSymbols.fnThreadKeyGet) + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__loadSymbol() [INTERNAL] +// Return the symbol for the function that is to be called. The symbol table +// is first consulted. If the symbol is not found there, it is looked up and +// then stored there so the next invocation does not have to perform the +// lookup. +//----------------------------------------------------------------------------- +static int dpiOci__loadSymbol(const char *symbolName, void **symbol, + dpiError *error) +{ + // if library not already opened, open it + if (!dpiOciLibHandle && dpiOci__loadLib(error) < 0) + return DPI_FAILURE; + + // load symbol +#ifdef _WIN32 + *symbol = GetProcAddress(dpiOciLibHandle, symbolName); +#else + *symbol = dlsym(dpiOciLibHandle, symbolName); +#endif + if (!*symbol) + return dpiError__set(error, "get symbol", DPI_ERR_LOAD_SYMBOL, + symbolName); + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobClose() [INTERNAL] +// Wrapper for OCILobClose(). +//----------------------------------------------------------------------------- +int dpiOci__lobClose(dpiLob *lob, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobClose", dpiOciSymbols.fnLobClose) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobClose)(lob->conn->handle, error->handle, + lob->locator); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "close LOB"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobCreateTemporary() [INTERNAL] +// Wrapper for OCILobCreateTemporary(). +//----------------------------------------------------------------------------- +int dpiOci__lobCreateTemporary(dpiLob *lob, dpiError *error) +{ + uint8_t lobType; + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobCreateTemporary", + dpiOciSymbols.fnLobCreateTemporary) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BLOB) + lobType = DPI_OCI_TEMP_BLOB; + else lobType = DPI_OCI_TEMP_CLOB; + status = (*dpiOciSymbols.fnLobCreateTemporary)(lob->conn->handle, + error->handle, lob->locator, DPI_OCI_DEFAULT, + lob->type->charsetForm, lobType, 1, DPI_OCI_DURATION_SESSION); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "create temporary LOB"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobFileExists() [INTERNAL] +// Wrapper for OCILobFileExists(). +//----------------------------------------------------------------------------- +int dpiOci__lobFileExists(dpiLob *lob, int *exists, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobFileExists", dpiOciSymbols.fnLobFileExists) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobFileExists)(lob->conn->handle, error->handle, + lob->locator, exists); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get file exists"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobFileGetName() [INTERNAL] +// Wrapper for OCILobFileGetName(). +//----------------------------------------------------------------------------- +int dpiOci__lobFileGetName(dpiLob *lob, char *dirAlias, + uint16_t *dirAliasLength, char *name, uint16_t *nameLength, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobFileGetName", dpiOciSymbols.fnLobFileGetName) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobFileGetName)(lob->env->handle, error->handle, + lob->locator, dirAlias, dirAliasLength, name, nameLength); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get LOB file name"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobFileSetName() [INTERNAL] +// Wrapper for OCILobFileSetName(). +//----------------------------------------------------------------------------- +int dpiOci__lobFileSetName(dpiLob *lob, const char *dirAlias, + uint16_t dirAliasLength, const char *name, uint16_t nameLength, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobFileSetName", dpiOciSymbols.fnLobFileSetName) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobFileSetName)(lob->env->handle, error->handle, + &lob->locator, dirAlias, dirAliasLength, name, nameLength); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "set LOB file name"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobFreeTemporary() [INTERNAL] +// Wrapper for OCILobFreeTemporary(). +//----------------------------------------------------------------------------- +int dpiOci__lobFreeTemporary(dpiConn *conn, void *lobLocator, int checkError, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobFreeTemporary", + dpiOciSymbols.fnLobFreeTemporary) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobFreeTemporary)(conn->handle, + error->handle, lobLocator); + if (!checkError) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "free temporary LOB"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobGetChunkSize() [INTERNAL] +// Wrapper for OCILobGetChunkSize(). +//----------------------------------------------------------------------------- +int dpiOci__lobGetChunkSize(dpiLob *lob, uint32_t *size, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobGetChunkSize", dpiOciSymbols.fnLobGetChunkSize) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobGetChunkSize)(lob->conn->handle, + error->handle, lob->locator, size); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get chunk size"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobGetLength2() [INTERNAL] +// Wrapper for OCILobGetLength2(). +//----------------------------------------------------------------------------- +int dpiOci__lobGetLength2(dpiLob *lob, uint64_t *size, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobGetLength2", dpiOciSymbols.fnLobGetLength2) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobGetLength2)(lob->conn->handle, error->handle, + lob->locator, size); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get length"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobIsOpen() [INTERNAL] +// Wrapper for OCILobIsOpen(). +//----------------------------------------------------------------------------- +int dpiOci__lobIsOpen(dpiLob *lob, int *isOpen, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobIsOpen", dpiOciSymbols.fnLobIsOpen) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobIsOpen)(lob->conn->handle, error->handle, + lob->locator, isOpen); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "check is open"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobIsTemporary() [INTERNAL] +// Wrapper for OCILobIsTemporary(). +//----------------------------------------------------------------------------- +int dpiOci__lobIsTemporary(dpiLob *lob, int *isTemporary, int checkError, + dpiError *error) +{ + int status; + + *isTemporary = 0; + DPI_OCI_LOAD_SYMBOL("OCILobIsTemporary", dpiOciSymbols.fnLobIsTemporary) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobIsTemporary)(lob->env->handle, error->handle, + lob->locator, isTemporary); + if (!checkError) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "check is temporary"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobLocatorAssign() [INTERNAL] +// Wrapper for OCILobLocatorAssign(). +//----------------------------------------------------------------------------- +int dpiOci__lobLocatorAssign(dpiLob *lob, void **copiedHandle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobLocatorAssign", + dpiOciSymbols.fnLobLocatorAssign) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobLocatorAssign)(lob->conn->handle, + error->handle, lob->locator, copiedHandle); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "assign locator"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobOpen() [INTERNAL] +// Wrapper for OCILobOpen(). +//----------------------------------------------------------------------------- +int dpiOci__lobOpen(dpiLob *lob, dpiError *error) +{ + uint8_t mode; + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobOpen", dpiOciSymbols.fnLobOpen) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + mode = (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE) ? + DPI_OCI_LOB_READONLY : DPI_OCI_LOB_READWRITE; + status = (*dpiOciSymbols.fnLobOpen)(lob->conn->handle, error->handle, + lob->locator, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "close LOB"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobRead2() [INTERNAL] +// Wrapper for OCILobRead2(). +//----------------------------------------------------------------------------- +int dpiOci__lobRead2(dpiLob *lob, uint64_t offset, uint64_t *amountInBytes, + uint64_t *amountInChars, char *buffer, uint64_t bufferLength, + dpiError *error) +{ + uint16_t charsetId; + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobRead2", dpiOciSymbols.fnLobRead2) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + charsetId = (lob->type->charsetForm == DPI_SQLCS_NCHAR) ? + lob->env->ncharsetId : lob->env->charsetId; + status = (*dpiOciSymbols.fnLobRead2)(lob->conn->handle, error->handle, + lob->locator, amountInBytes, amountInChars, offset, buffer, + bufferLength, DPI_OCI_ONE_PIECE, NULL, NULL, charsetId, + lob->type->charsetForm); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "read from LOB"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobTrim2() [INTERNAL] +// Wrapper for OCILobTrim2(). +//----------------------------------------------------------------------------- +int dpiOci__lobTrim2(dpiLob *lob, uint64_t newLength, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobTrim2", dpiOciSymbols.fnLobTrim2) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnLobTrim2)(lob->conn->handle, error->handle, + lob->locator, newLength); + if (status == DPI_OCI_INVALID_HANDLE) + return dpiOci__lobCreateTemporary(lob, error); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "trim LOB"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__lobWrite2() [INTERNAL] +// Wrapper for OCILobWrite2(). +//----------------------------------------------------------------------------- +int dpiOci__lobWrite2(dpiLob *lob, uint64_t offset, const char *value, + uint64_t valueLength, dpiError *error) +{ + uint64_t lengthInBytes = valueLength, lengthInChars = 0; + uint16_t charsetId; + int status; + + DPI_OCI_LOAD_SYMBOL("OCILobWrite2", dpiOciSymbols.fnLobWrite2) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + charsetId = (lob->type->charsetForm == DPI_SQLCS_NCHAR) ? + lob->env->ncharsetId : lob->env->charsetId; + status = (*dpiOciSymbols.fnLobWrite2)(lob->conn->handle, error->handle, + lob->locator, &lengthInBytes, &lengthInChars, offset, (void*) value, + valueLength, DPI_OCI_ONE_PIECE, NULL, NULL, charsetId, + lob->type->charsetForm); + DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "write to LOB"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__memoryAlloc() [INTERNAL] +// Wrapper for OCIMemoryAlloc(). +//----------------------------------------------------------------------------- +int dpiOci__memoryAlloc(dpiConn *conn, void **ptr, uint32_t size, + int checkError, dpiError *error) +{ + int status; + + *ptr = NULL; + DPI_OCI_LOAD_SYMBOL("OCIMemoryAlloc", dpiOciSymbols.fnMemoryAlloc) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnMemoryAlloc)(conn->sessionHandle, error->handle, + ptr, DPI_OCI_DURATION_SESSION, size, DPI_OCI_MEMORY_CLEARED); + if (!checkError) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "allocate memory"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__memoryFree() [INTERNAL] +// Wrapper for OCIMemoryFree(). +//----------------------------------------------------------------------------- +int dpiOci__memoryFree(dpiConn *conn, void *ptr, dpiError *error) +{ + DPI_OCI_LOAD_SYMBOL("OCIMemoryFree", dpiOciSymbols.fnMemoryFree) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + (*dpiOciSymbols.fnMemoryFree)(conn->sessionHandle, error->handle, ptr); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__nlsCharSetConvert() [INTERNAL] +// Wrapper for OCINlsCharSetConvert(). +//----------------------------------------------------------------------------- +int dpiOci__nlsCharSetConvert(void *envHandle, uint16_t destCharsetId, + char *dest, size_t destLength, uint16_t sourceCharsetId, + const char *source, size_t sourceLength, size_t *resultSize, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCINlsCharSetConvert", + dpiOciSymbols.fnNlsCharSetConvert) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnNlsCharSetConvert)(envHandle, error->handle, + destCharsetId, dest, destLength, sourceCharsetId, source, + sourceLength, resultSize); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "convert text"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__nlsCharSetIdToName() [INTERNAL] +// Wrapper for OCINlsCharSetIdToName(). +//----------------------------------------------------------------------------- +int dpiOci__nlsCharSetIdToName(void *envHandle, char *buf, size_t bufLength, + uint16_t charsetId, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCINlsCharSetIdToName", + dpiOciSymbols.fnNlsCharSetIdToName) + status = (*dpiOciSymbols.fnNlsCharSetIdToName)(envHandle, buf, bufLength, + charsetId); + return (status == DPI_OCI_SUCCESS) ? DPI_SUCCESS : DPI_FAILURE; +} + + +//----------------------------------------------------------------------------- +// dpiOci__nlsCharSetNameToId() [INTERNAL] +// Wrapper for OCINlsCharSetNameToId(). +//----------------------------------------------------------------------------- +int dpiOci__nlsCharSetNameToId(void *envHandle, const char *name, + uint16_t *charsetId, dpiError *error) +{ + DPI_OCI_LOAD_SYMBOL("OCINlsCharSetNameToId", + dpiOciSymbols.fnNlsCharSetNameToId) + *charsetId = (*dpiOciSymbols.fnNlsCharSetNameToId)(envHandle, name); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__nlsEnvironmentVariableGet() [INTERNAL] +// Wrapper for OCIEnvironmentVariableGet(). +//----------------------------------------------------------------------------- +int dpiOci__nlsEnvironmentVariableGet(uint16_t item, void *value, + dpiError *error) +{ + size_t ignored; + int status; + + DPI_OCI_LOAD_SYMBOL("OCINlsEnvironmentVariableGet", + dpiOciSymbols.fnNlsEnvironmentVariableGet) + status = (*dpiOciSymbols.fnNlsEnvironmentVariableGet)(value, 0, item, 0, + &ignored); + if (status != DPI_OCI_SUCCESS) + return dpiError__set(error, "get NLS environment variable", + DPI_ERR_NLS_ENV_VAR_GET); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__nlsNameMap() [INTERNAL] +// Wrapper for OCINlsNameMap(). +//----------------------------------------------------------------------------- +int dpiOci__nlsNameMap(void *envHandle, char *buf, size_t bufLength, + const char *source, uint32_t flag, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCINlsNameMap", dpiOciSymbols.fnNlsNameMap) + status = (*dpiOciSymbols.fnNlsNameMap)(envHandle, buf, bufLength, source, + flag); + return (status == DPI_OCI_SUCCESS) ? DPI_SUCCESS : DPI_FAILURE; +} + + +//----------------------------------------------------------------------------- +// dpiOci__nlsNumericInfoGet() [INTERNAL] +// Wrapper for OCINlsNumericInfoGet(). +//----------------------------------------------------------------------------- +int dpiOci__nlsNumericInfoGet(void *envHandle, int32_t *value, uint16_t item, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCINlsNumericInfoGet", + dpiOciSymbols.fnNlsNumericInfoGet) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnNlsNumericInfoGet)(envHandle, error->handle, + value, item); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get NLS info"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__numberFromInt() [INTERNAL] +// Wrapper for OCINumberFromInt(). +//----------------------------------------------------------------------------- +int dpiOci__numberFromInt(const void *value, unsigned int valueLength, + unsigned int flags, void *number, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCINumberFromInt", dpiOciSymbols.fnNumberFromInt) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnNumberFromInt)(error->handle, value, + valueLength, flags, number); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number from integer"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__numberFromReal() [INTERNAL] +// Wrapper for OCINumberFromReal(). +//----------------------------------------------------------------------------- +int dpiOci__numberFromReal(const double value, void *number, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCINumberFromReal", dpiOciSymbols.fnNumberFromReal) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnNumberFromReal)(error->handle, &value, + sizeof(double), number); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number from real"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__numberToInt() [INTERNAL] +// Wrapper for OCINumberToInt(). +//----------------------------------------------------------------------------- +int dpiOci__numberToInt(void *number, void *value, unsigned int valueLength, + unsigned int flags, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCINumberToInt", dpiOciSymbols.fnNumberToInt) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnNumberToInt)(error->handle, number, valueLength, + flags, value); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number to integer"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__numberToReal() [INTERNAL] +// Wrapper for OCINumberToReal(). +//----------------------------------------------------------------------------- +int dpiOci__numberToReal(double *value, void *number, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCINumberToReal", dpiOciSymbols.fnNumberToReal) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnNumberToReal)(error->handle, number, + sizeof(double), value); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number to real"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__objectCopy() [INTERNAL] +// Wrapper for OCIObjectCopy(). +//----------------------------------------------------------------------------- +int dpiOci__objectCopy(dpiObject *obj, void *sourceInstance, + void *sourceIndicator, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIObjectCopy", dpiOciSymbols.fnObjectCopy) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnObjectCopy)(obj->env->handle, error->handle, + obj->type->conn->handle, sourceInstance, sourceIndicator, + obj->instance, obj->indicator, obj->type->tdo, + DPI_OCI_DURATION_SESSION, DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "copy object"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__objectFree() [INTERNAL] +// Wrapper for OCIObjectFree(). +//----------------------------------------------------------------------------- +int dpiOci__objectFree(void *envHandle, void *data, int checkError, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIObjectFree", dpiOciSymbols.fnObjectFree) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnObjectFree)(envHandle, error->handle, data, + DPI_OCI_DEFAULT); + if (checkError && DPI_OCI_ERROR_OCCURRED(status)) { + dpiError__setFromOCI(error, status, NULL, "free instance"); + + // during the attempt to free, PL/SQL records fail with error + // "ORA-21602: operation does not support the specified typecode", but + // a subsequent attempt will yield error "OCI-21500: internal error + // code" and crash the process, so pretend like the free was + // successful! + if (error->buffer->code == 21602) + return DPI_SUCCESS; + return DPI_FAILURE; + } + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__objectGetAttr() [INTERNAL] +// Wrapper for OCIObjectGetAttr(). +//----------------------------------------------------------------------------- +int dpiOci__objectGetAttr(dpiObject *obj, dpiObjectAttr *attr, + int16_t *scalarValueIndicator, void **valueIndicator, void **value, + void **tdo, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIObjectGetAttr", dpiOciSymbols.fnObjectGetAttr) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnObjectGetAttr)(obj->env->handle, error->handle, + obj->instance, obj->indicator, obj->type->tdo, &attr->name, + &attr->nameLength, 1, 0, 0, scalarValueIndicator, valueIndicator, + value, tdo); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get attribute"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__objectGetInd() [INTERNAL] +// Wrapper for OCIObjectGetInd(). +//----------------------------------------------------------------------------- +int dpiOci__objectGetInd(dpiObject *obj, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIObjectGetInd", dpiOciSymbols.fnObjectGetInd) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnObjectGetInd)(obj->env->handle, error->handle, + obj->instance, &obj->indicator); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get indicator"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__objectNew() [INTERNAL] +// Wrapper for OCIObjectNew(). +//----------------------------------------------------------------------------- +int dpiOci__objectNew(dpiObject *obj, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIObjectNew", dpiOciSymbols.fnObjectNew) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnObjectNew)(obj->env->handle, error->handle, + obj->type->conn->handle, obj->type->typeCode, obj->type->tdo, NULL, + DPI_OCI_DURATION_SESSION, 1, &obj->instance); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "create object"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__objectPin() [INTERNAL] +// Wrapper for OCIObjectPin(). +//----------------------------------------------------------------------------- +int dpiOci__objectPin(void *envHandle, void *objRef, void **obj, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIObjectPin", dpiOciSymbols.fnObjectPin) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnObjectPin)(envHandle, error->handle, objRef, + NULL, DPI_OCI_PIN_ANY, DPI_OCI_DURATION_SESSION, DPI_OCI_LOCK_NONE, + obj); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "pin reference"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__objectSetAttr() [INTERNAL] +// Wrapper for OCIObjectSetAttr(). +//----------------------------------------------------------------------------- +int dpiOci__objectSetAttr(dpiObject *obj, dpiObjectAttr *attr, + int16_t scalarValueIndicator, void *valueIndicator, const void *value, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIObjectSetAttr", dpiOciSymbols.fnObjectSetAttr) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnObjectSetAttr)(obj->env->handle, error->handle, + obj->instance, obj->indicator, obj->type->tdo, &attr->name, + &attr->nameLength, 1, NULL, 0, scalarValueIndicator, + valueIndicator, value); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "set attribute"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__passwordChange() [INTERNAL] +// Wrapper for OCIPasswordChange(). +//----------------------------------------------------------------------------- +int dpiOci__passwordChange(dpiConn *conn, const char *userName, + uint32_t userNameLength, const char *oldPassword, + uint32_t oldPasswordLength, const char *newPassword, + uint32_t newPasswordLength, uint32_t mode, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIPasswordChange", dpiOciSymbols.fnPasswordChange) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnPasswordChange)(conn->handle, error->handle, + userName, userNameLength, oldPassword, oldPasswordLength, + newPassword, newPasswordLength, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "change password"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__paramGet() [INTERNAL] +// Wrapper for OCIParamGet(). +//----------------------------------------------------------------------------- +int dpiOci__paramGet(const void *handle, uint32_t handleType, void **parameter, + uint32_t pos, const char *action, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIParamGet", dpiOciSymbols.fnParamGet) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnParamGet)(handle, handleType, error->handle, + parameter, pos); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); +} + + +//----------------------------------------------------------------------------- +// dpiOci__ping() [INTERNAL] +// Wrapper for OCIPing(). +//----------------------------------------------------------------------------- +int dpiOci__ping(dpiConn *conn, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIPing", dpiOciSymbols.fnPing) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnPing)(conn->handle, error->handle, + DPI_OCI_DEFAULT); + if (DPI_OCI_ERROR_OCCURRED(status)) { + dpiError__setFromOCI(error, status, conn, "ping"); + + // attempting to ping a database earlier than 10g will result in error + // ORA-1010: invalid OCI operation, but that implies a successful ping + // so ignore that error and treat it as a successful operation + if (error->buffer->code == 1010) + return DPI_SUCCESS; + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__rawAssignBytes() [INTERNAL] +// Wrapper for OCIRawAssignBytes(). +//----------------------------------------------------------------------------- +int dpiOci__rawAssignBytes(void *envHandle, const char *value, + uint32_t valueLength, void **handle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIRawAssignBytes", dpiOciSymbols.fnRawAssignBytes) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnRawAssignBytes)(envHandle, error->handle, value, + valueLength, handle); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "assign bytes to raw"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__rawPtr() [INTERNAL] +// Wrapper for OCIRawPtr(). +//----------------------------------------------------------------------------- +int dpiOci__rawPtr(void *envHandle, void *handle, void **ptr) +{ + dpiError *error = NULL; + + DPI_OCI_LOAD_SYMBOL("OCIRawPtr", dpiOciSymbols.fnRawPtr) + *ptr = (*dpiOciSymbols.fnRawPtr)(envHandle, handle); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__rawResize() [INTERNAL] +// Wrapper for OCIRawResize(). +//----------------------------------------------------------------------------- +int dpiOci__rawResize(void *envHandle, void **handle, uint32_t newSize, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIRawResize", dpiOciSymbols.fnRawResize) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnRawResize)(envHandle, error->handle, newSize, + handle); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "resize raw"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__rawSize() [INTERNAL] +// Wrapper for OCIRawSize(). +//----------------------------------------------------------------------------- +int dpiOci__rawSize(void *envHandle, void *handle, uint32_t *size) +{ + dpiError *error = NULL; + + DPI_OCI_LOAD_SYMBOL("OCIRawSize", dpiOciSymbols.fnRawSize) + *size = (*dpiOciSymbols.fnRawSize)(envHandle, handle); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__reallocMem() [INTERNAL] +// Wrapper for OCI allocation of memory, only used when debugging memory +// allocation. +//----------------------------------------------------------------------------- +static void *dpiOci__reallocMem(UNUSED void *unused, void *ptr, size_t newSize) +{ + char message[80]; + void *newPtr; + + (void) sprintf(message, "OCI reallocated ptr at %p", ptr); + newPtr = realloc(ptr, newSize); + dpiDebug__print("%s to %u bytes at %p\n", message, newSize, newPtr); + return newPtr; +} + + +//----------------------------------------------------------------------------- +// dpiOci__rowidToChar() [INTERNAL] +// Wrapper for OCIRowidToChar(). +//----------------------------------------------------------------------------- +int dpiOci__rowidToChar(dpiRowid *rowid, char *buffer, uint16_t *bufferSize, + dpiError *error) +{ + uint16_t origSize; + int status; + + DPI_OCI_LOAD_SYMBOL("OCIRowidToChar", dpiOciSymbols.fnRowidToChar) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + origSize = *bufferSize; + status = (*dpiOciSymbols.fnRowidToChar)(rowid->handle, buffer, bufferSize, + error->handle); + if (origSize == 0) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get rowid as string"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__serverAttach() [INTERNAL] +// Wrapper for OCIServerAttach(). +//----------------------------------------------------------------------------- +int dpiOci__serverAttach(dpiConn *conn, const char *connectString, + uint32_t connectStringLength, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIServerAttach", dpiOciSymbols.fnServerAttach) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnServerAttach)(conn->serverHandle, error->handle, + connectString, (int32_t) connectStringLength, DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "server attach"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__serverDetach() [INTERNAL] +// Wrapper for OCIServerDetach(). +//----------------------------------------------------------------------------- +int dpiOci__serverDetach(dpiConn *conn, int checkError, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIServerDetach", dpiOciSymbols.fnServerDetach) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnServerDetach)(conn->serverHandle, error->handle, + DPI_OCI_DEFAULT); + if (!checkError) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "detatch from server"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__serverRelease() [INTERNAL] +// Wrapper for OCIServerRelease(). +//----------------------------------------------------------------------------- +int dpiOci__serverRelease(dpiConn *conn, char *buffer, uint32_t bufferSize, + uint32_t *version, dpiError *error) +{ + int status; + + DPI_OCI_ENSURE_ERROR_HANDLE(error) + if (conn->env->versionInfo->versionNum < 18) { + DPI_OCI_LOAD_SYMBOL("OCIServerRelease", dpiOciSymbols.fnServerRelease) + status = (*dpiOciSymbols.fnServerRelease)(conn->handle, error->handle, + buffer, bufferSize, DPI_OCI_HTYPE_SVCCTX, version); + } else { + DPI_OCI_LOAD_SYMBOL("OCIServerRelease2", + dpiOciSymbols.fnServerRelease2) + status = (*dpiOciSymbols.fnServerRelease2)(conn->handle, error->handle, + buffer, bufferSize, DPI_OCI_HTYPE_SVCCTX, version, + DPI_OCI_DEFAULT); + } + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get server version"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sessionBegin() [INTERNAL] +// Wrapper for OCISessionBegin(). +//----------------------------------------------------------------------------- +int dpiOci__sessionBegin(dpiConn *conn, uint32_t credentialType, + uint32_t mode, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISessionBegin", dpiOciSymbols.fnSessionBegin) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSessionBegin)(conn->handle, error->handle, + conn->sessionHandle, credentialType, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "begin session"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sessionEnd() [INTERNAL] +// Wrapper for OCISessionEnd(). +//----------------------------------------------------------------------------- +int dpiOci__sessionEnd(dpiConn *conn, int checkError, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISessionEnd", dpiOciSymbols.fnSessionEnd) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSessionEnd)(conn->handle, error->handle, + conn->sessionHandle, DPI_OCI_DEFAULT); + if (!checkError) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "end session"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sessionGet() [INTERNAL] +// Wrapper for OCISessionGet(). +//----------------------------------------------------------------------------- +int dpiOci__sessionGet(void *envHandle, void **handle, void *authInfo, + const char *connectString, uint32_t connectStringLength, + const char *tag, uint32_t tagLength, const char **outTag, + uint32_t *outTagLength, int *found, uint32_t mode, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISessionGet", dpiOciSymbols.fnSessionGet) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSessionGet)(envHandle, error->handle, handle, + authInfo, connectString, connectStringLength, tag, tagLength, + outTag, outTagLength, found, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get session"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sessionPoolCreate() [INTERNAL] +// Wrapper for OCISessionPoolCreate(). +//----------------------------------------------------------------------------- +int dpiOci__sessionPoolCreate(dpiPool *pool, const char *connectString, + uint32_t connectStringLength, uint32_t minSessions, + uint32_t maxSessions, uint32_t sessionIncrement, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + uint32_t mode, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISessionPoolCreate", + dpiOciSymbols.fnSessionPoolCreate) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSessionPoolCreate)(pool->env->handle, + error->handle, pool->handle, (char**) &pool->name, + &pool->nameLength, connectString, connectStringLength, minSessions, + maxSessions, sessionIncrement, userName, userNameLength, password, + passwordLength, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "create pool"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sessionPoolDestroy() [INTERNAL] +// Wrapper for OCISessionPoolDestroy(). +//----------------------------------------------------------------------------- +int dpiOci__sessionPoolDestroy(dpiPool *pool, uint32_t mode, int checkError, + dpiError *error) +{ + void *handle; + int status; + + DPI_OCI_LOAD_SYMBOL("OCISessionPoolDestroy", + dpiOciSymbols.fnSessionPoolDestroy) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + + // clear the pool handle immediately so that no further attempts are made + // to use the pool while the pool is being closed; if the pool close fails, + // restore the pool handle afterwards + handle = pool->handle; + pool->handle = NULL; + status = (*dpiOciSymbols.fnSessionPoolDestroy)(handle, error->handle, + mode); + if (checkError && DPI_OCI_ERROR_OCCURRED(status)) { + pool->handle = handle; + return dpiError__setFromOCI(error, status, NULL, "destroy pool"); + } + dpiOci__handleFree(handle, DPI_OCI_HTYPE_SPOOL); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__sessionRelease() [INTERNAL] +// Wrapper for OCISessionRelease(). +//----------------------------------------------------------------------------- +int dpiOci__sessionRelease(dpiConn *conn, const char *tag, uint32_t tagLength, + uint32_t mode, int checkError, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISessionRelease", dpiOciSymbols.fnSessionRelease) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSessionRelease)(conn->handle, error->handle, + tag, tagLength, mode); + if (!checkError) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "release session"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__shardingKeyColumnAdd() [INTERNAL] +// Wrapper for OCIshardingKeyColumnAdd(). +//----------------------------------------------------------------------------- +int dpiOci__shardingKeyColumnAdd(void *shardingKey, void *col, uint32_t colLen, + uint16_t colType, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIShardingKeyColumnAdd", + dpiOciSymbols.fnShardingKeyColumnAdd) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnShardingKeyColumnAdd)(shardingKey, + error->handle, col, colLen, colType, DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "add sharding column"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaBulkInsert() [INTERNAL] +// Wrapper for OCISodaBulkInsert(). +//----------------------------------------------------------------------------- +int dpiOci__sodaBulkInsert(dpiSodaColl *coll, void **documents, + uint32_t numDocuments, void *outputOptions, uint32_t mode, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaBulkInsert", dpiOciSymbols.fnSodaBulkInsert) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaBulkInsert)(coll->db->conn->handle, + coll->handle, documents, numDocuments, outputOptions, + error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "insert multiple documents"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaBulkInsertAndGet() [INTERNAL] +// Wrapper for OCISodaBulkInsert(). +//----------------------------------------------------------------------------- +int dpiOci__sodaBulkInsertAndGet(dpiSodaColl *coll, void **documents, + uint32_t numDocuments, void *outputOptions, uint32_t mode, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaBulkInsertAndGet", + dpiOciSymbols.fnSodaBulkInsertAndGet) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaBulkInsertAndGet)(coll->db->conn->handle, + coll->handle, documents, numDocuments, outputOptions, + error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "insert (and get) multiple documents"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaCollCreateWithMetadata() [INTERNAL] +// Wrapper for OCISodaCollCreateWithMetadata(). +//----------------------------------------------------------------------------- +int dpiOci__sodaCollCreateWithMetadata(dpiSodaDb *db, const char *name, + uint32_t nameLength, const char *metadata, uint32_t metadataLength, + uint32_t mode, void **handle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaCollCreateWithMetadata", + dpiOciSymbols.fnSodaCollCreateWithMetadata) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaCollCreateWithMetadata)(db->conn->handle, + name, nameLength, metadata, metadataLength, handle, error->handle, + mode); + DPI_OCI_CHECK_AND_RETURN(error, status, db->conn, + "create SODA collection"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaCollDrop() [INTERNAL] +// Wrapper for OCISodaCollDrop(). +//----------------------------------------------------------------------------- +int dpiOci__sodaCollDrop(dpiSodaColl *coll, int *isDropped, uint32_t mode, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaCollDrop", dpiOciSymbols.fnSodaCollDrop) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaCollDrop)(coll->db->conn->handle, + coll->handle, isDropped, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "drop SODA collection"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaCollGetNext() [INTERNAL] +// Wrapper for OCISodaCollGetNext(). +//----------------------------------------------------------------------------- +int dpiOci__sodaCollGetNext(dpiConn *conn, void *cursorHandle, + void **collectionHandle, uint32_t mode, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaCollGetNext", dpiOciSymbols.fnSodaCollGetNext) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaCollGetNext)(conn->handle, cursorHandle, + collectionHandle, error->handle, mode); + if (status == DPI_OCI_NO_DATA) { + *collectionHandle = NULL; + return DPI_SUCCESS; + } + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get next collection"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaCollList() [INTERNAL] +// Wrapper for OCISodaCollList(). +//----------------------------------------------------------------------------- +int dpiOci__sodaCollList(dpiSodaDb *db, const char *startingName, + uint32_t startingNameLength, void **handle, uint32_t mode, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaCollList", dpiOciSymbols.fnSodaCollList) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaCollList)(db->conn->handle, startingName, + startingNameLength, handle, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, db->conn, + "get SODA collection cursor"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaCollOpen() [INTERNAL] +// Wrapper for OCISodaCollOpen(). +//----------------------------------------------------------------------------- +int dpiOci__sodaCollOpen(dpiSodaDb *db, const char *name, uint32_t nameLength, + uint32_t mode, void **handle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaCollOpen", dpiOciSymbols.fnSodaCollOpen) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaCollOpen)(db->conn->handle, name, + nameLength, handle, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, db->conn, "open SODA collection"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaDataGuideGet() [INTERNAL] +// Wrapper for OCISodaDataGuideGet(). +//----------------------------------------------------------------------------- +int dpiOci__sodaDataGuideGet(dpiSodaColl *coll, void **handle, uint32_t mode, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaDataGuideGet", + dpiOciSymbols.fnSodaDataGuideGet) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaDataGuideGet)(coll->db->conn->handle, + coll->handle, DPI_OCI_DEFAULT, handle, error->handle, mode); + if (DPI_OCI_ERROR_OCCURRED(status)) { + dpiError__setFromOCI(error, status, coll->db->conn, "get data guide"); + if (error->buffer->code != 24801) + return DPI_FAILURE; + *handle = NULL; + } + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaDocCount() [INTERNAL] +// Wrapper for OCISodaDocCount(). +//----------------------------------------------------------------------------- +int dpiOci__sodaDocCount(dpiSodaColl *coll, void *options, uint32_t mode, + uint64_t *count, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaDocCount", dpiOciSymbols.fnSodaDocCount) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaDocCount)(coll->db->conn->handle, + coll->handle, options, count, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "get document count"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaDocGetNext() [INTERNAL] +// Wrapper for OCISodaDocGetNext(). +//----------------------------------------------------------------------------- +int dpiOci__sodaDocGetNext(dpiSodaDocCursor *cursor, void **handle, + uint32_t mode, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaDocGetNext", dpiOciSymbols.fnSodaDocGetNext) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaDocGetNext)(cursor->coll->db->conn->handle, + cursor->handle, handle, error->handle, mode); + if (status == DPI_OCI_NO_DATA) { + *handle = NULL; + return DPI_SUCCESS; + } + DPI_OCI_CHECK_AND_RETURN(error, status, cursor->coll->db->conn, + "get next document"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaFind() [INTERNAL] +// Wrapper for OCISodaFind(). +//----------------------------------------------------------------------------- +int dpiOci__sodaFind(dpiSodaColl *coll, const void *options, uint32_t flags, + uint32_t mode, void **handle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaFind", dpiOciSymbols.fnSodaFind) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaFind)(coll->db->conn->handle, + coll->handle, options, flags, handle, error->handle, mode); + if (status == DPI_OCI_NO_DATA) { + *handle = NULL; + return DPI_SUCCESS; + } + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "find SODA documents"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaFindOne() [INTERNAL] +// Wrapper for OCISodaFindOne(). +//----------------------------------------------------------------------------- +int dpiOci__sodaFindOne(dpiSodaColl *coll, const void *options, uint32_t flags, + uint32_t mode, void **handle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaFindOne", dpiOciSymbols.fnSodaFindOne) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaFindOne)(coll->db->conn->handle, + coll->handle, options, flags, handle, error->handle, mode); + if (status == DPI_OCI_NO_DATA) { + *handle = NULL; + return DPI_SUCCESS; + } + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "get SODA document"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaIndexCreate() [INTERNAL] +// Wrapper for OCISodaIndexCreate(). +//----------------------------------------------------------------------------- +int dpiOci__sodaIndexCreate(dpiSodaColl *coll, const char *indexSpec, + uint32_t indexSpecLength, uint32_t mode, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaIndexCreate", dpiOciSymbols.fnSodaIndexCreate) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaIndexCreate)(coll->db->conn->handle, + coll->handle, indexSpec, indexSpecLength, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "create index"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaIndexDrop() [INTERNAL] +// Wrapper for OCISodaIndexDrop(). +//----------------------------------------------------------------------------- +int dpiOci__sodaIndexDrop(dpiSodaColl *coll, const char *name, + uint32_t nameLength, uint32_t mode, int *isDropped, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaIndexDrop", dpiOciSymbols.fnSodaIndexDrop) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaIndexDrop)(coll->db->conn->handle, name, + nameLength, isDropped, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "drop index"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaInsert() [INTERNAL] +// Wrapper for OCISodaInsert(). +//----------------------------------------------------------------------------- +int dpiOci__sodaInsert(dpiSodaColl *coll, void *handle, uint32_t mode, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaInsert", dpiOciSymbols.fnSodaInsert) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaInsert)(coll->db->conn->handle, + coll->handle, handle, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "insert SODA document"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaInsertAndGet() [INTERNAL] +// Wrapper for OCISodaInsertAndGet(). +//----------------------------------------------------------------------------- +int dpiOci__sodaInsertAndGet(dpiSodaColl *coll, void **handle, uint32_t mode, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaInsertAndGet", + dpiOciSymbols.fnSodaInsertAndGet) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaInsertAndGet)(coll->db->conn->handle, + coll->handle, handle, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "insert and get SODA document"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaOperKeysSet() [INTERNAL] +// Wrapper for OCISodaOperKeysSet(). +//----------------------------------------------------------------------------- +int dpiOci__sodaOperKeysSet(const dpiSodaOperOptions *options, void *handle, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaOperKeysSet", dpiOciSymbols.fnSodaOperKeysSet) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaOperKeysSet)(handle, options->keys, + options->keyLengths, options->numKeys, error->handle, + DPI_OCI_DEFAULT); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, + "set operation options keys"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaRemove() [INTERNAL] +// Wrapper for OCISodaRemove(). +//----------------------------------------------------------------------------- +int dpiOci__sodaRemove(dpiSodaColl *coll, void *options, uint32_t mode, + uint64_t *count, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaRemove", dpiOciSymbols.fnSodaRemove) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaRemove)(coll->db->conn->handle, + coll->handle, options, count, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "remove documents from SODA collection"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaReplOne() [INTERNAL] +// Wrapper for OCISodaReplOne(). +//----------------------------------------------------------------------------- +int dpiOci__sodaReplOne(dpiSodaColl *coll, const void *options, void *handle, + uint32_t mode, int *isReplaced, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaReplOne", dpiOciSymbols.fnSodaReplOne) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaReplOne)(coll->db->conn->handle, + coll->handle, options, handle, isReplaced, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "replace SODA document"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__sodaReplOneAndGet() [INTERNAL] +// Wrapper for OCISodaReplOneAndGet(). +//----------------------------------------------------------------------------- +int dpiOci__sodaReplOneAndGet(dpiSodaColl *coll, const void *options, + void **handle, uint32_t mode, int *isReplaced, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISodaReplOneAndGet", + dpiOciSymbols.fnSodaReplOneAndGet) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSodaReplOneAndGet)(coll->db->conn->handle, + coll->handle, options, handle, isReplaced, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, + "replace and get SODA document"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__stmtExecute() [INTERNAL] +// Wrapper for OCIStmtExecute(). +//----------------------------------------------------------------------------- +int dpiOci__stmtExecute(dpiStmt *stmt, uint32_t numIters, uint32_t mode, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIStmtExecute", dpiOciSymbols.fnStmtExecute) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnStmtExecute)(stmt->conn->handle, stmt->handle, + error->handle, numIters, 0, 0, 0, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "execute"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__stmtFetch2() [INTERNAL] +// Wrapper for OCIStmtFetch2(). +//----------------------------------------------------------------------------- +int dpiOci__stmtFetch2(dpiStmt *stmt, uint32_t numRows, uint16_t fetchMode, + int32_t offset, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIStmtFetch2", dpiOciSymbols.fnStmtFetch2) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnStmtFetch2)(stmt->handle, error->handle, + numRows, fetchMode, offset, DPI_OCI_DEFAULT); + if (status == DPI_OCI_NO_DATA || fetchMode == DPI_MODE_FETCH_LAST) { + stmt->hasRowsToFetch = 0; + } else if (DPI_OCI_ERROR_OCCURRED(status)) { + return dpiError__setFromOCI(error, status, stmt->conn, "fetch"); + } else { + stmt->hasRowsToFetch = 1; + } + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__stmtGetBindInfo() [INTERNAL] +// Wrapper for OCIStmtGetBindInfo(). +//----------------------------------------------------------------------------- +int dpiOci__stmtGetBindInfo(dpiStmt *stmt, uint32_t size, uint32_t startLoc, + int32_t *numFound, char *names[], uint8_t nameLengths[], + char *indNames[], uint8_t indNameLengths[], uint8_t isDuplicate[], + void *bindHandles[], dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIStmtGetBindInfo", dpiOciSymbols.fnStmtGetBindInfo) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnStmtGetBindInfo)(stmt->handle, error->handle, + size, startLoc, numFound, names, nameLengths, indNames, + indNameLengths, isDuplicate, bindHandles); + if (status == DPI_OCI_NO_DATA) { + *numFound = 0; + return DPI_SUCCESS; + } + DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "get bind info"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__stmtGetNextResult() [INTERNAL] +// Wrapper for OCIStmtGetNextResult(). +//----------------------------------------------------------------------------- +int dpiOci__stmtGetNextResult(dpiStmt *stmt, void **handle, dpiError *error) +{ + uint32_t returnType; + int status; + + DPI_OCI_LOAD_SYMBOL("OCIStmtGetNextResult", + dpiOciSymbols.fnStmtGetNextResult) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnStmtGetNextResult)(stmt->handle, error->handle, + handle, &returnType, DPI_OCI_DEFAULT); + if (status == DPI_OCI_NO_DATA) { + *handle = NULL; + return DPI_SUCCESS; + } + DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "get next result"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__stmtPrepare2() [INTERNAL] +// Wrapper for OCIStmtPrepare2(). +//----------------------------------------------------------------------------- +int dpiOci__stmtPrepare2(dpiStmt *stmt, const char *sql, uint32_t sqlLength, + const char *tag, uint32_t tagLength, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIStmtPrepare2", dpiOciSymbols.fnStmtPrepare2) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnStmtPrepare2)(stmt->conn->handle, &stmt->handle, + error->handle, sql, sqlLength, tag, tagLength, DPI_OCI_NTV_SYNTAX, + DPI_OCI_DEFAULT); + if (DPI_OCI_ERROR_OCCURRED(status)) { + stmt->handle = NULL; + return dpiError__setFromOCI(error, status, stmt->conn, "prepare SQL"); + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__stmtRelease() [INTERNAL] +// Wrapper for OCIStmtRelease(). +//----------------------------------------------------------------------------- +int dpiOci__stmtRelease(dpiStmt *stmt, const char *tag, uint32_t tagLength, + int checkError, dpiError *error) +{ + uint32_t mode = DPI_OCI_DEFAULT; + uint32_t cacheSize = 0; + int status; + + // if the statement should be deleted from the cache, first check to see + // that there actually is a cache currently being used; otherwise, the + // error "ORA-24300: bad value for mode" will be raised + if (stmt->deleteFromCache) { + dpiOci__attrGet(stmt->conn->handle, DPI_OCI_HTYPE_SVCCTX, + &cacheSize, NULL, DPI_OCI_ATTR_STMTCACHESIZE, NULL, error); + if (cacheSize > 0) + mode = DPI_OCI_STRLS_CACHE_DELETE; + } + + DPI_OCI_LOAD_SYMBOL("OCIStmtRelease", dpiOciSymbols.fnStmtRelease) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnStmtRelease)(stmt->handle, error->handle, tag, + tagLength, mode); + if (!checkError) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "release statement"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__stringAssignText() [INTERNAL] +// Wrapper for OCIStringAssignText(). +//----------------------------------------------------------------------------- +int dpiOci__stringAssignText(void *envHandle, const char *value, + uint32_t valueLength, void **handle, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIStringAssignText", + dpiOciSymbols.fnStringAssignText) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnStringAssignText)(envHandle, error->handle, + value, valueLength, handle); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "assign to string"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__stringPtr() [INTERNAL] +// Wrapper for OCIStringPtr(). +//----------------------------------------------------------------------------- +int dpiOci__stringPtr(void *envHandle, void *handle, char **ptr) +{ + dpiError *error = NULL; + + DPI_OCI_LOAD_SYMBOL("OCIStringPtr", dpiOciSymbols.fnStringPtr) + *ptr = (*dpiOciSymbols.fnStringPtr)(envHandle, handle); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__stringResize() [INTERNAL] +// Wrapper for OCIStringResize(). +//----------------------------------------------------------------------------- +int dpiOci__stringResize(void *envHandle, void **handle, uint32_t newSize, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIStringResize", dpiOciSymbols.fnStringResize) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnStringResize)(envHandle, error->handle, newSize, + handle); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "resize string"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__stringSize() [INTERNAL] +// Wrapper for OCIStringSize(). +//----------------------------------------------------------------------------- +int dpiOci__stringSize(void *envHandle, void *handle, uint32_t *size) +{ + dpiError *error = NULL; + + DPI_OCI_LOAD_SYMBOL("OCIStringSize", dpiOciSymbols.fnStringSize) + *size = (*dpiOciSymbols.fnStringSize)(envHandle, handle); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__subscriptionRegister() [INTERNAL] +// Wrapper for OCISubscriptionRegister(). +//----------------------------------------------------------------------------- +int dpiOci__subscriptionRegister(dpiConn *conn, void **handle, uint32_t mode, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCISubscriptionRegister", + dpiOciSymbols.fnSubscriptionRegister) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnSubscriptionRegister)(conn->handle, handle, 1, + error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "register"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__subscriptionUnRegister() [INTERNAL] +// Wrapper for OCISubscriptionUnRegister(). +//----------------------------------------------------------------------------- +int dpiOci__subscriptionUnRegister(dpiConn *conn, dpiSubscr *subscr, + dpiError *error) +{ + uint32_t mode; + int status; + + DPI_OCI_LOAD_SYMBOL("OCISubscriptionUnRegister", + dpiOciSymbols.fnSubscriptionUnRegister) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + mode = (subscr->clientInitiated) ? DPI_OCI_SECURE_NOTIFICATION : + DPI_OCI_DEFAULT; + status = (*dpiOciSymbols.fnSubscriptionUnRegister)(conn->handle, + subscr->handle, error->handle, mode); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "unregister"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__tableDelete() [INTERNAL] +// Wrapper for OCITableDelete(). +//----------------------------------------------------------------------------- +int dpiOci__tableDelete(dpiObject *obj, int32_t index, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITableDelete", dpiOciSymbols.fnTableDelete) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTableDelete)(obj->env->handle, error->handle, + index, obj->instance); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "delete element"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__tableExists() [INTERNAL] +// Wrapper for OCITableExists(). +//----------------------------------------------------------------------------- +int dpiOci__tableExists(dpiObject *obj, int32_t index, int *exists, + dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITableExists", dpiOciSymbols.fnTableExists) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTableExists)(obj->env->handle, error->handle, + obj->instance, index, exists); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, + "get index exists"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__tableFirst() [INTERNAL] +// Wrapper for OCITableFirst(). +//----------------------------------------------------------------------------- +int dpiOci__tableFirst(dpiObject *obj, int32_t *index, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITableFirst", dpiOciSymbols.fnTableFirst) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTableFirst)(obj->env->handle, error->handle, + obj->instance, index); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, + "get first index"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__tableLast() [INTERNAL] +// Wrapper for OCITableLast(). +//----------------------------------------------------------------------------- +int dpiOci__tableLast(dpiObject *obj, int32_t *index, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITableLast", dpiOciSymbols.fnTableLast) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTableLast)(obj->env->handle, error->handle, + obj->instance, index); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get last index"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__tableNext() [INTERNAL] +// Wrapper for OCITableNext(). +//----------------------------------------------------------------------------- +int dpiOci__tableNext(dpiObject *obj, int32_t index, int32_t *nextIndex, + int *exists, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITableNext", dpiOciSymbols.fnTableNext) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTableNext)(obj->env->handle, error->handle, + index, obj->instance, nextIndex, exists); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get next index"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__tablePrev() [INTERNAL] +// Wrapper for OCITablePrev(). +//----------------------------------------------------------------------------- +int dpiOci__tablePrev(dpiObject *obj, int32_t index, int32_t *prevIndex, + int *exists, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITablePrev", dpiOciSymbols.fnTablePrev) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTablePrev)(obj->env->handle, error->handle, + index, obj->instance, prevIndex, exists); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get prev index"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__tableSize() [INTERNAL] +// Wrapper for OCITableSize(). +//----------------------------------------------------------------------------- +int dpiOci__tableSize(dpiObject *obj, int32_t *size, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITableSize", dpiOciSymbols.fnTableSize) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTableSize)(obj->env->handle, error->handle, + obj->instance, size); + DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get size"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__threadKeyDestroy() [INTERNAL] +// Wrapper for OCIThreadKeyDestroy(). +//----------------------------------------------------------------------------- +int dpiOci__threadKeyDestroy(void *envHandle, void *errorHandle, void **key, + dpiError *error) +{ + DPI_OCI_LOAD_SYMBOL("OCIThreadKeyDestroy", + dpiOciSymbols.fnThreadKeyDestroy) + (*dpiOciSymbols.fnThreadKeyDestroy)(envHandle, errorHandle, key); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__threadKeyGet() [INTERNAL] +// Wrapper for OCIThreadKeyGet(). +//----------------------------------------------------------------------------- +int dpiOci__threadKeyGet(void *envHandle, void *errorHandle, void *key, + void **value, dpiError *error) +{ + int status; + + status = (*dpiOciSymbols.fnThreadKeyGet)(envHandle, errorHandle, key, + value); + if (status != DPI_OCI_SUCCESS) + return dpiError__set(error, "get TLS error", DPI_ERR_TLS_ERROR); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__threadKeyInit() [INTERNAL] +// Wrapper for OCIThreadKeyInit(). +//----------------------------------------------------------------------------- +int dpiOci__threadKeyInit(void *envHandle, void *errorHandle, void **key, + void *destroyFunc, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIThreadKeyInit", dpiOciSymbols.fnThreadKeyInit) + status = (*dpiOciSymbols.fnThreadKeyInit)(envHandle, errorHandle, key, + destroyFunc); + DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "initialize thread key"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__threadKeySet() [INTERNAL] +// Wrapper for OCIThreadKeySet(). +//----------------------------------------------------------------------------- +int dpiOci__threadKeySet(void *envHandle, void *errorHandle, void *key, + void *value, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCIThreadKeySet", dpiOciSymbols.fnThreadKeySet) + status = (*dpiOciSymbols.fnThreadKeySet)(envHandle, errorHandle, key, + value); + if (status != DPI_OCI_SUCCESS) + return dpiError__set(error, "set TLS error", DPI_ERR_TLS_ERROR); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiOci__transCommit() [INTERNAL] +// Wrapper for OCITransCommit(). +//----------------------------------------------------------------------------- +int dpiOci__transCommit(dpiConn *conn, uint32_t flags, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITransCommit", dpiOciSymbols.fnTransCommit) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTransCommit)(conn->handle, error->handle, + flags); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "commit"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__transPrepare() [INTERNAL] +// Wrapper for OCITransPrepare(). +//----------------------------------------------------------------------------- +int dpiOci__transPrepare(dpiConn *conn, int *commitNeeded, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITransPrepare", dpiOciSymbols.fnTransPrepare) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTransPrepare)(conn->handle, error->handle, + DPI_OCI_DEFAULT); + *commitNeeded = (status == DPI_OCI_SUCCESS); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "prepare transaction"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__transRollback() [INTERNAL] +// Wrapper for OCITransRollback(). +//----------------------------------------------------------------------------- +int dpiOci__transRollback(dpiConn *conn, int checkError, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITransRollback", dpiOciSymbols.fnTransRollback) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTransRollback)(conn->handle, error->handle, + DPI_OCI_DEFAULT); + if (!checkError) + return DPI_SUCCESS; + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "rollback"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__transStart() [INTERNAL] +// Wrapper for OCITransStart(). +//----------------------------------------------------------------------------- +int dpiOci__transStart(dpiConn *conn, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITransStart", dpiOciSymbols.fnTransStart) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTransStart)(conn->handle, error->handle, 0, + DPI_OCI_TRANS_NEW); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "start transaction"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__typeByName() [INTERNAL] +// Wrapper for OCITypeByName(). +//----------------------------------------------------------------------------- +int dpiOci__typeByName(dpiConn *conn, const char *schema, + uint32_t schemaLength, const char *name, uint32_t nameLength, + void **tdo, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITypeByName", dpiOciSymbols.fnTypeByName) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTypeByName)(conn->env->handle, error->handle, + conn->handle, schema, schemaLength, name, nameLength, NULL, 0, + DPI_OCI_DURATION_SESSION, DPI_OCI_TYPEGET_ALL, tdo); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get type by name"); +} + + +//----------------------------------------------------------------------------- +// dpiOci__typeByFullName() [INTERNAL] +// Wrapper for OCITypeByFullName(). +//----------------------------------------------------------------------------- +int dpiOci__typeByFullName(dpiConn *conn, const char *name, + uint32_t nameLength, void **tdo, dpiError *error) +{ + int status; + + DPI_OCI_LOAD_SYMBOL("OCITypeByFullName", dpiOciSymbols.fnTypeByFullName) + DPI_OCI_ENSURE_ERROR_HANDLE(error) + status = (*dpiOciSymbols.fnTypeByFullName)(conn->env->handle, + error->handle, conn->handle, name, nameLength, NULL, 0, + DPI_OCI_DURATION_SESSION, DPI_OCI_TYPEGET_ALL, tdo); + DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get type by full name"); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiOracleType.c b/vendor/github.com/godror/godror/odpi/src/dpiOracleType.c new file mode 100644 index 00000000000..ee307a7d995 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiOracleType.c @@ -0,0 +1,504 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiOracleType.c +// Implementation of variable types. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// definition of Oracle types (MUST be in same order as enumeration) +//----------------------------------------------------------------------------- +static const dpiOracleType + dpiAllOracleTypes[DPI_ORACLE_TYPE_MAX - DPI_ORACLE_TYPE_NONE - 1] = { + { + DPI_ORACLE_TYPE_VARCHAR, // public Oracle type + DPI_NATIVE_TYPE_BYTES, // default native type + DPI_SQLT_CHR, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + 0, // buffer size + 1, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_NVARCHAR, // public Oracle type + DPI_NATIVE_TYPE_BYTES, // default native type + DPI_SQLT_CHR, // internal Oracle type + DPI_SQLCS_NCHAR, // charset form + 0, // buffer size + 1, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_CHAR, // public Oracle type + DPI_NATIVE_TYPE_BYTES, // default native type + DPI_SQLT_AFC, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + 0, // buffer size + 1, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_NCHAR, // public Oracle type + DPI_NATIVE_TYPE_BYTES, // default native type + DPI_SQLT_AFC, // internal Oracle type + DPI_SQLCS_NCHAR, // charset form + 0, // buffer size + 1, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_ROWID, // public Oracle type + DPI_NATIVE_TYPE_ROWID, // default native type + DPI_SQLT_RDD, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 1, // is character data + 1, // can be in array + 1 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_RAW, // public Oracle type + DPI_NATIVE_TYPE_BYTES, // default native type + DPI_SQLT_BIN, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + 0, // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_NATIVE_FLOAT, // public Oracle type + DPI_NATIVE_TYPE_FLOAT, // default native type + DPI_SQLT_BFLOAT, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(float), // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_NATIVE_DOUBLE, // public Oracle type + DPI_NATIVE_TYPE_DOUBLE, // default native type + DPI_SQLT_BDOUBLE, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(double), // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_NATIVE_INT, // public Oracle type + DPI_NATIVE_TYPE_INT64, // default native type + DPI_SQLT_INT, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(int64_t), // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_NUMBER, // public Oracle type + DPI_NATIVE_TYPE_DOUBLE, // default native type + DPI_SQLT_VNU, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + DPI_OCI_NUMBER_SIZE, // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_DATE, // public Oracle type + DPI_NATIVE_TYPE_TIMESTAMP, // default native type + DPI_SQLT_ODT, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(dpiOciDate), // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_TIMESTAMP, // public Oracle type + DPI_NATIVE_TYPE_TIMESTAMP, // default native type + DPI_SQLT_TIMESTAMP, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_TIMESTAMP_TZ, // public Oracle type + DPI_NATIVE_TYPE_TIMESTAMP, // default native type + DPI_SQLT_TIMESTAMP_TZ, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_TIMESTAMP_LTZ, // public Oracle type + DPI_NATIVE_TYPE_TIMESTAMP, // default native type + DPI_SQLT_TIMESTAMP_LTZ, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_INTERVAL_DS, // public Oracle type + DPI_NATIVE_TYPE_INTERVAL_DS, // default native type + DPI_SQLT_INTERVAL_DS, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_INTERVAL_YM, // public Oracle type + DPI_NATIVE_TYPE_INTERVAL_YM, // default native type + DPI_SQLT_INTERVAL_YM, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_CLOB, // public Oracle type + DPI_NATIVE_TYPE_LOB, // default native type + DPI_SQLT_CLOB, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 1, // is character data + 0, // can be in array + 1 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_NCLOB, // public Oracle type + DPI_NATIVE_TYPE_LOB, // default native type + DPI_SQLT_CLOB, // internal Oracle type + DPI_SQLCS_NCHAR, // charset form + sizeof(void*), // buffer size + 1, // is character data + 0, // can be in array + 1 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_BLOB, // public Oracle type + DPI_NATIVE_TYPE_LOB, // default native type + DPI_SQLT_BLOB, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 0, // is character data + 0, // can be in array + 1 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_BFILE, // public Oracle type + DPI_NATIVE_TYPE_LOB, // default native type + DPI_SQLT_BFILE, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 0, // is character data + 0, // can be in array + 1 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_STMT, // public Oracle type + DPI_NATIVE_TYPE_STMT, // default native type + DPI_SQLT_RSET, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 0, // is character data + 0, // can be in array + 1 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_BOOLEAN, // public Oracle type + DPI_NATIVE_TYPE_BOOLEAN, // default native type + DPI_SQLT_BOL, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(int), // buffer size + 0, // is character data + 0, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_OBJECT, // public Oracle type + DPI_NATIVE_TYPE_OBJECT, // default native type + DPI_SQLT_NTY, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(void*), // buffer size + 0, // is character data + 0, // can be in array + 1 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_LONG_VARCHAR, // public Oracle type + DPI_NATIVE_TYPE_BYTES, // default native type + DPI_SQLT_CHR, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + DPI_MAX_BASIC_BUFFER_SIZE + 1, // buffer size + 1, // is character data + 0, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_LONG_RAW, // public Oracle type + DPI_NATIVE_TYPE_BYTES, // default native type + DPI_SQLT_BIN, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + DPI_MAX_BASIC_BUFFER_SIZE + 1, // buffer size + 0, // is character data + 0, // can be in array + 0 // requires pre-fetch + }, + { + DPI_ORACLE_TYPE_NATIVE_UINT, // public Oracle type + DPI_NATIVE_TYPE_UINT64, // default native type + DPI_SQLT_UIN, // internal Oracle type + DPI_SQLCS_IMPLICIT, // charset form + sizeof(uint64_t), // buffer size + 0, // is character data + 1, // can be in array + 0 // requires pre-fetch + } +}; + + +//----------------------------------------------------------------------------- +// dpiOracleType__convertFromOracle() [INTERNAL] +// Return a value from the dpiOracleTypeNum enumeration for the OCI data type +// and charset form. If the OCI data type is not supported, 0 is returned. +//----------------------------------------------------------------------------- +static dpiOracleTypeNum dpiOracleType__convertFromOracle(uint16_t typeCode, + uint8_t charsetForm) +{ + switch(typeCode) { + case DPI_SQLT_CHR: + case DPI_SQLT_VCS: + if (charsetForm == DPI_SQLCS_NCHAR) + return DPI_ORACLE_TYPE_NVARCHAR; + return DPI_ORACLE_TYPE_VARCHAR; + case DPI_SQLT_INT: + case DPI_SQLT_FLT: + case DPI_SQLT_NUM: + case DPI_SQLT_PDN: + case DPI_SQLT_VNU: + case DPI_SQLT_BFLOAT: + case DPI_SQLT_BDOUBLE: + case DPI_OCI_TYPECODE_SMALLINT: + return DPI_ORACLE_TYPE_NUMBER; + case DPI_SQLT_DAT: + case DPI_SQLT_ODT: + return DPI_ORACLE_TYPE_DATE; + case DPI_SQLT_BIN: + case DPI_SQLT_LVB: + return DPI_ORACLE_TYPE_RAW; + case DPI_SQLT_AFC: + if (charsetForm == DPI_SQLCS_NCHAR) + return DPI_ORACLE_TYPE_NCHAR; + return DPI_ORACLE_TYPE_CHAR; + case DPI_OCI_TYPECODE_BINARY_INTEGER: + case DPI_OCI_TYPECODE_PLS_INTEGER: + return DPI_ORACLE_TYPE_NATIVE_INT; + case DPI_SQLT_IBFLOAT: + return DPI_ORACLE_TYPE_NATIVE_FLOAT; + case DPI_SQLT_IBDOUBLE: + return DPI_ORACLE_TYPE_NATIVE_DOUBLE; + case DPI_SQLT_DATE: + case DPI_SQLT_TIMESTAMP: + return DPI_ORACLE_TYPE_TIMESTAMP; + case DPI_SQLT_TIMESTAMP_TZ: + return DPI_ORACLE_TYPE_TIMESTAMP_TZ; + case DPI_SQLT_TIMESTAMP_LTZ: + return DPI_ORACLE_TYPE_TIMESTAMP_LTZ; + case DPI_SQLT_NTY: + case DPI_SQLT_REC: + case DPI_SQLT_NCO: + return DPI_ORACLE_TYPE_OBJECT; + case DPI_SQLT_BOL: + return DPI_ORACLE_TYPE_BOOLEAN; + case DPI_SQLT_CLOB: + if (charsetForm == DPI_SQLCS_NCHAR) + return DPI_ORACLE_TYPE_NCLOB; + return DPI_ORACLE_TYPE_CLOB; + case DPI_SQLT_BLOB: + return DPI_ORACLE_TYPE_BLOB; + case DPI_SQLT_BFILE: + return DPI_ORACLE_TYPE_BFILE; + case DPI_SQLT_RDD: + case DPI_OCI_TYPECODE_ROWID: + return DPI_ORACLE_TYPE_ROWID; + case DPI_SQLT_RSET: + return DPI_ORACLE_TYPE_STMT; + case DPI_SQLT_INTERVAL_DS: + return DPI_ORACLE_TYPE_INTERVAL_DS; + case DPI_SQLT_INTERVAL_YM: + return DPI_ORACLE_TYPE_INTERVAL_YM; + case DPI_SQLT_LNG: + case DPI_OCI_TYPECODE_LONG: + return DPI_ORACLE_TYPE_LONG_VARCHAR; + case DPI_SQLT_LBI: + case DPI_OCI_TYPECODE_LONG_RAW: + return DPI_ORACLE_TYPE_LONG_RAW; + } + return (dpiOracleTypeNum) 0; +} + + +//----------------------------------------------------------------------------- +// dpiOracleType__getFromNum() [INTERNAL] +// Return the type associated with the type number. +//----------------------------------------------------------------------------- +const dpiOracleType *dpiOracleType__getFromNum(dpiOracleTypeNum typeNum, + dpiError *error) +{ + if (typeNum > DPI_ORACLE_TYPE_NONE && typeNum < DPI_ORACLE_TYPE_MAX) + return &dpiAllOracleTypes[typeNum - DPI_ORACLE_TYPE_NONE - 1]; + dpiError__set(error, "check type", DPI_ERR_INVALID_ORACLE_TYPE, typeNum); + return NULL; +} + + +//----------------------------------------------------------------------------- +// dpiOracleType__populateTypeInfo() [INTERNAL] +// Populate dpiDataTypeInfo structure given an Oracle descriptor. Note that +// no error is raised by this function if the data type is not supported. This +// method is called for both implicit and explicit describes (which behave +// slightly differently). +//----------------------------------------------------------------------------- +int dpiOracleType__populateTypeInfo(dpiConn *conn, void *handle, + uint32_t handleType, dpiDataTypeInfo *info, dpiError *error) +{ + const dpiOracleType *oracleType = NULL; + dpiNativeTypeNum nativeTypeNum; + uint32_t dataTypeAttribute; + uint8_t charsetForm; + uint16_t ociSize; + + // acquire data type + if (handleType == DPI_OCI_DTYPE_PARAM) + dataTypeAttribute = DPI_OCI_ATTR_TYPECODE; + else dataTypeAttribute = DPI_OCI_ATTR_DATA_TYPE; + if (dpiOci__attrGet(handle, handleType, (void*) &info->ociTypeCode, 0, + dataTypeAttribute, "get data type", error) < 0) + return DPI_FAILURE; + + // acquire character set form + if (info->ociTypeCode != DPI_SQLT_CHR && + info->ociTypeCode != DPI_SQLT_AFC && + info->ociTypeCode != DPI_SQLT_VCS && + info->ociTypeCode != DPI_SQLT_CLOB) + charsetForm = DPI_SQLCS_IMPLICIT; + else if (dpiOci__attrGet(handle, handleType, (void*) &charsetForm, 0, + DPI_OCI_ATTR_CHARSET_FORM, "get charset form", error) < 0) + return DPI_FAILURE; + + // convert Oracle type to ODPI-C enumerations, if possible + info->oracleTypeNum = dpiOracleType__convertFromOracle(info->ociTypeCode, + charsetForm); + if (!info->oracleTypeNum) + info->defaultNativeTypeNum = (dpiNativeTypeNum) 0; + else { + oracleType = dpiOracleType__getFromNum(info->oracleTypeNum, error); + if (!oracleType) + return DPI_FAILURE; + info->defaultNativeTypeNum = oracleType->defaultNativeTypeNum; + } + + // determine precision/scale + nativeTypeNum = info->defaultNativeTypeNum; + switch (nativeTypeNum) { + case DPI_NATIVE_TYPE_DOUBLE: + case DPI_NATIVE_TYPE_FLOAT: + case DPI_NATIVE_TYPE_INT64: + case DPI_NATIVE_TYPE_TIMESTAMP: + case DPI_NATIVE_TYPE_INTERVAL_YM: + case DPI_NATIVE_TYPE_INTERVAL_DS: + if (dpiOci__attrGet(handle, handleType, (void*) &info->scale, 0, + DPI_OCI_ATTR_SCALE, "get scale", error) < 0) + return DPI_FAILURE; + if (dpiOci__attrGet(handle, handleType, (void*) &info->precision, + 0, DPI_OCI_ATTR_PRECISION, "get precision", error) < 0) + return DPI_FAILURE; + if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP || + nativeTypeNum == DPI_NATIVE_TYPE_INTERVAL_DS) { + info->fsPrecision = (uint8_t) info->scale; + info->scale = 0; + } + break; + default: + info->precision = 0; + info->fsPrecision = 0; + info->scale = 0; + break; + } + + // change default type to integer if precision/scale supports it + if (info->oracleTypeNum == DPI_ORACLE_TYPE_NUMBER && info->scale == 0 && + info->precision > 0 && info->precision <= DPI_MAX_INT64_PRECISION) + info->defaultNativeTypeNum = DPI_NATIVE_TYPE_INT64; + + // acquire size (in bytes) of item + info->sizeInChars = 0; + if (oracleType && oracleType->sizeInBytes == 0) { + if (dpiOci__attrGet(handle, handleType, (void*) &ociSize, 0, + DPI_OCI_ATTR_DATA_SIZE, "get size (bytes)", error) < 0) + return DPI_FAILURE; + info->dbSizeInBytes = ociSize; + info->clientSizeInBytes = ociSize; + } else { + info->dbSizeInBytes = 0; + info->clientSizeInBytes = 0; + } + + // acquire size (in characters) of item, if applicable + if (oracleType && oracleType->isCharacterData && + oracleType->sizeInBytes == 0) { + if (dpiOci__attrGet(handle, handleType, (void*) &ociSize, 0, + DPI_OCI_ATTR_CHAR_SIZE, "get size (chars)", error) < 0) + return DPI_FAILURE; + info->sizeInChars = ociSize; + if (charsetForm == DPI_SQLCS_NCHAR) + info->clientSizeInBytes = info->sizeInChars * + conn->env->nmaxBytesPerCharacter; + else if (conn->charsetId != conn->env->charsetId) + info->clientSizeInBytes = info->sizeInChars * + conn->env->maxBytesPerCharacter; + } + + // acquire object type, if applicable + if (info->oracleTypeNum == DPI_ORACLE_TYPE_OBJECT) { + if (dpiObjectType__allocate(conn, handle, DPI_OCI_ATTR_TYPE_NAME, + &info->objectType, error) < 0) + return DPI_FAILURE; + if (dpiObjectType__isXmlType(info->objectType)) { + dpiObjectType__free(info->objectType, error); + info->objectType = NULL; + info->ociTypeCode = DPI_SQLT_CHR; + info->oracleTypeNum = DPI_ORACLE_TYPE_LONG_VARCHAR; + info->defaultNativeTypeNum = DPI_NATIVE_TYPE_BYTES; + } + } + + return DPI_SUCCESS; +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiPool.c b/vendor/github.com/godror/godror/odpi/src/dpiPool.c new file mode 100644 index 00000000000..58f21e5efc9 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiPool.c @@ -0,0 +1,586 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiPool.c +// Implementation of session pools. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiPool__acquireConnection() [INTERNAL] +// Internal method used for acquiring a connection from a pool. +//----------------------------------------------------------------------------- +int dpiPool__acquireConnection(dpiPool *pool, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + dpiConnCreateParams *params, dpiConn **conn, dpiError *error) +{ + dpiConn *tempConn; + + // allocate new connection + if (dpiGen__allocate(DPI_HTYPE_CONN, pool->env, (void**) &tempConn, + error) < 0) + return DPI_FAILURE; + error->env = pool->env; + + // create the connection + if (dpiConn__create(tempConn, pool->env->context, userName, userNameLength, + password, passwordLength, pool->name, pool->nameLength, pool, + NULL, params, error) < 0) { + dpiConn__free(tempConn, error); + return DPI_FAILURE; + } + + *conn = tempConn; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiPool__checkConnected() [INTERNAL] +// Determine if the session pool is connected to the database. If not, an +// error is raised. +//----------------------------------------------------------------------------- +static int dpiPool__checkConnected(dpiPool *pool, const char *fnName, + dpiError *error) +{ + if (dpiGen__startPublicFn(pool, DPI_HTYPE_POOL, fnName, error) < 0) + return DPI_FAILURE; + if (!pool->handle) + return dpiError__set(error, "check pool", DPI_ERR_NOT_CONNECTED); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiPool__create() [INTERNAL] +// Internal method for creating a session pool. +//----------------------------------------------------------------------------- +static int dpiPool__create(dpiPool *pool, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + const char *connectString, uint32_t connectStringLength, + const dpiCommonCreateParams *commonParams, + dpiPoolCreateParams *createParams, dpiError *error) +{ + uint32_t poolMode; + uint8_t getMode; + void *authInfo; + + // validate parameters + if (createParams->externalAuth && + ((userName && userNameLength > 0) || + (password && passwordLength > 0))) + return dpiError__set(error, "check mixed credentials", + DPI_ERR_EXT_AUTH_WITH_CREDENTIALS); + + // create the session pool handle + if (dpiOci__handleAlloc(pool->env->handle, &pool->handle, + DPI_OCI_HTYPE_SPOOL, "allocate pool handle", error) < 0) + return DPI_FAILURE; + + // prepare pool mode + poolMode = DPI_OCI_SPC_STMTCACHE; + if (createParams->homogeneous) + poolMode |= DPI_OCI_SPC_HOMOGENEOUS; + + // create authorization handle + if (dpiOci__handleAlloc(pool->env->handle, &authInfo, + DPI_OCI_HTYPE_AUTHINFO, "allocate authinfo handle", error) < 0) + return DPI_FAILURE; + + // set context attributes + if (dpiUtils__setAttributesFromCommonCreateParams(authInfo, + DPI_OCI_HTYPE_AUTHINFO, commonParams, error) < 0) + return DPI_FAILURE; + + // set PL/SQL session state fixup callback, if applicable + if (createParams->plsqlFixupCallback && + createParams->plsqlFixupCallbackLength > 0) { + if (dpiUtils__checkClientVersion(pool->env->versionInfo, 12, 2, + error) < 0) + return DPI_FAILURE; + if (dpiOci__attrSet(authInfo, DPI_OCI_HTYPE_AUTHINFO, + (void*) createParams->plsqlFixupCallback, + createParams->plsqlFixupCallbackLength, + DPI_OCI_ATTR_FIXUP_CALLBACK, + "set PL/SQL session state fixup callback", error) < 0) + return DPI_FAILURE; + } + + // set authorization info on session pool + if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) authInfo, 0, + DPI_OCI_ATTR_SPOOL_AUTH, "set auth info", error) < 0) + return DPI_FAILURE; + + // create pool + if (dpiOci__sessionPoolCreate(pool, connectString, connectStringLength, + createParams->minSessions, createParams->maxSessions, + createParams->sessionIncrement, userName, userNameLength, password, + passwordLength, poolMode, error) < 0) + return DPI_FAILURE; + + // set the get mode on the pool + getMode = (uint8_t) createParams->getMode; + if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) &getMode, 0, + DPI_OCI_ATTR_SPOOL_GETMODE, "set get mode", error) < 0) + return DPI_FAILURE; + + // set the session timeout on the pool + if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) + &createParams->timeout, 0, DPI_OCI_ATTR_SPOOL_TIMEOUT, + "set timeout", error) < 0) + return DPI_FAILURE; + + // set the wait timeout on the pool (valid in 12.2 and higher) + if (pool->env->versionInfo->versionNum > 12 || + (pool->env->versionInfo->versionNum == 12 && + pool->env->versionInfo->releaseNum >= 2)) { + if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) + &createParams->waitTimeout, 0, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT, + "set wait timeout", error) < 0) + return DPI_FAILURE; + } + + // set the maximum lifetime session on the pool (valid in 12.1 and higher) + if (pool->env->versionInfo->versionNum >= 12) { + if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) + &createParams->maxLifetimeSession, 0, + DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION, + "set max lifetime session", error) < 0) + return DPI_FAILURE; + } + + // set the maximum number of sessions per shard (valid in 18.3 and higher) + if (pool->env->versionInfo->versionNum > 18 || + (pool->env->versionInfo->versionNum == 18 && + pool->env->versionInfo->releaseNum >= 3)) { + if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) + &createParams->maxSessionsPerShard, 0, + DPI_OCI_ATTR_SPOOL_MAX_PER_SHARD, + "set max sessions per shard", error) < 0) + return DPI_FAILURE; + } + + // set reamining attributes directly + pool->homogeneous = createParams->homogeneous; + pool->externalAuth = createParams->externalAuth; + pool->pingInterval = createParams->pingInterval; + pool->pingTimeout = createParams->pingTimeout; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiPool__free() [INTERNAL] +// Free any memory associated with the pool. +//----------------------------------------------------------------------------- +void dpiPool__free(dpiPool *pool, dpiError *error) +{ + if (pool->handle) { + dpiOci__sessionPoolDestroy(pool, DPI_OCI_SPD_FORCE, 0, error); + pool->handle = NULL; + } + if (pool->env) { + dpiEnv__free(pool->env, error); + pool->env = NULL; + } + dpiUtils__freeMemory(pool); +} + + +//----------------------------------------------------------------------------- +// dpiPool__getAttributeUint() [INTERNAL] +// Return the value of the attribute as an unsigned integer. +//----------------------------------------------------------------------------- +static int dpiPool__getAttributeUint(dpiPool *pool, uint32_t attribute, + uint32_t *value, const char *fnName) +{ + int status, supported = 1; + dpiError error; + + if (dpiPool__checkConnected(pool, fnName, &error) < 0) + return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(pool, value) + switch (attribute) { + case DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION: + if (pool->env->versionInfo->versionNum < 12) + supported = 0; + break; + case DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT: + if (pool->env->versionInfo->versionNum < 12 || + (pool->env->versionInfo->versionNum == 12 && + pool->env->versionInfo->releaseNum < 2)) + supported = 0; + break; + case DPI_OCI_ATTR_SPOOL_BUSY_COUNT: + case DPI_OCI_ATTR_SPOOL_OPEN_COUNT: + case DPI_OCI_ATTR_SPOOL_STMTCACHESIZE: + case DPI_OCI_ATTR_SPOOL_TIMEOUT: + break; + default: + supported = 0; + break; + } + if (supported) + status = dpiOci__attrGet(pool->handle, DPI_OCI_HTYPE_SPOOL, value, + NULL, attribute, "get attribute value", &error); + else status = dpiError__set(&error, "get attribute value", + DPI_ERR_NOT_SUPPORTED); + return dpiGen__endPublicFn(pool, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiPool__setAttributeUint() [INTERNAL] +// Set the value of the OCI attribute as an unsigned integer. +//----------------------------------------------------------------------------- +static int dpiPool__setAttributeUint(dpiPool *pool, uint32_t attribute, + uint32_t value, const char *fnName) +{ + int status, supported = 1; + void *ociValue = &value; + uint8_t shortValue; + dpiError error; + + // make sure session pool is connected + if (dpiPool__checkConnected(pool, fnName, &error) < 0) + return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); + + // determine pointer to pass (OCI uses different sizes) + switch (attribute) { + case DPI_OCI_ATTR_SPOOL_GETMODE: + shortValue = (uint8_t) value; + ociValue = &shortValue; + break; + case DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION: + if (pool->env->versionInfo->versionNum < 12) + supported = 0; + break; + case DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT: + if (pool->env->versionInfo->versionNum < 12 || + (pool->env->versionInfo->versionNum == 12 && + pool->env->versionInfo->releaseNum < 2)) + supported = 0; + break; + case DPI_OCI_ATTR_SPOOL_STMTCACHESIZE: + case DPI_OCI_ATTR_SPOOL_TIMEOUT: + break; + default: + supported = 0; + break; + } + + // set value in the OCI + if (supported) + status = dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, ociValue, + 0, attribute, "set attribute value", &error); + else status = dpiError__set(&error, "set attribute value", + DPI_ERR_NOT_SUPPORTED); + return dpiGen__endPublicFn(pool, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiPool_acquireConnection() [PUBLIC] +// Acquire a connection from the pool. +//----------------------------------------------------------------------------- +int dpiPool_acquireConnection(dpiPool *pool, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + dpiConnCreateParams *params, dpiConn **conn) +{ + dpiConnCreateParams localParams; + dpiError error; + int status; + + // validate parameters + if (dpiPool__checkConnected(pool, __func__, &error) < 0) + return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(pool, userName) + DPI_CHECK_PTR_AND_LENGTH(pool, password) + DPI_CHECK_PTR_NOT_NULL(pool, conn) + + // use default parameters if none provided + if (!params) { + dpiContext__initConnCreateParams(&localParams); + params = &localParams; + } + + // the username must be enclosed within [] if external authentication + // with proxy is desired + if (pool->externalAuth && userName && userNameLength > 0 && + (userName[0] != '[' || userName[userNameLength - 1] != ']')) { + dpiError__set(&error, "verify proxy user name with external auth", + DPI_ERR_EXT_AUTH_INVALID_PROXY); + return dpiGen__endPublicFn(pool, DPI_FAILURE, &error ); + } + + status = dpiPool__acquireConnection(pool, userName, userNameLength, + password, passwordLength, params, conn, &error); + return dpiGen__endPublicFn(pool, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiPool_addRef() [PUBLIC] +// Add a reference to the pool. +//----------------------------------------------------------------------------- +int dpiPool_addRef(dpiPool *pool) +{ + return dpiGen__addRef(pool, DPI_HTYPE_POOL, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_close() [PUBLIC] +// Destroy the pool now, not when the reference count reaches zero. +//----------------------------------------------------------------------------- +int dpiPool_close(dpiPool *pool, dpiPoolCloseMode mode) +{ + dpiError error; + + if (dpiPool__checkConnected(pool, __func__, &error) < 0) + return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); + if (dpiOci__sessionPoolDestroy(pool, mode, 1, &error) < 0) + return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); + return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiPool_create() [PUBLIC] +// Create a new session pool and return it. +//----------------------------------------------------------------------------- +int dpiPool_create(const dpiContext *context, const char *userName, + uint32_t userNameLength, const char *password, uint32_t passwordLength, + const char *connectString, uint32_t connectStringLength, + const dpiCommonCreateParams *commonParams, + dpiPoolCreateParams *createParams, dpiPool **pool) +{ + dpiCommonCreateParams localCommonParams; + dpiPoolCreateParams localCreateParams; + dpiPool *tempPool; + dpiError error; + + // validate parameters + if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, + &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(context, userName) + DPI_CHECK_PTR_AND_LENGTH(context, password) + DPI_CHECK_PTR_AND_LENGTH(context, connectString) + DPI_CHECK_PTR_NOT_NULL(context, pool) + + // use default parameters if none provided + if (!commonParams) { + dpiContext__initCommonCreateParams(&localCommonParams); + commonParams = &localCommonParams; + } + + // size changed in 3.1; must use local variable until version 4 released + if (!createParams || context->dpiMinorVersion < 1) { + dpiContext__initPoolCreateParams(&localCreateParams); + if (createParams) + memcpy(&localCreateParams, createParams, + sizeof(dpiPoolCreateParams__v30)); + createParams = &localCreateParams; + } + + // allocate memory for pool + if (dpiGen__allocate(DPI_HTYPE_POOL, NULL, (void**) &tempPool, &error) < 0) + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + + // initialize environment + if (dpiEnv__init(tempPool->env, context, commonParams, NULL, &error) < 0) { + dpiPool__free(tempPool, &error); + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + } + + // perform remaining steps required to create pool + if (dpiPool__create(tempPool, userName, userNameLength, password, + passwordLength, connectString, connectStringLength, commonParams, + createParams, &error) < 0) { + dpiPool__free(tempPool, &error); + return dpiGen__endPublicFn(context, DPI_FAILURE, &error); + } + + createParams->outPoolName = tempPool->name; + createParams->outPoolNameLength = tempPool->nameLength; + *pool = tempPool; + dpiHandlePool__release(tempPool->env->errorHandles, &error.handle); + return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiPool_getBusyCount() [PUBLIC] +// Return the pool's busy count. +//----------------------------------------------------------------------------- +int dpiPool_getBusyCount(dpiPool *pool, uint32_t *value) +{ + return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_BUSY_COUNT, + value, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_getEncodingInfo() [PUBLIC] +// Get the encoding information from the pool. +//----------------------------------------------------------------------------- +int dpiPool_getEncodingInfo(dpiPool *pool, dpiEncodingInfo *info) +{ + dpiError error; + int status; + + if (dpiPool__checkConnected(pool, __func__, &error) < 0) + return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(pool, info) + status = dpiEnv__getEncodingInfo(pool->env, info); + return dpiGen__endPublicFn(pool, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiPool_getGetMode() [PUBLIC] +// Return the pool's "get" mode. +//----------------------------------------------------------------------------- +int dpiPool_getGetMode(dpiPool *pool, dpiPoolGetMode *value) +{ + dpiError error; + + if (dpiPool__checkConnected(pool, __func__, &error) < 0) + return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(pool, value) + if (dpiOci__attrGet(pool->handle, DPI_OCI_HTYPE_SPOOL, value, NULL, + DPI_OCI_ATTR_SPOOL_GETMODE, "get attribute value", &error) < 0) + return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); + return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiPool_getMaxLifetimeSession() [PUBLIC] +// Return the pool's maximum lifetime session. +//----------------------------------------------------------------------------- +int dpiPool_getMaxLifetimeSession(dpiPool *pool, uint32_t *value) +{ + return dpiPool__getAttributeUint(pool, + DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION, value, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_getOpenCount() [PUBLIC] +// Return the pool's open count. +//----------------------------------------------------------------------------- +int dpiPool_getOpenCount(dpiPool *pool, uint32_t *value) +{ + return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_OPEN_COUNT, + value, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_getStmtCacheSize() [PUBLIC] +// Return the pool's default statement cache size. +//----------------------------------------------------------------------------- +int dpiPool_getStmtCacheSize(dpiPool *pool, uint32_t *value) +{ + return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_STMTCACHESIZE, + value, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_getTimeout() [PUBLIC] +// Return the pool's timeout value. +//----------------------------------------------------------------------------- +int dpiPool_getTimeout(dpiPool *pool, uint32_t *value) +{ + return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_TIMEOUT, value, + __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_getWaitTimeout() [PUBLIC] +// Return the pool's wait timeout value. +//----------------------------------------------------------------------------- +int dpiPool_getWaitTimeout(dpiPool *pool, uint32_t *value) +{ + return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT, + value, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_release() [PUBLIC] +// Release a reference to the pool. +//----------------------------------------------------------------------------- +int dpiPool_release(dpiPool *pool) +{ + return dpiGen__release(pool, DPI_HTYPE_POOL, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_setGetMode() [PUBLIC] +// Set the pool's "get" mode. +//----------------------------------------------------------------------------- +int dpiPool_setGetMode(dpiPool *pool, dpiPoolGetMode value) +{ + return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_GETMODE, value, + __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_setMaxLifetimeSession() [PUBLIC] +// Set the pool's maximum lifetime session. +//----------------------------------------------------------------------------- +int dpiPool_setMaxLifetimeSession(dpiPool *pool, uint32_t value) +{ + return dpiPool__setAttributeUint(pool, + DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION, value, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_setStmtCacheSize() [PUBLIC] +// Set the pool's default statement cache size. +//----------------------------------------------------------------------------- +int dpiPool_setStmtCacheSize(dpiPool *pool, uint32_t value) +{ + return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_STMTCACHESIZE, + value, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_setTimeout() [PUBLIC] +// Set the pool's timeout value. +//----------------------------------------------------------------------------- +int dpiPool_setTimeout(dpiPool *pool, uint32_t value) +{ + return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_TIMEOUT, value, + __func__); +} + + +//----------------------------------------------------------------------------- +// dpiPool_setWaitTimeout() [PUBLIC] +// Set the pool's wait timeout value. +//----------------------------------------------------------------------------- +int dpiPool_setWaitTimeout(dpiPool *pool, uint32_t value) +{ + return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT, + value, __func__); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiQueue.c b/vendor/github.com/godror/godror/odpi/src/dpiQueue.c new file mode 100644 index 00000000000..9c2f39a9a82 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiQueue.c @@ -0,0 +1,560 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiQueue.c +// Implementation of AQ queues. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +// forward declarations of internal functions only used in this file +static int dpiQueue__allocateBuffer(dpiQueue *queue, uint32_t numElements, + dpiError *error); +static int dpiQueue__deq(dpiQueue *queue, uint32_t *numProps, + dpiMsgProps **props, dpiError *error); +static void dpiQueue__freeBuffer(dpiQueue *queue, dpiError *error); +static int dpiQueue__getPayloadTDO(dpiQueue *queue, void **tdo, + dpiError *error); + + +//----------------------------------------------------------------------------- +// dpiQueue__allocate() [INTERNAL] +// Allocate and initialize a queue. +//----------------------------------------------------------------------------- +int dpiQueue__allocate(dpiConn *conn, const char *name, uint32_t nameLength, + dpiObjectType *payloadType, dpiQueue **queue, dpiError *error) +{ + dpiQueue *tempQueue; + char *buffer; + + // allocate handle; store reference to the connection that created it + if (dpiGen__allocate(DPI_HTYPE_QUEUE, conn->env, (void**) &tempQueue, + error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(conn, error, 1); + tempQueue->conn = conn; + + // store payload type, which is either an object type or NULL (meaning that + // RAW payloads are being enqueued and dequeued) + if (payloadType) { + dpiGen__setRefCount(payloadType, error, 1); + tempQueue->payloadType = payloadType; + } + + // allocate space for the name of the queue; OCI requires a NULL-terminated + // string so allocate enough space to store the NULL terminator; UTF-16 + // encoded strings are not currently supported + if (dpiUtils__allocateMemory(1, nameLength + 1, 0, "queue name", + (void**) &buffer, error) < 0) { + dpiQueue__free(tempQueue, error); + return DPI_FAILURE; + } + memcpy(buffer, name, nameLength); + buffer[nameLength] = '\0'; + tempQueue->name = buffer; + + *queue = tempQueue; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiQueue__allocateBuffer() [INTERNAL] +// Ensure there is enough space in the buffer for the specified number of +// elements. +//----------------------------------------------------------------------------- +static int dpiQueue__allocateBuffer(dpiQueue *queue, uint32_t numElements, + dpiError *error) +{ + dpiQueue__freeBuffer(queue, error); + queue->buffer.numElements = numElements; + if (dpiUtils__allocateMemory(numElements, sizeof(dpiMsgProps*), 1, + "allocate msg props array", (void**) &queue->buffer.props, + error) < 0) + return DPI_FAILURE; + if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, + "allocate OCI handles array", (void**) &queue->buffer.handles, + error) < 0) + return DPI_FAILURE; + if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, + "allocate OCI instances array", (void**) &queue->buffer.instances, + error) < 0) + return DPI_FAILURE; + if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, + "allocate OCI indicators array", + (void**) &queue->buffer.indicators, error) < 0) + return DPI_FAILURE; + if (!queue->payloadType) { + if (dpiUtils__allocateMemory(numElements, sizeof(int16_t), 1, + "allocate OCI raw indicators array", + (void**) &queue->buffer.rawIndicators, error) < 0) + return DPI_FAILURE; + } + if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, + "allocate message ids array", (void**) &queue->buffer.msgIds, + error) < 0) + return DPI_FAILURE; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiQueue__check() [INTERNAL] +// Determine if the queue is available to use. +//----------------------------------------------------------------------------- +static int dpiQueue__check(dpiQueue *queue, const char *fnName, + dpiError *error) +{ + if (dpiGen__startPublicFn(queue, DPI_HTYPE_QUEUE, fnName, error) < 0) + return DPI_FAILURE; + if (!queue->conn->handle || queue->conn->closing) + return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiQueue__createDeqOptions() [INTERNAL] +// Create the dequeue options object that will be used for performing +// dequeues against the queue. +//----------------------------------------------------------------------------- +static int dpiQueue__createDeqOptions(dpiQueue *queue, dpiError *error) +{ + dpiDeqOptions *tempOptions; + + if (dpiGen__allocate(DPI_HTYPE_DEQ_OPTIONS, queue->env, + (void**) &tempOptions, error) < 0) + return DPI_FAILURE; + if (dpiDeqOptions__create(tempOptions, queue->conn, error) < 0) { + dpiDeqOptions__free(tempOptions, error); + return DPI_FAILURE; + } + + queue->deqOptions = tempOptions; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiQueue__createEnqOptions() [INTERNAL] +// Create the dequeue options object that will be used for performing +// dequeues against the queue. +//----------------------------------------------------------------------------- +static int dpiQueue__createEnqOptions(dpiQueue *queue, dpiError *error) +{ + dpiEnqOptions *tempOptions; + + if (dpiGen__allocate(DPI_HTYPE_ENQ_OPTIONS, queue->env, + (void**) &tempOptions, error) < 0) + return DPI_FAILURE; + if (dpiEnqOptions__create(tempOptions, queue->conn, error) < 0) { + dpiEnqOptions__free(tempOptions, error); + return DPI_FAILURE; + } + + queue->enqOptions = tempOptions; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiQueue__deq() [INTERNAL] +// Perform a dequeue of up to the specified number of properties. +//----------------------------------------------------------------------------- +static int dpiQueue__deq(dpiQueue *queue, uint32_t *numProps, + dpiMsgProps **props, dpiError *error) +{ + dpiMsgProps *prop; + void *payloadTDO; + uint32_t i; + + // create dequeue options, if necessary + if (!queue->deqOptions && dpiQueue__createDeqOptions(queue, error) < 0) + return DPI_FAILURE; + + // allocate buffer, if necessary + if (queue->buffer.numElements < *numProps && + dpiQueue__allocateBuffer(queue, *numProps, error) < 0) + return DPI_FAILURE; + + // populate buffer + for (i = 0; i < *numProps; i++) { + prop = queue->buffer.props[i]; + + // create new message properties, if applicable + if (!prop) { + if (dpiMsgProps__allocate(queue->conn, &prop, error) < 0) + return DPI_FAILURE; + queue->buffer.props[i] = prop; + } + + // create payload object, if applicable + if (queue->payloadType && !prop->payloadObj && + dpiObject__allocate(queue->payloadType, NULL, NULL, NULL, + &prop->payloadObj, error) < 0) + return DPI_FAILURE; + + // set OCI arrays + queue->buffer.handles[i] = prop->handle; + if (queue->payloadType) { + queue->buffer.instances[i] = prop->payloadObj->instance; + queue->buffer.indicators[i] = prop->payloadObj->indicator; + } else { + queue->buffer.instances[i] = prop->payloadRaw; + queue->buffer.indicators[i] = &queue->buffer.rawIndicators[i]; + } + queue->buffer.msgIds[i] = prop->msgIdRaw; + + } + + // perform dequeue + if (dpiQueue__getPayloadTDO(queue, &payloadTDO, error) < 0) + return DPI_FAILURE; + if (dpiOci__aqDeqArray(queue->conn, queue->name, queue->deqOptions->handle, + numProps, queue->buffer.handles, payloadTDO, + queue->buffer.instances, queue->buffer.indicators, + queue->buffer.msgIds, error) < 0) { + if (error->buffer->code != 25228) + return DPI_FAILURE; + error->buffer->offset = (uint16_t) *numProps; + } + + // transfer message properties to destination array + for (i = 0; i < *numProps; i++) { + props[i] = queue->buffer.props[i]; + queue->buffer.props[i] = NULL; + if (!queue->payloadType) + props[i]->payloadRaw = queue->buffer.instances[i]; + props[i]->msgIdRaw = queue->buffer.msgIds[i]; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiQueue__enq() [INTERNAL] +// Perform an enqueue of the specified properties. +//----------------------------------------------------------------------------- +static int dpiQueue__enq(dpiQueue *queue, uint32_t numProps, + dpiMsgProps **props, dpiError *error) +{ + void *payloadTDO; + uint32_t i; + + // if no messages are being enqueued, nothing to do! + if (numProps == 0) + return DPI_SUCCESS; + + // create enqueue options, if necessary + if (!queue->enqOptions && dpiQueue__createEnqOptions(queue, error) < 0) + return DPI_FAILURE; + + // allocate buffer, if necessary + if (queue->buffer.numElements < numProps && + dpiQueue__allocateBuffer(queue, numProps, error) < 0) + return DPI_FAILURE; + + // populate buffer + for (i = 0; i < numProps; i++) { + + // perform checks + if (!props[i]->payloadObj && !props[i]->payloadRaw) + return dpiError__set(error, "check payload", + DPI_ERR_QUEUE_NO_PAYLOAD); + if ((queue->payloadType && !props[i]->payloadObj) || + (!queue->payloadType && props[i]->payloadObj)) + return dpiError__set(error, "check payload", + DPI_ERR_QUEUE_WRONG_PAYLOAD_TYPE); + if (queue->payloadType && props[i]->payloadObj && + queue->payloadType->tdo != props[i]->payloadObj->type->tdo) + return dpiError__set(error, "check payload", + DPI_ERR_WRONG_TYPE, + props[i]->payloadObj->type->schemaLength, + props[i]->payloadObj->type->schema, + props[i]->payloadObj->type->nameLength, + props[i]->payloadObj->type->name, + queue->payloadType->schemaLength, + queue->payloadType->schema, + queue->payloadType->nameLength, + queue->payloadType->name); + + // set OCI arrays + queue->buffer.handles[i] = props[i]->handle; + if (queue->payloadType) { + queue->buffer.instances[i] = props[i]->payloadObj->instance; + queue->buffer.indicators[i] = props[i]->payloadObj->indicator; + } else { + queue->buffer.instances[i] = props[i]->payloadRaw; + queue->buffer.indicators[i] = &queue->buffer.rawIndicators[i]; + } + queue->buffer.msgIds[i] = props[i]->msgIdRaw; + + } + + // perform enqueue + if (dpiQueue__getPayloadTDO(queue, &payloadTDO, error) < 0) + return DPI_FAILURE; + if (numProps == 1) { + if (dpiOci__aqEnq(queue->conn, queue->name, queue->enqOptions->handle, + queue->buffer.handles[0], payloadTDO, queue->buffer.instances, + queue->buffer.indicators, queue->buffer.msgIds, error) < 0) + return DPI_FAILURE; + } else { + if (dpiOci__aqEnqArray(queue->conn, queue->name, + queue->enqOptions->handle, &numProps, queue->buffer.handles, + payloadTDO, queue->buffer.instances, queue->buffer.indicators, + queue->buffer.msgIds, error) < 0) { + error->buffer->offset = (uint16_t) numProps; + return DPI_FAILURE; + } + } + + // transfer message ids back to message properties + for (i = 0; i < numProps; i++) + props[i]->msgIdRaw = queue->buffer.msgIds[i]; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiQueue__free() [INTERNAL] +// Free the memory for a queue. +//----------------------------------------------------------------------------- +void dpiQueue__free(dpiQueue *queue, dpiError *error) +{ + if (queue->conn) { + dpiGen__setRefCount(queue->conn, error, -1); + queue->conn = NULL; + } + if (queue->payloadType) { + dpiGen__setRefCount(queue->payloadType, error, -1); + queue->payloadType = NULL; + } + if (queue->name) { + dpiUtils__freeMemory((void*) queue->name); + queue->name = NULL; + } + if (queue->deqOptions) { + dpiGen__setRefCount(queue->deqOptions, error, -1); + queue->deqOptions = NULL; + } + if (queue->enqOptions) { + dpiGen__setRefCount(queue->enqOptions, error, -1); + queue->enqOptions = NULL; + } + dpiQueue__freeBuffer(queue, error); + dpiUtils__freeMemory(queue); +} + + +//----------------------------------------------------------------------------- +// dpiQueue__freeBuffer() [INTERNAL] +// Free the memory areas in the queue buffer. +//----------------------------------------------------------------------------- +static void dpiQueue__freeBuffer(dpiQueue *queue, dpiError *error) +{ + dpiQueueBuffer *buffer = &queue->buffer; + uint32_t i; + + if (buffer->props) { + for (i = 0; i < buffer->numElements; i++) { + if (buffer->props[i]) { + dpiGen__setRefCount(buffer->props[i], error, -1); + buffer->props[i] = NULL; + } + } + dpiUtils__freeMemory(buffer->props); + buffer->props = NULL; + } + if (buffer->handles) { + dpiUtils__freeMemory(buffer->handles); + buffer->handles = NULL; + } + if (buffer->instances) { + dpiUtils__freeMemory(buffer->instances); + buffer->instances = NULL; + } + if (buffer->indicators) { + dpiUtils__freeMemory(buffer->indicators); + buffer->indicators = NULL; + } + if (buffer->rawIndicators) { + dpiUtils__freeMemory(buffer->rawIndicators); + buffer->rawIndicators = NULL; + } + if (buffer->msgIds) { + dpiUtils__freeMemory(buffer->msgIds); + buffer->msgIds = NULL; + } +} + + +//----------------------------------------------------------------------------- +// dpiQueue__getPayloadTDO() [INTERNAL] +// Acquire the TDO to use for the payload. This will either be the TDO of the +// object type (if one was specified when the queue was created) or it will be +// the RAW TDO cached on the connection. +//----------------------------------------------------------------------------- +static int dpiQueue__getPayloadTDO(dpiQueue *queue, void **tdo, + dpiError *error) +{ + if (queue->payloadType) { + *tdo = queue->payloadType->tdo; + } else { + if (dpiConn__getRawTDO(queue->conn, error) < 0) + return DPI_FAILURE; + *tdo = queue->conn->rawTDO; + } + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiQueue_addRef() [PUBLIC] +// Add a reference to the queue. +//----------------------------------------------------------------------------- +int dpiQueue_addRef(dpiQueue *queue) +{ + return dpiGen__addRef(queue, DPI_HTYPE_QUEUE, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiQueue_deqMany() [PUBLIC] +// Dequeue multiple messages from the queue. +//----------------------------------------------------------------------------- +int dpiQueue_deqMany(dpiQueue *queue, uint32_t *numProps, dpiMsgProps **props) +{ + dpiError error; + int status; + + if (dpiQueue__check(queue, __func__, &error) < 0) + return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(queue, numProps) + DPI_CHECK_PTR_NOT_NULL(queue, props) + status = dpiQueue__deq(queue, numProps, props, &error); + return dpiGen__endPublicFn(queue, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiQueue_deqOne() [PUBLIC] +// Dequeue a single message from the queue. +//----------------------------------------------------------------------------- +int dpiQueue_deqOne(dpiQueue *queue, dpiMsgProps **props) +{ + uint32_t numProps = 1; + dpiError error; + + if (dpiQueue__check(queue, __func__, &error) < 0) + return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(queue, props) + if (dpiQueue__deq(queue, &numProps, props, &error) < 0) + return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); + if (numProps == 0) + *props = NULL; + return dpiGen__endPublicFn(queue, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiQueue_enqMany() [PUBLIC] +// Enqueue multiple message to the queue. +//----------------------------------------------------------------------------- +int dpiQueue_enqMany(dpiQueue *queue, uint32_t numProps, dpiMsgProps **props) +{ + dpiError error; + uint32_t i; + int status; + + // validate parameters + if (dpiQueue__check(queue, __func__, &error) < 0) + return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(queue, props) + for (i = 0; i < numProps; i++) { + if (dpiGen__checkHandle(props[i], DPI_HTYPE_MSG_PROPS, + "check message properties", &error) < 0) + return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); + } + status = dpiQueue__enq(queue, numProps, props, &error); + return dpiGen__endPublicFn(queue, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiQueue_enqOne() [PUBLIC] +// Enqueue a single message to the queue. +//----------------------------------------------------------------------------- +int dpiQueue_enqOne(dpiQueue *queue, dpiMsgProps *props) +{ + dpiError error; + int status; + + if (dpiQueue__check(queue, __func__, &error) < 0) + return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); + if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS, + "check message properties", &error) < 0) + return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); + status = dpiQueue__enq(queue, 1, &props, &error); + return dpiGen__endPublicFn(queue, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiQueue_getDeqOptions() [PUBLIC] +// Return the dequeue options associated with the queue. If no dequeue +// options are currently associated with the queue, create them first. +//----------------------------------------------------------------------------- +int dpiQueue_getDeqOptions(dpiQueue *queue, dpiDeqOptions **options) +{ + dpiError error; + + if (dpiGen__startPublicFn(queue, DPI_HTYPE_QUEUE, __func__, &error) < 0) + return DPI_FAILURE; + DPI_CHECK_PTR_NOT_NULL(queue, options) + if (!queue->deqOptions && dpiQueue__createDeqOptions(queue, &error) < 0) + return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); + *options = queue->deqOptions; + return dpiGen__endPublicFn(queue, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiQueue_getEnqOptions() [PUBLIC] +// Return the enqueue options associated with the queue. If no enqueue +// options are currently associated with the queue, create them first. +//----------------------------------------------------------------------------- +int dpiQueue_getEnqOptions(dpiQueue *queue, dpiEnqOptions **options) +{ + dpiError error; + + if (dpiGen__startPublicFn(queue, DPI_HTYPE_QUEUE, __func__, &error) < 0) + return DPI_FAILURE; + DPI_CHECK_PTR_NOT_NULL(queue, options) + if (!queue->enqOptions && dpiQueue__createEnqOptions(queue, &error) < 0) + return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); + *options = queue->enqOptions; + return dpiGen__endPublicFn(queue, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiQueue_release() [PUBLIC] +// Release a reference to the queue. +//----------------------------------------------------------------------------- +int dpiQueue_release(dpiQueue *queue) +{ + return dpiGen__release(queue, DPI_HTYPE_QUEUE, __func__); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiRowid.c b/vendor/github.com/godror/godror/odpi/src/dpiRowid.c new file mode 100644 index 00000000000..9bda49e7cd1 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiRowid.c @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiRowid.c +// Implementation of rowids. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiRowid__allocate() [INTERNAL] +// Allocate and initialize a rowid object. +//----------------------------------------------------------------------------- +int dpiRowid__allocate(dpiConn *conn, dpiRowid **rowid, dpiError *error) +{ + dpiRowid *tempRowid; + + if (dpiGen__allocate(DPI_HTYPE_ROWID, conn->env, (void**) &tempRowid, + error) < 0) + return DPI_FAILURE; + if (dpiOci__descriptorAlloc(conn->env->handle, &tempRowid->handle, + DPI_OCI_DTYPE_ROWID, "allocate descriptor", error) < 0) { + dpiRowid__free(tempRowid, error); + return DPI_FAILURE; + } + + *rowid = tempRowid; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiRowid__free() [INTERNAL] +// Free the memory for a rowid. +//----------------------------------------------------------------------------- +void dpiRowid__free(dpiRowid *rowid, UNUSED dpiError *error) +{ + if (rowid->handle) { + dpiOci__descriptorFree(rowid->handle, DPI_OCI_DTYPE_ROWID); + rowid->handle = NULL; + } + if (rowid->buffer) { + dpiUtils__freeMemory(rowid->buffer); + rowid->buffer = NULL; + } + dpiUtils__freeMemory(rowid); +} + + +//----------------------------------------------------------------------------- +// dpiRowid_addRef() [PUBLIC] +// Add a reference to the rowid. +//----------------------------------------------------------------------------- +int dpiRowid_addRef(dpiRowid *rowid) +{ + return dpiGen__addRef(rowid, DPI_HTYPE_ROWID, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiRowid_getStringValue() [PUBLIC] +// Get the string representation of the rowid. +//----------------------------------------------------------------------------- +int dpiRowid_getStringValue(dpiRowid *rowid, const char **value, + uint32_t *valueLength) +{ + char temp, *adjustedBuffer, *sourcePtr; + uint16_t *targetPtr; + dpiError error; + uint16_t i; + + if (dpiGen__startPublicFn(rowid, DPI_HTYPE_ROWID, __func__, &error) < 0) + return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(rowid, value) + DPI_CHECK_PTR_NOT_NULL(rowid, valueLength) + if (!rowid->buffer) { + + // determine length of rowid + rowid->bufferLength = 0; + dpiOci__rowidToChar(rowid, &temp, &rowid->bufferLength, &error); + + // allocate and populate buffer containing string representation + if (dpiUtils__allocateMemory(1, rowid->bufferLength, 0, + "allocate rowid buffer", (void**) &rowid->buffer, &error) < 0) + return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); + if (dpiOci__rowidToChar(rowid, rowid->buffer, &rowid->bufferLength, + &error) < 0) + return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); + + // UTF-16 is not handled properly (data is returned as ASCII instead) + // adjust the buffer to use the correct encoding + if (rowid->env->charsetId == DPI_CHARSET_ID_UTF16) { + if (dpiUtils__allocateMemory(2, rowid->bufferLength, 0, + "allocate rowid buffer", (void**) &adjustedBuffer, + &error) < 0) { + dpiUtils__freeMemory(rowid->buffer); + rowid->bufferLength = 0; + rowid->buffer = NULL; + return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); + } + sourcePtr = rowid->buffer; + targetPtr = (uint16_t*) adjustedBuffer; + for (i = 0; i < rowid->bufferLength; i++) + *targetPtr++ = (uint16_t) *sourcePtr++; + dpiUtils__freeMemory(rowid->buffer); + rowid->buffer = adjustedBuffer; + rowid->bufferLength *= 2; + } + + } + + *value = rowid->buffer; + *valueLength = rowid->bufferLength; + return dpiGen__endPublicFn(rowid, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiRowid_release() [PUBLIC] +// Release a reference to the rowid. +//----------------------------------------------------------------------------- +int dpiRowid_release(dpiRowid *rowid) +{ + return dpiGen__release(rowid, DPI_HTYPE_ROWID, __func__); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSodaColl.c b/vendor/github.com/godror/godror/odpi/src/dpiSodaColl.c new file mode 100644 index 00000000000..b0a0ded7c34 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiSodaColl.c @@ -0,0 +1,812 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiSodaColl.c +// Implementation of SODA collections. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiSodaColl__allocate() [INTERNAL] +// Allocate and initialize a SODA collection structure. +//----------------------------------------------------------------------------- +int dpiSodaColl__allocate(dpiSodaDb *db, void *handle, dpiSodaColl **coll, + dpiError *error) +{ + uint8_t sqlType, contentType; + dpiSodaColl *tempColl; + + if (dpiOci__attrGet(handle, DPI_OCI_HTYPE_SODA_COLLECTION, + (void*) &sqlType, 0, DPI_OCI_ATTR_SODA_CTNT_SQL_TYPE, + "get content sql type", error) < 0) + return DPI_FAILURE; + if (dpiGen__allocate(DPI_HTYPE_SODA_COLL, db->env, (void**) &tempColl, + error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(db, error, 1); + tempColl->db = db; + tempColl->handle = handle; + if (sqlType == DPI_SQLT_BLOB) { + tempColl->binaryContent = 1; + contentType = 0; + dpiOci__attrGet(handle, DPI_OCI_HTYPE_SODA_COLLECTION, + (void*) &contentType, 0, DPI_OCI_ATTR_SODA_CTNT_FORMAT, + NULL, error); + if (contentType == DPI_OCI_JSON_FORMAT_OSON) + tempColl->binaryContent = 0; + } + *coll = tempColl; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl__check() [INTERNAL] +// Determine if the SODA collection is available to use. +//----------------------------------------------------------------------------- +static int dpiSodaColl__check(dpiSodaColl *coll, const char *fnName, + dpiError *error) +{ + if (dpiGen__startPublicFn(coll, DPI_HTYPE_SODA_COLL, fnName, error) < 0) + return DPI_FAILURE; + if (!coll->db->conn->handle || coll->db->conn->closing) + return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl__createOperOptions() [INTERNAL] +// Create a SODA operation options handle with the specified information. +//----------------------------------------------------------------------------- +static int dpiSodaColl__createOperOptions(dpiSodaColl *coll, + const dpiSodaOperOptions *options, void **handle, dpiError *error) +{ + dpiSodaOperOptions localOptions; + + // if no options specified, use default values + if (!options) { + dpiContext__initSodaOperOptions(&localOptions); + options = &localOptions; + } + + // allocate new handle + if (dpiOci__handleAlloc(coll->env->handle, handle, + DPI_OCI_HTYPE_SODA_OPER_OPTIONS, + "allocate SODA operation options handle", error) < 0) + return DPI_FAILURE; + + // set multiple keys, if applicable + if (options->numKeys > 0) { + if (dpiOci__sodaOperKeysSet(options, *handle, error) < 0) { + dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); + return DPI_FAILURE; + } + } + + // set single key, if applicable + if (options->keyLength > 0) { + if (dpiOci__attrSet(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, + (void*) options->key, options->keyLength, + DPI_OCI_ATTR_SODA_KEY, "set key", error) < 0) { + dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); + return DPI_FAILURE; + } + } + + // set single version, if applicable + if (options->versionLength > 0) { + if (dpiOci__attrSet(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, + (void*) options->version, options->versionLength, + DPI_OCI_ATTR_SODA_VERSION, "set version", error) < 0) { + dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); + return DPI_FAILURE; + } + } + + // set filter, if applicable + if (options->filterLength > 0) { + if (dpiOci__attrSet(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, + (void*) options->filter, options->filterLength, + DPI_OCI_ATTR_SODA_FILTER, "set filter", error) < 0) { + dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); + return DPI_FAILURE; + } + } + + // set skip count, if applicable + if (options->skip > 0) { + if (dpiOci__attrSet(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, + (void*) &options->skip, 0, DPI_OCI_ATTR_SODA_SKIP, + "set skip count", error) < 0) { + dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); + return DPI_FAILURE; + } + } + + // set limit, if applicable + if (options->limit > 0) { + if (dpiOci__attrSet(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, + (void*) &options->limit, 0, DPI_OCI_ATTR_SODA_LIMIT, + "set limit", error) < 0) { + dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); + return DPI_FAILURE; + } + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl__find() [INTERNAL] +// Perform a find of SODA documents by creating an operation options handle +// and populating it with the requested options. Once the find is complete, +// return either a cursor or a document. +//----------------------------------------------------------------------------- +static int dpiSodaColl__find(dpiSodaColl *coll, + const dpiSodaOperOptions *options, uint32_t flags, + dpiSodaDocCursor **cursor, dpiSodaDoc **doc, dpiError *error) +{ + uint32_t ociMode, returnHandleType, ociFlags; + void *optionsHandle, *ociReturnHandle; + int status; + + // determine OCI mode to pass + ociMode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + ociMode |= DPI_OCI_SODA_ATOMIC_COMMIT; + + // create new OCI operation options handle + if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, + error) < 0) + return DPI_FAILURE; + + // determine OCI flags to use + ociFlags = (coll->binaryContent) ? DPI_OCI_SODA_AS_STORED : + DPI_OCI_SODA_AS_AL32UTF8; + + // perform actual find + if (cursor) { + *cursor = NULL; + status = dpiOci__sodaFind(coll, optionsHandle, ociFlags, ociMode, + &ociReturnHandle, error); + } else { + *doc = NULL; + status = dpiOci__sodaFindOne(coll, optionsHandle, ociFlags, ociMode, + &ociReturnHandle, error); + } + dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); + if (status < 0) + return DPI_FAILURE; + + // return cursor or document, as appropriate + if (cursor) { + status = dpiSodaDocCursor__allocate(coll, ociReturnHandle, cursor, + error); + returnHandleType = DPI_OCI_HTYPE_SODA_DOC_CURSOR; + } else if (ociReturnHandle) { + status = dpiSodaDoc__allocate(coll->db, ociReturnHandle, doc, error); + returnHandleType = DPI_OCI_HTYPE_SODA_DOCUMENT; + } + if (status < 0) + dpiOci__handleFree(ociReturnHandle, returnHandleType); + + return status; +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl__free() [INTERNAL] +// Free the memory for a SODA collection. Note that the reference to the +// database must remain until after the handle is freed; otherwise, a segfault +// can take place. +//----------------------------------------------------------------------------- +void dpiSodaColl__free(dpiSodaColl *coll, dpiError *error) +{ + if (coll->handle) { + dpiOci__handleFree(coll->handle, DPI_OCI_HTYPE_SODA_COLLECTION); + coll->handle = NULL; + } + if (coll->db) { + dpiGen__setRefCount(coll->db, error, -1); + coll->db = NULL; + } + dpiUtils__freeMemory(coll); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl__getDocCount() [INTERNAL] +// Internal method for getting document count. +//----------------------------------------------------------------------------- +static int dpiSodaColl__getDocCount(dpiSodaColl *coll, + const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count, + dpiError *error) +{ + void *optionsHandle; + uint32_t ociMode; + int status; + + // determine OCI mode to pass + ociMode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + ociMode |= DPI_OCI_SODA_ATOMIC_COMMIT; + + // create new OCI operation options handle + if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, + error) < 0) + return DPI_FAILURE; + + // perform actual document count + status = dpiOci__sodaDocCount(coll, optionsHandle, ociMode, count, error); + dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); + return status; +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl__insertMany() [INTERNAL] +// Insert multiple documents into the collection and return handles to the +// newly created documents, if desired. +//----------------------------------------------------------------------------- +static int dpiSodaColl__insertMany(dpiSodaColl *coll, uint32_t numDocs, + void **docHandles, uint32_t flags, dpiSodaDoc **insertedDocs, + dpiError *error) +{ + void *optionsHandle; + uint32_t i, j, mode; + uint64_t docCount; + int status; + + // create OCI output options handle + if (dpiOci__handleAlloc(coll->env->handle, &optionsHandle, + DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS, + "allocate SODA output options handle", error) < 0) + return DPI_FAILURE; + + // determine mode to pass + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + + // perform actual bulk insert + if (insertedDocs) { + status = dpiOci__sodaBulkInsertAndGet(coll, docHandles, numDocs, + optionsHandle, mode, error); + } else { + status = dpiOci__sodaBulkInsert(coll, docHandles, numDocs, + optionsHandle, mode, error); + } + + // on failure, determine the number of documents that were successfully + // inserted and store that information in the error buffer + if (status < 0) { + dpiOci__attrGet(optionsHandle, DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS, + (void*) &docCount, 0, DPI_OCI_ATTR_SODA_DOC_COUNT, + NULL, error); + error->buffer->offset = (uint16_t) docCount; + } + dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS); + + // on failure, if using the "AndGet" variant, any document handles that + // were created need to be freed + if (insertedDocs && status < 0) { + for (i = 0; i < numDocs; i++) { + if (docHandles[i]) { + dpiOci__handleFree(docHandles[i], DPI_OCI_HTYPE_SODA_DOCUMENT); + docHandles[i] = NULL; + } + } + } + if (status < 0) + return DPI_FAILURE; + + // return document handles, if desired + if (insertedDocs) { + for (i = 0; i < numDocs; i++) { + if (dpiSodaDoc__allocate(coll->db, docHandles[i], &insertedDocs[i], + error) < 0) { + for (j = 0; j < i; j++) { + dpiSodaDoc__free(insertedDocs[j], error); + insertedDocs[j] = NULL; + } + for (j = i; j < numDocs; j++) { + dpiOci__handleFree(docHandles[i], + DPI_OCI_HTYPE_SODA_DOCUMENT); + } + return DPI_FAILURE; + } + } + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl__remove() [INTERNAL] +// Internal method for removing documents from a collection. +//----------------------------------------------------------------------------- +static int dpiSodaColl__remove(dpiSodaColl *coll, + const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count, + dpiError *error) +{ + void *optionsHandle; + uint32_t mode; + int status; + + // determine OCI mode to pass + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + + // create new OCI operation options handle + if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, + error) < 0) + return DPI_FAILURE; + + // remove documents from collection + status = dpiOci__sodaRemove(coll, optionsHandle, mode, count, error); + dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); + return status; +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl__replace() [INTERNAL] +// Internal method for replacing a document in the collection. +//----------------------------------------------------------------------------- +static int dpiSodaColl__replace(dpiSodaColl *coll, + const dpiSodaOperOptions *options, dpiSodaDoc *doc, uint32_t flags, + int *replaced, dpiSodaDoc **replacedDoc, dpiError *error) +{ + void *docHandle, *optionsHandle; + int status, dummyIsReplaced; + uint32_t mode; + + // use dummy value if the replaced flag is not desired + if (!replaced) + replaced = &dummyIsReplaced; + + // determine OCI mode to pass + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + + // create new OCI operation options handle + if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, + error) < 0) + return DPI_FAILURE; + + // replace document in collection + // use "AndGet" variant if the replaced document is requested + docHandle = doc->handle; + if (!replacedDoc) { + status = dpiOci__sodaReplOne(coll, optionsHandle, docHandle, mode, + replaced, error); + } else { + *replacedDoc = NULL; + status = dpiOci__sodaReplOneAndGet(coll, optionsHandle, &docHandle, + mode, replaced, error); + if (status == 0 && docHandle) { + status = dpiSodaDoc__allocate(coll->db, docHandle, replacedDoc, + error); + if (status < 0) + dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); + } + } + + dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); + return status; +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_addRef() [PUBLIC] +// Add a reference to the SODA collection. +//----------------------------------------------------------------------------- +int dpiSodaColl_addRef(dpiSodaColl *coll) +{ + return dpiGen__addRef(coll, DPI_HTYPE_SODA_COLL, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_createIndex() [PUBLIC] +// Create an index on the collection. +//----------------------------------------------------------------------------- +int dpiSodaColl_createIndex(dpiSodaColl *coll, const char *indexSpec, + uint32_t indexSpecLength, uint32_t flags) +{ + dpiError error; + uint32_t mode; + int status; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(coll, indexSpec) + + // determine mode to pass to OCI + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + + // create index + status = dpiOci__sodaIndexCreate(coll, indexSpec, indexSpecLength, mode, + &error); + return dpiGen__endPublicFn(coll, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_drop() [PUBLIC] +// Drop the collection. +//----------------------------------------------------------------------------- +int dpiSodaColl_drop(dpiSodaColl *coll, uint32_t flags, int *isDropped) +{ + int status, dummyIsDropped; + dpiError error; + uint32_t mode; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + + // isDropped is not a mandatory parameter, but it is for OCI + if (!isDropped) + isDropped = &dummyIsDropped; + + // determine mode to pass to OCI + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + + // drop collection + status = dpiOci__sodaCollDrop(coll, isDropped, mode, &error); + return dpiGen__endPublicFn(coll, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_dropIndex() [PUBLIC] +// Drop the index on the collection. +//----------------------------------------------------------------------------- +int dpiSodaColl_dropIndex(dpiSodaColl *coll, const char *name, + uint32_t nameLength, uint32_t flags, int *isDropped) +{ + int status, dummyIsDropped; + dpiError error; + uint32_t mode; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(coll, name) + + // isDropped is not a mandatory parameter, but it is for OCI + if (!isDropped) + isDropped = &dummyIsDropped; + + // determine mode to pass to OCI + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + if (flags & DPI_SODA_FLAGS_INDEX_DROP_FORCE) + mode |= DPI_OCI_SODA_INDEX_DROP_FORCE; + + // drop index + status = dpiOci__sodaIndexDrop(coll, name, nameLength, mode, isDropped, + &error); + return dpiGen__endPublicFn(coll, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_find() [PUBLIC] +// Find documents in a collection and return a cursor. +//----------------------------------------------------------------------------- +int dpiSodaColl_find(dpiSodaColl *coll, const dpiSodaOperOptions *options, + uint32_t flags, dpiSodaDocCursor **cursor) +{ + dpiError error; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(coll, cursor) + + // perform find and return a cursor + if (dpiSodaColl__find(coll, options, flags, cursor, NULL, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + + return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_findOne() [PUBLIC] +// Find a single document in a collection and return it. +//----------------------------------------------------------------------------- +int dpiSodaColl_findOne(dpiSodaColl *coll, const dpiSodaOperOptions *options, + uint32_t flags, dpiSodaDoc **doc) +{ + dpiError error; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(coll, doc) + + // perform find and return a document + if (dpiSodaColl__find(coll, options, flags, NULL, doc, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + + return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_getDataGuide() [PUBLIC] +// Return the data guide document for the collection. +//----------------------------------------------------------------------------- +int dpiSodaColl_getDataGuide(dpiSodaColl *coll, uint32_t flags, + dpiSodaDoc **doc) +{ + void *docHandle; + dpiError error; + uint32_t mode; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(coll, doc) + + // determine mode to pass + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + + // get data guide + if (dpiOci__sodaDataGuideGet(coll, &docHandle, mode, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + if (!docHandle) { + *doc = NULL; + } else if (dpiSodaDoc__allocate(coll->db, docHandle, doc, &error) < 0) { + dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + } + + return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_getDocCount() [PUBLIC] +// Return the number of documents in the collection that match the specified +// criteria. +//----------------------------------------------------------------------------- +int dpiSodaColl_getDocCount(dpiSodaColl *coll, + const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count) +{ + dpiError error; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(coll, count) + + // get document count + if (dpiSodaColl__getDocCount(coll, options, flags, count, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + + return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_getMetadata() [PUBLIC] +// Return the metadata for the collection. +//----------------------------------------------------------------------------- +int dpiSodaColl_getMetadata(dpiSodaColl *coll, const char **value, + uint32_t *valueLength) +{ + dpiError error; + int status; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(coll, value) + DPI_CHECK_PTR_NOT_NULL(coll, valueLength) + + // get attribute value + status = dpiOci__attrGet(coll->handle, DPI_OCI_HTYPE_SODA_COLLECTION, + (void*) value, valueLength, DPI_OCI_ATTR_SODA_COLL_DESCRIPTOR, + "get value", &error); + return dpiGen__endPublicFn(coll, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_getName() [PUBLIC] +// Return the name of the collection. +//----------------------------------------------------------------------------- +int dpiSodaColl_getName(dpiSodaColl *coll, const char **value, + uint32_t *valueLength) +{ + dpiError error; + int status; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(coll, value) + DPI_CHECK_PTR_NOT_NULL(coll, valueLength) + + // get attribute value + status = dpiOci__attrGet(coll->handle, DPI_OCI_HTYPE_SODA_COLLECTION, + (void*) value, valueLength, DPI_OCI_ATTR_SODA_COLL_NAME, + "get value", &error); + return dpiGen__endPublicFn(coll, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_insertMany() [PUBLIC] +// Insert multiple documents into the collection and return handles to the +// newly created documents, if desired. +//----------------------------------------------------------------------------- +int dpiSodaColl_insertMany(dpiSodaColl *coll, uint32_t numDocs, + dpiSodaDoc **docs, uint32_t flags, dpiSodaDoc **insertedDocs) +{ + void **docHandles; + dpiError error; + uint32_t i; + int status; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(coll, docs) + if (numDocs == 0) { + dpiError__set(&error, "check num documents", DPI_ERR_ARRAY_SIZE_ZERO); + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + } + for (i = 0; i < numDocs; i++) { + if (dpiGen__checkHandle(docs[i], DPI_HTYPE_SODA_DOC, "check document", + &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + } + + // bulk insert is only supported with Oracle Client 18.5+ + if (dpiUtils__checkClientVersion(coll->env->versionInfo, 18, 5, + &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + + // create and populate array to hold document handles + if (dpiUtils__allocateMemory(numDocs, sizeof(void*), 1, + "allocate document handles", (void**) &docHandles, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + for (i = 0; i < numDocs; i++) + docHandles[i] = docs[i]->handle; + + // perform bulk insert + status = dpiSodaColl__insertMany(coll, numDocs, docHandles, flags, + insertedDocs, &error); + dpiUtils__freeMemory(docHandles); + return dpiGen__endPublicFn(coll, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_insertOne() [PUBLIC] +// Insert a document into the collection and return a handle to the newly +// created document, if desired. +//----------------------------------------------------------------------------- +int dpiSodaColl_insertOne(dpiSodaColl *coll, dpiSodaDoc *doc, uint32_t flags, + dpiSodaDoc **insertedDoc) +{ + void *docHandle; + dpiError error; + uint32_t mode; + int status; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + if (dpiGen__checkHandle(doc, DPI_HTYPE_SODA_DOC, "check document", + &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + + // determine OCI mode to use + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + + // insert document into collection + // use "AndGet" variant if the inserted document is requested + docHandle = doc->handle; + if (!insertedDoc) + status = dpiOci__sodaInsert(coll, docHandle, mode, &error); + else { + status = dpiOci__sodaInsertAndGet(coll, &docHandle, mode, &error); + if (status == 0) { + status = dpiSodaDoc__allocate(coll->db, docHandle, insertedDoc, + &error); + if (status < 0) + dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); + } + } + + return dpiGen__endPublicFn(coll, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_release() [PUBLIC] +// Release a reference to the SODA collection. +//----------------------------------------------------------------------------- +int dpiSodaColl_release(dpiSodaColl *coll) +{ + return dpiGen__release(coll, DPI_HTYPE_SODA_COLL, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_remove() [PUBLIC] +// Remove the documents from the collection that match the given criteria. +//----------------------------------------------------------------------------- +int dpiSodaColl_remove(dpiSodaColl *coll, const dpiSodaOperOptions *options, + uint32_t flags, uint64_t *count) +{ + dpiError error; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(coll, count) + + // perform removal + if (dpiSodaColl__remove(coll, options, flags, count, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + + return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaColl_replaceOne() [PUBLIC] +// Replace the first document in the collection that matches the given +// criteria. Returns a handle to the newly replaced document, if desired. +//----------------------------------------------------------------------------- +int dpiSodaColl_replaceOne(dpiSodaColl *coll, + const dpiSodaOperOptions *options, dpiSodaDoc *doc, uint32_t flags, + int *replaced, dpiSodaDoc **replacedDoc) +{ + dpiError error; + int status; + + // validate parameters + if (dpiSodaColl__check(coll, __func__, &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + if (dpiGen__checkHandle(doc, DPI_HTYPE_SODA_DOC, "check document", + &error) < 0) + return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); + + // perform replace + status = dpiSodaColl__replace(coll, options, doc, flags, replaced, + replacedDoc, &error); + return dpiGen__endPublicFn(coll, status, &error); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSodaCollCursor.c b/vendor/github.com/godror/godror/odpi/src/dpiSodaCollCursor.c new file mode 100644 index 00000000000..f4e91a427cb --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiSodaCollCursor.c @@ -0,0 +1,144 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiSodaCollCursor.c +// Implementation of SODA collection cursors. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiSodaCollCursor__allocate() [INTERNAL] +// Allocate and initialize a SODA collection cursor structure. +//----------------------------------------------------------------------------- +int dpiSodaCollCursor__allocate(dpiSodaDb *db, void *handle, + dpiSodaCollCursor **cursor, dpiError *error) +{ + dpiSodaCollCursor *tempCursor; + + if (dpiGen__allocate(DPI_HTYPE_SODA_COLL_CURSOR, db->env, + (void**) &tempCursor, error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(db, error, 1); + tempCursor->db = db; + tempCursor->handle = handle; + *cursor = tempCursor; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaCollCursor__check() [INTERNAL] +// Determine if the SODA collection cursor is available to use. +//----------------------------------------------------------------------------- +static int dpiSodaCollCursor__check(dpiSodaCollCursor *cursor, + const char *fnName, dpiError *error) +{ + if (dpiGen__startPublicFn(cursor, DPI_HTYPE_SODA_COLL_CURSOR, fnName, + error) < 0) + return DPI_FAILURE; + if (!cursor->handle) + return dpiError__set(error, "check closed", + DPI_ERR_SODA_CURSOR_CLOSED); + if (!cursor->db->conn->handle || cursor->db->conn->closing) + return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaCollCursor__free() [INTERNAL] +// Free the memory for a SODA collection cursor. Note that the reference to +// the database must remain until after the handle is freed; otherwise, a +// segfault can take place. +//----------------------------------------------------------------------------- +void dpiSodaCollCursor__free(dpiSodaCollCursor *cursor, dpiError *error) +{ + if (cursor->handle) { + dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); + cursor->handle = NULL; + } + if (cursor->db) { + dpiGen__setRefCount(cursor->db, error, -1); + cursor->db = NULL; + } + dpiUtils__freeMemory(cursor); +} + + +//----------------------------------------------------------------------------- +// dpiSodaCollCursor_addRef() [PUBLIC] +// Add a reference to the SODA collection cursor. +//----------------------------------------------------------------------------- +int dpiSodaCollCursor_addRef(dpiSodaCollCursor *cursor) +{ + return dpiGen__addRef(cursor, DPI_HTYPE_SODA_COLL_CURSOR, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaCollCursor_close() [PUBLIC] +// Close the cursor. +//----------------------------------------------------------------------------- +int dpiSodaCollCursor_close(dpiSodaCollCursor *cursor) +{ + dpiError error; + + if (dpiSodaCollCursor__check(cursor, __func__, &error) < 0) + return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); + if (cursor->handle) { + dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); + cursor->handle = NULL; + } + return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaCollCursor_getNext() [PUBLIC] +// Return the next collection available from the cursor. +//----------------------------------------------------------------------------- +int dpiSodaCollCursor_getNext(dpiSodaCollCursor *cursor, uint32_t flags, + dpiSodaColl **coll) +{ + dpiError error; + uint32_t mode; + void *handle; + + if (dpiSodaCollCursor__check(cursor, __func__, &error) < 0) + return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(cursor, coll) + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + if (dpiOci__sodaCollGetNext(cursor->db->conn, cursor->handle, &handle, + mode, &error) < 0) + return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); + *coll = NULL; + if (handle) { + if (dpiSodaColl__allocate(cursor->db, handle, coll, &error) < 0) { + dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLLECTION); + return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); + } + } + return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaCollCursor_release() [PUBLIC] +// Release a reference to the SODA collection cursor. +//----------------------------------------------------------------------------- +int dpiSodaCollCursor_release(dpiSodaCollCursor *cursor) +{ + return dpiGen__release(cursor, DPI_HTYPE_SODA_COLL_CURSOR, __func__); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSodaDb.c b/vendor/github.com/godror/godror/odpi/src/dpiSodaDb.c new file mode 100644 index 00000000000..0e1605a3507 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiSodaDb.c @@ -0,0 +1,431 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiSodaDb.c +// Implementation of SODA database methods. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiSodaDb__checkConnected() [INTERNAL] +// Check to see that the connection to the database is available for use. +//----------------------------------------------------------------------------- +static int dpiSodaDb__checkConnected(dpiSodaDb *db, const char *fnName, + dpiError *error) +{ + if (dpiGen__startPublicFn(db, DPI_HTYPE_SODA_DB, fnName, error) < 0) + return DPI_FAILURE; + if (!db->conn->handle || db->conn->closing) + return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaDb__getCollectionNames() [PUBLIC] +// Internal method used for getting all collection names from the database. +// The provided cursor handle is iterated until either the limit is reached +// or there are no more collections to find. +//----------------------------------------------------------------------------- +static int dpiSodaDb__getCollectionNames(dpiSodaDb *db, void *cursorHandle, + uint32_t limit, dpiSodaCollNames *names, char **namesBuffer, + dpiError *error) +{ + uint32_t numAllocatedNames, namesBufferUsed, namesBufferAllocated; + uint32_t i, nameLength, *tempNameLengths; + char *name, *tempNamesBuffer, *ptr; + void *collectionHandle; + + ptr = *namesBuffer; + namesBufferUsed = namesBufferAllocated = numAllocatedNames = 0; + while (names->numNames < limit || limit == 0) { + + // get next collection from cursor + if (dpiOci__sodaCollGetNext(db->conn, cursorHandle, &collectionHandle, + DPI_OCI_DEFAULT, error) < 0) + return DPI_FAILURE; + if (!collectionHandle) + break; + + // get name from collection + if (dpiOci__attrGet(collectionHandle, DPI_OCI_HTYPE_SODA_COLLECTION, + (void*) &name, &nameLength, DPI_OCI_ATTR_SODA_COLL_NAME, + "get collection name", error) < 0) { + dpiOci__handleFree(collectionHandle, + DPI_OCI_HTYPE_SODA_COLLECTION); + return DPI_FAILURE; + } + + // allocate additional space for the lengths array, if needed + if (numAllocatedNames <= names->numNames) { + numAllocatedNames += 256; + if (dpiUtils__allocateMemory(numAllocatedNames, sizeof(uint32_t), + 0, "allocate lengths array", (void**) &tempNameLengths, + error) < 0) { + dpiOci__handleFree(collectionHandle, + DPI_OCI_HTYPE_SODA_COLLECTION); + return DPI_FAILURE; + } + if (names->nameLengths) { + memcpy(tempNameLengths, names->nameLengths, + names->numNames * sizeof(uint32_t)); + dpiUtils__freeMemory(names->nameLengths); + } + names->nameLengths = tempNameLengths; + } + + // allocate additional space for the names buffer, if needed + if (namesBufferUsed + nameLength > namesBufferAllocated) { + namesBufferAllocated += 32768; + if (dpiUtils__allocateMemory(namesBufferAllocated, 1, 0, + "allocate names buffer", (void**) &tempNamesBuffer, + error) < 0) { + dpiOci__handleFree(collectionHandle, + DPI_OCI_HTYPE_SODA_COLLECTION); + return DPI_FAILURE; + } + if (*namesBuffer) { + memcpy(tempNamesBuffer, *namesBuffer, namesBufferUsed); + dpiUtils__freeMemory(*namesBuffer); + } + *namesBuffer = tempNamesBuffer; + ptr = *namesBuffer + namesBufferUsed; + } + + // store name in buffer and length in array + // the names array itself is created and populated afterwards in order + // to avoid unnecessary copying + memcpy(ptr, name, nameLength); + namesBufferUsed += nameLength; + names->nameLengths[names->numNames] = nameLength; + names->numNames++; + ptr += nameLength; + + // free collection now that we have processed it successfully + dpiOci__handleFree(collectionHandle, DPI_OCI_HTYPE_SODA_COLLECTION); + + } + + // now that all of the names have been determined, populate names array + if (names->numNames > 0) { + if (dpiUtils__allocateMemory(names->numNames, sizeof(char*), 0, + "allocate names array", (void**) &names->names, error) < 0) + return DPI_FAILURE; + ptr = *namesBuffer; + for (i = 0; i < names->numNames; i++) { + names->names[i] = ptr; + ptr += names->nameLengths[i]; + } + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaDb__free() [INTERNAL] +// Free the memory for a SODA database. +//----------------------------------------------------------------------------- +void dpiSodaDb__free(dpiSodaDb *db, dpiError *error) +{ + if (db->conn) { + dpiGen__setRefCount(db->conn, error, -1); + db->conn = NULL; + } + dpiUtils__freeMemory(db); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDb_addRef() [PUBLIC] +// Add a reference to the SODA database. +//----------------------------------------------------------------------------- +int dpiSodaDb_addRef(dpiSodaDb *db) +{ + return dpiGen__addRef(db, DPI_HTYPE_SODA_DB, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDb_createCollection() [PUBLIC] +// Create a new SODA collection with the given name and metadata. +//----------------------------------------------------------------------------- +int dpiSodaDb_createCollection(dpiSodaDb *db, const char *name, + uint32_t nameLength, const char *metadata, uint32_t metadataLength, + uint32_t flags, dpiSodaColl **coll) +{ + dpiError error; + uint32_t mode; + void *handle; + + // validate parameters + if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(db, name) + DPI_CHECK_PTR_AND_LENGTH(db, metadata) + DPI_CHECK_PTR_NOT_NULL(db, coll) + + // determine OCI mode to use + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + if (flags & DPI_SODA_FLAGS_CREATE_COLL_MAP) + mode |= DPI_OCI_SODA_COLL_CREATE_MAP; + + // create collection + if (dpiOci__sodaCollCreateWithMetadata(db, name, nameLength, metadata, + metadataLength, mode, &handle, &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + if (dpiSodaColl__allocate(db, handle, coll, &error) < 0) { + dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLLECTION); + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + } + return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDb_createDocument() [PUBLIC] +// Create a SODA document that can be inserted in the collection or can be +// used to replace and existing document in the collection. +//----------------------------------------------------------------------------- +int dpiSodaDb_createDocument(dpiSodaDb *db, const char *key, + uint32_t keyLength, const char *content, uint32_t contentLength, + const char *mediaType, uint32_t mediaTypeLength, UNUSED uint32_t flags, + dpiSodaDoc **doc) +{ + int detectEncoding; + void *docHandle; + dpiError error; + + // validate parameters + if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(db, key) + DPI_CHECK_PTR_AND_LENGTH(db, content) + DPI_CHECK_PTR_AND_LENGTH(db, mediaType) + DPI_CHECK_PTR_NOT_NULL(db, doc) + + // allocate SODA document handle + if (dpiOci__handleAlloc(db->env->handle, &docHandle, + DPI_OCI_HTYPE_SODA_DOCUMENT, "allocate SODA document handle", + &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + + // set key, if applicable + if (key && keyLength > 0) { + if (dpiOci__attrSet(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT, + (void*) key, keyLength, DPI_OCI_ATTR_SODA_KEY, "set key", + &error) < 0) { + dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + } + } + + // set content, if applicable + if (content && contentLength > 0) { + detectEncoding = 1; + if (dpiOci__attrSet(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT, + (void*) &detectEncoding, 0, DPI_OCI_ATTR_SODA_DETECT_JSON_ENC, + "set detect encoding", &error) < 0) { + dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + } + if (dpiOci__attrSet(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT, + (void*) content, contentLength, DPI_OCI_ATTR_SODA_CONTENT, + "set content", &error) < 0) { + dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + } + } + + // set media type, if applicable + if (mediaType && mediaTypeLength > 0) { + if (dpiOci__attrSet(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT, + (void*) mediaType, mediaTypeLength, + DPI_OCI_ATTR_SODA_MEDIA_TYPE, "set media type", &error) < 0) { + dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + } + } + + // allocate the ODPI-C document that will be returned + if (dpiSodaDoc__allocate(db, docHandle, doc, &error) < 0) { + dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + } + (*doc)->binaryContent = 1; + + return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDb_freeCollectionNames() [PUBLIC] +// Free the names of the collections allocated earlier with a call to +// dpiSodaDb_getCollectionNames(). +//----------------------------------------------------------------------------- +int dpiSodaDb_freeCollectionNames(dpiSodaDb *db, dpiSodaCollNames *names) +{ + dpiError error; + + // validate parameters + if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(db, names) + + // perform frees; note that the memory for the names themselves is stored + // in one contiguous block pointed to by the first name + if (names->names) { + dpiUtils__freeMemory((void*) names->names[0]); + dpiUtils__freeMemory((void*) names->names); + names->names = NULL; + } + if (names->nameLengths) { + dpiUtils__freeMemory(names->nameLengths); + names->nameLengths = NULL; + } + names->numNames = 0; + + return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDb_getCollections() [PUBLIC] +// Return a cursor to iterate over the SODA collections in the database. +//----------------------------------------------------------------------------- +int dpiSodaDb_getCollections(dpiSodaDb *db, const char *startName, + uint32_t startNameLength, uint32_t flags, dpiSodaCollCursor **cursor) +{ + dpiError error; + uint32_t mode; + void *handle; + + if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(db, startName) + DPI_CHECK_PTR_NOT_NULL(db, cursor) + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + if (dpiOci__sodaCollList(db, startName, startNameLength, &handle, mode, + &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + if (dpiSodaCollCursor__allocate(db, handle, cursor, &error) < 0) { + dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + } + return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDb_getCollectionNames() [PUBLIC] +// Return the names of all collections in the provided array. +//----------------------------------------------------------------------------- +int dpiSodaDb_getCollectionNames(dpiSodaDb *db, const char *startName, + uint32_t startNameLength, uint32_t limit, uint32_t flags, + dpiSodaCollNames *names) +{ + char *namesBuffer; + dpiError error; + uint32_t mode; + void *handle; + int status; + + // validate parameters + if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(db, startName) + DPI_CHECK_PTR_NOT_NULL(db, names) + + // initialize output structure + names->numNames = 0; + names->names = NULL; + names->nameLengths = NULL; + + // determine OCI mode to use + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + + // acquire collection cursor + if (dpiOci__sodaCollList(db, startName, startNameLength, &handle, mode, + &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + + // iterate over cursor to acquire collection names + namesBuffer = NULL; + status = dpiSodaDb__getCollectionNames(db, handle, limit, names, + &namesBuffer, &error); + dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); + if (status < 0) { + names->numNames = 0; + if (namesBuffer) { + dpiUtils__freeMemory(namesBuffer); + namesBuffer = NULL; + } + if (names->names) { + dpiUtils__freeMemory((void*) names->names); + names->names = NULL; + } + if (names->nameLengths) { + dpiUtils__freeMemory(names->nameLengths); + names->nameLengths = NULL; + } + } + return dpiGen__endPublicFn(db, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDb_openCollection() [PUBLIC] +// Open an existing SODA collection and return a handle to it. +//----------------------------------------------------------------------------- +int dpiSodaDb_openCollection(dpiSodaDb *db, const char *name, + uint32_t nameLength, uint32_t flags, dpiSodaColl **coll) +{ + dpiError error; + uint32_t mode; + void *handle; + + if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(db, name) + DPI_CHECK_PTR_NOT_NULL(db, coll) + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + if (dpiOci__sodaCollOpen(db, name, nameLength, mode, &handle, + &error) < 0) + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + *coll = NULL; + if (handle) { + if (dpiSodaColl__allocate(db, handle, coll, &error) < 0) { + dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLLECTION); + return dpiGen__endPublicFn(db, DPI_FAILURE, &error); + } + } + return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDb_release() [PUBLIC] +// Release a reference to the SODA database. +//----------------------------------------------------------------------------- +int dpiSodaDb_release(dpiSodaDb *db) +{ + return dpiGen__release(db, DPI_HTYPE_SODA_DB, __func__); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSodaDoc.c b/vendor/github.com/godror/godror/odpi/src/dpiSodaDoc.c new file mode 100644 index 00000000000..b009e33a44a --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiSodaDoc.c @@ -0,0 +1,231 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiSodaDoc.c +// Implementation of SODA documents. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiSodaDoc__allocate() [INTERNAL] +// Allocate and initialize a SODA document structure. +//----------------------------------------------------------------------------- +int dpiSodaDoc__allocate(dpiSodaDb *db, void *handle, dpiSodaDoc **doc, + dpiError *error) +{ + dpiSodaDoc *tempDoc; + + if (dpiGen__allocate(DPI_HTYPE_SODA_DOC, db->env, (void**) &tempDoc, + error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(db, error, 1); + tempDoc->db = db; + tempDoc->handle = handle; + *doc = tempDoc; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc__check() [INTERNAL] +// Determine if the SODA document is available to use. +//----------------------------------------------------------------------------- +static int dpiSodaDoc__check(dpiSodaDoc *doc, const char *fnName, + dpiError *error) +{ + if (dpiGen__startPublicFn(doc, DPI_HTYPE_SODA_DOC, fnName, error) < 0) + return DPI_FAILURE; + if (!doc->db->conn->handle || doc->db->conn->closing) + return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc__free() [INTERNAL] +// Free the memory for a SODA document. Note that the reference to the +// database must remain until after the handle is freed; otherwise, a segfault +// can take place. +//----------------------------------------------------------------------------- +void dpiSodaDoc__free(dpiSodaDoc *doc, dpiError *error) +{ + if (doc->handle) { + dpiOci__handleFree(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT); + doc->handle = NULL; + } + if (doc->db) { + dpiGen__setRefCount(doc->db, error, -1); + doc->db = NULL; + } + dpiUtils__freeMemory(doc); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc__getAttributeText() [INTERNAL] +// Get the value of the OCI attribute as a text string. +//----------------------------------------------------------------------------- +static int dpiSodaDoc__getAttributeText(dpiSodaDoc *doc, uint32_t attribute, + const char **value, uint32_t *valueLength, const char *fnName) +{ + dpiError error; + int status; + + // validate parameters + if (dpiSodaDoc__check(doc, fnName, &error) < 0) + return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(doc, value) + DPI_CHECK_PTR_NOT_NULL(doc, valueLength) + + // get attribute value + status = dpiOci__attrGet(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, + (void*) value, valueLength, attribute, "get value", &error); + return dpiGen__endPublicFn(doc, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc_addRef() [PUBLIC] +// Add a reference to the SODA document. +//----------------------------------------------------------------------------- +int dpiSodaDoc_addRef(dpiSodaDoc *doc) +{ + return dpiGen__addRef(doc, DPI_HTYPE_SODA_DOC, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc_getContent() [PUBLIC] +// Return the content of the SODA document. +//----------------------------------------------------------------------------- +int dpiSodaDoc_getContent(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength, const char **encoding) +{ + uint16_t charsetId; + dpiError error; + + // validate parameters + if (dpiSodaDoc__check(doc, __func__, &error) < 0) + return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(doc, value) + DPI_CHECK_PTR_NOT_NULL(doc, valueLength) + DPI_CHECK_PTR_NOT_NULL(doc, encoding) + + // get content + if (dpiOci__attrGet(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, + (void*) value, valueLength, DPI_OCI_ATTR_SODA_CONTENT, + "get content", &error) < 0) + return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); + + // if content is not in binary form, always use UTF-8 + if (!doc->binaryContent) + *encoding = DPI_CHARSET_NAME_UTF8; + + // otherwise, determine the encoding from OCI + else { + if (dpiOci__attrGet(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, + (void*) &charsetId, 0, DPI_OCI_ATTR_SODA_JSON_CHARSET_ID, + "get charset", &error) < 0) + return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); + switch (charsetId) { + case 0: + *encoding = NULL; + break; + case DPI_CHARSET_ID_UTF8: + *encoding = DPI_CHARSET_NAME_UTF8; + break; + case DPI_CHARSET_ID_UTF16BE: + *encoding = DPI_CHARSET_NAME_UTF16BE; + break; + case DPI_CHARSET_ID_UTF16LE: + *encoding = DPI_CHARSET_NAME_UTF16LE; + break; + default: + dpiError__set(&error, "check charset", + DPI_ERR_INVALID_CHARSET_ID, charsetId); + return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); + } + } + + return dpiGen__endPublicFn(doc, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc_getCreatedOn() [PUBLIC] +// Return the created timestamp of the SODA document. +//----------------------------------------------------------------------------- +int dpiSodaDoc_getCreatedOn(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength) +{ + return dpiSodaDoc__getAttributeText(doc, + DPI_OCI_ATTR_SODA_CREATE_TIMESTAMP, value, valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc_getKey() [PUBLIC] +// Return the key of the SODA document. +//----------------------------------------------------------------------------- +int dpiSodaDoc_getKey(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength) +{ + return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_KEY, value, + valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc_getLastModified() [PUBLIC] +// Return the last modified timestamp of the SODA document. +//----------------------------------------------------------------------------- +int dpiSodaDoc_getLastModified(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength) +{ + return dpiSodaDoc__getAttributeText(doc, + DPI_OCI_ATTR_SODA_LASTMOD_TIMESTAMP, value, valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc_getMediaType() [PUBLIC] +// Return the media type of the SODA document. +//----------------------------------------------------------------------------- +int dpiSodaDoc_getMediaType(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength) +{ + return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_MEDIA_TYPE, + value, valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc_getVersion() [PUBLIC] +// Return the version of the SODA document. +//----------------------------------------------------------------------------- +int dpiSodaDoc_getVersion(dpiSodaDoc *doc, const char **value, + uint32_t *valueLength) +{ + return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_VERSION, + value, valueLength, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDoc_release() [PUBLIC] +// Release a reference to the SODA document. +//----------------------------------------------------------------------------- +int dpiSodaDoc_release(dpiSodaDoc *doc) +{ + return dpiGen__release(doc, DPI_HTYPE_SODA_DOC, __func__); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSodaDocCursor.c b/vendor/github.com/godror/godror/odpi/src/dpiSodaDocCursor.c new file mode 100644 index 00000000000..9bfd2bdbeea --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiSodaDocCursor.c @@ -0,0 +1,144 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiSodaDocCursor.c +// Implementation of SODA document cursors. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiSodaDocCursor__allocate() [INTERNAL] +// Allocate and initialize a SODA document cursor structure. +//----------------------------------------------------------------------------- +int dpiSodaDocCursor__allocate(dpiSodaColl *coll, void *handle, + dpiSodaDocCursor **cursor, dpiError *error) +{ + dpiSodaDocCursor *tempCursor; + + if (dpiGen__allocate(DPI_HTYPE_SODA_DOC_CURSOR, coll->env, + (void**) &tempCursor, error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(coll, error, 1); + tempCursor->coll = coll; + tempCursor->handle = handle; + *cursor = tempCursor; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaDocCursor__check() [INTERNAL] +// Determine if the SODA document cursor is available to use. +//----------------------------------------------------------------------------- +static int dpiSodaDocCursor__check(dpiSodaDocCursor *cursor, + const char *fnName, dpiError *error) +{ + if (dpiGen__startPublicFn(cursor, DPI_HTYPE_SODA_DOC_CURSOR, fnName, + error) < 0) + return DPI_FAILURE; + if (!cursor->handle) + return dpiError__set(error, "check closed", + DPI_ERR_SODA_CURSOR_CLOSED); + if (!cursor->coll->db->conn->handle || cursor->coll->db->conn->closing) + return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSodaDocCursor__free() [INTERNAL] +// Free the memory for a SODA document cursor. Note that the reference to the +// collection must remain until after the handle is freed; otherwise, a +// segfault can take place. +//----------------------------------------------------------------------------- +void dpiSodaDocCursor__free(dpiSodaDocCursor *cursor, dpiError *error) +{ + if (cursor->handle) { + dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_DOC_CURSOR); + cursor->handle = NULL; + } + if (cursor->coll) { + dpiGen__setRefCount(cursor->coll, error, -1); + cursor->coll = NULL; + } + dpiUtils__freeMemory(cursor); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDocCursor_addRef() [PUBLIC] +// Add a reference to the SODA document cursor. +//----------------------------------------------------------------------------- +int dpiSodaDocCursor_addRef(dpiSodaDocCursor *cursor) +{ + return dpiGen__addRef(cursor, DPI_HTYPE_SODA_DOC_CURSOR, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDocCursor_close() [PUBLIC] +// Close the cursor. +//----------------------------------------------------------------------------- +int dpiSodaDocCursor_close(dpiSodaDocCursor *cursor) +{ + dpiError error; + + if (dpiSodaDocCursor__check(cursor, __func__, &error) < 0) + return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); + if (cursor->handle) { + dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_DOC_CURSOR); + cursor->handle = NULL; + } + return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDocCursor_getNext() [PUBLIC] +// Return the next document available from the cursor. +//----------------------------------------------------------------------------- +int dpiSodaDocCursor_getNext(dpiSodaDocCursor *cursor, uint32_t flags, + dpiSodaDoc **doc) +{ + dpiError error; + uint32_t mode; + void *handle; + + if (dpiSodaDocCursor__check(cursor, __func__, &error) < 0) + return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(cursor, doc) + mode = DPI_OCI_DEFAULT; + if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) + mode |= DPI_OCI_SODA_ATOMIC_COMMIT; + if (dpiOci__sodaDocGetNext(cursor, &handle, mode, &error) < 0) + return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); + *doc = NULL; + if (handle) { + if (dpiSodaDoc__allocate(cursor->coll->db, handle, doc, &error) < 0) { + dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_DOCUMENT); + return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); + } + (*doc)->binaryContent = cursor->coll->binaryContent; + } + return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSodaDocCursor_release() [PUBLIC] +// Release a reference to the SODA document cursor. +//----------------------------------------------------------------------------- +int dpiSodaDocCursor_release(dpiSodaDocCursor *cursor) +{ + return dpiGen__release(cursor, DPI_HTYPE_SODA_DOC_CURSOR, __func__); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiStmt.c b/vendor/github.com/godror/godror/odpi/src/dpiStmt.c new file mode 100644 index 00000000000..cd3520b93b0 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiStmt.c @@ -0,0 +1,1898 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiStmt.c +// Implementation of statements (cursors). +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +// forward declarations of internal functions only used in this file +static int dpiStmt__getQueryInfo(dpiStmt *stmt, uint32_t pos, + dpiQueryInfo *info, dpiError *error); +static int dpiStmt__getQueryInfoFromParam(dpiStmt *stmt, void *param, + dpiQueryInfo *info, dpiError *error); +static int dpiStmt__postFetch(dpiStmt *stmt, dpiError *error); +static int dpiStmt__beforeFetch(dpiStmt *stmt, dpiError *error); +static int dpiStmt__reExecute(dpiStmt *stmt, uint32_t numIters, + uint32_t mode, dpiError *error); + + +//----------------------------------------------------------------------------- +// dpiStmt__allocate() [INTERNAL] +// Create a new statement object and return it. In case of error NULL is +// returned. +//----------------------------------------------------------------------------- +int dpiStmt__allocate(dpiConn *conn, int scrollable, dpiStmt **stmt, + dpiError *error) +{ + dpiStmt *tempStmt; + + *stmt = NULL; + if (dpiGen__allocate(DPI_HTYPE_STMT, conn->env, (void**) &tempStmt, + error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(conn, error, 1); + tempStmt->conn = conn; + tempStmt->fetchArraySize = DPI_DEFAULT_FETCH_ARRAY_SIZE; + tempStmt->scrollable = scrollable; + *stmt = tempStmt; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__bind() [INTERNAL] +// Bind the variable to the statement using either a position or a name. A +// reference to the variable will be retained. +//----------------------------------------------------------------------------- +static int dpiStmt__bind(dpiStmt *stmt, dpiVar *var, int addReference, + uint32_t pos, const char *name, uint32_t nameLength, dpiError *error) +{ + dpiBindVar *bindVars, *entry = NULL; + int found, dynamicBind, status; + void *bindHandle = NULL; + uint32_t i; + + // a zero length name is not supported + if (pos == 0 && nameLength == 0) + return dpiError__set(error, "bind zero length name", + DPI_ERR_NOT_SUPPORTED); + + // prevent attempts to bind a statement to itself + if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_STMT) { + for (i = 0; i < var->buffer.maxArraySize; i++) { + if (var->buffer.externalData[i].value.asStmt == stmt) { + return dpiError__set(error, "bind to self", + DPI_ERR_NOT_SUPPORTED); + } + } + } + + // check to see if the bind position or name has already been bound + found = 0; + for (i = 0; i < stmt->numBindVars; i++) { + entry = &stmt->bindVars[i]; + if (entry->pos == pos && entry->nameLength == nameLength) { + if (nameLength > 0 && strncmp(entry->name, name, nameLength) != 0) + continue; + found = 1; + break; + } + } + + // if already found, use that entry + if (found) { + + // if already bound, no need to bind a second time + if (entry->var == var) + return DPI_SUCCESS; + + // otherwise, release previously bound variable, if applicable + else if (entry->var) { + dpiGen__setRefCount(entry->var, error, -1); + entry->var = NULL; + } + + // if not found, add to the list of bind variables + } else { + + // allocate memory for additional bind variables, if needed + if (stmt->numBindVars == stmt->allocatedBindVars) { + if (dpiUtils__allocateMemory(stmt->allocatedBindVars + 8, + sizeof(dpiBindVar), 1, "allocate bind vars", + (void**) &bindVars, error) < 0) + return DPI_FAILURE; + if (stmt->bindVars) { + for (i = 0; i < stmt->numBindVars; i++) + bindVars[i] = stmt->bindVars[i]; + dpiUtils__freeMemory(stmt->bindVars); + } + stmt->bindVars = bindVars; + stmt->allocatedBindVars += 8; + } + + // add to the list of bind variables + entry = &stmt->bindVars[stmt->numBindVars]; + entry->var = NULL; + entry->pos = pos; + if (name) { + if (dpiUtils__allocateMemory(1, nameLength, 0, + "allocate memory for name", (void**) &entry->name, + error) < 0) + return DPI_FAILURE; + entry->nameLength = nameLength; + memcpy( (void*) entry->name, name, nameLength); + } + stmt->numBindVars++; + + } + + // for PL/SQL where the maxSize is greater than 32K, adjust the variable + // so that LOBs are used internally + if (var->isDynamic && (stmt->statementType == DPI_STMT_TYPE_BEGIN || + stmt->statementType == DPI_STMT_TYPE_DECLARE || + stmt->statementType == DPI_STMT_TYPE_CALL)) { + if (dpiVar__convertToLob(var, error) < 0) + return DPI_FAILURE; + } + + // perform actual bind + if (addReference) + dpiGen__setRefCount(var, error, 1); + entry->var = var; + dynamicBind = stmt->isReturning || var->isDynamic; + if (pos > 0) { + if (stmt->env->versionInfo->versionNum < 12) + status = dpiOci__bindByPos(stmt, &bindHandle, pos, dynamicBind, + var, error); + else status = dpiOci__bindByPos2(stmt, &bindHandle, pos, dynamicBind, + var, error); + } else { + if (stmt->env->versionInfo->versionNum < 12) + status = dpiOci__bindByName(stmt, &bindHandle, name, + (int32_t) nameLength, dynamicBind, var, error); + else status = dpiOci__bindByName2(stmt, &bindHandle, name, + (int32_t) nameLength, dynamicBind, var, error); + } + + // attempt to improve message "ORA-01036: illegal variable name/number" + if (status < 0) { + if (error->buffer->code == 1036) { + if (stmt->statementType == DPI_STMT_TYPE_CREATE || + stmt->statementType == DPI_STMT_TYPE_DROP || + stmt->statementType == DPI_STMT_TYPE_ALTER) + dpiError__set(error, error->buffer->action, + DPI_ERR_NO_BIND_VARS_IN_DDL); + } + return DPI_FAILURE; + } + + // set the charset form if applicable + if (var->type->charsetForm != DPI_SQLCS_IMPLICIT) { + if (dpiOci__attrSet(bindHandle, DPI_OCI_HTYPE_BIND, + (void*) &var->type->charsetForm, 0, DPI_OCI_ATTR_CHARSET_FORM, + "set charset form", error) < 0) + return DPI_FAILURE; + } + + // set the max data size, if applicable + if (var->type->sizeInBytes == 0 && !var->isDynamic) { + if (dpiOci__attrSet(bindHandle, DPI_OCI_HTYPE_BIND, + (void*) &var->sizeInBytes, 0, DPI_OCI_ATTR_MAXDATA_SIZE, + "set max data size", error) < 0) + return DPI_FAILURE; + } + + // bind object, if applicable + if (var->buffer.objectIndicator && + dpiOci__bindObject(var, bindHandle, error) < 0) + return DPI_FAILURE; + + // setup dynamic bind, if applicable + if (dynamicBind && dpiOci__bindDynamic(var, bindHandle, error) < 0) + return DPI_FAILURE; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__check() [INTERNAL] +// Determine if the statement is open and available for use. +//----------------------------------------------------------------------------- +static int dpiStmt__check(dpiStmt *stmt, const char *fnName, dpiError *error) +{ + if (dpiGen__startPublicFn(stmt, DPI_HTYPE_STMT, fnName, error) < 0) + return DPI_FAILURE; + if (!stmt->handle || (stmt->parentStmt && !stmt->parentStmt->handle)) + return dpiError__set(error, "check closed", DPI_ERR_STMT_CLOSED); + if (dpiConn__checkConnected(stmt->conn, error) < 0) + return DPI_FAILURE; + if (stmt->statementType == 0 && dpiStmt__init(stmt, error) < 0) + return DPI_FAILURE; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__clearBatchErrors() [INTERNAL] +// Clear the batch errors associated with the statement. +//----------------------------------------------------------------------------- +static void dpiStmt__clearBatchErrors(dpiStmt *stmt) +{ + if (stmt->batchErrors) { + dpiUtils__freeMemory(stmt->batchErrors); + stmt->batchErrors = NULL; + } + stmt->numBatchErrors = 0; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__clearBindVars() [INTERNAL] +// Clear the bind variables associated with the statement. +//----------------------------------------------------------------------------- +static void dpiStmt__clearBindVars(dpiStmt *stmt, dpiError *error) +{ + uint32_t i; + + if (stmt->bindVars) { + for (i = 0; i < stmt->numBindVars; i++) { + dpiGen__setRefCount(stmt->bindVars[i].var, error, -1); + if (stmt->bindVars[i].name) + dpiUtils__freeMemory( (void*) stmt->bindVars[i].name); + } + dpiUtils__freeMemory(stmt->bindVars); + stmt->bindVars = NULL; + } + stmt->numBindVars = 0; + stmt->allocatedBindVars = 0; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__clearQueryVars() [INTERNAL] +// Clear the query variables associated with the statement. +//----------------------------------------------------------------------------- +static void dpiStmt__clearQueryVars(dpiStmt *stmt, dpiError *error) +{ + uint32_t i; + + if (stmt->queryVars) { + for (i = 0; i < stmt->numQueryVars; i++) { + if (stmt->queryVars[i]) { + dpiGen__setRefCount(stmt->queryVars[i], error, -1); + stmt->queryVars[i] = NULL; + } + if (stmt->queryInfo[i].typeInfo.objectType) { + dpiGen__setRefCount(stmt->queryInfo[i].typeInfo.objectType, + error, -1); + stmt->queryInfo[i].typeInfo.objectType = NULL; + } + } + dpiUtils__freeMemory(stmt->queryVars); + stmt->queryVars = NULL; + } + if (stmt->queryInfo) { + dpiUtils__freeMemory(stmt->queryInfo); + stmt->queryInfo = NULL; + } + stmt->numQueryVars = 0; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__close() [INTERNAL] +// Internal method used for closing the statement. If the statement is marked +// as needing to be dropped from the statement cache that is done as well. This +// is called from dpiStmt_close() where errors are expected to be propagated +// and from dpiStmt__free() where errors are ignored. +//----------------------------------------------------------------------------- +int dpiStmt__close(dpiStmt *stmt, const char *tag, uint32_t tagLength, + int propagateErrors, dpiError *error) +{ + int closing, status = DPI_SUCCESS; + + // determine whether statement is already being closed and if not, mark + // statement as being closed; this MUST be done while holding the lock (if + // in threaded mode) to avoid race conditions! + if (stmt->env->threaded) + dpiMutex__acquire(stmt->env->mutex); + closing = stmt->closing; + stmt->closing = 1; + if (stmt->env->threaded) + dpiMutex__release(stmt->env->mutex); + + // if statement is already being closed, nothing needs to be done + if (closing) + return DPI_SUCCESS; + + // perform actual work of closing statement + dpiStmt__clearBatchErrors(stmt); + dpiStmt__clearBindVars(stmt, error); + dpiStmt__clearQueryVars(stmt, error); + if (stmt->lastRowid) + dpiGen__setRefCount(stmt->lastRowid, error, -1); + if (stmt->handle) { + if (stmt->parentStmt) { + dpiGen__setRefCount(stmt->parentStmt, error, -1); + stmt->parentStmt = NULL; + } else if (!stmt->conn->deadSession && stmt->conn->handle) { + if (stmt->isOwned) + dpiOci__handleFree(stmt->handle, DPI_OCI_HTYPE_STMT); + else status = dpiOci__stmtRelease(stmt, tag, tagLength, + propagateErrors, error); + } + if (!stmt->conn->closing && !stmt->parentStmt) + dpiHandleList__removeHandle(stmt->conn->openStmts, + stmt->openSlotNum); + stmt->handle = NULL; + } + + // if actual close fails, reset closing flag; again, this must be done + // while holding the lock (if in threaded mode) in order to avoid race + // conditions! + if (status < 0) { + if (stmt->env->threaded) + dpiMutex__acquire(stmt->env->mutex); + stmt->closing = 0; + if (stmt->env->threaded) + dpiMutex__release(stmt->env->mutex); + } + + return status; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__createBindVar() [INTERNAL] +// Create a bind variable given a value to bind. +//----------------------------------------------------------------------------- +static int dpiStmt__createBindVar(dpiStmt *stmt, + dpiNativeTypeNum nativeTypeNum, dpiData *data, dpiVar **var, + uint32_t pos, const char *name, uint32_t nameLength, dpiError *error) +{ + dpiOracleTypeNum oracleTypeNum; + dpiObjectType *objType; + dpiData *varData; + dpiVar *tempVar; + uint32_t size; + + // determine the type (and size) of bind variable to create + size = 0; + objType = NULL; + switch (nativeTypeNum) { + case DPI_NATIVE_TYPE_INT64: + case DPI_NATIVE_TYPE_UINT64: + case DPI_NATIVE_TYPE_FLOAT: + case DPI_NATIVE_TYPE_DOUBLE: + oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; + break; + case DPI_NATIVE_TYPE_BYTES: + oracleTypeNum = DPI_ORACLE_TYPE_VARCHAR; + size = data->value.asBytes.length; + break; + case DPI_NATIVE_TYPE_TIMESTAMP: + oracleTypeNum = DPI_ORACLE_TYPE_TIMESTAMP; + break; + case DPI_NATIVE_TYPE_INTERVAL_DS: + oracleTypeNum = DPI_ORACLE_TYPE_INTERVAL_DS; + break; + case DPI_NATIVE_TYPE_INTERVAL_YM: + oracleTypeNum = DPI_ORACLE_TYPE_INTERVAL_YM; + break; + case DPI_NATIVE_TYPE_OBJECT: + oracleTypeNum = DPI_ORACLE_TYPE_OBJECT; + if (data->value.asObject) + objType = data->value.asObject->type; + break; + case DPI_NATIVE_TYPE_ROWID: + oracleTypeNum = DPI_ORACLE_TYPE_ROWID; + break; + case DPI_NATIVE_TYPE_BOOLEAN: + oracleTypeNum = DPI_ORACLE_TYPE_BOOLEAN; + break; + default: + return dpiError__set(error, "create bind var", + DPI_ERR_UNHANDLED_CONVERSION, 0, nativeTypeNum); + } + + // create the variable and set its value + if (dpiVar__allocate(stmt->conn, oracleTypeNum, nativeTypeNum, 1, size, 1, + 0, objType, &tempVar, &varData, error) < 0) + return DPI_FAILURE; + + // copy value from source to target data + if (dpiVar__copyData(tempVar, 0, data, error) < 0) + return DPI_FAILURE; + + // bind variable to statement + if (dpiStmt__bind(stmt, tempVar, 0, pos, name, nameLength, error) < 0) { + dpiVar__free(tempVar, error); + return DPI_FAILURE; + } + + *var = tempVar; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__createQueryVars() [INTERNAL] +// Create space for the number of query variables required to support the +// query. +//----------------------------------------------------------------------------- +static int dpiStmt__createQueryVars(dpiStmt *stmt, dpiError *error) +{ + uint32_t numQueryVars, i; + + // determine number of query variables + if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, + (void*) &numQueryVars, 0, DPI_OCI_ATTR_PARAM_COUNT, + "get parameter count", error) < 0) + return DPI_FAILURE; + + // clear the previous query vars if the number has changed + if (stmt->numQueryVars > 0 && stmt->numQueryVars != numQueryVars) + dpiStmt__clearQueryVars(stmt, error); + + // allocate space for the query vars, if needed + if (numQueryVars != stmt->numQueryVars) { + if (dpiUtils__allocateMemory(numQueryVars, sizeof(dpiVar*), 1, + "allocate query vars", (void**) &stmt->queryVars, error) < 0) + return DPI_FAILURE; + if (dpiUtils__allocateMemory(numQueryVars, sizeof(dpiQueryInfo), 1, + "allocate query info", (void**) &stmt->queryInfo, error) < 0) { + dpiStmt__clearQueryVars(stmt, error); + return DPI_FAILURE; + } + stmt->numQueryVars = numQueryVars; + for (i = 0; i < numQueryVars; i++) { + if (dpiStmt__getQueryInfo(stmt, i + 1, &stmt->queryInfo[i], + error) < 0) { + dpiStmt__clearQueryVars(stmt, error); + return DPI_FAILURE; + } + } + } + + // indicate start of fetch + stmt->bufferRowIndex = stmt->fetchArraySize; + stmt->hasRowsToFetch = 1; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__define() [INTERNAL] +// Define the variable that will accept output from the statement in the +// specified column. At this point the statement, position and variable are all +// assumed to be valid. +//----------------------------------------------------------------------------- +static int dpiStmt__define(dpiStmt *stmt, uint32_t pos, dpiVar *var, + dpiError *error) +{ + void *defineHandle = NULL; + dpiQueryInfo *queryInfo; + int tempBool; + + // no need to perform define if variable is unchanged + if (stmt->queryVars[pos - 1] == var) + return DPI_SUCCESS; + + // for objects, the type specified must match the type in the database + queryInfo = &stmt->queryInfo[pos - 1]; + if (var->objectType && queryInfo->typeInfo.objectType && + var->objectType->tdo != queryInfo->typeInfo.objectType->tdo) + return dpiError__set(error, "check type", DPI_ERR_WRONG_TYPE, + var->objectType->schemaLength, var->objectType->schema, + var->objectType->nameLength, var->objectType->name, + queryInfo->typeInfo.objectType->schemaLength, + queryInfo->typeInfo.objectType->schema, + queryInfo->typeInfo.objectType->nameLength, + queryInfo->typeInfo.objectType->name); + + // perform the define + if (stmt->env->versionInfo->versionNum < 12) { + if (dpiOci__defineByPos(stmt, &defineHandle, pos, var, error) < 0) + return DPI_FAILURE; + } else { + if (dpiOci__defineByPos2(stmt, &defineHandle, pos, var, error) < 0) + return DPI_FAILURE; + } + + // set the charset form if applicable + if (var->type->charsetForm != DPI_SQLCS_IMPLICIT) { + if (dpiOci__attrSet(defineHandle, DPI_OCI_HTYPE_DEFINE, + (void*) &var->type->charsetForm, 0, DPI_OCI_ATTR_CHARSET_FORM, + "set charset form", error) < 0) + return DPI_FAILURE; + } + + // specify that the LOB length should be prefetched + if (var->nativeTypeNum == DPI_NATIVE_TYPE_LOB) { + tempBool = 1; + if (dpiOci__attrSet(defineHandle, DPI_OCI_HTYPE_DEFINE, + (void*) &tempBool, 0, DPI_OCI_ATTR_LOBPREFETCH_LENGTH, + "set lob prefetch length", error) < 0) + return DPI_FAILURE; + } + + // define objects, if applicable + if (var->buffer.objectIndicator && dpiOci__defineObject(var, defineHandle, + error) < 0) + return DPI_FAILURE; + + // register callback for dynamic defines + if (var->isDynamic && dpiOci__defineDynamic(var, defineHandle, error) < 0) + return DPI_FAILURE; + + // remove previous variable and retain new one + if (stmt->queryVars[pos - 1]) + dpiGen__setRefCount(stmt->queryVars[pos - 1], error, -1); + dpiGen__setRefCount(var, error, 1); + stmt->queryVars[pos - 1] = var; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__execute() [INTERNAL] +// Internal execution of statement. +//----------------------------------------------------------------------------- +static int dpiStmt__execute(dpiStmt *stmt, uint32_t numIters, + uint32_t mode, int reExecute, dpiError *error) +{ + uint32_t prefetchSize, i, j; + dpiData *data; + dpiVar *var; + + // for all bound variables, transfer data from dpiData structure to Oracle + // buffer structures + for (i = 0; i < stmt->numBindVars; i++) { + var = stmt->bindVars[i].var; + if (var->isArray && numIters > 1) + return dpiError__set(error, "bind array var", + DPI_ERR_ARRAY_VAR_NOT_SUPPORTED); + for (j = 0; j < var->buffer.maxArraySize; j++) { + data = &var->buffer.externalData[j]; + if (dpiVar__setValue(var, &var->buffer, j, data, error) < 0) + return DPI_FAILURE; + if (var->dynBindBuffers) + var->dynBindBuffers[j].actualArraySize = 0; + } + if (stmt->isReturning || var->isDynamic) + var->error = error; + } + + // for queries, set the OCI prefetch to a fixed value; this prevents an + // additional round trip for single row fetches while avoiding the overhead + // of copying from the OCI prefetch buffer to our own buffers for larger + // fetches + if (stmt->statementType == DPI_STMT_TYPE_SELECT) { + prefetchSize = DPI_PREFETCH_ROWS_DEFAULT; + if (dpiOci__attrSet(stmt->handle, DPI_OCI_HTYPE_STMT, &prefetchSize, + sizeof(prefetchSize), DPI_OCI_ATTR_PREFETCH_ROWS, + "set prefetch rows", error) < 0) + return DPI_FAILURE; + } + + // clear batch errors from any previous execution + dpiStmt__clearBatchErrors(stmt); + + // adjust mode for scrollable cursors + if (stmt->scrollable) + mode |= DPI_OCI_STMT_SCROLLABLE_READONLY; + + // perform execution + // re-execute statement for ORA-01007: variable not in select list + // drop statement from cache for all errors (except those which are due to + // invalid data which may be fixed in subsequent execution) + if (dpiOci__stmtExecute(stmt, numIters, mode, error) < 0) { + dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, + &error->buffer->offset, 0, DPI_OCI_ATTR_PARSE_ERROR_OFFSET, + "set parse offset", error); + switch (error->buffer->code) { + case 1007: + if (reExecute) + return dpiStmt__reExecute(stmt, numIters, mode, error); + stmt->deleteFromCache = 1; + break; + case 1: + case 1400: + case 1438: + case 1461: + case 2290: + case 2291: + case 2292: + case 21525: + break; + default: + stmt->deleteFromCache = 1; + } + return DPI_FAILURE; + } + + // for all bound variables, transfer data from Oracle buffer structures to + // dpiData structures; OCI doesn't provide a way of knowing if a variable + // is an out variable so do this for all of them when this is a possibility + if (stmt->isReturning || stmt->statementType == DPI_STMT_TYPE_BEGIN || + stmt->statementType == DPI_STMT_TYPE_DECLARE || + stmt->statementType == DPI_STMT_TYPE_CALL) { + for (i = 0; i < stmt->numBindVars; i++) { + var = stmt->bindVars[i].var; + for (j = 0; j < var->buffer.maxArraySize; j++) { + if (dpiVar__getValue(var, &var->buffer, j, 0, error) < 0) + return DPI_FAILURE; + } + var->error = NULL; + } + } + + // create query variables (if applicable) and reset row count to zero + if (stmt->statementType == DPI_STMT_TYPE_SELECT) { + stmt->rowCount = 0; + if (!(mode & DPI_MODE_EXEC_PARSE_ONLY) && + dpiStmt__createQueryVars(stmt, error) < 0) + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__fetch() [INTERNAL] +// Performs the actual fetch from Oracle. +//----------------------------------------------------------------------------- +static int dpiStmt__fetch(dpiStmt *stmt, dpiError *error) +{ + // perform any pre-fetch activities required + if (dpiStmt__beforeFetch(stmt, error) < 0) + return DPI_FAILURE; + + // perform fetch + if (dpiOci__stmtFetch2(stmt, stmt->fetchArraySize, DPI_MODE_FETCH_NEXT, 0, + error) < 0) + return DPI_FAILURE; + + // determine the number of rows fetched into buffers + if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, + &stmt->bufferRowCount, 0, DPI_OCI_ATTR_ROWS_FETCHED, + "get rows fetched", error) < 0) + return DPI_FAILURE; + + // set buffer row info + stmt->bufferMinRow = stmt->rowCount + 1; + stmt->bufferRowIndex = 0; + + // perform post-fetch activities required + if (dpiStmt__postFetch(stmt, error) < 0) + return DPI_FAILURE; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__free() [INTERNAL] +// Free the memory associated with the statement. +//----------------------------------------------------------------------------- +void dpiStmt__free(dpiStmt *stmt, dpiError *error) +{ + dpiStmt__close(stmt, NULL, 0, 0, error); + if (stmt->parentStmt) { + dpiGen__setRefCount(stmt->parentStmt, error, -1); + stmt->parentStmt = NULL; + } + if (stmt->conn) { + dpiGen__setRefCount(stmt->conn, error, -1); + stmt->conn = NULL; + } + dpiUtils__freeMemory(stmt); +} + + +//----------------------------------------------------------------------------- +// dpiStmt__getBatchErrors() [INTERNAL] +// Get batch errors after statement executed with batch errors enabled. +//----------------------------------------------------------------------------- +static int dpiStmt__getBatchErrors(dpiStmt *stmt, dpiError *error) +{ + void *batchErrorHandle, *localErrorHandle; + dpiError localError; + int overallStatus; + int32_t rowOffset; + uint32_t i; + + // determine the number of batch errors that were found + if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, + &stmt->numBatchErrors, 0, DPI_OCI_ATTR_NUM_DML_ERRORS, + "get batch error count", error) < 0) + return DPI_FAILURE; + + // allocate memory for the batch errors + if (dpiUtils__allocateMemory(stmt->numBatchErrors, sizeof(dpiErrorBuffer), + 1, "allocate errors", (void**) &stmt->batchErrors, error) < 0) { + stmt->numBatchErrors = 0; + return DPI_FAILURE; + } + + // allocate error handle used for OCIParamGet() + if (dpiOci__handleAlloc(stmt->env->handle, &localErrorHandle, + DPI_OCI_HTYPE_ERROR, "allocate parameter error handle", + error) < 0) { + dpiStmt__clearBatchErrors(stmt); + return DPI_FAILURE; + } + + // allocate error handle used for batch errors + if (dpiOci__handleAlloc(stmt->env->handle, &batchErrorHandle, + DPI_OCI_HTYPE_ERROR, "allocate batch error handle", error) < 0) { + dpiStmt__clearBatchErrors(stmt); + dpiOci__handleFree(localErrorHandle, DPI_OCI_HTYPE_ERROR); + return DPI_FAILURE; + } + + // process each error + overallStatus = DPI_SUCCESS; + localError.buffer = error->buffer; + localError.env = error->env; + for (i = 0; i < stmt->numBatchErrors; i++) { + + // get error handle for iteration + if (dpiOci__paramGet(error->handle, DPI_OCI_HTYPE_ERROR, + &batchErrorHandle, i, "get batch error", error) < 0) { + overallStatus = dpiError__set(error, "get batch error", + DPI_ERR_INVALID_INDEX, i); + break; + } + + // determine row offset + localError.handle = localErrorHandle; + if (dpiOci__attrGet(batchErrorHandle, DPI_OCI_HTYPE_ERROR, &rowOffset, + 0, DPI_OCI_ATTR_DML_ROW_OFFSET, "get row offset", + &localError) < 0) { + overallStatus = dpiError__set(error, "get row offset", + DPI_ERR_CANNOT_GET_ROW_OFFSET); + break; + } + + // get error message + localError.buffer = &stmt->batchErrors[i]; + localError.handle = batchErrorHandle; + dpiError__setFromOCI(&localError, DPI_OCI_ERROR, stmt->conn, + "get batch error"); + if (error->buffer->errorNum) { + overallStatus = DPI_FAILURE; + break; + } + localError.buffer->fnName = error->buffer->fnName; + localError.buffer->offset = (uint16_t) rowOffset; + + } + + // cleanup + dpiOci__handleFree(localErrorHandle, DPI_OCI_HTYPE_ERROR); + dpiOci__handleFree(batchErrorHandle, DPI_OCI_HTYPE_ERROR); + if (overallStatus < 0) + dpiStmt__clearBatchErrors(stmt); + return overallStatus; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__getRowCount() [INTERNAL] +// Return the number of rows affected by the last DML executed (for insert, +// update, delete and merge) or the number of rows fetched (for queries). In +// all other cases, 0 is returned. +//----------------------------------------------------------------------------- +static int dpiStmt__getRowCount(dpiStmt *stmt, uint64_t *count, + dpiError *error) +{ + uint32_t rowCount32; + + if (stmt->statementType == DPI_STMT_TYPE_SELECT) + *count = stmt->rowCount; + else if (stmt->statementType != DPI_STMT_TYPE_INSERT && + stmt->statementType != DPI_STMT_TYPE_UPDATE && + stmt->statementType != DPI_STMT_TYPE_DELETE && + stmt->statementType != DPI_STMT_TYPE_MERGE && + stmt->statementType != DPI_STMT_TYPE_CALL && + stmt->statementType != DPI_STMT_TYPE_BEGIN && + stmt->statementType != DPI_STMT_TYPE_DECLARE) { + *count = 0; + } else if (stmt->env->versionInfo->versionNum < 12) { + if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &rowCount32, 0, + DPI_OCI_ATTR_ROW_COUNT, "get row count", error) < 0) + return DPI_FAILURE; + *count = rowCount32; + } else { + if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, count, 0, + DPI_OCI_ATTR_UB8_ROW_COUNT, "get row count", error) < 0) + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__getQueryInfo() [INTERNAL] +// Get query information for the position in question. +//----------------------------------------------------------------------------- +static int dpiStmt__getQueryInfo(dpiStmt *stmt, uint32_t pos, + dpiQueryInfo *info, dpiError *error) +{ + void *param; + int status; + + // acquire parameter descriptor + if (dpiOci__paramGet(stmt->handle, DPI_OCI_HTYPE_STMT, ¶m, pos, + "get parameter", error) < 0) + return DPI_FAILURE; + + // acquire information from the parameter descriptor + status = dpiStmt__getQueryInfoFromParam(stmt, param, info, error); + dpiOci__descriptorFree(param, DPI_OCI_DTYPE_PARAM); + return status; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__getQueryInfoFromParam() [INTERNAL] +// Get query information from the parameter. +//----------------------------------------------------------------------------- +static int dpiStmt__getQueryInfoFromParam(dpiStmt *stmt, void *param, + dpiQueryInfo *info, dpiError *error) +{ + uint8_t ociNullOk; + + // aquire name of item + if (dpiOci__attrGet(param, DPI_OCI_HTYPE_DESCRIBE, (void*) &info->name, + &info->nameLength, DPI_OCI_ATTR_NAME, "get name", error) < 0) + return DPI_FAILURE; + + // acquire type information + if (dpiOracleType__populateTypeInfo(stmt->conn, param, + DPI_OCI_HTYPE_DESCRIBE, &info->typeInfo, error) < 0) + return DPI_FAILURE; + + // acquire if column is permitted to be null + if (dpiOci__attrGet(param, DPI_OCI_HTYPE_DESCRIBE, (void*) &ociNullOk, 0, + DPI_OCI_ATTR_IS_NULL, "get null ok", error) < 0) + return DPI_FAILURE; + info->nullOk = ociNullOk; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__init() [INTERNAL] +// Initialize the statement for use. This is needed when preparing a +// statement for use and when returning a REF cursor. +//----------------------------------------------------------------------------- +int dpiStmt__init(dpiStmt *stmt, dpiError *error) +{ + // get statement type + if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, + (void*) &stmt->statementType, 0, DPI_OCI_ATTR_STMT_TYPE, + "get statement type", error) < 0) + return DPI_FAILURE; + + // for queries, mark statement as having rows to fetch + if (stmt->statementType == DPI_STMT_TYPE_SELECT) + stmt->hasRowsToFetch = 1; + + // otherwise, check if this is a RETURNING statement + else if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, + (void*) &stmt->isReturning, 0, DPI_OCI_ATTR_STMT_IS_RETURNING, + "get is returning", error) < 0) + return DPI_FAILURE; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__postFetch() [INTERNAL] +// Performs the transformations required to convert Oracle data values into +// C data values. +//----------------------------------------------------------------------------- +static int dpiStmt__postFetch(dpiStmt *stmt, dpiError *error) +{ + uint32_t i, j; + dpiVar *var; + + for (i = 0; i < stmt->numQueryVars; i++) { + var = stmt->queryVars[i]; + for (j = 0; j < stmt->bufferRowCount; j++) { + if (dpiVar__getValue(var, &var->buffer, j, 1, error) < 0) + return DPI_FAILURE; + if (var->type->requiresPreFetch) + var->requiresPreFetch = 1; + } + var->error = NULL; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__beforeFetch() [INTERNAL] +// Performs work that needs to be done prior to fetch for each variable. In +// addition, variables are created if they do not already exist. A check is +// also made to ensure that the variable has enough space to support a fetch +// of the requested size. +//----------------------------------------------------------------------------- +static int dpiStmt__beforeFetch(dpiStmt *stmt, dpiError *error) +{ + dpiQueryInfo *queryInfo; + dpiData *data; + dpiVar *var; + uint32_t i; + + if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, error) < 0) + return DPI_FAILURE; + for (i = 0; i < stmt->numQueryVars; i++) { + var = stmt->queryVars[i]; + if (!var) { + queryInfo = &stmt->queryInfo[i]; + if (dpiVar__allocate(stmt->conn, queryInfo->typeInfo.oracleTypeNum, + queryInfo->typeInfo.defaultNativeTypeNum, + stmt->fetchArraySize, + queryInfo->typeInfo.clientSizeInBytes, 1, 0, + queryInfo->typeInfo.objectType, &var, &data, error) < 0) + return DPI_FAILURE; + if (dpiStmt__define(stmt, i + 1, var, error) < 0) + return DPI_FAILURE; + dpiGen__setRefCount(var, error, -1); + } + var->error = error; + if (stmt->fetchArraySize > var->buffer.maxArraySize) + return dpiError__set(error, "check array size", + DPI_ERR_ARRAY_SIZE_TOO_SMALL, var->buffer.maxArraySize); + if (var->requiresPreFetch && dpiVar__extendedPreFetch(var, + &var->buffer, error) < 0) + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiStmt__prepare() [INTERNAL] +// Prepare a statement for execution. +//----------------------------------------------------------------------------- +int dpiStmt__prepare(dpiStmt *stmt, const char *sql, uint32_t sqlLength, + const char *tag, uint32_t tagLength, dpiError *error) +{ + if (sql && dpiDebugLevel & DPI_DEBUG_LEVEL_SQL) + dpiDebug__print("SQL %.*s\n", sqlLength, sql); + if (dpiOci__stmtPrepare2(stmt, sql, sqlLength, tag, tagLength, error) < 0) + return DPI_FAILURE; + if (dpiHandleList__addHandle(stmt->conn->openStmts, stmt, + &stmt->openSlotNum, error) < 0) { + dpiOci__stmtRelease(stmt, NULL, 0, 0, error); + stmt->handle = NULL; + return DPI_FAILURE; + } + + return dpiStmt__init(stmt, error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt__reExecute() [INTERNAL] +// Re-execute the statement after receiving the error ORA-01007: variable not +// in select list. This takes place when one of the columns in a query is +// dropped, but the original metadata is still being used because the query +// statement was found in the statement cache. +//----------------------------------------------------------------------------- +static int dpiStmt__reExecute(dpiStmt *stmt, uint32_t numIters, + uint32_t mode, dpiError *error) +{ + void *origHandle, *newHandle; + uint32_t sqlLength, i; + dpiError localError; + dpiBindVar *bindVar; + dpiVar *var; + int status; + char *sql; + + // acquire the statement that was previously prepared; if this cannot be + // determined, let the original error propagate + localError.buffer = error->buffer; + localError.env = error->env; + localError.handle = error->handle; + if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) &sql, + &sqlLength, DPI_OCI_ATTR_STATEMENT, "get statement", + &localError) < 0) + return DPI_FAILURE; + + // prepare statement a second time before releasing the original statement; + // release the original statement and delete it from the statement cache + // so that it does not return with the invalid metadata; again, if this + // cannot be done, let the original error propagate + origHandle = stmt->handle; + status = dpiOci__stmtPrepare2(stmt, sql, sqlLength, NULL, 0, &localError); + newHandle = stmt->handle; + stmt->handle = origHandle; + stmt->deleteFromCache = 1; + if (dpiOci__stmtRelease(stmt, NULL, 0, 1, &localError) < 0 || status < 0) + return DPI_FAILURE; + stmt->handle = newHandle; + dpiStmt__clearBatchErrors(stmt); + dpiStmt__clearQueryVars(stmt, error); + + // perform binds + for (i = 0; i < stmt->numBindVars; i++) { + bindVar = &stmt->bindVars[i]; + if (!bindVar->var) + continue; + var = bindVar->var; + bindVar->var = NULL; + if (dpiStmt__bind(stmt, var, 0, bindVar->pos, bindVar->name, + bindVar->nameLength, error) < 0) { + dpiGen__setRefCount(var, error, -1); + return DPI_FAILURE; + } + } + + // now re-execute the statement + return dpiStmt__execute(stmt, numIters, mode, 0, error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_addRef() [PUBLIC] +// Add a reference to the statement. +//----------------------------------------------------------------------------- +int dpiStmt_addRef(dpiStmt *stmt) +{ + return dpiGen__addRef(stmt, DPI_HTYPE_STMT, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_bindByName() [PUBLIC] +// Bind the variable by name. +//----------------------------------------------------------------------------- +int dpiStmt_bindByName(dpiStmt *stmt, const char *name, uint32_t nameLength, + dpiVar *var) +{ + dpiError error; + int status; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, name) + if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "bind by name", &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + status = dpiStmt__bind(stmt, var, 1, 0, name, nameLength, &error); + return dpiGen__endPublicFn(stmt, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_bindByPos() [PUBLIC] +// Bind the variable by position. +//----------------------------------------------------------------------------- +int dpiStmt_bindByPos(dpiStmt *stmt, uint32_t pos, dpiVar *var) +{ + dpiError error; + int status; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "bind by pos", &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + status = dpiStmt__bind(stmt, var, 1, pos, NULL, 0, &error); + return dpiGen__endPublicFn(stmt, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_bindValueByName() [PUBLIC] +// Create a variable and bind it by name. +//----------------------------------------------------------------------------- +int dpiStmt_bindValueByName(dpiStmt *stmt, const char *name, + uint32_t nameLength, dpiNativeTypeNum nativeTypeNum, dpiData *data) +{ + dpiVar *var = NULL; + dpiError error; + int status; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, name) + DPI_CHECK_PTR_NOT_NULL(stmt, data) + if (dpiStmt__createBindVar(stmt, nativeTypeNum, data, &var, 0, name, + nameLength, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + status = dpiStmt__bind(stmt, var, 1, 0, name, nameLength, &error); + return dpiGen__endPublicFn(stmt, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_bindValueByPos() [PUBLIC] +// Create a variable and bind it by position. +//----------------------------------------------------------------------------- +int dpiStmt_bindValueByPos(dpiStmt *stmt, uint32_t pos, + dpiNativeTypeNum nativeTypeNum, dpiData *data) +{ + dpiVar *var = NULL; + dpiError error; + int status; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, data) + if (dpiStmt__createBindVar(stmt, nativeTypeNum, data, &var, pos, NULL, 0, + &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + status = dpiStmt__bind(stmt, var, 1, pos, NULL, 0, &error); + return dpiGen__endPublicFn(stmt, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_close() [PUBLIC] +// Close the statement so that it is no longer usable and all resources have +// been released. +//----------------------------------------------------------------------------- +int dpiStmt_close(dpiStmt *stmt, const char *tag, uint32_t tagLength) +{ + dpiError error; + int status; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(stmt, tag) + status = dpiStmt__close(stmt, tag, tagLength, 1, &error); + return dpiGen__endPublicFn(stmt, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_define() [PUBLIC] +// Define the variable that will accept output from the cursor in the +// specified column. +//----------------------------------------------------------------------------- +int dpiStmt_define(dpiStmt *stmt, uint32_t pos, dpiVar *var) +{ + dpiError error; + int status; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (pos == 0 || pos > stmt->numQueryVars) { + dpiError__set(&error, "check query position", + DPI_ERR_QUERY_POSITION_INVALID, pos); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "check variable", &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + + status = dpiStmt__define(stmt, pos, var, &error); + return dpiGen__endPublicFn(stmt, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_defineValue() [PUBLIC] +// Define the type of data to use for output from the cursor in the specified +// column. This implicitly creates a variable of the specified type and is +// intended for subsequent use by dpiStmt_getQueryValue(), which makes use of +// implicitly created variables. +//----------------------------------------------------------------------------- +int dpiStmt_defineValue(dpiStmt *stmt, uint32_t pos, + dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, + uint32_t size, int sizeIsBytes, dpiObjectType *objType) +{ + dpiError error; + dpiData *data; + dpiVar *var; + + // verify parameters + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (pos == 0 || pos > stmt->numQueryVars) { + dpiError__set(&error, "check query position", + DPI_ERR_QUERY_POSITION_INVALID, pos); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + + // create a new variable of the specified type + if (dpiVar__allocate(stmt->conn, oracleTypeNum, nativeTypeNum, + stmt->fetchArraySize, size, sizeIsBytes, 0, objType, &var, &data, + &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (dpiStmt__define(stmt, pos, var, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + dpiGen__setRefCount(var, &error, -1); + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_execute() [PUBLIC] +// Execute a statement. If the statement has been executed before, however, +// and this is a query, the describe information is already available so defer +// execution until the first fetch. +//----------------------------------------------------------------------------- +int dpiStmt_execute(dpiStmt *stmt, dpiExecMode mode, uint32_t *numQueryColumns) +{ + uint32_t numIters; + dpiError error; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + numIters = (stmt->statementType == DPI_STMT_TYPE_SELECT) ? 0 : 1; + if (dpiStmt__execute(stmt, numIters, mode, 1, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (numQueryColumns) + *numQueryColumns = stmt->numQueryVars; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_executeMany() [PUBLIC] +// Execute a statement multiple times. Queries are not supported. The bind +// variables are checked to ensure that their maxArraySize is sufficient to +// support this. +//----------------------------------------------------------------------------- +int dpiStmt_executeMany(dpiStmt *stmt, dpiExecMode mode, uint32_t numIters) +{ + dpiError error; + uint32_t i; + + // verify statement is open + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + + // queries are not supported + if (stmt->statementType == DPI_STMT_TYPE_SELECT) { + dpiError__set(&error, "check statement type", DPI_ERR_NOT_SUPPORTED); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + + // batch errors and array DML row counts are only supported with DML + // statements (insert, update, delete and merge) + if ((mode & DPI_MODE_EXEC_BATCH_ERRORS || + mode & DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS) && + stmt->statementType != DPI_STMT_TYPE_INSERT && + stmt->statementType != DPI_STMT_TYPE_UPDATE && + stmt->statementType != DPI_STMT_TYPE_DELETE && + stmt->statementType != DPI_STMT_TYPE_MERGE) { + dpiError__set(&error, "check mode", DPI_ERR_EXEC_MODE_ONLY_FOR_DML); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + + // ensure that all bind variables have a big enough maxArraySize to + // support this operation + for (i = 0; i < stmt->numBindVars; i++) { + if (stmt->bindVars[i].var->buffer.maxArraySize < numIters) { + dpiError__set(&error, "check array size", + DPI_ERR_ARRAY_SIZE_TOO_SMALL, + stmt->bindVars[i].var->buffer.maxArraySize); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + } + + // perform execution + dpiStmt__clearBatchErrors(stmt); + if (dpiStmt__execute(stmt, numIters, mode, 0, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + + // handle batch errors if mode was specified + if (mode & DPI_MODE_EXEC_BATCH_ERRORS) { + if (dpiStmt__getBatchErrors(stmt, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_fetch() [PUBLIC] +// Fetch a row from the database. +//----------------------------------------------------------------------------- +int dpiStmt_fetch(dpiStmt *stmt, int *found, uint32_t *bufferRowIndex) +{ + dpiError error; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, found) + DPI_CHECK_PTR_NOT_NULL(stmt, bufferRowIndex) + if (stmt->bufferRowIndex >= stmt->bufferRowCount) { + if (stmt->hasRowsToFetch && dpiStmt__fetch(stmt, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (stmt->bufferRowIndex >= stmt->bufferRowCount) { + *found = 0; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); + } + } + *found = 1; + *bufferRowIndex = stmt->bufferRowIndex; + stmt->bufferRowIndex++; + stmt->rowCount++; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_fetchRows() [PUBLIC] +// Fetch rows into buffers and return the number of rows that were so +// fetched. If there are still rows available in the buffer, no additional +// fetch will take place. +//----------------------------------------------------------------------------- +int dpiStmt_fetchRows(dpiStmt *stmt, uint32_t maxRows, + uint32_t *bufferRowIndex, uint32_t *numRowsFetched, int *moreRows) +{ + dpiError error; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, bufferRowIndex) + DPI_CHECK_PTR_NOT_NULL(stmt, numRowsFetched) + DPI_CHECK_PTR_NOT_NULL(stmt, moreRows) + if (stmt->bufferRowIndex >= stmt->bufferRowCount) { + if (stmt->hasRowsToFetch && dpiStmt__fetch(stmt, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (stmt->bufferRowIndex >= stmt->bufferRowCount) { + *moreRows = 0; + *bufferRowIndex = 0; + *numRowsFetched = 0; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); + } + } + *bufferRowIndex = stmt->bufferRowIndex; + *numRowsFetched = stmt->bufferRowCount - stmt->bufferRowIndex; + *moreRows = stmt->hasRowsToFetch; + if (*numRowsFetched > maxRows) { + *numRowsFetched = maxRows; + *moreRows = 1; + } + stmt->bufferRowIndex += *numRowsFetched; + stmt->rowCount += *numRowsFetched; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getBatchErrorCount() [PUBLIC] +// Return the number of batch errors that took place during the last +// execution of the statement. +//----------------------------------------------------------------------------- +int dpiStmt_getBatchErrorCount(dpiStmt *stmt, uint32_t *count) +{ + dpiError error; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, count) + *count = stmt->numBatchErrors; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getBatchErrors() [PUBLIC] +// Return the batch errors that took place during the last execution of the +// statement. +//----------------------------------------------------------------------------- +int dpiStmt_getBatchErrors(dpiStmt *stmt, uint32_t numErrors, + dpiErrorInfo *errors) +{ + dpiError error, tempError; + uint32_t i; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, errors) + if (numErrors < stmt->numBatchErrors) { + dpiError__set(&error, "check num errors", DPI_ERR_ARRAY_SIZE_TOO_SMALL, + numErrors); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + for (i = 0; i < stmt->numBatchErrors; i++) { + tempError.buffer = &stmt->batchErrors[i]; + dpiError__getInfo(&tempError, &errors[i]); + } + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getBindCount() [PUBLIC] +// Return the number of bind variables referenced in the prepared SQL. In +// SQL statements this counts all bind variables but in PL/SQL statements +// this counts only uniquely named bind variables. +//----------------------------------------------------------------------------- +int dpiStmt_getBindCount(dpiStmt *stmt, uint32_t *count) +{ + dpiError error; + int status; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, count) + status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) count, + 0, DPI_OCI_ATTR_BIND_COUNT, "get bind count", &error); + return dpiGen__endPublicFn(stmt, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getBindNames() [PUBLIC] +// Return the unique names of the bind variables referenced in the prepared +// SQL. +//----------------------------------------------------------------------------- +int dpiStmt_getBindNames(dpiStmt *stmt, uint32_t *numBindNames, + const char **bindNames, uint32_t *bindNameLengths) +{ + uint8_t bindNameLengthsBuffer[8], indNameLengthsBuffer[8], isDuplicate[8]; + uint32_t startLoc, i, numThisPass, numActualBindNames; + char *bindNamesBuffer[8], *indNamesBuffer[8]; + void *bindHandles[8]; + int32_t numFound; + dpiError error; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, numBindNames) + DPI_CHECK_PTR_NOT_NULL(stmt, bindNames) + DPI_CHECK_PTR_NOT_NULL(stmt, bindNameLengths) + startLoc = 1; + numActualBindNames = 0; + while (1) { + if (dpiOci__stmtGetBindInfo(stmt, 8, startLoc, &numFound, + bindNamesBuffer, bindNameLengthsBuffer, indNamesBuffer, + indNameLengthsBuffer, isDuplicate, bindHandles, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (numFound == 0) + break; + numThisPass = abs(numFound) - startLoc + 1; + if (numThisPass > 8) + numThisPass = 8; + for (i = 0; i < numThisPass; i++) { + startLoc++; + if (isDuplicate[i]) + continue; + if (numActualBindNames == *numBindNames) { + dpiError__set(&error, "check num bind names", + DPI_ERR_ARRAY_SIZE_TOO_SMALL, *numBindNames); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + bindNames[numActualBindNames] = bindNamesBuffer[i]; + bindNameLengths[numActualBindNames] = bindNameLengthsBuffer[i]; + numActualBindNames++; + } + if (numFound > 0) + break; + } + *numBindNames = numActualBindNames; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getFetchArraySize() [PUBLIC] +// Get the array size used for fetches. +//----------------------------------------------------------------------------- +int dpiStmt_getFetchArraySize(dpiStmt *stmt, uint32_t *arraySize) +{ + dpiError error; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, arraySize) + *arraySize = stmt->fetchArraySize; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getImplicitResult() [PUBLIC] +// Return the next implicit result from the previously executed statement. If +// no more implicit results exist, NULL is returned. +//----------------------------------------------------------------------------- +int dpiStmt_getImplicitResult(dpiStmt *stmt, dpiStmt **implicitResult) +{ + dpiStmt *tempStmt; + dpiError error; + void *handle; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, implicitResult) + if (dpiUtils__checkClientVersion(stmt->env->versionInfo, 12, 1, + &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (dpiOci__stmtGetNextResult(stmt, &handle, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + *implicitResult = NULL; + if (handle) { + if (dpiStmt__allocate(stmt->conn, 0, &tempStmt, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + tempStmt->handle = handle; + dpiGen__setRefCount(stmt, &error, 1); + tempStmt->parentStmt = stmt; + if (dpiStmt__createQueryVars(tempStmt, &error) < 0) { + dpiStmt__free(tempStmt, &error); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + *implicitResult = tempStmt; + } + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getInfo() [PUBLIC] +// Return information about the statement in the provided structure. +//----------------------------------------------------------------------------- +int dpiStmt_getInfo(dpiStmt *stmt, dpiStmtInfo *info) +{ + dpiError error; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, info) + info->isQuery = (stmt->statementType == DPI_STMT_TYPE_SELECT); + info->isPLSQL = (stmt->statementType == DPI_STMT_TYPE_BEGIN || + stmt->statementType == DPI_STMT_TYPE_DECLARE || + stmt->statementType == DPI_STMT_TYPE_CALL); + info->isDDL = (stmt->statementType == DPI_STMT_TYPE_CREATE || + stmt->statementType == DPI_STMT_TYPE_DROP || + stmt->statementType == DPI_STMT_TYPE_ALTER); + info->isDML = (stmt->statementType == DPI_STMT_TYPE_INSERT || + stmt->statementType == DPI_STMT_TYPE_UPDATE || + stmt->statementType == DPI_STMT_TYPE_DELETE || + stmt->statementType == DPI_STMT_TYPE_MERGE); + info->statementType = stmt->statementType; + info->isReturning = stmt->isReturning; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getLastRowid() [PUBLIC] +// Returns the rowid of the last row that was affected by a DML statement. If +// no rows were affected by the last statement executed or the last statement +// executed was not a DML statement, NULL is returned. +//----------------------------------------------------------------------------- +int dpiStmt_getLastRowid(dpiStmt *stmt, dpiRowid **rowid) +{ + uint64_t rowCount; + dpiError error; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, rowid) + *rowid = NULL; + if (stmt->statementType == DPI_STMT_TYPE_INSERT || + stmt->statementType == DPI_STMT_TYPE_UPDATE || + stmt->statementType == DPI_STMT_TYPE_DELETE || + stmt->statementType == DPI_STMT_TYPE_MERGE) { + if (dpiStmt__getRowCount(stmt, &rowCount, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (rowCount > 0) { + if (stmt->lastRowid) { + dpiGen__setRefCount(stmt->lastRowid, &error, -1); + stmt->lastRowid = NULL; + } + if (dpiRowid__allocate(stmt->conn, &stmt->lastRowid, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, + stmt->lastRowid->handle, 0, DPI_OCI_ATTR_ROWID, + "get last rowid", &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + *rowid = stmt->lastRowid; + } + } + + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getNumQueryColumns() [PUBLIC] +// Returns the number of query columns associated with a statement. If the +// statement does not refer to a query, 0 is returned. +//----------------------------------------------------------------------------- +int dpiStmt_getNumQueryColumns(dpiStmt *stmt, uint32_t *numQueryColumns) +{ + dpiError error; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, numQueryColumns) + if (stmt->statementType == DPI_STMT_TYPE_SELECT && + stmt->numQueryVars == 0 && + dpiStmt__createQueryVars(stmt, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + *numQueryColumns = stmt->numQueryVars; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getQueryInfo() [PUBLIC] +// Get query information for the position in question. +//----------------------------------------------------------------------------- +int dpiStmt_getQueryInfo(dpiStmt *stmt, uint32_t pos, dpiQueryInfo *info) +{ + dpiError error; + + // validate parameters + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, info) + if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (pos == 0 || pos > stmt->numQueryVars) { + dpiError__set(&error, "check query position", + DPI_ERR_QUERY_POSITION_INVALID, pos); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + + // copy query information from internal cache + memcpy(info, &stmt->queryInfo[pos - 1], sizeof(dpiQueryInfo)); + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getQueryValue() [PUBLIC] +// Get value from query at specified position. +//----------------------------------------------------------------------------- +int dpiStmt_getQueryValue(dpiStmt *stmt, uint32_t pos, + dpiNativeTypeNum *nativeTypeNum, dpiData **data) +{ + dpiError error; + dpiVar *var; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, nativeTypeNum) + DPI_CHECK_PTR_NOT_NULL(stmt, data) + if (!stmt->queryVars) { + dpiError__set(&error, "check query vars", DPI_ERR_QUERY_NOT_EXECUTED); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + if (pos == 0 || pos > stmt->numQueryVars) { + dpiError__set(&error, "check query position", + DPI_ERR_QUERY_POSITION_INVALID, pos); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + var = stmt->queryVars[pos - 1]; + if (!var || stmt->bufferRowIndex == 0 || + stmt->bufferRowIndex > stmt->bufferRowCount) { + dpiError__set(&error, "check fetched row", DPI_ERR_NO_ROW_FETCHED); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + *nativeTypeNum = var->nativeTypeNum; + *data = &var->buffer.externalData[stmt->bufferRowIndex - 1]; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getRowCount() [PUBLIC] +// Return the number of rows affected by the last DML executed (for insert, +// update, delete and merge) or the number of rows fetched (for queries). In +// all other cases, 0 is returned. +//----------------------------------------------------------------------------- +int dpiStmt_getRowCount(dpiStmt *stmt, uint64_t *count) +{ + dpiError error; + int status; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, count) + status = dpiStmt__getRowCount(stmt, count, &error); + return dpiGen__endPublicFn(stmt, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getRowCounts() [PUBLIC] +// Return the number of rows affected by each of the iterations executed +// using dpiStmt_executeMany(). +//----------------------------------------------------------------------------- +int dpiStmt_getRowCounts(dpiStmt *stmt, uint32_t *numRowCounts, + uint64_t **rowCounts) +{ + dpiError error; + int status; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, numRowCounts) + DPI_CHECK_PTR_NOT_NULL(stmt, rowCounts) + if (dpiUtils__checkClientVersion(stmt->env->versionInfo, 12, 1, + &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, rowCounts, + numRowCounts, DPI_OCI_ATTR_DML_ROW_COUNT_ARRAY, "get row counts", + &error); + return dpiGen__endPublicFn(stmt, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_getSubscrQueryId() [PUBLIC] +// Return the query id for a query registered using this statement. +//----------------------------------------------------------------------------- +int dpiStmt_getSubscrQueryId(dpiStmt *stmt, uint64_t *queryId) +{ + dpiError error; + int status; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(stmt, queryId) + status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, queryId, 0, + DPI_OCI_ATTR_CQ_QUERYID, "get query id", &error); + return dpiGen__endPublicFn(stmt, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_release() [PUBLIC] +// Release a reference to the statement. +//----------------------------------------------------------------------------- +int dpiStmt_release(dpiStmt *stmt) +{ + return dpiGen__release(stmt, DPI_HTYPE_STMT, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_scroll() [PUBLIC] +// Scroll to the specified location in the cursor. +//----------------------------------------------------------------------------- +int dpiStmt_scroll(dpiStmt *stmt, dpiFetchMode mode, int32_t offset, + int32_t rowCountOffset) +{ + uint32_t numRows, currentPosition; + uint64_t desiredRow = 0; + dpiError error; + + // make sure the cursor is open + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + + // validate mode; determine desired row to fetch + switch (mode) { + case DPI_MODE_FETCH_NEXT: + desiredRow = stmt->rowCount + rowCountOffset + 1; + break; + case DPI_MODE_FETCH_PRIOR: + desiredRow = stmt->rowCount + rowCountOffset - 1; + break; + case DPI_MODE_FETCH_FIRST: + desiredRow = 1; + break; + case DPI_MODE_FETCH_LAST: + break; + case DPI_MODE_FETCH_ABSOLUTE: + desiredRow = (uint64_t) offset; + break; + case DPI_MODE_FETCH_RELATIVE: + desiredRow = stmt->rowCount + rowCountOffset + offset; + offset = (int32_t) (desiredRow - + (stmt->bufferMinRow + stmt->bufferRowCount - 1)); + break; + default: + dpiError__set(&error, "scroll mode", DPI_ERR_NOT_SUPPORTED); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + + // determine if a fetch is actually required; "last" is always fetched + if (mode != DPI_MODE_FETCH_LAST && desiredRow >= stmt->bufferMinRow && + desiredRow < stmt->bufferMinRow + stmt->bufferRowCount) { + stmt->bufferRowIndex = (uint32_t) (desiredRow - stmt->bufferMinRow); + stmt->rowCount = desiredRow - 1; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); + } + + // perform any pre-fetch activities required + if (dpiStmt__beforeFetch(stmt, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + + // perform fetch; when fetching the last row, only fetch a single row + numRows = (mode == DPI_MODE_FETCH_LAST) ? 1 : stmt->fetchArraySize; + if (dpiOci__stmtFetch2(stmt, numRows, mode, offset, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + + // determine the number of rows actually fetched + if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, + &stmt->bufferRowCount, 0, DPI_OCI_ATTR_ROWS_FETCHED, + "get rows fetched", &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + + // check that we haven't gone outside of the result set + if (stmt->bufferRowCount == 0) { + if (mode != DPI_MODE_FETCH_FIRST && mode != DPI_MODE_FETCH_LAST) { + dpiError__set(&error, "check result set bounds", + DPI_ERR_SCROLL_OUT_OF_RS); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + stmt->hasRowsToFetch = 0; + stmt->rowCount = 0; + stmt->bufferRowIndex = 0; + stmt->bufferMinRow = 0; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); + } + + // determine the current position of the cursor + if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, ¤tPosition, 0, + DPI_OCI_ATTR_CURRENT_POSITION, "get current pos", &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + + // reset buffer row index and row count + stmt->rowCount = currentPosition - stmt->bufferRowCount; + stmt->bufferMinRow = stmt->rowCount + 1; + stmt->bufferRowIndex = 0; + + // perform post-fetch activities required + if (dpiStmt__postFetch(stmt, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiStmt_setFetchArraySize() [PUBLIC] +// Set the array size used for fetches. Using a value of zero will select the +// default value. A check is made to ensure that all defined variables have +// sufficient space to support the array size. +//----------------------------------------------------------------------------- +int dpiStmt_setFetchArraySize(dpiStmt *stmt, uint32_t arraySize) +{ + dpiError error; + dpiVar *var; + uint32_t i; + + if (dpiStmt__check(stmt, __func__, &error) < 0) + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + if (arraySize == 0) + arraySize = DPI_DEFAULT_FETCH_ARRAY_SIZE; + for (i = 0; i < stmt->numQueryVars; i++) { + var = stmt->queryVars[i]; + if (var && var->buffer.maxArraySize < arraySize) { + dpiError__set(&error, "check array size", + DPI_ERR_ARRAY_SIZE_TOO_BIG, arraySize); + return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); + } + } + stmt->fetchArraySize = arraySize; + return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiSubscr.c b/vendor/github.com/godror/godror/odpi/src/dpiSubscr.c new file mode 100644 index 00000000000..cf1ed60b2d8 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiSubscr.c @@ -0,0 +1,713 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiSubscr.c +// Implementation of subscriptions (CQN). +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +// forward declarations of internal functions only used in this file +static void dpiSubscr__freeMessage(dpiSubscrMessage *message); +static int dpiSubscr__populateMessage(dpiSubscr *subscr, + dpiSubscrMessage *message, void *descriptor, dpiError *error); +static int dpiSubscr__populateMessageTable(dpiSubscr *subscr, + dpiSubscrMessageTable *table, void *descriptor, dpiError *error); +static int dpiSubscr__populateQueryChangeMessage(dpiSubscr *subscr, + dpiSubscrMessage *message, void *descriptor, dpiError *error); + + +//----------------------------------------------------------------------------- +// dpiSubscr__callback() [INTERNAL] +// Callback that is used to execute the callback registered when the +// subscription was created. +//----------------------------------------------------------------------------- +static void dpiSubscr__callback(dpiSubscr *subscr, UNUSED void *handle, + UNUSED void *payload, UNUSED uint32_t payloadLength, void *descriptor, + UNUSED uint32_t mode) +{ + dpiSubscrMessage message; + dpiErrorInfo errorInfo; + dpiError error; + + // ensure that the subscription handle is still valid + if (dpiGen__startPublicFn(subscr, DPI_HTYPE_SUBSCR, __func__, + &error) < 0) { + dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); + return; + } + + // if the subscription is no longer registered, nothing further to do + dpiMutex__acquire(subscr->mutex); + if (!subscr->registered) { + dpiMutex__release(subscr->mutex); + dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); + return; + } + + // populate message + memset(&message, 0, sizeof(message)); + if (dpiSubscr__populateMessage(subscr, &message, descriptor, &error) < 0) { + dpiError__getInfo(&error, &errorInfo); + message.errorInfo = &errorInfo; + } + message.registered = subscr->registered; + + // invoke user callback; temporarily increase reference count to ensure + // that the subscription is not freed during the callback + dpiGen__setRefCount(subscr, &error, 1); + (*subscr->callback)(subscr->callbackContext, &message); + dpiSubscr__freeMessage(&message); + dpiMutex__release(subscr->mutex); + dpiGen__setRefCount(subscr, &error, -1); + dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__check() [INTERNAL] +// Determine if the subscription is open and available for use. +//----------------------------------------------------------------------------- +static int dpiSubscr__check(dpiSubscr *subscr, const char *fnName, + dpiError *error) +{ + if (dpiGen__startPublicFn(subscr, DPI_HTYPE_SUBSCR, fnName, error) < 0) + return DPI_FAILURE; + if (!subscr->handle) + return dpiError__set(error, "check closed", DPI_ERR_SUBSCR_CLOSED); + return dpiConn__checkConnected(subscr->conn, error); +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__create() [INTERNAL] +// Create a new subscription structure and return it. In case of error NULL +// is returned. +//----------------------------------------------------------------------------- +int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn, + dpiSubscrCreateParams *params, dpiError *error) +{ + uint32_t qosFlags, mode; + int32_t int32Val; + int rowids; + + // retain a reference to the connection + dpiGen__setRefCount(conn, error, 1); + subscr->conn = conn; + subscr->callback = params->callback; + subscr->callbackContext = params->callbackContext; + subscr->subscrNamespace = params->subscrNamespace; + subscr->qos = params->qos; + subscr->clientInitiated = params->clientInitiated; + dpiMutex__initialize(subscr->mutex); + + // create the subscription handle + if (dpiOci__handleAlloc(conn->env->handle, &subscr->handle, + DPI_OCI_HTYPE_SUBSCRIPTION, "create subscr handle", error) < 0) + return DPI_FAILURE; + + // set the namespace + if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) ¶ms->subscrNamespace, sizeof(uint32_t), + DPI_OCI_ATTR_SUBSCR_NAMESPACE, "set namespace", error) < 0) + return DPI_FAILURE; + + // set the protocol + if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) ¶ms->protocol, sizeof(uint32_t), + DPI_OCI_ATTR_SUBSCR_RECPTPROTO, "set protocol", error) < 0) + return DPI_FAILURE; + + // set the timeout + if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) ¶ms->timeout, sizeof(uint32_t), + DPI_OCI_ATTR_SUBSCR_TIMEOUT, "set timeout", error) < 0) + return DPI_FAILURE; + + // set the IP address used on the client to listen for events + if (params->ipAddress && params->ipAddressLength > 0 && + dpiOci__attrSet(subscr->env->handle, DPI_OCI_HTYPE_ENV, + (void*) params->ipAddress, params->ipAddressLength, + DPI_OCI_ATTR_SUBSCR_IPADDR, "set IP address", error) < 0) + return DPI_FAILURE; + + // set the port number used on the client to listen for events + if (params->portNumber > 0 && dpiOci__attrSet(subscr->env->handle, + DPI_OCI_HTYPE_ENV, (void*) ¶ms->portNumber, 0, + DPI_OCI_ATTR_SUBSCR_PORTNO, "set port number", error) < 0) + return DPI_FAILURE; + + // set the context for the callback + if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) subscr, 0, DPI_OCI_ATTR_SUBSCR_CTX, "set callback context", + error) < 0) + return DPI_FAILURE; + + // set the callback, if applicable + if (params->callback && dpiOci__attrSet(subscr->handle, + DPI_OCI_HTYPE_SUBSCRIPTION, (void*) dpiSubscr__callback, 0, + DPI_OCI_ATTR_SUBSCR_CALLBACK, "set callback", error) < 0) + return DPI_FAILURE; + + // set the subscription name, if applicable + if (params->name && params->nameLength > 0 && + dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) params->name, params->nameLength, + DPI_OCI_ATTR_SUBSCR_NAME, "set name", error) < 0) + return DPI_FAILURE; + + // set QOS flags + qosFlags = 0; + if (params->qos & DPI_SUBSCR_QOS_RELIABLE) + qosFlags |= DPI_OCI_SUBSCR_QOS_RELIABLE; + if (params->qos & DPI_SUBSCR_QOS_DEREG_NFY) + qosFlags |= DPI_OCI_SUBSCR_QOS_PURGE_ON_NTFN; + if (qosFlags && dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) &qosFlags, sizeof(uint32_t), DPI_OCI_ATTR_SUBSCR_QOSFLAGS, + "set QOS", error) < 0) + return DPI_FAILURE; + + // set CQ specific QOS flags + qosFlags = 0; + if (params->qos & DPI_SUBSCR_QOS_QUERY) + qosFlags |= DPI_OCI_SUBSCR_CQ_QOS_QUERY; + if (params->qos & DPI_SUBSCR_QOS_BEST_EFFORT) + qosFlags |= DPI_OCI_SUBSCR_CQ_QOS_BEST_EFFORT; + if (qosFlags && dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) &qosFlags, sizeof(uint32_t), + DPI_OCI_ATTR_SUBSCR_CQ_QOSFLAGS, "set CQ QOS", error) < 0) + return DPI_FAILURE; + + // set rowids flag, if applicable + if (params->qos & DPI_SUBSCR_QOS_ROWIDS) { + rowids = 1; + if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) &rowids, 0, DPI_OCI_ATTR_CHNF_ROWIDS, + "set rowids flag", error) < 0) + return DPI_FAILURE; + } + + // set which operations are desired, if applicable + if (params->operations && dpiOci__attrSet(subscr->handle, + DPI_OCI_HTYPE_SUBSCRIPTION, (void*) ¶ms->operations, 0, + DPI_OCI_ATTR_CHNF_OPERATIONS, "set operations", error) < 0) + return DPI_FAILURE; + + // set grouping information, if applicable + if (params->groupingClass) { + + // set grouping class + if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) ¶ms->groupingClass, 0, + DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_CLASS, "set grouping class", + error) < 0) + return DPI_FAILURE; + + // set grouping value + if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) ¶ms->groupingValue, 0, + DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_VALUE, "set grouping value", + error) < 0) + return DPI_FAILURE; + + // set grouping type + if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) ¶ms->groupingType, 0, + DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_TYPE, "set grouping type", + error) < 0) + return DPI_FAILURE; + + // set grouping repeat count + int32Val = DPI_SUBSCR_GROUPING_FOREVER; + if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + (void*) &int32Val, 0, + DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_REPEAT_COUNT, + "set grouping repeat count", error) < 0) + return DPI_FAILURE; + + } + + // register the subscription; client initiated subscriptions are only valid + // with 19.4 client and database + mode = DPI_OCI_DEFAULT; + if (params->clientInitiated) { + if (dpiUtils__checkClientVersion(conn->env->versionInfo, 19, 4, + error) < 0) + return DPI_FAILURE; + if (dpiUtils__checkDatabaseVersion(conn, 19, 4, error) < 0) + return DPI_FAILURE; + mode = DPI_OCI_SECURE_NOTIFICATION; + } + if (dpiOci__subscriptionRegister(conn, &subscr->handle, mode, error) < 0) + return DPI_FAILURE; + subscr->registered = 1; + + // acquire the registration id + if (dpiOci__attrGet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, + ¶ms->outRegId, NULL, DPI_OCI_ATTR_SUBSCR_CQ_REGID, + "get registration id", error) < 0) + return DPI_FAILURE; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__free() [INTERNAL] +// Free the memory and any resources associated with the subscription. +//----------------------------------------------------------------------------- +void dpiSubscr__free(dpiSubscr *subscr, dpiError *error) +{ + dpiMutex__acquire(subscr->mutex); + if (subscr->handle) { + if (subscr->registered) + dpiOci__subscriptionUnRegister(subscr->conn, subscr, error); + dpiOci__handleFree(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION); + subscr->handle = NULL; + } + if (subscr->conn) { + dpiGen__setRefCount(subscr->conn, error, -1); + subscr->conn = NULL; + } + dpiMutex__release(subscr->mutex); + dpiMutex__destroy(subscr->mutex); + dpiUtils__freeMemory(subscr); +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__freeMessage() [INTERNAL] +// Free memory associated with the message. +//----------------------------------------------------------------------------- +static void dpiSubscr__freeMessage(dpiSubscrMessage *message) +{ + dpiSubscrMessageQuery *query; + uint32_t i, j; + + // free the tables for the message + if (message->numTables > 0) { + for (i = 0; i < message->numTables; i++) { + if (message->tables[i].numRows > 0) + dpiUtils__freeMemory(message->tables[i].rows); + } + dpiUtils__freeMemory(message->tables); + } + + // free the queries for the message + if (message->numQueries > 0) { + for (i = 0; i < message->numQueries; i++) { + query = &message->queries[i]; + if (query->numTables > 0) { + for (j = 0; j < query->numTables; j++) { + if (query->tables[j].numRows > 0) + dpiUtils__freeMemory(query->tables[j].rows); + } + dpiUtils__freeMemory(query->tables); + } + } + dpiUtils__freeMemory(message->queries); + } +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__populateAQMessage() [INTERNAL] +// Populate message with details. +//----------------------------------------------------------------------------- +static int dpiSubscr__populateAQMessage(dpiSubscr *subscr, + dpiSubscrMessage *message, void *descriptor, dpiError *error) +{ + uint32_t flags = 0; + + // determine if message is a deregistration message + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, &flags, + NULL, DPI_OCI_ATTR_NFY_FLAGS, "get flags", error) < 0) + return DPI_FAILURE; + message->eventType = (flags == 1) ? DPI_EVENT_DEREG : DPI_EVENT_AQ; + if (message->eventType == DPI_EVENT_DEREG) { + subscr->registered = 0; + return DPI_SUCCESS; + } + + // determine the name of the queue which spawned the event + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, + (void*) &message->queueName, &message->queueNameLength, + DPI_OCI_ATTR_QUEUE_NAME, "get queue name", error) < 0) + return DPI_FAILURE; + + // determine the consumer name for the queue that spawned the event + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, + (void*) &message->consumerName, &message->consumerNameLength, + DPI_OCI_ATTR_CONSUMER_NAME, "get consumer name", error) < 0) + return DPI_FAILURE; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__populateObjectChangeMessage() [INTERNAL] +// Populate object change message with details. +//----------------------------------------------------------------------------- +static int dpiSubscr__populateObjectChangeMessage(dpiSubscr *subscr, + dpiSubscrMessage *message, void *descriptor, dpiError *error) +{ + void **tableDescriptor, *indicator; + int32_t numTables; + void *tables; + uint32_t i; + int exists; + + // determine table collection + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &tables, 0, + DPI_OCI_ATTR_CHDES_TABLE_CHANGES, "get tables", error) < 0) + return DPI_FAILURE; + if (!tables) + return DPI_SUCCESS; + + // determine number of tables + if (dpiOci__collSize(subscr->conn, tables, &numTables, error) < 0) + return DPI_FAILURE; + + // allocate memory for table entries + if (dpiUtils__allocateMemory((size_t) numTables, + sizeof(dpiSubscrMessageTable), 1, "allocate msg tables", + (void**) &message->tables, error) < 0) + return DPI_FAILURE; + message->numTables = (uint32_t) numTables; + + // populate message table entries + for (i = 0; i < message->numTables; i++) { + if (dpiOci__collGetElem(subscr->conn, tables, (int32_t) i, &exists, + (void**) &tableDescriptor, &indicator, error) < 0) + return DPI_FAILURE; + if (dpiSubscr__populateMessageTable(subscr, &message->tables[i], + *tableDescriptor, error) < 0) + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__populateMessage() [INTERNAL] +// Populate message with details. +//----------------------------------------------------------------------------- +static int dpiSubscr__populateMessage(dpiSubscr *subscr, + dpiSubscrMessage *message, void *descriptor, dpiError *error) +{ + void *rawValue; + + // if quality of service flag indicates that deregistration should take + // place when the first notification is received, mark the subscription + // as no longer registered + if (subscr->qos & DPI_SUBSCR_QOS_DEREG_NFY) + subscr->registered = 0; + + // handle AQ messages, if applicable + if (subscr->subscrNamespace == DPI_SUBSCR_NAMESPACE_AQ) + return dpiSubscr__populateAQMessage(subscr, message, descriptor, + error); + + // determine the type of event that was spawned + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &message->eventType, + NULL, DPI_OCI_ATTR_CHDES_NFYTYPE, "get event type", error) < 0) + return DPI_FAILURE; + + // determine the name of the database which spawned the event + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, + (void*) &message->dbName, &message->dbNameLength, + DPI_OCI_ATTR_CHDES_DBNAME, "get DB name", error) < 0) + return DPI_FAILURE; + + // determine the id of the transaction which spawned the event + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &rawValue, NULL, + DPI_OCI_ATTR_CHDES_XID, "get transaction id", error) < 0) + return DPI_FAILURE; + dpiOci__rawPtr(subscr->env->handle, rawValue, (void**) &message->txId); + dpiOci__rawSize(subscr->env->handle, rawValue, &message->txIdLength); + + // populate event specific attributes + switch (message->eventType) { + case DPI_EVENT_OBJCHANGE: + return dpiSubscr__populateObjectChangeMessage(subscr, message, + descriptor, error); + case DPI_EVENT_QUERYCHANGE: + return dpiSubscr__populateQueryChangeMessage(subscr, message, + descriptor, error); + case DPI_EVENT_DEREG: + subscr->registered = 0; + break; + case DPI_EVENT_STARTUP: + case DPI_EVENT_SHUTDOWN: + case DPI_EVENT_SHUTDOWN_ANY: + break; + default: + return dpiError__set(error, "event type", DPI_ERR_NOT_SUPPORTED); + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__populateMessageQuery() [INTERNAL] +// Populate a message query structure from the OCI descriptor. +//----------------------------------------------------------------------------- +static int dpiSubscr__populateMessageQuery(dpiSubscr *subscr, + dpiSubscrMessageQuery *query, void *descriptor, dpiError *error) +{ + void **tableDescriptor, *indicator, *tables; + int32_t numTables; + uint32_t i; + int exists; + + // determine query id + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CQDES, &query->id, 0, + DPI_OCI_ATTR_CQDES_QUERYID, "get id", error) < 0) + return DPI_FAILURE; + + // determine operation + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CQDES, &query->operation, 0, + DPI_OCI_ATTR_CQDES_OPERATION, "get operation", error) < 0) + return DPI_FAILURE; + + // determine table collection + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CQDES, &tables, 0, + DPI_OCI_ATTR_CQDES_TABLE_CHANGES, "get table descriptor", + error) < 0) + return DPI_FAILURE; + if (!tables) + return DPI_SUCCESS; + + // determine number of tables + if (dpiOci__collSize(subscr->conn, tables, &numTables, error) < 0) + return DPI_FAILURE; + + // allocate memory for table entries + if (dpiUtils__allocateMemory((size_t) numTables, + sizeof(dpiSubscrMessageTable), 1, "allocate query tables", + (void**) &query->tables, error) < 0) + return DPI_FAILURE; + query->numTables = (uint32_t) numTables; + + // populate message table entries + for (i = 0; i < query->numTables; i++) { + if (dpiOci__collGetElem(subscr->conn, tables, (int32_t) i, &exists, + (void**) &tableDescriptor, &indicator, error) < 0) + return DPI_FAILURE; + if (dpiSubscr__populateMessageTable(subscr, &query->tables[i], + *tableDescriptor, error) < 0) + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__populateMessageRow() [INTERNAL] +// Populate a message row structure from the OCI descriptor. +//----------------------------------------------------------------------------- +static int dpiSubscr__populateMessageRow(dpiSubscrMessageRow *row, + void *descriptor, dpiError *error) +{ + // determine operation + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_ROW_CHDES, &row->operation, + 0, DPI_OCI_ATTR_CHDES_ROW_OPFLAGS, "get operation", error) < 0) + return DPI_FAILURE; + + // determine rowid + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_ROW_CHDES, + (void*) &row->rowid, &row->rowidLength, + DPI_OCI_ATTR_CHDES_ROW_ROWID, "get rowid", error) < 0) + return DPI_FAILURE; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__populateMessageTable() [INTERNAL] +// Populate a message table structure from the OCI descriptor. +//----------------------------------------------------------------------------- +static int dpiSubscr__populateMessageTable(dpiSubscr *subscr, + dpiSubscrMessageTable *table, void *descriptor, dpiError *error) +{ + void **rowDescriptor, *indicator, *rows; + int32_t numRows; + int exists; + uint32_t i; + + // determine operation + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_TABLE_CHDES, + &table->operation, 0, DPI_OCI_ATTR_CHDES_TABLE_OPFLAGS, + "get operation", error) < 0) + return DPI_FAILURE; + + // determine table name + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_TABLE_CHDES, + (void*) &table->name, &table->nameLength, + DPI_OCI_ATTR_CHDES_TABLE_NAME, "get table name", error) < 0) + return DPI_FAILURE; + + // if change invalidated all rows, nothing to do + if (table->operation & DPI_OPCODE_ALL_ROWS) + return DPI_SUCCESS; + + // determine rows collection + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_TABLE_CHDES, &rows, 0, + DPI_OCI_ATTR_CHDES_TABLE_ROW_CHANGES, "get rows descriptor", + error) < 0) + return DPI_FAILURE; + + // determine number of rows in collection + if (dpiOci__collSize(subscr->conn, rows, &numRows, error) < 0) + return DPI_FAILURE; + + // allocate memory for row entries + if (dpiUtils__allocateMemory((size_t) numRows, sizeof(dpiSubscrMessageRow), + 1, "allocate rows", (void**) &table->rows, error) < 0) + return DPI_FAILURE; + table->numRows = (uint32_t) numRows; + + // populate the rows attribute + for (i = 0; i < table->numRows; i++) { + if (dpiOci__collGetElem(subscr->conn, rows, (int32_t) i, &exists, + (void**) &rowDescriptor, &indicator, error) < 0) + return DPI_FAILURE; + if (dpiSubscr__populateMessageRow(&table->rows[i], *rowDescriptor, + error) < 0) + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__populateQueryChangeMessage() [INTERNAL] +// Populate query change message with details. +//----------------------------------------------------------------------------- +static int dpiSubscr__populateQueryChangeMessage(dpiSubscr *subscr, + dpiSubscrMessage *message, void *descriptor, dpiError *error) +{ + void **queryDescriptor, *indicator, *queries; + int32_t numQueries; + int exists; + uint32_t i; + + // determine query collection + if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &queries, 0, + DPI_OCI_ATTR_CHDES_QUERIES, "get queries", error) < 0) + return DPI_FAILURE; + if (!queries) + return DPI_SUCCESS; + + // determine number of queries + if (dpiOci__collSize(subscr->conn, queries, &numQueries, error) < 0) + return DPI_FAILURE; + + // allocate memory for query entries + if (dpiUtils__allocateMemory((size_t) numQueries, + sizeof(dpiSubscrMessageQuery), 1, "allocate queries", + (void**) &message->queries, error) < 0) + return DPI_FAILURE; + message->numQueries = (uint32_t) numQueries; + + // populate each entry with a message query instance + for (i = 0; i < message->numQueries; i++) { + if (dpiOci__collGetElem(subscr->conn, queries, (int32_t) i, &exists, + (void**) &queryDescriptor, &indicator, error) < 0) + return DPI_FAILURE; + if (dpiSubscr__populateMessageQuery(subscr, &message->queries[i], + *queryDescriptor, error) < 0) + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiSubscr__prepareStmt() [INTERNAL] +// Internal method for preparing statement against a subscription. This +// allows for normal error processing without having to worry about freeing the +// statement for every error that might take place. +//----------------------------------------------------------------------------- +static int dpiSubscr__prepareStmt(dpiSubscr *subscr, dpiStmt *stmt, + const char *sql, uint32_t sqlLength, dpiError *error) +{ + // prepare statement for execution; only SELECT statements are supported + if (dpiStmt__prepare(stmt, sql, sqlLength, NULL, 0, error) < 0) + return DPI_FAILURE; + if (stmt->statementType != DPI_STMT_TYPE_SELECT) + return dpiError__set(error, "subscr prepare statement", + DPI_ERR_NOT_SUPPORTED); + + // fetch array size is set to 1 in order to avoid over allocation since + // the query is not really going to be used for fetching rows, just for + // registration + stmt->fetchArraySize = 1; + + // set subscription handle + return dpiOci__attrSet(stmt->handle, DPI_OCI_HTYPE_STMT, subscr->handle, 0, + DPI_OCI_ATTR_CHNF_REGHANDLE, "set subscription handle", error); +} + + +//----------------------------------------------------------------------------- +// dpiSubscr_addRef() [PUBLIC] +// Add a reference to the subscription. +//----------------------------------------------------------------------------- +int dpiSubscr_addRef(dpiSubscr *subscr) +{ + return dpiGen__addRef(subscr, DPI_HTYPE_SUBSCR, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiSubscr_prepareStmt() [PUBLIC] +// Prepare statement for registration with subscription. +//----------------------------------------------------------------------------- +int dpiSubscr_prepareStmt(dpiSubscr *subscr, const char *sql, + uint32_t sqlLength, dpiStmt **stmt) +{ + dpiStmt *tempStmt; + dpiError error; + + if (dpiSubscr__check(subscr, __func__, &error) < 0) + return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(subscr, sql) + DPI_CHECK_PTR_NOT_NULL(subscr, stmt) + if (dpiStmt__allocate(subscr->conn, 0, &tempStmt, &error) < 0) + return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); + if (dpiSubscr__prepareStmt(subscr, tempStmt, sql, sqlLength, + &error) < 0) { + dpiStmt__free(tempStmt, &error); + return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); + } + + *stmt = tempStmt; + return dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiSubscr_release() [PUBLIC] +// Release a reference to the subscription. +//----------------------------------------------------------------------------- +int dpiSubscr_release(dpiSubscr *subscr) +{ + return dpiGen__release(subscr, DPI_HTYPE_SUBSCR, __func__); +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiUtils.c b/vendor/github.com/godror/godror/odpi/src/dpiUtils.c new file mode 100644 index 00000000000..0ab09e54487 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiUtils.c @@ -0,0 +1,401 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiUtils.c +// Utility methods that aren't specific to a particular type. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +//----------------------------------------------------------------------------- +// dpiUtils__allocateMemory() [INTERNAL] +// Method for allocating memory which permits tracing and populates the error +// structure in the event of a memory allocation failure. +//----------------------------------------------------------------------------- +int dpiUtils__allocateMemory(size_t numMembers, size_t memberSize, + int clearMemory, const char *action, void **ptr, dpiError *error) +{ + if (clearMemory) + *ptr = calloc(numMembers, memberSize); + else *ptr = malloc(numMembers * memberSize); + if (!*ptr) + return dpiError__set(error, action, DPI_ERR_NO_MEMORY); + if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM) + dpiDebug__print("allocated %u bytes at %p (%s)\n", + numMembers * memberSize, *ptr, action); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiUtils__checkClientVersion() [INTERNAL] +// Check the Oracle Client version and verify that it is at least at the +// minimum version that is required. +//----------------------------------------------------------------------------- +int dpiUtils__checkClientVersion(dpiVersionInfo *versionInfo, + int minVersionNum, int minReleaseNum, dpiError *error) +{ + if (versionInfo->versionNum < minVersionNum || + (versionInfo->versionNum == minVersionNum && + versionInfo->releaseNum < minReleaseNum)) + return dpiError__set(error, "check Oracle Client version", + DPI_ERR_ORACLE_CLIENT_TOO_OLD, versionInfo->versionNum, + versionInfo->releaseNum, minVersionNum, minReleaseNum); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiUtils__checkDatabaseVersion() [INTERNAL] +// Check the Oracle Database version and verify that it is at least at the +// minimum version that is required. +//----------------------------------------------------------------------------- +int dpiUtils__checkDatabaseVersion(dpiConn *conn, int minVersionNum, + int minReleaseNum, dpiError *error) +{ + if (dpiConn__getServerVersion(conn, error) < 0) + return DPI_FAILURE; + if (conn->versionInfo.versionNum < minVersionNum || + (conn->versionInfo.versionNum == minVersionNum && + conn->versionInfo.releaseNum < minReleaseNum)) + return dpiError__set(error, "check Oracle Database version", + DPI_ERR_ORACLE_DB_TOO_OLD, conn->versionInfo.versionNum, + conn->versionInfo.releaseNum, minVersionNum, minReleaseNum); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiUtils__clearMemory() [INTERNAL] +// Method for clearing memory that will not be optimised away by the +// compiler. Simple use of memset() can be optimised away. This routine makes +// use of a volatile pointer which most compilers will avoid optimising away, +// even if the pointer appears to be unused after the call. +//----------------------------------------------------------------------------- +void dpiUtils__clearMemory(void *ptr, size_t length) +{ + volatile unsigned char *temp = (unsigned char *) ptr; + + while (length--) + *temp++ = '\0'; +} + + +//----------------------------------------------------------------------------- +// dpiUtils__freeMemory() [INTERNAL] +// Method for allocating memory which permits tracing and populates the error +// structure in the event of a memory allocation failure. +//----------------------------------------------------------------------------- +void dpiUtils__freeMemory(void *ptr) +{ + if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM) + dpiDebug__print("freed ptr at %p\n", ptr); + free(ptr); +} + + +//----------------------------------------------------------------------------- +// dpiUtils__getAttrStringWithDup() [INTERNAL] +// Get the string attribute from the OCI and duplicate its contents. +//----------------------------------------------------------------------------- +int dpiUtils__getAttrStringWithDup(const char *action, const void *ociHandle, + uint32_t ociHandleType, uint32_t ociAttribute, const char **value, + uint32_t *valueLength, dpiError *error) +{ + char *source, *temp; + + if (dpiOci__attrGet(ociHandle, ociHandleType, (void*) &source, + valueLength, ociAttribute, action, error) < 0) + return DPI_FAILURE; + if (dpiUtils__allocateMemory(1, *valueLength, 0, action, (void**) &temp, + error) < 0) + return DPI_FAILURE; + *value = (const char*) memcpy(temp, source, *valueLength); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiUtils__parseNumberString() [INTERNAL] +// Parse the contents of a string that is supposed to contain a number. The +// number is expected to be in the format (www.json.org): +// - optional negative sign (-) +// - any number of digits but at least one (0-9) +// - an optional decimal point (.) +// - any number of digits but at least one if decimal point specified (0-9) +// - an optional exponent indicator (e or E) +// - an optional exponent sign (+ or -) +// - any number of digits, but at least one if exponent specified (0-9) +// What is returned is an indication of whether the number is negative, what +// the index of the decimal point in the string is and the list of digits +// without the decimal point. Note that OCI doesn't support more than 40 digits +// so if there are more than this amount an error is raised. OCI doesn't +// support larger than 1e126 so check for this value and raise a numeric +// overflow error if found. OCI also doesn't support smaller than 1E-130 so +// check for this value as well and if smaller than that value simply return +// zero. +//----------------------------------------------------------------------------- +int dpiUtils__parseNumberString(const char *value, uint32_t valueLength, + uint16_t charsetId, int *isNegative, int16_t *decimalPointIndex, + uint8_t *numDigits, uint8_t *digits, dpiError *error) +{ + char convertedValue[DPI_NUMBER_AS_TEXT_CHARS], exponentDigits[4]; + uint8_t numExponentDigits, digit; + uint32_t convertedValueLength; + uint16_t *utf16chars, i; + int exponentIsNegative; + const char *endValue; + int16_t exponent; + + // empty strings are not valid numbers + if (valueLength == 0) + return dpiError__set(error, "zero length", DPI_ERR_INVALID_NUMBER); + + // strings longer than the maximum length of a valid number are also + // excluded + if ((charsetId == DPI_CHARSET_ID_UTF16 && + valueLength > DPI_NUMBER_AS_TEXT_CHARS * 2) || + (charsetId != DPI_CHARSET_ID_UTF16 && + valueLength > DPI_NUMBER_AS_TEXT_CHARS)) + return dpiError__set(error, "check length", + DPI_ERR_NUMBER_STRING_TOO_LONG); + + // if value is encoded in UTF-16, convert to single byte encoding first + // check for values that cannot be encoded in a single byte and are + // obviously not part of a valid numeric string + // also verify maximum length of number + if (charsetId == DPI_CHARSET_ID_UTF16) { + utf16chars = (uint16_t*) value; + convertedValue[0] = '\0'; + convertedValueLength = valueLength / 2; + for (i = 0; i < convertedValueLength; i++) { + if (*utf16chars > 127) + return dpiError__set(error, "convert from UTF-16", + DPI_ERR_INVALID_NUMBER); + convertedValue[i] = (char) *utf16chars++; + } + value = convertedValue; + valueLength = convertedValueLength; + } + + // see if first character is a minus sign (number is negative) + endValue = value + valueLength; + *isNegative = (*value == '-'); + if (*isNegative) + value++; + + // scan for digits until the decimal point or exponent indicator is found + *numDigits = 0; + while (value < endValue) { + if (*value == '.' || *value == 'e' || *value == 'E') + break; + if (*value < '0' || *value > '9') + return dpiError__set(error, "check digits before decimal point", + DPI_ERR_INVALID_NUMBER); + digit = (uint8_t) (*value++ - '0'); + if (digit == 0 && *numDigits == 0) + continue; + *digits++ = digit; + (*numDigits)++; + } + *decimalPointIndex = *numDigits; + + // scan for digits following the decimal point, if applicable + if (value < endValue && *value == '.') { + value++; + while (value < endValue) { + if (*value == 'e' || *value == 'E') + break; + if (*value < '0' || *value > '9') + return dpiError__set(error, "check digits after decimal point", + DPI_ERR_INVALID_NUMBER); + digit = (uint8_t) (*value++ - '0'); + if (digit == 0 && *numDigits == 0) { + (*decimalPointIndex)--; + continue; + } + *digits++ = digit; + (*numDigits)++; + } + } + + // handle exponent, if applicable + if (value < endValue && (*value == 'e' || *value == 'E')) { + value++; + exponentIsNegative = 0; + numExponentDigits = 0; + if (value < endValue && (*value == '+' || *value == '-')) { + exponentIsNegative = (*value == '-'); + value++; + } + while (value < endValue) { + if (*value < '0' || *value > '9') + return dpiError__set(error, "check digits in exponent", + DPI_ERR_INVALID_NUMBER); + if (numExponentDigits == 3) + return dpiError__set(error, "check exponent digits > 3", + DPI_ERR_NOT_SUPPORTED); + exponentDigits[numExponentDigits] = *value++; + numExponentDigits++; + } + if (numExponentDigits == 0) + return dpiError__set(error, "no digits in exponent", + DPI_ERR_INVALID_NUMBER); + exponentDigits[numExponentDigits] = '\0'; + exponent = (int16_t) strtol(exponentDigits, NULL, 10); + if (exponentIsNegative) + exponent = -exponent; + *decimalPointIndex += exponent; + } + + // if there is anything left in the string, that indicates an invalid + // number as well + if (value < endValue) + return dpiError__set(error, "check string used", + DPI_ERR_INVALID_NUMBER); + + // strip trailing zeroes + digits--; + while (*numDigits > 0 && *digits-- == 0) + (*numDigits)--; + + // values must be less than 1e126 and greater than 1e-129; the number of + // digits also cannot exceed the maximum precision of Oracle numbers + if (*numDigits > DPI_NUMBER_MAX_DIGITS || *decimalPointIndex > 126 || + *decimalPointIndex < -129) { + return dpiError__set(error, "check value can be represented", + DPI_ERR_NUMBER_NO_REPR); + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiUtils__parseOracleNumber() [INTERNAL] +// Parse the contents of an Oracle number and return its constituent parts +// so that a string can be generated from it easily. +//----------------------------------------------------------------------------- +int dpiUtils__parseOracleNumber(void *oracleValue, int *isNegative, + int16_t *decimalPointIndex, uint8_t *numDigits, uint8_t *digits, + dpiError *error) +{ + uint8_t *source, length, i, byte, digit; + int8_t ociExponent; + + // the first byte of the structure is a length byte which includes the + // exponent and the mantissa bytes + source = (uint8_t*) oracleValue; + length = *source++ - 1; + + // a mantissa length longer than 20 signals corruption of some kind + if (length > 20) + return dpiError__set(error, "check mantissa length", + DPI_ERR_INVALID_OCI_NUMBER); + + // the second byte of the structure is the exponent + // positive numbers have the highest order bit set whereas negative numbers + // have the highest order bit cleared and the bits inverted + ociExponent = (int8_t) *source++; + *isNegative = (ociExponent & 0x80) ? 0 : 1; + if (*isNegative) + ociExponent = ~ociExponent; + ociExponent -= 193; + *decimalPointIndex = ociExponent * 2 + 2; + + // a mantissa length of 0 implies a value of 0 (if positive) + // or -1e126 (if negative) + if (length == 0) { + if (*isNegative) { + *digits = 1; + *decimalPointIndex = 127; + } + else { + *decimalPointIndex = 1; + *digits = 0; + } + *numDigits = 1; + return DPI_SUCCESS; + } + + // check for the trailing 102 byte for negative numbers and if present, + // reduce the number of mantissa digits + if (*isNegative && source[length - 1] == 102) + length--; + + // process the mantissa which are the remaining bytes + // each mantissa byte is a base-100 digit + *numDigits = length * 2; + for (i = 0; i < length; i++) { + byte = *source++; + + // positive numbers have 1 added to them; negative numbers are + // subtracted from the value 101 + if (*isNegative) + byte = 101 - byte; + else byte--; + + // process the first digit; leading zeroes are ignored + digit = (uint8_t) (byte / 10); + if (digit == 0 && i == 0) { + (*numDigits)--; + (*decimalPointIndex)--; + } else if (digit == 10) { + (*numDigits)++; + (*decimalPointIndex)++; + *digits++ = 1; + *digits++ = 0; + } else *digits++ = digit; + + // process the second digit; trailing zeroes are ignored + digit = byte % 10; + if (digit == 0 && i == length - 1) + (*numDigits)--; + else *digits++ = digit; + + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiUtils__setAttributesFromCommonCreateParams() [INTERNAL] +// Set the attributes on the authorization info structure or session handle +// using the specified parameters. +//----------------------------------------------------------------------------- +int dpiUtils__setAttributesFromCommonCreateParams(void *handle, + uint32_t handleType, const dpiCommonCreateParams *params, + dpiError *error) +{ + uint32_t driverNameLength; + const char *driverName; + + if (params->driverName && params->driverNameLength > 0) { + driverName = params->driverName; + driverNameLength = params->driverNameLength; + } else { + driverName = DPI_DEFAULT_DRIVER_NAME; + driverNameLength = (uint32_t) strlen(driverName); + } + if (driverName && driverNameLength > 0 && dpiOci__attrSet(handle, + handleType, (void*) driverName, driverNameLength, + DPI_OCI_ATTR_DRIVER_NAME, "set driver name", error) < 0) + return DPI_FAILURE; + if (params->edition && params->editionLength > 0 && + dpiOci__attrSet(handle, handleType, + (void*) params->edition, params->editionLength, + DPI_OCI_ATTR_EDITION, "set edition", error) < 0) + return DPI_FAILURE; + + return DPI_SUCCESS; +} diff --git a/vendor/github.com/godror/godror/odpi/src/dpiVar.c b/vendor/github.com/godror/godror/odpi/src/dpiVar.c new file mode 100644 index 00000000000..d8cde787c64 --- /dev/null +++ b/vendor/github.com/godror/godror/odpi/src/dpiVar.c @@ -0,0 +1,1813 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. +// This program is free software: you can modify it and/or redistribute it +// under the terms of: +// +// (i) the Universal Permissive License v 1.0 or at your option, any +// later version (http://oss.oracle.com/licenses/upl); and/or +// +// (ii) the Apache License v 2.0. (http://www.apache.org/licenses/LICENSE-2.0) +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// dpiVar.c +// Implementation of variables. +//----------------------------------------------------------------------------- + +#include "dpiImpl.h" + +// forward declarations of internal functions only used in this file +static int dpiVar__initBuffer(dpiVar *var, dpiVarBuffer *buffer, + dpiError *error); +static int dpiVar__setBytesFromDynamicBytes(dpiBytes *bytes, + dpiDynamicBytes *dynBytes, dpiError *error); +static int dpiVar__setBytesFromLob(dpiBytes *bytes, dpiDynamicBytes *dynBytes, + dpiLob *lob, dpiError *error); +static int dpiVar__setFromBytes(dpiVar *var, uint32_t pos, const char *value, + uint32_t valueLength, dpiError *error); +static int dpiVar__setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob, + dpiError *error); +static int dpiVar__setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj, + dpiError *error); +static int dpiVar__setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid, + dpiError *error); +static int dpiVar__setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt, + dpiError *error); +static int dpiVar__validateTypes(const dpiOracleType *oracleType, + dpiNativeTypeNum nativeTypeNum, dpiError *error); + + +//----------------------------------------------------------------------------- +// dpiVar__allocate() [INTERNAL] +// Create a new variable object and return it. In case of error NULL is +// returned. +//----------------------------------------------------------------------------- +int dpiVar__allocate(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, + dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, + int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, + dpiData **data, dpiError *error) +{ + const dpiOracleType *type; + uint32_t sizeInBytes; + dpiVar *tempVar; + + // validate arguments + *var = NULL; + type = dpiOracleType__getFromNum(oracleTypeNum, error); + if (!type) + return DPI_FAILURE; + if (maxArraySize == 0) + return dpiError__set(error, "check max array size", + DPI_ERR_ARRAY_SIZE_ZERO); + if (isArray && !type->canBeInArray) + return dpiError__set(error, "check can be in array", + DPI_ERR_NOT_SUPPORTED); + if (oracleTypeNum == DPI_ORACLE_TYPE_BOOLEAN && + dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 1, + error) < 0) + return DPI_FAILURE; + if (nativeTypeNum != type->defaultNativeTypeNum) { + if (dpiVar__validateTypes(type, nativeTypeNum, error) < 0) + return DPI_FAILURE; + } + + // calculate size in bytes + if (size == 0) + size = 1; + if (type->sizeInBytes) + sizeInBytes = type->sizeInBytes; + else if (sizeIsBytes || !type->isCharacterData) + sizeInBytes = size; + else if (type->charsetForm == DPI_SQLCS_IMPLICIT) + sizeInBytes = size * conn->env->maxBytesPerCharacter; + else sizeInBytes = size * conn->env->nmaxBytesPerCharacter; + + // allocate memory for variable type + if (dpiGen__allocate(DPI_HTYPE_VAR, conn->env, (void**) &tempVar, + error) < 0) + return DPI_FAILURE; + + // basic initialization + tempVar->buffer.maxArraySize = maxArraySize; + if (!isArray) + tempVar->buffer.actualArraySize = maxArraySize; + tempVar->sizeInBytes = sizeInBytes; + if (sizeInBytes > DPI_MAX_BASIC_BUFFER_SIZE) { + tempVar->sizeInBytes = 0; + tempVar->isDynamic = 1; + tempVar->requiresPreFetch = 1; + } + tempVar->type = type; + tempVar->nativeTypeNum = nativeTypeNum; + tempVar->isArray = isArray; + dpiGen__setRefCount(conn, error, 1); + tempVar->conn = conn; + if (objType) { + if (dpiGen__checkHandle(objType, DPI_HTYPE_OBJECT_TYPE, + "check object type", error) < 0) { + dpiVar__free(tempVar, error); + return DPI_FAILURE; + } + dpiGen__setRefCount(objType, error, 1); + tempVar->objectType = objType; + } + + // allocate the data for the variable + if (dpiVar__initBuffer(tempVar, &tempVar->buffer, error) < 0) { + dpiVar__free(tempVar, error); + return DPI_FAILURE; + } + + *var = tempVar; + *data = tempVar->buffer.externalData; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__allocateChunks() [INTERNAL] +// Allocate more chunks for handling dynamic bytes. +//----------------------------------------------------------------------------- +static int dpiVar__allocateChunks(dpiDynamicBytes *dynBytes, dpiError *error) +{ + dpiDynamicBytesChunk *chunks; + uint32_t allocatedChunks; + + allocatedChunks = dynBytes->allocatedChunks + 8; + if (dpiUtils__allocateMemory(allocatedChunks, sizeof(dpiDynamicBytesChunk), + 1, "allocate chunks", (void**) &chunks, error) < 0) + return DPI_FAILURE; + if (dynBytes->chunks) { + memcpy(chunks, dynBytes->chunks, + dynBytes->numChunks * sizeof(dpiDynamicBytesChunk)); + dpiUtils__freeMemory(dynBytes->chunks); + } + dynBytes->chunks = chunks; + dynBytes->allocatedChunks = allocatedChunks; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__allocateDynamicBytes() [INTERNAL] +// Allocate space in the dynamic bytes structure for the specified number of +// bytes. When complete, there will be exactly one allocated chunk of the +// specified size or greater in the dynamic bytes structure. +//----------------------------------------------------------------------------- +static int dpiVar__allocateDynamicBytes(dpiDynamicBytes *dynBytes, + uint32_t size, dpiError *error) +{ + // if an error occurs, none of the original space is valid + dynBytes->numChunks = 0; + + // if there are no chunks at all, make sure some exist + if (dynBytes->allocatedChunks == 0 && + dpiVar__allocateChunks(dynBytes, error) < 0) + return DPI_FAILURE; + + // at this point there should be 0 or 1 chunks as any retrieval that + // resulted in multiple chunks would have been consolidated already + // make sure that chunk has enough space in it + if (size > dynBytes->chunks->allocatedLength) { + if (dynBytes->chunks->ptr) + dpiUtils__freeMemory(dynBytes->chunks->ptr); + dynBytes->chunks->allocatedLength = + (size + DPI_DYNAMIC_BYTES_CHUNK_SIZE - 1) & + ~(DPI_DYNAMIC_BYTES_CHUNK_SIZE - 1); + if (dpiUtils__allocateMemory(1, dynBytes->chunks->allocatedLength, 0, + "allocate chunk", (void**) &dynBytes->chunks->ptr, error) < 0) + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__assignCallbackBuffer() [INTERNAL] +// Assign callback pointers during OCI statement execution. This is used with +// the callack functions used for dynamic binding during DML returning +// statement execution. +//----------------------------------------------------------------------------- +static void dpiVar__assignCallbackBuffer(dpiVar *var, dpiVarBuffer *buffer, + uint32_t index, void **bufpp) +{ + switch (var->type->oracleTypeNum) { + case DPI_ORACLE_TYPE_TIMESTAMP: + case DPI_ORACLE_TYPE_TIMESTAMP_TZ: + case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: + *bufpp = buffer->data.asTimestamp[index]; + break; + case DPI_ORACLE_TYPE_INTERVAL_DS: + case DPI_ORACLE_TYPE_INTERVAL_YM: + *bufpp = buffer->data.asInterval[index]; + break; + case DPI_ORACLE_TYPE_CLOB: + case DPI_ORACLE_TYPE_BLOB: + case DPI_ORACLE_TYPE_NCLOB: + case DPI_ORACLE_TYPE_BFILE: + *bufpp = buffer->data.asLobLocator[index]; + break; + case DPI_ORACLE_TYPE_ROWID: + *bufpp = buffer->data.asRowid[index]; + break; + case DPI_ORACLE_TYPE_STMT: + *bufpp = buffer->data.asStmt[index]; + break; + default: + *bufpp = buffer->data.asBytes + index * var->sizeInBytes; + break; + } +} + + +//----------------------------------------------------------------------------- +// dpiVar__checkArraySize() [INTERNAL] +// Verifies that the array size has not been exceeded. +//----------------------------------------------------------------------------- +static int dpiVar__checkArraySize(dpiVar *var, uint32_t pos, + const char *fnName, dpiError *error) +{ + if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, fnName, error) < 0) + return DPI_FAILURE; + if (pos >= var->buffer.maxArraySize) + return dpiError__set(error, "check array size", + DPI_ERR_INVALID_ARRAY_POSITION, pos, + var->buffer.maxArraySize); + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__convertToLob() [INTERNAL] +// Convert the variable from using dynamic bytes for a long string to using a +// LOB instead. This is needed for PL/SQL which cannot handle more than 32K +// without the use of a LOB. +//----------------------------------------------------------------------------- +int dpiVar__convertToLob(dpiVar *var, dpiError *error) +{ + dpiDynamicBytes *dynBytes; + dpiLob *lob; + uint32_t i; + + // change type based on the original Oracle type + if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_RAW || + var->type->oracleTypeNum == DPI_ORACLE_TYPE_LONG_RAW) + var->type = dpiOracleType__getFromNum(DPI_ORACLE_TYPE_BLOB, error); + else if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_NCHAR) + var->type = dpiOracleType__getFromNum(DPI_ORACLE_TYPE_NCLOB, + error); + else var->type = dpiOracleType__getFromNum(DPI_ORACLE_TYPE_CLOB, + error); + + // adjust attributes and re-initialize buffers + // the dynamic bytes structures will not be removed + var->sizeInBytes = var->type->sizeInBytes; + var->isDynamic = 0; + if (dpiVar__initBuffer(var, &var->buffer, error) < 0) + return DPI_FAILURE; + + // copy any values already set + for (i = 0; i < var->buffer.maxArraySize; i++) { + dynBytes = &var->buffer.dynamicBytes[i]; + lob = var->buffer.references[i].asLOB; + if (dynBytes->numChunks == 0) + continue; + if (dpiLob__setFromBytes(lob, dynBytes->chunks->ptr, + dynBytes->chunks->length, error) < 0) + return DPI_FAILURE; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__copyData() [INTERNAL] +// Copy the data from the source to the target variable at the given array +// position. +//----------------------------------------------------------------------------- +int dpiVar__copyData(dpiVar *var, uint32_t pos, dpiData *sourceData, + dpiError *error) +{ + dpiData *targetData = &var->buffer.externalData[pos]; + + // handle null case + targetData->isNull = sourceData->isNull; + if (sourceData->isNull) + return DPI_SUCCESS; + + // handle copying of value from source to target + switch (var->nativeTypeNum) { + case DPI_NATIVE_TYPE_BYTES: + return dpiVar__setFromBytes(var, pos, + sourceData->value.asBytes.ptr, + sourceData->value.asBytes.length, error); + case DPI_NATIVE_TYPE_LOB: + return dpiVar__setFromLob(var, pos, sourceData->value.asLOB, + error); + case DPI_NATIVE_TYPE_OBJECT: + return dpiVar__setFromObject(var, pos, sourceData->value.asObject, + error); + case DPI_NATIVE_TYPE_STMT: + return dpiVar__setFromStmt(var, pos, sourceData->value.asStmt, + error); + case DPI_NATIVE_TYPE_ROWID: + return dpiVar__setFromRowid(var, pos, sourceData->value.asRowid, + error); + default: + memcpy(targetData, sourceData, sizeof(dpiData)); + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__defineCallback() [INTERNAL] +// Callback which runs during OCI statement execution and allocates the +// buffers required as well as provides that information to the OCI. This is +// intended for handling string and raw columns for which the size is unknown. +// These include LONG, LONG RAW and retrieving CLOB and BLOB as bytes, rather +// than use the LOB API. +//----------------------------------------------------------------------------- +int32_t dpiVar__defineCallback(dpiVar *var, UNUSED void *defnp, uint32_t iter, + void **bufpp, uint32_t **alenpp, UNUSED uint8_t *piecep, void **indpp, + uint16_t **rcodepp) +{ + dpiDynamicBytesChunk *chunk; + dpiDynamicBytes *bytes; + + // allocate more chunks, if necessary + bytes = &var->buffer.dynamicBytes[iter]; + if (bytes->numChunks == bytes->allocatedChunks && + dpiVar__allocateChunks(bytes, var->error) < 0) + return DPI_OCI_ERROR; + + // allocate memory for the chunk, if needed + chunk = &bytes->chunks[bytes->numChunks]; + if (!chunk->ptr) { + chunk->allocatedLength = DPI_DYNAMIC_BYTES_CHUNK_SIZE; + if (dpiUtils__allocateMemory(1, chunk->allocatedLength, 0, + "allocate chunk", (void**) &chunk->ptr, var->error) < 0) + return DPI_OCI_ERROR; + } + + // return chunk to OCI + bytes->numChunks++; + chunk->length = chunk->allocatedLength; + *bufpp = chunk->ptr; + *alenpp = &chunk->length; + *indpp = &(var->buffer.indicator[iter]); + *rcodepp = NULL; + return DPI_OCI_CONTINUE; +} + + +//----------------------------------------------------------------------------- +// dpiVar__extendedPreFetch() [INTERNAL] +// Perform any necessary actions prior to fetching data. +//----------------------------------------------------------------------------- +int dpiVar__extendedPreFetch(dpiVar *var, dpiVarBuffer *buffer, + dpiError *error) +{ + dpiRowid *rowid; + dpiData *data; + dpiStmt *stmt; + dpiLob *lob; + uint32_t i; + + if (var->isDynamic) { + for (i = 0; i < buffer->maxArraySize; i++) + buffer->dynamicBytes[i].numChunks = 0; + return DPI_SUCCESS; + } + + switch (var->type->oracleTypeNum) { + case DPI_ORACLE_TYPE_STMT: + for (i = 0; i < buffer->maxArraySize; i++) { + data = &buffer->externalData[i]; + if (buffer->references[i].asStmt) { + dpiGen__setRefCount(buffer->references[i].asStmt, + error, -1); + buffer->references[i].asStmt = NULL; + } + buffer->data.asStmt[i] = NULL; + data->value.asStmt = NULL; + if (dpiStmt__allocate(var->conn, 0, &stmt, error) < 0) + return DPI_FAILURE; + if (dpiOci__handleAlloc(var->env->handle, &stmt->handle, + DPI_OCI_HTYPE_STMT, "allocate statement", error) < 0) { + dpiStmt__free(stmt, error); + return DPI_FAILURE; + } + if (dpiHandleList__addHandle(var->conn->openStmts, stmt, + &stmt->openSlotNum, error) < 0) { + dpiOci__handleFree(stmt->handle, DPI_OCI_HTYPE_STMT); + stmt->handle = NULL; + dpiStmt__free(stmt, error); + return DPI_FAILURE; + } + buffer->references[i].asStmt = stmt; + stmt->isOwned = 1; + buffer->data.asStmt[i] = stmt->handle; + data->value.asStmt = stmt; + } + break; + case DPI_ORACLE_TYPE_CLOB: + case DPI_ORACLE_TYPE_BLOB: + case DPI_ORACLE_TYPE_NCLOB: + case DPI_ORACLE_TYPE_BFILE: + for (i = 0; i < buffer->maxArraySize; i++) { + data = &buffer->externalData[i]; + if (buffer->references[i].asLOB) { + dpiGen__setRefCount(buffer->references[i].asLOB, + error, -1); + buffer->references[i].asLOB = NULL; + } + buffer->data.asLobLocator[i] = NULL; + data->value.asLOB = NULL; + if (dpiLob__allocate(var->conn, var->type, &lob, error) < 0) + return DPI_FAILURE; + buffer->references[i].asLOB = lob; + buffer->data.asLobLocator[i] = lob->locator; + data->value.asLOB = lob; + if (buffer->dynamicBytes && + dpiOci__lobCreateTemporary(lob, error) < 0) + return DPI_FAILURE; + } + break; + case DPI_ORACLE_TYPE_ROWID: + for (i = 0; i < buffer->maxArraySize; i++) { + data = &buffer->externalData[i]; + if (buffer->references[i].asRowid) { + dpiGen__setRefCount(buffer->references[i].asRowid, + error, -1); + buffer->references[i].asRowid = NULL; + } + buffer->data.asRowid[i] = NULL; + data->value.asRowid = NULL; + if (dpiRowid__allocate(var->conn, &rowid, error) < 0) + return DPI_FAILURE; + buffer->references[i].asRowid = rowid; + buffer->data.asRowid[i] = rowid->handle; + data->value.asRowid = rowid; + } + break; + case DPI_ORACLE_TYPE_OBJECT: + for (i = 0; i < buffer->maxArraySize; i++) { + data = &buffer->externalData[i]; + if (buffer->references[i].asObject) { + dpiGen__setRefCount(buffer->references[i].asObject, + error, -1); + buffer->references[i].asObject = NULL; + } + buffer->data.asObject[i] = NULL; + buffer->objectIndicator[i] = NULL; + data->value.asObject = NULL; + } + break; + default: + break; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__finalizeBuffer() [INTERNAL] +// Finalize buffer used for passing data to/from Oracle. +//----------------------------------------------------------------------------- +static void dpiVar__finalizeBuffer(dpiVar *var, dpiVarBuffer *buffer, + dpiError *error) +{ + dpiDynamicBytes *dynBytes; + uint32_t i, j; + + // free any descriptors that were created + switch (var->type->oracleTypeNum) { + case DPI_ORACLE_TYPE_TIMESTAMP: + dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0], + DPI_OCI_DTYPE_TIMESTAMP); + break; + case DPI_ORACLE_TYPE_TIMESTAMP_TZ: + dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0], + DPI_OCI_DTYPE_TIMESTAMP_TZ); + break; + case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: + dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0], + DPI_OCI_DTYPE_TIMESTAMP_LTZ); + break; + case DPI_ORACLE_TYPE_INTERVAL_DS: + dpiOci__arrayDescriptorFree(&buffer->data.asInterval[0], + DPI_OCI_DTYPE_INTERVAL_DS); + break; + case DPI_ORACLE_TYPE_INTERVAL_YM: + dpiOci__arrayDescriptorFree(&buffer->data.asInterval[0], + DPI_OCI_DTYPE_INTERVAL_YM); + break; + default: + break; + } + + // release any references that were created + if (buffer->references) { + for (i = 0; i < buffer->maxArraySize; i++) { + if (buffer->references[i].asHandle) { + dpiGen__setRefCount(buffer->references[i].asHandle, error, -1); + buffer->references[i].asHandle = NULL; + } + } + dpiUtils__freeMemory(buffer->references); + buffer->references = NULL; + } + + // free any dynamic buffers + if (buffer->dynamicBytes) { + for (i = 0; i < buffer->maxArraySize; i++) { + dynBytes = &buffer->dynamicBytes[i]; + if (dynBytes->allocatedChunks > 0) { + for (j = 0; j < dynBytes->allocatedChunks; j++) { + if (dynBytes->chunks[j].ptr) { + dpiUtils__freeMemory(dynBytes->chunks[j].ptr); + dynBytes->chunks[j].ptr = NULL; + } + } + dpiUtils__freeMemory(dynBytes->chunks); + dynBytes->allocatedChunks = 0; + dynBytes->chunks = NULL; + } + } + dpiUtils__freeMemory(buffer->dynamicBytes); + buffer->dynamicBytes = NULL; + } + + // free other memory allocated + if (buffer->indicator) { + dpiUtils__freeMemory(buffer->indicator); + buffer->indicator = NULL; + } + if (buffer->returnCode) { + dpiUtils__freeMemory(buffer->returnCode); + buffer->returnCode = NULL; + } + if (buffer->actualLength16) { + dpiUtils__freeMemory(buffer->actualLength16); + buffer->actualLength16 = NULL; + } + if (buffer->actualLength32) { + dpiUtils__freeMemory(buffer->actualLength32); + buffer->actualLength32 = NULL; + } + if (buffer->externalData) { + dpiUtils__freeMemory(buffer->externalData); + buffer->externalData = NULL; + } + if (buffer->data.asRaw) { + dpiUtils__freeMemory(buffer->data.asRaw); + buffer->data.asRaw = NULL; + } + if (buffer->objectIndicator) { + dpiUtils__freeMemory(buffer->objectIndicator); + buffer->objectIndicator = NULL; + } + if (buffer->tempBuffer) { + dpiUtils__freeMemory(buffer->tempBuffer); + buffer->tempBuffer = NULL; + } +} + + +//----------------------------------------------------------------------------- +// dpiVar__free() [INTERNAL] +// Free the memory associated with the variable. +//----------------------------------------------------------------------------- +void dpiVar__free(dpiVar *var, dpiError *error) +{ + uint32_t i; + + dpiVar__finalizeBuffer(var, &var->buffer, error); + if (var->dynBindBuffers) { + for (i = 0; i < var->buffer.maxArraySize; i++) + dpiVar__finalizeBuffer(var, &var->dynBindBuffers[i], error); + dpiUtils__freeMemory(var->dynBindBuffers); + var->dynBindBuffers = NULL; + } + if (var->objectType) { + dpiGen__setRefCount(var->objectType, error, -1); + var->objectType = NULL; + } + if (var->conn) { + dpiGen__setRefCount(var->conn, error, -1); + var->conn = NULL; + } + dpiUtils__freeMemory(var); +} + + +//----------------------------------------------------------------------------- +// dpiVar__getValue() [PRIVATE] +// Returns the contents of the variable in the type specified, if possible. +//----------------------------------------------------------------------------- +int dpiVar__getValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, + int inFetch, dpiError *error) +{ + dpiOracleTypeNum oracleTypeNum; + dpiBytes *bytes; + dpiData *data; + uint32_t i; + + // check for dynamic binds first; if they exist, process them instead + if (var->dynBindBuffers && buffer == &var->buffer) { + buffer = &var->dynBindBuffers[pos]; + for (i = 0; i < buffer->maxArraySize; i++) { + if (dpiVar__getValue(var, buffer, i, inFetch, error) < 0) + return DPI_FAILURE; + } + return DPI_SUCCESS; + } + + // check for a NULL value; for objects the indicator is elsewhere + data = &buffer->externalData[pos]; + if (!buffer->objectIndicator) + data->isNull = (buffer->indicator[pos] == DPI_OCI_IND_NULL); + else if (buffer->objectIndicator[pos]) + data->isNull = (*((int16_t*) buffer->objectIndicator[pos]) == + DPI_OCI_IND_NULL); + else data->isNull = 1; + if (data->isNull) { + if (inFetch && var->objectType && var->objectType->isCollection) { + if (dpiOci__objectFree(var->env->handle, + buffer->data.asObject[pos], 1, error) < 0) + return DPI_FAILURE; + if (dpiOci__objectFree(var->env->handle, + buffer->objectIndicator[pos], 1, error) < 0) + return DPI_FAILURE; + } + return DPI_SUCCESS; + } + + // check return code for variable length data + if (buffer->returnCode) { + if (buffer->returnCode[pos] != 0) { + dpiError__set(error, "check return code", DPI_ERR_COLUMN_FETCH, + pos, buffer->returnCode[pos]); + error->buffer->code = buffer->returnCode[pos]; + return DPI_FAILURE; + } + } + + // for 11g, dynamic lengths are 32-bit whereas static lengths are 16-bit + if (buffer->actualLength16 && buffer->actualLength32) + buffer->actualLength16[pos] = (uint16_t) buffer->actualLength32[pos]; + + // transform the various types + oracleTypeNum = var->type->oracleTypeNum; + switch (var->nativeTypeNum) { + case DPI_NATIVE_TYPE_INT64: + case DPI_NATIVE_TYPE_UINT64: + switch (oracleTypeNum) { + case DPI_ORACLE_TYPE_NATIVE_INT: + data->value.asInt64 = buffer->data.asInt64[pos]; + return DPI_SUCCESS; + case DPI_ORACLE_TYPE_NATIVE_UINT: + data->value.asUint64 = buffer->data.asUint64[pos]; + return DPI_SUCCESS; + case DPI_ORACLE_TYPE_NUMBER: + if (var->nativeTypeNum == DPI_NATIVE_TYPE_INT64) + return dpiDataBuffer__fromOracleNumberAsInteger( + &data->value, error, + &buffer->data.asNumber[pos]); + return dpiDataBuffer__fromOracleNumberAsUnsignedInteger( + &data->value, error, &buffer->data.asNumber[pos]); + default: + break; + } + break; + case DPI_NATIVE_TYPE_DOUBLE: + switch (oracleTypeNum) { + case DPI_ORACLE_TYPE_NUMBER: + return dpiDataBuffer__fromOracleNumberAsDouble( + &data->value, error, &buffer->data.asNumber[pos]); + case DPI_ORACLE_TYPE_NATIVE_DOUBLE: + data->value.asDouble = buffer->data.asDouble[pos]; + return DPI_SUCCESS; + case DPI_ORACLE_TYPE_TIMESTAMP: + case DPI_ORACLE_TYPE_TIMESTAMP_TZ: + case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: + return dpiDataBuffer__fromOracleTimestampAsDouble( + &data->value, var->env, error, + buffer->data.asTimestamp[pos]); + default: + break; + } + break; + case DPI_NATIVE_TYPE_BYTES: + bytes = &data->value.asBytes; + switch (oracleTypeNum) { + case DPI_ORACLE_TYPE_VARCHAR: + case DPI_ORACLE_TYPE_NVARCHAR: + case DPI_ORACLE_TYPE_CHAR: + case DPI_ORACLE_TYPE_NCHAR: + case DPI_ORACLE_TYPE_ROWID: + case DPI_ORACLE_TYPE_RAW: + case DPI_ORACLE_TYPE_LONG_VARCHAR: + case DPI_ORACLE_TYPE_LONG_RAW: + if (buffer->dynamicBytes) + return dpiVar__setBytesFromDynamicBytes(bytes, + &buffer->dynamicBytes[pos], error); + if (buffer->actualLength16) + bytes->length = buffer->actualLength16[pos]; + else bytes->length = buffer->actualLength32[pos]; + return DPI_SUCCESS; + case DPI_ORACLE_TYPE_CLOB: + case DPI_ORACLE_TYPE_NCLOB: + case DPI_ORACLE_TYPE_BLOB: + case DPI_ORACLE_TYPE_BFILE: + return dpiVar__setBytesFromLob(bytes, + &buffer->dynamicBytes[pos], + buffer->references[pos].asLOB, error); + case DPI_ORACLE_TYPE_NUMBER: + bytes->length = DPI_NUMBER_AS_TEXT_CHARS; + if (var->env->charsetId == DPI_CHARSET_ID_UTF16) + bytes->length *= 2; + return dpiDataBuffer__fromOracleNumberAsText(&data->value, + var->env, error, &buffer->data.asNumber[pos]); + default: + break; + } + break; + case DPI_NATIVE_TYPE_FLOAT: + data->value.asFloat = buffer->data.asFloat[pos]; + break; + case DPI_NATIVE_TYPE_TIMESTAMP: + if (oracleTypeNum == DPI_ORACLE_TYPE_DATE) + return dpiDataBuffer__fromOracleDate(&data->value, + &buffer->data.asDate[pos]); + return dpiDataBuffer__fromOracleTimestamp(&data->value, var->env, + error, buffer->data.asTimestamp[pos], + oracleTypeNum != DPI_ORACLE_TYPE_TIMESTAMP); + break; + case DPI_NATIVE_TYPE_INTERVAL_DS: + return dpiDataBuffer__fromOracleIntervalDS(&data->value, var->env, + error, buffer->data.asInterval[pos]); + case DPI_NATIVE_TYPE_INTERVAL_YM: + return dpiDataBuffer__fromOracleIntervalYM(&data->value, var->env, + error, buffer->data.asInterval[pos]); + case DPI_NATIVE_TYPE_OBJECT: + data->value.asObject = NULL; + if (!buffer->references[pos].asObject) { + if (dpiObject__allocate(var->objectType, + buffer->data.asObject[pos], + buffer->objectIndicator[pos], NULL, + &buffer->references[pos].asObject, error) < 0) + return DPI_FAILURE; + if (inFetch && var->objectType->isCollection) + buffer->references[pos].asObject->freeIndicator = 1; + } + data->value.asObject = buffer->references[pos].asObject; + break; + case DPI_NATIVE_TYPE_STMT: + data->value.asStmt = buffer->references[pos].asStmt; + break; + case DPI_NATIVE_TYPE_BOOLEAN: + data->value.asBoolean = buffer->data.asBoolean[pos]; + break; + default: + break; + } + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__inBindCallback() [INTERNAL] +// Callback which runs during OCI statement execution and provides buffers to +// OCI for binding data IN. This is not used with DML returning so this method +// does nothing useful except satisfy OCI requirements. +//----------------------------------------------------------------------------- +int32_t dpiVar__inBindCallback(dpiVar *var, UNUSED void *bindp, + UNUSED uint32_t iter, UNUSED uint32_t index, void **bufpp, + uint32_t *alenp, uint8_t *piecep, void **indpp) +{ + dpiDynamicBytes *dynBytes; + + if (var->isDynamic) { + dynBytes = &var->buffer.dynamicBytes[iter]; + if (dynBytes->allocatedChunks == 0) { + *bufpp = NULL; + *alenp = 0; + } else { + *bufpp = dynBytes->chunks->ptr; + *alenp = dynBytes->chunks->length; + } + } else { + dpiVar__assignCallbackBuffer(var, &var->buffer, iter, bufpp); + if (var->buffer.actualLength16) + *alenp = var->buffer.actualLength16[iter]; + else if (var->buffer.actualLength32) + *alenp = var->buffer.actualLength32[iter]; + else *alenp = var->type->sizeInBytes; + } + *piecep = DPI_OCI_ONE_PIECE; + if (var->buffer.objectIndicator) + *indpp = var->buffer.objectIndicator[iter]; + else *indpp = &var->buffer.indicator[iter]; + return DPI_OCI_CONTINUE; +} + + +//----------------------------------------------------------------------------- +// dpiVar__initBuffer() [INTERNAL] +// Initialize buffers necessary for passing data to/from Oracle. +//----------------------------------------------------------------------------- +static int dpiVar__initBuffer(dpiVar *var, dpiVarBuffer *buffer, + dpiError *error) +{ + uint32_t i, tempBufferSize = 0; + unsigned long long dataLength; + dpiBytes *bytes; + + // initialize dynamic buffers for dynamic variables + if (var->isDynamic) { + if (dpiUtils__allocateMemory(buffer->maxArraySize, + sizeof(dpiDynamicBytes), 1, "allocate dynamic bytes", + (void**) &buffer->dynamicBytes, error) < 0) + return DPI_FAILURE; + + // for all other variables, validate length and allocate buffers + } else { + dataLength = (unsigned long long) buffer->maxArraySize * + (unsigned long long) var->sizeInBytes; + if (dataLength > INT_MAX) + return dpiError__set(error, "check max array size", + DPI_ERR_ARRAY_SIZE_TOO_BIG, buffer->maxArraySize); + if (dpiUtils__allocateMemory(1, (size_t) dataLength, 0, + "allocate buffer", (void**) &buffer->data.asRaw, error) < 0) + return DPI_FAILURE; + } + + // allocate the indicator for the variable + // ensure all values start out as null + if (!buffer->indicator) { + if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(int16_t), 0, + "allocate indicator", (void**) &buffer->indicator, error) < 0) + return DPI_FAILURE; + for (i = 0; i < buffer->maxArraySize; i++) + buffer->indicator[i] = DPI_OCI_IND_NULL; + } + + // allocate the actual length buffers for all but dynamic bytes which are + // handled differently; ensure actual length starts out as maximum value + if (!var->isDynamic && !buffer->actualLength16 && + !buffer->actualLength32) { + if (var->env->versionInfo->versionNum < 12 && buffer == &var->buffer) { + if (dpiUtils__allocateMemory(buffer->maxArraySize, + sizeof(uint16_t), 0, "allocate actual length", + (void**) &buffer->actualLength16, error) < 0) + return DPI_FAILURE; + for (i = 0; i < buffer->maxArraySize; i++) + buffer->actualLength16[i] = (uint16_t) var->sizeInBytes; + } else { + if (dpiUtils__allocateMemory(buffer->maxArraySize, + sizeof(uint32_t), 0, "allocate actual length", + (void**) &buffer->actualLength32, error) < 0) + return DPI_FAILURE; + for (i = 0; i < buffer->maxArraySize; i++) + buffer->actualLength32[i] = var->sizeInBytes; + } + } + + // for variable length data, also allocate the return code array + if (var->type->defaultNativeTypeNum == DPI_NATIVE_TYPE_BYTES && + !var->isDynamic && !buffer->returnCode) { + if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(uint16_t), 0, + "allocate return code", (void**) &buffer->returnCode, + error) < 0) + return DPI_FAILURE; + } + + // for numbers transferred to/from Oracle as bytes, allocate an additional + // set of buffers + if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_NUMBER && + var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { + tempBufferSize = DPI_NUMBER_AS_TEXT_CHARS; + if (var->env->charsetId == DPI_CHARSET_ID_UTF16) + tempBufferSize *= 2; + if (!buffer->tempBuffer) { + if (dpiUtils__allocateMemory(buffer->maxArraySize, tempBufferSize, + 0, "allocate temp buffer", (void**) &buffer->tempBuffer, + error) < 0) + return DPI_FAILURE; + } + } + + // allocate the external data array, if needed + if (!buffer->externalData) { + if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(dpiData), 1, + "allocate external data", (void**) &buffer->externalData, + error) < 0) + return DPI_FAILURE; + for (i = 0; i < buffer->maxArraySize; i++) + buffer->externalData[i].isNull = 1; + } + + // for bytes transfers, set encoding and pointers for small strings + if (var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { + for (i = 0; i < buffer->maxArraySize; i++) { + bytes = &buffer->externalData[i].value.asBytes; + if (var->type->charsetForm == DPI_SQLCS_IMPLICIT) + bytes->encoding = var->env->encoding; + else bytes->encoding = var->env->nencoding; + if (buffer->tempBuffer) + bytes->ptr = buffer->tempBuffer + i * tempBufferSize; + else if (!var->isDynamic && !buffer->dynamicBytes) + bytes->ptr = buffer->data.asBytes + i * var->sizeInBytes; + } + } + + // create array of references, if applicable + if (var->type->requiresPreFetch && !var->isDynamic) { + if (dpiUtils__allocateMemory(buffer->maxArraySize, + sizeof(dpiReferenceBuffer), 1, "allocate references", + (void**) &buffer->references, error) < 0) + return DPI_FAILURE; + } + + // perform variable specific initialization + switch (var->type->oracleTypeNum) { + case DPI_ORACLE_TYPE_TIMESTAMP: + return dpiOci__arrayDescriptorAlloc(var->env->handle, + &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP, + buffer->maxArraySize, error); + case DPI_ORACLE_TYPE_TIMESTAMP_TZ: + return dpiOci__arrayDescriptorAlloc(var->env->handle, + &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_TZ, + buffer->maxArraySize, error); + case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: + return dpiOci__arrayDescriptorAlloc(var->env->handle, + &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_LTZ, + buffer->maxArraySize, error); + case DPI_ORACLE_TYPE_INTERVAL_DS: + return dpiOci__arrayDescriptorAlloc(var->env->handle, + &buffer->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_DS, + buffer->maxArraySize, error); + case DPI_ORACLE_TYPE_INTERVAL_YM: + return dpiOci__arrayDescriptorAlloc(var->env->handle, + &buffer->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_YM, + buffer->maxArraySize, error); + break; + case DPI_ORACLE_TYPE_CLOB: + case DPI_ORACLE_TYPE_BLOB: + case DPI_ORACLE_TYPE_NCLOB: + case DPI_ORACLE_TYPE_BFILE: + case DPI_ORACLE_TYPE_STMT: + case DPI_ORACLE_TYPE_ROWID: + return dpiVar__extendedPreFetch(var, buffer, error); + case DPI_ORACLE_TYPE_OBJECT: + if (!var->objectType) + return dpiError__set(error, "check object type", + DPI_ERR_NO_OBJECT_TYPE); + if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(void*), + 0, "allocate object indicator", + (void**) &buffer->objectIndicator, error) < 0) + return DPI_FAILURE; + return dpiVar__extendedPreFetch(var, buffer, error); + default: + break; + } + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__outBindCallback() [INTERNAL] +// Callback which runs during OCI statement execution and allocates the +// buffers required as well as provides that information to the OCI. This is +// intended for use with DML returning only. +//----------------------------------------------------------------------------- +int32_t dpiVar__outBindCallback(dpiVar *var, void *bindp, UNUSED uint32_t iter, + uint32_t index, void **bufpp, uint32_t **alenpp, uint8_t *piecep, + void **indpp, uint16_t **rcodepp) +{ + dpiDynamicBytesChunk *chunk; + uint32_t numRowsReturned; + dpiDynamicBytes *bytes; + dpiVarBuffer *buffer; + + // determine which variable buffer to use + if (!var->dynBindBuffers) { + if (dpiUtils__allocateMemory(var->buffer.maxArraySize, + sizeof(dpiVarBuffer), 1, "allocate DML returning buffers", + (void**) &var->dynBindBuffers, var->error) < 0) + return DPI_FAILURE; + } + buffer = &var->dynBindBuffers[iter]; + + // special processing during first value returned for each iteration + if (index == 0) { + + // determine number of rows returned + if (dpiOci__attrGet(bindp, DPI_OCI_HTYPE_BIND, &numRowsReturned, 0, + DPI_OCI_ATTR_ROWS_RETURNED, "get rows returned", + var->error) < 0) + return DPI_OCI_ERROR; + + // reallocate buffers, if needed + if (numRowsReturned > buffer->maxArraySize) { + dpiVar__finalizeBuffer(var, buffer, var->error); + buffer->maxArraySize = numRowsReturned; + if (dpiVar__initBuffer(var, buffer, var->error) < 0) + return DPI_OCI_ERROR; + } + + // set actual array size to number of rows returned + buffer->actualArraySize = numRowsReturned; + + } + + // handle dynamically allocated strings (multiple piece) + // index is the current index into the chunks + if (var->isDynamic) { + + // allocate more chunks, if necessary + bytes = &buffer->dynamicBytes[index]; + if (*piecep == DPI_OCI_ONE_PIECE) + bytes->numChunks = 0; + if (bytes->numChunks == bytes->allocatedChunks && + dpiVar__allocateChunks(bytes, var->error) < 0) + return DPI_OCI_ERROR; + + // allocate memory for the chunk, if needed + chunk = &bytes->chunks[bytes->numChunks]; + if (!chunk->ptr) { + chunk->allocatedLength = DPI_DYNAMIC_BYTES_CHUNK_SIZE; + if (dpiUtils__allocateMemory(1, chunk->allocatedLength, 0, + "allocate chunk", (void**) &chunk->ptr, var->error) < 0) + return DPI_OCI_ERROR; + } + + // return chunk to OCI + bytes->numChunks++; + chunk->length = chunk->allocatedLength; + *bufpp = chunk->ptr; + *alenpp = &chunk->length; + *indpp = &(buffer->indicator[index]); + *rcodepp = NULL; + + // handle normally allocated variables (one piece) + } else { + + *piecep = DPI_OCI_ONE_PIECE; + if (dpiVar__setValue(var, buffer, index, &buffer->externalData[index], + var->error) < 0) + return DPI_OCI_ERROR; + dpiVar__assignCallbackBuffer(var, buffer, index, bufpp); + if (buffer->actualLength32 || buffer->actualLength16) { + if (!buffer->actualLength32) { + if (dpiUtils__allocateMemory(buffer->maxArraySize, + sizeof(uint32_t), 1, "allocate 11g lengths", + (void**) &buffer->actualLength32, var->error) < 0) + return DPI_OCI_ERROR; + } + buffer->actualLength32[index] = var->sizeInBytes; + *alenpp = &(buffer->actualLength32[index]); + } else if (*alenpp && var->type->sizeInBytes) + **alenpp = var->type->sizeInBytes; + if (buffer->objectIndicator) + *indpp = buffer->objectIndicator[index]; + else *indpp = &(buffer->indicator[index]); + if (buffer->returnCode) + *rcodepp = &buffer->returnCode[index]; + + } + + return DPI_OCI_CONTINUE; +} + + +//----------------------------------------------------------------------------- +// dpiVar__setBytesFromDynamicBytes() [PRIVATE] +// Set the pointer and length in the dpiBytes structure to the values +// retrieved from the database. At this point, if multiple chunks exist, they +// are combined into one. +//----------------------------------------------------------------------------- +static int dpiVar__setBytesFromDynamicBytes(dpiBytes *bytes, + dpiDynamicBytes *dynBytes, dpiError *error) +{ + uint32_t i, totalAllocatedLength; + + // if only one chunk is available, make use of it + if (dynBytes->numChunks == 1) { + bytes->ptr = dynBytes->chunks->ptr; + bytes->length = dynBytes->chunks->length; + return DPI_SUCCESS; + } + + // determine total allocated size of all chunks + totalAllocatedLength = 0; + for (i = 0; i < dynBytes->numChunks; i++) + totalAllocatedLength += dynBytes->chunks[i].allocatedLength; + + // allocate new memory consolidating all of the chunks + if (dpiUtils__allocateMemory(1, totalAllocatedLength, 0, + "allocate consolidated chunk", (void**) &bytes->ptr, error) < 0) + return DPI_FAILURE; + + // copy memory from chunks to consolidated chunk + bytes->length = 0; + for (i = 0; i < dynBytes->numChunks; i++) { + memcpy(bytes->ptr + bytes->length, dynBytes->chunks[i].ptr, + dynBytes->chunks[i].length); + bytes->length += dynBytes->chunks[i].length; + dpiUtils__freeMemory(dynBytes->chunks[i].ptr); + dynBytes->chunks[i].ptr = NULL; + dynBytes->chunks[i].length = 0; + dynBytes->chunks[i].allocatedLength = 0; + } + + // populate first chunk with consolidated information + dynBytes->numChunks = 1; + dynBytes->chunks->ptr = bytes->ptr; + dynBytes->chunks->length = bytes->length; + dynBytes->chunks->allocatedLength = totalAllocatedLength; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__setBytesFromLob() [PRIVATE] +// Populate the dynamic bytes structure with the data from the LOB and then +// populate the bytes structure. +//----------------------------------------------------------------------------- +static int dpiVar__setBytesFromLob(dpiBytes *bytes, dpiDynamicBytes *dynBytes, + dpiLob *lob, dpiError *error) +{ + uint64_t length, lengthInBytes, lengthReadInBytes; + + // determine length of LOB in bytes + if (dpiOci__lobGetLength2(lob, &length, error) < 0) + return DPI_FAILURE; + if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_CLOB) + lengthInBytes = length * lob->env->maxBytesPerCharacter; + else if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB) + lengthInBytes = length * lob->env->nmaxBytesPerCharacter; + else lengthInBytes = length; + + // ensure there is enough space to store the entire LOB value + if (lengthInBytes > UINT_MAX) + return dpiError__set(error, "check max length", DPI_ERR_NOT_SUPPORTED); + if (dpiVar__allocateDynamicBytes(dynBytes, (uint32_t) lengthInBytes, + error) < 0) + return DPI_FAILURE; + + // read data from the LOB + lengthReadInBytes = lengthInBytes; + if (length > 0 && dpiLob__readBytes(lob, 1, length, dynBytes->chunks->ptr, + &lengthReadInBytes, error) < 0) + return DPI_FAILURE; + + dynBytes->chunks->length = (uint32_t) lengthReadInBytes; + bytes->ptr = dynBytes->chunks->ptr; + bytes->length = dynBytes->chunks->length; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__setFromBytes() [PRIVATE] +// Set the value of the variable at the given array position from a byte +// string. The byte string is not retained in any way. A copy will be made into +// buffers allocated by ODPI-C. +//----------------------------------------------------------------------------- +static int dpiVar__setFromBytes(dpiVar *var, uint32_t pos, const char *value, + uint32_t valueLength, dpiError *error) +{ + dpiData *data = &var->buffer.externalData[pos]; + dpiDynamicBytes *dynBytes; + dpiBytes *bytes; + + // for internally used LOBs, write the data directly + if (var->buffer.references) { + data->isNull = 0; + return dpiLob__setFromBytes(var->buffer.references[pos].asLOB, value, + valueLength, error); + } + + // validate the target can accept the input + if ((var->buffer.tempBuffer && + var->env->charsetId == DPI_CHARSET_ID_UTF16 && + valueLength > DPI_NUMBER_AS_TEXT_CHARS * 2) || + (var->buffer.tempBuffer && + var->env->charsetId != DPI_CHARSET_ID_UTF16 && + valueLength > DPI_NUMBER_AS_TEXT_CHARS) || + (!var->buffer.dynamicBytes && !var->buffer.tempBuffer && + valueLength > var->sizeInBytes)) + return dpiError__set(error, "check source length", + DPI_ERR_BUFFER_SIZE_TOO_SMALL, var->sizeInBytes); + + // for dynamic bytes, allocate space as needed + bytes = &data->value.asBytes; + if (var->buffer.dynamicBytes) { + dynBytes = &var->buffer.dynamicBytes[pos]; + if (dpiVar__allocateDynamicBytes(dynBytes, valueLength, error) < 0) + return DPI_FAILURE; + if (valueLength > 0) + memcpy(dynBytes->chunks->ptr, value, valueLength); + dynBytes->numChunks = 1; + dynBytes->chunks->length = valueLength; + bytes->ptr = dynBytes->chunks->ptr; + bytes->length = valueLength; + + // for everything else, space has already been allocated + } else { + bytes->length = valueLength; + if (valueLength > 0) + memcpy(bytes->ptr, value, valueLength); + if (var->type->sizeInBytes == 0) { + if (var->buffer.actualLength32) + var->buffer.actualLength32[pos] = valueLength; + else if (var->buffer.actualLength16) + var->buffer.actualLength16[pos] = (uint16_t) valueLength; + } + if (var->buffer.returnCode) + var->buffer.returnCode[pos] = 0; + } + data->isNull = 0; + + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__setFromLob() [PRIVATE] +// Set the value of the variable at the given array position from a LOB. +// A reference to the LOB is retained by the variable. +//----------------------------------------------------------------------------- +static int dpiVar__setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob, + dpiError *error) +{ + dpiData *data; + + // validate the LOB object + if (dpiGen__checkHandle(lob, DPI_HTYPE_LOB, "check LOB", error) < 0) + return DPI_FAILURE; + + // mark the value as not null + data = &var->buffer.externalData[pos]; + data->isNull = 0; + + // if values are the same, nothing to do + if (var->buffer.references[pos].asLOB == lob) + return DPI_SUCCESS; + + // clear original value, if needed + if (var->buffer.references[pos].asLOB) { + dpiGen__setRefCount(var->buffer.references[pos].asLOB, error, -1); + var->buffer.references[pos].asLOB = NULL; + } + + // add reference to passed object + dpiGen__setRefCount(lob, error, 1); + var->buffer.references[pos].asLOB = lob; + var->buffer.data.asLobLocator[pos] = lob->locator; + data->value.asLOB = lob; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__setFromObject() [PRIVATE] +// Set the value of the variable at the given array position from an object. +// The variable and position are assumed to be valid at this point. A reference +// to the object is retained by the variable. +//----------------------------------------------------------------------------- +static int dpiVar__setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj, + dpiError *error) +{ + dpiData *data; + + // validate the object + if (dpiGen__checkHandle(obj, DPI_HTYPE_OBJECT, "check obj", error) < 0) + return DPI_FAILURE; + if (obj->type->tdo != var->objectType->tdo) + return dpiError__set(error, "check type", DPI_ERR_WRONG_TYPE, + obj->type->schemaLength, obj->type->schema, + obj->type->nameLength, obj->type->name, + var->objectType->schemaLength, var->objectType->schema, + var->objectType->nameLength, var->objectType->name); + + // mark the value as not null + data = &var->buffer.externalData[pos]; + data->isNull = 0; + + // if values are the same, nothing to do + if (var->buffer.references[pos].asObject == obj) + return DPI_SUCCESS; + + // clear original value, if needed + if (var->buffer.references[pos].asObject) { + dpiGen__setRefCount(var->buffer.references[pos].asObject, error, -1); + var->buffer.references[pos].asObject = NULL; + } + + // add reference to passed object + dpiGen__setRefCount(obj, error, 1); + var->buffer.references[pos].asObject = obj; + var->buffer.data.asObject[pos] = obj->instance; + var->buffer.objectIndicator[pos] = obj->indicator; + data->value.asObject = obj; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__setFromRowid() [PRIVATE] +// Set the value of the variable at the given array position from a rowid. +// A reference to the rowid is retained by the variable. +//----------------------------------------------------------------------------- +static int dpiVar__setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid, + dpiError *error) +{ + dpiData *data; + + // validate the rowid + if (dpiGen__checkHandle(rowid, DPI_HTYPE_ROWID, "check rowid", error) < 0) + return DPI_FAILURE; + + // mark the value as not null + data = &var->buffer.externalData[pos]; + data->isNull = 0; + + // if values are the same, nothing to do + if (var->buffer.references[pos].asRowid == rowid) + return DPI_SUCCESS; + + // clear original value, if needed + if (var->buffer.references[pos].asRowid) { + dpiGen__setRefCount(var->buffer.references[pos].asRowid, error, -1); + var->buffer.references[pos].asRowid = NULL; + } + + // add reference to passed object + dpiGen__setRefCount(rowid, error, 1); + var->buffer.references[pos].asRowid = rowid; + var->buffer.data.asRowid[pos] = rowid->handle; + data->value.asRowid = rowid; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__setFromStmt() [PRIVATE] +// Set the value of the variable at the given array position from a +// statement. A reference to the statement is retained by the variable. +//----------------------------------------------------------------------------- +static int dpiVar__setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt, + dpiError *error) +{ + dpiData *data; + uint32_t i; + + // validate the statement + if (dpiGen__checkHandle(stmt, DPI_HTYPE_STMT, "check stmt", error) < 0) + return DPI_FAILURE; + + // prevent attempts to bind a statement to itself + for (i = 0; i < stmt->numBindVars; i++) { + if (stmt->bindVars[i].var == var) + return dpiError__set(error, "bind to self", DPI_ERR_NOT_SUPPORTED); + } + + // mark the value as not null + data = &var->buffer.externalData[pos]; + data->isNull = 0; + + // if values are the same, nothing to do + if (var->buffer.references[pos].asStmt == stmt) + return DPI_SUCCESS; + + // clear original value, if needed + if (var->buffer.references[pos].asStmt) { + dpiGen__setRefCount(var->buffer.references[pos].asStmt, error, -1); + var->buffer.references[pos].asStmt = NULL; + } + + // add reference to passed object + dpiGen__setRefCount(stmt, error, 1); + var->buffer.references[pos].asStmt = stmt; + var->buffer.data.asStmt[pos] = stmt->handle; + data->value.asStmt = stmt; + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__setValue() [PRIVATE] +// Sets the contents of the variable using the type specified, if possible. +//----------------------------------------------------------------------------- +int dpiVar__setValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, + dpiData *data, dpiError *error) +{ + dpiOracleTypeNum oracleTypeNum; + dpiObject *obj; + + // if value is null, no need to proceed further + // however, when binding objects a value MUST be present or OCI will + // segfault! + if (data->isNull) { + buffer->indicator[pos] = DPI_OCI_IND_NULL; + if (buffer->objectIndicator && !buffer->data.asObject[pos]) { + if (dpiObject__allocate(var->objectType, NULL, NULL, NULL, &obj, + error) < 0) + return DPI_FAILURE; + buffer->references[pos].asObject = obj; + data->value.asObject = obj; + buffer->data.asObject[pos] = obj->instance; + buffer->objectIndicator[pos] = obj->indicator; + if (buffer->objectIndicator[pos]) + *((int16_t*) buffer->objectIndicator[pos]) = DPI_OCI_IND_NULL; + } + return DPI_SUCCESS; + } + + // transform the various types + buffer->indicator[pos] = DPI_OCI_IND_NOTNULL; + oracleTypeNum = var->type->oracleTypeNum; + switch (var->nativeTypeNum) { + case DPI_NATIVE_TYPE_INT64: + case DPI_NATIVE_TYPE_UINT64: + switch (oracleTypeNum) { + case DPI_ORACLE_TYPE_NATIVE_INT: + buffer->data.asInt64[pos] = data->value.asInt64; + return DPI_SUCCESS; + case DPI_ORACLE_TYPE_NATIVE_UINT: + buffer->data.asUint64[pos] = data->value.asUint64; + return DPI_SUCCESS; + case DPI_ORACLE_TYPE_NUMBER: + if (var->nativeTypeNum == DPI_NATIVE_TYPE_INT64) + return dpiDataBuffer__toOracleNumberFromInteger( + &data->value, error, + &buffer->data.asNumber[pos]); + return dpiDataBuffer__toOracleNumberFromUnsignedInteger( + &data->value, error, &buffer->data.asNumber[pos]); + default: + break; + } + break; + case DPI_NATIVE_TYPE_FLOAT: + buffer->data.asFloat[pos] = data->value.asFloat; + return DPI_SUCCESS; + case DPI_NATIVE_TYPE_DOUBLE: + switch (oracleTypeNum) { + case DPI_ORACLE_TYPE_NATIVE_DOUBLE: + buffer->data.asDouble[pos] = data->value.asDouble; + return DPI_SUCCESS; + case DPI_ORACLE_TYPE_NUMBER: + return dpiDataBuffer__toOracleNumberFromDouble( + &data->value, error, &buffer->data.asNumber[pos]); + case DPI_ORACLE_TYPE_DATE: + return dpiDataBuffer__toOracleDateFromDouble( + &data->value, var->env, error, + &buffer->data.asDate[pos]); + case DPI_ORACLE_TYPE_TIMESTAMP: + case DPI_ORACLE_TYPE_TIMESTAMP_TZ: + case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: + return dpiDataBuffer__toOracleTimestampFromDouble( + &data->value, var->env, error, + buffer->data.asTimestamp[pos]); + default: + break; + } + break; + case DPI_NATIVE_TYPE_BYTES: + if (oracleTypeNum == DPI_ORACLE_TYPE_NUMBER) + return dpiDataBuffer__toOracleNumberFromText(&data->value, + var->env, error, &buffer->data.asNumber[pos]); + if (buffer->actualLength32) + buffer->actualLength32[pos] = data->value.asBytes.length; + else if (buffer->actualLength16) + buffer->actualLength16[pos] = + (uint16_t) data->value.asBytes.length; + if (buffer->returnCode) + buffer->returnCode[pos] = 0; + break; + case DPI_NATIVE_TYPE_TIMESTAMP: + if (oracleTypeNum == DPI_ORACLE_TYPE_DATE) + return dpiDataBuffer__toOracleDate(&data->value, + &buffer->data.asDate[pos]); + else if (oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP) + return dpiDataBuffer__toOracleTimestamp(&data->value, + var->env, error, buffer->data.asTimestamp[pos], 0); + else if (oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_TZ || + oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_LTZ) + return dpiDataBuffer__toOracleTimestamp(&data->value, + var->env, error, buffer->data.asTimestamp[pos], 1); + break; + case DPI_NATIVE_TYPE_INTERVAL_DS: + return dpiDataBuffer__toOracleIntervalDS(&data->value, var->env, + error, buffer->data.asInterval[pos]); + case DPI_NATIVE_TYPE_INTERVAL_YM: + return dpiDataBuffer__toOracleIntervalYM(&data->value, var->env, + error, buffer->data.asInterval[pos]); + case DPI_NATIVE_TYPE_BOOLEAN: + buffer->data.asBoolean[pos] = data->value.asBoolean; + return DPI_SUCCESS; + default: + break; + } + return DPI_SUCCESS; +} + + +//----------------------------------------------------------------------------- +// dpiVar__validateTypes() [PRIVATE] +// Validate that the Oracle type and the native type are compatible with +// each other when the native type is not already the default native type. +//----------------------------------------------------------------------------- +static int dpiVar__validateTypes(const dpiOracleType *oracleType, + dpiNativeTypeNum nativeTypeNum, dpiError *error) +{ + switch (oracleType->oracleTypeNum) { + case DPI_ORACLE_TYPE_DATE: + case DPI_ORACLE_TYPE_TIMESTAMP: + case DPI_ORACLE_TYPE_TIMESTAMP_TZ: + case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: + if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) + return DPI_SUCCESS; + break; + case DPI_ORACLE_TYPE_NUMBER: + if (nativeTypeNum == DPI_NATIVE_TYPE_INT64 || + nativeTypeNum == DPI_NATIVE_TYPE_UINT64 || + nativeTypeNum == DPI_NATIVE_TYPE_BYTES) + return DPI_SUCCESS; + break; + default: + break; + } + return dpiError__set(error, "validate types", DPI_ERR_UNHANDLED_CONVERSION, + oracleType->oracleTypeNum, nativeTypeNum); +} + + +//----------------------------------------------------------------------------- +// dpiVar_addRef() [PUBLIC] +// Add a reference to the variable. +//----------------------------------------------------------------------------- +int dpiVar_addRef(dpiVar *var) +{ + return dpiGen__addRef(var, DPI_HTYPE_VAR, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiVar_copyData() [PUBLIC] +// Copy the data from the source variable to the target variable at the given +// array position. The variables must use the same native type. If the +// variables contain variable length data, the source length must not exceed +// the target allocated memory. +//----------------------------------------------------------------------------- +int dpiVar_copyData(dpiVar *var, uint32_t pos, dpiVar *sourceVar, + uint32_t sourcePos) +{ + dpiData *sourceData; + dpiError error; + int status; + + if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + if (dpiGen__checkHandle(sourceVar, DPI_HTYPE_VAR, "check source var", + &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + if (sourcePos >= sourceVar->buffer.maxArraySize) { + dpiError__set(&error, "check source size", + DPI_ERR_INVALID_ARRAY_POSITION, sourcePos, + sourceVar->buffer.maxArraySize); + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + } + if (var->nativeTypeNum != sourceVar->nativeTypeNum) { + dpiError__set(&error, "check types match", DPI_ERR_NOT_SUPPORTED); + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + } + sourceData = &sourceVar->buffer.externalData[sourcePos]; + status = dpiVar__copyData(var, pos, sourceData, &error); + return dpiGen__endPublicFn(var, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiVar_getNumElementsInArray() [PUBLIC] +// Return the actual number of elements in the array. This value is only +// relevant if the variable is bound as an array. +//----------------------------------------------------------------------------- +int dpiVar_getNumElementsInArray(dpiVar *var, uint32_t *numElements) +{ + dpiError error; + + if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(var, numElements) + if (var->dynBindBuffers) + *numElements = var->dynBindBuffers->actualArraySize; + else *numElements = var->buffer.actualArraySize; + return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); +} + +//----------------------------------------------------------------------------- +// dpiVar_getReturnedData() [PUBLIC] +// Return a pointer to the array of dpiData structures allocated for the +// given row that have been returned by a DML returning statement. The number +// of returned rows is also provided. If the bind variable had no data +// returned, the number of rows returned will be 0 and the pointer to the array +// of dpiData structures will be NULL. This will also be the case if the +// variable was only bound IN or was not bound to a DML returning statement. +// There is no way to differentiate between the two. +//----------------------------------------------------------------------------- +int dpiVar_getReturnedData(dpiVar *var, uint32_t pos, uint32_t *numElements, + dpiData **data) +{ + dpiError error; + + if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(var, numElements) + DPI_CHECK_PTR_NOT_NULL(var, data) + if (var->dynBindBuffers) { + *numElements = var->dynBindBuffers[pos].actualArraySize; + *data = var->dynBindBuffers[pos].externalData; + } else { + *numElements = 0; + *data = NULL; + } + return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); +} + + + +//----------------------------------------------------------------------------- +// dpiVar_getSizeInBytes() [PUBLIC] +// Returns the size in bytes of the buffer allocated for the variable. +//----------------------------------------------------------------------------- +int dpiVar_getSizeInBytes(dpiVar *var, uint32_t *sizeInBytes) +{ + dpiError error; + + if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + DPI_CHECK_PTR_NOT_NULL(var, sizeInBytes) + *sizeInBytes = var->sizeInBytes; + return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); +} + + +//----------------------------------------------------------------------------- +// dpiVar_release() [PUBLIC] +// Release a reference to the variable. +//----------------------------------------------------------------------------- +int dpiVar_release(dpiVar *var) +{ + return dpiGen__release(var, DPI_HTYPE_VAR, __func__); +} + + +//----------------------------------------------------------------------------- +// dpiVar_setFromBytes() [PUBLIC] +// Set the value of the variable at the given array position from a byte +// string. Checks on the array position, the size of the string and the type of +// variable will be made. The byte string is not retained in any way. A copy +// will be made into buffers allocated by ODPI-C. +//----------------------------------------------------------------------------- +int dpiVar_setFromBytes(dpiVar *var, uint32_t pos, const char *value, + uint32_t valueLength) +{ + dpiError error; + int status; + + if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + DPI_CHECK_PTR_AND_LENGTH(var, value) + if (var->nativeTypeNum != DPI_NATIVE_TYPE_BYTES && + var->nativeTypeNum != DPI_NATIVE_TYPE_LOB) { + dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + } + if (valueLength > DPI_MAX_VAR_BUFFER_SIZE) { + dpiError__set(&error, "check buffer", DPI_ERR_BUFFER_SIZE_TOO_LARGE, + valueLength, DPI_MAX_VAR_BUFFER_SIZE); + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + } + status = dpiVar__setFromBytes(var, pos, value, valueLength, &error); + return dpiGen__endPublicFn(var, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiVar_setFromLob() [PUBLIC] +// Set the value of the variable at the given array position from a LOB. +// Checks on the array position and the validity of the passed handle. A +// reference to the LOB is retained by the variable. +//----------------------------------------------------------------------------- +int dpiVar_setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob) +{ + dpiError error; + int status; + + if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + if (var->nativeTypeNum != DPI_NATIVE_TYPE_LOB) { + dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + } + status = dpiVar__setFromLob(var, pos, lob, &error); + return dpiGen__endPublicFn(var, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiVar_setFromObject() [PUBLIC] +// Set the value of the variable at the given array position from an object. +// Checks on the array position and the validity of the passed handle. A +// reference to the object is retained by the variable. +//----------------------------------------------------------------------------- +int dpiVar_setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj) +{ + dpiError error; + int status; + + if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + if (var->nativeTypeNum != DPI_NATIVE_TYPE_OBJECT) { + dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + } + status = dpiVar__setFromObject(var, pos, obj, &error); + return dpiGen__endPublicFn(var, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiVar_setFromRowid() [PUBLIC] +// Set the value of the variable at the given array position from a rowid. +// Checks on the array position and the validity of the passed handle. A +// reference to the rowid is retained by the variable. +//----------------------------------------------------------------------------- +int dpiVar_setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid) +{ + dpiError error; + int status; + + if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + if (var->nativeTypeNum != DPI_NATIVE_TYPE_ROWID) { + dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + } + status = dpiVar__setFromRowid(var, pos, rowid, &error); + return dpiGen__endPublicFn(var, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiVar_setFromStmt() [PUBLIC] +// Set the value of the variable at the given array position from a +// statement. Checks on the array position and the validity of the passed +// handle. A reference to the statement is retained by the variable. +//----------------------------------------------------------------------------- +int dpiVar_setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt) +{ + dpiError error; + int status; + + if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + if (var->nativeTypeNum != DPI_NATIVE_TYPE_STMT) { + dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + } + status = dpiVar__setFromStmt(var, pos, stmt, &error); + return dpiGen__endPublicFn(var, status, &error); +} + + +//----------------------------------------------------------------------------- +// dpiVar_setNumElementsInArray() [PUBLIC] +// Set the number of elements in the array (different from the number of +// allocated elements). +//----------------------------------------------------------------------------- +int dpiVar_setNumElementsInArray(dpiVar *var, uint32_t numElements) +{ + dpiError error; + + if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, &error) < 0) + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + if (numElements > var->buffer.maxArraySize) { + dpiError__set(&error, "check num elements", + DPI_ERR_ARRAY_SIZE_TOO_SMALL, var->buffer.maxArraySize); + return dpiGen__endPublicFn(var, DPI_FAILURE, &error); + } + var->buffer.actualArraySize = numElements; + return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); +} diff --git a/vendor/github.com/tsg/go-daemon/src/god.c b/vendor/github.com/tsg/go-daemon/src/god.c new file mode 100644 index 00000000000..7f63e081efd --- /dev/null +++ b/vendor/github.com/tsg/go-daemon/src/god.c @@ -0,0 +1,313 @@ +// Copyright 2013-2014 Alexandre Fiori +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +void usage() { + printf( + "Use: god [options] [--] program [arguments]\n" + "Options:\n" + "-h --help show this help and exit\n" + "-v --version show version and exit\n" + "-f --foreground run in foreground\n" + "-n --nohup make the program immune to SIGHUP\n" + "-l --logfile FILE write the program's stdout and stderr to FILE\n" + "-p --pidfile FILE write pid to FILE\n" + "-r --rundir DIR switch to DIR before executing the program\n" + "-u --user USER switch to USER before executing the program\n" + "-g --group GROUP switch to GROUP before executing the program\n" + "\nThe program's output go to a blackhole if no logfile is set.\n" + "Log files are recycled on SIGHUP.\n" + ); + exit(1); +} + +static int nohup = 0; +static int logfd[2]; // pipe +static pid_t childpid = 0; +static FILE *logfp = NULL; +static FILE *pidfp = NULL; +static char logfile[PATH_MAX]; +static char pidfile[PATH_MAX]; +static char linebuf[1024]; +static struct passwd *pwd = NULL; +static struct group *grp = NULL; +static pthread_mutex_t logger_mutex; + +void daemon_main(int optind, char **argv); +void *logger_thread(void *cmdname); +void sighup(int signum); +void sigfwd(int signum); + +int main(int argc, char **argv) { + char rundir[PATH_MAX]; + char user[64]; + char group[64]; + int foreground = 0; + struct stat exec_stat; + + memset(logfile, 0, sizeof logfile); + memset(pidfile, 0, sizeof pidfile); + memset(rundir, 0, sizeof rundir); + memset(user, 0, sizeof user); + memset(group, 0, sizeof group); + + static struct option opts[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { "foreground", no_argument, NULL, 'f' }, + { "nohup", no_argument, NULL, 'n' }, + { "logfile", required_argument, NULL, 'l' }, + { "pidfile", required_argument, NULL, 'p' }, + { "rundir", required_argument, NULL, 'r' }, + { "user", required_argument, NULL, 'u' }, + { "group", required_argument, NULL, 'g' }, + { NULL, 0, NULL, 0 }, + }; + + int ch; + while (1) { + ch = getopt_long(argc, argv, "l:p:r:u:g:hvfns", opts, NULL); + if (ch == -1) + break; + + switch (ch) { + case 'v': + printf("Go daemon v1.2\n"); + printf("http://github.com/fiorix/go-daemon\n"); + return 0; + case 'f': + foreground = 1; + break; + case 'n': + nohup = 1; + break; + case 'l': + strncpy(logfile, optarg, sizeof logfile - 1); + break; + case 'p': + strncpy(pidfile, optarg, sizeof pidfile - 1); + break; + case 'r': + strncpy(rundir, optarg, sizeof rundir - 1); + break; + case 'u': + strncpy(user, optarg, sizeof user - 1); + break; + case 'g': + strncpy(group, optarg, sizeof group - 1); + break; + default: + usage(); + } + } + + // utility is expected to be argv's leftovers. + if (optind >= argc) + usage(); + + if (*rundir != 0 && chdir(rundir) == -1) { + perror("failed to switch to rundir"); + return 1; + } + + if (*user != 0 && (pwd = getpwnam(user)) == NULL) { + fprintf(stderr, "failed to switch to user %s: %s\n", + user, strerror(errno)); + return 1; + } + + if (*group != 0 && (grp = getgrnam(group)) == NULL) { + fprintf(stderr, "failed to switch to group %s: %s\n", + group, strerror(errno)); + return 1; + } + + if (*logfile != 0 && (logfp = fopen(logfile, "a")) == NULL) { + perror("failed to open logfile"); + return 1; + } + if (logfp) + setvbuf(logfp, linebuf, _IOLBF, sizeof linebuf); + + if (*pidfile != 0 && (pidfp = fopen(pidfile, "w+")) == NULL) { + perror("failed to open pidfile"); + return 1; + } + + if (grp != NULL && setegid(grp->gr_gid) == -1) { + fprintf(stderr, "failed to switch to group %s: %s\n", + group, strerror(errno)); + return 1; + } + + if (pwd != NULL && seteuid(pwd->pw_uid) == -1) { + fprintf(stderr, "failed to switch to user %s: %s\n", + user, strerror(errno)); + return 1; + } + + if (stat(argv[optind], &exec_stat) < 0) { + fprintf(stderr, "failed to stat %s: %s\n", + argv[optind], strerror(errno)); + return 1; + } + if (!(exec_stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { + fprintf(stderr, "permission denied: %s\n", + argv[optind]); + return 1; + } + + if (foreground) { + daemon_main(optind, argv); + } else { + // Daemonize. + pid_t pid = fork(); + if (pid) { + waitpid(pid, NULL, 0); + } else if (!pid) { + if ((pid = fork())) { + exit(0); + } else if (!pid) { + close(0); + close(1); + close(2); + daemon_main(optind, argv); + } else { + perror("fork"); + exit(1); + } + } else { + perror("fork"); + exit(1); + } + } + + return 0; +} + +void daemon_main(int optind, char **argv) { + if (pidfp) { + fprintf(pidfp, "%d\n", getpid()); + fclose(pidfp); + } + // Fwd all signals to the child, except SIGHUP. + int signum; + for (signum = 1; signum < 33; signum++) { + if (signal(signum, sigfwd) == SIG_IGN) + signal(signum, SIG_IGN); + } + signal(SIGHUP, sighup); + pipe(logfd); + if ((childpid = fork())) { + close(logfd[1]); + pthread_t logth; + pthread_create(&logth, NULL, logger_thread, argv[optind]); + waitpid(childpid, NULL, 0); + pthread_join(logth, NULL); + } else if (!childpid) { + close(logfd[0]); + close(0); + close(1); + close(2); + dup2(logfd[1], 1); + dup2(logfd[1], 2); + execvp(argv[optind], argv + optind); + printf("\x1b%s", strerror(errno)); + fflush(stdout); + close(logfd[1]); + close(1); + close(2); + } else { + perror("fork"); + exit(1); + } + if (pidfp) + unlink(pidfile); +} + +void *logger_thread(void *cmdname) { + int n; + char buf[4096]; + int has_read = 0; + + while(1) { + // read() will fail when the child process fails + // to execute or dies, and closes its terminal. + // This is what terminates this thread and therefore + // the main thread can move along. + n = read(logfd[0], buf, sizeof buf); + if (n <= 0) + break; + + buf[n] = 0; + if (!has_read) { + has_read = 1; + if (*buf == '\x1b') { + char *p = buf; + printf("%s: %s\n", (char *) cmdname, ++p); + close(logfd[0]); + break; + } + } + + pthread_mutex_lock(&logger_mutex); + if (logfp) { + fwrite(buf, 1, n, logfp); + //fflush(logfp); + } + pthread_mutex_unlock(&logger_mutex); + } + + return NULL; +} + +void sighup(int signum) { + if (pwd != NULL) { + seteuid(getuid()); + } + if (grp != NULL) { + setegid(getgid()); + } + pthread_mutex_lock(&logger_mutex); + if (logfp) { + FILE *fp = fopen(logfile, "a"); + if (fp != NULL) { + fclose(logfp); + logfp = fp; + setvbuf(logfp, linebuf, _IOLBF, sizeof linebuf); + } + } + if (grp != NULL) { + setegid(grp->gr_gid); + } + if (pwd != NULL) { + seteuid(pwd->pw_uid); + } + pthread_mutex_unlock(&logger_mutex); + if (!nohup && childpid) // nonohup :~ + kill(childpid, signum); +} + +void sigfwd(int signum) { + if (childpid) + kill(childpid, signum); +} diff --git a/vendor/github.com/yuin/gopher-lua/parse/Makefile b/vendor/github.com/yuin/gopher-lua/parse/Makefile deleted file mode 100644 index b5b69096086..00000000000 --- a/vendor/github.com/yuin/gopher-lua/parse/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -all : parser.go - -parser.go : parser.go.y - go tool yacc -o $@ parser.go.y; [ -f y.output ] && ( rm -f y.output ) diff --git a/vendor/github.com/yuin/gopher-lua/parse/parser.go.y b/vendor/github.com/yuin/gopher-lua/parse/parser.go.y deleted file mode 100644 index 956133db292..00000000000 --- a/vendor/github.com/yuin/gopher-lua/parse/parser.go.y +++ /dev/null @@ -1,524 +0,0 @@ -%{ -package parse - -import ( - "github.com/yuin/gopher-lua/ast" -) -%} -%type chunk -%type chunk1 -%type block -%type stat -%type elseifs -%type laststat -%type funcname -%type funcname1 -%type varlist -%type var -%type namelist -%type exprlist -%type expr -%type string -%type prefixexp -%type functioncall -%type afunctioncall -%type args -%type function -%type funcbody -%type parlist -%type tableconstructor -%type fieldlist -%type field -%type fieldsep - -%union { - token ast.Token - - stmts []ast.Stmt - stmt ast.Stmt - - funcname *ast.FuncName - funcexpr *ast.FunctionExpr - - exprlist []ast.Expr - expr ast.Expr - - fieldlist []*ast.Field - field *ast.Field - fieldsep string - - namelist []string - parlist *ast.ParList -} - -/* Reserved words */ -%token TAnd TBreak TDo TElse TElseIf TEnd TFalse TFor TFunction TIf TIn TLocal TNil TNot TOr TReturn TRepeat TThen TTrue TUntil TWhile - -/* Literals */ -%token TEqeq TNeq TLte TGte T2Comma T3Comma TIdent TNumber TString '{' '(' - -/* Operators */ -%left TOr -%left TAnd -%left '>' '<' TGte TLte TEqeq TNeq -%right T2Comma -%left '+' '-' -%left '*' '/' '%' -%right UNARY /* not # -(unary) */ -%right '^' - -%% - -chunk: - chunk1 { - $$ = $1 - if l, ok := yylex.(*Lexer); ok { - l.Stmts = $$ - } - } | - chunk1 laststat { - $$ = append($1, $2) - if l, ok := yylex.(*Lexer); ok { - l.Stmts = $$ - } - } | - chunk1 laststat ';' { - $$ = append($1, $2) - if l, ok := yylex.(*Lexer); ok { - l.Stmts = $$ - } - } - -chunk1: - { - $$ = []ast.Stmt{} - } | - chunk1 stat { - $$ = append($1, $2) - } | - chunk1 ';' { - $$ = $1 - } - -block: - chunk { - $$ = $1 - } - -stat: - varlist '=' exprlist { - $$ = &ast.AssignStmt{Lhs: $1, Rhs: $3} - $$.SetLine($1[0].Line()) - } | - /* 'stat = functioncal' causes a reduce/reduce conflict */ - prefixexp { - if _, ok := $1.(*ast.FuncCallExpr); !ok { - yylex.(*Lexer).Error("parse error") - } else { - $$ = &ast.FuncCallStmt{Expr: $1} - $$.SetLine($1.Line()) - } - } | - TDo block TEnd { - $$ = &ast.DoBlockStmt{Stmts: $2} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($3.Pos.Line) - } | - TWhile expr TDo block TEnd { - $$ = &ast.WhileStmt{Condition: $2, Stmts: $4} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($5.Pos.Line) - } | - TRepeat block TUntil expr { - $$ = &ast.RepeatStmt{Condition: $4, Stmts: $2} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($4.Line()) - } | - TIf expr TThen block elseifs TEnd { - $$ = &ast.IfStmt{Condition: $2, Then: $4} - cur := $$ - for _, elseif := range $5 { - cur.(*ast.IfStmt).Else = []ast.Stmt{elseif} - cur = elseif - } - $$.SetLine($1.Pos.Line) - $$.SetLastLine($6.Pos.Line) - } | - TIf expr TThen block elseifs TElse block TEnd { - $$ = &ast.IfStmt{Condition: $2, Then: $4} - cur := $$ - for _, elseif := range $5 { - cur.(*ast.IfStmt).Else = []ast.Stmt{elseif} - cur = elseif - } - cur.(*ast.IfStmt).Else = $7 - $$.SetLine($1.Pos.Line) - $$.SetLastLine($8.Pos.Line) - } | - TFor TIdent '=' expr ',' expr TDo block TEnd { - $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Stmts: $8} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($9.Pos.Line) - } | - TFor TIdent '=' expr ',' expr ',' expr TDo block TEnd { - $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Step:$8, Stmts: $10} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($11.Pos.Line) - } | - TFor namelist TIn exprlist TDo block TEnd { - $$ = &ast.GenericForStmt{Names:$2, Exprs:$4, Stmts: $6} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($7.Pos.Line) - } | - TFunction funcname funcbody { - $$ = &ast.FuncDefStmt{Name: $2, Func: $3} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($3.LastLine()) - } | - TLocal TFunction TIdent funcbody { - $$ = &ast.LocalAssignStmt{Names:[]string{$3.Str}, Exprs: []ast.Expr{$4}} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($4.LastLine()) - } | - TLocal namelist '=' exprlist { - $$ = &ast.LocalAssignStmt{Names: $2, Exprs:$4} - $$.SetLine($1.Pos.Line) - } | - TLocal namelist { - $$ = &ast.LocalAssignStmt{Names: $2, Exprs:[]ast.Expr{}} - $$.SetLine($1.Pos.Line) - } - -elseifs: - { - $$ = []ast.Stmt{} - } | - elseifs TElseIf expr TThen block { - $$ = append($1, &ast.IfStmt{Condition: $3, Then: $5}) - $$[len($$)-1].SetLine($2.Pos.Line) - } - -laststat: - TReturn { - $$ = &ast.ReturnStmt{Exprs:nil} - $$.SetLine($1.Pos.Line) - } | - TReturn exprlist { - $$ = &ast.ReturnStmt{Exprs:$2} - $$.SetLine($1.Pos.Line) - } | - TBreak { - $$ = &ast.BreakStmt{} - $$.SetLine($1.Pos.Line) - } - -funcname: - funcname1 { - $$ = $1 - } | - funcname1 ':' TIdent { - $$ = &ast.FuncName{Func:nil, Receiver:$1.Func, Method: $3.Str} - } - -funcname1: - TIdent { - $$ = &ast.FuncName{Func: &ast.IdentExpr{Value:$1.Str}} - $$.Func.SetLine($1.Pos.Line) - } | - funcname1 '.' TIdent { - key:= &ast.StringExpr{Value:$3.Str} - key.SetLine($3.Pos.Line) - fn := &ast.AttrGetExpr{Object: $1.Func, Key: key} - fn.SetLine($3.Pos.Line) - $$ = &ast.FuncName{Func: fn} - } - -varlist: - var { - $$ = []ast.Expr{$1} - } | - varlist ',' var { - $$ = append($1, $3) - } - -var: - TIdent { - $$ = &ast.IdentExpr{Value:$1.Str} - $$.SetLine($1.Pos.Line) - } | - prefixexp '[' expr ']' { - $$ = &ast.AttrGetExpr{Object: $1, Key: $3} - $$.SetLine($1.Line()) - } | - prefixexp '.' TIdent { - key := &ast.StringExpr{Value:$3.Str} - key.SetLine($3.Pos.Line) - $$ = &ast.AttrGetExpr{Object: $1, Key: key} - $$.SetLine($1.Line()) - } - -namelist: - TIdent { - $$ = []string{$1.Str} - } | - namelist ',' TIdent { - $$ = append($1, $3.Str) - } - -exprlist: - expr { - $$ = []ast.Expr{$1} - } | - exprlist ',' expr { - $$ = append($1, $3) - } - -expr: - TNil { - $$ = &ast.NilExpr{} - $$.SetLine($1.Pos.Line) - } | - TFalse { - $$ = &ast.FalseExpr{} - $$.SetLine($1.Pos.Line) - } | - TTrue { - $$ = &ast.TrueExpr{} - $$.SetLine($1.Pos.Line) - } | - TNumber { - $$ = &ast.NumberExpr{Value: $1.Str} - $$.SetLine($1.Pos.Line) - } | - T3Comma { - $$ = &ast.Comma3Expr{} - $$.SetLine($1.Pos.Line) - } | - function { - $$ = $1 - } | - prefixexp { - $$ = $1 - } | - string { - $$ = $1 - } | - tableconstructor { - $$ = $1 - } | - expr TOr expr { - $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "or", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr TAnd expr { - $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "and", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr '>' expr { - $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr '<' expr { - $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr TGte expr { - $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">=", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr TLte expr { - $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<=", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr TEqeq expr { - $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "==", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr TNeq expr { - $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "~=", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr T2Comma expr { - $$ = &ast.StringConcatOpExpr{Lhs: $1, Rhs: $3} - $$.SetLine($1.Line()) - } | - expr '+' expr { - $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "+", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr '-' expr { - $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "-", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr '*' expr { - $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "*", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr '/' expr { - $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "/", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr '%' expr { - $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "%", Rhs: $3} - $$.SetLine($1.Line()) - } | - expr '^' expr { - $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "^", Rhs: $3} - $$.SetLine($1.Line()) - } | - '-' expr %prec UNARY { - $$ = &ast.UnaryMinusOpExpr{Expr: $2} - $$.SetLine($2.Line()) - } | - TNot expr %prec UNARY { - $$ = &ast.UnaryNotOpExpr{Expr: $2} - $$.SetLine($2.Line()) - } | - '#' expr %prec UNARY { - $$ = &ast.UnaryLenOpExpr{Expr: $2} - $$.SetLine($2.Line()) - } - -string: - TString { - $$ = &ast.StringExpr{Value: $1.Str} - $$.SetLine($1.Pos.Line) - } - -prefixexp: - var { - $$ = $1 - } | - afunctioncall { - $$ = $1 - } | - functioncall { - $$ = $1 - } | - '(' expr ')' { - $$ = $2 - $$.SetLine($1.Pos.Line) - } - -afunctioncall: - '(' functioncall ')' { - $2.(*ast.FuncCallExpr).AdjustRet = true - $$ = $2 - } - -functioncall: - prefixexp args { - $$ = &ast.FuncCallExpr{Func: $1, Args: $2} - $$.SetLine($1.Line()) - } | - prefixexp ':' TIdent args { - $$ = &ast.FuncCallExpr{Method: $3.Str, Receiver: $1, Args: $4} - $$.SetLine($1.Line()) - } - -args: - '(' ')' { - if yylex.(*Lexer).PNewLine { - yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)") - } - $$ = []ast.Expr{} - } | - '(' exprlist ')' { - if yylex.(*Lexer).PNewLine { - yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)") - } - $$ = $2 - } | - tableconstructor { - $$ = []ast.Expr{$1} - } | - string { - $$ = []ast.Expr{$1} - } - -function: - TFunction funcbody { - $$ = &ast.FunctionExpr{ParList:$2.ParList, Stmts: $2.Stmts} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($2.LastLine()) - } - -funcbody: - '(' parlist ')' block TEnd { - $$ = &ast.FunctionExpr{ParList: $2, Stmts: $4} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($5.Pos.Line) - } | - '(' ')' block TEnd { - $$ = &ast.FunctionExpr{ParList: &ast.ParList{HasVargs: false, Names: []string{}}, Stmts: $3} - $$.SetLine($1.Pos.Line) - $$.SetLastLine($4.Pos.Line) - } - -parlist: - T3Comma { - $$ = &ast.ParList{HasVargs: true, Names: []string{}} - } | - namelist { - $$ = &ast.ParList{HasVargs: false, Names: []string{}} - $$.Names = append($$.Names, $1...) - } | - namelist ',' T3Comma { - $$ = &ast.ParList{HasVargs: true, Names: []string{}} - $$.Names = append($$.Names, $1...) - } - - -tableconstructor: - '{' '}' { - $$ = &ast.TableExpr{Fields: []*ast.Field{}} - $$.SetLine($1.Pos.Line) - } | - '{' fieldlist '}' { - $$ = &ast.TableExpr{Fields: $2} - $$.SetLine($1.Pos.Line) - } - - -fieldlist: - field { - $$ = []*ast.Field{$1} - } | - fieldlist fieldsep field { - $$ = append($1, $3) - } | - fieldlist fieldsep { - $$ = $1 - } - -field: - TIdent '=' expr { - $$ = &ast.Field{Key: &ast.StringExpr{Value:$1.Str}, Value: $3} - $$.Key.SetLine($1.Pos.Line) - } | - '[' expr ']' '=' expr { - $$ = &ast.Field{Key: $2, Value: $5} - } | - expr { - $$ = &ast.Field{Value: $1} - } - -fieldsep: - ',' { - $$ = "," - } | - ';' { - $$ = ";" - } - -%% - -func TokenName(c int) string { - if c >= TAnd && c-TAnd < len(yyToknames) { - if yyToknames[c-TAnd] != "" { - return yyToknames[c-TAnd] - } - } - return string([]byte{byte(c)}) -} - From 09facca01b4383b717c9a730bffcfe3c24b8970b Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Mon, 27 Apr 2020 23:17:57 -0400 Subject: [PATCH 08/10] Add changelog entry --- CHANGELOG.next.asciidoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 71aae915595..e01125fcd7b 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -207,6 +207,8 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Log to stderr when running using reference kubernetes manifests. {pull}17443[174443] - Fix syscall kprobe arguments for 32-bit systems in socket module. {pull}17500[17500] - Fix memory leak on when we miss socket close kprobe events. {pull}17500[17500] +- Add file integrity module ECS categorization fields. {pull}18012[18012] +- Add `file.mime_type`, `file.extension`, and `file.drive_letter` for file integrity module. {pull}18012[18012] *Filebeat* From 515cf700119eba66e87a9000f20c5d72a1664940 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Tue, 5 May 2020 12:03:52 -0400 Subject: [PATCH 09/10] Extract isASCIILetter --- auditbeat/module/file_integrity/event.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/auditbeat/module/file_integrity/event.go b/auditbeat/module/file_integrity/event.go index 50b856f190c..41e4d5a3795 100644 --- a/auditbeat/module/file_integrity/event.go +++ b/auditbeat/module/file_integrity/event.go @@ -215,11 +215,18 @@ func NewEvent( return NewEventFromFileInfo(path, info, err, action, source, maxFileSize, hashTypes) } +func isASCIILetter(letter byte) bool { + // It appears that Windows only allows ascii characters for drive letters + // and that's what go checks for: https://golang.org/src/path/filepath/path_windows.go#L63 + // **If** Windows/go ever return multibyte utf16 characters we'll need to change + // the drive letter mapping logic. + return (letter >= 'a' && letter <= 'z') || (letter >= 'A' && letter <= 'Z') +} + func getDriveLetter(path string) string { volume := filepath.VolumeName(path) if len(volume) == 2 && volume[1] == ':' { - letter := path[0] - if (letter >= 'a' && letter <= 'z') || (letter >= 'A' && letter <= 'Z') { + if isASCIILetter(volume[0]) { return strings.ToUpper(volume[:1]) } } From 4ba9e6f7c09556b200244c86e39d310aadee603c Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Tue, 5 May 2020 15:22:07 -0400 Subject: [PATCH 10/10] switch over to godoc style comment --- auditbeat/module/file_integrity/mime.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auditbeat/module/file_integrity/mime.go b/auditbeat/module/file_integrity/mime.go index 7c07138e00f..94dcdc60de5 100644 --- a/auditbeat/module/file_integrity/mime.go +++ b/auditbeat/module/file_integrity/mime.go @@ -29,7 +29,7 @@ const ( headerSize = 8192 ) -// this does a best-effort to get the file type, if no +// getMimeType does a best-effort to get the file type, if no // filetype can be determined, it just returns an empty // string func getMimeType(path string) string {